xref: /rk3399_ARM-atf/drivers/auth/mbedtls/mbedtls_x509_parser.c (revision 7d37aa171158422b5ee7ee6c3cdad58f6aa066b4)
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 PolarSSL
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 /* mbedTLS headers */
47 #include <polarssl/asn1.h>
48 #include <polarssl/oid.h>
49 #include <polarssl/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	"mbedTLS 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 asn1_buf tbs;
61 static asn1_buf v3_ext;
62 static asn1_buf pk;
63 static asn1_buf sig_alg;
64 static 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 	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 	asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
90 
91 	while (p < end) {
92 		memset(&extn_oid, 0x0, sizeof(extn_oid));
93 		is_critical = 0; /* DEFAULT FALSE */
94 
95 		asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
96 		end_ext_data = p + len;
97 
98 		/* Get extension ID */
99 		extn_oid.tag = *p;
100 		asn1_get_tag(&p, end, &extn_oid.len, ASN1_OID);
101 		extn_oid.p = p;
102 		p += extn_oid.len;
103 
104 		/* Get optional critical */
105 		asn1_get_bool(&p, end_ext_data, &is_critical);
106 
107 		/* Extension data */
108 		asn1_get_tag(&p, end_ext_data, &len, ASN1_OCTET_STRING);
109 		end_ext_octet = p + len;
110 
111 		/* Detect requested extension */
112 		oid_len = oid_get_numeric_string(oid_str,
113 				MAX_OID_STR_LEN, &extn_oid);
114 		if (oid_len == POLARSSL_ERR_OID_BUF_TOO_SMALL) {
115 			return IMG_PARSER_ERR;
116 		}
117 		if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) {
118 			*ext = (void *)p;
119 			*ext_len = (unsigned int)len;
120 			return IMG_PARSER_OK;
121 		}
122 
123 		/* Next */
124 		p = end_ext_octet;
125 	}
126 
127 	return IMG_PARSER_ERR_NOT_FOUND;
128 }
129 
130 
131 /*
132  * Check the integrity of the certificate ASN.1 structure.
133  * Extract the relevant data that will be used later during authentication.
134  */
135 static int cert_parse(void *img, unsigned int img_len)
136 {
137 	int ret, is_critical;
138 	size_t len;
139 	unsigned char *p, *end, *crt_end;
140 	asn1_buf sig_alg1, sig_alg2;
141 
142 	p = (unsigned char *)img;
143 	len = img_len;
144 	end = p + len;
145 
146 	/*
147 	 * Certificate  ::=  SEQUENCE  {
148 	 *      tbsCertificate       TBSCertificate,
149 	 *      signatureAlgorithm   AlgorithmIdentifier,
150 	 *      signatureValue       BIT STRING  }
151 	 */
152 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
153 	if (ret != 0) {
154 		return IMG_PARSER_ERR_FORMAT;
155 	}
156 
157 	if (len > (size_t)(end - p)) {
158 		return IMG_PARSER_ERR_FORMAT;
159 	}
160 	crt_end = p + len;
161 
162 	/*
163 	 * TBSCertificate  ::=  SEQUENCE  {
164 	 */
165 	tbs.p = p;
166 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
167 	if (ret != 0) {
168 		return IMG_PARSER_ERR_FORMAT;
169 	}
170 	end = p + len;
171 	tbs.len = end - tbs.p;
172 
173 	/*
174 	 * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
175 	 */
176 	ret = asn1_get_tag(&p, end, &len,
177 			ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0);
178 	if (ret != 0) {
179 		return IMG_PARSER_ERR_FORMAT;
180 	}
181 	p += len;
182 
183 	/*
184 	 * CertificateSerialNumber  ::=  INTEGER
185 	 */
186 	ret = asn1_get_tag(&p, end, &len, ASN1_INTEGER);
187 	if (ret != 0) {
188 		return IMG_PARSER_ERR_FORMAT;
189 	}
190 	p += len;
191 
192 	/*
193 	 * signature            AlgorithmIdentifier
194 	 */
195 	sig_alg1.p = p;
196 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
197 	if (ret != 0) {
198 		return IMG_PARSER_ERR_FORMAT;
199 	}
200 	if ((end - p) < 1) {
201 		return IMG_PARSER_ERR_FORMAT;
202 	}
203 	sig_alg1.len = (p + len) - sig_alg1.p;
204 	p += len;
205 
206 	/*
207 	 * issuer               Name
208 	 */
209 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
210 	if (ret != 0) {
211 		return IMG_PARSER_ERR_FORMAT;
212 	}
213 	p += len;
214 
215 	/*
216 	 * Validity ::= SEQUENCE {
217 	 *      notBefore      Time,
218 	 *      notAfter       Time }
219 	 *
220 	 */
221 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
222 	if (ret != 0) {
223 		return IMG_PARSER_ERR_FORMAT;
224 	}
225 	p += len;
226 
227 	/*
228 	 * subject              Name
229 	 */
230 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
231 	if (ret != 0) {
232 		return IMG_PARSER_ERR_FORMAT;
233 	}
234 	p += len;
235 
236 	/*
237 	 * SubjectPublicKeyInfo
238 	 */
239 	pk.p = p;
240 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
241 	if (ret != 0) {
242 		return IMG_PARSER_ERR_FORMAT;
243 	}
244 	pk.len = (p + len) - pk.p;
245 	p += len;
246 
247 	/*
248 	 * issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
249 	 */
250 	ret = asn1_get_tag(&p, end, &len,
251 			ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1);
252 	if (ret != 0) {
253 		if (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG) {
254 			return IMG_PARSER_ERR_FORMAT;
255 		}
256 	} else {
257 		p += len;
258 	}
259 
260 	/*
261 	 * subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
262 	 */
263 	ret = asn1_get_tag(&p, end, &len,
264 			ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2);
265 	if (ret != 0) {
266 		if (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG) {
267 			return IMG_PARSER_ERR_FORMAT;
268 		}
269 	} else {
270 		p += len;
271 	}
272 
273 	/*
274 	 * extensions      [3]  EXPLICIT Extensions OPTIONAL
275 	 */
276 	ret = asn1_get_tag(&p, end, &len,
277 			ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3);
278 	if (ret != 0) {
279 		return IMG_PARSER_ERR_FORMAT;
280 	}
281 
282 	/*
283 	 * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
284 	 */
285 	v3_ext.p = p;
286 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
287 	if (ret != 0) {
288 		return IMG_PARSER_ERR_FORMAT;
289 	}
290 	v3_ext.len = (p + len) - v3_ext.p;
291 
292 	/*
293 	 * Check extensions integrity
294 	 */
295 	while (p < end) {
296 		ret = asn1_get_tag(&p, end, &len,
297 				ASN1_CONSTRUCTED | ASN1_SEQUENCE);
298 		if (ret != 0) {
299 			return IMG_PARSER_ERR_FORMAT;
300 		}
301 
302 		/* Get extension ID */
303 		ret = asn1_get_tag(&p, end, &len, ASN1_OID);
304 		if (ret != 0) {
305 			return IMG_PARSER_ERR_FORMAT;
306 		}
307 		p += len;
308 
309 		/* Get optional critical */
310 		ret = asn1_get_bool(&p, end, &is_critical);
311 		if ((ret != 0) && (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG)) {
312 			return IMG_PARSER_ERR_FORMAT;
313 		}
314 
315 		/* Data should be octet string type */
316 		ret = asn1_get_tag(&p, end, &len, ASN1_OCTET_STRING);
317 		if (ret != 0) {
318 			return IMG_PARSER_ERR_FORMAT;
319 		}
320 		p += len;
321 	}
322 
323 	if (p != end) {
324 		return IMG_PARSER_ERR_FORMAT;
325 	}
326 
327 	end = crt_end;
328 
329 	/*
330 	 *  }
331 	 *  -- end of TBSCertificate
332 	 *
333 	 *  signatureAlgorithm   AlgorithmIdentifier
334 	 */
335 	sig_alg2.p = p;
336 	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
337 	if (ret != 0) {
338 		return IMG_PARSER_ERR_FORMAT;
339 	}
340 	if ((end - p) < 1) {
341 		return IMG_PARSER_ERR_FORMAT;
342 	}
343 	sig_alg2.len = (p + len) - sig_alg2.p;
344 	p += len;
345 
346 	/* Compare both signature algorithms */
347 	if (sig_alg1.len != sig_alg2.len) {
348 		return IMG_PARSER_ERR_FORMAT;
349 	}
350 	if (0 != memcmp(sig_alg1.p, sig_alg2.p, sig_alg1.len)) {
351 		return IMG_PARSER_ERR_FORMAT;
352 	}
353 	memcpy(&sig_alg, &sig_alg1, sizeof(sig_alg));
354 
355 	/*
356 	 * signatureValue       BIT STRING
357 	 */
358 	signature.p = p;
359 	ret = asn1_get_tag(&p, end, &len, ASN1_BIT_STRING);
360 	if (ret != 0) {
361 		return IMG_PARSER_ERR_FORMAT;
362 	}
363 	signature.len = (p + len) - signature.p;
364 	p += len;
365 
366 	/* Check certificate length */
367 	if (p != end) {
368 		return IMG_PARSER_ERR_FORMAT;
369 	}
370 
371 	return IMG_PARSER_OK;
372 }
373 
374 
375 /* Exported functions */
376 
377 static void init(void)
378 {
379 	mbedtls_init();
380 }
381 
382 static int check_integrity(void *img, unsigned int img_len)
383 {
384 	return cert_parse(img, img_len);
385 }
386 
387 /*
388  * Extract an authentication parameter from an X509v3 certificate
389  */
390 static int get_auth_param(const auth_param_type_desc_t *type_desc,
391 		void *img, unsigned int img_len,
392 		void **param, unsigned int *param_len)
393 {
394 	int rc = IMG_PARSER_OK;
395 
396 	/* We do not use img because the check_integrity function has already
397 	 * extracted the relevant data (v3_ext, pk, sig_alg, etc) */
398 
399 	switch (type_desc->type) {
400 	case AUTH_PARAM_RAW_DATA:
401 		/* Data to be signed */
402 		*param = (void *)tbs.p;
403 		*param_len = (unsigned int)tbs.len;
404 		break;
405 	case AUTH_PARAM_HASH:
406 		/* All these parameters are included as X509v3 extensions */
407 		rc = get_ext(type_desc->cookie, param, param_len);
408 		break;
409 	case AUTH_PARAM_PUB_KEY:
410 		if (type_desc->cookie != 0) {
411 			/* Get public key from extension */
412 			rc = get_ext(type_desc->cookie, param, param_len);
413 		} else {
414 			/* Get the subject public key */
415 			*param = (void *)pk.p;
416 			*param_len = (unsigned int)pk.len;
417 		}
418 		break;
419 	case AUTH_PARAM_SIG_ALG:
420 		/* Get the certificate signature algorithm */
421 		*param = (void *)sig_alg.p;
422 		*param_len = (unsigned int)sig_alg.len;
423 		break;
424 	case AUTH_PARAM_SIG:
425 		/* Get the certificate signature */
426 		*param = (void *)signature.p;
427 		*param_len = (unsigned int)signature.len;
428 		break;
429 	default:
430 		rc = IMG_PARSER_ERR_NOT_FOUND;
431 		break;
432 	}
433 
434 	return rc;
435 }
436 
437 REGISTER_IMG_PARSER_LIB(IMG_CERT, LIB_NAME, init, \
438 		       check_integrity, get_auth_param);
439