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