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 279 md_info = mbedtls_md_info_from_type(md_type(md_algo)); 280 if (md_info == NULL) { 281 return CRYPTO_ERR_HASH; 282 } 283 284 /* 285 * Calculate the hash of the data, it is safe to pass the 286 * 'output' hash buffer pointer considering its size is always 287 * bigger than or equal to MBEDTLS_MD_MAX_SIZE. 288 */ 289 return mbedtls_md(md_info, data_ptr, data_len, output); 290 } 291 #endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 292 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ 293 294 #if TF_MBEDTLS_USE_AES_GCM 295 /* 296 * Stack based buffer allocation for decryption operation. It could 297 * be configured to balance stack usage vs execution speed. 298 */ 299 #define DEC_OP_BUF_SIZE 128 300 301 static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key, 302 unsigned int key_len, const void *iv, 303 unsigned int iv_len, const void *tag, 304 unsigned int tag_len) 305 { 306 mbedtls_gcm_context ctx; 307 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; 308 unsigned char buf[DEC_OP_BUF_SIZE]; 309 unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE]; 310 unsigned char *pt = data_ptr; 311 size_t dec_len; 312 int diff, i, rc; 313 size_t output_length __unused; 314 315 mbedtls_gcm_init(&ctx); 316 317 rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8); 318 if (rc != 0) { 319 rc = CRYPTO_ERR_DECRYPTION; 320 goto exit_gcm; 321 } 322 323 #if (MBEDTLS_VERSION_MAJOR < 3) 324 rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0); 325 #else 326 rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len); 327 #endif 328 if (rc != 0) { 329 rc = CRYPTO_ERR_DECRYPTION; 330 goto exit_gcm; 331 } 332 333 while (len > 0) { 334 dec_len = MIN(sizeof(buf), len); 335 336 #if (MBEDTLS_VERSION_MAJOR < 3) 337 rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf); 338 #else 339 rc = mbedtls_gcm_update(&ctx, pt, dec_len, buf, sizeof(buf), &output_length); 340 #endif 341 342 if (rc != 0) { 343 rc = CRYPTO_ERR_DECRYPTION; 344 goto exit_gcm; 345 } 346 347 memcpy(pt, buf, dec_len); 348 pt += dec_len; 349 len -= dec_len; 350 } 351 352 #if (MBEDTLS_VERSION_MAJOR < 3) 353 rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf)); 354 #else 355 rc = mbedtls_gcm_finish(&ctx, NULL, 0, &output_length, tag_buf, sizeof(tag_buf)); 356 #endif 357 358 if (rc != 0) { 359 rc = CRYPTO_ERR_DECRYPTION; 360 goto exit_gcm; 361 } 362 363 /* Check tag in "constant-time" */ 364 for (diff = 0, i = 0; i < tag_len; i++) 365 diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i]; 366 367 if (diff != 0) { 368 rc = CRYPTO_ERR_DECRYPTION; 369 goto exit_gcm; 370 } 371 372 /* GCM decryption success */ 373 rc = CRYPTO_SUCCESS; 374 375 exit_gcm: 376 mbedtls_gcm_free(&ctx); 377 return rc; 378 } 379 380 /* 381 * Authenticated decryption of an image 382 */ 383 static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, 384 size_t len, const void *key, unsigned int key_len, 385 unsigned int key_flags, const void *iv, 386 unsigned int iv_len, const void *tag, 387 unsigned int tag_len) 388 { 389 int rc; 390 391 assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0); 392 393 switch (dec_algo) { 394 case CRYPTO_GCM_DECRYPT: 395 rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len, 396 tag, tag_len); 397 if (rc != 0) 398 return rc; 399 break; 400 default: 401 return CRYPTO_ERR_DECRYPTION; 402 } 403 404 return CRYPTO_SUCCESS; 405 } 406 #endif /* TF_MBEDTLS_USE_AES_GCM */ 407 408 /* 409 * Register crypto library descriptor 410 */ 411 #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 412 #if TF_MBEDTLS_USE_AES_GCM 413 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 414 auth_decrypt, NULL); 415 #else 416 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 417 NULL, NULL); 418 #endif 419 #elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY 420 #if TF_MBEDTLS_USE_AES_GCM 421 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, 422 auth_decrypt, NULL); 423 #else 424 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, 425 NULL, NULL); 426 #endif 427 #elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY 428 REGISTER_CRYPTO_LIB(LIB_NAME, init, NULL, NULL, calc_hash, NULL, NULL); 429 #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ 430