1 /*
2 Copyright (c) 2021 Fraunhofer AISEC. See the COPYRIGHT
3 file at the top-level directory of this distribution.
4
5 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 option. This file may not be copied, modified, or distributed
9 except according to those terms.
10 */
11
12 #include <stdbool.h>
13 #include <stdint.h>
14
15 #include "edhoc/buffer_sizes.h"
16
17 #include "edhoc/cert.h"
18
19 #include "common/memcpy_s.h"
20 #include "common/oscore_edhoc_error.h"
21 #include "common/crypto_wrapper.h"
22 #include "common/print_util.h"
23
24 #include "cbor/edhoc_decode_cert.h"
25
26 #ifdef MBEDTLS
27 #define MBEDTLS_ALLOW_PRIVATE_ACCESS
28
29 #include <psa/crypto.h>
30 #include <mbedtls/asn1.h>
31 #include <mbedtls/error.h>
32 #include <mbedtls/md.h>
33 #include <mbedtls/oid.h>
34 #include <mbedtls/x509.h>
35 #include <mbedtls/x509_crt.h>
36
37 struct deser_sign_ctx_s {
38 uint8_t *seek;
39 uint8_t *end;
40 int unit_size;
41 };
42
deser_sign_ctx_init(struct deser_sign_ctx_s * ctx,uint8_t * seek,uint8_t * end,int unit_size)43 static void deser_sign_ctx_init(struct deser_sign_ctx_s *ctx, uint8_t *seek,
44 uint8_t *end, int unit_size)
45 {
46 ctx->seek = seek;
47 ctx->end = end;
48 ctx->unit_size = unit_size;
49 }
50
deser_sign_cb(void * void_ctx,int tag,unsigned char * start,size_t len)51 static int deser_sign_cb(void *void_ctx, int tag, unsigned char *start,
52 size_t len)
53 {
54 if (tag == MBEDTLS_ASN1_INTEGER) {
55 struct deser_sign_ctx_s *ctx = void_ctx;
56 uint8_t *unit_end = ctx->seek + ctx->unit_size;
57 if (unit_end <= ctx->end) {
58 memcpy(ctx->seek, start + len - ctx->unit_size,
59 (uint32_t)ctx->unit_size);
60 ctx->seek = unit_end;
61 }
62 }
63 return 0;
64 }
65
find_pk_cb(void * void_ppk,int tag,unsigned char * start,size_t len)66 static int find_pk_cb(void *void_ppk, int tag, unsigned char *start, size_t len)
67 {
68 (void)len;
69
70 if (tag == MBEDTLS_ASN1_BIT_STRING) {
71 uint8_t **pk = void_ppk;
72 *pk = start;
73 }
74 return 0;
75 }
76
77 #define PSA_KEY_ALL_USAGES \
78 (PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | \
79 PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_SIGN_MESSAGE | \
80 PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_SIGN_HASH | \
81 PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE)
82
83 #else /* MBEDTLS */
84
85 #define ISSUER_CN_OID "\x55\x04\x03"
86
87 #define EXPECTO_TAG(tag, cursor, len) \
88 if (*cursor != tag) { \
89 rv = wrong_parameter; \
90 PRINTF(RED \
91 "Runtime error: expected %s tag at %s:%d\n\n" RESET, \
92 #tag, __FILE__, __LINE__); \
93 break; \
94 } else { \
95 cursor++; \
96 mbedtls_asn1_get_len(&cursor, end, &len); \
97 if (0 == *cursor) { \
98 cursor++; \
99 len--; \
100 } \
101 }
102
103 enum tag_map_enum {
104 ASN1_INTEGER = 0x02,
105 ASN1_BIT_STRING = 0x03,
106 ASN1_SEQUENCE = 0x30
107 };
108
109 /* Extracted from mbedtls library; asn1_parse.c */
110 /* License for file: Apache-2.0 */
111 /* ASN.1 DER encoding is described in ITU-T X.690 standard. */
112 /* First bit of length byte contains information, if length
113 value shall be concatenated with following byte length. */
mbedtls_asn1_get_len(const unsigned char ** p,const unsigned char * end,uint32_t * len)114 static int mbedtls_asn1_get_len(const unsigned char **p,
115 const unsigned char *end, uint32_t *len)
116 {
117 if ((end - *p) < 1)
118 return (buffer_to_small);
119
120 if ((**p & 0x80) == 0)
121 *len = *(*p)++;
122 else {
123 switch (**p & 0x7F) {
124 case 1:
125 if ((end - *p) < 2)
126 return (buffer_to_small);
127
128 *len = (*p)[1];
129 (*p) += 2;
130 break;
131
132 case 2:
133 if ((end - *p) < 3)
134 return (buffer_to_small);
135
136 *len = ((uint32_t)(*p)[1] << 8) | (*p)[2];
137 (*p) += 3;
138 break;
139
140 case 3:
141 if ((end - *p) < 4)
142 return (buffer_to_small);
143
144 *len = ((uint32_t)(*p)[1] << 16) |
145 ((uint32_t)(*p)[2] << 8) | (*p)[3];
146 (*p) += 4;
147 break;
148
149 case 4:
150 if ((end - *p) < 5)
151 return (buffer_to_small);
152
153 *len = ((uint32_t)(*p)[1] << 24) |
154 ((uint32_t)(*p)[2] << 16) |
155 ((uint32_t)(*p)[3] << 8) | (*p)[4];
156 (*p) += 5;
157 break;
158
159 default:
160 return (buffer_to_small);
161 }
162 }
163
164 if (*len > (uint32_t)(end - *p))
165 return (buffer_to_small);
166
167 return (0);
168 }
169
170 #endif /* MBEDTLS */
171
172 /**
173 * @brief retrieves the public key of the CA from CRED_ARRAY.
174 *
175 *
176 * @param[in] cred_array contains the public key of the root CA
177 * @param[in] issuer the issuer name, i.e. the name of the CA
178 * @param[out] root_pk the root public key
179 * @return error code
180 */
ca_pk_get(const struct cred_array * cred_array,const uint8_t * issuer,struct byte_array * root_pk)181 static enum err ca_pk_get(const struct cred_array *cred_array,
182 const uint8_t *issuer, struct byte_array *root_pk)
183 {
184 /* when single credential without certificate is stored, return stored ca_pk if available */
185 if (1 == cred_array->len
186 #ifdef MBEDTLS
187 /* In case no MBEDTLS is enabled, issuer identification is not extracted from certificate */
188 && (0 == cred_array->ptr[0].ca.len ||
189 NULL == cred_array->ptr[0].ca.ptr)
190 #endif
191 ) {
192 if (NULL == cred_array->ptr[0].ca_pk.ptr ||
193 0 == cred_array->ptr[0].ca_pk.len) {
194 return no_such_ca;
195 }
196
197 root_pk->ptr = cred_array->ptr[0].ca_pk.ptr;
198 root_pk->len = cred_array->ptr[0].ca_pk.len;
199 return ok;
200 }
201
202 #ifdef MBEDTLS
203 /* Accept only certificate based search if multiple credentials available*/
204 for (uint16_t i = 0; i < cred_array->len; i++) {
205 if (NULL == cred_array->ptr[i].ca.ptr ||
206 0 == cred_array->ptr[i].ca.len) {
207 continue;
208 }
209
210 PRINT_ARRAY("cred_array[i].ca.ptr", cred_array->ptr[i].ca.ptr,
211 cred_array->ptr[i].ca.len);
212
213 mbedtls_x509_crt m_cert;
214 mbedtls_x509_crt_init(&m_cert);
215
216 /* parse the certificate */
217 TRY_EXPECT(mbedtls_x509_crt_parse_der_nocopy(
218 &m_cert, cred_array->ptr[i].ca.ptr,
219 cred_array->ptr[i].ca.len),
220 0);
221
222 const mbedtls_x509_name *p = &m_cert.subject;
223 const mbedtls_asn1_buf *subject_id = NULL;
224 while (p) {
225 if (0 == MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &p->oid)) {
226 subject_id = &p->val;
227 }
228 p = p->next;
229 };
230
231 if (0 == memcmp(subject_id->p, issuer, subject_id->len)) {
232 root_pk->ptr = cred_array->ptr[i].ca_pk.ptr;
233 root_pk->len = cred_array->ptr[i].ca_pk.len;
234 PRINT_ARRAY("Root PK of the CA", root_pk->ptr,
235 root_pk->len);
236 mbedtls_x509_crt_free(&m_cert);
237 return ok;
238 } else {
239 mbedtls_x509_crt_free(&m_cert);
240 }
241 }
242 #endif /* MBEDTLS */
243
244 return no_such_ca;
245 }
246
cert_c509_verify(struct const_byte_array * cert,const struct cred_array * cred_array,struct byte_array * pk,bool * verified)247 enum err cert_c509_verify(struct const_byte_array *cert,
248 const struct cred_array *cred_array,
249 struct byte_array *pk, bool *verified)
250 {
251 size_t decode_len = 0;
252 struct cert c;
253
254 TRY_EXPECT(cbor_decode_cert(cert->ptr, cert->len, &c, &decode_len), 0);
255
256 PRINT_MSG("CBOR certificate parsed.\n");
257 PRINTF("Certificate type: %d\n", c.cert_type);
258 PRINT_ARRAY("issuer", c.cert_issuer.value, (uint32_t)c.cert_issuer.len);
259 PRINTF("validity_not_before: %d\n", c.cert_validity_not_before);
260 PRINTF("validity_not_after: %d\n", c.cert_validity_not_after);
261 PRINT_ARRAY("subject", c.cert_subject.value,
262 (uint32_t)c.cert_subject.len);
263 PRINT_ARRAY("PK", c.cert_pk.value, (uint32_t)c.cert_pk.len);
264 PRINTF("extensions: %d\n", c.cert_extensions);
265 PRINTF("issuer_signature_algorithm: %d\n",
266 c.cert_issuer_signature_algorithm);
267 PRINT_ARRAY("Signature", c.cert_signature.value,
268 (uint32_t)c.cert_signature.len);
269
270 /*get the CA's public key*/
271 struct byte_array root_pk;
272 TRY(ca_pk_get(cred_array, c.cert_issuer.value, &root_pk));
273
274 /*verify the certificates signature*/
275 struct const_byte_array m = BYTE_ARRAY_INIT(
276 cert->ptr, cert->len - 2 - (uint32_t)c.cert_signature.len);
277 struct const_byte_array sgn = BYTE_ARRAY_INIT(
278 c.cert_signature.value, (uint32_t)c.cert_signature.len);
279
280 TRY(verify((enum sign_alg)c.cert_issuer_signature_algorithm, &root_pk,
281 &m, &sgn, verified));
282
283 TRY(_memcpy_s(pk->ptr, pk->len, c.cert_pk.value,
284 (uint32_t)c.cert_pk.len));
285 pk->len = (uint32_t)c.cert_pk.len;
286
287 return ok;
288 }
289
cert_x509_verify(struct const_byte_array * cert,const struct cred_array * cred_array,struct byte_array * pk,bool * verified)290 enum err cert_x509_verify(struct const_byte_array *cert,
291 const struct cred_array *cred_array,
292 struct byte_array *pk, bool *verified)
293 {
294 #ifdef MBEDTLS
295
296 PRINT_MSG("Start parsing an ASN.1 certificate\n");
297
298 mbedtls_x509_crt m_cert;
299 mbedtls_x509_crt_init(&m_cert);
300
301 /* parse the certificate */
302 TRY_EXPECT(mbedtls_x509_crt_parse_der_nocopy(&m_cert, cert->ptr,
303 cert->len),
304 0);
305
306 /* some raw data from certificate */
307 PRINT_ARRAY("cert.serial", m_cert.serial.p,
308 (uint32_t)m_cert.serial.len);
309 PRINT_ARRAY("cert.issuer_raw", m_cert.issuer_raw.p,
310 (uint32_t)m_cert.issuer_raw.len);
311
312 /* write details about the issuer */
313 /* and find CN (Common Name), further referred to as "issuer_id" */
314 const mbedtls_x509_name *p = &m_cert.issuer;
315
316 #ifdef DEBUG_PRINT
317 const char *short_name;
318 #endif
319 const mbedtls_asn1_buf *issuer_id = NULL;
320 while (p) {
321 #ifdef DEBUG_PRINT
322 mbedtls_oid_get_attr_short_name(&p->oid, &short_name);
323 PRINTF(" %s: %.*s\n", short_name, (int)p->val.len,
324 p->val.p);
325 #endif
326 if (0 == MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &p->oid)) {
327 issuer_id = &p->val;
328 }
329 p = p->next;
330 };
331
332 PRINT_ARRAY("cert issuer_id", issuer_id->p, (uint32_t)issuer_id->len);
333
334 enum sign_alg sign_alg;
335
336 /* make sure it is ECDSA */
337 if (MBEDTLS_PK_ECDSA == m_cert.sig_pk) {
338 sign_alg = ES256;
339 } else {
340 mbedtls_x509_crt_free(&m_cert);
341 return unsupported_signature_algorithm;
342 }
343
344 /* check hash algorithm and init signature buffer */
345 const mbedtls_md_info_t *md_info =
346 mbedtls_md_info_from_type(m_cert.sig_md);
347 if (NULL == md_info) {
348 PRINTF("mbedtls_md_info_from_type(%d) : not found\n",
349 m_cert.sig_md);
350 mbedtls_x509_crt_free(&m_cert);
351 return unsupported_signature_algorithm;
352 }
353 int hash_len = mbedtls_md_get_size(md_info);
354
355 BYTE_ARRAY_NEW(sig, SIGNATURE_SIZE, get_signature_len(sign_alg));
356
357 /* get the public key of the CA */
358 struct byte_array root_pk;
359 TRY(ca_pk_get(cred_array, issuer_id->p, &root_pk));
360
361 /* deserialize signature from ASN.1 to raw concatenation of (R, S) */
362 {
363 uint8_t *pp = m_cert.sig.p;
364 struct deser_sign_ctx_s deser_sign_ctx;
365 deser_sign_ctx_init(&deser_sign_ctx, sig.ptr, sig.ptr + sig.len,
366 hash_len);
367 mbedtls_asn1_traverse_sequence_of(&pp, pp + m_cert.sig.len, 0,
368 0, 0, 0, deser_sign_cb,
369 &deser_sign_ctx);
370 PRINT_ARRAY("Certificate signature", sig.ptr, sig.len);
371 }
372
373 /*verify the certificates signature*/
374 struct const_byte_array m =
375 BYTE_ARRAY_INIT(m_cert.tbs.p, (uint32_t)m_cert.tbs.len);
376 TRY(verify(sign_alg, &root_pk, &m, (struct const_byte_array *)&sig,
377 verified));
378
379 /* export the public key from certificate */
380 {
381 uint8_t *cpk = NULL;
382 uint32_t cpk_len = 0;
383 uint8_t *pp = m_cert.pk_raw.p;
384 mbedtls_asn1_traverse_sequence_of(&pp, pp + m_cert.pk_raw.len,
385 0, 0, 0, 0, find_pk_cb, &cpk);
386 if (cpk) {
387 if (*cpk == 0) {
388 ++cpk;
389 }
390 cpk_len = (uint32_t)m_cert.pk_raw.len -
391 (uint32_t)(cpk - m_cert.pk_raw.p);
392 }
393 TRY(_memcpy_s(pk->ptr, pk->len, cpk, (uint32_t)cpk_len));
394 pk->len = (uint32_t)cpk_len;
395 PRINT_ARRAY("pk from cert", pk->ptr, pk->len);
396 }
397
398 /* cleanup */
399 mbedtls_x509_crt_free(&m_cert);
400
401 return ok;
402
403 #else /* MBEDTLS */
404
405 const uint8_t *tbs_start = cert->ptr;
406 const uint8_t *tbs_end = &cert->ptr[cert->len];
407 BYTE_ARRAY_NEW(sig, SIGNATURE_SIZE, get_signature_len(ES256));
408
409 enum err rv = certificate_authentication_failed;
410
411 /* Crude way to get TBSCertificate address, public key and signature */
412 do {
413 const uint8_t *cursor = cert->ptr;
414 const uint8_t *end = &cert->ptr[cert->len];
415 uint32_t len;
416
417 /* Get first tag, which should be first sequence */
418 EXPECTO_TAG(ASN1_SEQUENCE, cursor, len);
419
420 /* Get second, inner tag, which should be TBSCertificate */
421 tbs_start = cursor;
422 EXPECTO_TAG(ASN1_SEQUENCE, cursor, len);
423 tbs_end = cursor + len;
424
425 /* Iterate over 6 elements to get to public key according to X.509 schema */
426 for (uint32_t iter = 0; iter < 6; iter++) {
427 /* TAG shall not be parsed as it is not used */
428 cursor++;
429 /* Get section length */
430 mbedtls_asn1_get_len(&cursor, end, &len);
431 cursor += len;
432 }
433
434 /* Here should be 7th element with information about key */
435 EXPECTO_TAG(ASN1_SEQUENCE, cursor, len);
436
437 /* Here should be element with information about type of key */
438 EXPECTO_TAG(ASN1_SEQUENCE, cursor, len);
439 /* This section is being skippped */
440 cursor += len;
441
442 /* Expected BIT STRING containing public key */
443 EXPECTO_TAG(ASN1_BIT_STRING, cursor, len);
444
445 /* Now cursor points to public key */
446 _memcpy_s(pk->ptr, pk->len, cursor, (uint32_t)len);
447 pk->len = (uint32_t)len;
448 PRINT_ARRAY("pk from cert", pk->ptr, pk->len);
449
450 /* We can skip whole TBSCertificate */
451 cursor = tbs_end;
452
453 /* Here should be information about signature algorithm */
454 EXPECTO_TAG(ASN1_SEQUENCE, cursor, len);
455 /* We can skip algorithm info length */
456 cursor += len;
457
458 /* Expected BIT STRING containing signature */
459 EXPECTO_TAG(ASN1_BIT_STRING, cursor, len);
460 // cursor++;
461
462 EXPECTO_TAG(ASN1_SEQUENCE, cursor, len);
463
464 EXPECTO_TAG(ASN1_INTEGER, cursor, len);
465
466 TRY_EXPECT((cursor + len) <= end, 1);
467 _memcpy_s(sig.ptr, SIGNATURE_SIZE, cursor, (uint32_t)len);
468 sig.len = len;
469 cursor += len;
470 PRINT_ARRAY("Certificate signature - part1", sig.ptr,
471 (uint32_t)sig.len);
472
473 EXPECTO_TAG(ASN1_INTEGER, cursor, len);
474 TRY_EXPECT((cursor + len) <= end, 1);
475 _memcpy_s(sig.ptr + sig.len,
476 (uint32_t)(SIGNATURE_SIZE - sig.len), cursor,
477 (uint32_t)len);
478 sig.len += len;
479 rv = ok;
480 PRINT_ARRAY("Certificate signature", sig.ptr,
481 (uint32_t)sig.len);
482
483 } while (0);
484
485 struct byte_array root_pk;
486 struct const_byte_array m =
487 BYTE_ARRAY_INIT(tbs_start, (uint32_t)(tbs_end - tbs_start));
488
489 if (ok == rv) {
490 for (uint32_t iter = 0; iter < cred_array->len; iter++) {
491 /* Issuer will not be read from certificate, so no identification is possible within public keys array. */
492 TRY(ca_pk_get(&cred_array[iter], NULL, &root_pk));
493 PRINT_ARRAY("pk from cred_list", root_pk.ptr,
494 root_pk.len);
495 struct const_byte_array s = { .ptr = sig.ptr,
496 .len = sig.len };
497 rv = verify(ES256, &root_pk, &m, &s, verified);
498 }
499 }
500 return rv;
501
502 #endif /* MBEDTLS */
503 }
504