xref: /rk3399_ARM-atf/drivers/auth/mbedtls/mbedtls_x509_parser.c (revision 7d37aa171158422b5ee7ee6c3cdad58f6aa066b4)
1*7d37aa17SJuan Castillo /*
2*7d37aa17SJuan Castillo  * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3*7d37aa17SJuan Castillo  *
4*7d37aa17SJuan Castillo  * Redistribution and use in source and binary forms, with or without
5*7d37aa17SJuan Castillo  * modification, are permitted provided that the following conditions are met:
6*7d37aa17SJuan Castillo  *
7*7d37aa17SJuan Castillo  * Redistributions of source code must retain the above copyright notice, this
8*7d37aa17SJuan Castillo  * list of conditions and the following disclaimer.
9*7d37aa17SJuan Castillo  *
10*7d37aa17SJuan Castillo  * Redistributions in binary form must reproduce the above copyright notice,
11*7d37aa17SJuan Castillo  * this list of conditions and the following disclaimer in the documentation
12*7d37aa17SJuan Castillo  * and/or other materials provided with the distribution.
13*7d37aa17SJuan Castillo  *
14*7d37aa17SJuan Castillo  * Neither the name of ARM nor the names of its contributors may be used
15*7d37aa17SJuan Castillo  * to endorse or promote products derived from this software without specific
16*7d37aa17SJuan Castillo  * prior written permission.
17*7d37aa17SJuan Castillo  *
18*7d37aa17SJuan Castillo  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*7d37aa17SJuan Castillo  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*7d37aa17SJuan Castillo  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*7d37aa17SJuan Castillo  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22*7d37aa17SJuan Castillo  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*7d37aa17SJuan Castillo  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*7d37aa17SJuan Castillo  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*7d37aa17SJuan Castillo  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*7d37aa17SJuan Castillo  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*7d37aa17SJuan Castillo  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*7d37aa17SJuan Castillo  * POSSIBILITY OF SUCH DAMAGE.
29*7d37aa17SJuan Castillo  */
30*7d37aa17SJuan Castillo 
31*7d37aa17SJuan Castillo /*
32*7d37aa17SJuan Castillo  * X509 parser based on PolarSSL
33*7d37aa17SJuan Castillo  *
34*7d37aa17SJuan Castillo  * This module implements functions to check the integrity of a X509v3
35*7d37aa17SJuan Castillo  * certificate ASN.1 structure and extract authentication parameters from the
36*7d37aa17SJuan Castillo  * extensions field, such as an image hash or a public key.
37*7d37aa17SJuan Castillo  */
38*7d37aa17SJuan Castillo 
39*7d37aa17SJuan Castillo #include <assert.h>
40*7d37aa17SJuan Castillo #include <img_parser_mod.h>
41*7d37aa17SJuan Castillo #include <mbedtls_common.h>
42*7d37aa17SJuan Castillo #include <stddef.h>
43*7d37aa17SJuan Castillo #include <stdint.h>
44*7d37aa17SJuan Castillo #include <string.h>
45*7d37aa17SJuan Castillo 
46*7d37aa17SJuan Castillo /* mbedTLS headers */
47*7d37aa17SJuan Castillo #include <polarssl/asn1.h>
48*7d37aa17SJuan Castillo #include <polarssl/oid.h>
49*7d37aa17SJuan Castillo #include <polarssl/platform.h>
50*7d37aa17SJuan Castillo 
51*7d37aa17SJuan Castillo /* Maximum OID string length ("a.b.c.d.e.f ...") */
52*7d37aa17SJuan Castillo #define MAX_OID_STR_LEN			64
53*7d37aa17SJuan Castillo 
54*7d37aa17SJuan Castillo #define LIB_NAME	"mbedTLS X509v3"
55*7d37aa17SJuan Castillo 
56*7d37aa17SJuan Castillo /* Temporary variables to speed up the authentication parameters search. These
57*7d37aa17SJuan Castillo  * variables are assigned once during the integrity check and used any time an
58*7d37aa17SJuan Castillo  * authentication parameter is requested, so we do not have to parse the image
59*7d37aa17SJuan Castillo  * again */
60*7d37aa17SJuan Castillo static asn1_buf tbs;
61*7d37aa17SJuan Castillo static asn1_buf v3_ext;
62*7d37aa17SJuan Castillo static asn1_buf pk;
63*7d37aa17SJuan Castillo static asn1_buf sig_alg;
64*7d37aa17SJuan Castillo static asn1_buf signature;
65*7d37aa17SJuan Castillo 
66*7d37aa17SJuan Castillo /*
67*7d37aa17SJuan Castillo  * Get X509v3 extension
68*7d37aa17SJuan Castillo  *
69*7d37aa17SJuan Castillo  * Global variable 'v3_ext' must point to the extensions region
70*7d37aa17SJuan Castillo  * in the certificate. No need to check for errors since the image has passed
71*7d37aa17SJuan Castillo  * the integrity check.
72*7d37aa17SJuan Castillo  */
73*7d37aa17SJuan Castillo static int get_ext(const char *oid, void **ext, unsigned int *ext_len)
74*7d37aa17SJuan Castillo {
75*7d37aa17SJuan Castillo 	int oid_len;
76*7d37aa17SJuan Castillo 	size_t len;
77*7d37aa17SJuan Castillo 	unsigned char *end_ext_data, *end_ext_octet;
78*7d37aa17SJuan Castillo 	unsigned char *p;
79*7d37aa17SJuan Castillo 	const unsigned char *end;
80*7d37aa17SJuan Castillo 	char oid_str[MAX_OID_STR_LEN];
81*7d37aa17SJuan Castillo 	asn1_buf extn_oid;
82*7d37aa17SJuan Castillo 	int is_critical;
83*7d37aa17SJuan Castillo 
84*7d37aa17SJuan Castillo 	assert(oid != NULL);
85*7d37aa17SJuan Castillo 
86*7d37aa17SJuan Castillo 	p = v3_ext.p;
87*7d37aa17SJuan Castillo 	end = v3_ext.p + v3_ext.len;
88*7d37aa17SJuan Castillo 
89*7d37aa17SJuan Castillo 	asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
90*7d37aa17SJuan Castillo 
91*7d37aa17SJuan Castillo 	while (p < end) {
92*7d37aa17SJuan Castillo 		memset(&extn_oid, 0x0, sizeof(extn_oid));
93*7d37aa17SJuan Castillo 		is_critical = 0; /* DEFAULT FALSE */
94*7d37aa17SJuan Castillo 
95*7d37aa17SJuan Castillo 		asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
96*7d37aa17SJuan Castillo 		end_ext_data = p + len;
97*7d37aa17SJuan Castillo 
98*7d37aa17SJuan Castillo 		/* Get extension ID */
99*7d37aa17SJuan Castillo 		extn_oid.tag = *p;
100*7d37aa17SJuan Castillo 		asn1_get_tag(&p, end, &extn_oid.len, ASN1_OID);
101*7d37aa17SJuan Castillo 		extn_oid.p = p;
102*7d37aa17SJuan Castillo 		p += extn_oid.len;
103*7d37aa17SJuan Castillo 
104*7d37aa17SJuan Castillo 		/* Get optional critical */
105*7d37aa17SJuan Castillo 		asn1_get_bool(&p, end_ext_data, &is_critical);
106*7d37aa17SJuan Castillo 
107*7d37aa17SJuan Castillo 		/* Extension data */
108*7d37aa17SJuan Castillo 		asn1_get_tag(&p, end_ext_data, &len, ASN1_OCTET_STRING);
109*7d37aa17SJuan Castillo 		end_ext_octet = p + len;
110*7d37aa17SJuan Castillo 
111*7d37aa17SJuan Castillo 		/* Detect requested extension */
112*7d37aa17SJuan Castillo 		oid_len = oid_get_numeric_string(oid_str,
113*7d37aa17SJuan Castillo 				MAX_OID_STR_LEN, &extn_oid);
114*7d37aa17SJuan Castillo 		if (oid_len == POLARSSL_ERR_OID_BUF_TOO_SMALL) {
115*7d37aa17SJuan Castillo 			return IMG_PARSER_ERR;
116*7d37aa17SJuan Castillo 		}
117*7d37aa17SJuan Castillo 		if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) {
118*7d37aa17SJuan Castillo 			*ext = (void *)p;
119*7d37aa17SJuan Castillo 			*ext_len = (unsigned int)len;
120*7d37aa17SJuan Castillo 			return IMG_PARSER_OK;
121*7d37aa17SJuan Castillo 		}
122*7d37aa17SJuan Castillo 
123*7d37aa17SJuan Castillo 		/* Next */
124*7d37aa17SJuan Castillo 		p = end_ext_octet;
125*7d37aa17SJuan Castillo 	}
126*7d37aa17SJuan Castillo 
127*7d37aa17SJuan Castillo 	return IMG_PARSER_ERR_NOT_FOUND;
128*7d37aa17SJuan Castillo }
129*7d37aa17SJuan Castillo 
130*7d37aa17SJuan Castillo 
131*7d37aa17SJuan Castillo /*
132*7d37aa17SJuan Castillo  * Check the integrity of the certificate ASN.1 structure.
133*7d37aa17SJuan Castillo  * Extract the relevant data that will be used later during authentication.
134*7d37aa17SJuan Castillo  */
135*7d37aa17SJuan Castillo static int cert_parse(void *img, unsigned int img_len)
136*7d37aa17SJuan Castillo {
137*7d37aa17SJuan Castillo 	int ret, is_critical;
138*7d37aa17SJuan Castillo 	size_t len;
139*7d37aa17SJuan Castillo 	unsigned char *p, *end, *crt_end;
140*7d37aa17SJuan Castillo 	asn1_buf sig_alg1, sig_alg2;
141*7d37aa17SJuan Castillo 
142*7d37aa17SJuan Castillo 	p = (unsigned char *)img;
143*7d37aa17SJuan Castillo 	len = img_len;
144*7d37aa17SJuan Castillo 	end = p + len;
145*7d37aa17SJuan Castillo 
146*7d37aa17SJuan Castillo 	/*
147*7d37aa17SJuan Castillo 	 * Certificate  ::=  SEQUENCE  {
148*7d37aa17SJuan Castillo 	 *      tbsCertificate       TBSCertificate,
149*7d37aa17SJuan Castillo 	 *      signatureAlgorithm   AlgorithmIdentifier,
150*7d37aa17SJuan Castillo 	 *      signatureValue       BIT STRING  }
151*7d37aa17SJuan Castillo 	 */
152*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
153*7d37aa17SJuan Castillo 	if (ret != 0) {
154*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
155*7d37aa17SJuan Castillo 	}
156*7d37aa17SJuan Castillo 
157*7d37aa17SJuan Castillo 	if (len > (size_t)(end - p)) {
158*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
159*7d37aa17SJuan Castillo 	}
160*7d37aa17SJuan Castillo 	crt_end = p + len;
161*7d37aa17SJuan Castillo 
162*7d37aa17SJuan Castillo 	/*
163*7d37aa17SJuan Castillo 	 * TBSCertificate  ::=  SEQUENCE  {
164*7d37aa17SJuan Castillo 	 */
165*7d37aa17SJuan Castillo 	tbs.p = p;
166*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
167*7d37aa17SJuan Castillo 	if (ret != 0) {
168*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
169*7d37aa17SJuan Castillo 	}
170*7d37aa17SJuan Castillo 	end = p + len;
171*7d37aa17SJuan Castillo 	tbs.len = end - tbs.p;
172*7d37aa17SJuan Castillo 
173*7d37aa17SJuan Castillo 	/*
174*7d37aa17SJuan Castillo 	 * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
175*7d37aa17SJuan Castillo 	 */
176*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len,
177*7d37aa17SJuan Castillo 			ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0);
178*7d37aa17SJuan Castillo 	if (ret != 0) {
179*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
180*7d37aa17SJuan Castillo 	}
181*7d37aa17SJuan Castillo 	p += len;
182*7d37aa17SJuan Castillo 
183*7d37aa17SJuan Castillo 	/*
184*7d37aa17SJuan Castillo 	 * CertificateSerialNumber  ::=  INTEGER
185*7d37aa17SJuan Castillo 	 */
186*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len, ASN1_INTEGER);
187*7d37aa17SJuan Castillo 	if (ret != 0) {
188*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
189*7d37aa17SJuan Castillo 	}
190*7d37aa17SJuan Castillo 	p += len;
191*7d37aa17SJuan Castillo 
192*7d37aa17SJuan Castillo 	/*
193*7d37aa17SJuan Castillo 	 * signature            AlgorithmIdentifier
194*7d37aa17SJuan Castillo 	 */
195*7d37aa17SJuan Castillo 	sig_alg1.p = p;
196*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
197*7d37aa17SJuan Castillo 	if (ret != 0) {
198*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
199*7d37aa17SJuan Castillo 	}
200*7d37aa17SJuan Castillo 	if ((end - p) < 1) {
201*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
202*7d37aa17SJuan Castillo 	}
203*7d37aa17SJuan Castillo 	sig_alg1.len = (p + len) - sig_alg1.p;
204*7d37aa17SJuan Castillo 	p += len;
205*7d37aa17SJuan Castillo 
206*7d37aa17SJuan Castillo 	/*
207*7d37aa17SJuan Castillo 	 * issuer               Name
208*7d37aa17SJuan Castillo 	 */
209*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
210*7d37aa17SJuan Castillo 	if (ret != 0) {
211*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
212*7d37aa17SJuan Castillo 	}
213*7d37aa17SJuan Castillo 	p += len;
214*7d37aa17SJuan Castillo 
215*7d37aa17SJuan Castillo 	/*
216*7d37aa17SJuan Castillo 	 * Validity ::= SEQUENCE {
217*7d37aa17SJuan Castillo 	 *      notBefore      Time,
218*7d37aa17SJuan Castillo 	 *      notAfter       Time }
219*7d37aa17SJuan Castillo 	 *
220*7d37aa17SJuan Castillo 	 */
221*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
222*7d37aa17SJuan Castillo 	if (ret != 0) {
223*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
224*7d37aa17SJuan Castillo 	}
225*7d37aa17SJuan Castillo 	p += len;
226*7d37aa17SJuan Castillo 
227*7d37aa17SJuan Castillo 	/*
228*7d37aa17SJuan Castillo 	 * subject              Name
229*7d37aa17SJuan Castillo 	 */
230*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
231*7d37aa17SJuan Castillo 	if (ret != 0) {
232*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
233*7d37aa17SJuan Castillo 	}
234*7d37aa17SJuan Castillo 	p += len;
235*7d37aa17SJuan Castillo 
236*7d37aa17SJuan Castillo 	/*
237*7d37aa17SJuan Castillo 	 * SubjectPublicKeyInfo
238*7d37aa17SJuan Castillo 	 */
239*7d37aa17SJuan Castillo 	pk.p = p;
240*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
241*7d37aa17SJuan Castillo 	if (ret != 0) {
242*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
243*7d37aa17SJuan Castillo 	}
244*7d37aa17SJuan Castillo 	pk.len = (p + len) - pk.p;
245*7d37aa17SJuan Castillo 	p += len;
246*7d37aa17SJuan Castillo 
247*7d37aa17SJuan Castillo 	/*
248*7d37aa17SJuan Castillo 	 * issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
249*7d37aa17SJuan Castillo 	 */
250*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len,
251*7d37aa17SJuan Castillo 			ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1);
252*7d37aa17SJuan Castillo 	if (ret != 0) {
253*7d37aa17SJuan Castillo 		if (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG) {
254*7d37aa17SJuan Castillo 			return IMG_PARSER_ERR_FORMAT;
255*7d37aa17SJuan Castillo 		}
256*7d37aa17SJuan Castillo 	} else {
257*7d37aa17SJuan Castillo 		p += len;
258*7d37aa17SJuan Castillo 	}
259*7d37aa17SJuan Castillo 
260*7d37aa17SJuan Castillo 	/*
261*7d37aa17SJuan Castillo 	 * subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
262*7d37aa17SJuan Castillo 	 */
263*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len,
264*7d37aa17SJuan Castillo 			ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2);
265*7d37aa17SJuan Castillo 	if (ret != 0) {
266*7d37aa17SJuan Castillo 		if (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG) {
267*7d37aa17SJuan Castillo 			return IMG_PARSER_ERR_FORMAT;
268*7d37aa17SJuan Castillo 		}
269*7d37aa17SJuan Castillo 	} else {
270*7d37aa17SJuan Castillo 		p += len;
271*7d37aa17SJuan Castillo 	}
272*7d37aa17SJuan Castillo 
273*7d37aa17SJuan Castillo 	/*
274*7d37aa17SJuan Castillo 	 * extensions      [3]  EXPLICIT Extensions OPTIONAL
275*7d37aa17SJuan Castillo 	 */
276*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len,
277*7d37aa17SJuan Castillo 			ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3);
278*7d37aa17SJuan Castillo 	if (ret != 0) {
279*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
280*7d37aa17SJuan Castillo 	}
281*7d37aa17SJuan Castillo 
282*7d37aa17SJuan Castillo 	/*
283*7d37aa17SJuan Castillo 	 * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
284*7d37aa17SJuan Castillo 	 */
285*7d37aa17SJuan Castillo 	v3_ext.p = p;
286*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
287*7d37aa17SJuan Castillo 	if (ret != 0) {
288*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
289*7d37aa17SJuan Castillo 	}
290*7d37aa17SJuan Castillo 	v3_ext.len = (p + len) - v3_ext.p;
291*7d37aa17SJuan Castillo 
292*7d37aa17SJuan Castillo 	/*
293*7d37aa17SJuan Castillo 	 * Check extensions integrity
294*7d37aa17SJuan Castillo 	 */
295*7d37aa17SJuan Castillo 	while (p < end) {
296*7d37aa17SJuan Castillo 		ret = asn1_get_tag(&p, end, &len,
297*7d37aa17SJuan Castillo 				ASN1_CONSTRUCTED | ASN1_SEQUENCE);
298*7d37aa17SJuan Castillo 		if (ret != 0) {
299*7d37aa17SJuan Castillo 			return IMG_PARSER_ERR_FORMAT;
300*7d37aa17SJuan Castillo 		}
301*7d37aa17SJuan Castillo 
302*7d37aa17SJuan Castillo 		/* Get extension ID */
303*7d37aa17SJuan Castillo 		ret = asn1_get_tag(&p, end, &len, ASN1_OID);
304*7d37aa17SJuan Castillo 		if (ret != 0) {
305*7d37aa17SJuan Castillo 			return IMG_PARSER_ERR_FORMAT;
306*7d37aa17SJuan Castillo 		}
307*7d37aa17SJuan Castillo 		p += len;
308*7d37aa17SJuan Castillo 
309*7d37aa17SJuan Castillo 		/* Get optional critical */
310*7d37aa17SJuan Castillo 		ret = asn1_get_bool(&p, end, &is_critical);
311*7d37aa17SJuan Castillo 		if ((ret != 0) && (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG)) {
312*7d37aa17SJuan Castillo 			return IMG_PARSER_ERR_FORMAT;
313*7d37aa17SJuan Castillo 		}
314*7d37aa17SJuan Castillo 
315*7d37aa17SJuan Castillo 		/* Data should be octet string type */
316*7d37aa17SJuan Castillo 		ret = asn1_get_tag(&p, end, &len, ASN1_OCTET_STRING);
317*7d37aa17SJuan Castillo 		if (ret != 0) {
318*7d37aa17SJuan Castillo 			return IMG_PARSER_ERR_FORMAT;
319*7d37aa17SJuan Castillo 		}
320*7d37aa17SJuan Castillo 		p += len;
321*7d37aa17SJuan Castillo 	}
322*7d37aa17SJuan Castillo 
323*7d37aa17SJuan Castillo 	if (p != end) {
324*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
325*7d37aa17SJuan Castillo 	}
326*7d37aa17SJuan Castillo 
327*7d37aa17SJuan Castillo 	end = crt_end;
328*7d37aa17SJuan Castillo 
329*7d37aa17SJuan Castillo 	/*
330*7d37aa17SJuan Castillo 	 *  }
331*7d37aa17SJuan Castillo 	 *  -- end of TBSCertificate
332*7d37aa17SJuan Castillo 	 *
333*7d37aa17SJuan Castillo 	 *  signatureAlgorithm   AlgorithmIdentifier
334*7d37aa17SJuan Castillo 	 */
335*7d37aa17SJuan Castillo 	sig_alg2.p = p;
336*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
337*7d37aa17SJuan Castillo 	if (ret != 0) {
338*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
339*7d37aa17SJuan Castillo 	}
340*7d37aa17SJuan Castillo 	if ((end - p) < 1) {
341*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
342*7d37aa17SJuan Castillo 	}
343*7d37aa17SJuan Castillo 	sig_alg2.len = (p + len) - sig_alg2.p;
344*7d37aa17SJuan Castillo 	p += len;
345*7d37aa17SJuan Castillo 
346*7d37aa17SJuan Castillo 	/* Compare both signature algorithms */
347*7d37aa17SJuan Castillo 	if (sig_alg1.len != sig_alg2.len) {
348*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
349*7d37aa17SJuan Castillo 	}
350*7d37aa17SJuan Castillo 	if (0 != memcmp(sig_alg1.p, sig_alg2.p, sig_alg1.len)) {
351*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
352*7d37aa17SJuan Castillo 	}
353*7d37aa17SJuan Castillo 	memcpy(&sig_alg, &sig_alg1, sizeof(sig_alg));
354*7d37aa17SJuan Castillo 
355*7d37aa17SJuan Castillo 	/*
356*7d37aa17SJuan Castillo 	 * signatureValue       BIT STRING
357*7d37aa17SJuan Castillo 	 */
358*7d37aa17SJuan Castillo 	signature.p = p;
359*7d37aa17SJuan Castillo 	ret = asn1_get_tag(&p, end, &len, ASN1_BIT_STRING);
360*7d37aa17SJuan Castillo 	if (ret != 0) {
361*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
362*7d37aa17SJuan Castillo 	}
363*7d37aa17SJuan Castillo 	signature.len = (p + len) - signature.p;
364*7d37aa17SJuan Castillo 	p += len;
365*7d37aa17SJuan Castillo 
366*7d37aa17SJuan Castillo 	/* Check certificate length */
367*7d37aa17SJuan Castillo 	if (p != end) {
368*7d37aa17SJuan Castillo 		return IMG_PARSER_ERR_FORMAT;
369*7d37aa17SJuan Castillo 	}
370*7d37aa17SJuan Castillo 
371*7d37aa17SJuan Castillo 	return IMG_PARSER_OK;
372*7d37aa17SJuan Castillo }
373*7d37aa17SJuan Castillo 
374*7d37aa17SJuan Castillo 
375*7d37aa17SJuan Castillo /* Exported functions */
376*7d37aa17SJuan Castillo 
377*7d37aa17SJuan Castillo static void init(void)
378*7d37aa17SJuan Castillo {
379*7d37aa17SJuan Castillo 	mbedtls_init();
380*7d37aa17SJuan Castillo }
381*7d37aa17SJuan Castillo 
382*7d37aa17SJuan Castillo static int check_integrity(void *img, unsigned int img_len)
383*7d37aa17SJuan Castillo {
384*7d37aa17SJuan Castillo 	return cert_parse(img, img_len);
385*7d37aa17SJuan Castillo }
386*7d37aa17SJuan Castillo 
387*7d37aa17SJuan Castillo /*
388*7d37aa17SJuan Castillo  * Extract an authentication parameter from an X509v3 certificate
389*7d37aa17SJuan Castillo  */
390*7d37aa17SJuan Castillo static int get_auth_param(const auth_param_type_desc_t *type_desc,
391*7d37aa17SJuan Castillo 		void *img, unsigned int img_len,
392*7d37aa17SJuan Castillo 		void **param, unsigned int *param_len)
393*7d37aa17SJuan Castillo {
394*7d37aa17SJuan Castillo 	int rc = IMG_PARSER_OK;
395*7d37aa17SJuan Castillo 
396*7d37aa17SJuan Castillo 	/* We do not use img because the check_integrity function has already
397*7d37aa17SJuan Castillo 	 * extracted the relevant data (v3_ext, pk, sig_alg, etc) */
398*7d37aa17SJuan Castillo 
399*7d37aa17SJuan Castillo 	switch (type_desc->type) {
400*7d37aa17SJuan Castillo 	case AUTH_PARAM_RAW_DATA:
401*7d37aa17SJuan Castillo 		/* Data to be signed */
402*7d37aa17SJuan Castillo 		*param = (void *)tbs.p;
403*7d37aa17SJuan Castillo 		*param_len = (unsigned int)tbs.len;
404*7d37aa17SJuan Castillo 		break;
405*7d37aa17SJuan Castillo 	case AUTH_PARAM_HASH:
406*7d37aa17SJuan Castillo 		/* All these parameters are included as X509v3 extensions */
407*7d37aa17SJuan Castillo 		rc = get_ext(type_desc->cookie, param, param_len);
408*7d37aa17SJuan Castillo 		break;
409*7d37aa17SJuan Castillo 	case AUTH_PARAM_PUB_KEY:
410*7d37aa17SJuan Castillo 		if (type_desc->cookie != 0) {
411*7d37aa17SJuan Castillo 			/* Get public key from extension */
412*7d37aa17SJuan Castillo 			rc = get_ext(type_desc->cookie, param, param_len);
413*7d37aa17SJuan Castillo 		} else {
414*7d37aa17SJuan Castillo 			/* Get the subject public key */
415*7d37aa17SJuan Castillo 			*param = (void *)pk.p;
416*7d37aa17SJuan Castillo 			*param_len = (unsigned int)pk.len;
417*7d37aa17SJuan Castillo 		}
418*7d37aa17SJuan Castillo 		break;
419*7d37aa17SJuan Castillo 	case AUTH_PARAM_SIG_ALG:
420*7d37aa17SJuan Castillo 		/* Get the certificate signature algorithm */
421*7d37aa17SJuan Castillo 		*param = (void *)sig_alg.p;
422*7d37aa17SJuan Castillo 		*param_len = (unsigned int)sig_alg.len;
423*7d37aa17SJuan Castillo 		break;
424*7d37aa17SJuan Castillo 	case AUTH_PARAM_SIG:
425*7d37aa17SJuan Castillo 		/* Get the certificate signature */
426*7d37aa17SJuan Castillo 		*param = (void *)signature.p;
427*7d37aa17SJuan Castillo 		*param_len = (unsigned int)signature.len;
428*7d37aa17SJuan Castillo 		break;
429*7d37aa17SJuan Castillo 	default:
430*7d37aa17SJuan Castillo 		rc = IMG_PARSER_ERR_NOT_FOUND;
431*7d37aa17SJuan Castillo 		break;
432*7d37aa17SJuan Castillo 	}
433*7d37aa17SJuan Castillo 
434*7d37aa17SJuan Castillo 	return rc;
435*7d37aa17SJuan Castillo }
436*7d37aa17SJuan Castillo 
437*7d37aa17SJuan Castillo REGISTER_IMG_PARSER_LIB(IMG_CERT, LIB_NAME, init, \
438*7d37aa17SJuan Castillo 		       check_integrity, get_auth_param);
439