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/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 */