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