17d37aa17SJuan Castillo /* 27d37aa17SJuan Castillo * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 37d37aa17SJuan Castillo * 47d37aa17SJuan Castillo * Redistribution and use in source and binary forms, with or without 57d37aa17SJuan Castillo * modification, are permitted provided that the following conditions are met: 67d37aa17SJuan Castillo * 77d37aa17SJuan Castillo * Redistributions of source code must retain the above copyright notice, this 87d37aa17SJuan Castillo * list of conditions and the following disclaimer. 97d37aa17SJuan Castillo * 107d37aa17SJuan Castillo * Redistributions in binary form must reproduce the above copyright notice, 117d37aa17SJuan Castillo * this list of conditions and the following disclaimer in the documentation 127d37aa17SJuan Castillo * and/or other materials provided with the distribution. 137d37aa17SJuan Castillo * 147d37aa17SJuan Castillo * Neither the name of ARM nor the names of its contributors may be used 157d37aa17SJuan Castillo * to endorse or promote products derived from this software without specific 167d37aa17SJuan Castillo * prior written permission. 177d37aa17SJuan Castillo * 187d37aa17SJuan Castillo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 197d37aa17SJuan Castillo * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 207d37aa17SJuan Castillo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 217d37aa17SJuan Castillo * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 227d37aa17SJuan Castillo * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 237d37aa17SJuan Castillo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 247d37aa17SJuan Castillo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 257d37aa17SJuan Castillo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 267d37aa17SJuan Castillo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 277d37aa17SJuan Castillo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 287d37aa17SJuan Castillo * POSSIBILITY OF SUCH DAMAGE. 297d37aa17SJuan Castillo */ 307d37aa17SJuan Castillo 317d37aa17SJuan Castillo /* 32649dbf6fSJuan Castillo * X509 parser based on mbed TLS 337d37aa17SJuan Castillo * 347d37aa17SJuan Castillo * This module implements functions to check the integrity of a X509v3 357d37aa17SJuan Castillo * certificate ASN.1 structure and extract authentication parameters from the 367d37aa17SJuan Castillo * extensions field, such as an image hash or a public key. 377d37aa17SJuan Castillo */ 387d37aa17SJuan Castillo 397d37aa17SJuan Castillo #include <assert.h> 407d37aa17SJuan Castillo #include <img_parser_mod.h> 417d37aa17SJuan Castillo #include <mbedtls_common.h> 427d37aa17SJuan Castillo #include <stddef.h> 437d37aa17SJuan Castillo #include <stdint.h> 447d37aa17SJuan Castillo #include <string.h> 457d37aa17SJuan Castillo 467d37aa17SJuan Castillo /* mbed TLS headers */ 47649dbf6fSJuan Castillo #include <mbedtls/asn1.h> 48649dbf6fSJuan Castillo #include <mbedtls/oid.h> 49649dbf6fSJuan Castillo #include <mbedtls/platform.h> 507d37aa17SJuan Castillo 517d37aa17SJuan Castillo /* Maximum OID string length ("a.b.c.d.e.f ...") */ 527d37aa17SJuan Castillo #define MAX_OID_STR_LEN 64 537d37aa17SJuan Castillo 547d37aa17SJuan Castillo #define LIB_NAME "mbed TLS X509v3" 557d37aa17SJuan Castillo 567d37aa17SJuan Castillo /* Temporary variables to speed up the authentication parameters search. These 577d37aa17SJuan Castillo * variables are assigned once during the integrity check and used any time an 587d37aa17SJuan Castillo * authentication parameter is requested, so we do not have to parse the image 597d37aa17SJuan Castillo * again */ 60649dbf6fSJuan Castillo static mbedtls_asn1_buf tbs; 61649dbf6fSJuan Castillo static mbedtls_asn1_buf v3_ext; 62649dbf6fSJuan Castillo static mbedtls_asn1_buf pk; 63649dbf6fSJuan Castillo static mbedtls_asn1_buf sig_alg; 64649dbf6fSJuan Castillo static mbedtls_asn1_buf signature; 657d37aa17SJuan Castillo 667d37aa17SJuan Castillo /* 677d37aa17SJuan Castillo * Get X509v3 extension 687d37aa17SJuan Castillo * 697d37aa17SJuan Castillo * Global variable 'v3_ext' must point to the extensions region 707d37aa17SJuan Castillo * in the certificate. No need to check for errors since the image has passed 717d37aa17SJuan Castillo * the integrity check. 727d37aa17SJuan Castillo */ 737d37aa17SJuan Castillo static int get_ext(const char *oid, void **ext, unsigned int *ext_len) 747d37aa17SJuan Castillo { 757d37aa17SJuan Castillo int oid_len; 767d37aa17SJuan Castillo size_t len; 777d37aa17SJuan Castillo unsigned char *end_ext_data, *end_ext_octet; 787d37aa17SJuan Castillo unsigned char *p; 797d37aa17SJuan Castillo const unsigned char *end; 807d37aa17SJuan Castillo char oid_str[MAX_OID_STR_LEN]; 81649dbf6fSJuan Castillo mbedtls_asn1_buf extn_oid; 827d37aa17SJuan Castillo int is_critical; 837d37aa17SJuan Castillo 847d37aa17SJuan Castillo assert(oid != NULL); 857d37aa17SJuan Castillo 867d37aa17SJuan Castillo p = v3_ext.p; 877d37aa17SJuan Castillo end = v3_ext.p + v3_ext.len; 887d37aa17SJuan Castillo 89649dbf6fSJuan Castillo mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 90649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 917d37aa17SJuan Castillo 927d37aa17SJuan Castillo while (p < end) { 937d37aa17SJuan Castillo memset(&extn_oid, 0x0, sizeof(extn_oid)); 947d37aa17SJuan Castillo is_critical = 0; /* DEFAULT FALSE */ 957d37aa17SJuan Castillo 96649dbf6fSJuan Castillo mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 97649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 987d37aa17SJuan Castillo end_ext_data = p + len; 997d37aa17SJuan Castillo 1007d37aa17SJuan Castillo /* Get extension ID */ 1017d37aa17SJuan Castillo extn_oid.tag = *p; 102649dbf6fSJuan Castillo mbedtls_asn1_get_tag(&p, end, &extn_oid.len, MBEDTLS_ASN1_OID); 1037d37aa17SJuan Castillo extn_oid.p = p; 1047d37aa17SJuan Castillo p += extn_oid.len; 1057d37aa17SJuan Castillo 1067d37aa17SJuan Castillo /* Get optional critical */ 107649dbf6fSJuan Castillo mbedtls_asn1_get_bool(&p, end_ext_data, &is_critical); 1087d37aa17SJuan Castillo 1097d37aa17SJuan Castillo /* Extension data */ 110649dbf6fSJuan Castillo mbedtls_asn1_get_tag(&p, end_ext_data, &len, 111649dbf6fSJuan Castillo MBEDTLS_ASN1_OCTET_STRING); 1127d37aa17SJuan Castillo end_ext_octet = p + len; 1137d37aa17SJuan Castillo 1147d37aa17SJuan Castillo /* Detect requested extension */ 115649dbf6fSJuan Castillo oid_len = mbedtls_oid_get_numeric_string(oid_str, 116649dbf6fSJuan Castillo MAX_OID_STR_LEN, 117649dbf6fSJuan Castillo &extn_oid); 118649dbf6fSJuan Castillo if (oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) { 1197d37aa17SJuan Castillo return IMG_PARSER_ERR; 1207d37aa17SJuan Castillo } 1217d37aa17SJuan Castillo if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) { 1227d37aa17SJuan Castillo *ext = (void *)p; 1237d37aa17SJuan Castillo *ext_len = (unsigned int)len; 1247d37aa17SJuan Castillo return IMG_PARSER_OK; 1257d37aa17SJuan Castillo } 1267d37aa17SJuan Castillo 1277d37aa17SJuan Castillo /* Next */ 1287d37aa17SJuan Castillo p = end_ext_octet; 1297d37aa17SJuan Castillo } 1307d37aa17SJuan Castillo 1317d37aa17SJuan Castillo return IMG_PARSER_ERR_NOT_FOUND; 1327d37aa17SJuan Castillo } 1337d37aa17SJuan Castillo 1347d37aa17SJuan Castillo 1357d37aa17SJuan Castillo /* 1367d37aa17SJuan Castillo * Check the integrity of the certificate ASN.1 structure. 1377d37aa17SJuan Castillo * Extract the relevant data that will be used later during authentication. 1387d37aa17SJuan Castillo */ 1397d37aa17SJuan Castillo static int cert_parse(void *img, unsigned int img_len) 1407d37aa17SJuan Castillo { 1417d37aa17SJuan Castillo int ret, is_critical; 1427d37aa17SJuan Castillo size_t len; 1437d37aa17SJuan Castillo unsigned char *p, *end, *crt_end; 144649dbf6fSJuan Castillo mbedtls_asn1_buf sig_alg1, sig_alg2; 1457d37aa17SJuan Castillo 1467d37aa17SJuan Castillo p = (unsigned char *)img; 1477d37aa17SJuan Castillo len = img_len; 1487d37aa17SJuan Castillo end = p + len; 1497d37aa17SJuan Castillo 1507d37aa17SJuan Castillo /* 1517d37aa17SJuan Castillo * Certificate ::= SEQUENCE { 1527d37aa17SJuan Castillo * tbsCertificate TBSCertificate, 1537d37aa17SJuan Castillo * signatureAlgorithm AlgorithmIdentifier, 1547d37aa17SJuan Castillo * signatureValue BIT STRING } 1557d37aa17SJuan Castillo */ 156649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 157649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 1587d37aa17SJuan Castillo if (ret != 0) { 1597d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 1607d37aa17SJuan Castillo } 1617d37aa17SJuan Castillo 1627d37aa17SJuan Castillo if (len > (size_t)(end - p)) { 1637d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 1647d37aa17SJuan Castillo } 1657d37aa17SJuan Castillo crt_end = p + len; 1667d37aa17SJuan Castillo 1677d37aa17SJuan Castillo /* 1687d37aa17SJuan Castillo * TBSCertificate ::= SEQUENCE { 1697d37aa17SJuan Castillo */ 1707d37aa17SJuan Castillo tbs.p = p; 171649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 172649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 1737d37aa17SJuan Castillo if (ret != 0) { 1747d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 1757d37aa17SJuan Castillo } 1767d37aa17SJuan Castillo end = p + len; 1777d37aa17SJuan Castillo tbs.len = end - tbs.p; 1787d37aa17SJuan Castillo 1797d37aa17SJuan Castillo /* 1807d37aa17SJuan Castillo * Version ::= INTEGER { v1(0), v2(1), v3(2) } 1817d37aa17SJuan Castillo */ 182649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, 183649dbf6fSJuan Castillo MBEDTLS_ASN1_CONTEXT_SPECIFIC | 184649dbf6fSJuan Castillo MBEDTLS_ASN1_CONSTRUCTED | 0); 1857d37aa17SJuan Castillo if (ret != 0) { 1867d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 1877d37aa17SJuan Castillo } 1887d37aa17SJuan Castillo p += len; 1897d37aa17SJuan Castillo 1907d37aa17SJuan Castillo /* 1917d37aa17SJuan Castillo * CertificateSerialNumber ::= INTEGER 1927d37aa17SJuan Castillo */ 193649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER); 1947d37aa17SJuan Castillo if (ret != 0) { 1957d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 1967d37aa17SJuan Castillo } 1977d37aa17SJuan Castillo p += len; 1987d37aa17SJuan Castillo 1997d37aa17SJuan Castillo /* 2007d37aa17SJuan Castillo * signature AlgorithmIdentifier 2017d37aa17SJuan Castillo */ 2027d37aa17SJuan Castillo sig_alg1.p = p; 203649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 204649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 2057d37aa17SJuan Castillo if (ret != 0) { 2067d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 2077d37aa17SJuan Castillo } 2087d37aa17SJuan Castillo if ((end - p) < 1) { 2097d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 2107d37aa17SJuan Castillo } 2117d37aa17SJuan Castillo sig_alg1.len = (p + len) - sig_alg1.p; 2127d37aa17SJuan Castillo p += len; 2137d37aa17SJuan Castillo 2147d37aa17SJuan Castillo /* 2157d37aa17SJuan Castillo * issuer Name 2167d37aa17SJuan Castillo */ 217649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 218649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 2197d37aa17SJuan Castillo if (ret != 0) { 2207d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 2217d37aa17SJuan Castillo } 2227d37aa17SJuan Castillo p += len; 2237d37aa17SJuan Castillo 2247d37aa17SJuan Castillo /* 2257d37aa17SJuan Castillo * Validity ::= SEQUENCE { 2267d37aa17SJuan Castillo * notBefore Time, 2277d37aa17SJuan Castillo * notAfter Time } 2287d37aa17SJuan Castillo * 2297d37aa17SJuan Castillo */ 230649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 231649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 2327d37aa17SJuan Castillo if (ret != 0) { 2337d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 2347d37aa17SJuan Castillo } 2357d37aa17SJuan Castillo p += len; 2367d37aa17SJuan Castillo 2377d37aa17SJuan Castillo /* 2387d37aa17SJuan Castillo * subject Name 2397d37aa17SJuan Castillo */ 240649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 241649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 2427d37aa17SJuan Castillo if (ret != 0) { 2437d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 2447d37aa17SJuan Castillo } 2457d37aa17SJuan Castillo p += len; 2467d37aa17SJuan Castillo 2477d37aa17SJuan Castillo /* 2487d37aa17SJuan Castillo * SubjectPublicKeyInfo 2497d37aa17SJuan Castillo */ 2507d37aa17SJuan Castillo pk.p = p; 251649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 252649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 2537d37aa17SJuan Castillo if (ret != 0) { 2547d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 2557d37aa17SJuan Castillo } 2567d37aa17SJuan Castillo pk.len = (p + len) - pk.p; 2577d37aa17SJuan Castillo p += len; 2587d37aa17SJuan Castillo 2597d37aa17SJuan Castillo /* 2607d37aa17SJuan Castillo * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, 2617d37aa17SJuan Castillo */ 262649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, 263649dbf6fSJuan Castillo MBEDTLS_ASN1_CONTEXT_SPECIFIC | 264649dbf6fSJuan Castillo MBEDTLS_ASN1_CONSTRUCTED | 1); 2657d37aa17SJuan Castillo if (ret != 0) { 266649dbf6fSJuan Castillo if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 2677d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 2687d37aa17SJuan Castillo } 2697d37aa17SJuan Castillo } else { 2707d37aa17SJuan Castillo p += len; 2717d37aa17SJuan Castillo } 2727d37aa17SJuan Castillo 2737d37aa17SJuan Castillo /* 2747d37aa17SJuan Castillo * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, 2757d37aa17SJuan Castillo */ 276649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, 277649dbf6fSJuan Castillo MBEDTLS_ASN1_CONTEXT_SPECIFIC | 278649dbf6fSJuan Castillo MBEDTLS_ASN1_CONSTRUCTED | 2); 2797d37aa17SJuan Castillo if (ret != 0) { 280649dbf6fSJuan Castillo if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 2817d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 2827d37aa17SJuan Castillo } 2837d37aa17SJuan Castillo } else { 2847d37aa17SJuan Castillo p += len; 2857d37aa17SJuan Castillo } 2867d37aa17SJuan Castillo 2877d37aa17SJuan Castillo /* 2887d37aa17SJuan Castillo * extensions [3] EXPLICIT Extensions OPTIONAL 2897d37aa17SJuan Castillo */ 290649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, 291649dbf6fSJuan Castillo MBEDTLS_ASN1_CONTEXT_SPECIFIC | 292649dbf6fSJuan Castillo MBEDTLS_ASN1_CONSTRUCTED | 3); 2937d37aa17SJuan Castillo if (ret != 0) { 2947d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 2957d37aa17SJuan Castillo } 2967d37aa17SJuan Castillo 2977d37aa17SJuan Castillo /* 2987d37aa17SJuan Castillo * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 2997d37aa17SJuan Castillo */ 3007d37aa17SJuan Castillo v3_ext.p = p; 301649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 302649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 3037d37aa17SJuan Castillo if (ret != 0) { 3047d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 3057d37aa17SJuan Castillo } 3067d37aa17SJuan Castillo v3_ext.len = (p + len) - v3_ext.p; 3077d37aa17SJuan Castillo 3087d37aa17SJuan Castillo /* 3097d37aa17SJuan Castillo * Check extensions integrity 3107d37aa17SJuan Castillo */ 3117d37aa17SJuan Castillo while (p < end) { 312649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, 313649dbf6fSJuan Castillo MBEDTLS_ASN1_CONSTRUCTED | 314649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 3157d37aa17SJuan Castillo if (ret != 0) { 3167d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 3177d37aa17SJuan Castillo } 3187d37aa17SJuan Castillo 3197d37aa17SJuan Castillo /* Get extension ID */ 320649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID); 3217d37aa17SJuan Castillo if (ret != 0) { 3227d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 3237d37aa17SJuan Castillo } 3247d37aa17SJuan Castillo p += len; 3257d37aa17SJuan Castillo 3267d37aa17SJuan Castillo /* Get optional critical */ 327649dbf6fSJuan Castillo ret = mbedtls_asn1_get_bool(&p, end, &is_critical); 328649dbf6fSJuan Castillo if ((ret != 0) && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { 3297d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 3307d37aa17SJuan Castillo } 3317d37aa17SJuan Castillo 3327d37aa17SJuan Castillo /* Data should be octet string type */ 333649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, 334649dbf6fSJuan Castillo MBEDTLS_ASN1_OCTET_STRING); 3357d37aa17SJuan Castillo if (ret != 0) { 3367d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 3377d37aa17SJuan Castillo } 3387d37aa17SJuan Castillo p += len; 3397d37aa17SJuan Castillo } 3407d37aa17SJuan Castillo 3417d37aa17SJuan Castillo if (p != end) { 3427d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 3437d37aa17SJuan Castillo } 3447d37aa17SJuan Castillo 3457d37aa17SJuan Castillo end = crt_end; 3467d37aa17SJuan Castillo 3477d37aa17SJuan Castillo /* 3487d37aa17SJuan Castillo * } 3497d37aa17SJuan Castillo * -- end of TBSCertificate 3507d37aa17SJuan Castillo * 3517d37aa17SJuan Castillo * signatureAlgorithm AlgorithmIdentifier 3527d37aa17SJuan Castillo */ 3537d37aa17SJuan Castillo sig_alg2.p = p; 354649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 355649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 3567d37aa17SJuan Castillo if (ret != 0) { 3577d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 3587d37aa17SJuan Castillo } 3597d37aa17SJuan Castillo if ((end - p) < 1) { 3607d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 3617d37aa17SJuan Castillo } 3627d37aa17SJuan Castillo sig_alg2.len = (p + len) - sig_alg2.p; 3637d37aa17SJuan Castillo p += len; 3647d37aa17SJuan Castillo 3657d37aa17SJuan Castillo /* Compare both signature algorithms */ 3667d37aa17SJuan Castillo if (sig_alg1.len != sig_alg2.len) { 3677d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 3687d37aa17SJuan Castillo } 3697d37aa17SJuan Castillo if (0 != memcmp(sig_alg1.p, sig_alg2.p, sig_alg1.len)) { 3707d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 3717d37aa17SJuan Castillo } 3727d37aa17SJuan Castillo memcpy(&sig_alg, &sig_alg1, sizeof(sig_alg)); 3737d37aa17SJuan Castillo 3747d37aa17SJuan Castillo /* 3757d37aa17SJuan Castillo * signatureValue BIT STRING 3767d37aa17SJuan Castillo */ 3777d37aa17SJuan Castillo signature.p = p; 378649dbf6fSJuan Castillo ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_BIT_STRING); 3797d37aa17SJuan Castillo if (ret != 0) { 3807d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 3817d37aa17SJuan Castillo } 3827d37aa17SJuan Castillo signature.len = (p + len) - signature.p; 3837d37aa17SJuan Castillo p += len; 3847d37aa17SJuan Castillo 3857d37aa17SJuan Castillo /* Check certificate length */ 3867d37aa17SJuan Castillo if (p != end) { 3877d37aa17SJuan Castillo return IMG_PARSER_ERR_FORMAT; 3887d37aa17SJuan Castillo } 3897d37aa17SJuan Castillo 3907d37aa17SJuan Castillo return IMG_PARSER_OK; 3917d37aa17SJuan Castillo } 3927d37aa17SJuan Castillo 3937d37aa17SJuan Castillo 3947d37aa17SJuan Castillo /* Exported functions */ 3957d37aa17SJuan Castillo 3967d37aa17SJuan Castillo static void init(void) 3977d37aa17SJuan Castillo { 3987d37aa17SJuan Castillo mbedtls_init(); 3997d37aa17SJuan Castillo } 4007d37aa17SJuan Castillo 4017d37aa17SJuan Castillo static int check_integrity(void *img, unsigned int img_len) 4027d37aa17SJuan Castillo { 4037d37aa17SJuan Castillo return cert_parse(img, img_len); 4047d37aa17SJuan Castillo } 4057d37aa17SJuan Castillo 4067d37aa17SJuan Castillo /* 4077d37aa17SJuan Castillo * Extract an authentication parameter from an X509v3 certificate 408*48279d52SJuan Castillo * 409*48279d52SJuan Castillo * This function returns a pointer to the extracted data and its length. 410*48279d52SJuan Castillo * Depending on the type of parameter, a pointer to the data stored in the 411*48279d52SJuan Castillo * certificate may be returned (i.e. an octet string containing a hash). Other 412*48279d52SJuan Castillo * data may need to be copied and formatted (i.e. integers). In the later case, 413*48279d52SJuan Castillo * a buffer of the correct type needs to be statically allocated, filled and 414*48279d52SJuan Castillo * returned. 4157d37aa17SJuan Castillo */ 4167d37aa17SJuan Castillo static int get_auth_param(const auth_param_type_desc_t *type_desc, 4177d37aa17SJuan Castillo void *img, unsigned int img_len, 4187d37aa17SJuan Castillo void **param, unsigned int *param_len) 4197d37aa17SJuan Castillo { 4207d37aa17SJuan Castillo int rc = IMG_PARSER_OK; 4217d37aa17SJuan Castillo 4227d37aa17SJuan Castillo /* We do not use img because the check_integrity function has already 4237d37aa17SJuan Castillo * extracted the relevant data (v3_ext, pk, sig_alg, etc) */ 4247d37aa17SJuan Castillo 4257d37aa17SJuan Castillo switch (type_desc->type) { 4267d37aa17SJuan Castillo case AUTH_PARAM_RAW_DATA: 4277d37aa17SJuan Castillo /* Data to be signed */ 4287d37aa17SJuan Castillo *param = (void *)tbs.p; 4297d37aa17SJuan Castillo *param_len = (unsigned int)tbs.len; 4307d37aa17SJuan Castillo break; 4317d37aa17SJuan Castillo case AUTH_PARAM_HASH: 432*48279d52SJuan Castillo case AUTH_PARAM_NV_CTR: 4337d37aa17SJuan Castillo /* All these parameters are included as X509v3 extensions */ 4347d37aa17SJuan Castillo rc = get_ext(type_desc->cookie, param, param_len); 4357d37aa17SJuan Castillo break; 4367d37aa17SJuan Castillo case AUTH_PARAM_PUB_KEY: 4377d37aa17SJuan Castillo if (type_desc->cookie != 0) { 4387d37aa17SJuan Castillo /* Get public key from extension */ 4397d37aa17SJuan Castillo rc = get_ext(type_desc->cookie, param, param_len); 4407d37aa17SJuan Castillo } else { 4417d37aa17SJuan Castillo /* Get the subject public key */ 4427d37aa17SJuan Castillo *param = (void *)pk.p; 4437d37aa17SJuan Castillo *param_len = (unsigned int)pk.len; 4447d37aa17SJuan Castillo } 4457d37aa17SJuan Castillo break; 4467d37aa17SJuan Castillo case AUTH_PARAM_SIG_ALG: 4477d37aa17SJuan Castillo /* Get the certificate signature algorithm */ 4487d37aa17SJuan Castillo *param = (void *)sig_alg.p; 4497d37aa17SJuan Castillo *param_len = (unsigned int)sig_alg.len; 4507d37aa17SJuan Castillo break; 4517d37aa17SJuan Castillo case AUTH_PARAM_SIG: 4527d37aa17SJuan Castillo /* Get the certificate signature */ 4537d37aa17SJuan Castillo *param = (void *)signature.p; 4547d37aa17SJuan Castillo *param_len = (unsigned int)signature.len; 4557d37aa17SJuan Castillo break; 4567d37aa17SJuan Castillo default: 4577d37aa17SJuan Castillo rc = IMG_PARSER_ERR_NOT_FOUND; 4587d37aa17SJuan Castillo break; 4597d37aa17SJuan Castillo } 4607d37aa17SJuan Castillo 4617d37aa17SJuan Castillo return rc; 4627d37aa17SJuan Castillo } 4637d37aa17SJuan Castillo 4647d37aa17SJuan Castillo REGISTER_IMG_PARSER_LIB(IMG_CERT, LIB_NAME, init, \ 4657d37aa17SJuan Castillo check_integrity, get_auth_param); 466