]> git.baikalelectronics.ru Git - arm-tf.git/commitdiff
drivers: crypto: Add authenticated decryption framework
authorSumit Garg <sumit.garg@linaro.org>
Fri, 15 Nov 2019 05:13:00 +0000 (10:43 +0530)
committerSumit Garg <sumit.garg@linaro.org>
Fri, 6 Mar 2020 11:10:37 +0000 (16:40 +0530)
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

Makefile
docs/getting_started/build-options.rst
drivers/auth/crypto_mod.c
drivers/auth/cryptocell/712/cryptocell_crypto.c
drivers/auth/mbedtls/mbedtls_common.mk
drivers/auth/mbedtls/mbedtls_crypto.c
include/drivers/auth/crypto_mod.h
include/drivers/auth/mbedtls/mbedtls_config.h
include/plat/common/platform.h
make_helpers/defaults.mk

index f3cb9be6b70625e07d56eadd857279135a9205d0..f7ae5ea506ffa5457824cd749760e6f16d9d24e3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -623,7 +623,7 @@ endif
 
 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 @@ ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
     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,CTX_INCLUDE_PAUTH_REGS))
 $(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))
index da5dcbf894178b3796f8b0ea6a25d6453eb5bf9a..af4895efcb98b505d7352b80e5dab7a04e31c7c0 100644 (file)
@@ -160,6 +160,12 @@ Common build options
 -  ``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.
index 110c5045fd09c69a1df702c075ae707de627f82c..c63ff080f9a9df61b11aa89ef7c91cb8002c26d4 100644 (file)
@@ -124,3 +124,35 @@ int crypto_mod_calc_hash(unsigned int alg, void *data_ptr,
        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);
+}
index 25eb6bcb6d9384303eddd1b1000e8a5b0e77867b..cf43175348232aea4f8eae169575253a6509cc78 100644 (file)
@@ -301,5 +301,5 @@ static int verify_hash(void *data_ptr, unsigned int data_len,
 /*
  * 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);
 
index 4b83015417b1c3ed1b1b8c8b7938d4bae5d4fce6..044b368bc0b8dc4ab5e023dd8674319ee519ae5f 100644 (file)
@@ -23,13 +23,17 @@ MBEDTLS_SOURCES     +=              drivers/auth/mbedtls/mbedtls_common.c
 
 
 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 @@ else
     $(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))
 
index 04fbc648b9d9f096e10e684005fca5e925ce6eea..2a9801497c2aec58beedfeb41d954adda51e7cff 100644 (file)
@@ -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 @@ int calc_hash(unsigned int alg, void *data_ptr,
 }
 #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 */
index f211035d707a5c9fa8c4bf78c82ac675fefbce7b..71cf67306da51c5ae574a9501f4284f098f35cc6 100644 (file)
@@ -13,9 +13,18 @@ enum crypto_ret_value {
        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 @@ typedef struct crypto_lib_desc_s {
                         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 @@ int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len,
                                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 @@ int crypto_mod_calc_hash(unsigned int alg, void *data_ptr,
 
 /* 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 */
 
index 6e179bbd1e3c442a8419ce13c98326e563c97e3f..dc00da7d60c7cb482ec932639b66805e51b02c08 100644 (file)
 #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
 
index f5bd298c5ae9df64985307cd670f0ec7a5bb1794..06b334d705e4497e1f67fe8bb77c126ef3b8bcfe 100644 (file)
@@ -36,6 +36,15 @@ struct sp_res_desc;
    ROTPK is not deployed */
 #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
  ******************************************************************************/
index 9273469e258a66753a5d18d631a30a200148b330..012760733a04aad2d939d328f9e644262302f100 100644 (file)
@@ -65,6 +65,9 @@ CTX_INCLUDE_PAUTH_REGS                := 0
 # Debug build
 DEBUG                          := 0
 
+# By default disable authenticated decryption support.
+DECRYPTION_SUPPORT             := none
+
 # Build platform
 DEFAULT_PLAT                   := fvp