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 327d37aa17SJuan Castillo #include <crypto_mod.h> 337d37aa17SJuan Castillo #include <debug.h> 347d37aa17SJuan Castillo #include <mbedtls_common.h> 357d37aa17SJuan Castillo #include <stddef.h> 367d37aa17SJuan Castillo #include <string.h> 377d37aa17SJuan Castillo 387d37aa17SJuan Castillo /* mbed TLS headers */ 39649dbf6fSJuan Castillo #include <mbedtls/md.h> 40649dbf6fSJuan Castillo #include <mbedtls/memory_buffer_alloc.h> 41649dbf6fSJuan Castillo #include <mbedtls/oid.h> 42649dbf6fSJuan Castillo #include <mbedtls/platform.h> 437d37aa17SJuan Castillo 447d37aa17SJuan Castillo #define LIB_NAME "mbed TLS" 457d37aa17SJuan Castillo 467d37aa17SJuan Castillo /* 477d37aa17SJuan Castillo * AlgorithmIdentifier ::= SEQUENCE { 487d37aa17SJuan Castillo * algorithm OBJECT IDENTIFIER, 497d37aa17SJuan Castillo * parameters ANY DEFINED BY algorithm OPTIONAL 507d37aa17SJuan Castillo * } 517d37aa17SJuan Castillo * 527d37aa17SJuan Castillo * SubjectPublicKeyInfo ::= SEQUENCE { 537d37aa17SJuan Castillo * algorithm AlgorithmIdentifier, 547d37aa17SJuan Castillo * subjectPublicKey BIT STRING 557d37aa17SJuan Castillo * } 567d37aa17SJuan Castillo * 577d37aa17SJuan Castillo * DigestInfo ::= SEQUENCE { 587d37aa17SJuan Castillo * digestAlgorithm AlgorithmIdentifier, 597d37aa17SJuan Castillo * digest OCTET STRING 607d37aa17SJuan Castillo * } 617d37aa17SJuan Castillo */ 627d37aa17SJuan Castillo 637d37aa17SJuan Castillo /* 647d37aa17SJuan Castillo * Initialize the library and export the descriptor 657d37aa17SJuan Castillo */ 667d37aa17SJuan Castillo static void init(void) 677d37aa17SJuan Castillo { 687d37aa17SJuan Castillo /* Initialize mbed TLS */ 697d37aa17SJuan Castillo mbedtls_init(); 707d37aa17SJuan Castillo } 717d37aa17SJuan Castillo 727d37aa17SJuan Castillo /* 737d37aa17SJuan Castillo * Verify a signature. 747d37aa17SJuan Castillo * 757d37aa17SJuan Castillo * Parameters are passed using the DER encoding format following the ASN.1 767d37aa17SJuan Castillo * structures detailed above. 777d37aa17SJuan Castillo */ 787d37aa17SJuan Castillo static int verify_signature(void *data_ptr, unsigned int data_len, 797d37aa17SJuan Castillo void *sig_ptr, unsigned int sig_len, 807d37aa17SJuan Castillo void *sig_alg, unsigned int sig_alg_len, 817d37aa17SJuan Castillo void *pk_ptr, unsigned int pk_len) 827d37aa17SJuan Castillo { 83649dbf6fSJuan Castillo mbedtls_asn1_buf sig_oid, sig_params; 84649dbf6fSJuan Castillo mbedtls_asn1_buf signature; 85649dbf6fSJuan Castillo mbedtls_md_type_t md_alg; 86649dbf6fSJuan Castillo mbedtls_pk_type_t pk_alg; 87649dbf6fSJuan Castillo mbedtls_pk_context pk; 887d37aa17SJuan Castillo int rc; 897d37aa17SJuan Castillo void *sig_opts = NULL; 90649dbf6fSJuan Castillo const mbedtls_md_info_t *md_info; 917d37aa17SJuan Castillo unsigned char *p, *end; 92649dbf6fSJuan Castillo unsigned char hash[MBEDTLS_MD_MAX_SIZE]; 937d37aa17SJuan Castillo 947d37aa17SJuan Castillo /* Get pointers to signature OID and parameters */ 957d37aa17SJuan Castillo p = (unsigned char *)sig_alg; 967d37aa17SJuan Castillo end = (unsigned char *)(p + sig_alg_len); 97649dbf6fSJuan Castillo rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params); 987d37aa17SJuan Castillo if (rc != 0) { 997d37aa17SJuan Castillo return CRYPTO_ERR_SIGNATURE; 1007d37aa17SJuan Castillo } 1017d37aa17SJuan Castillo 1027d37aa17SJuan Castillo /* Get the actual signature algorithm (MD + PK) */ 103649dbf6fSJuan Castillo rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg); 1047d37aa17SJuan Castillo if (rc != 0) { 1057d37aa17SJuan Castillo return CRYPTO_ERR_SIGNATURE; 1067d37aa17SJuan Castillo } 1077d37aa17SJuan Castillo 1087d37aa17SJuan Castillo /* Parse the public key */ 109649dbf6fSJuan Castillo mbedtls_pk_init(&pk); 1107d37aa17SJuan Castillo p = (unsigned char *)pk_ptr; 1117d37aa17SJuan Castillo end = (unsigned char *)(p + pk_len); 112649dbf6fSJuan Castillo rc = mbedtls_pk_parse_subpubkey(&p, end, &pk); 1137d37aa17SJuan Castillo if (rc != 0) { 1147d37aa17SJuan Castillo return CRYPTO_ERR_SIGNATURE; 1157d37aa17SJuan Castillo } 1167d37aa17SJuan Castillo 1177d37aa17SJuan Castillo /* Get the signature (bitstring) */ 1187d37aa17SJuan Castillo p = (unsigned char *)sig_ptr; 1197d37aa17SJuan Castillo end = (unsigned char *)(p + sig_len); 1207d37aa17SJuan Castillo signature.tag = *p; 121649dbf6fSJuan Castillo rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len); 1227d37aa17SJuan Castillo if (rc != 0) { 1237d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 1247d37aa17SJuan Castillo goto end; 1257d37aa17SJuan Castillo } 1267d37aa17SJuan Castillo signature.p = p; 1277d37aa17SJuan Castillo 1287d37aa17SJuan Castillo /* Calculate the hash of the data */ 129649dbf6fSJuan Castillo md_info = mbedtls_md_info_from_type(md_alg); 1307d37aa17SJuan Castillo if (md_info == NULL) { 1317d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 1327d37aa17SJuan Castillo goto end; 1337d37aa17SJuan Castillo } 1347d37aa17SJuan Castillo p = (unsigned char *)data_ptr; 135649dbf6fSJuan Castillo rc = mbedtls_md(md_info, p, data_len, hash); 1367d37aa17SJuan Castillo if (rc != 0) { 1377d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 1387d37aa17SJuan Castillo goto end; 1397d37aa17SJuan Castillo } 1407d37aa17SJuan Castillo 1417d37aa17SJuan Castillo /* Verify the signature */ 142649dbf6fSJuan Castillo rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash, 143649dbf6fSJuan Castillo mbedtls_md_get_size(md_info), 144649dbf6fSJuan Castillo signature.p, signature.len); 1457d37aa17SJuan Castillo if (rc != 0) { 1467d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 1477d37aa17SJuan Castillo goto end; 1487d37aa17SJuan Castillo } 1497d37aa17SJuan Castillo 1507d37aa17SJuan Castillo /* Signature verification success */ 1517d37aa17SJuan Castillo rc = CRYPTO_SUCCESS; 1527d37aa17SJuan Castillo 1537d37aa17SJuan Castillo end: 154649dbf6fSJuan Castillo mbedtls_pk_free(&pk); 1557d37aa17SJuan Castillo return rc; 1567d37aa17SJuan Castillo } 1577d37aa17SJuan Castillo 1587d37aa17SJuan Castillo /* 1597d37aa17SJuan Castillo * Match a hash 1607d37aa17SJuan Castillo * 1617d37aa17SJuan Castillo * Digest info is passed in DER format following the ASN.1 structure detailed 1627d37aa17SJuan Castillo * above. 1637d37aa17SJuan Castillo */ 1647d37aa17SJuan Castillo static int verify_hash(void *data_ptr, unsigned int data_len, 1657d37aa17SJuan Castillo void *digest_info_ptr, unsigned int digest_info_len) 1667d37aa17SJuan Castillo { 167649dbf6fSJuan Castillo mbedtls_asn1_buf hash_oid, params; 168649dbf6fSJuan Castillo mbedtls_md_type_t md_alg; 169649dbf6fSJuan Castillo const mbedtls_md_info_t *md_info; 1707d37aa17SJuan Castillo unsigned char *p, *end, *hash; 171649dbf6fSJuan Castillo unsigned char data_hash[MBEDTLS_MD_MAX_SIZE]; 1727d37aa17SJuan Castillo size_t len; 1737d37aa17SJuan Castillo int rc; 1747d37aa17SJuan Castillo 175649dbf6fSJuan Castillo /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ 1767d37aa17SJuan Castillo p = (unsigned char *)digest_info_ptr; 177aa856917SSandrine Bailleux end = p + digest_info_len; 178649dbf6fSJuan Castillo rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 179649dbf6fSJuan Castillo MBEDTLS_ASN1_SEQUENCE); 1807d37aa17SJuan Castillo if (rc != 0) { 1817d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1827d37aa17SJuan Castillo } 1837d37aa17SJuan Castillo 1847d37aa17SJuan Castillo /* Get the hash algorithm */ 185649dbf6fSJuan Castillo rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); 1867d37aa17SJuan Castillo if (rc != 0) { 1877d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1887d37aa17SJuan Castillo } 1897d37aa17SJuan Castillo 190649dbf6fSJuan Castillo rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); 1917d37aa17SJuan Castillo if (rc != 0) { 1927d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1937d37aa17SJuan Castillo } 1947d37aa17SJuan Castillo 195649dbf6fSJuan Castillo md_info = mbedtls_md_info_from_type(md_alg); 1967d37aa17SJuan Castillo if (md_info == NULL) { 1977d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 1987d37aa17SJuan Castillo } 1997d37aa17SJuan Castillo 2007d37aa17SJuan Castillo /* Hash should be octet string type */ 201649dbf6fSJuan Castillo rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); 2027d37aa17SJuan Castillo if (rc != 0) { 2037d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 2047d37aa17SJuan Castillo } 2057d37aa17SJuan Castillo 2067d37aa17SJuan Castillo /* Length of hash must match the algorithm's size */ 207649dbf6fSJuan Castillo if (len != mbedtls_md_get_size(md_info)) { 2087d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 2097d37aa17SJuan Castillo } 2107d37aa17SJuan Castillo hash = p; 2117d37aa17SJuan Castillo 2127d37aa17SJuan Castillo /* Calculate the hash of the data */ 2137d37aa17SJuan Castillo p = (unsigned char *)data_ptr; 214649dbf6fSJuan Castillo rc = mbedtls_md(md_info, p, data_len, data_hash); 2157d37aa17SJuan Castillo if (rc != 0) { 2167d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 2177d37aa17SJuan Castillo } 2187d37aa17SJuan Castillo 2197d37aa17SJuan Castillo /* Compare values */ 220*fabd21adSAntonio Nino Diaz rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info)); 2217d37aa17SJuan Castillo if (rc != 0) { 2227d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 2237d37aa17SJuan Castillo } 2247d37aa17SJuan Castillo 2257d37aa17SJuan Castillo return CRYPTO_SUCCESS; 2267d37aa17SJuan Castillo } 2277d37aa17SJuan Castillo 2287d37aa17SJuan Castillo /* 2297d37aa17SJuan Castillo * Register crypto library descriptor 2307d37aa17SJuan Castillo */ 2317d37aa17SJuan Castillo REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash); 232