xref: /rk3399_ARM-atf/drivers/auth/mbedtls/mbedtls_x509_parser.c (revision 93f398205a8ebd2c1cef780251a0d24576ab1b28)
1 /*
2  * Copyright (c) 2015-2017, 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 <arch_helpers.h>
40 #include <assert.h>
41 #include <img_parser_mod.h>
42 #include <mbedtls_common.h>
43 #include <stddef.h>
44 #include <stdint.h>
45 #include <string.h>
46 #include <utils.h>
47 
48 /* mbed TLS headers */
49 #include <mbedtls/asn1.h>
50 #include <mbedtls/oid.h>
51 #include <mbedtls/platform.h>
52 
53 /* Maximum OID string length ("a.b.c.d.e.f ...") */
54 #define MAX_OID_STR_LEN			64
55 
56 #define LIB_NAME	"mbed TLS X509v3"
57 
58 /* Temporary variables to speed up the authentication parameters search. These
59  * variables are assigned once during the integrity check and used any time an
60  * authentication parameter is requested, so we do not have to parse the image
61  * again */
62 static mbedtls_asn1_buf tbs;
63 static mbedtls_asn1_buf v3_ext;
64 static mbedtls_asn1_buf pk;
65 static mbedtls_asn1_buf sig_alg;
66 static mbedtls_asn1_buf signature;
67 
68 /*
69  * Clear all static temporary variables.
70  */
71 static void clear_temp_vars(void)
72 {
73 #define ZERO_AND_CLEAN(x)					\
74 	do {							\
75 		zeromem(&x, sizeof(x));				\
76 		clean_dcache_range((uintptr_t)&x, sizeof(x));	\
77 	} while (0);
78 
79 	ZERO_AND_CLEAN(tbs)
80 	ZERO_AND_CLEAN(v3_ext);
81 	ZERO_AND_CLEAN(pk);
82 	ZERO_AND_CLEAN(sig_alg);
83 	ZERO_AND_CLEAN(signature);
84 
85 #undef ZERO_AND_CLEAN
86 }
87 
88 /*
89  * Get X509v3 extension
90  *
91  * Global variable 'v3_ext' must point to the extensions region
92  * in the certificate. No need to check for errors since the image has passed
93  * the integrity check.
94  */
95 static int get_ext(const char *oid, void **ext, unsigned int *ext_len)
96 {
97 	int oid_len;
98 	size_t len;
99 	unsigned char *end_ext_data, *end_ext_octet;
100 	unsigned char *p;
101 	const unsigned char *end;
102 	char oid_str[MAX_OID_STR_LEN];
103 	mbedtls_asn1_buf extn_oid;
104 	int is_critical;
105 
106 	assert(oid != NULL);
107 
108 	p = v3_ext.p;
109 	end = v3_ext.p + v3_ext.len;
110 
111 	mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
112 			     MBEDTLS_ASN1_SEQUENCE);
113 
114 	while (p < end) {
115 		zeromem(&extn_oid, sizeof(extn_oid));
116 		is_critical = 0; /* DEFAULT FALSE */
117 
118 		mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
119 				     MBEDTLS_ASN1_SEQUENCE);
120 		end_ext_data = p + len;
121 
122 		/* Get extension ID */
123 		extn_oid.tag = *p;
124 		mbedtls_asn1_get_tag(&p, end, &extn_oid.len, MBEDTLS_ASN1_OID);
125 		extn_oid.p = p;
126 		p += extn_oid.len;
127 
128 		/* Get optional critical */
129 		mbedtls_asn1_get_bool(&p, end_ext_data, &is_critical);
130 
131 		/* Extension data */
132 		mbedtls_asn1_get_tag(&p, end_ext_data, &len,
133 				     MBEDTLS_ASN1_OCTET_STRING);
134 		end_ext_octet = p + len;
135 
136 		/* Detect requested extension */
137 		oid_len = mbedtls_oid_get_numeric_string(oid_str,
138 							 MAX_OID_STR_LEN,
139 							 &extn_oid);
140 		if (oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) {
141 			return IMG_PARSER_ERR;
142 		}
143 		if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) {
144 			*ext = (void *)p;
145 			*ext_len = (unsigned int)len;
146 			return IMG_PARSER_OK;
147 		}
148 
149 		/* Next */
150 		p = end_ext_octet;
151 	}
152 
153 	return IMG_PARSER_ERR_NOT_FOUND;
154 }
155 
156 
157 /*
158  * Check the integrity of the certificate ASN.1 structure.
159  *
160  * Extract the relevant data that will be used later during authentication.
161  *
162  * This function doesn't clear the static variables located on the top of this
163  * file in case of an error. It is only called from check_integrity(), which
164  * performs the cleanup if necessary.
165  */
166 static int cert_parse(void *img, unsigned int img_len)
167 {
168 	int ret, is_critical;
169 	size_t len;
170 	unsigned char *p, *end, *crt_end;
171 	mbedtls_asn1_buf sig_alg1, sig_alg2;
172 
173 	p = (unsigned char *)img;
174 	len = img_len;
175 	end = p + len;
176 
177 	/*
178 	 * Certificate  ::=  SEQUENCE  {
179 	 *      tbsCertificate       TBSCertificate,
180 	 *      signatureAlgorithm   AlgorithmIdentifier,
181 	 *      signatureValue       BIT STRING  }
182 	 */
183 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
184 				   MBEDTLS_ASN1_SEQUENCE);
185 	if (ret != 0) {
186 		return IMG_PARSER_ERR_FORMAT;
187 	}
188 
189 	if (len > (size_t)(end - p)) {
190 		return IMG_PARSER_ERR_FORMAT;
191 	}
192 	crt_end = p + len;
193 
194 	/*
195 	 * TBSCertificate  ::=  SEQUENCE  {
196 	 */
197 	tbs.p = p;
198 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
199 				   MBEDTLS_ASN1_SEQUENCE);
200 	if (ret != 0) {
201 		return IMG_PARSER_ERR_FORMAT;
202 	}
203 	end = p + len;
204 	tbs.len = end - tbs.p;
205 
206 	/*
207 	 * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
208 	 */
209 	ret = mbedtls_asn1_get_tag(&p, end, &len,
210 				   MBEDTLS_ASN1_CONTEXT_SPECIFIC |
211 				   MBEDTLS_ASN1_CONSTRUCTED | 0);
212 	if (ret != 0) {
213 		return IMG_PARSER_ERR_FORMAT;
214 	}
215 	p += len;
216 
217 	/*
218 	 * CertificateSerialNumber  ::=  INTEGER
219 	 */
220 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
221 	if (ret != 0) {
222 		return IMG_PARSER_ERR_FORMAT;
223 	}
224 	p += len;
225 
226 	/*
227 	 * signature            AlgorithmIdentifier
228 	 */
229 	sig_alg1.p = p;
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 	if ((end - p) < 1) {
236 		return IMG_PARSER_ERR_FORMAT;
237 	}
238 	sig_alg1.len = (p + len) - sig_alg1.p;
239 	p += len;
240 
241 	/*
242 	 * issuer               Name
243 	 */
244 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
245 				   MBEDTLS_ASN1_SEQUENCE);
246 	if (ret != 0) {
247 		return IMG_PARSER_ERR_FORMAT;
248 	}
249 	p += len;
250 
251 	/*
252 	 * Validity ::= SEQUENCE {
253 	 *      notBefore      Time,
254 	 *      notAfter       Time }
255 	 *
256 	 */
257 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
258 				   MBEDTLS_ASN1_SEQUENCE);
259 	if (ret != 0) {
260 		return IMG_PARSER_ERR_FORMAT;
261 	}
262 	p += len;
263 
264 	/*
265 	 * subject              Name
266 	 */
267 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
268 				   MBEDTLS_ASN1_SEQUENCE);
269 	if (ret != 0) {
270 		return IMG_PARSER_ERR_FORMAT;
271 	}
272 	p += len;
273 
274 	/*
275 	 * SubjectPublicKeyInfo
276 	 */
277 	pk.p = p;
278 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
279 				   MBEDTLS_ASN1_SEQUENCE);
280 	if (ret != 0) {
281 		return IMG_PARSER_ERR_FORMAT;
282 	}
283 	pk.len = (p + len) - pk.p;
284 	p += len;
285 
286 	/*
287 	 * issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
288 	 */
289 	ret = mbedtls_asn1_get_tag(&p, end, &len,
290 				   MBEDTLS_ASN1_CONTEXT_SPECIFIC |
291 				   MBEDTLS_ASN1_CONSTRUCTED | 1);
292 	if (ret != 0) {
293 		if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
294 			return IMG_PARSER_ERR_FORMAT;
295 		}
296 	} else {
297 		p += len;
298 	}
299 
300 	/*
301 	 * subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
302 	 */
303 	ret = mbedtls_asn1_get_tag(&p, end, &len,
304 				   MBEDTLS_ASN1_CONTEXT_SPECIFIC |
305 				   MBEDTLS_ASN1_CONSTRUCTED | 2);
306 	if (ret != 0) {
307 		if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
308 			return IMG_PARSER_ERR_FORMAT;
309 		}
310 	} else {
311 		p += len;
312 	}
313 
314 	/*
315 	 * extensions      [3]  EXPLICIT Extensions OPTIONAL
316 	 */
317 	ret = mbedtls_asn1_get_tag(&p, end, &len,
318 				   MBEDTLS_ASN1_CONTEXT_SPECIFIC |
319 				   MBEDTLS_ASN1_CONSTRUCTED | 3);
320 	if (ret != 0) {
321 		return IMG_PARSER_ERR_FORMAT;
322 	}
323 
324 	/*
325 	 * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
326 	 */
327 	v3_ext.p = p;
328 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
329 				   MBEDTLS_ASN1_SEQUENCE);
330 	if (ret != 0) {
331 		return IMG_PARSER_ERR_FORMAT;
332 	}
333 	v3_ext.len = (p + len) - v3_ext.p;
334 
335 	/*
336 	 * Check extensions integrity
337 	 */
338 	while (p < end) {
339 		ret = mbedtls_asn1_get_tag(&p, end, &len,
340 					   MBEDTLS_ASN1_CONSTRUCTED |
341 					   MBEDTLS_ASN1_SEQUENCE);
342 		if (ret != 0) {
343 			return IMG_PARSER_ERR_FORMAT;
344 		}
345 
346 		/* Get extension ID */
347 		ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID);
348 		if (ret != 0) {
349 			return IMG_PARSER_ERR_FORMAT;
350 		}
351 		p += len;
352 
353 		/* Get optional critical */
354 		ret = mbedtls_asn1_get_bool(&p, end, &is_critical);
355 		if ((ret != 0) && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {
356 			return IMG_PARSER_ERR_FORMAT;
357 		}
358 
359 		/* Data should be octet string type */
360 		ret = mbedtls_asn1_get_tag(&p, end, &len,
361 					   MBEDTLS_ASN1_OCTET_STRING);
362 		if (ret != 0) {
363 			return IMG_PARSER_ERR_FORMAT;
364 		}
365 		p += len;
366 	}
367 
368 	if (p != end) {
369 		return IMG_PARSER_ERR_FORMAT;
370 	}
371 
372 	end = crt_end;
373 
374 	/*
375 	 *  }
376 	 *  -- end of TBSCertificate
377 	 *
378 	 *  signatureAlgorithm   AlgorithmIdentifier
379 	 */
380 	sig_alg2.p = p;
381 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
382 				   MBEDTLS_ASN1_SEQUENCE);
383 	if (ret != 0) {
384 		return IMG_PARSER_ERR_FORMAT;
385 	}
386 	if ((end - p) < 1) {
387 		return IMG_PARSER_ERR_FORMAT;
388 	}
389 	sig_alg2.len = (p + len) - sig_alg2.p;
390 	p += len;
391 
392 	/* Compare both signature algorithms */
393 	if (sig_alg1.len != sig_alg2.len) {
394 		return IMG_PARSER_ERR_FORMAT;
395 	}
396 	if (0 != memcmp(sig_alg1.p, sig_alg2.p, sig_alg1.len)) {
397 		return IMG_PARSER_ERR_FORMAT;
398 	}
399 	memcpy(&sig_alg, &sig_alg1, sizeof(sig_alg));
400 
401 	/*
402 	 * signatureValue       BIT STRING
403 	 */
404 	signature.p = p;
405 	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_BIT_STRING);
406 	if (ret != 0) {
407 		return IMG_PARSER_ERR_FORMAT;
408 	}
409 	signature.len = (p + len) - signature.p;
410 	p += len;
411 
412 	/* Check certificate length */
413 	if (p != end) {
414 		return IMG_PARSER_ERR_FORMAT;
415 	}
416 
417 	return IMG_PARSER_OK;
418 }
419 
420 
421 /* Exported functions */
422 
423 static void init(void)
424 {
425 	mbedtls_init();
426 }
427 
428 /*
429  * Wrapper for cert_parse() that clears the static variables used by it in case
430  * of an error.
431  */
432 static int check_integrity(void *img, unsigned int img_len)
433 {
434 	int rc = cert_parse(img, img_len);
435 
436 	if (rc != IMG_PARSER_OK)
437 		clear_temp_vars();
438 
439 	return rc;
440 }
441 
442 /*
443  * Extract an authentication parameter from an X509v3 certificate
444  *
445  * This function returns a pointer to the extracted data and its length.
446  * Depending on the type of parameter, a pointer to the data stored in the
447  * certificate may be returned (i.e. an octet string containing a hash). Other
448  * data may need to be copied and formatted (i.e. integers). In the later case,
449  * a buffer of the correct type needs to be statically allocated, filled and
450  * returned.
451  */
452 static int get_auth_param(const auth_param_type_desc_t *type_desc,
453 		void *img, unsigned int img_len,
454 		void **param, unsigned int *param_len)
455 {
456 	int rc = IMG_PARSER_OK;
457 
458 	/* We do not use img because the check_integrity function has already
459 	 * extracted the relevant data (v3_ext, pk, sig_alg, etc) */
460 
461 	switch (type_desc->type) {
462 	case AUTH_PARAM_RAW_DATA:
463 		/* Data to be signed */
464 		*param = (void *)tbs.p;
465 		*param_len = (unsigned int)tbs.len;
466 		break;
467 	case AUTH_PARAM_HASH:
468 	case AUTH_PARAM_NV_CTR:
469 		/* All these parameters are included as X509v3 extensions */
470 		rc = get_ext(type_desc->cookie, param, param_len);
471 		break;
472 	case AUTH_PARAM_PUB_KEY:
473 		if (type_desc->cookie != 0) {
474 			/* Get public key from extension */
475 			rc = get_ext(type_desc->cookie, param, param_len);
476 		} else {
477 			/* Get the subject public key */
478 			*param = (void *)pk.p;
479 			*param_len = (unsigned int)pk.len;
480 		}
481 		break;
482 	case AUTH_PARAM_SIG_ALG:
483 		/* Get the certificate signature algorithm */
484 		*param = (void *)sig_alg.p;
485 		*param_len = (unsigned int)sig_alg.len;
486 		break;
487 	case AUTH_PARAM_SIG:
488 		/* Get the certificate signature */
489 		*param = (void *)signature.p;
490 		*param_len = (unsigned int)signature.len;
491 		break;
492 	default:
493 		rc = IMG_PARSER_ERR_NOT_FOUND;
494 		break;
495 	}
496 
497 	return rc;
498 }
499 
500 REGISTER_IMG_PARSER_LIB(IMG_CERT, LIB_NAME, init, \
501 		       check_integrity, get_auth_param);
502