1*7d37aa17SJuan Castillo /* 2*7d37aa17SJuan Castillo * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3*7d37aa17SJuan Castillo * 4*7d37aa17SJuan Castillo * Redistribution and use in source and binary forms, with or without 5*7d37aa17SJuan Castillo * modification, are permitted provided that the following conditions are met: 6*7d37aa17SJuan Castillo * 7*7d37aa17SJuan Castillo * Redistributions of source code must retain the above copyright notice, this 8*7d37aa17SJuan Castillo * list of conditions and the following disclaimer. 9*7d37aa17SJuan Castillo * 10*7d37aa17SJuan Castillo * Redistributions in binary form must reproduce the above copyright notice, 11*7d37aa17SJuan Castillo * this list of conditions and the following disclaimer in the documentation 12*7d37aa17SJuan Castillo * and/or other materials provided with the distribution. 13*7d37aa17SJuan Castillo * 14*7d37aa17SJuan Castillo * Neither the name of ARM nor the names of its contributors may be used 15*7d37aa17SJuan Castillo * to endorse or promote products derived from this software without specific 16*7d37aa17SJuan Castillo * prior written permission. 17*7d37aa17SJuan Castillo * 18*7d37aa17SJuan Castillo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19*7d37aa17SJuan Castillo * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*7d37aa17SJuan Castillo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*7d37aa17SJuan Castillo * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22*7d37aa17SJuan Castillo * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23*7d37aa17SJuan Castillo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24*7d37aa17SJuan Castillo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25*7d37aa17SJuan Castillo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26*7d37aa17SJuan Castillo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27*7d37aa17SJuan Castillo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28*7d37aa17SJuan Castillo * POSSIBILITY OF SUCH DAMAGE. 29*7d37aa17SJuan Castillo */ 30*7d37aa17SJuan Castillo 31*7d37aa17SJuan Castillo /* 32*7d37aa17SJuan Castillo * X509 parser based on PolarSSL 33*7d37aa17SJuan Castillo * 34*7d37aa17SJuan Castillo * This module implements functions to check the integrity of a X509v3 35*7d37aa17SJuan Castillo * certificate ASN.1 structure and extract authentication parameters from the 36*7d37aa17SJuan Castillo * extensions field, such as an image hash or a public key. 37*7d37aa17SJuan Castillo */ 38*7d37aa17SJuan Castillo 39*7d37aa17SJuan Castillo #include <assert.h> 40*7d37aa17SJuan Castillo #include <img_parser_mod.h> 41*7d37aa17SJuan Castillo #include <mbedtls_common.h> 42*7d37aa17SJuan Castillo #include <stddef.h> 43*7d37aa17SJuan Castillo #include <stdint.h> 44*7d37aa17SJuan Castillo #include <string.h> 45*7d37aa17SJuan Castillo 46*7d37aa17SJuan Castillo /* mbedTLS headers */ 47*7d37aa17SJuan Castillo #include <polarssl/asn1.h> 48*7d37aa17SJuan Castillo #include <polarssl/oid.h> 49*7d37aa17SJuan Castillo #include <polarssl/platform.h> 50*7d37aa17SJuan Castillo 51*7d37aa17SJuan Castillo /* Maximum OID string length ("a.b.c.d.e.f ...") */ 52*7d37aa17SJuan Castillo #define MAX_OID_STR_LEN 64 53*7d37aa17SJuan Castillo 54*7d37aa17SJuan Castillo #define LIB_NAME "mbedTLS X509v3" 55*7d37aa17SJuan Castillo 56*7d37aa17SJuan Castillo /* Temporary variables to speed up the authentication parameters search. These 57*7d37aa17SJuan Castillo * variables are assigned once during the integrity check and used any time an 58*7d37aa17SJuan Castillo * authentication parameter is requested, so we do not have to parse the image 59*7d37aa17SJuan Castillo * again */ 60*7d37aa17SJuan Castillo static asn1_buf tbs; 61*7d37aa17SJuan Castillo static asn1_buf v3_ext; 62*7d37aa17SJuan Castillo static asn1_buf pk; 63*7d37aa17SJuan Castillo static asn1_buf sig_alg; 64*7d37aa17SJuan Castillo static asn1_buf signature; 65*7d37aa17SJuan Castillo 66*7d37aa17SJuan Castillo /* 67*7d37aa17SJuan Castillo * Get X509v3 extension 68*7d37aa17SJuan Castillo * 69*7d37aa17SJuan Castillo * Global variable 'v3_ext' must point to the extensions region 70*7d37aa17SJuan Castillo * in the certificate. No need to check for errors since the image has passed 71*7d37aa17SJuan Castillo * the integrity check. 72*7d37aa17SJuan Castillo */ 73*7d37aa17SJuan Castillo static int get_ext(const char *oid, void **ext, unsigned int *ext_len) 74*7d37aa17SJuan Castillo { 75*7d37aa17SJuan Castillo int oid_len; 76*7d37aa17SJuan Castillo size_t len; 77*7d37aa17SJuan Castillo unsigned char *end_ext_data, *end_ext_octet; 78*7d37aa17SJuan Castillo unsigned char *p; 79*7d37aa17SJuan Castillo const unsigned char *end; 80*7d37aa17SJuan Castillo char oid_str[MAX_OID_STR_LEN]; 81*7d37aa17SJuan Castillo asn1_buf extn_oid; 82*7d37aa17SJuan Castillo int is_critical; 83*7d37aa17SJuan Castillo 84*7d37aa17SJuan Castillo assert(oid != NULL); 85*7d37aa17SJuan Castillo 86*7d37aa17SJuan Castillo p = v3_ext.p; 87*7d37aa17SJuan Castillo end = v3_ext.p + v3_ext.len; 88*7d37aa17SJuan Castillo 89*7d37aa17SJuan Castillo asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); 90*7d37aa17SJuan Castillo 91*7d37aa17SJuan Castillo while (p < end) { 92*7d37aa17SJuan Castillo memset(&extn_oid, 0x0, sizeof(extn_oid)); 93*7d37aa17SJuan Castillo is_critical = 0; /* DEFAULT FALSE */ 94*7d37aa17SJuan Castillo 95*7d37aa17SJuan Castillo asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); 96*7d37aa17SJuan Castillo end_ext_data = p + len; 97*7d37aa17SJuan Castillo 98*7d37aa17SJuan Castillo /* Get extension ID */ 99*7d37aa17SJuan Castillo extn_oid.tag = *p; 100*7d37aa17SJuan Castillo asn1_get_tag(&p, end, &extn_oid.len, ASN1_OID); 101*7d37aa17SJuan Castillo extn_oid.p = p; 102*7d37aa17SJuan Castillo p += extn_oid.len; 103*7d37aa17SJuan Castillo 104*7d37aa17SJuan Castillo /* Get optional critical */ 105*7d37aa17SJuan Castillo asn1_get_bool(&p, end_ext_data, &is_critical); 106*7d37aa17SJuan Castillo 107*7d37aa17SJuan Castillo /* Extension data */ 108*7d37aa17SJuan Castillo asn1_get_tag(&p, end_ext_data, &len, ASN1_OCTET_STRING); 109*7d37aa17SJuan Castillo end_ext_octet = p + len; 110*7d37aa17SJuan Castillo 111*7d37aa17SJuan Castillo /* Detect requested extension */ 112*7d37aa17SJuan Castillo oid_len = oid_get_numeric_string(oid_str, 113*7d37aa17SJuan Castillo MAX_OID_STR_LEN, &extn_oid); 114*7d37aa17SJuan Castillo if (oid_len == POLARSSL_ERR_OID_BUF_TOO_SMALL) { 115*7d37aa17SJuan Castillo return IMG_PARSER_ERR; 116*7d37aa17SJuan Castillo } 117*7d37aa17SJuan Castillo if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) { 118*7d37aa17SJuan Castillo *ext = (void *)p; 119*7d37aa17SJuan Castillo *ext_len = (unsigned int)len; 120*7d37aa17SJuan Castillo return IMG_PARSER_OK; 121*7d37aa17SJuan Castillo } 122*7d37aa17SJuan Castillo 123*7d37aa17SJuan Castillo /* Next */ 124*7d37aa17SJuan Castillo p = end_ext_octet; 125*7d37aa17SJuan Castillo } 126*7d37aa17SJuan Castillo 127*7d37aa17SJuan Castillo return IMG_PARSER_ERR_NOT_FOUND; 128*7d37aa17SJuan Castillo } 129*7d37aa17SJuan Castillo 130*7d37aa17SJuan Castillo 131*7d37aa17SJuan Castillo /* 132*7d37aa17SJuan Castillo * Check the integrity of the certificate ASN.1 structure. 133*7d37aa17SJuan Castillo * Extract the relevant data that will be used later during authentication. 134*7d37aa17SJuan Castillo */ 135*7d37aa17SJuan Castillo static int cert_parse(void *img, unsigned int img_len) 136*7d37aa17SJuan Castillo { 137*7d37aa17SJuan Castillo int ret, is_critical; 138*7d37aa17SJuan Castillo size_t len; 139*7d37aa17SJuan Castillo unsigned char *p, *end, *crt_end; 140*7d37aa17SJuan Castillo asn1_buf sig_alg1, sig_alg2; 141*7d37aa17SJuan Castillo 142*7d37aa17SJuan Castillo p = (unsigned char *)img; 143*7d37aa17SJuan Castillo len = img_len; 144*7d37aa17SJuan Castillo end = p + len; 145*7d37aa17SJuan Castillo 146*7d37aa17SJuan Castillo /* 147*7d37aa17SJuan Castillo * Certificate ::= SEQUENCE { 148*7d37aa17SJuan Castillo * tbsCertificate TBSCertificate, 149*7d37aa17SJuan Castillo * signatureAlgorithm AlgorithmIdentifier, 150*7d37aa17SJuan Castillo * signatureValue BIT STRING } 151*7d37aa17SJuan Castillo */ 152*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); 153*7d37aa17SJuan Castillo if (ret != 0) { 154*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 155*7d37aa17SJuan Castillo } 156*7d37aa17SJuan Castillo 157*7d37aa17SJuan Castillo if (len > (size_t)(end - p)) { 158*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 159*7d37aa17SJuan Castillo } 160*7d37aa17SJuan Castillo crt_end = p + len; 161*7d37aa17SJuan Castillo 162*7d37aa17SJuan Castillo /* 163*7d37aa17SJuan Castillo * TBSCertificate ::= SEQUENCE { 164*7d37aa17SJuan Castillo */ 165*7d37aa17SJuan Castillo tbs.p = p; 166*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); 167*7d37aa17SJuan Castillo if (ret != 0) { 168*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 169*7d37aa17SJuan Castillo } 170*7d37aa17SJuan Castillo end = p + len; 171*7d37aa17SJuan Castillo tbs.len = end - tbs.p; 172*7d37aa17SJuan Castillo 173*7d37aa17SJuan Castillo /* 174*7d37aa17SJuan Castillo * Version ::= INTEGER { v1(0), v2(1), v3(2) } 175*7d37aa17SJuan Castillo */ 176*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, 177*7d37aa17SJuan Castillo ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0); 178*7d37aa17SJuan Castillo if (ret != 0) { 179*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 180*7d37aa17SJuan Castillo } 181*7d37aa17SJuan Castillo p += len; 182*7d37aa17SJuan Castillo 183*7d37aa17SJuan Castillo /* 184*7d37aa17SJuan Castillo * CertificateSerialNumber ::= INTEGER 185*7d37aa17SJuan Castillo */ 186*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, ASN1_INTEGER); 187*7d37aa17SJuan Castillo if (ret != 0) { 188*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 189*7d37aa17SJuan Castillo } 190*7d37aa17SJuan Castillo p += len; 191*7d37aa17SJuan Castillo 192*7d37aa17SJuan Castillo /* 193*7d37aa17SJuan Castillo * signature AlgorithmIdentifier 194*7d37aa17SJuan Castillo */ 195*7d37aa17SJuan Castillo sig_alg1.p = p; 196*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); 197*7d37aa17SJuan Castillo if (ret != 0) { 198*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 199*7d37aa17SJuan Castillo } 200*7d37aa17SJuan Castillo if ((end - p) < 1) { 201*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 202*7d37aa17SJuan Castillo } 203*7d37aa17SJuan Castillo sig_alg1.len = (p + len) - sig_alg1.p; 204*7d37aa17SJuan Castillo p += len; 205*7d37aa17SJuan Castillo 206*7d37aa17SJuan Castillo /* 207*7d37aa17SJuan Castillo * issuer Name 208*7d37aa17SJuan Castillo */ 209*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); 210*7d37aa17SJuan Castillo if (ret != 0) { 211*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 212*7d37aa17SJuan Castillo } 213*7d37aa17SJuan Castillo p += len; 214*7d37aa17SJuan Castillo 215*7d37aa17SJuan Castillo /* 216*7d37aa17SJuan Castillo * Validity ::= SEQUENCE { 217*7d37aa17SJuan Castillo * notBefore Time, 218*7d37aa17SJuan Castillo * notAfter Time } 219*7d37aa17SJuan Castillo * 220*7d37aa17SJuan Castillo */ 221*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); 222*7d37aa17SJuan Castillo if (ret != 0) { 223*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 224*7d37aa17SJuan Castillo } 225*7d37aa17SJuan Castillo p += len; 226*7d37aa17SJuan Castillo 227*7d37aa17SJuan Castillo /* 228*7d37aa17SJuan Castillo * subject Name 229*7d37aa17SJuan Castillo */ 230*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); 231*7d37aa17SJuan Castillo if (ret != 0) { 232*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 233*7d37aa17SJuan Castillo } 234*7d37aa17SJuan Castillo p += len; 235*7d37aa17SJuan Castillo 236*7d37aa17SJuan Castillo /* 237*7d37aa17SJuan Castillo * SubjectPublicKeyInfo 238*7d37aa17SJuan Castillo */ 239*7d37aa17SJuan Castillo pk.p = p; 240*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); 241*7d37aa17SJuan Castillo if (ret != 0) { 242*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 243*7d37aa17SJuan Castillo } 244*7d37aa17SJuan Castillo pk.len = (p + len) - pk.p; 245*7d37aa17SJuan Castillo p += len; 246*7d37aa17SJuan Castillo 247*7d37aa17SJuan Castillo /* 248*7d37aa17SJuan Castillo * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, 249*7d37aa17SJuan Castillo */ 250*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, 251*7d37aa17SJuan Castillo ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1); 252*7d37aa17SJuan Castillo if (ret != 0) { 253*7d37aa17SJuan Castillo if (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG) { 254*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 255*7d37aa17SJuan Castillo } 256*7d37aa17SJuan Castillo } else { 257*7d37aa17SJuan Castillo p += len; 258*7d37aa17SJuan Castillo } 259*7d37aa17SJuan Castillo 260*7d37aa17SJuan Castillo /* 261*7d37aa17SJuan Castillo * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, 262*7d37aa17SJuan Castillo */ 263*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, 264*7d37aa17SJuan Castillo ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2); 265*7d37aa17SJuan Castillo if (ret != 0) { 266*7d37aa17SJuan Castillo if (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG) { 267*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 268*7d37aa17SJuan Castillo } 269*7d37aa17SJuan Castillo } else { 270*7d37aa17SJuan Castillo p += len; 271*7d37aa17SJuan Castillo } 272*7d37aa17SJuan Castillo 273*7d37aa17SJuan Castillo /* 274*7d37aa17SJuan Castillo * extensions [3] EXPLICIT Extensions OPTIONAL 275*7d37aa17SJuan Castillo */ 276*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, 277*7d37aa17SJuan Castillo ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3); 278*7d37aa17SJuan Castillo if (ret != 0) { 279*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 280*7d37aa17SJuan Castillo } 281*7d37aa17SJuan Castillo 282*7d37aa17SJuan Castillo /* 283*7d37aa17SJuan Castillo * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 284*7d37aa17SJuan Castillo */ 285*7d37aa17SJuan Castillo v3_ext.p = p; 286*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); 287*7d37aa17SJuan Castillo if (ret != 0) { 288*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 289*7d37aa17SJuan Castillo } 290*7d37aa17SJuan Castillo v3_ext.len = (p + len) - v3_ext.p; 291*7d37aa17SJuan Castillo 292*7d37aa17SJuan Castillo /* 293*7d37aa17SJuan Castillo * Check extensions integrity 294*7d37aa17SJuan Castillo */ 295*7d37aa17SJuan Castillo while (p < end) { 296*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, 297*7d37aa17SJuan Castillo ASN1_CONSTRUCTED | ASN1_SEQUENCE); 298*7d37aa17SJuan Castillo if (ret != 0) { 299*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 300*7d37aa17SJuan Castillo } 301*7d37aa17SJuan Castillo 302*7d37aa17SJuan Castillo /* Get extension ID */ 303*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, ASN1_OID); 304*7d37aa17SJuan Castillo if (ret != 0) { 305*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 306*7d37aa17SJuan Castillo } 307*7d37aa17SJuan Castillo p += len; 308*7d37aa17SJuan Castillo 309*7d37aa17SJuan Castillo /* Get optional critical */ 310*7d37aa17SJuan Castillo ret = asn1_get_bool(&p, end, &is_critical); 311*7d37aa17SJuan Castillo if ((ret != 0) && (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG)) { 312*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 313*7d37aa17SJuan Castillo } 314*7d37aa17SJuan Castillo 315*7d37aa17SJuan Castillo /* Data should be octet string type */ 316*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, ASN1_OCTET_STRING); 317*7d37aa17SJuan Castillo if (ret != 0) { 318*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 319*7d37aa17SJuan Castillo } 320*7d37aa17SJuan Castillo p += len; 321*7d37aa17SJuan Castillo } 322*7d37aa17SJuan Castillo 323*7d37aa17SJuan Castillo if (p != end) { 324*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 325*7d37aa17SJuan Castillo } 326*7d37aa17SJuan Castillo 327*7d37aa17SJuan Castillo end = crt_end; 328*7d37aa17SJuan Castillo 329*7d37aa17SJuan Castillo /* 330*7d37aa17SJuan Castillo * } 331*7d37aa17SJuan Castillo * -- end of TBSCertificate 332*7d37aa17SJuan Castillo * 333*7d37aa17SJuan Castillo * signatureAlgorithm AlgorithmIdentifier 334*7d37aa17SJuan Castillo */ 335*7d37aa17SJuan Castillo sig_alg2.p = p; 336*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); 337*7d37aa17SJuan Castillo if (ret != 0) { 338*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 339*7d37aa17SJuan Castillo } 340*7d37aa17SJuan Castillo if ((end - p) < 1) { 341*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 342*7d37aa17SJuan Castillo } 343*7d37aa17SJuan Castillo sig_alg2.len = (p + len) - sig_alg2.p; 344*7d37aa17SJuan Castillo p += len; 345*7d37aa17SJuan Castillo 346*7d37aa17SJuan Castillo /* Compare both signature algorithms */ 347*7d37aa17SJuan Castillo if (sig_alg1.len != sig_alg2.len) { 348*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 349*7d37aa17SJuan Castillo } 350*7d37aa17SJuan Castillo if (0 != memcmp(sig_alg1.p, sig_alg2.p, sig_alg1.len)) { 351*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 352*7d37aa17SJuan Castillo } 353*7d37aa17SJuan Castillo memcpy(&sig_alg, &sig_alg1, sizeof(sig_alg)); 354*7d37aa17SJuan Castillo 355*7d37aa17SJuan Castillo /* 356*7d37aa17SJuan Castillo * signatureValue BIT STRING 357*7d37aa17SJuan Castillo */ 358*7d37aa17SJuan Castillo signature.p = p; 359*7d37aa17SJuan Castillo ret = asn1_get_tag(&p, end, &len, ASN1_BIT_STRING); 360*7d37aa17SJuan Castillo if (ret != 0) { 361*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 362*7d37aa17SJuan Castillo } 363*7d37aa17SJuan Castillo signature.len = (p + len) - signature.p; 364*7d37aa17SJuan Castillo p += len; 365*7d37aa17SJuan Castillo 366*7d37aa17SJuan Castillo /* Check certificate length */ 367*7d37aa17SJuan Castillo if (p != end) { 368*7d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 369*7d37aa17SJuan Castillo } 370*7d37aa17SJuan Castillo 371*7d37aa17SJuan Castillo return IMG_PARSER_OK; 372*7d37aa17SJuan Castillo } 373*7d37aa17SJuan Castillo 374*7d37aa17SJuan Castillo 375*7d37aa17SJuan Castillo /* Exported functions */ 376*7d37aa17SJuan Castillo 377*7d37aa17SJuan Castillo static void init(void) 378*7d37aa17SJuan Castillo { 379*7d37aa17SJuan Castillo mbedtls_init(); 380*7d37aa17SJuan Castillo } 381*7d37aa17SJuan Castillo 382*7d37aa17SJuan Castillo static int check_integrity(void *img, unsigned int img_len) 383*7d37aa17SJuan Castillo { 384*7d37aa17SJuan Castillo return cert_parse(img, img_len); 385*7d37aa17SJuan Castillo } 386*7d37aa17SJuan Castillo 387*7d37aa17SJuan Castillo /* 388*7d37aa17SJuan Castillo * Extract an authentication parameter from an X509v3 certificate 389*7d37aa17SJuan Castillo */ 390*7d37aa17SJuan Castillo static int get_auth_param(const auth_param_type_desc_t *type_desc, 391*7d37aa17SJuan Castillo void *img, unsigned int img_len, 392*7d37aa17SJuan Castillo void **param, unsigned int *param_len) 393*7d37aa17SJuan Castillo { 394*7d37aa17SJuan Castillo int rc = IMG_PARSER_OK; 395*7d37aa17SJuan Castillo 396*7d37aa17SJuan Castillo /* We do not use img because the check_integrity function has already 397*7d37aa17SJuan Castillo * extracted the relevant data (v3_ext, pk, sig_alg, etc) */ 398*7d37aa17SJuan Castillo 399*7d37aa17SJuan Castillo switch (type_desc->type) { 400*7d37aa17SJuan Castillo case AUTH_PARAM_RAW_DATA: 401*7d37aa17SJuan Castillo /* Data to be signed */ 402*7d37aa17SJuan Castillo *param = (void *)tbs.p; 403*7d37aa17SJuan Castillo *param_len = (unsigned int)tbs.len; 404*7d37aa17SJuan Castillo break; 405*7d37aa17SJuan Castillo case AUTH_PARAM_HASH: 406*7d37aa17SJuan Castillo /* All these parameters are included as X509v3 extensions */ 407*7d37aa17SJuan Castillo rc = get_ext(type_desc->cookie, param, param_len); 408*7d37aa17SJuan Castillo break; 409*7d37aa17SJuan Castillo case AUTH_PARAM_PUB_KEY: 410*7d37aa17SJuan Castillo if (type_desc->cookie != 0) { 411*7d37aa17SJuan Castillo /* Get public key from extension */ 412*7d37aa17SJuan Castillo rc = get_ext(type_desc->cookie, param, param_len); 413*7d37aa17SJuan Castillo } else { 414*7d37aa17SJuan Castillo /* Get the subject public key */ 415*7d37aa17SJuan Castillo *param = (void *)pk.p; 416*7d37aa17SJuan Castillo *param_len = (unsigned int)pk.len; 417*7d37aa17SJuan Castillo } 418*7d37aa17SJuan Castillo break; 419*7d37aa17SJuan Castillo case AUTH_PARAM_SIG_ALG: 420*7d37aa17SJuan Castillo /* Get the certificate signature algorithm */ 421*7d37aa17SJuan Castillo *param = (void *)sig_alg.p; 422*7d37aa17SJuan Castillo *param_len = (unsigned int)sig_alg.len; 423*7d37aa17SJuan Castillo break; 424*7d37aa17SJuan Castillo case AUTH_PARAM_SIG: 425*7d37aa17SJuan Castillo /* Get the certificate signature */ 426*7d37aa17SJuan Castillo *param = (void *)signature.p; 427*7d37aa17SJuan Castillo *param_len = (unsigned int)signature.len; 428*7d37aa17SJuan Castillo break; 429*7d37aa17SJuan Castillo default: 430*7d37aa17SJuan Castillo rc = IMG_PARSER_ERR_NOT_FOUND; 431*7d37aa17SJuan Castillo break; 432*7d37aa17SJuan Castillo } 433*7d37aa17SJuan Castillo 434*7d37aa17SJuan Castillo return rc; 435*7d37aa17SJuan Castillo } 436*7d37aa17SJuan Castillo 437*7d37aa17SJuan Castillo REGISTER_IMG_PARSER_LIB(IMG_CERT, LIB_NAME, init, \ 438*7d37aa17SJuan Castillo check_integrity, get_auth_param); 439