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