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