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