libmbedtls: support mbedtls HMAC algorithm
Implement HMAC function based on mbedtls.
Acked-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Edison Ai <edison.ai@arm.com>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
diff --git a/lib/libmbedtls/core/hmac.c b/lib/libmbedtls/core/hmac.c
new file mode 100644
index 0000000..391693a
--- /dev/null
+++ b/lib/libmbedtls/core/hmac.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2018, ARM Limited
+ * Copyright (C) 2019, Linaro Limited
+ */
+
+#include <assert.h>
+#include <compiler.h>
+#include <crypto/crypto.h>
+#include <crypto/crypto_impl.h>
+#include <kernel/panic.h>
+#include <mbedtls/md.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tee_api_types.h>
+#include <utee_defines.h>
+#include <util.h>
+
+struct mbed_hmac_ctx {
+ struct crypto_mac_ctx mac_ctx;
+ mbedtls_md_context_t md_ctx;
+};
+
+static const struct crypto_mac_ops mbed_hmac_ops;
+
+static struct mbed_hmac_ctx *to_hmac_ctx(struct crypto_mac_ctx *ctx)
+{
+ assert(ctx && ctx->ops == &mbed_hmac_ops);
+
+ return container_of(ctx, struct mbed_hmac_ctx, mac_ctx);
+}
+
+static TEE_Result mbed_hmac_init(struct crypto_mac_ctx *ctx,
+ const uint8_t *key, size_t len)
+{
+ if (mbedtls_md_hmac_starts(&to_hmac_ctx(ctx)->md_ctx, key, len))
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result mbed_hmac_update(struct crypto_mac_ctx *ctx,
+ const uint8_t *data, size_t len)
+{
+ if (mbedtls_md_hmac_update(&to_hmac_ctx(ctx)->md_ctx, data, len))
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result mbed_hmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest,
+ size_t len)
+{
+ struct mbed_hmac_ctx *c = to_hmac_ctx(ctx);
+ size_t hmac_size = mbedtls_md_get_size(c->md_ctx.md_info);
+ uint8_t block_digest[TEE_MAX_HASH_SIZE] = { 0 };
+ uint8_t *tmp_digest = NULL;
+
+ if (len == 0)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ if (hmac_size > len) {
+ if (hmac_size > sizeof(block_digest))
+ return TEE_ERROR_BAD_STATE;
+ tmp_digest = block_digest; /* use a tempory buffer */
+ } else {
+ tmp_digest = digest;
+ }
+
+ if (mbedtls_md_hmac_finish(&c->md_ctx, tmp_digest))
+ return TEE_ERROR_BAD_STATE;
+
+ if (hmac_size > len)
+ memcpy(digest, tmp_digest, len);
+
+ return TEE_SUCCESS;
+}
+
+static void mbed_hmac_free_ctx(struct crypto_mac_ctx *ctx)
+{
+ struct mbed_hmac_ctx *c = to_hmac_ctx(ctx);
+
+ mbedtls_md_free(&c->md_ctx);
+ free(c);
+}
+
+static void mbed_hmac_copy_state(struct crypto_mac_ctx *dst_ctx,
+ struct crypto_mac_ctx *src_ctx)
+{
+ struct mbed_hmac_ctx *src = to_hmac_ctx(src_ctx);
+ struct mbed_hmac_ctx *dst = to_hmac_ctx(dst_ctx);
+
+ if (mbedtls_md_clone(&dst->md_ctx, &src->md_ctx))
+ panic();
+}
+
+static const struct crypto_mac_ops mbed_hmac_ops = {
+ .init = mbed_hmac_init,
+ .update = mbed_hmac_update,
+ .final = mbed_hmac_final,
+ .free_ctx = mbed_hmac_free_ctx,
+ .copy_state = mbed_hmac_copy_state,
+};
+
+static TEE_Result mbed_hmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret,
+ mbedtls_md_type_t md_type)
+{
+ int mbed_res = 0;
+ struct mbed_hmac_ctx *c = NULL;
+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
+
+ if (!md_info)
+ return TEE_ERROR_NOT_SUPPORTED;
+
+ c = calloc(1, sizeof(*c));
+ if (!c)
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ c->mac_ctx.ops = &mbed_hmac_ops;
+ mbed_res = mbedtls_md_setup(&c->md_ctx, md_info, 1);
+ if (mbed_res) {
+ free(c);
+ if (mbed_res == MBEDTLS_ERR_MD_ALLOC_FAILED)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+
+ *ctx_ret = &c->mac_ctx;
+
+ return TEE_SUCCESS;
+}
+
+#if defined(CFG_CRYPTO_MD5)
+TEE_Result crypto_hmac_md5_alloc_ctx(struct crypto_mac_ctx **ctx)
+{
+ return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_MD5);
+}
+#endif
+
+#if defined(CFG_CRYPTO_SHA1)
+TEE_Result crypto_hmac_sha1_alloc_ctx(struct crypto_mac_ctx **ctx)
+{
+ return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA1);
+}
+#endif
+
+#if defined(CFG_CRYPTO_SHA224)
+TEE_Result crypto_hmac_sha224_alloc_ctx(struct crypto_mac_ctx **ctx)
+{
+ return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA224);
+}
+#endif
+
+#if defined(CFG_CRYPTO_SHA256)
+TEE_Result crypto_hmac_sha256_alloc_ctx(struct crypto_mac_ctx **ctx)
+{
+ return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA256);
+}
+#endif
+
+#if defined(CFG_CRYPTO_SHA384)
+TEE_Result crypto_hmac_sha384_alloc_ctx(struct crypto_mac_ctx **ctx)
+{
+ return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA384);
+}
+#endif
+
+#if defined(CFG_CRYPTO_SHA512)
+TEE_Result crypto_hmac_sha512_alloc_ctx(struct crypto_mac_ctx **ctx)
+{
+ return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA512);
+}
+#endif
diff --git a/lib/libmbedtls/core/stubbed.c b/lib/libmbedtls/core/stubbed.c
index 58ddcf5..2aca4e4 100644
--- a/lib/libmbedtls/core/stubbed.c
+++ b/lib/libmbedtls/core/stubbed.c
@@ -283,15 +283,6 @@
crypto_##name##_alloc_ctx(struct crypto_##type##_ctx **ctx __unused) \
{ return TEE_ERROR_NOT_IMPLEMENTED; }
-#if defined(CFG_CRYPTO_HMAC)
-CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_md5, mac)
-CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha1, mac)
-CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha224, mac)
-CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha256, mac)
-CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha384, mac)
-CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha512, mac)
-#endif
-
#if defined(CFG_CRYPTO_CMAC)
CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_cmac, mac)
#endif
diff --git a/lib/libmbedtls/core/sub.mk b/lib/libmbedtls/core/sub.mk
index 0626574..cd0bdb0 100644
--- a/lib/libmbedtls/core/sub.mk
+++ b/lib/libmbedtls/core/sub.mk
@@ -18,3 +18,5 @@
srcs-$(CFG_CRYPTO_CBC) += des_cbc.c
srcs-$(CFG_CRYPTO_CBC) += des3_cbc.c
endif
+
+srcs-$(CFG_CRYPTO_HMAC) += hmac.c
diff --git a/lib/libmbedtls/include/mbedtls_config_kernel.h b/lib/libmbedtls/include/mbedtls_config_kernel.h
index 0c8ad37..bdb34e8 100644
--- a/lib/libmbedtls/include/mbedtls_config_kernel.h
+++ b/lib/libmbedtls/include/mbedtls_config_kernel.h
@@ -37,6 +37,10 @@
#define MBEDTLS_MD_C
#endif
+#if defined(CFG_CRYPTO_HMAC)
+#define MBEDTLS_MD_C
+#endif
+
#if defined(CFG_CRYPTO_AES)
#define MBEDTLS_AES_C
#define MBEDTLS_AES_ROM_TABLES