1 /* 2 * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <stddef.h> 9 #include <string.h> 10 11 /* mbed TLS headers */ 12 #include <mbedtls/gcm.h> 13 #include <mbedtls/md.h> 14 #include <mbedtls/memory_buffer_alloc.h> 15 #include <mbedtls/oid.h> 16 #include <mbedtls/platform.h> 17 #include <mbedtls/x509.h> 18 19 #include <common/debug.h> 20 #include <drivers/auth/crypto_mod.h> 21 #include <drivers/auth/mbedtls/mbedtls_common.h> 22 #include <drivers/auth/mbedtls/mbedtls_config.h> 23 #include <plat/common/platform.h> 24 25 #define LIB_NAME "mbed TLS" 26 27 /* 28 * AlgorithmIdentifier ::= SEQUENCE { 29 * algorithm OBJECT IDENTIFIER, 30 * parameters ANY DEFINED BY algorithm OPTIONAL 31 * } 32 * 33 * SubjectPublicKeyInfo ::= SEQUENCE { 34 * algorithm AlgorithmIdentifier, 35 * subjectPublicKey BIT STRING 36 * } 37 * 38 * DigestInfo ::= SEQUENCE { 39 * digestAlgorithm AlgorithmIdentifier, 40 * digest OCTET STRING 41 * } 42 */ 43 44 /* 45 * Initialize the library and export the descriptor 46 */ 47 static void init(void) 48 { 49 /* Initialize mbed TLS */ 50 mbedtls_init(); 51 } 52 53 /* 54 * Verify a signature. 55 * 56 * Parameters are passed using the DER encoding format following the ASN.1 57 * structures detailed above. 58 */ 59 static int verify_signature(void *data_ptr, unsigned int data_len, 60 void *sig_ptr, unsigned int sig_len, 61 void *sig_alg, unsigned int sig_alg_len, 62 void *pk_ptr, unsigned int pk_len) 63 { 64 mbedtls_asn1_buf sig_oid, sig_params; 65 mbedtls_asn1_buf signature; 66 mbedtls_md_type_t md_alg; 67 mbedtls_pk_type_t pk_alg; 68 mbedtls_pk_context pk = {0}; 69 int rc; 70 void *sig_opts = NULL; 71 const mbedtls_md_info_t *md_info; 72 unsigned char *p, *end; 73 unsigned char hash[MBEDTLS_MD_MAX_SIZE]; 74 75 /* Get pointers to signature OID and parameters */ 76 p = (unsigned char *)sig_alg; 77 end = (unsigned char *)(p + sig_alg_len); 78 rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params); 79 if (rc != 0) { 80 return CRYPTO_ERR_SIGNATURE; 81 } 82 83 /* Get the actual signature algorithm (MD + PK) */ 84 rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts); 85 if (rc != 0) { 86 return CRYPTO_ERR_SIGNATURE; 87 } 88 89 /* Parse the public key */ 90 mbedtls_pk_init(&pk); 91 p = (unsigned char *)pk_ptr; 92 end = (unsigned char *)(p + pk_len); 93 rc = mbedtls_pk_parse_subpubkey(&p, end, &pk); 94 if (rc != 0) { 95 rc = CRYPTO_ERR_SIGNATURE; 96 goto end2; 97 } 98 99 /* Get the signature (bitstring) */ 100 p = (unsigned char *)sig_ptr; 101 end = (unsigned char *)(p + sig_len); 102 signature.tag = *p; 103 rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len); 104 if (rc != 0) { 105 rc = CRYPTO_ERR_SIGNATURE; 106 goto end1; 107 } 108 signature.p = p; 109 110 /* Calculate the hash of the data */ 111 md_info = mbedtls_md_info_from_type(md_alg); 112 if (md_info == NULL) { 113 rc = CRYPTO_ERR_SIGNATURE; 114 goto end1; 115 } 116 p = (unsigned char *)data_ptr; 117 rc = mbedtls_md(md_info, p, data_len, hash); 118 if (rc != 0) { 119 rc = CRYPTO_ERR_SIGNATURE; 120 goto end1; 121 } 122 123 /* Verify the signature */ 124 rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash, 125 mbedtls_md_get_size(md_info), 126 signature.p, signature.len); 127 if (rc != 0) { 128 rc = CRYPTO_ERR_SIGNATURE; 129 goto end1; 130 } 131 132 /* Signature verification success */ 133 rc = CRYPTO_SUCCESS; 134 135 end1: 136 mbedtls_pk_free(&pk); 137 end2: 138 mbedtls_free(sig_opts); 139 return rc; 140 } 141 142 /* 143 * Match a hash 144 * 145 * Digest info is passed in DER format following the ASN.1 structure detailed 146 * above. 147 */ 148 static int verify_hash(void *data_ptr, unsigned int data_len, 149 void *digest_info_ptr, unsigned int digest_info_len) 150 { 151 mbedtls_asn1_buf hash_oid, params; 152 mbedtls_md_type_t md_alg; 153 const mbedtls_md_info_t *md_info; 154 unsigned char *p, *end, *hash; 155 unsigned char data_hash[MBEDTLS_MD_MAX_SIZE]; 156 size_t len; 157 int rc; 158 159 /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ 160 p = (unsigned char *)digest_info_ptr; 161 end = p + digest_info_len; 162 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 163 MBEDTLS_ASN1_SEQUENCE); 164 if (rc != 0) { 165 return CRYPTO_ERR_HASH; 166 } 167 168 /* Get the hash algorithm */ 169 rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); 170 if (rc != 0) { 171 return CRYPTO_ERR_HASH; 172 } 173 174 rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); 175 if (rc != 0) { 176 return CRYPTO_ERR_HASH; 177 } 178 179 md_info = mbedtls_md_info_from_type(md_alg); 180 if (md_info == NULL) { 181 return CRYPTO_ERR_HASH; 182 } 183 184 /* Hash should be octet string type */ 185 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); 186 if (rc != 0) { 187 return CRYPTO_ERR_HASH; 188 } 189 190 /* Length of hash must match the algorithm's size */ 191 if (len != mbedtls_md_get_size(md_info)) { 192 return CRYPTO_ERR_HASH; 193 } 194 hash = p; 195 196 /* Calculate the hash of the data */ 197 p = (unsigned char *)data_ptr; 198 rc = mbedtls_md(md_info, p, data_len, data_hash); 199 if (rc != 0) { 200 return CRYPTO_ERR_HASH; 201 } 202 203 /* Compare values */ 204 rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info)); 205 if (rc != 0) { 206 return CRYPTO_ERR_HASH; 207 } 208 209 return CRYPTO_SUCCESS; 210 } 211 212 #if MEASURED_BOOT 213 /* 214 * Calculate a hash 215 * 216 * output points to the computed hash 217 */ 218 int calc_hash(unsigned int alg, void *data_ptr, 219 unsigned int data_len, unsigned char *output) 220 { 221 const mbedtls_md_info_t *md_info; 222 223 md_info = mbedtls_md_info_from_type((mbedtls_md_type_t)alg); 224 if (md_info == NULL) { 225 return CRYPTO_ERR_HASH; 226 } 227 228 /* Calculate the hash of the data */ 229 return mbedtls_md(md_info, data_ptr, data_len, output); 230 } 231 #endif /* MEASURED_BOOT */ 232 233 #if TF_MBEDTLS_USE_AES_GCM 234 /* 235 * Stack based buffer allocation for decryption operation. It could 236 * be configured to balance stack usage vs execution speed. 237 */ 238 #define DEC_OP_BUF_SIZE 128 239 240 static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key, 241 unsigned int key_len, const void *iv, 242 unsigned int iv_len, const void *tag, 243 unsigned int tag_len) 244 { 245 mbedtls_gcm_context ctx; 246 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; 247 unsigned char buf[DEC_OP_BUF_SIZE]; 248 unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE]; 249 unsigned char *pt = data_ptr; 250 size_t dec_len; 251 int diff, i, rc; 252 253 mbedtls_gcm_init(&ctx); 254 255 rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8); 256 if (rc != 0) { 257 rc = CRYPTO_ERR_DECRYPTION; 258 goto exit_gcm; 259 } 260 261 rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0); 262 if (rc != 0) { 263 rc = CRYPTO_ERR_DECRYPTION; 264 goto exit_gcm; 265 } 266 267 while (len > 0) { 268 dec_len = MIN(sizeof(buf), len); 269 270 rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf); 271 if (rc != 0) { 272 rc = CRYPTO_ERR_DECRYPTION; 273 goto exit_gcm; 274 } 275 276 memcpy(pt, buf, dec_len); 277 pt += dec_len; 278 len -= dec_len; 279 } 280 281 rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf)); 282 if (rc != 0) { 283 rc = CRYPTO_ERR_DECRYPTION; 284 goto exit_gcm; 285 } 286 287 /* Check tag in "constant-time" */ 288 for (diff = 0, i = 0; i < tag_len; i++) 289 diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i]; 290 291 if (diff != 0) { 292 rc = CRYPTO_ERR_DECRYPTION; 293 goto exit_gcm; 294 } 295 296 /* GCM decryption success */ 297 rc = CRYPTO_SUCCESS; 298 299 exit_gcm: 300 mbedtls_gcm_free(&ctx); 301 return rc; 302 } 303 304 /* 305 * Authenticated decryption of an image 306 */ 307 static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, 308 size_t len, const void *key, unsigned int key_len, 309 unsigned int key_flags, const void *iv, 310 unsigned int iv_len, const void *tag, 311 unsigned int tag_len) 312 { 313 int rc; 314 315 assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0); 316 317 switch (dec_algo) { 318 case CRYPTO_GCM_DECRYPT: 319 rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len, 320 tag, tag_len); 321 if (rc != 0) 322 return rc; 323 break; 324 default: 325 return CRYPTO_ERR_DECRYPTION; 326 } 327 328 return CRYPTO_SUCCESS; 329 } 330 #endif /* TF_MBEDTLS_USE_AES_GCM */ 331 332 /* 333 * Register crypto library descriptor 334 */ 335 #if MEASURED_BOOT 336 #if TF_MBEDTLS_USE_AES_GCM 337 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 338 auth_decrypt); 339 #else 340 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 341 NULL); 342 #endif 343 #else /* MEASURED_BOOT */ 344 #if TF_MBEDTLS_USE_AES_GCM 345 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, 346 auth_decrypt); 347 #else 348 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); 349 #endif 350 #endif /* MEASURED_BOOT */ 351