diff --git a/Makefile b/Makefile index f3cb9be..f7ae5ea 100644 --- a/Makefile +++ b/Makefile @@ -623,7 +623,7 @@ ifeq ($(MEASURED_BOOT),1) ifneq (${TRUSTED_BOARD_BOOT},1) - $(error MEASURED_BOOT requires TRUSTED_BOARD_BOOT=1") + $(error MEASURED_BOOT requires TRUSTED_BOARD_BOOT=1) else $(info MEASURED_BOOT is an experimental feature) endif @@ -635,6 +635,14 @@ endif endif +ifneq (${DECRYPTION_SUPPORT},none) + ifeq (${TRUSTED_BOARD_BOOT}, 0) + $(error TRUSTED_BOARD_BOOT must be enabled for DECRYPTION_SUPPORT to be set) + else + $(info DECRYPTION_SUPPORT is an experimental feature) + endif +endif + ################################################################################ # Process platform overrideable behaviour ################################################################################ @@ -843,6 +851,7 @@ $(eval $(call add_define,EL3_EXCEPTION_HANDLING)) $(eval $(call add_define,CTX_INCLUDE_MTE_REGS)) $(eval $(call add_define,CTX_INCLUDE_EL2_REGS)) +$(eval $(call add_define,DECRYPTION_SUPPORT_${DECRYPTION_SUPPORT})) $(eval $(call add_define,ENABLE_AMU)) $(eval $(call add_define,ENABLE_ASSERTIONS)) $(eval $(call add_define,ENABLE_BTI)) diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst index da5dcbf..af4895e 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -160,6 +160,12 @@ - ``DEBUG``: Chooses between a debug and release build. It can take either 0 (release) or 1 (debug) as values. 0 is the default. +- ``DECRYPTION_SUPPORT``: This build flag enables the user to select the + authenticated decryption algorithm to be used to decrypt firmware/s during + boot. It accepts 2 values: ``aes_gcm`` and ``none``. The default value of + this flag is ``none`` to disable firmware decryption which is an optional + feature as per TBBR. Also, it is an experimental feature. + - ``DISABLE_BIN_GENERATION``: Boolean option to disable the generation of the binary image. If set to 1, then only the ELF image is built. 0 is the default. diff --git a/drivers/auth/crypto_mod.c b/drivers/auth/crypto_mod.c index 110c504..c63ff08 100644 --- a/drivers/auth/crypto_mod.c +++ b/drivers/auth/crypto_mod.c @@ -124,3 +124,35 @@ return crypto_lib_desc.calc_hash(alg, data_ptr, data_len, output); } #endif /* MEASURED_BOOT */ + +/* + * Authenticated decryption of data + * + * Parameters: + * + * dec_algo: authenticated decryption algorithm + * data_ptr, len: data to be decrypted (inout param) + * key, key_len, key_flags: symmetric decryption key + * iv, iv_len: initialization vector + * tag, tag_len: authentication tag + */ +int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, + size_t len, const void *key, unsigned int key_len, + unsigned int key_flags, const void *iv, + unsigned int iv_len, const void *tag, + unsigned int tag_len) +{ + assert(crypto_lib_desc.auth_decrypt != NULL); + assert(data_ptr != NULL); + assert(len != 0U); + assert(key != NULL); + assert(key_len != 0U); + assert(iv != NULL); + assert((iv_len != 0U) && (iv_len <= CRYPTO_MAX_IV_SIZE)); + assert(tag != NULL); + assert((tag_len != 0U) && (tag_len <= CRYPTO_MAX_TAG_SIZE)); + + return crypto_lib_desc.auth_decrypt(dec_algo, data_ptr, len, key, + key_len, key_flags, iv, iv_len, tag, + tag_len); +} diff --git a/drivers/auth/cryptocell/712/cryptocell_crypto.c b/drivers/auth/cryptocell/712/cryptocell_crypto.c index 25eb6bc..cf43175 100644 --- a/drivers/auth/cryptocell/712/cryptocell_crypto.c +++ b/drivers/auth/cryptocell/712/cryptocell_crypto.c @@ -301,5 +301,5 @@ /* * Register crypto library descriptor */ -REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash); +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk index 4b83015..044b368 100644 --- a/drivers/auth/mbedtls/mbedtls_common.mk +++ b/drivers/auth/mbedtls/mbedtls_common.mk @@ -23,13 +23,17 @@ LIBMBEDTLS_SRCS := $(addprefix ${MBEDTLS_DIR}/library/, \ + aes.c \ asn1parse.c \ asn1write.c \ + cipher.c \ + cipher_wrap.c \ memory_buffer_alloc.c \ oid.c \ platform.c \ platform_util.c \ bignum.c \ + gcm.c \ md.c \ md_wrap.c \ pk.c \ @@ -87,11 +91,17 @@ $(error "TF_MBEDTLS_KEY_ALG=${TF_MBEDTLS_KEY_ALG} not supported on mbed TLS") endif +ifeq (${DECRYPTION_SUPPORT}, aes_gcm) + TF_MBEDTLS_USE_AES_GCM := 1 +else + TF_MBEDTLS_USE_AES_GCM := 0 +endif + # Needs to be set to drive mbed TLS configuration correctly $(eval $(call add_define,TF_MBEDTLS_KEY_ALG_ID)) $(eval $(call add_define,TF_MBEDTLS_KEY_SIZE)) $(eval $(call add_define,TF_MBEDTLS_HASH_ALG_ID)) - +$(eval $(call add_define,TF_MBEDTLS_USE_AES_GCM)) $(eval $(call MAKE_LIB,mbedtls)) diff --git a/drivers/auth/mbedtls/mbedtls_crypto.c b/drivers/auth/mbedtls/mbedtls_crypto.c index 04fbc64..2a98014 100644 --- a/drivers/auth/mbedtls/mbedtls_crypto.c +++ b/drivers/auth/mbedtls/mbedtls_crypto.c @@ -4,10 +4,12 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include #include #include /* mbed TLS headers */ +#include #include #include #include @@ -17,6 +19,7 @@ #include #include #include +#include #define LIB_NAME "mbed TLS" @@ -226,11 +229,121 @@ } #endif /* MEASURED_BOOT */ +#if TF_MBEDTLS_USE_AES_GCM +/* + * Stack based buffer allocation for decryption operation. It could + * be configured to balance stack usage vs execution speed. + */ +#define DEC_OP_BUF_SIZE 128 + +static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key, + unsigned int key_len, const void *iv, + unsigned int iv_len, const void *tag, + unsigned int tag_len) +{ + mbedtls_gcm_context ctx; + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + unsigned char buf[DEC_OP_BUF_SIZE]; + unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE]; + unsigned char *pt = data_ptr; + size_t dec_len; + int diff, i, rc; + + mbedtls_gcm_init(&ctx); + + rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8); + if (rc != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0); + if (rc != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + while (len > 0) { + dec_len = MIN(sizeof(buf), len); + + rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf); + if (rc != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + memcpy(pt, buf, dec_len); + pt += dec_len; + len -= dec_len; + } + + rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf)); + if (rc != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + /* Check tag in "constant-time" */ + for (diff = 0, i = 0; i < tag_len; i++) + diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i]; + + if (diff != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + /* GCM decryption success */ + rc = CRYPTO_SUCCESS; + +exit_gcm: + mbedtls_gcm_free(&ctx); + return rc; +} + +/* + * Authenticated decryption of an image + */ +static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, + size_t len, const void *key, unsigned int key_len, + unsigned int key_flags, const void *iv, + unsigned int iv_len, const void *tag, + unsigned int tag_len) +{ + int rc; + + assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0); + + switch (dec_algo) { + case CRYPTO_GCM_DECRYPT: + rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len, + tag, tag_len); + if (rc != 0) + return rc; + break; + default: + return CRYPTO_ERR_DECRYPTION; + } + + return CRYPTO_SUCCESS; +} +#endif /* TF_MBEDTLS_USE_AES_GCM */ + /* * Register crypto library descriptor */ #if MEASURED_BOOT -REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash); +#if TF_MBEDTLS_USE_AES_GCM +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, + auth_decrypt); #else -REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash); +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, + NULL); +#endif +#else /* MEASURED_BOOT */ +#if TF_MBEDTLS_USE_AES_GCM +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, + auth_decrypt); +#else +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); +#endif #endif /* MEASURED_BOOT */ diff --git a/include/drivers/auth/crypto_mod.h b/include/drivers/auth/crypto_mod.h index f211035..71cf673 100644 --- a/include/drivers/auth/crypto_mod.h +++ b/include/drivers/auth/crypto_mod.h @@ -13,9 +13,18 @@ CRYPTO_ERR_INIT, CRYPTO_ERR_HASH, CRYPTO_ERR_SIGNATURE, + CRYPTO_ERR_DECRYPTION, CRYPTO_ERR_UNKNOWN }; +#define CRYPTO_MAX_IV_SIZE 16U +#define CRYPTO_MAX_TAG_SIZE 16U + +/* Decryption algorithm */ +enum crypto_dec_algo { + CRYPTO_GCM_DECRYPT = 0 +}; + /* * Cryptographic library descriptor */ @@ -44,6 +53,15 @@ unsigned int data_len, unsigned char *output); #endif /* MEASURED_BOOT */ + /* + * Authenticated decryption. Return one of the + * 'enum crypto_ret_value' options. + */ + int (*auth_decrypt)(enum crypto_dec_algo dec_algo, void *data_ptr, + size_t len, const void *key, unsigned int key_len, + unsigned int key_flags, const void *iv, + unsigned int iv_len, const void *tag, + unsigned int tag_len); } crypto_lib_desc_t; /* Public functions */ @@ -54,6 +72,11 @@ void *pk_ptr, unsigned int pk_len); int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len, void *digest_info_ptr, unsigned int digest_info_len); +int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, + size_t len, const void *key, unsigned int key_len, + unsigned int key_flags, const void *iv, + unsigned int iv_len, const void *tag, + unsigned int tag_len); #if MEASURED_BOOT int crypto_mod_calc_hash(unsigned int alg, void *data_ptr, @@ -61,21 +84,24 @@ /* Macro to register a cryptographic library */ #define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \ - _calc_hash) \ + _calc_hash, _auth_decrypt) \ const crypto_lib_desc_t crypto_lib_desc = { \ .name = _name, \ .init = _init, \ .verify_signature = _verify_signature, \ .verify_hash = _verify_hash, \ - .calc_hash = _calc_hash \ + .calc_hash = _calc_hash, \ + .auth_decrypt = _auth_decrypt \ } #else -#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash) \ +#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \ + _auth_decrypt) \ const crypto_lib_desc_t crypto_lib_desc = { \ .name = _name, \ .init = _init, \ .verify_signature = _verify_signature, \ - .verify_hash = _verify_hash \ + .verify_hash = _verify_hash, \ + .auth_decrypt = _auth_decrypt \ } #endif /* MEASURED_BOOT */ diff --git a/include/drivers/auth/mbedtls/mbedtls_config.h b/include/drivers/auth/mbedtls/mbedtls_config.h index 6e179bb..dc00da7 100644 --- a/include/drivers/auth/mbedtls/mbedtls_config.h +++ b/include/drivers/auth/mbedtls/mbedtls_config.h @@ -79,6 +79,12 @@ #define MBEDTLS_X509_USE_C #define MBEDTLS_X509_CRT_PARSE_C +#if TF_MBEDTLS_USE_AES_GCM +#define MBEDTLS_AES_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_GCM_C +#endif + /* MPI / BIGNUM options */ #define MBEDTLS_MPI_WINDOW_SIZE 2 diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index f5bd298..06b334d 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -37,6 +37,15 @@ #define ROTPK_NOT_DEPLOYED (1 << 1) /******************************************************************************* + * plat_get_enc_key_info() flags + ******************************************************************************/ +/* + * Flag used to notify caller that information provided in key buffer is an + * identifier rather than an actual key. + */ +#define ENC_KEY_IS_IDENTIFIER (1 << 0) + +/******************************************************************************* * Function declarations ******************************************************************************/ /******************************************************************************* diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 9273469..0127607 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -65,6 +65,9 @@ # Debug build DEBUG := 0 +# By default disable authenticated decryption support. +DECRYPTION_SUPPORT := none + # Build platform DEFAULT_PLAT := fvp