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