]> git.zerfleddert.de Git - proxmark3-svn/blob - client/fido/cose.c
Fido2 (#727)
[proxmark3-svn] / client / fido / cose.c
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
Impressum, Datenschutz