1 /* 2 * Copyright (c) 2015-2023, 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. OID may be NULL to request that get_ext() 70 * is only being called for integrity checking. 71 */ 72 static int get_ext(const char *oid, void **ext, unsigned int *ext_len) 73 { 74 int oid_len, ret, is_critical; 75 size_t len; 76 unsigned char *p; 77 const unsigned char *end; 78 char oid_str[MAX_OID_STR_LEN]; 79 mbedtls_asn1_buf extn_oid; 80 81 p = v3_ext.p; 82 end = v3_ext.p + v3_ext.len; 83 84 /* 85 * Check extensions integrity. At least one extension is 86 * required: the ASN.1 specifies a minimum size of 1, and at 87 * least one extension is needed to authenticate the next stage 88 * in the boot chain. 89 */ 90 do { 91 unsigned char *end_ext_data; 92 93 ret = mbedtls_asn1_get_tag(&p, end, &len, 94 MBEDTLS_ASN1_CONSTRUCTED | 95 MBEDTLS_ASN1_SEQUENCE); 96 if (ret != 0) { 97 return IMG_PARSER_ERR_FORMAT; 98 } 99 end_ext_data = p + len; 100 101 /* Get extension ID */ 102 ret = mbedtls_asn1_get_tag(&p, end_ext_data, &extn_oid.len, 103 MBEDTLS_ASN1_OID); 104 if (ret != 0) { 105 return IMG_PARSER_ERR_FORMAT; 106 } 107 extn_oid.tag = MBEDTLS_ASN1_OID; 108 extn_oid.p = p; 109 p += extn_oid.len; 110 111 /* Get optional critical */ 112 ret = mbedtls_asn1_get_bool(&p, end_ext_data, &is_critical); 113 if ((ret != 0) && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { 114 return IMG_PARSER_ERR_FORMAT; 115 } 116 117 /* 118 * Data should be octet string type and must use all bytes in 119 * the Extension. 120 */ 121 ret = mbedtls_asn1_get_tag(&p, end_ext_data, &len, 122 MBEDTLS_ASN1_OCTET_STRING); 123 if ((ret != 0) || ((p + len) != end_ext_data)) { 124 return IMG_PARSER_ERR_FORMAT; 125 } 126 127 /* Detect requested extension */ 128 oid_len = mbedtls_oid_get_numeric_string(oid_str, 129 MAX_OID_STR_LEN, 130 &extn_oid); 131 if ((oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) || (oid_len < 0)) { 132 return IMG_PARSER_ERR; 133 } 134 135 if ((oid != NULL) && 136 ((size_t)oid_len == strlen(oid_str)) && 137 (strcmp(oid, oid_str) == 0)) { 138 /* Extension must be ASN.1 DER */ 139 if (len < 2) { 140 /* too short */ 141 return IMG_PARSER_ERR_FORMAT; 142 } 143 144 if ((p[0] & 0x1F) == 0x1F) { 145 /* multi-byte ASN.1 DER tag, not allowed */ 146 return IMG_PARSER_ERR_FORMAT; 147 } 148 149 if ((p[0] & 0xDF) == 0) { 150 /* UNIVERSAL 0 tag, not allowed */ 151 return IMG_PARSER_ERR_FORMAT; 152 } 153 154 *ext = (void *)p; 155 *ext_len = (unsigned int)len; 156 157 /* Advance past the tag byte */ 158 p++; 159 160 if (mbedtls_asn1_get_len(&p, end_ext_data, &len)) { 161 /* not valid DER */ 162 return IMG_PARSER_ERR_FORMAT; 163 } 164 165 if (p + len != end_ext_data) { 166 /* junk after ASN.1 object */ 167 return IMG_PARSER_ERR_FORMAT; 168 } 169 170 return IMG_PARSER_OK; 171 } 172 173 /* Next */ 174 p = end_ext_data; 175 } while (p < end); 176 177 return (oid == NULL) ? IMG_PARSER_OK : IMG_PARSER_ERR_NOT_FOUND; 178 } 179 180 181 /* 182 * Check the integrity of the certificate ASN.1 structure. 183 * 184 * Extract the relevant data that will be used later during authentication. 185 * 186 * This function doesn't clear the static variables located on the top of this 187 * file in case of an error. It is only called from check_integrity(), which 188 * performs the cleanup if necessary. 189 */ 190 static int cert_parse(void *img, unsigned int img_len) 191 { 192 int ret; 193 size_t len; 194 unsigned char *p, *end, *crt_end, *pk_end; 195 mbedtls_asn1_buf sig_alg1; 196 /* 197 * The unique ASN.1 DER encoding of [0] EXPLICIT INTEGER { v3(2} }. 198 */ 199 static const char v3[] = { 200 /* The outer CONTEXT SPECIFIC 0 tag */ 201 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0, 202 /* The number bytes used to encode the inner INTEGER */ 203 3, 204 /* The tag of the inner INTEGER */ 205 MBEDTLS_ASN1_INTEGER, 206 /* The number of bytes needed to represent 2 */ 207 1, 208 /* The actual value 2 */ 209 2, 210 }; 211 212 p = (unsigned char *)img; 213 len = img_len; 214 crt_end = p + len; 215 end = crt_end; 216 217 /* 218 * Certificate ::= SEQUENCE { 219 * tbsCertificate TBSCertificate, 220 * signatureAlgorithm AlgorithmIdentifier, 221 * signatureValue BIT STRING } 222 */ 223 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 224 MBEDTLS_ASN1_SEQUENCE); 225 if ((ret != 0) || ((p + len) != end)) { 226 return IMG_PARSER_ERR_FORMAT; 227 } 228 229 /* 230 * TBSCertificate ::= SEQUENCE { 231 */ 232 tbs.p = p; 233 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 234 MBEDTLS_ASN1_SEQUENCE); 235 if (ret != 0) { 236 return IMG_PARSER_ERR_FORMAT; 237 } 238 end = p + len; 239 tbs.len = end - tbs.p; 240 241 /* 242 * Version ::= [0] EXPLICIT INTEGER { v1(0), v2(1), v3(2) } 243 * -- only v3 accepted 244 */ 245 if (((end - p) <= (ptrdiff_t)sizeof(v3)) || 246 (memcmp(p, v3, sizeof(v3)) != 0)) { 247 return IMG_PARSER_ERR_FORMAT; 248 } 249 p += sizeof(v3); 250 251 /* 252 * CertificateSerialNumber ::= INTEGER 253 */ 254 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER); 255 if (ret != 0) { 256 return IMG_PARSER_ERR_FORMAT; 257 } 258 p += len; 259 260 /* 261 * signature AlgorithmIdentifier 262 */ 263 sig_alg1.p = p; 264 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 265 MBEDTLS_ASN1_SEQUENCE); 266 if (ret != 0) { 267 return IMG_PARSER_ERR_FORMAT; 268 } 269 sig_alg1.len = (p + len) - sig_alg1.p; 270 p += len; 271 272 /* 273 * issuer Name 274 */ 275 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 276 MBEDTLS_ASN1_SEQUENCE); 277 if (ret != 0) { 278 return IMG_PARSER_ERR_FORMAT; 279 } 280 p += len; 281 282 /* 283 * Validity ::= SEQUENCE { 284 * notBefore Time, 285 * notAfter Time } 286 * 287 */ 288 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 289 MBEDTLS_ASN1_SEQUENCE); 290 if (ret != 0) { 291 return IMG_PARSER_ERR_FORMAT; 292 } 293 p += len; 294 295 /* 296 * subject Name 297 */ 298 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 299 MBEDTLS_ASN1_SEQUENCE); 300 if (ret != 0) { 301 return IMG_PARSER_ERR_FORMAT; 302 } 303 p += len; 304 305 /* 306 * SubjectPublicKeyInfo 307 */ 308 pk.p = p; 309 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 310 MBEDTLS_ASN1_SEQUENCE); 311 if (ret != 0) { 312 return IMG_PARSER_ERR_FORMAT; 313 } 314 pk_end = p + len; 315 pk.len = pk_end - pk.p; 316 317 /* algorithm */ 318 ret = mbedtls_asn1_get_tag(&p, pk_end, &len, MBEDTLS_ASN1_CONSTRUCTED | 319 MBEDTLS_ASN1_SEQUENCE); 320 if (ret != 0) { 321 return IMG_PARSER_ERR_FORMAT; 322 } 323 p += len; 324 325 /* Key is a BIT STRING and must use all bytes in SubjectPublicKeyInfo */ 326 ret = mbedtls_asn1_get_bitstring_null(&p, pk_end, &len); 327 if ((ret != 0) || (p + len != pk_end)) { 328 return IMG_PARSER_ERR_FORMAT; 329 } 330 p = pk_end; 331 332 /* 333 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, 334 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, 335 * -- technically these contain BIT STRINGs but that is not worth 336 * -- validating 337 */ 338 for (int i = 1; i < 3; i++) { 339 ret = mbedtls_asn1_get_tag(&p, end, &len, 340 MBEDTLS_ASN1_CONTEXT_SPECIFIC | 341 MBEDTLS_ASN1_CONSTRUCTED | i); 342 /* 343 * Unique IDs are obsolete, so MBEDTLS_ERR_ASN1_UNEXPECTED_TAG 344 * is the common case. 345 */ 346 if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 347 if (ret != 0) { 348 return IMG_PARSER_ERR_FORMAT; 349 } 350 p += len; 351 } 352 } 353 354 /* 355 * extensions [3] EXPLICIT Extensions OPTIONAL 356 * } 357 * 358 * X.509 and RFC5280 allow omitting the extensions entirely. 359 * However, in TF-A, a certificate with no extensions would 360 * always fail later on, as the extensions contain the 361 * information needed to authenticate the next stage in the 362 * boot chain. Furthermore, get_ext() assumes that the 363 * extensions have been parsed into v3_ext, and allowing 364 * there to be no extensions would pointlessly complicate 365 * the code. Therefore, just reject certificates without 366 * extensions. This is also why version 1 and 2 certificates 367 * are rejected above. 368 */ 369 ret = mbedtls_asn1_get_tag(&p, end, &len, 370 MBEDTLS_ASN1_CONTEXT_SPECIFIC | 371 MBEDTLS_ASN1_CONSTRUCTED | 3); 372 if ((ret != 0) || (len != (size_t)(end - p))) { 373 return IMG_PARSER_ERR_FORMAT; 374 } 375 376 /* 377 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 378 * -- must use all remaining bytes in TBSCertificate 379 */ 380 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 381 MBEDTLS_ASN1_SEQUENCE); 382 if ((ret != 0) || (len != (size_t)(end - p))) { 383 return IMG_PARSER_ERR_FORMAT; 384 } 385 v3_ext.p = p; 386 v3_ext.len = len; 387 p += len; 388 389 /* Check extensions integrity */ 390 ret = get_ext(NULL, NULL, NULL); 391 if (ret != IMG_PARSER_OK) { 392 return ret; 393 } 394 395 end = crt_end; 396 397 /* 398 * } 399 * -- end of TBSCertificate 400 * 401 * signatureAlgorithm AlgorithmIdentifier 402 * -- Does not need to be parsed. Ensuring it is bitwise 403 * -- identical (including the tag!) with the first signature 404 * -- algorithm is sufficient. 405 */ 406 if ((sig_alg1.len >= (size_t)(end - p)) || 407 (0 != memcmp(sig_alg1.p, p, sig_alg1.len))) { 408 return IMG_PARSER_ERR_FORMAT; 409 } 410 p += sig_alg1.len; 411 memcpy(&sig_alg, &sig_alg1, sizeof(sig_alg)); 412 413 /* 414 * signatureValue BIT STRING 415 * } -- must consume all bytes 416 */ 417 signature.p = p; 418 ret = mbedtls_asn1_get_bitstring_null(&p, end, &len); 419 if ((ret != 0) || ((p + len) != end)) { 420 return IMG_PARSER_ERR_FORMAT; 421 } 422 signature.len = end - signature.p; 423 424 return IMG_PARSER_OK; 425 } 426 427 428 /* Exported functions */ 429 430 static void init(void) 431 { 432 mbedtls_init(); 433 } 434 435 /* 436 * Wrapper for cert_parse() that clears the static variables used by it in case 437 * of an error. 438 */ 439 static int check_integrity(void *img, unsigned int img_len) 440 { 441 int rc = cert_parse(img, img_len); 442 443 if (rc != IMG_PARSER_OK) 444 clear_temp_vars(); 445 446 return rc; 447 } 448 449 /* 450 * Extract an authentication parameter from an X509v3 certificate 451 * 452 * This function returns a pointer to the extracted data and its length. 453 * Depending on the type of parameter, a pointer to the data stored in the 454 * certificate may be returned (i.e. an octet string containing a hash). Other 455 * data may need to be copied and formatted (i.e. integers). In the later case, 456 * a buffer of the correct type needs to be statically allocated, filled and 457 * returned. 458 */ 459 static int get_auth_param(const auth_param_type_desc_t *type_desc, 460 void *img, unsigned int img_len, 461 void **param, unsigned int *param_len) 462 { 463 int rc = IMG_PARSER_OK; 464 465 /* We do not use img because the check_integrity function has already 466 * extracted the relevant data (v3_ext, pk, sig_alg, etc) */ 467 468 switch (type_desc->type) { 469 case AUTH_PARAM_RAW_DATA: 470 /* Data to be signed */ 471 *param = (void *)tbs.p; 472 *param_len = (unsigned int)tbs.len; 473 break; 474 case AUTH_PARAM_HASH: 475 case AUTH_PARAM_NV_CTR: 476 /* All these parameters are included as X509v3 extensions */ 477 rc = get_ext(type_desc->cookie, param, param_len); 478 break; 479 case AUTH_PARAM_PUB_KEY: 480 if (type_desc->cookie != NULL) { 481 /* Get public key from extension */ 482 rc = get_ext(type_desc->cookie, param, param_len); 483 } else { 484 /* Get the subject public key */ 485 *param = (void *)pk.p; 486 *param_len = (unsigned int)pk.len; 487 } 488 break; 489 case AUTH_PARAM_SIG_ALG: 490 /* Get the certificate signature algorithm */ 491 *param = (void *)sig_alg.p; 492 *param_len = (unsigned int)sig_alg.len; 493 break; 494 case AUTH_PARAM_SIG: 495 /* Get the certificate signature */ 496 *param = (void *)signature.p; 497 *param_len = (unsigned int)signature.len; 498 break; 499 default: 500 rc = IMG_PARSER_ERR_NOT_FOUND; 501 break; 502 } 503 504 return rc; 505 } 506 507 REGISTER_IMG_PARSER_LIB(IMG_CERT, LIB_NAME, init, 508 check_integrity, get_auth_param); 509