1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2018 Merlok
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
8 // Tools for work with COSE (CBOR Object Signing and Encryption) rfc8152
9 // https://tools.ietf.org/html/rfc8152
10 //-----------------------------------------------------------------------------
15 #include "cbortools.h"
19 static const char COSEEmptyStr
[] = "";
25 } COSEValueNameDesc_t
;
32 } COSEValueTypeNameDesc_t
;
34 // kty - Key Type Values
35 COSEValueNameDesc_t COSEKeyTypeValueDesc
[] = {
36 {0, "Reserved", "Reserved"},
37 {1, "OKP", "Octet Key Pair"},
38 {2, "EC2", "Elliptic Curve Key w/ x- and y-coordinate pair"},
39 {4, "Symmetric", "Symmetric Key"},
42 COSEValueNameDesc_t
*GetCOSEktyElm(int id
) {
43 for (int i
= 0; i
< ARRAYLEN(COSEKeyTypeValueDesc
); i
++)
44 if (COSEKeyTypeValueDesc
[i
].Value
== id
)
45 return &COSEKeyTypeValueDesc
[i
];
49 const char *GetCOSEktyDescription(int id
) {
50 COSEValueNameDesc_t
*elm
= GetCOSEktyElm(id
);
52 return elm
->Description
;
57 COSEValueTypeNameDesc_t COSECurvesDesc
[] = {
58 {1, "EC2", "P-256", "NIST P-256 also known as secp256r1"},
59 {2, "EC2", "P-384", "NIST P-384 also known as secp384r1"},
60 {3, "EC2", "P-521", "NIST P-521 also known as secp521r1"},
61 {4, "OKP", "X25519", "X25519 for use w/ ECDH only"},
62 {5, "OKP", "X448", "X448 for use w/ ECDH only"},
63 {6, "OKP", "Ed25519", "Ed25519 for use w/ EdDSA only"},
64 {7, "OKP", "Ed448", "Ed448 for use w/ EdDSA only"},
67 COSEValueTypeNameDesc_t
*GetCOSECurveElm(int id
) {
68 for (int i
= 0; i
< ARRAYLEN(COSECurvesDesc
); i
++)
69 if (COSECurvesDesc
[i
].Value
== id
)
70 return &COSECurvesDesc
[i
];
74 const char *GetCOSECurveDescription(int id
) {
75 COSEValueTypeNameDesc_t
*elm
= GetCOSECurveElm(id
);
77 return elm
->Description
;
81 // RFC8152 https://www.iana.org/assignments/cose/cose.xhtml#algorithms
82 COSEValueNameDesc_t COSEAlg
[] = {
83 {-65536, "Unassigned", "Unassigned"},
84 {-65535, "RS1", "RSASSA-PKCS1-v1_5 w/ SHA-1"},
85 {-259, "RS512", "RSASSA-PKCS1-v1_5 w/ SHA-512"},
86 {-258, "RS384", "RSASSA-PKCS1-v1_5 w/ SHA-384"},
87 {-257, "RS256", "RSASSA-PKCS1-v1_5 w/ SHA-256"},
88 {-42, "RSAES-OAEP w/ SHA-512", "RSAES-OAEP w/ SHA-512"},
89 {-41, "RSAES-OAEP w/ SHA-256", "RSAES-OAEP w/ SHA-256"},
90 {-40, "RSAES-OAEP w/ RFC 8017 def param", "RSAES-OAEP w/ SHA-1"},
91 {-39, "PS512", "RSASSA-PSS w/ SHA-512"},
92 {-38, "PS384", "RSASSA-PSS w/ SHA-384"},
93 {-37, "PS256", "RSASSA-PSS w/ SHA-256"},
94 {-36, "ES512", "ECDSA w/ SHA-512"},
95 {-35, "ES384", "ECDSA w/ SHA-384"},
96 {-34, "ECDH-SS + A256KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 256-bit key"},
97 {-33, "ECDH-SS + A192KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 192-bit key"},
98 {-32, "ECDH-SS + A128KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 128-bit key"},
99 {-31, "ECDH-ES + A256KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 256-bit key"},
100 {-30, "ECDH-ES + A192KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 192-bit key"},
101 {-29, "ECDH-ES + A128KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 128-bit key"},
102 {-28, "ECDH-SS + HKDF-512", "ECDH SS w/ HKDF - generate key directly"},
103 {-27, "ECDH-SS + HKDF-256", "ECDH SS w/ HKDF - generate key directly"},
104 {-26, "ECDH-ES + HKDF-512", "ECDH ES w/ HKDF - generate key directly"},
105 {-25, "ECDH-ES + HKDF-256", "ECDH ES w/ HKDF - generate key directly"},
106 {-13, "direct+HKDF-AES-256", "Shared secret w/ AES-MAC 256-bit key"},
107 {-12, "direct+HKDF-AES-128", "Shared secret w/ AES-MAC 128-bit key"},
108 {-11, "direct+HKDF-SHA-512", "Shared secret w/ HKDF and SHA-512"},
109 {-10, "direct+HKDF-SHA-256", "Shared secret w/ HKDF and SHA-256"},
110 {-8, "EdDSA", "EdDSA"},
111 {-7, "ES256", "ECDSA w/ SHA-256"},
112 {-6, "direct", "Direct use of CEK"},
113 {-5, "A256KW", "AES Key Wrap w/ 256-bit key"},
114 {-4, "A192KW", "AES Key Wrap w/ 192-bit key"},
115 {-3, "A128KW", "AES Key Wrap w/ 128-bit key"},
116 {0, "Reserved", "Reserved"},
117 {1, "A128GCM", "AES-GCM mode w/ 128-bit key, 128-bit tag"},
118 {2, "A192GCM", "AES-GCM mode w/ 192-bit key, 128-bit tag"},
119 {3, "A256GCM", "AES-GCM mode w/ 256-bit key, 128-bit tag"},
120 {4, "HMAC 256/64", "HMAC w/ SHA-256 truncated to 64 bits"},
121 {5, "HMAC 256/256", "HMAC w/ SHA-256"},
122 {6, "HMAC 384/384", "HMAC w/ SHA-384"},
123 {7, "HMAC 512/512", "HMAC w/ SHA-512"},
124 {10, "AES-CCM-16-64-128", "AES-CCM mode 128-bit key, 64-bit tag, 13-byte nonce"},
125 {11, "AES-CCM-16-64-256", "AES-CCM mode 256-bit key, 64-bit tag, 13-byte nonce"},
126 {12, "AES-CCM-64-64-128", "AES-CCM mode 128-bit key, 64-bit tag, 7-byte nonce"},
127 {13, "AES-CCM-64-64-256", "AES-CCM mode 256-bit key, 64-bit tag, 7-byte nonce"},
128 {14, "AES-MAC 128/64", "AES-MAC 128-bit key, 64-bit tag"},
129 {15, "AES-MAC 256/64", "AES-MAC 256-bit key, 64-bit tag"},
130 {24, "ChaCha20/Poly1305", "ChaCha20/Poly1305 w/ 256-bit key, 128-bit tag"},
131 {25, "AES-MAC 128/128", "AES-MAC 128-bit key, 128-bit tag"},
132 {26, "AES-MAC 256/128", "AES-MAC 256-bit key, 128-bit tag"},
133 {30, "AES-CCM-16-128-128", "AES-CCM mode 128-bit key, 128-bit tag, 13-byte nonce"},
134 {31, "AES-CCM-16-128-256", "AES-CCM mode 256-bit key, 128-bit tag, 13-byte nonce"},
135 {32, "AES-CCM-64-128-128", "AES-CCM mode 128-bit key, 128-bit tag, 7-byte nonce"},
136 {33, "AES-CCM-64-128-256", "AES-CCM mode 256-bit key, 128-bit tag, 7-byte nonce"}
139 COSEValueNameDesc_t
*GetCOSEAlgElm(int id
) {
140 for (int i
= 0; i
< ARRAYLEN(COSEAlg
); i
++)
141 if (COSEAlg
[i
].Value
== id
)
146 const char *GetCOSEAlgName(int id
) {
147 COSEValueNameDesc_t
*elm
= GetCOSEAlgElm(id
);
153 const char *GetCOSEAlgDescription(int id
) {
154 COSEValueNameDesc_t
*elm
= GetCOSEAlgElm(id
);
156 return elm
->Description
;
160 int COSEGetECDSAKey(uint8_t *data
, size_t datalen
, bool verbose
, uint8_t *public_key
) {
167 PrintAndLog("----------- CBOR decode ----------------");
170 int res
= CborMapGetKeyById(&parser
, &map
, data
, datalen
, 1);
172 cbor_value_get_int64(&map
, &i64
);
174 PrintAndLog("kty [%lld] %s", (long long)i64
, GetCOSEktyDescription(i64
));
176 PrintAndLog("ERROR: kty must be 2.");
180 res
= CborMapGetKeyById(&parser
, &map
, data
, datalen
, 3);
182 cbor_value_get_int64(&map
, &i64
);
184 PrintAndLog("algorithm [%lld] %s", (long long)i64
, GetCOSEAlgDescription(i64
));
186 PrintAndLog("ERROR: algorithm must be -7.");
190 res
= CborMapGetKeyById(&parser
, &map
, data
, datalen
, -1);
192 cbor_value_get_int64(&map
, &i64
);
194 PrintAndLog("curve [%lld] %s", (long long)i64
, GetCOSECurveDescription(i64
));
196 PrintAndLog("ERROR: curve must be 1.");
200 public_key
[0] = 0x04;
203 res
= CborMapGetKeyById(&parser
, &map
, data
, datalen
, -2);
205 res
= CborGetBinStringValue(&map
, &public_key
[1], 32, &len
);
208 PrintAndLog("x - coordinate [%d]: %s", len
, sprint_hex(&public_key
[1], 32));
210 PrintAndLog("ERROR: x - coordinate length must be 32.");
214 res
= CborMapGetKeyById(&parser
, &map
, data
, datalen
, -3);
216 res
= CborGetBinStringValue(&map
, &public_key
[33], 32, &len
);
219 PrintAndLog("y - coordinate [%d]: %s", len
, sprint_hex(&public_key
[33], 32));
221 PrintAndLog("ERROR: y - coordinate length must be 32.");
225 uint8_t private_key
[128] = {0};
226 res
= CborMapGetKeyById(&parser
, &map
, data
, datalen
, -4);
228 res
= CborGetBinStringValue(&map
, private_key
, sizeof(private_key
), &len
);
231 PrintAndLog("d - private key [%d]: %s", len
, sprint_hex(private_key
, len
));
235 PrintAndLog("----------- CBOR decode ----------------");