xref: /arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509_parser.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu /*
8*91f16700Schasinglulu  * X509 parser based on mbed TLS
9*91f16700Schasinglulu  *
10*91f16700Schasinglulu  * This module implements functions to check the integrity of a X509v3
11*91f16700Schasinglulu  * certificate ASN.1 structure and extract authentication parameters from the
12*91f16700Schasinglulu  * extensions field, such as an image hash or a public key.
13*91f16700Schasinglulu  */
14*91f16700Schasinglulu 
15*91f16700Schasinglulu #include <assert.h>
16*91f16700Schasinglulu #include <stddef.h>
17*91f16700Schasinglulu #include <stdint.h>
18*91f16700Schasinglulu #include <string.h>
19*91f16700Schasinglulu 
20*91f16700Schasinglulu /* mbed TLS headers */
21*91f16700Schasinglulu #include <mbedtls/asn1.h>
22*91f16700Schasinglulu #include <mbedtls/oid.h>
23*91f16700Schasinglulu #include <mbedtls/platform.h>
24*91f16700Schasinglulu 
25*91f16700Schasinglulu #include <arch_helpers.h>
26*91f16700Schasinglulu #include <drivers/auth/img_parser_mod.h>
27*91f16700Schasinglulu #include <drivers/auth/mbedtls/mbedtls_common.h>
28*91f16700Schasinglulu #include <lib/utils.h>
29*91f16700Schasinglulu 
30*91f16700Schasinglulu /* Maximum OID string length ("a.b.c.d.e.f ...") */
31*91f16700Schasinglulu #define MAX_OID_STR_LEN			64
32*91f16700Schasinglulu 
33*91f16700Schasinglulu #define LIB_NAME	"mbed TLS X509v3"
34*91f16700Schasinglulu 
35*91f16700Schasinglulu /* Temporary variables to speed up the authentication parameters search. These
36*91f16700Schasinglulu  * variables are assigned once during the integrity check and used any time an
37*91f16700Schasinglulu  * authentication parameter is requested, so we do not have to parse the image
38*91f16700Schasinglulu  * again */
39*91f16700Schasinglulu static mbedtls_asn1_buf tbs;
40*91f16700Schasinglulu static mbedtls_asn1_buf v3_ext;
41*91f16700Schasinglulu static mbedtls_asn1_buf pk;
42*91f16700Schasinglulu static mbedtls_asn1_buf sig_alg;
43*91f16700Schasinglulu static mbedtls_asn1_buf signature;
44*91f16700Schasinglulu 
45*91f16700Schasinglulu /*
46*91f16700Schasinglulu  * Clear all static temporary variables.
47*91f16700Schasinglulu  */
48*91f16700Schasinglulu static void clear_temp_vars(void)
49*91f16700Schasinglulu {
50*91f16700Schasinglulu #define ZERO_AND_CLEAN(x)					\
51*91f16700Schasinglulu 	do {							\
52*91f16700Schasinglulu 		zeromem(&x, sizeof(x));				\
53*91f16700Schasinglulu 		clean_dcache_range((uintptr_t)&x, sizeof(x));	\
54*91f16700Schasinglulu 	} while (0);
55*91f16700Schasinglulu 
56*91f16700Schasinglulu 	ZERO_AND_CLEAN(tbs)
57*91f16700Schasinglulu 	ZERO_AND_CLEAN(v3_ext);
58*91f16700Schasinglulu 	ZERO_AND_CLEAN(pk);
59*91f16700Schasinglulu 	ZERO_AND_CLEAN(sig_alg);
60*91f16700Schasinglulu 	ZERO_AND_CLEAN(signature);
61*91f16700Schasinglulu 
62*91f16700Schasinglulu #undef ZERO_AND_CLEAN
63*91f16700Schasinglulu }
64*91f16700Schasinglulu 
65*91f16700Schasinglulu /*
66*91f16700Schasinglulu  * Get X509v3 extension
67*91f16700Schasinglulu  *
68*91f16700Schasinglulu  * Global variable 'v3_ext' must point to the extensions region
69*91f16700Schasinglulu  * in the certificate.  OID may be NULL to request that get_ext()
70*91f16700Schasinglulu  * is only being called for integrity checking.
71*91f16700Schasinglulu  */
72*91f16700Schasinglulu static int get_ext(const char *oid, void **ext, unsigned int *ext_len)
73*91f16700Schasinglulu {
74*91f16700Schasinglulu 	int oid_len, ret, is_critical;
75*91f16700Schasinglulu 	size_t len;
76*91f16700Schasinglulu 	unsigned char *p;
77*91f16700Schasinglulu 	const unsigned char *end;
78*91f16700Schasinglulu 	char oid_str[MAX_OID_STR_LEN];
79*91f16700Schasinglulu 	mbedtls_asn1_buf extn_oid;
80*91f16700Schasinglulu 
81*91f16700Schasinglulu 	p = v3_ext.p;
82*91f16700Schasinglulu 	end = v3_ext.p + v3_ext.len;
83*91f16700Schasinglulu 
84*91f16700Schasinglulu 	/*
85*91f16700Schasinglulu 	 * Check extensions integrity.  At least one extension is
86*91f16700Schasinglulu 	 * required: the ASN.1 specifies a minimum size of 1, and at
87*91f16700Schasinglulu 	 * least one extension is needed to authenticate the next stage
88*91f16700Schasinglulu 	 * in the boot chain.
89*91f16700Schasinglulu 	 */
90*91f16700Schasinglulu 	do {
91*91f16700Schasinglulu 		unsigned char *end_ext_data;
92*91f16700Schasinglulu 
93*91f16700Schasinglulu 		ret = mbedtls_asn1_get_tag(&p, end, &len,
94*91f16700Schasinglulu 					   MBEDTLS_ASN1_CONSTRUCTED |
95*91f16700Schasinglulu 					   MBEDTLS_ASN1_SEQUENCE);
96*91f16700Schasinglulu 		if (ret != 0) {
97*91f16700Schasinglulu 			return IMG_PARSER_ERR_FORMAT;
98*91f16700Schasinglulu 		}
99*91f16700Schasinglulu 		end_ext_data = p + len;
100*91f16700Schasinglulu 
101*91f16700Schasinglulu 		/* Get extension ID */
102*91f16700Schasinglulu 		ret = mbedtls_asn1_get_tag(&p, end_ext_data, &extn_oid.len,
103*91f16700Schasinglulu 					   MBEDTLS_ASN1_OID);
104*91f16700Schasinglulu 		if (ret != 0) {
105*91f16700Schasinglulu 			return IMG_PARSER_ERR_FORMAT;
106*91f16700Schasinglulu 		}
107*91f16700Schasinglulu 		extn_oid.tag = MBEDTLS_ASN1_OID;
108*91f16700Schasinglulu 		extn_oid.p = p;
109*91f16700Schasinglulu 		p += extn_oid.len;
110*91f16700Schasinglulu 
111*91f16700Schasinglulu 		/* Get optional critical */
112*91f16700Schasinglulu 		ret = mbedtls_asn1_get_bool(&p, end_ext_data, &is_critical);
113*91f16700Schasinglulu 		if ((ret != 0) && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {
114*91f16700Schasinglulu 			return IMG_PARSER_ERR_FORMAT;
115*91f16700Schasinglulu 		}
116*91f16700Schasinglulu 
117*91f16700Schasinglulu 		/*
118*91f16700Schasinglulu 		 * Data should be octet string type and must use all bytes in
119*91f16700Schasinglulu 		 * the Extension.
120*91f16700Schasinglulu 		 */
121*91f16700Schasinglulu 		ret = mbedtls_asn1_get_tag(&p, end_ext_data, &len,
122*91f16700Schasinglulu 					   MBEDTLS_ASN1_OCTET_STRING);
123*91f16700Schasinglulu 		if ((ret != 0) || ((p + len) != end_ext_data)) {
124*91f16700Schasinglulu 			return IMG_PARSER_ERR_FORMAT;
125*91f16700Schasinglulu 		}
126*91f16700Schasinglulu 
127*91f16700Schasinglulu 		/* Detect requested extension */
128*91f16700Schasinglulu 		oid_len = mbedtls_oid_get_numeric_string(oid_str,
129*91f16700Schasinglulu 							 MAX_OID_STR_LEN,
130*91f16700Schasinglulu 							 &extn_oid);
131*91f16700Schasinglulu 		if ((oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) || (oid_len < 0)) {
132*91f16700Schasinglulu 			return IMG_PARSER_ERR;
133*91f16700Schasinglulu 		}
134*91f16700Schasinglulu 
135*91f16700Schasinglulu 		if ((oid != NULL) &&
136*91f16700Schasinglulu 		    ((size_t)oid_len == strlen(oid_str)) &&
137*91f16700Schasinglulu 		    (strcmp(oid, oid_str) == 0)) {
138*91f16700Schasinglulu 			/* Extension must be ASN.1 DER */
139*91f16700Schasinglulu 			if (len < 2) {
140*91f16700Schasinglulu 				/* too short */
141*91f16700Schasinglulu 				return IMG_PARSER_ERR_FORMAT;
142*91f16700Schasinglulu 			}
143*91f16700Schasinglulu 
144*91f16700Schasinglulu 			if ((p[0] & 0x1F) == 0x1F) {
145*91f16700Schasinglulu 				/* multi-byte ASN.1 DER tag, not allowed */
146*91f16700Schasinglulu 				return IMG_PARSER_ERR_FORMAT;
147*91f16700Schasinglulu 			}
148*91f16700Schasinglulu 
149*91f16700Schasinglulu 			if ((p[0] & 0xDF) == 0) {
150*91f16700Schasinglulu 				/* UNIVERSAL 0 tag, not allowed */
151*91f16700Schasinglulu 				return IMG_PARSER_ERR_FORMAT;
152*91f16700Schasinglulu 			}
153*91f16700Schasinglulu 
154*91f16700Schasinglulu 			*ext = (void *)p;
155*91f16700Schasinglulu 			*ext_len = (unsigned int)len;
156*91f16700Schasinglulu 
157*91f16700Schasinglulu 			/* Advance past the tag byte */
158*91f16700Schasinglulu 			p++;
159*91f16700Schasinglulu 
160*91f16700Schasinglulu 			if (mbedtls_asn1_get_len(&p, end_ext_data, &len)) {
161*91f16700Schasinglulu 				/* not valid DER */
162*91f16700Schasinglulu 				return IMG_PARSER_ERR_FORMAT;
163*91f16700Schasinglulu 			}
164*91f16700Schasinglulu 
165*91f16700Schasinglulu 			if (p + len != end_ext_data) {
166*91f16700Schasinglulu 				/* junk after ASN.1 object */
167*91f16700Schasinglulu 				return IMG_PARSER_ERR_FORMAT;
168*91f16700Schasinglulu 			}
169*91f16700Schasinglulu 
170*91f16700Schasinglulu 			return IMG_PARSER_OK;
171*91f16700Schasinglulu 		}
172*91f16700Schasinglulu 
173*91f16700Schasinglulu 		/* Next */
174*91f16700Schasinglulu 		p = end_ext_data;
175*91f16700Schasinglulu 	} while (p < end);
176*91f16700Schasinglulu 
177*91f16700Schasinglulu 	return (oid == NULL) ? IMG_PARSER_OK : IMG_PARSER_ERR_NOT_FOUND;
178*91f16700Schasinglulu }
179*91f16700Schasinglulu 
180*91f16700Schasinglulu 
181*91f16700Schasinglulu /*
182*91f16700Schasinglulu  * Check the integrity of the certificate ASN.1 structure.
183*91f16700Schasinglulu  *
184*91f16700Schasinglulu  * Extract the relevant data that will be used later during authentication.
185*91f16700Schasinglulu  *
186*91f16700Schasinglulu  * This function doesn't clear the static variables located on the top of this
187*91f16700Schasinglulu  * file in case of an error. It is only called from check_integrity(), which
188*91f16700Schasinglulu  * performs the cleanup if necessary.
189*91f16700Schasinglulu  */
190*91f16700Schasinglulu static int cert_parse(void *img, unsigned int img_len)
191*91f16700Schasinglulu {
192*91f16700Schasinglulu 	int ret;
193*91f16700Schasinglulu 	size_t len;
194*91f16700Schasinglulu 	unsigned char *p, *end, *crt_end, *pk_end;
195*91f16700Schasinglulu 	mbedtls_asn1_buf sig_alg1;
196*91f16700Schasinglulu 	/*
197*91f16700Schasinglulu 	 * The unique ASN.1 DER encoding of [0] EXPLICIT INTEGER { v3(2} }.
198*91f16700Schasinglulu 	 */
199*91f16700Schasinglulu 	static const char v3[] = {
200*91f16700Schasinglulu 		/* The outer CONTEXT SPECIFIC 0 tag */
201*91f16700Schasinglulu 		MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0,
202*91f16700Schasinglulu 		/* The number bytes used to encode the inner INTEGER */
203*91f16700Schasinglulu 		3,
204*91f16700Schasinglulu 		/* The tag of the inner INTEGER */
205*91f16700Schasinglulu 		MBEDTLS_ASN1_INTEGER,
206*91f16700Schasinglulu 		/* The number of bytes needed to represent 2 */
207*91f16700Schasinglulu 		1,
208*91f16700Schasinglulu 		/* The actual value 2 */
209*91f16700Schasinglulu 		2,
210*91f16700Schasinglulu 	};
211*91f16700Schasinglulu 
212*91f16700Schasinglulu 	p = (unsigned char *)img;
213*91f16700Schasinglulu 	len = img_len;
214*91f16700Schasinglulu 	crt_end = p + len;
215*91f16700Schasinglulu 	end = crt_end;
216*91f16700Schasinglulu 
217*91f16700Schasinglulu 	/*
218*91f16700Schasinglulu 	 * Certificate  ::=  SEQUENCE  {
219*91f16700Schasinglulu 	 *      tbsCertificate       TBSCertificate,
220*91f16700Schasinglulu 	 *      signatureAlgorithm   AlgorithmIdentifier,
221*91f16700Schasinglulu 	 *      signatureValue       BIT STRING  }
222*91f16700Schasinglulu 	 */
223*91f16700Schasinglulu 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
224*91f16700Schasinglulu 				   MBEDTLS_ASN1_SEQUENCE);
225*91f16700Schasinglulu 	if ((ret != 0) || ((p + len) != end)) {
226*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
227*91f16700Schasinglulu 	}
228*91f16700Schasinglulu 
229*91f16700Schasinglulu 	/*
230*91f16700Schasinglulu 	 * TBSCertificate  ::=  SEQUENCE  {
231*91f16700Schasinglulu 	 */
232*91f16700Schasinglulu 	tbs.p = p;
233*91f16700Schasinglulu 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
234*91f16700Schasinglulu 				   MBEDTLS_ASN1_SEQUENCE);
235*91f16700Schasinglulu 	if (ret != 0) {
236*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
237*91f16700Schasinglulu 	}
238*91f16700Schasinglulu 	end = p + len;
239*91f16700Schasinglulu 	tbs.len = end - tbs.p;
240*91f16700Schasinglulu 
241*91f16700Schasinglulu 	/*
242*91f16700Schasinglulu 	 * Version  ::=  [0] EXPLICIT INTEGER {  v1(0), v2(1), v3(2)  }
243*91f16700Schasinglulu 	 * -- only v3 accepted
244*91f16700Schasinglulu 	 */
245*91f16700Schasinglulu 	if (((end - p) <= (ptrdiff_t)sizeof(v3)) ||
246*91f16700Schasinglulu 	    (memcmp(p, v3, sizeof(v3)) != 0)) {
247*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
248*91f16700Schasinglulu 	}
249*91f16700Schasinglulu 	p += sizeof(v3);
250*91f16700Schasinglulu 
251*91f16700Schasinglulu 	/*
252*91f16700Schasinglulu 	 * CertificateSerialNumber  ::=  INTEGER
253*91f16700Schasinglulu 	 */
254*91f16700Schasinglulu 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
255*91f16700Schasinglulu 	if (ret != 0) {
256*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
257*91f16700Schasinglulu 	}
258*91f16700Schasinglulu 	p += len;
259*91f16700Schasinglulu 
260*91f16700Schasinglulu 	/*
261*91f16700Schasinglulu 	 * signature            AlgorithmIdentifier
262*91f16700Schasinglulu 	 */
263*91f16700Schasinglulu 	sig_alg1.p = p;
264*91f16700Schasinglulu 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
265*91f16700Schasinglulu 				   MBEDTLS_ASN1_SEQUENCE);
266*91f16700Schasinglulu 	if (ret != 0) {
267*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
268*91f16700Schasinglulu 	}
269*91f16700Schasinglulu 	sig_alg1.len = (p + len) - sig_alg1.p;
270*91f16700Schasinglulu 	p += len;
271*91f16700Schasinglulu 
272*91f16700Schasinglulu 	/*
273*91f16700Schasinglulu 	 * issuer               Name
274*91f16700Schasinglulu 	 */
275*91f16700Schasinglulu 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
276*91f16700Schasinglulu 				   MBEDTLS_ASN1_SEQUENCE);
277*91f16700Schasinglulu 	if (ret != 0) {
278*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
279*91f16700Schasinglulu 	}
280*91f16700Schasinglulu 	p += len;
281*91f16700Schasinglulu 
282*91f16700Schasinglulu 	/*
283*91f16700Schasinglulu 	 * Validity ::= SEQUENCE {
284*91f16700Schasinglulu 	 *      notBefore      Time,
285*91f16700Schasinglulu 	 *      notAfter       Time }
286*91f16700Schasinglulu 	 *
287*91f16700Schasinglulu 	 */
288*91f16700Schasinglulu 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
289*91f16700Schasinglulu 				   MBEDTLS_ASN1_SEQUENCE);
290*91f16700Schasinglulu 	if (ret != 0) {
291*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
292*91f16700Schasinglulu 	}
293*91f16700Schasinglulu 	p += len;
294*91f16700Schasinglulu 
295*91f16700Schasinglulu 	/*
296*91f16700Schasinglulu 	 * subject              Name
297*91f16700Schasinglulu 	 */
298*91f16700Schasinglulu 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
299*91f16700Schasinglulu 				   MBEDTLS_ASN1_SEQUENCE);
300*91f16700Schasinglulu 	if (ret != 0) {
301*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
302*91f16700Schasinglulu 	}
303*91f16700Schasinglulu 	p += len;
304*91f16700Schasinglulu 
305*91f16700Schasinglulu 	/*
306*91f16700Schasinglulu 	 * SubjectPublicKeyInfo
307*91f16700Schasinglulu 	 */
308*91f16700Schasinglulu 	pk.p = p;
309*91f16700Schasinglulu 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
310*91f16700Schasinglulu 				   MBEDTLS_ASN1_SEQUENCE);
311*91f16700Schasinglulu 	if (ret != 0) {
312*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
313*91f16700Schasinglulu 	}
314*91f16700Schasinglulu 	pk_end = p + len;
315*91f16700Schasinglulu 	pk.len = pk_end - pk.p;
316*91f16700Schasinglulu 
317*91f16700Schasinglulu 	/* algorithm */
318*91f16700Schasinglulu 	ret = mbedtls_asn1_get_tag(&p, pk_end, &len, MBEDTLS_ASN1_CONSTRUCTED |
319*91f16700Schasinglulu 				   MBEDTLS_ASN1_SEQUENCE);
320*91f16700Schasinglulu 	if (ret != 0) {
321*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
322*91f16700Schasinglulu 	}
323*91f16700Schasinglulu 	p += len;
324*91f16700Schasinglulu 
325*91f16700Schasinglulu 	/* Key is a BIT STRING and must use all bytes in SubjectPublicKeyInfo */
326*91f16700Schasinglulu 	ret = mbedtls_asn1_get_bitstring_null(&p, pk_end, &len);
327*91f16700Schasinglulu 	if ((ret != 0) || (p + len != pk_end)) {
328*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
329*91f16700Schasinglulu 	}
330*91f16700Schasinglulu 	p = pk_end;
331*91f16700Schasinglulu 
332*91f16700Schasinglulu 	/*
333*91f16700Schasinglulu 	 * issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
334*91f16700Schasinglulu 	 * subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
335*91f16700Schasinglulu 	 * -- technically these contain BIT STRINGs but that is not worth
336*91f16700Schasinglulu 	 * -- validating
337*91f16700Schasinglulu 	 */
338*91f16700Schasinglulu 	for (int i = 1; i < 3; i++) {
339*91f16700Schasinglulu 		ret = mbedtls_asn1_get_tag(&p, end, &len,
340*91f16700Schasinglulu 					   MBEDTLS_ASN1_CONTEXT_SPECIFIC |
341*91f16700Schasinglulu 					   MBEDTLS_ASN1_CONSTRUCTED | i);
342*91f16700Schasinglulu 		/*
343*91f16700Schasinglulu 		 * Unique IDs are obsolete, so MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
344*91f16700Schasinglulu 		 * is the common case.
345*91f16700Schasinglulu 		 */
346*91f16700Schasinglulu 		if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
347*91f16700Schasinglulu 			if (ret != 0) {
348*91f16700Schasinglulu 				return IMG_PARSER_ERR_FORMAT;
349*91f16700Schasinglulu 			}
350*91f16700Schasinglulu 			p += len;
351*91f16700Schasinglulu 		}
352*91f16700Schasinglulu 	}
353*91f16700Schasinglulu 
354*91f16700Schasinglulu 	/*
355*91f16700Schasinglulu 	 * extensions      [3]  EXPLICIT Extensions OPTIONAL
356*91f16700Schasinglulu 	 * }
357*91f16700Schasinglulu 	 *
358*91f16700Schasinglulu 	 * X.509 and RFC5280 allow omitting the extensions entirely.
359*91f16700Schasinglulu 	 * However, in TF-A, a certificate with no extensions would
360*91f16700Schasinglulu 	 * always fail later on, as the extensions contain the
361*91f16700Schasinglulu 	 * information needed to authenticate the next stage in the
362*91f16700Schasinglulu 	 * boot chain.  Furthermore, get_ext() assumes that the
363*91f16700Schasinglulu 	 * extensions have been parsed into v3_ext, and allowing
364*91f16700Schasinglulu 	 * there to be no extensions would pointlessly complicate
365*91f16700Schasinglulu 	 * the code.  Therefore, just reject certificates without
366*91f16700Schasinglulu 	 * extensions.  This is also why version 1 and 2 certificates
367*91f16700Schasinglulu 	 * are rejected above.
368*91f16700Schasinglulu 	 */
369*91f16700Schasinglulu 	ret = mbedtls_asn1_get_tag(&p, end, &len,
370*91f16700Schasinglulu 				   MBEDTLS_ASN1_CONTEXT_SPECIFIC |
371*91f16700Schasinglulu 				   MBEDTLS_ASN1_CONSTRUCTED | 3);
372*91f16700Schasinglulu 	if ((ret != 0) || (len != (size_t)(end - p))) {
373*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
374*91f16700Schasinglulu 	}
375*91f16700Schasinglulu 
376*91f16700Schasinglulu 	/*
377*91f16700Schasinglulu 	 * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
378*91f16700Schasinglulu 	 * -- must use all remaining bytes in TBSCertificate
379*91f16700Schasinglulu 	 */
380*91f16700Schasinglulu 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
381*91f16700Schasinglulu 				   MBEDTLS_ASN1_SEQUENCE);
382*91f16700Schasinglulu 	if ((ret != 0) || (len != (size_t)(end - p))) {
383*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
384*91f16700Schasinglulu 	}
385*91f16700Schasinglulu 	v3_ext.p = p;
386*91f16700Schasinglulu 	v3_ext.len = len;
387*91f16700Schasinglulu 	p += len;
388*91f16700Schasinglulu 
389*91f16700Schasinglulu 	/* Check extensions integrity */
390*91f16700Schasinglulu 	ret = get_ext(NULL, NULL, NULL);
391*91f16700Schasinglulu 	if (ret != IMG_PARSER_OK) {
392*91f16700Schasinglulu 		return ret;
393*91f16700Schasinglulu 	}
394*91f16700Schasinglulu 
395*91f16700Schasinglulu 	end = crt_end;
396*91f16700Schasinglulu 
397*91f16700Schasinglulu 	/*
398*91f16700Schasinglulu 	 *  }
399*91f16700Schasinglulu 	 *  -- end of TBSCertificate
400*91f16700Schasinglulu 	 *
401*91f16700Schasinglulu 	 *  signatureAlgorithm   AlgorithmIdentifier
402*91f16700Schasinglulu 	 *  -- Does not need to be parsed.  Ensuring it is bitwise
403*91f16700Schasinglulu 	 *  -- identical (including the tag!) with the first signature
404*91f16700Schasinglulu 	 *  -- algorithm is sufficient.
405*91f16700Schasinglulu 	 */
406*91f16700Schasinglulu 	if ((sig_alg1.len >= (size_t)(end - p)) ||
407*91f16700Schasinglulu 	    (0 != memcmp(sig_alg1.p, p, sig_alg1.len))) {
408*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
409*91f16700Schasinglulu 	}
410*91f16700Schasinglulu 	p += sig_alg1.len;
411*91f16700Schasinglulu 	memcpy(&sig_alg, &sig_alg1, sizeof(sig_alg));
412*91f16700Schasinglulu 
413*91f16700Schasinglulu 	/*
414*91f16700Schasinglulu 	 * signatureValue       BIT STRING
415*91f16700Schasinglulu 	 * } -- must consume all bytes
416*91f16700Schasinglulu 	 */
417*91f16700Schasinglulu 	signature.p = p;
418*91f16700Schasinglulu 	ret = mbedtls_asn1_get_bitstring_null(&p, end, &len);
419*91f16700Schasinglulu 	if ((ret != 0) || ((p + len) != end)) {
420*91f16700Schasinglulu 		return IMG_PARSER_ERR_FORMAT;
421*91f16700Schasinglulu 	}
422*91f16700Schasinglulu 	signature.len = end - signature.p;
423*91f16700Schasinglulu 
424*91f16700Schasinglulu 	return IMG_PARSER_OK;
425*91f16700Schasinglulu }
426*91f16700Schasinglulu 
427*91f16700Schasinglulu 
428*91f16700Schasinglulu /* Exported functions */
429*91f16700Schasinglulu 
430*91f16700Schasinglulu static void init(void)
431*91f16700Schasinglulu {
432*91f16700Schasinglulu 	mbedtls_init();
433*91f16700Schasinglulu }
434*91f16700Schasinglulu 
435*91f16700Schasinglulu /*
436*91f16700Schasinglulu  * Wrapper for cert_parse() that clears the static variables used by it in case
437*91f16700Schasinglulu  * of an error.
438*91f16700Schasinglulu  */
439*91f16700Schasinglulu static int check_integrity(void *img, unsigned int img_len)
440*91f16700Schasinglulu {
441*91f16700Schasinglulu 	int rc = cert_parse(img, img_len);
442*91f16700Schasinglulu 
443*91f16700Schasinglulu 	if (rc != IMG_PARSER_OK)
444*91f16700Schasinglulu 		clear_temp_vars();
445*91f16700Schasinglulu 
446*91f16700Schasinglulu 	return rc;
447*91f16700Schasinglulu }
448*91f16700Schasinglulu 
449*91f16700Schasinglulu /*
450*91f16700Schasinglulu  * Extract an authentication parameter from an X509v3 certificate
451*91f16700Schasinglulu  *
452*91f16700Schasinglulu  * This function returns a pointer to the extracted data and its length.
453*91f16700Schasinglulu  * Depending on the type of parameter, a pointer to the data stored in the
454*91f16700Schasinglulu  * certificate may be returned (i.e. an octet string containing a hash). Other
455*91f16700Schasinglulu  * data may need to be copied and formatted (i.e. integers). In the later case,
456*91f16700Schasinglulu  * a buffer of the correct type needs to be statically allocated, filled and
457*91f16700Schasinglulu  * returned.
458*91f16700Schasinglulu  */
459*91f16700Schasinglulu static int get_auth_param(const auth_param_type_desc_t *type_desc,
460*91f16700Schasinglulu 		void *img, unsigned int img_len,
461*91f16700Schasinglulu 		void **param, unsigned int *param_len)
462*91f16700Schasinglulu {
463*91f16700Schasinglulu 	int rc = IMG_PARSER_OK;
464*91f16700Schasinglulu 
465*91f16700Schasinglulu 	/* We do not use img because the check_integrity function has already
466*91f16700Schasinglulu 	 * extracted the relevant data (v3_ext, pk, sig_alg, etc) */
467*91f16700Schasinglulu 
468*91f16700Schasinglulu 	switch (type_desc->type) {
469*91f16700Schasinglulu 	case AUTH_PARAM_RAW_DATA:
470*91f16700Schasinglulu 		/* Data to be signed */
471*91f16700Schasinglulu 		*param = (void *)tbs.p;
472*91f16700Schasinglulu 		*param_len = (unsigned int)tbs.len;
473*91f16700Schasinglulu 		break;
474*91f16700Schasinglulu 	case AUTH_PARAM_HASH:
475*91f16700Schasinglulu 	case AUTH_PARAM_NV_CTR:
476*91f16700Schasinglulu 		/* All these parameters are included as X509v3 extensions */
477*91f16700Schasinglulu 		rc = get_ext(type_desc->cookie, param, param_len);
478*91f16700Schasinglulu 		break;
479*91f16700Schasinglulu 	case AUTH_PARAM_PUB_KEY:
480*91f16700Schasinglulu 		if (type_desc->cookie != NULL) {
481*91f16700Schasinglulu 			/* Get public key from extension */
482*91f16700Schasinglulu 			rc = get_ext(type_desc->cookie, param, param_len);
483*91f16700Schasinglulu 		} else {
484*91f16700Schasinglulu 			/* Get the subject public key */
485*91f16700Schasinglulu 			*param = (void *)pk.p;
486*91f16700Schasinglulu 			*param_len = (unsigned int)pk.len;
487*91f16700Schasinglulu 		}
488*91f16700Schasinglulu 		break;
489*91f16700Schasinglulu 	case AUTH_PARAM_SIG_ALG:
490*91f16700Schasinglulu 		/* Get the certificate signature algorithm */
491*91f16700Schasinglulu 		*param = (void *)sig_alg.p;
492*91f16700Schasinglulu 		*param_len = (unsigned int)sig_alg.len;
493*91f16700Schasinglulu 		break;
494*91f16700Schasinglulu 	case AUTH_PARAM_SIG:
495*91f16700Schasinglulu 		/* Get the certificate signature */
496*91f16700Schasinglulu 		*param = (void *)signature.p;
497*91f16700Schasinglulu 		*param_len = (unsigned int)signature.len;
498*91f16700Schasinglulu 		break;
499*91f16700Schasinglulu 	default:
500*91f16700Schasinglulu 		rc = IMG_PARSER_ERR_NOT_FOUND;
501*91f16700Schasinglulu 		break;
502*91f16700Schasinglulu 	}
503*91f16700Schasinglulu 
504*91f16700Schasinglulu 	return rc;
505*91f16700Schasinglulu }
506*91f16700Schasinglulu 
507*91f16700Schasinglulu REGISTER_IMG_PARSER_LIB(IMG_CERT, LIB_NAME, init,
508*91f16700Schasinglulu 		       check_integrity, get_auth_param);
509