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) || ((size_t)(end - p) != signature.len)) { 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 /* 174 * Digest info should be an MBEDTLS_ASN1_SEQUENCE 175 * and consume all bytes. 176 */ 177 p = (unsigned char *)digest_info_ptr; 178 end = p + digest_info_len; 179 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | 180 MBEDTLS_ASN1_SEQUENCE); 181 if (rc != 0 || ((size_t)(end - p) != len)) { 182 return CRYPTO_ERR_HASH; 183 } 184 185 /* Get the hash algorithm */ 186 rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); 187 if (rc != 0) { 188 return CRYPTO_ERR_HASH; 189 } 190 191 rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); 192 if (rc != 0) { 193 return CRYPTO_ERR_HASH; 194 } 195 196 md_info = mbedtls_md_info_from_type(md_alg); 197 if (md_info == NULL) { 198 return CRYPTO_ERR_HASH; 199 } 200 201 /* Hash should be octet string type and consume all bytes */ 202 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); 203 if ((rc != 0) || ((size_t)(end - p) != len)) { 204 return CRYPTO_ERR_HASH; 205 } 206 207 /* Length of hash must match the algorithm's size */ 208 if (len != mbedtls_md_get_size(md_info)) { 209 return CRYPTO_ERR_HASH; 210 } 211 hash = p; 212 213 /* Calculate the hash of the data */ 214 p = (unsigned char *)data_ptr; 215 rc = mbedtls_md(md_info, p, data_len, data_hash); 216 if (rc != 0) { 217 return CRYPTO_ERR_HASH; 218 } 219 220 /* Compare values */ 221 rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info)); 222 if (rc != 0) { 223 return CRYPTO_ERR_HASH; 224 } 225 226 return CRYPTO_SUCCESS; 227 } 228 #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ 229 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ 230 231 #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 232 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 233 /* 234 * Map a generic crypto message digest algorithm to the corresponding macro used 235 * by Mbed TLS. 236 */ 237 static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo) 238 { 239 switch (algo) { 240 case CRYPTO_MD_SHA512: 241 return MBEDTLS_MD_SHA512; 242 case CRYPTO_MD_SHA384: 243 return MBEDTLS_MD_SHA384; 244 case CRYPTO_MD_SHA256: 245 return MBEDTLS_MD_SHA256; 246 default: 247 /* Invalid hash algorithm. */ 248 return MBEDTLS_MD_NONE; 249 } 250 } 251 252 /* 253 * Calculate a hash 254 * 255 * output points to the computed hash 256 */ 257 static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr, 258 unsigned int data_len, 259 unsigned char output[CRYPTO_MD_MAX_SIZE]) 260 { 261 const mbedtls_md_info_t *md_info; 262 263 md_info = mbedtls_md_info_from_type(md_type(md_algo)); 264 if (md_info == NULL) { 265 return CRYPTO_ERR_HASH; 266 } 267 268 /* 269 * Calculate the hash of the data, it is safe to pass the 270 * 'output' hash buffer pointer considering its size is always 271 * bigger than or equal to MBEDTLS_MD_MAX_SIZE. 272 */ 273 return mbedtls_md(md_info, data_ptr, data_len, output); 274 } 275 #endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ 276 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ 277 278 #if TF_MBEDTLS_USE_AES_GCM 279 /* 280 * Stack based buffer allocation for decryption operation. It could 281 * be configured to balance stack usage vs execution speed. 282 */ 283 #define DEC_OP_BUF_SIZE 128 284 285 static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key, 286 unsigned int key_len, const void *iv, 287 unsigned int iv_len, const void *tag, 288 unsigned int tag_len) 289 { 290 mbedtls_gcm_context ctx; 291 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; 292 unsigned char buf[DEC_OP_BUF_SIZE]; 293 unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE]; 294 unsigned char *pt = data_ptr; 295 size_t dec_len; 296 int diff, i, rc; 297 298 mbedtls_gcm_init(&ctx); 299 300 rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8); 301 if (rc != 0) { 302 rc = CRYPTO_ERR_DECRYPTION; 303 goto exit_gcm; 304 } 305 306 rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0); 307 if (rc != 0) { 308 rc = CRYPTO_ERR_DECRYPTION; 309 goto exit_gcm; 310 } 311 312 while (len > 0) { 313 dec_len = MIN(sizeof(buf), len); 314 315 rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf); 316 if (rc != 0) { 317 rc = CRYPTO_ERR_DECRYPTION; 318 goto exit_gcm; 319 } 320 321 memcpy(pt, buf, dec_len); 322 pt += dec_len; 323 len -= dec_len; 324 } 325 326 rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf)); 327 if (rc != 0) { 328 rc = CRYPTO_ERR_DECRYPTION; 329 goto exit_gcm; 330 } 331 332 /* Check tag in "constant-time" */ 333 for (diff = 0, i = 0; i < tag_len; i++) 334 diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i]; 335 336 if (diff != 0) { 337 rc = CRYPTO_ERR_DECRYPTION; 338 goto exit_gcm; 339 } 340 341 /* GCM decryption success */ 342 rc = CRYPTO_SUCCESS; 343 344 exit_gcm: 345 mbedtls_gcm_free(&ctx); 346 return rc; 347 } 348 349 /* 350 * Authenticated decryption of an image 351 */ 352 static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, 353 size_t len, const void *key, unsigned int key_len, 354 unsigned int key_flags, const void *iv, 355 unsigned int iv_len, const void *tag, 356 unsigned int tag_len) 357 { 358 int rc; 359 360 assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0); 361 362 switch (dec_algo) { 363 case CRYPTO_GCM_DECRYPT: 364 rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len, 365 tag, tag_len); 366 if (rc != 0) 367 return rc; 368 break; 369 default: 370 return CRYPTO_ERR_DECRYPTION; 371 } 372 373 return CRYPTO_SUCCESS; 374 } 375 #endif /* TF_MBEDTLS_USE_AES_GCM */ 376 377 /* 378 * Register crypto library descriptor 379 */ 380 #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC 381 #if TF_MBEDTLS_USE_AES_GCM 382 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 383 auth_decrypt); 384 #else 385 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, 386 NULL); 387 #endif 388 #elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY 389 #if TF_MBEDTLS_USE_AES_GCM 390 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, 391 auth_decrypt); 392 #else 393 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); 394 #endif 395 #elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY 396 REGISTER_CRYPTO_LIB(LIB_NAME, init, calc_hash); 397 #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ 398