1 /* 2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <crypto_mod.h> 8 #include <debug.h> 9 #include <mbedtls_common.h> 10 #include <stddef.h> 11 #include <string.h> 12 13 /* mbed TLS headers */ 14 #include <mbedtls/md.h> 15 #include <mbedtls/memory_buffer_alloc.h> 16 #include <mbedtls/oid.h> 17 #include <mbedtls/platform.h> 18 19 #define LIB_NAME "mbed TLS" 20 21 /* 22 * AlgorithmIdentifier ::= SEQUENCE { 23 * algorithm OBJECT IDENTIFIER, 24 * parameters ANY DEFINED BY algorithm OPTIONAL 25 * } 26 * 27 * SubjectPublicKeyInfo ::= SEQUENCE { 28 * algorithm AlgorithmIdentifier, 29 * subjectPublicKey BIT STRING 30 * } 31 * 32 * DigestInfo ::= SEQUENCE { 33 * digestAlgorithm AlgorithmIdentifier, 34 * digest OCTET STRING 35 * } 36 */ 37 38 /* 39 * Initialize the library and export the descriptor 40 */ 41 static void init(void) 42 { 43 /* Initialize mbed TLS */ 44 mbedtls_init(); 45 } 46 47 /* 48 * Verify a signature. 49 * 50 * Parameters are passed using the DER encoding format following the ASN.1 51 * structures detailed above. 52 */ 53 static int verify_signature(void *data_ptr, unsigned int data_len, 54 void *sig_ptr, unsigned int sig_len, 55 void *sig_alg, unsigned int sig_alg_len, 56 void *pk_ptr, unsigned int pk_len) 57 { 58 mbedtls_asn1_buf sig_oid, sig_params; 59 mbedtls_asn1_buf signature; 60 mbedtls_md_type_t md_alg; 61 mbedtls_pk_type_t pk_alg; 62 mbedtls_pk_context pk = {0}; 63 int rc; 64 void *sig_opts = NULL; 65 const mbedtls_md_info_t *md_info; 66 unsigned char *p, *end; 67 unsigned char hash[MBEDTLS_MD_MAX_SIZE]; 68 69 /* Get pointers to signature OID and parameters */ 70 p = (unsigned char *)sig_alg; 71 end = (unsigned char *)(p + sig_alg_len); 72 rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params); 73 if (rc != 0) { 74 return CRYPTO_ERR_SIGNATURE; 75 } 76 77 /* Get the actual signature algorithm (MD + PK) */ 78 rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts); 79 if (rc != 0) { 80 return CRYPTO_ERR_SIGNATURE; 81 } 82 83 /* Parse the public key */ 84 mbedtls_pk_init(&pk); 85 p = (unsigned char *)pk_ptr; 86 end = (unsigned char *)(p + pk_len); 87 rc = mbedtls_pk_parse_subpubkey(&p, end, &pk); 88 if (rc != 0) { 89 rc = CRYPTO_ERR_SIGNATURE; 90 goto end2; 91 } 92 93 /* Get the signature (bitstring) */ 94 p = (unsigned char *)sig_ptr; 95 end = (unsigned char *)(p + sig_len); 96 signature.tag = *p; 97 rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len); 98 if (rc != 0) { 99 rc = CRYPTO_ERR_SIGNATURE; 100 goto end1; 101 } 102 signature.p = p; 103 104 /* Calculate the hash of the data */ 105 md_info = mbedtls_md_info_from_type(md_alg); 106 if (md_info == NULL) { 107 rc = CRYPTO_ERR_SIGNATURE; 108 goto end1; 109 } 110 p = (unsigned char *)data_ptr; 111 rc = mbedtls_md(md_info, p, data_len, hash); 112 if (rc != 0) { 113 rc = CRYPTO_ERR_SIGNATURE; 114 goto end1; 115 } 116 117 /* Verify the signature */ 118 rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash, 119 mbedtls_md_get_size(md_info), 120 signature.p, signature.len); 121 if (rc != 0) { 122 rc = CRYPTO_ERR_SIGNATURE; 123 goto end1; 124 } 125 126 /* Signature verification success */ 127 rc = CRYPTO_SUCCESS; 128 129 end1: 130 mbedtls_pk_free(&pk); 131 end2: 132 mbedtls_free(sig_opts); 133 return rc; 134 } 135 136 /* 137 * Match a hash 138 * 139 * Digest info is passed in DER format following the ASN.1 structure detailed 140 * above. 141 */ 142 static int verify_hash(void *data_ptr, unsigned int data_len, 143 void *digest_info_ptr, unsigned int digest_info_len) 144 { 145 mbedtls_asn1_buf hash_oid, params; 146 mbedtls_md_type_t md_alg; 147 const mbedtls_md_info_t *md_info; 148 unsigned char *p, *end, *hash; 149 unsigned char data_hash[MBEDTLS_MD_MAX_SIZE]; 150 size_t len; 151 int rc; 152 153 /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ 154 p = (unsigned char *)digest_info_ptr; 155 end = p + digest_info_len; 156 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 157 MBEDTLS_ASN1_SEQUENCE); 158 if (rc != 0) { 159 return CRYPTO_ERR_HASH; 160 } 161 162 /* Get the hash algorithm */ 163 rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); 164 if (rc != 0) { 165 return CRYPTO_ERR_HASH; 166 } 167 168 rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); 169 if (rc != 0) { 170 return CRYPTO_ERR_HASH; 171 } 172 173 md_info = mbedtls_md_info_from_type(md_alg); 174 if (md_info == NULL) { 175 return CRYPTO_ERR_HASH; 176 } 177 178 /* Hash should be octet string type */ 179 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); 180 if (rc != 0) { 181 return CRYPTO_ERR_HASH; 182 } 183 184 /* Length of hash must match the algorithm's size */ 185 if (len != mbedtls_md_get_size(md_info)) { 186 return CRYPTO_ERR_HASH; 187 } 188 hash = p; 189 190 /* Calculate the hash of the data */ 191 p = (unsigned char *)data_ptr; 192 rc = mbedtls_md(md_info, p, data_len, data_hash); 193 if (rc != 0) { 194 return CRYPTO_ERR_HASH; 195 } 196 197 /* Compare values */ 198 rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info)); 199 if (rc != 0) { 200 return CRYPTO_ERR_HASH; 201 } 202 203 return CRYPTO_SUCCESS; 204 } 205 206 /* 207 * Register crypto library descriptor 208 */ 209 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash); 210