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"
16 #include "commonutil.h" // ARRAYLEN
17 #include "ui.h" // Print...
20 static const char COSEEmptyStr
[] = "";
25 const char *Description
;
26 } COSEValueNameDesc_t
;
32 const char *Description
;
33 } COSEValueTypeNameDesc_t
;
35 // kty - Key Type Values
36 COSEValueNameDesc_t COSEKeyTypeValueDesc
[] = {
37 {0, "Reserved", "Reserved"},
38 {1, "OKP", "Octet Key Pair"},
39 {2, "EC2", "Elliptic Curve Key w/ x- and y-coordinate pair"},
40 {4, "Symmetric", "Symmetric Key"},
43 static COSEValueNameDesc_t
*GetCOSEktyElm(int id
) {
44 for (size_t i
= 0; i
< ARRAYLEN(COSEKeyTypeValueDesc
); i
++)
45 if (COSEKeyTypeValueDesc
[i
].Value
== id
)
46 return &COSEKeyTypeValueDesc
[i
];
50 const char *GetCOSEktyDescription(int id
) {
51 COSEValueNameDesc_t
*elm
= GetCOSEktyElm(id
);
53 return elm
->Description
;
58 COSEValueTypeNameDesc_t COSECurvesDesc
[] = {
59 {1, "EC2", "P-256", "NIST P-256 also known as secp256r1"},
60 {2, "EC2", "P-384", "NIST P-384 also known as secp384r1"},
61 {3, "EC2", "P-521", "NIST P-521 also known as secp521r1"},
62 {4, "OKP", "X25519", "X25519 for use w/ ECDH only"},
63 {5, "OKP", "X448", "X448 for use w/ ECDH only"},
64 {6, "OKP", "Ed25519", "Ed25519 for use w/ EdDSA only"},
65 {7, "OKP", "Ed448", "Ed448 for use w/ EdDSA only"},
68 static COSEValueTypeNameDesc_t
*GetCOSECurveElm(int id
) {
69 for (size_t i
= 0; i
< ARRAYLEN(COSECurvesDesc
); i
++)
70 if (COSECurvesDesc
[i
].Value
== id
)
71 return &COSECurvesDesc
[i
];
75 const char *GetCOSECurveDescription(int id
) {
76 COSEValueTypeNameDesc_t
*elm
= GetCOSECurveElm(id
);
78 return elm
->Description
;
82 // RFC8152 https://www.iana.org/assignments/cose/cose.xhtml#algorithms
83 COSEValueNameDesc_t COSEAlg
[] = {
84 { -65536, "Unassigned", "Unassigned"},
85 { -65535, "RS1", "RSASSA-PKCS1-v1_5 w/ SHA-1"},
86 { -259, "RS512", "RSASSA-PKCS1-v1_5 w/ SHA-512"},
87 { -258, "RS384", "RSASSA-PKCS1-v1_5 w/ SHA-384"},
88 { -257, "RS256", "RSASSA-PKCS1-v1_5 w/ SHA-256"},
89 { -42, "RSAES-OAEP w/ SHA-512", "RSAES-OAEP w/ SHA-512"},
90 { -41, "RSAES-OAEP w/ SHA-256", "RSAES-OAEP w/ SHA-256"},
91 { -40, "RSAES-OAEP w/ RFC 8017 def param", "RSAES-OAEP w/ SHA-1"},
92 { -39, "PS512", "RSASSA-PSS w/ SHA-512"},
93 { -38, "PS384", "RSASSA-PSS w/ SHA-384"},
94 { -37, "PS256", "RSASSA-PSS w/ SHA-256"},
95 { -36, "ES512", "ECDSA w/ SHA-512"},
96 { -35, "ES384", "ECDSA w/ SHA-384"},
97 { -34, "ECDH-SS + A256KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 256-bit key"},
98 { -33, "ECDH-SS + A192KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 192-bit key"},
99 { -32, "ECDH-SS + A128KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 128-bit key"},
100 { -31, "ECDH-ES + A256KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 256-bit key"},
101 { -30, "ECDH-ES + A192KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 192-bit key"},
102 { -29, "ECDH-ES + A128KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 128-bit key"},
103 { -28, "ECDH-SS + HKDF-512", "ECDH SS w/ HKDF - generate key directly"},
104 { -27, "ECDH-SS + HKDF-256", "ECDH SS w/ HKDF - generate key directly"},
105 { -26, "ECDH-ES + HKDF-512", "ECDH ES w/ HKDF - generate key directly"},
106 { -25, "ECDH-ES + HKDF-256", "ECDH ES w/ HKDF - generate key directly"},
107 { -13, "direct+HKDF-AES-256", "Shared secret w/ AES-MAC 256-bit key"},
108 { -12, "direct+HKDF-AES-128", "Shared secret w/ AES-MAC 128-bit key"},
109 { -11, "direct+HKDF-SHA-512", "Shared secret w/ HKDF and SHA-512"},
110 { -10, "direct+HKDF-SHA-256", "Shared secret w/ HKDF and SHA-256"},
111 { -8, "EdDSA", "EdDSA"},
112 { -7, "ES256", "ECDSA w/ SHA-256"},
113 { -6, "direct", "Direct use of CEK"},
114 { -5, "A256KW", "AES Key Wrap w/ 256-bit key"},
115 { -4, "A192KW", "AES Key Wrap w/ 192-bit key"},
116 { -3, "A128KW", "AES Key Wrap w/ 128-bit key"},
117 {0, "Reserved", "Reserved"},
118 {1, "A128GCM", "AES-GCM mode w/ 128-bit key, 128-bit tag"},
119 {2, "A192GCM", "AES-GCM mode w/ 192-bit key, 128-bit tag"},
120 {3, "A256GCM", "AES-GCM mode w/ 256-bit key, 128-bit tag"},
121 {4, "HMAC 256/64", "HMAC w/ SHA-256 truncated to 64 bits"},
122 {5, "HMAC 256/256", "HMAC w/ SHA-256"},
123 {6, "HMAC 384/384", "HMAC w/ SHA-384"},
124 {7, "HMAC 512/512", "HMAC w/ SHA-512"},
125 {10, "AES-CCM-16-64-128", "AES-CCM mode 128-bit key, 64-bit tag, 13-byte nonce"},
126 {11, "AES-CCM-16-64-256", "AES-CCM mode 256-bit key, 64-bit tag, 13-byte nonce"},
127 {12, "AES-CCM-64-64-128", "AES-CCM mode 128-bit key, 64-bit tag, 7-byte nonce"},
128 {13, "AES-CCM-64-64-256", "AES-CCM mode 256-bit key, 64-bit tag, 7-byte nonce"},
129 {14, "AES-MAC 128/64", "AES-MAC 128-bit key, 64-bit tag"},
130 {15, "AES-MAC 256/64", "AES-MAC 256-bit key, 64-bit tag"},
131 {24, "ChaCha20/Poly1305", "ChaCha20/Poly1305 w/ 256-bit key, 128-bit tag"},
132 {25, "AES-MAC 128/128", "AES-MAC 128-bit key, 128-bit tag"},
133 {26, "AES-MAC 256/128", "AES-MAC 256-bit key, 128-bit tag"},
134 {30, "AES-CCM-16-128-128", "AES-CCM mode 128-bit key, 128-bit tag, 13-byte nonce"},
135 {31, "AES-CCM-16-128-256", "AES-CCM mode 256-bit key, 128-bit tag, 13-byte nonce"},
136 {32, "AES-CCM-64-128-128", "AES-CCM mode 128-bit key, 128-bit tag, 7-byte nonce"},
137 {33, "AES-CCM-64-128-256", "AES-CCM mode 256-bit key, 128-bit tag, 7-byte nonce"}
140 static COSEValueNameDesc_t
*GetCOSEAlgElm(int id
) {
141 for (size_t i
= 0; i
< ARRAYLEN(COSEAlg
); i
++)
142 if (COSEAlg
[i
].Value
== id
)
147 const char *GetCOSEAlgName(int id
) {
148 COSEValueNameDesc_t
*elm
= GetCOSEAlgElm(id
);
154 const char *GetCOSEAlgDescription(int id
) {
155 COSEValueNameDesc_t
*elm
= GetCOSEAlgElm(id
);
157 return elm
->Description
;
161 int COSEGetECDSAKey(uint8_t *data
, size_t datalen
, bool verbose
, uint8_t *public_key
) {
168 PrintAndLogEx(NORMAL
, "----------- CBOR decode ----------------");
171 int res
= CborMapGetKeyById(&parser
, &map
, data
, datalen
, 1);
173 cbor_value_get_int64(&map
, &i64
);
175 PrintAndLogEx(SUCCESS
, "kty [%lld] %s", (long long)i64
, GetCOSEktyDescription(i64
));
177 PrintAndLogEx(ERR
, "ERROR: kty must be 2.");
181 res
= CborMapGetKeyById(&parser
, &map
, data
, datalen
, 3);
183 cbor_value_get_int64(&map
, &i64
);
185 PrintAndLogEx(SUCCESS
, "algorithm [%lld] %s", (long long)i64
, GetCOSEAlgDescription(i64
));
187 PrintAndLogEx(ERR
, "ERROR: algorithm must be -7.");
191 res
= CborMapGetKeyById(&parser
, &map
, data
, datalen
, -1);
193 cbor_value_get_int64(&map
, &i64
);
195 PrintAndLogEx(SUCCESS
, "curve [%lld] %s", (long long)i64
, GetCOSECurveDescription(i64
));
197 PrintAndLogEx(ERR
, "ERROR: curve must be 1.");
201 public_key
[0] = 0x04;
204 res
= CborMapGetKeyById(&parser
, &map
, data
, datalen
, -2);
206 res
= CborGetBinStringValue(&map
, &public_key
[1], 32, &len
);
209 PrintAndLogEx(SUCCESS
, "x - coordinate [%zu]: %s", len
, sprint_hex(&public_key
[1], 32));
211 PrintAndLogEx(ERR
, "ERROR: x - coordinate length must be 32.");
215 res
= CborMapGetKeyById(&parser
, &map
, data
, datalen
, -3);
217 res
= CborGetBinStringValue(&map
, &public_key
[33], 32, &len
);
220 PrintAndLogEx(SUCCESS
, "y - coordinate [%zu]: %s", len
, sprint_hex(&public_key
[33], 32));
222 PrintAndLogEx(ERR
, "ERROR: y - coordinate length must be 32.");
226 res
= CborMapGetKeyById(&parser
, &map
, data
, datalen
, -4);
228 uint8_t private_key
[128] = {0};
229 res
= CborGetBinStringValue(&map
, private_key
, sizeof(private_key
), &len
);
232 PrintAndLogEx(SUCCESS
, "d - private key [%zu]: %s", len
, sprint_hex(private_key
, len
));
236 PrintAndLogEx(NORMAL
, "----------- CBOR decode ----------------");