drivers: crypto: Add authenticated decryption framework
Add framework for autheticated decryption of data. Currently this
patch optionally imports mbedtls library as a backend if build option
"DECRYPTION_SUPPORT = aes_gcm" is set to perform authenticated decryption
using AES-GCM algorithm.
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
Change-Id: I2966f0e79033151012bf4ffc66f484cd949e7271
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 <assert.h>
#include <stddef.h>
#include <string.h>
/* mbed TLS headers */
+#include <mbedtls/gcm.h>
#include <mbedtls/md.h>
#include <mbedtls/memory_buffer_alloc.h>
#include <mbedtls/oid.h>
@@ -17,6 +19,7 @@
#include <drivers/auth/crypto_mod.h>
#include <drivers/auth/mbedtls/mbedtls_common.h>
#include <drivers/auth/mbedtls/mbedtls_config.h>
+#include <plat/common/platform.h>
#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, 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);
+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