17d37aa17SJuan Castillo /* 28c105290SAlexei Fedorov * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. 37d37aa17SJuan Castillo * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 57d37aa17SJuan Castillo */ 67d37aa17SJuan Castillo 77d37aa17SJuan Castillo #include <stddef.h> 87d37aa17SJuan Castillo #include <string.h> 97d37aa17SJuan Castillo 107d37aa17SJuan Castillo /* mbed TLS headers */ 11649dbf6fSJuan Castillo #include <mbedtls/md.h> 12649dbf6fSJuan Castillo #include <mbedtls/memory_buffer_alloc.h> 13649dbf6fSJuan Castillo #include <mbedtls/oid.h> 14649dbf6fSJuan Castillo #include <mbedtls/platform.h> 15*93ee2799SMadhukar Pappireddy #include <mbedtls/x509.h> 167d37aa17SJuan Castillo 1709d40e0eSAntonio Nino Diaz #include <common/debug.h> 1809d40e0eSAntonio Nino Diaz #include <drivers/auth/crypto_mod.h> 1909d40e0eSAntonio Nino Diaz #include <drivers/auth/mbedtls/mbedtls_common.h> 2009d40e0eSAntonio Nino Diaz #include <drivers/auth/mbedtls/mbedtls_config.h> 2109d40e0eSAntonio Nino Diaz 227d37aa17SJuan Castillo #define LIB_NAME "mbed TLS" 237d37aa17SJuan Castillo 247d37aa17SJuan Castillo /* 257d37aa17SJuan Castillo * AlgorithmIdentifier ::= SEQUENCE { 267d37aa17SJuan Castillo * algorithm OBJECT IDENTIFIER, 277d37aa17SJuan Castillo * parameters ANY DEFINED BY algorithm OPTIONAL 287d37aa17SJuan Castillo * } 297d37aa17SJuan Castillo * 307d37aa17SJuan Castillo * SubjectPublicKeyInfo ::= SEQUENCE { 317d37aa17SJuan Castillo * algorithm AlgorithmIdentifier, 327d37aa17SJuan Castillo * subjectPublicKey BIT STRING 337d37aa17SJuan Castillo * } 347d37aa17SJuan Castillo * 357d37aa17SJuan Castillo * DigestInfo ::= SEQUENCE { 367d37aa17SJuan Castillo * digestAlgorithm AlgorithmIdentifier, 377d37aa17SJuan Castillo * digest OCTET STRING 387d37aa17SJuan Castillo * } 397d37aa17SJuan Castillo */ 407d37aa17SJuan Castillo 417d37aa17SJuan Castillo /* 427d37aa17SJuan Castillo * Initialize the library and export the descriptor 437d37aa17SJuan Castillo */ 447d37aa17SJuan Castillo static void init(void) 457d37aa17SJuan Castillo { 467d37aa17SJuan Castillo /* Initialize mbed TLS */ 477d37aa17SJuan Castillo mbedtls_init(); 487d37aa17SJuan Castillo } 497d37aa17SJuan Castillo 507d37aa17SJuan Castillo /* 517d37aa17SJuan Castillo * Verify a signature. 527d37aa17SJuan Castillo * 537d37aa17SJuan Castillo * Parameters are passed using the DER encoding format following the ASN.1 547d37aa17SJuan Castillo * structures detailed above. 557d37aa17SJuan Castillo */ 567d37aa17SJuan Castillo static int verify_signature(void *data_ptr, unsigned int data_len, 577d37aa17SJuan Castillo void *sig_ptr, unsigned int sig_len, 587d37aa17SJuan Castillo void *sig_alg, unsigned int sig_alg_len, 597d37aa17SJuan Castillo void *pk_ptr, unsigned int pk_len) 607d37aa17SJuan Castillo { 61649dbf6fSJuan Castillo mbedtls_asn1_buf sig_oid, sig_params; 62649dbf6fSJuan Castillo mbedtls_asn1_buf signature; 63649dbf6fSJuan Castillo mbedtls_md_type_t md_alg; 64649dbf6fSJuan Castillo mbedtls_pk_type_t pk_alg; 651001202dSSoby Mathew mbedtls_pk_context pk = {0}; 667d37aa17SJuan Castillo int rc; 677d37aa17SJuan Castillo void *sig_opts = NULL; 68649dbf6fSJuan Castillo const mbedtls_md_info_t *md_info; 697d37aa17SJuan Castillo unsigned char *p, *end; 70649dbf6fSJuan Castillo unsigned char hash[MBEDTLS_MD_MAX_SIZE]; 717d37aa17SJuan Castillo 727d37aa17SJuan Castillo /* Get pointers to signature OID and parameters */ 737d37aa17SJuan Castillo p = (unsigned char *)sig_alg; 747d37aa17SJuan Castillo end = (unsigned char *)(p + sig_alg_len); 75649dbf6fSJuan Castillo rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params); 767d37aa17SJuan Castillo if (rc != 0) { 777d37aa17SJuan Castillo return CRYPTO_ERR_SIGNATURE; 787d37aa17SJuan Castillo } 797d37aa17SJuan Castillo 807d37aa17SJuan Castillo /* Get the actual signature algorithm (MD + PK) */ 811001202dSSoby Mathew rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts); 827d37aa17SJuan Castillo if (rc != 0) { 837d37aa17SJuan Castillo return CRYPTO_ERR_SIGNATURE; 847d37aa17SJuan Castillo } 857d37aa17SJuan Castillo 867d37aa17SJuan Castillo /* Parse the public key */ 87649dbf6fSJuan Castillo mbedtls_pk_init(&pk); 887d37aa17SJuan Castillo p = (unsigned char *)pk_ptr; 897d37aa17SJuan Castillo end = (unsigned char *)(p + pk_len); 90649dbf6fSJuan Castillo rc = mbedtls_pk_parse_subpubkey(&p, end, &pk); 917d37aa17SJuan Castillo if (rc != 0) { 921001202dSSoby Mathew rc = CRYPTO_ERR_SIGNATURE; 931001202dSSoby Mathew goto end2; 947d37aa17SJuan Castillo } 957d37aa17SJuan Castillo 967d37aa17SJuan Castillo /* Get the signature (bitstring) */ 977d37aa17SJuan Castillo p = (unsigned char *)sig_ptr; 987d37aa17SJuan Castillo end = (unsigned char *)(p + sig_len); 997d37aa17SJuan Castillo signature.tag = *p; 100649dbf6fSJuan Castillo rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len); 1017d37aa17SJuan Castillo if (rc != 0) { 1027d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 1031001202dSSoby Mathew goto end1; 1047d37aa17SJuan Castillo } 1057d37aa17SJuan Castillo signature.p = p; 1067d37aa17SJuan Castillo 1077d37aa17SJuan Castillo /* Calculate the hash of the data */ 108649dbf6fSJuan Castillo md_info = mbedtls_md_info_from_type(md_alg); 1097d37aa17SJuan Castillo if (md_info == NULL) { 1107d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 1111001202dSSoby Mathew goto end1; 1127d37aa17SJuan Castillo } 1137d37aa17SJuan Castillo p = (unsigned char *)data_ptr; 114649dbf6fSJuan Castillo rc = mbedtls_md(md_info, p, data_len, hash); 1157d37aa17SJuan Castillo if (rc != 0) { 1167d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 1171001202dSSoby Mathew goto end1; 1187d37aa17SJuan Castillo } 1197d37aa17SJuan Castillo 1207d37aa17SJuan Castillo /* Verify the signature */ 121649dbf6fSJuan Castillo rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash, 122649dbf6fSJuan Castillo mbedtls_md_get_size(md_info), 123649dbf6fSJuan Castillo signature.p, signature.len); 1247d37aa17SJuan Castillo if (rc != 0) { 1257d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 1261001202dSSoby Mathew goto end1; 1277d37aa17SJuan Castillo } 1287d37aa17SJuan Castillo 1297d37aa17SJuan Castillo /* Signature verification success */ 1307d37aa17SJuan Castillo rc = CRYPTO_SUCCESS; 1317d37aa17SJuan Castillo 1321001202dSSoby Mathew end1: 133649dbf6fSJuan Castillo mbedtls_pk_free(&pk); 1341001202dSSoby Mathew end2: 1351001202dSSoby Mathew mbedtls_free(sig_opts); 1367d37aa17SJuan Castillo return rc; 1377d37aa17SJuan Castillo } 1387d37aa17SJuan Castillo 1397d37aa17SJuan Castillo /* 1407d37aa17SJuan Castillo * Match a hash 1417d37aa17SJuan Castillo * 1427d37aa17SJuan Castillo * Digest info is passed in DER format following the ASN.1 structure detailed 1437d37aa17SJuan Castillo * above. 1447d37aa17SJuan Castillo */ 1457d37aa17SJuan Castillo static int verify_hash(void *data_ptr, unsigned int data_len, 1467d37aa17SJuan Castillo void *digest_info_ptr, unsigned int digest_info_len) 1477d37aa17SJuan Castillo { 148649dbf6fSJuan Castillo mbedtls_asn1_buf hash_oid, params; 149649dbf6fSJuan Castillo mbedtls_md_type_t md_alg; 150649dbf6fSJuan Castillo const mbedtls_md_info_t *md_info; 1517d37aa17SJuan Castillo unsigned char *p, *end, *hash; 152649dbf6fSJuan Castillo unsigned char data_hash[MBEDTLS_MD_MAX_SIZE]; 1537d37aa17SJuan Castillo size_t len; 1547d37aa17SJuan Castillo int rc; 1557d37aa17SJuan Castillo 156649dbf6fSJuan Castillo /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ 1577d37aa17SJuan Castillo p = (unsigned char *)digest_info_ptr; 158aa856917SSandrine Bailleux end = p + digest_info_len; 159649dbf6fSJuan Castillo rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 160649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 1617d37aa17SJuan Castillo if (rc != 0) { 1627d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1637d37aa17SJuan Castillo } 1647d37aa17SJuan Castillo 1657d37aa17SJuan Castillo /* Get the hash algorithm */ 166649dbf6fSJuan Castillo rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); 1677d37aa17SJuan Castillo if (rc != 0) { 1687d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1697d37aa17SJuan Castillo } 1707d37aa17SJuan Castillo 171649dbf6fSJuan Castillo rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); 1727d37aa17SJuan Castillo if (rc != 0) { 1737d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1747d37aa17SJuan Castillo } 1757d37aa17SJuan Castillo 176649dbf6fSJuan Castillo md_info = mbedtls_md_info_from_type(md_alg); 1777d37aa17SJuan Castillo if (md_info == NULL) { 1787d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1797d37aa17SJuan Castillo } 1807d37aa17SJuan Castillo 1817d37aa17SJuan Castillo /* Hash should be octet string type */ 182649dbf6fSJuan Castillo rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); 1837d37aa17SJuan Castillo if (rc != 0) { 1847d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1857d37aa17SJuan Castillo } 1867d37aa17SJuan Castillo 1877d37aa17SJuan Castillo /* Length of hash must match the algorithm's size */ 188649dbf6fSJuan Castillo if (len != mbedtls_md_get_size(md_info)) { 1897d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1907d37aa17SJuan Castillo } 1917d37aa17SJuan Castillo hash = p; 1927d37aa17SJuan Castillo 1937d37aa17SJuan Castillo /* Calculate the hash of the data */ 1947d37aa17SJuan Castillo p = (unsigned char *)data_ptr; 195649dbf6fSJuan Castillo rc = mbedtls_md(md_info, p, data_len, data_hash); 1967d37aa17SJuan Castillo if (rc != 0) { 1977d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1987d37aa17SJuan Castillo } 1997d37aa17SJuan Castillo 2007d37aa17SJuan Castillo /* Compare values */ 201fabd21adSAntonio Nino Diaz rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info)); 2027d37aa17SJuan Castillo if (rc != 0) { 2037d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 2047d37aa17SJuan Castillo } 2057d37aa17SJuan Castillo 2067d37aa17SJuan Castillo return CRYPTO_SUCCESS; 2077d37aa17SJuan Castillo } 2087d37aa17SJuan Castillo 2098c105290SAlexei Fedorov #if MEASURED_BOOT 2108c105290SAlexei Fedorov /* 2118c105290SAlexei Fedorov * Calculate a hash 2128c105290SAlexei Fedorov * 2138c105290SAlexei Fedorov * output points to the computed hash 2148c105290SAlexei Fedorov */ 2158c105290SAlexei Fedorov int calc_hash(unsigned int alg, void *data_ptr, 2168c105290SAlexei Fedorov unsigned int data_len, unsigned char *output) 2178c105290SAlexei Fedorov { 2188c105290SAlexei Fedorov const mbedtls_md_info_t *md_info; 2198c105290SAlexei Fedorov 2208c105290SAlexei Fedorov md_info = mbedtls_md_info_from_type((mbedtls_md_type_t)alg); 2218c105290SAlexei Fedorov if (md_info == NULL) { 2228c105290SAlexei Fedorov return CRYPTO_ERR_HASH; 2238c105290SAlexei Fedorov } 2248c105290SAlexei Fedorov 2258c105290SAlexei Fedorov /* Calculate the hash of the data */ 2268c105290SAlexei Fedorov return mbedtls_md(md_info, data_ptr, data_len, output); 2278c105290SAlexei Fedorov } 2288c105290SAlexei Fedorov #endif /* MEASURED_BOOT */ 2298c105290SAlexei Fedorov 2307d37aa17SJuan Castillo /* 2317d37aa17SJuan Castillo * Register crypto library descriptor 2327d37aa17SJuan Castillo */ 2338c105290SAlexei Fedorov #if MEASURED_BOOT 2348c105290SAlexei Fedorov REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash); 2358c105290SAlexei Fedorov #else 2367d37aa17SJuan Castillo REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash); 2378c105290SAlexei Fedorov #endif /* MEASURED_BOOT */ 238