17d37aa17SJuan Castillo /* 29a3088a5SQixiang Xu * Copyright (c) 2015-2017, 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> 157d37aa17SJuan Castillo 16*09d40e0eSAntonio Nino Diaz #include <common/debug.h> 17*09d40e0eSAntonio Nino Diaz #include <drivers/auth/crypto_mod.h> 18*09d40e0eSAntonio Nino Diaz #include <drivers/auth/mbedtls/mbedtls_common.h> 19*09d40e0eSAntonio Nino Diaz #include <drivers/auth/mbedtls/mbedtls_config.h> 20*09d40e0eSAntonio Nino Diaz 217d37aa17SJuan Castillo #define LIB_NAME "mbed TLS" 227d37aa17SJuan Castillo 237d37aa17SJuan Castillo /* 247d37aa17SJuan Castillo * AlgorithmIdentifier ::= SEQUENCE { 257d37aa17SJuan Castillo * algorithm OBJECT IDENTIFIER, 267d37aa17SJuan Castillo * parameters ANY DEFINED BY algorithm OPTIONAL 277d37aa17SJuan Castillo * } 287d37aa17SJuan Castillo * 297d37aa17SJuan Castillo * SubjectPublicKeyInfo ::= SEQUENCE { 307d37aa17SJuan Castillo * algorithm AlgorithmIdentifier, 317d37aa17SJuan Castillo * subjectPublicKey BIT STRING 327d37aa17SJuan Castillo * } 337d37aa17SJuan Castillo * 347d37aa17SJuan Castillo * DigestInfo ::= SEQUENCE { 357d37aa17SJuan Castillo * digestAlgorithm AlgorithmIdentifier, 367d37aa17SJuan Castillo * digest OCTET STRING 377d37aa17SJuan Castillo * } 387d37aa17SJuan Castillo */ 397d37aa17SJuan Castillo 407d37aa17SJuan Castillo /* 417d37aa17SJuan Castillo * Initialize the library and export the descriptor 427d37aa17SJuan Castillo */ 437d37aa17SJuan Castillo static void init(void) 447d37aa17SJuan Castillo { 457d37aa17SJuan Castillo /* Initialize mbed TLS */ 467d37aa17SJuan Castillo mbedtls_init(); 477d37aa17SJuan Castillo } 487d37aa17SJuan Castillo 497d37aa17SJuan Castillo /* 507d37aa17SJuan Castillo * Verify a signature. 517d37aa17SJuan Castillo * 527d37aa17SJuan Castillo * Parameters are passed using the DER encoding format following the ASN.1 537d37aa17SJuan Castillo * structures detailed above. 547d37aa17SJuan Castillo */ 557d37aa17SJuan Castillo static int verify_signature(void *data_ptr, unsigned int data_len, 567d37aa17SJuan Castillo void *sig_ptr, unsigned int sig_len, 577d37aa17SJuan Castillo void *sig_alg, unsigned int sig_alg_len, 587d37aa17SJuan Castillo void *pk_ptr, unsigned int pk_len) 597d37aa17SJuan Castillo { 60649dbf6fSJuan Castillo mbedtls_asn1_buf sig_oid, sig_params; 61649dbf6fSJuan Castillo mbedtls_asn1_buf signature; 62649dbf6fSJuan Castillo mbedtls_md_type_t md_alg; 63649dbf6fSJuan Castillo mbedtls_pk_type_t pk_alg; 641001202dSSoby Mathew mbedtls_pk_context pk = {0}; 657d37aa17SJuan Castillo int rc; 667d37aa17SJuan Castillo void *sig_opts = NULL; 67649dbf6fSJuan Castillo const mbedtls_md_info_t *md_info; 687d37aa17SJuan Castillo unsigned char *p, *end; 69649dbf6fSJuan Castillo unsigned char hash[MBEDTLS_MD_MAX_SIZE]; 707d37aa17SJuan Castillo 717d37aa17SJuan Castillo /* Get pointers to signature OID and parameters */ 727d37aa17SJuan Castillo p = (unsigned char *)sig_alg; 737d37aa17SJuan Castillo end = (unsigned char *)(p + sig_alg_len); 74649dbf6fSJuan Castillo rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params); 757d37aa17SJuan Castillo if (rc != 0) { 767d37aa17SJuan Castillo return CRYPTO_ERR_SIGNATURE; 777d37aa17SJuan Castillo } 787d37aa17SJuan Castillo 797d37aa17SJuan Castillo /* Get the actual signature algorithm (MD + PK) */ 801001202dSSoby Mathew rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts); 817d37aa17SJuan Castillo if (rc != 0) { 827d37aa17SJuan Castillo return CRYPTO_ERR_SIGNATURE; 837d37aa17SJuan Castillo } 847d37aa17SJuan Castillo 857d37aa17SJuan Castillo /* Parse the public key */ 86649dbf6fSJuan Castillo mbedtls_pk_init(&pk); 877d37aa17SJuan Castillo p = (unsigned char *)pk_ptr; 887d37aa17SJuan Castillo end = (unsigned char *)(p + pk_len); 89649dbf6fSJuan Castillo rc = mbedtls_pk_parse_subpubkey(&p, end, &pk); 907d37aa17SJuan Castillo if (rc != 0) { 911001202dSSoby Mathew rc = CRYPTO_ERR_SIGNATURE; 921001202dSSoby Mathew goto end2; 937d37aa17SJuan Castillo } 947d37aa17SJuan Castillo 957d37aa17SJuan Castillo /* Get the signature (bitstring) */ 967d37aa17SJuan Castillo p = (unsigned char *)sig_ptr; 977d37aa17SJuan Castillo end = (unsigned char *)(p + sig_len); 987d37aa17SJuan Castillo signature.tag = *p; 99649dbf6fSJuan Castillo rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len); 1007d37aa17SJuan Castillo if (rc != 0) { 1017d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 1021001202dSSoby Mathew goto end1; 1037d37aa17SJuan Castillo } 1047d37aa17SJuan Castillo signature.p = p; 1057d37aa17SJuan Castillo 1067d37aa17SJuan Castillo /* Calculate the hash of the data */ 107649dbf6fSJuan Castillo md_info = mbedtls_md_info_from_type(md_alg); 1087d37aa17SJuan Castillo if (md_info == NULL) { 1097d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 1101001202dSSoby Mathew goto end1; 1117d37aa17SJuan Castillo } 1127d37aa17SJuan Castillo p = (unsigned char *)data_ptr; 113649dbf6fSJuan Castillo rc = mbedtls_md(md_info, p, data_len, hash); 1147d37aa17SJuan Castillo if (rc != 0) { 1157d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 1161001202dSSoby Mathew goto end1; 1177d37aa17SJuan Castillo } 1187d37aa17SJuan Castillo 1197d37aa17SJuan Castillo /* Verify the signature */ 120649dbf6fSJuan Castillo rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash, 121649dbf6fSJuan Castillo mbedtls_md_get_size(md_info), 122649dbf6fSJuan Castillo signature.p, signature.len); 1237d37aa17SJuan Castillo if (rc != 0) { 1247d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 1251001202dSSoby Mathew goto end1; 1267d37aa17SJuan Castillo } 1277d37aa17SJuan Castillo 1287d37aa17SJuan Castillo /* Signature verification success */ 1297d37aa17SJuan Castillo rc = CRYPTO_SUCCESS; 1307d37aa17SJuan Castillo 1311001202dSSoby Mathew end1: 132649dbf6fSJuan Castillo mbedtls_pk_free(&pk); 1331001202dSSoby Mathew end2: 1341001202dSSoby Mathew mbedtls_free(sig_opts); 1357d37aa17SJuan Castillo return rc; 1367d37aa17SJuan Castillo } 1377d37aa17SJuan Castillo 1387d37aa17SJuan Castillo /* 1397d37aa17SJuan Castillo * Match a hash 1407d37aa17SJuan Castillo * 1417d37aa17SJuan Castillo * Digest info is passed in DER format following the ASN.1 structure detailed 1427d37aa17SJuan Castillo * above. 1437d37aa17SJuan Castillo */ 1447d37aa17SJuan Castillo static int verify_hash(void *data_ptr, unsigned int data_len, 1457d37aa17SJuan Castillo void *digest_info_ptr, unsigned int digest_info_len) 1467d37aa17SJuan Castillo { 147649dbf6fSJuan Castillo mbedtls_asn1_buf hash_oid, params; 148649dbf6fSJuan Castillo mbedtls_md_type_t md_alg; 149649dbf6fSJuan Castillo const mbedtls_md_info_t *md_info; 1507d37aa17SJuan Castillo unsigned char *p, *end, *hash; 151649dbf6fSJuan Castillo unsigned char data_hash[MBEDTLS_MD_MAX_SIZE]; 1527d37aa17SJuan Castillo size_t len; 1537d37aa17SJuan Castillo int rc; 1547d37aa17SJuan Castillo 155649dbf6fSJuan Castillo /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ 1567d37aa17SJuan Castillo p = (unsigned char *)digest_info_ptr; 157aa856917SSandrine Bailleux end = p + digest_info_len; 158649dbf6fSJuan Castillo rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 159649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 1607d37aa17SJuan Castillo if (rc != 0) { 1617d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1627d37aa17SJuan Castillo } 1637d37aa17SJuan Castillo 1647d37aa17SJuan Castillo /* Get the hash algorithm */ 165649dbf6fSJuan Castillo rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); 1667d37aa17SJuan Castillo if (rc != 0) { 1677d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1687d37aa17SJuan Castillo } 1697d37aa17SJuan Castillo 170649dbf6fSJuan Castillo rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); 1717d37aa17SJuan Castillo if (rc != 0) { 1727d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1737d37aa17SJuan Castillo } 1747d37aa17SJuan Castillo 175649dbf6fSJuan Castillo md_info = mbedtls_md_info_from_type(md_alg); 1767d37aa17SJuan Castillo if (md_info == NULL) { 1777d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1787d37aa17SJuan Castillo } 1797d37aa17SJuan Castillo 1807d37aa17SJuan Castillo /* Hash should be octet string type */ 181649dbf6fSJuan Castillo rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); 1827d37aa17SJuan Castillo if (rc != 0) { 1837d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1847d37aa17SJuan Castillo } 1857d37aa17SJuan Castillo 1867d37aa17SJuan Castillo /* Length of hash must match the algorithm's size */ 187649dbf6fSJuan Castillo if (len != mbedtls_md_get_size(md_info)) { 1887d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1897d37aa17SJuan Castillo } 1907d37aa17SJuan Castillo hash = p; 1917d37aa17SJuan Castillo 1927d37aa17SJuan Castillo /* Calculate the hash of the data */ 1937d37aa17SJuan Castillo p = (unsigned char *)data_ptr; 194649dbf6fSJuan Castillo rc = mbedtls_md(md_info, p, data_len, data_hash); 1957d37aa17SJuan Castillo if (rc != 0) { 1967d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1977d37aa17SJuan Castillo } 1987d37aa17SJuan Castillo 1997d37aa17SJuan Castillo /* Compare values */ 200fabd21adSAntonio Nino Diaz rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info)); 2017d37aa17SJuan Castillo if (rc != 0) { 2027d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 2037d37aa17SJuan Castillo } 2047d37aa17SJuan Castillo 2057d37aa17SJuan Castillo return CRYPTO_SUCCESS; 2067d37aa17SJuan Castillo } 2077d37aa17SJuan Castillo 2087d37aa17SJuan Castillo /* 2097d37aa17SJuan Castillo * Register crypto library descriptor 2107d37aa17SJuan Castillo */ 2117d37aa17SJuan Castillo REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash); 212