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