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