1 /* 2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 32 #include <crypto_mod.h> 33 #include <debug.h> 34 #include <mbedtls_common.h> 35 #include <stddef.h> 36 #include <string.h> 37 38 /* mbed TLS headers */ 39 #include <mbedtls/md.h> 40 #include <mbedtls/memory_buffer_alloc.h> 41 #include <mbedtls/oid.h> 42 #include <mbedtls/platform.h> 43 44 #define LIB_NAME "mbed TLS" 45 46 /* 47 * AlgorithmIdentifier ::= SEQUENCE { 48 * algorithm OBJECT IDENTIFIER, 49 * parameters ANY DEFINED BY algorithm OPTIONAL 50 * } 51 * 52 * SubjectPublicKeyInfo ::= SEQUENCE { 53 * algorithm AlgorithmIdentifier, 54 * subjectPublicKey BIT STRING 55 * } 56 * 57 * DigestInfo ::= SEQUENCE { 58 * digestAlgorithm AlgorithmIdentifier, 59 * digest OCTET STRING 60 * } 61 */ 62 63 /* 64 * Initialize the library and export the descriptor 65 */ 66 static void init(void) 67 { 68 /* Initialize mbed TLS */ 69 mbedtls_init(); 70 } 71 72 /* 73 * Verify a signature. 74 * 75 * Parameters are passed using the DER encoding format following the ASN.1 76 * structures detailed above. 77 */ 78 static int verify_signature(void *data_ptr, unsigned int data_len, 79 void *sig_ptr, unsigned int sig_len, 80 void *sig_alg, unsigned int sig_alg_len, 81 void *pk_ptr, unsigned int pk_len) 82 { 83 mbedtls_asn1_buf sig_oid, sig_params; 84 mbedtls_asn1_buf signature; 85 mbedtls_md_type_t md_alg; 86 mbedtls_pk_type_t pk_alg; 87 mbedtls_pk_context pk; 88 int rc; 89 void *sig_opts = NULL; 90 const mbedtls_md_info_t *md_info; 91 unsigned char *p, *end; 92 unsigned char hash[MBEDTLS_MD_MAX_SIZE]; 93 94 /* Get pointers to signature OID and parameters */ 95 p = (unsigned char *)sig_alg; 96 end = (unsigned char *)(p + sig_alg_len); 97 rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params); 98 if (rc != 0) { 99 return CRYPTO_ERR_SIGNATURE; 100 } 101 102 /* Get the actual signature algorithm (MD + PK) */ 103 rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg); 104 if (rc != 0) { 105 return CRYPTO_ERR_SIGNATURE; 106 } 107 108 /* Parse the public key */ 109 mbedtls_pk_init(&pk); 110 p = (unsigned char *)pk_ptr; 111 end = (unsigned char *)(p + pk_len); 112 rc = mbedtls_pk_parse_subpubkey(&p, end, &pk); 113 if (rc != 0) { 114 return CRYPTO_ERR_SIGNATURE; 115 } 116 117 /* Get the signature (bitstring) */ 118 p = (unsigned char *)sig_ptr; 119 end = (unsigned char *)(p + sig_len); 120 signature.tag = *p; 121 rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len); 122 if (rc != 0) { 123 rc = CRYPTO_ERR_SIGNATURE; 124 goto end; 125 } 126 signature.p = p; 127 128 /* Calculate the hash of the data */ 129 md_info = mbedtls_md_info_from_type(md_alg); 130 if (md_info == NULL) { 131 rc = CRYPTO_ERR_SIGNATURE; 132 goto end; 133 } 134 p = (unsigned char *)data_ptr; 135 rc = mbedtls_md(md_info, p, data_len, hash); 136 if (rc != 0) { 137 rc = CRYPTO_ERR_SIGNATURE; 138 goto end; 139 } 140 141 /* Verify the signature */ 142 rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash, 143 mbedtls_md_get_size(md_info), 144 signature.p, signature.len); 145 if (rc != 0) { 146 rc = CRYPTO_ERR_SIGNATURE; 147 goto end; 148 } 149 150 /* Signature verification success */ 151 rc = CRYPTO_SUCCESS; 152 153 end: 154 mbedtls_pk_free(&pk); 155 return rc; 156 } 157 158 /* 159 * Match a hash 160 * 161 * Digest info is passed in DER format following the ASN.1 structure detailed 162 * above. 163 */ 164 static int verify_hash(void *data_ptr, unsigned int data_len, 165 void *digest_info_ptr, unsigned int digest_info_len) 166 { 167 mbedtls_asn1_buf hash_oid, params; 168 mbedtls_md_type_t md_alg; 169 const mbedtls_md_info_t *md_info; 170 unsigned char *p, *end, *hash; 171 unsigned char data_hash[MBEDTLS_MD_MAX_SIZE]; 172 size_t len; 173 int rc; 174 175 /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ 176 p = (unsigned char *)digest_info_ptr; 177 end = p + digest_info_len; 178 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 179 MBEDTLS_ASN1_SEQUENCE); 180 if (rc != 0) { 181 return CRYPTO_ERR_HASH; 182 } 183 184 /* Get the hash algorithm */ 185 rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); 186 if (rc != 0) { 187 return CRYPTO_ERR_HASH; 188 } 189 190 rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); 191 if (rc != 0) { 192 return CRYPTO_ERR_HASH; 193 } 194 195 md_info = mbedtls_md_info_from_type(md_alg); 196 if (md_info == NULL) { 197 return CRYPTO_ERR_HASH; 198 } 199 200 /* Hash should be octet string type */ 201 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); 202 if (rc != 0) { 203 return CRYPTO_ERR_HASH; 204 } 205 206 /* Length of hash must match the algorithm's size */ 207 if (len != mbedtls_md_get_size(md_info)) { 208 return CRYPTO_ERR_HASH; 209 } 210 hash = p; 211 212 /* Calculate the hash of the data */ 213 p = (unsigned char *)data_ptr; 214 rc = mbedtls_md(md_info, p, data_len, data_hash); 215 if (rc != 0) { 216 return CRYPTO_ERR_HASH; 217 } 218 219 /* Compare values */ 220 rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info)); 221 if (rc != 0) { 222 return CRYPTO_ERR_HASH; 223 } 224 225 return CRYPTO_SUCCESS; 226 } 227 228 /* 229 * Register crypto library descriptor 230 */ 231 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash); 232