Commit | Line | Data |
---|---|---|
0bb51450 OM |
1 | //----------------------------------------------------------------------------- |
2 | // Copyright (C) 2018 Merlok | |
3 | // | |
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 | |
6 | // the license. | |
7 | //----------------------------------------------------------------------------- | |
8 | // Tools for work with COSE (CBOR Object Signing and Encryption) rfc8152 | |
9 | // https://tools.ietf.org/html/rfc8152 | |
10 | //----------------------------------------------------------------------------- | |
11 | // | |
12 | ||
13 | #include "cose.h" | |
14 | #include <cbor.h> | |
15 | #include "cbortools.h" | |
16 | #include "util.h" | |
17 | #include "ui.h" | |
18 | ||
19 | static const char COSEEmptyStr[] = ""; | |
20 | ||
21 | typedef struct { | |
22 | int Value; | |
23 | char *Name; | |
24 | char *Description; | |
25 | } COSEValueNameDesc_t; | |
26 | ||
27 | typedef struct { | |
28 | int Value; | |
29 | char *Type; | |
30 | char *Name; | |
31 | char *Description; | |
32 | } COSEValueTypeNameDesc_t; | |
33 | ||
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"}, | |
40 | }; | |
41 | ||
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]; | |
46 | return NULL; | |
47 | } | |
48 | ||
49 | const char *GetCOSEktyDescription(int id) { | |
50 | COSEValueNameDesc_t *elm = GetCOSEktyElm(id); | |
51 | if (elm) | |
52 | return elm->Description; | |
53 | return COSEEmptyStr; | |
54 | } | |
55 | ||
56 | // keys | |
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"}, | |
65 | }; | |
66 | ||
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]; | |
71 | return NULL; | |
72 | } | |
73 | ||
74 | const char *GetCOSECurveDescription(int id) { | |
75 | COSEValueTypeNameDesc_t *elm = GetCOSECurveElm(id); | |
76 | if (elm) | |
77 | return elm->Description; | |
78 | return COSEEmptyStr; | |
79 | } | |
80 | ||
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"} | |
137 | }; | |
138 | ||
139 | COSEValueNameDesc_t *GetCOSEAlgElm(int id) { | |
140 | for (int i = 0; i < ARRAYLEN(COSEAlg); i++) | |
141 | if (COSEAlg[i].Value == id) | |
142 | return &COSEAlg[i]; | |
143 | return NULL; | |
144 | } | |
145 | ||
146 | const char *GetCOSEAlgName(int id) { | |
147 | COSEValueNameDesc_t *elm = GetCOSEAlgElm(id); | |
148 | if (elm) | |
149 | return elm->Name; | |
150 | return COSEEmptyStr; | |
151 | } | |
152 | ||
153 | const char *GetCOSEAlgDescription(int id) { | |
154 | COSEValueNameDesc_t *elm = GetCOSEAlgElm(id); | |
155 | if (elm) | |
156 | return elm->Description; | |
157 | return COSEEmptyStr; | |
158 | } | |
159 | ||
160 | int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public_key) { | |
161 | CborParser parser; | |
162 | CborValue map; | |
163 | int64_t i64; | |
164 | size_t len; | |
165 | ||
166 | if(verbose) | |
167 | PrintAndLog("----------- CBOR decode ----------------"); | |
168 | ||
169 | // kty | |
170 | int res = CborMapGetKeyById(&parser, &map, data, datalen, 1); | |
171 | if(!res) { | |
172 | cbor_value_get_int64(&map, &i64); | |
173 | if(verbose) | |
174 | PrintAndLog("kty [%lld] %s", (long long)i64, GetCOSEktyDescription(i64)); | |
175 | if (i64 != 2) | |
176 | PrintAndLog("ERROR: kty must be 2."); | |
177 | } | |
178 | ||
179 | // algorithm | |
180 | res = CborMapGetKeyById(&parser, &map, data, datalen, 3); | |
181 | if(!res) { | |
182 | cbor_value_get_int64(&map, &i64); | |
183 | if(verbose) | |
184 | PrintAndLog("algorithm [%lld] %s", (long long)i64, GetCOSEAlgDescription(i64)); | |
185 | if (i64 != -7) | |
186 | PrintAndLog("ERROR: algorithm must be -7."); | |
187 | } | |
188 | ||
189 | // curve | |
190 | res = CborMapGetKeyById(&parser, &map, data, datalen, -1); | |
191 | if(!res) { | |
192 | cbor_value_get_int64(&map, &i64); | |
193 | if(verbose) | |
194 | PrintAndLog("curve [%lld] %s", (long long)i64, GetCOSECurveDescription(i64)); | |
195 | if (i64 != 1) | |
196 | PrintAndLog("ERROR: curve must be 1."); | |
197 | } | |
198 | ||
199 | // plain key | |
200 | public_key[0] = 0x04; | |
201 | ||
202 | // x - coordinate | |
203 | res = CborMapGetKeyById(&parser, &map, data, datalen, -2); | |
204 | if(!res) { | |
205 | res = CborGetBinStringValue(&map, &public_key[1], 32, &len); | |
206 | cbor_check(res); | |
207 | if(verbose) | |
208 | PrintAndLog("x - coordinate [%d]: %s", len, sprint_hex(&public_key[1], 32)); | |
209 | if (len != 32) | |
210 | PrintAndLog("ERROR: x - coordinate length must be 32."); | |
211 | } | |
212 | ||
213 | // y - coordinate | |
214 | res = CborMapGetKeyById(&parser, &map, data, datalen, -3); | |
215 | if(!res) { | |
216 | res = CborGetBinStringValue(&map, &public_key[33], 32, &len); | |
217 | cbor_check(res); | |
218 | if(verbose) | |
219 | PrintAndLog("y - coordinate [%d]: %s", len, sprint_hex(&public_key[33], 32)); | |
220 | if (len != 32) | |
221 | PrintAndLog("ERROR: y - coordinate length must be 32."); | |
222 | } | |
223 | ||
224 | // d - private key | |
225 | uint8_t private_key[128] = {0}; | |
226 | res = CborMapGetKeyById(&parser, &map, data, datalen, -4); | |
227 | if(!res) { | |
228 | res = CborGetBinStringValue(&map, private_key, sizeof(private_key), &len); | |
229 | cbor_check(res); | |
230 | if(verbose) | |
231 | PrintAndLog("d - private key [%d]: %s", len, sprint_hex(private_key, len)); | |
232 | } | |
233 | ||
234 | if(verbose) | |
235 | PrintAndLog("----------- CBOR decode ----------------"); | |
236 | ||
237 | return 0; | |
238 | } | |
239 | ||
240 |