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 #include <crypto_mod.h> 33*7d37aa17SJuan Castillo #include <debug.h> 34*7d37aa17SJuan Castillo #include <mbedtls_common.h> 35*7d37aa17SJuan Castillo #include <stddef.h> 36*7d37aa17SJuan Castillo #include <string.h> 37*7d37aa17SJuan Castillo 38*7d37aa17SJuan Castillo /* mbedTLS headers */ 39*7d37aa17SJuan Castillo #include <polarssl/md_wrap.h> 40*7d37aa17SJuan Castillo #include <polarssl/memory_buffer_alloc.h> 41*7d37aa17SJuan Castillo #include <polarssl/oid.h> 42*7d37aa17SJuan Castillo #include <polarssl/platform.h> 43*7d37aa17SJuan Castillo 44*7d37aa17SJuan Castillo #define LIB_NAME "mbedTLS" 45*7d37aa17SJuan Castillo 46*7d37aa17SJuan Castillo /* 47*7d37aa17SJuan Castillo * AlgorithmIdentifier ::= SEQUENCE { 48*7d37aa17SJuan Castillo * algorithm OBJECT IDENTIFIER, 49*7d37aa17SJuan Castillo * parameters ANY DEFINED BY algorithm OPTIONAL 50*7d37aa17SJuan Castillo * } 51*7d37aa17SJuan Castillo * 52*7d37aa17SJuan Castillo * SubjectPublicKeyInfo ::= SEQUENCE { 53*7d37aa17SJuan Castillo * algorithm AlgorithmIdentifier, 54*7d37aa17SJuan Castillo * subjectPublicKey BIT STRING 55*7d37aa17SJuan Castillo * } 56*7d37aa17SJuan Castillo * 57*7d37aa17SJuan Castillo * DigestInfo ::= SEQUENCE { 58*7d37aa17SJuan Castillo * digestAlgorithm AlgorithmIdentifier, 59*7d37aa17SJuan Castillo * digest OCTET STRING 60*7d37aa17SJuan Castillo * } 61*7d37aa17SJuan Castillo */ 62*7d37aa17SJuan Castillo 63*7d37aa17SJuan Castillo /* 64*7d37aa17SJuan Castillo * Initialize the library and export the descriptor 65*7d37aa17SJuan Castillo */ 66*7d37aa17SJuan Castillo static void init(void) 67*7d37aa17SJuan Castillo { 68*7d37aa17SJuan Castillo /* Initialize mbedTLS */ 69*7d37aa17SJuan Castillo mbedtls_init(); 70*7d37aa17SJuan Castillo } 71*7d37aa17SJuan Castillo 72*7d37aa17SJuan Castillo /* 73*7d37aa17SJuan Castillo * Verify a signature. 74*7d37aa17SJuan Castillo * 75*7d37aa17SJuan Castillo * Parameters are passed using the DER encoding format following the ASN.1 76*7d37aa17SJuan Castillo * structures detailed above. 77*7d37aa17SJuan Castillo */ 78*7d37aa17SJuan Castillo static int verify_signature(void *data_ptr, unsigned int data_len, 79*7d37aa17SJuan Castillo void *sig_ptr, unsigned int sig_len, 80*7d37aa17SJuan Castillo void *sig_alg, unsigned int sig_alg_len, 81*7d37aa17SJuan Castillo void *pk_ptr, unsigned int pk_len) 82*7d37aa17SJuan Castillo { 83*7d37aa17SJuan Castillo asn1_buf sig_oid, sig_params; 84*7d37aa17SJuan Castillo asn1_buf signature; 85*7d37aa17SJuan Castillo md_type_t md_alg; 86*7d37aa17SJuan Castillo pk_type_t pk_alg; 87*7d37aa17SJuan Castillo pk_context pk; 88*7d37aa17SJuan Castillo int rc; 89*7d37aa17SJuan Castillo void *sig_opts = NULL; 90*7d37aa17SJuan Castillo const md_info_t *md_info; 91*7d37aa17SJuan Castillo unsigned char *p, *end; 92*7d37aa17SJuan Castillo unsigned char hash[POLARSSL_MD_MAX_SIZE]; 93*7d37aa17SJuan Castillo 94*7d37aa17SJuan Castillo /* Get pointers to signature OID and parameters */ 95*7d37aa17SJuan Castillo p = (unsigned char *)sig_alg; 96*7d37aa17SJuan Castillo end = (unsigned char *)(p + sig_alg_len); 97*7d37aa17SJuan Castillo rc = asn1_get_alg(&p, end, &sig_oid, &sig_params); 98*7d37aa17SJuan Castillo if (rc != 0) { 99*7d37aa17SJuan Castillo return CRYPTO_ERR_SIGNATURE; 100*7d37aa17SJuan Castillo } 101*7d37aa17SJuan Castillo 102*7d37aa17SJuan Castillo /* Get the actual signature algorithm (MD + PK) */ 103*7d37aa17SJuan Castillo rc = oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg); 104*7d37aa17SJuan Castillo if (rc != 0) { 105*7d37aa17SJuan Castillo return CRYPTO_ERR_SIGNATURE; 106*7d37aa17SJuan Castillo } 107*7d37aa17SJuan Castillo 108*7d37aa17SJuan Castillo /* Parse the public key */ 109*7d37aa17SJuan Castillo pk_init(&pk); 110*7d37aa17SJuan Castillo p = (unsigned char *)pk_ptr; 111*7d37aa17SJuan Castillo end = (unsigned char *)(p + pk_len); 112*7d37aa17SJuan Castillo rc = pk_parse_subpubkey(&p, end, &pk); 113*7d37aa17SJuan Castillo if (rc != 0) { 114*7d37aa17SJuan Castillo return CRYPTO_ERR_SIGNATURE; 115*7d37aa17SJuan Castillo } 116*7d37aa17SJuan Castillo 117*7d37aa17SJuan Castillo /* Get the signature (bitstring) */ 118*7d37aa17SJuan Castillo p = (unsigned char *)sig_ptr; 119*7d37aa17SJuan Castillo end = (unsigned char *)(p + sig_len); 120*7d37aa17SJuan Castillo signature.tag = *p; 121*7d37aa17SJuan Castillo rc = asn1_get_bitstring_null(&p, end, &signature.len); 122*7d37aa17SJuan Castillo if (rc != 0) { 123*7d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 124*7d37aa17SJuan Castillo goto end; 125*7d37aa17SJuan Castillo } 126*7d37aa17SJuan Castillo signature.p = p; 127*7d37aa17SJuan Castillo 128*7d37aa17SJuan Castillo /* Calculate the hash of the data */ 129*7d37aa17SJuan Castillo md_info = md_info_from_type(md_alg); 130*7d37aa17SJuan Castillo if (md_info == NULL) { 131*7d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 132*7d37aa17SJuan Castillo goto end; 133*7d37aa17SJuan Castillo } 134*7d37aa17SJuan Castillo p = (unsigned char *)data_ptr; 135*7d37aa17SJuan Castillo rc = md(md_info, p, data_len, hash); 136*7d37aa17SJuan Castillo if (rc != 0) { 137*7d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 138*7d37aa17SJuan Castillo goto end; 139*7d37aa17SJuan Castillo } 140*7d37aa17SJuan Castillo 141*7d37aa17SJuan Castillo /* Verify the signature */ 142*7d37aa17SJuan Castillo rc = pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash, 143*7d37aa17SJuan Castillo md_info->size, signature.p, signature.len); 144*7d37aa17SJuan Castillo if (rc != 0) { 145*7d37aa17SJuan Castillo rc = CRYPTO_ERR_SIGNATURE; 146*7d37aa17SJuan Castillo goto end; 147*7d37aa17SJuan Castillo } 148*7d37aa17SJuan Castillo 149*7d37aa17SJuan Castillo /* Signature verification success */ 150*7d37aa17SJuan Castillo rc = CRYPTO_SUCCESS; 151*7d37aa17SJuan Castillo 152*7d37aa17SJuan Castillo end: 153*7d37aa17SJuan Castillo pk_free(&pk); 154*7d37aa17SJuan Castillo return rc; 155*7d37aa17SJuan Castillo } 156*7d37aa17SJuan Castillo 157*7d37aa17SJuan Castillo /* 158*7d37aa17SJuan Castillo * Match a hash 159*7d37aa17SJuan Castillo * 160*7d37aa17SJuan Castillo * Digest info is passed in DER format following the ASN.1 structure detailed 161*7d37aa17SJuan Castillo * above. 162*7d37aa17SJuan Castillo */ 163*7d37aa17SJuan Castillo static int verify_hash(void *data_ptr, unsigned int data_len, 164*7d37aa17SJuan Castillo void *digest_info_ptr, unsigned int digest_info_len) 165*7d37aa17SJuan Castillo { 166*7d37aa17SJuan Castillo asn1_buf hash_oid, params; 167*7d37aa17SJuan Castillo md_type_t md_alg; 168*7d37aa17SJuan Castillo const md_info_t *md_info; 169*7d37aa17SJuan Castillo unsigned char *p, *end, *hash; 170*7d37aa17SJuan Castillo unsigned char data_hash[POLARSSL_MD_MAX_SIZE]; 171*7d37aa17SJuan Castillo size_t len; 172*7d37aa17SJuan Castillo int rc; 173*7d37aa17SJuan Castillo 174*7d37aa17SJuan Castillo /* Digest info should be an ASN1_SEQUENCE */ 175*7d37aa17SJuan Castillo p = (unsigned char *)digest_info_ptr; 176*7d37aa17SJuan Castillo end = (unsigned char *)(digest_info_ptr + digest_info_len); 177*7d37aa17SJuan Castillo rc = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); 178*7d37aa17SJuan Castillo if (rc != 0) { 179*7d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 180*7d37aa17SJuan Castillo } 181*7d37aa17SJuan Castillo 182*7d37aa17SJuan Castillo /* Get the hash algorithm */ 183*7d37aa17SJuan Castillo rc = asn1_get_alg(&p, end, &hash_oid, ¶ms); 184*7d37aa17SJuan Castillo if (rc != 0) { 185*7d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 186*7d37aa17SJuan Castillo } 187*7d37aa17SJuan Castillo 188*7d37aa17SJuan Castillo rc = oid_get_md_alg(&hash_oid, &md_alg); 189*7d37aa17SJuan Castillo if (rc != 0) { 190*7d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 191*7d37aa17SJuan Castillo } 192*7d37aa17SJuan Castillo 193*7d37aa17SJuan Castillo md_info = md_info_from_type(md_alg); 194*7d37aa17SJuan Castillo if (md_info == NULL) { 195*7d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 196*7d37aa17SJuan Castillo } 197*7d37aa17SJuan Castillo 198*7d37aa17SJuan Castillo /* Hash should be octet string type */ 199*7d37aa17SJuan Castillo rc = asn1_get_tag(&p, end, &len, ASN1_OCTET_STRING); 200*7d37aa17SJuan Castillo if (rc != 0) { 201*7d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 202*7d37aa17SJuan Castillo } 203*7d37aa17SJuan Castillo 204*7d37aa17SJuan Castillo /* Length of hash must match the algorithm's size */ 205*7d37aa17SJuan Castillo if (len != md_info->size) { 206*7d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 207*7d37aa17SJuan Castillo } 208*7d37aa17SJuan Castillo hash = p; 209*7d37aa17SJuan Castillo 210*7d37aa17SJuan Castillo /* Calculate the hash of the data */ 211*7d37aa17SJuan Castillo p = (unsigned char *)data_ptr; 212*7d37aa17SJuan Castillo rc = md(md_info, p, data_len, data_hash); 213*7d37aa17SJuan Castillo if (rc != 0) { 214*7d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 215*7d37aa17SJuan Castillo } 216*7d37aa17SJuan Castillo 217*7d37aa17SJuan Castillo /* Compare values */ 218*7d37aa17SJuan Castillo rc = memcmp(data_hash, hash, md_info->size); 219*7d37aa17SJuan Castillo if (rc != 0) { 220*7d37aa17SJuan Castillo return CRYPTO_ERR_HASH; 221*7d37aa17SJuan Castillo } 222*7d37aa17SJuan Castillo 223*7d37aa17SJuan Castillo return CRYPTO_SUCCESS; 224*7d37aa17SJuan Castillo } 225*7d37aa17SJuan Castillo 226*7d37aa17SJuan Castillo /* 227*7d37aa17SJuan Castillo * Register crypto library descriptor 228*7d37aa17SJuan Castillo */ 229*7d37aa17SJuan Castillo REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash); 230