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