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