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