aboutsummaryrefslogtreecommitdiff
path: root/core/lib
diff options
context:
space:
mode:
authorJens Wiklander <jens.wiklander@linaro.org>2019-03-08 15:22:14 +0100
committerJérôme Forissier <jerome.forissier@linaro.org>2019-03-11 17:58:04 +0100
commitf1e9b21b29bdc21a51c6c1a4b8df7eb5e2bd5189 (patch)
tree3f7280058413d43e605e867b156f86bd6271941a /core/lib
parent96098f011f7cc334d2c9eb694e1cc45ded4f64cf (diff)
core: crypto: introduce struct crypto_authenc_ops
Uses struct crypto_authenc_ops pointer in crypto context for authenc ciphers (AES-GCM and AES-CCM) as a glue layer instead of a switch(algo) in each cryto_authenc_*() function. Reviewed-by: Jerome Forissier <jerome.forissier@linaro.org> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Diffstat (limited to 'core/lib')
-rw-r--r--core/lib/libtomcrypt/ccm.c226
-rw-r--r--core/lib/libtomcrypt/gcm.c219
-rw-r--r--core/lib/libtomcrypt/src/tee_ltc_provider.c419
-rw-r--r--core/lib/libtomcrypt/sub.mk2
4 files changed, 447 insertions, 419 deletions
diff --git a/core/lib/libtomcrypt/ccm.c b/core/lib/libtomcrypt/ccm.c
new file mode 100644
index 00000000..a7c06b9c
--- /dev/null
+++ b/core/lib/libtomcrypt/ccm.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2014-2019, Linaro Limited
+ */
+
+#include <assert.h>
+#include <crypto/crypto.h>
+#include <crypto/crypto_impl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tee_api_types.h>
+#include <tomcrypt.h>
+#include <util.h>
+
+#define TEE_CCM_KEY_MAX_LENGTH 32
+#define TEE_CCM_NONCE_MAX_LENGTH 13
+#define TEE_CCM_TAG_MAX_LENGTH 16
+
+struct tee_ccm_state {
+ struct crypto_authenc_ctx aectx;
+ ccm_state ctx; /* the ccm state as defined by LTC */
+ size_t tag_len; /* tag length */
+};
+
+static const struct crypto_authenc_ops aes_ccm_ops;
+
+TEE_Result crypto_aes_ccm_alloc_ctx(struct crypto_authenc_ctx **ctx_ret)
+{
+ struct tee_ccm_state *ctx = calloc(1, sizeof(*ctx));
+
+ if (!ctx)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ ctx->aectx.ops = &aes_ccm_ops;
+
+ *ctx_ret = &ctx->aectx;
+ return TEE_SUCCESS;
+}
+
+static struct tee_ccm_state *to_tee_ccm_state(struct crypto_authenc_ctx *aectx)
+{
+ assert(aectx && aectx->ops == &aes_ccm_ops);
+
+ return container_of(aectx, struct tee_ccm_state, aectx);
+}
+
+static void crypto_aes_ccm_free_ctx(struct crypto_authenc_ctx *aectx)
+{
+ free(to_tee_ccm_state(aectx));
+}
+
+static void crypto_aes_ccm_copy_state(struct crypto_authenc_ctx *dst_aectx,
+ struct crypto_authenc_ctx *src_aectx)
+{
+ struct tee_ccm_state *dst_ctx = to_tee_ccm_state(dst_aectx);
+ struct tee_ccm_state *src_ctx = to_tee_ccm_state(src_aectx);
+
+ dst_ctx->ctx = src_ctx->ctx;
+ dst_ctx->tag_len = src_ctx->tag_len;
+}
+
+static TEE_Result crypto_aes_ccm_init(struct crypto_authenc_ctx *aectx,
+ TEE_OperationMode mode __unused,
+ const uint8_t *key, size_t key_len,
+ const uint8_t *nonce, size_t nonce_len,
+ size_t tag_len, size_t aad_len,
+ size_t payload_len)
+{
+ int ltc_res = 0;
+ int ltc_cipherindex = find_cipher("aes");
+ struct tee_ccm_state *ccm = to_tee_ccm_state(aectx);
+
+ if (ltc_cipherindex < 0)
+ return TEE_ERROR_NOT_SUPPORTED;
+
+ /* reset the state */
+ memset(&ccm->ctx, 0, sizeof(ccm->ctx));
+ ccm->tag_len = tag_len;
+
+ /* Check the key length */
+ if ((!key) || (key_len > TEE_CCM_KEY_MAX_LENGTH))
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ /* check the nonce */
+ if (nonce_len > TEE_CCM_NONCE_MAX_LENGTH)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ /* check the tag len */
+ if ((tag_len < 4) || (tag_len > TEE_CCM_TAG_MAX_LENGTH) ||
+ (tag_len % 2 != 0))
+ return TEE_ERROR_NOT_SUPPORTED;
+
+ ltc_res = ccm_init(&ccm->ctx, ltc_cipherindex, key, key_len,
+ payload_len, tag_len, aad_len);
+ if (ltc_res != CRYPT_OK)
+ return TEE_ERROR_BAD_STATE;
+
+ /* Add the IV */
+ ltc_res = ccm_add_nonce(&ccm->ctx, nonce, nonce_len);
+ if (ltc_res != CRYPT_OK)
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result crypto_aes_ccm_update_aad(struct crypto_authenc_ctx *aectx,
+ const uint8_t *data, size_t len)
+{
+ struct tee_ccm_state *ccm = to_tee_ccm_state(aectx);
+ int ltc_res = 0;
+
+ /* Add the AAD (note: aad can be NULL if aadlen == 0) */
+ ltc_res = ccm_add_aad(&ccm->ctx, data, len);
+ if (ltc_res != CRYPT_OK)
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result
+crypto_aes_ccm_update_payload(struct crypto_authenc_ctx *aectx,
+ TEE_OperationMode mode, const uint8_t *src_data,
+ size_t len, uint8_t *dst_data)
+{
+ int ltc_res = 0;
+ int dir = 0;
+ struct tee_ccm_state *ccm = to_tee_ccm_state(aectx);
+ unsigned char *pt = NULL;
+ unsigned char *ct = NULL;
+
+ if (mode == TEE_MODE_ENCRYPT) {
+ pt = (unsigned char *)src_data;
+ ct = dst_data;
+ dir = CCM_ENCRYPT;
+ } else {
+ pt = dst_data;
+ ct = (unsigned char *)src_data;
+ dir = CCM_DECRYPT;
+ }
+ ltc_res = ccm_process(&ccm->ctx, pt, len, ct, dir);
+ if (ltc_res != CRYPT_OK)
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result crypto_aes_ccm_enc_final(struct crypto_authenc_ctx *aectx,
+ const uint8_t *src_data,
+ size_t len, uint8_t *dst_data,
+ uint8_t *dst_tag,
+ size_t *dst_tag_len)
+{
+ TEE_Result res = TEE_SUCCESS;
+ struct tee_ccm_state *ccm = to_tee_ccm_state(aectx);
+ int ltc_res = 0;
+
+ /* Finalize the remaining buffer */
+ res = crypto_aes_ccm_update_payload(aectx, TEE_MODE_ENCRYPT, src_data,
+ len, dst_data);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ /* Check the tag length */
+ if (*dst_tag_len < ccm->tag_len) {
+ *dst_tag_len = ccm->tag_len;
+ return TEE_ERROR_SHORT_BUFFER;
+ }
+ *dst_tag_len = ccm->tag_len;
+
+ /* Compute the tag */
+ ltc_res = ccm_done(&ccm->ctx, dst_tag,
+ (unsigned long *)dst_tag_len);
+ if (ltc_res != CRYPT_OK)
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result crypto_aes_ccm_dec_final(struct crypto_authenc_ctx *aectx,
+ const uint8_t *src_data, size_t len,
+ uint8_t *dst_data,
+ const uint8_t *tag, size_t tag_len)
+{
+ TEE_Result res = TEE_ERROR_BAD_STATE;
+ struct tee_ccm_state *ccm = to_tee_ccm_state(aectx);
+ int ltc_res = 0;
+ uint8_t dst_tag[TEE_CCM_TAG_MAX_LENGTH] = { 0 };
+ unsigned long ltc_tag_len = tag_len;
+
+ if (tag_len == 0)
+ return TEE_ERROR_SHORT_BUFFER;
+ if (tag_len > TEE_CCM_TAG_MAX_LENGTH)
+ return TEE_ERROR_BAD_STATE;
+
+ /* Process the last buffer, if any */
+ res = crypto_aes_ccm_update_payload(aectx, TEE_MODE_DECRYPT, src_data,
+ len, dst_data);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ /* Finalize the authentication */
+ ltc_res = ccm_done(&ccm->ctx, dst_tag, &ltc_tag_len);
+ if (ltc_res != CRYPT_OK)
+ return TEE_ERROR_BAD_STATE;
+
+ if (consttime_memcmp(dst_tag, tag, tag_len) != 0)
+ res = TEE_ERROR_MAC_INVALID;
+ else
+ res = TEE_SUCCESS;
+ return res;
+}
+
+static void crypto_aes_ccm_final(struct crypto_authenc_ctx *aectx)
+{
+ ccm_reset(&to_tee_ccm_state(aectx)->ctx);
+}
+
+static const struct crypto_authenc_ops aes_ccm_ops = {
+ .init = crypto_aes_ccm_init,
+ .update_aad = crypto_aes_ccm_update_aad,
+ .update_payload = crypto_aes_ccm_update_payload,
+ .enc_final = crypto_aes_ccm_enc_final,
+ .dec_final = crypto_aes_ccm_dec_final,
+ .final = crypto_aes_ccm_final,
+ .free_ctx = crypto_aes_ccm_free_ctx,
+ .copy_state = crypto_aes_ccm_copy_state,
+};
diff --git a/core/lib/libtomcrypt/gcm.c b/core/lib/libtomcrypt/gcm.c
new file mode 100644
index 00000000..5f22cb87
--- /dev/null
+++ b/core/lib/libtomcrypt/gcm.c
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2014-2019, Linaro Limited
+ */
+
+#include <assert.h>
+#include <crypto/crypto.h>
+#include <crypto/crypto_impl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tee_api_types.h>
+#include <tomcrypt.h>
+#include <util.h>
+
+#define TEE_GCM_TAG_MAX_LENGTH 16
+
+struct tee_gcm_state {
+ struct crypto_authenc_ctx aectx;
+ gcm_state ctx; /* the gcm state as defined by LTC */
+ size_t tag_len; /* tag length */
+};
+
+static const struct crypto_authenc_ops aes_gcm_ops;
+
+static struct tee_gcm_state *to_tee_gcm_state(struct crypto_authenc_ctx *aectx)
+{
+ assert(aectx && aectx->ops == &aes_gcm_ops);
+
+ return container_of(aectx, struct tee_gcm_state, aectx);
+}
+
+TEE_Result crypto_aes_gcm_alloc_ctx(struct crypto_authenc_ctx **ctx_ret)
+{
+ struct tee_gcm_state *ctx = calloc(1, sizeof(*ctx));
+
+ if (!ctx)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ ctx->aectx.ops = &aes_gcm_ops;
+
+ *ctx_ret = &ctx->aectx;
+
+ return TEE_SUCCESS;
+}
+
+static void crypto_aes_gcm_free_ctx(struct crypto_authenc_ctx *aectx)
+{
+ free(to_tee_gcm_state(aectx));
+}
+
+static void crypto_aes_gcm_copy_state(struct crypto_authenc_ctx *dst_aectx,
+ struct crypto_authenc_ctx *src_aectx)
+{
+ struct tee_gcm_state *dst_ctx = to_tee_gcm_state(dst_aectx);
+ struct tee_gcm_state *src_ctx = to_tee_gcm_state(src_aectx);
+
+ dst_ctx->ctx = src_ctx->ctx;
+ dst_ctx->tag_len = src_ctx->tag_len;
+}
+
+static TEE_Result crypto_aes_gcm_init(struct crypto_authenc_ctx *aectx,
+ TEE_OperationMode mode __unused,
+ const uint8_t *key, size_t key_len,
+ const uint8_t *nonce, size_t nonce_len,
+ size_t tag_len, size_t aad_len __unused,
+ size_t payload_len __unused)
+{
+ int ltc_res = 0;
+ int ltc_cipherindex = find_cipher("aes");
+ struct tee_gcm_state *gcm = to_tee_gcm_state(aectx);
+
+ if (ltc_cipherindex < 0)
+ return TEE_ERROR_NOT_SUPPORTED;
+
+ /* reset the state */
+ memset(&gcm->ctx, 0, sizeof(gcm->ctx));
+ gcm->tag_len = tag_len;
+
+ ltc_res = gcm_init(&gcm->ctx, ltc_cipherindex, key, key_len);
+ if (ltc_res != CRYPT_OK)
+ return TEE_ERROR_BAD_STATE;
+
+ /* Add the IV */
+ ltc_res = gcm_add_iv(&gcm->ctx, nonce, nonce_len);
+ if (ltc_res != CRYPT_OK)
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result crypto_aes_gcm_update_aad(struct crypto_authenc_ctx *aectx,
+ const uint8_t *data, size_t len)
+{
+ struct tee_gcm_state *gcm = to_tee_gcm_state(aectx);
+ int ltc_res = 0;
+
+ /* Add the AAD (note: aad can be NULL if aadlen == 0) */
+ ltc_res = gcm_add_aad(&gcm->ctx, data, len);
+ if (ltc_res != CRYPT_OK)
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result
+crypto_aes_gcm_update_payload(struct crypto_authenc_ctx *aectx,
+ TEE_OperationMode mode, const uint8_t *src_data,
+ size_t len, uint8_t *dst_data)
+{
+ TEE_Result res = TEE_SUCCESS;
+ int ltc_res = 0;
+ int dir = 0;
+ struct tee_gcm_state *gcm = to_tee_gcm_state(aectx);
+ unsigned char *pt = NULL;
+ unsigned char *ct = NULL;
+
+ if (mode == TEE_MODE_ENCRYPT) {
+ pt = (unsigned char *)src_data;
+ ct = dst_data;
+ dir = GCM_ENCRYPT;
+ } else {
+ pt = dst_data;
+ ct = (unsigned char *)src_data;
+ dir = GCM_DECRYPT;
+ }
+
+ /* aad is optional ==> add one without length */
+ if (gcm->ctx.mode == LTC_GCM_MODE_IV) {
+ res = crypto_aes_gcm_update_aad(aectx, NULL, 0);
+ if (res != TEE_SUCCESS)
+ return res;
+ }
+
+ /* process the data */
+ ltc_res = gcm_process(&gcm->ctx, pt, len, ct, dir);
+ if (ltc_res != CRYPT_OK)
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result crypto_aes_gcm_enc_final(struct crypto_authenc_ctx *aectx,
+ const uint8_t *src_data, size_t len,
+ uint8_t *dst_data, uint8_t *dst_tag,
+ size_t *dst_tag_len)
+{
+ TEE_Result res = TEE_SUCCESS;
+ struct tee_gcm_state *gcm = to_tee_gcm_state(aectx);
+ int ltc_res = 0;
+
+ /* Finalize the remaining buffer */
+ res = crypto_aes_gcm_update_payload(aectx, TEE_MODE_ENCRYPT, src_data,
+ len, dst_data);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ /* Check the tag length */
+ if (*dst_tag_len < gcm->tag_len) {
+ *dst_tag_len = gcm->tag_len;
+ return TEE_ERROR_SHORT_BUFFER;
+ }
+ *dst_tag_len = gcm->tag_len;
+
+ /* Compute the tag */
+ ltc_res = gcm_done(&gcm->ctx, dst_tag, (unsigned long *)dst_tag_len);
+ if (ltc_res != CRYPT_OK)
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result crypto_aes_gcm_dec_final(struct crypto_authenc_ctx *aectx,
+ const uint8_t *src_data, size_t len,
+ uint8_t *dst_data,
+ const uint8_t *tag, size_t tag_len)
+{
+ TEE_Result res = TEE_ERROR_BAD_STATE;
+ struct tee_gcm_state *gcm = to_tee_gcm_state(aectx);
+ int ltc_res = 0;
+ uint8_t dst_tag[TEE_GCM_TAG_MAX_LENGTH] = { 0 };
+ unsigned long ltc_tag_len = tag_len;
+
+ if (tag_len == 0)
+ return TEE_ERROR_SHORT_BUFFER;
+ if (tag_len > TEE_GCM_TAG_MAX_LENGTH)
+ return TEE_ERROR_BAD_STATE;
+
+ /* Process the last buffer, if any */
+ res = crypto_aes_gcm_update_payload(aectx, TEE_MODE_DECRYPT, src_data,
+ len, dst_data);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ /* Finalize the authentication */
+ ltc_res = gcm_done(&gcm->ctx, dst_tag, &ltc_tag_len);
+ if (ltc_res != CRYPT_OK)
+ return TEE_ERROR_BAD_STATE;
+
+ if (consttime_memcmp(dst_tag, tag, tag_len) != 0)
+ res = TEE_ERROR_MAC_INVALID;
+ else
+ res = TEE_SUCCESS;
+ return res;
+}
+
+static void crypto_aes_gcm_final(struct crypto_authenc_ctx *aectx)
+{
+ gcm_reset(&to_tee_gcm_state(aectx)->ctx);
+}
+
+static const struct crypto_authenc_ops aes_gcm_ops = {
+ .init = crypto_aes_gcm_init,
+ .update_aad = crypto_aes_gcm_update_aad,
+ .update_payload = crypto_aes_gcm_update_payload,
+ .enc_final = crypto_aes_gcm_enc_final,
+ .dec_final = crypto_aes_gcm_dec_final,
+ .final = crypto_aes_gcm_final,
+ .free_ctx = crypto_aes_gcm_free_ctx,
+ .copy_state = crypto_aes_gcm_copy_state,
+};
diff --git a/core/lib/libtomcrypt/src/tee_ltc_provider.c b/core/lib/libtomcrypt/src/tee_ltc_provider.c
index 40df474f..cae91b7d 100644
--- a/core/lib/libtomcrypt/src/tee_ltc_provider.c
+++ b/core/lib/libtomcrypt/src/tee_ltc_provider.c
@@ -4,8 +4,6 @@
*/
#include <assert.h>
-#include <crypto/aes-ccm.h>
-#include <crypto/aes-gcm.h>
#include <crypto/crypto.h>
#include <kernel/panic.h>
#include <stdlib.h>
@@ -198,60 +196,6 @@ static TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex)
}
#endif /* defined(CFG_CRYPTO_RSA) */
-#if defined(CFG_CRYPTO_CCM) || defined(CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB)
-/*
- * Compute the LibTomCrypt "cipherindex" given a TEE Algorithm "algo"
- * Return
- * - TEE_SUCCESS in case of success,
- * - TEE_ERROR_BAD_PARAMETERS in case algo is not a valid algo
- * - TEE_ERROR_NOT_SUPPORTED in case algo is not supported by LTC
- * Return -1 in case of error
- */
-static TEE_Result tee_algo_to_ltc_cipherindex(uint32_t algo,
- int *ltc_cipherindex)
-{
- switch (algo) {
-#if defined(CFG_CRYPTO_AES)
- case TEE_ALG_AES_CBC_MAC_NOPAD:
- case TEE_ALG_AES_CBC_MAC_PKCS5:
- case TEE_ALG_AES_CMAC:
- case TEE_ALG_AES_ECB_NOPAD:
- case TEE_ALG_AES_CBC_NOPAD:
- case TEE_ALG_AES_CTR:
- case TEE_ALG_AES_CTS:
- case TEE_ALG_AES_XTS:
- case TEE_ALG_AES_CCM:
- case TEE_ALG_AES_GCM:
- *ltc_cipherindex = find_cipher("aes");
- break;
-#endif
-#if defined(CFG_CRYPTO_DES)
- case TEE_ALG_DES_CBC_MAC_NOPAD:
- case TEE_ALG_DES_CBC_MAC_PKCS5:
- case TEE_ALG_DES_ECB_NOPAD:
- case TEE_ALG_DES_CBC_NOPAD:
- *ltc_cipherindex = find_cipher("des");
- break;
-
- case TEE_ALG_DES3_CBC_MAC_NOPAD:
- case TEE_ALG_DES3_CBC_MAC_PKCS5:
- case TEE_ALG_DES3_ECB_NOPAD:
- case TEE_ALG_DES3_CBC_NOPAD:
- *ltc_cipherindex = find_cipher("3des");
- break;
-#endif
- default:
- return TEE_ERROR_BAD_PARAMETERS;
- }
-
- if (*ltc_cipherindex < 0)
- return TEE_ERROR_NOT_SUPPORTED;
- else
- return TEE_SUCCESS;
-}
-#endif /* defined(CFG_CRYPTO_CCM) ||
- defined(CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB) */
-
/******************************************************************************
* Asymmetric algorithms
******************************************************************************/
@@ -1440,369 +1384,6 @@ out:
#endif /* _CFG_CRYPTO_WITH_ACIPHER */
-/******************************************************************************
- * Authenticated encryption
- ******************************************************************************/
-
-#define TEE_CCM_KEY_MAX_LENGTH 32
-#define TEE_CCM_NONCE_MAX_LENGTH 13
-#define TEE_CCM_TAG_MAX_LENGTH 16
-#define TEE_GCM_TAG_MAX_LENGTH 16
-
-#if defined(CFG_CRYPTO_CCM)
-struct tee_ccm_state {
- ccm_state ctx; /* the ccm state as defined by LTC */
- size_t tag_len; /* tag length */
-};
-
-TEE_Result crypto_aes_ccm_alloc_ctx(void **ctx_ret)
-{
- struct tee_ccm_state *ctx = calloc(1, sizeof(*ctx));
-
- if (!ctx)
- return TEE_ERROR_OUT_OF_MEMORY;
-
- *ctx_ret = ctx;
- return TEE_SUCCESS;
-}
-
-void crypto_aes_ccm_free_ctx(void *ctx)
-{
- free(ctx);
-}
-
-void crypto_aes_ccm_copy_state(void *dst_ctx, void *src_ctx)
-{
- memcpy(dst_ctx, src_ctx, sizeof(struct tee_ccm_state));
-}
-
-TEE_Result crypto_aes_ccm_init(void *ctx, TEE_OperationMode mode __unused,
- const uint8_t *key, size_t key_len,
- const uint8_t *nonce, size_t nonce_len,
- size_t tag_len, size_t aad_len,
- size_t payload_len)
-{
- TEE_Result res;
- int ltc_res;
- int ltc_cipherindex;
- struct tee_ccm_state *ccm = ctx;
-
- res = tee_algo_to_ltc_cipherindex(TEE_ALG_AES_CCM, &ltc_cipherindex);
- if (res != TEE_SUCCESS)
- return TEE_ERROR_NOT_SUPPORTED;
-
- /* reset the state */
- memset(ccm, 0, sizeof(struct tee_ccm_state));
- ccm->tag_len = tag_len;
-
- /* Check the key length */
- if ((!key) || (key_len > TEE_CCM_KEY_MAX_LENGTH))
- return TEE_ERROR_BAD_PARAMETERS;
-
- /* check the nonce */
- if (nonce_len > TEE_CCM_NONCE_MAX_LENGTH)
- return TEE_ERROR_BAD_PARAMETERS;
-
- /* check the tag len */
- if ((tag_len < 4) || (tag_len > TEE_CCM_TAG_MAX_LENGTH) ||
- (tag_len % 2 != 0))
- return TEE_ERROR_NOT_SUPPORTED;
-
- ltc_res = ccm_init(&ccm->ctx, ltc_cipherindex, key, key_len,
- payload_len, tag_len, aad_len);
- if (ltc_res != CRYPT_OK)
- return TEE_ERROR_BAD_STATE;
-
- /* Add the IV */
- ltc_res = ccm_add_nonce(&ccm->ctx, nonce, nonce_len);
- if (ltc_res != CRYPT_OK)
- return TEE_ERROR_BAD_STATE;
-
- return TEE_SUCCESS;
-}
-
-TEE_Result crypto_aes_ccm_update_aad(void *ctx, const uint8_t *data, size_t len)
-{
- struct tee_ccm_state *ccm = ctx;
- int ltc_res;
-
- /* Add the AAD (note: aad can be NULL if aadlen == 0) */
- ltc_res = ccm_add_aad(&ccm->ctx, data, len);
- if (ltc_res != CRYPT_OK)
- return TEE_ERROR_BAD_STATE;
-
- return TEE_SUCCESS;
-}
-
-TEE_Result crypto_aes_ccm_update_payload(void *ctx, TEE_OperationMode mode,
- const uint8_t *src_data,
- size_t len, uint8_t *dst_data)
-{
- int ltc_res, dir;
- struct tee_ccm_state *ccm = ctx;
- unsigned char *pt, *ct; /* the plain and the cipher text */
-
- if (mode == TEE_MODE_ENCRYPT) {
- pt = (unsigned char *)src_data;
- ct = dst_data;
- dir = CCM_ENCRYPT;
- } else {
- pt = dst_data;
- ct = (unsigned char *)src_data;
- dir = CCM_DECRYPT;
- }
- ltc_res = ccm_process(&ccm->ctx, pt, len, ct, dir);
- if (ltc_res != CRYPT_OK)
- return TEE_ERROR_BAD_STATE;
-
- return TEE_SUCCESS;
-}
-
-TEE_Result crypto_aes_ccm_enc_final(void *ctx, const uint8_t *src_data,
- size_t len, uint8_t *dst_data,
- uint8_t *dst_tag, size_t *dst_tag_len)
-{
- TEE_Result res;
- struct tee_ccm_state *ccm = ctx;
- int ltc_res;
-
- /* Finalize the remaining buffer */
- res = crypto_aes_ccm_update_payload(ctx, TEE_MODE_ENCRYPT, src_data,
- len, dst_data);
- if (res != TEE_SUCCESS)
- return res;
-
- /* Check the tag length */
- if (*dst_tag_len < ccm->tag_len) {
- *dst_tag_len = ccm->tag_len;
- return TEE_ERROR_SHORT_BUFFER;
- }
- *dst_tag_len = ccm->tag_len;
-
- /* Compute the tag */
- ltc_res = ccm_done(&ccm->ctx, dst_tag,
- (unsigned long *)dst_tag_len);
- if (ltc_res != CRYPT_OK)
- return TEE_ERROR_BAD_STATE;
-
- return TEE_SUCCESS;
-}
-
-TEE_Result crypto_aes_ccm_dec_final(void *ctx, const uint8_t *src_data,
- size_t len, uint8_t *dst_data,
- const uint8_t *tag, size_t tag_len)
-{
- TEE_Result res = TEE_ERROR_BAD_STATE;
- struct tee_ccm_state *ccm = ctx;
- int ltc_res;
- uint8_t dst_tag[TEE_CCM_TAG_MAX_LENGTH];
- unsigned long ltc_tag_len = tag_len;
-
- if (tag_len == 0)
- return TEE_ERROR_SHORT_BUFFER;
- if (tag_len > TEE_CCM_TAG_MAX_LENGTH)
- return TEE_ERROR_BAD_STATE;
-
- /* Process the last buffer, if any */
- res = crypto_aes_ccm_update_payload(ctx, TEE_MODE_DECRYPT, src_data,
- len, dst_data);
- if (res != TEE_SUCCESS)
- return res;
-
- /* Finalize the authentication */
- ltc_res = ccm_done(&ccm->ctx, dst_tag, &ltc_tag_len);
- if (ltc_res != CRYPT_OK)
- return TEE_ERROR_BAD_STATE;
-
- if (consttime_memcmp(dst_tag, tag, tag_len) != 0)
- res = TEE_ERROR_MAC_INVALID;
- else
- res = TEE_SUCCESS;
- return res;
-}
-
-void crypto_aes_ccm_final(void *ctx)
-{
- struct tee_ccm_state *ccm = ctx;
-
- ccm_reset(&ccm->ctx);
-}
-#endif /*CFG_CRYPTO_CCM*/
-
-#if defined(CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB)
-struct tee_gcm_state {
- gcm_state ctx; /* the gcm state as defined by LTC */
- size_t tag_len; /* tag length */
-};
-
-TEE_Result crypto_aes_gcm_alloc_ctx(void **ctx_ret)
-{
- struct tee_gcm_state *ctx = calloc(1, sizeof(*ctx));
-
- if (!ctx)
- return TEE_ERROR_OUT_OF_MEMORY;
-
- *ctx_ret = ctx;
- return TEE_SUCCESS;
-}
-
-void crypto_aes_gcm_free_ctx(void *ctx)
-{
- free(ctx);
-}
-
-void crypto_aes_gcm_copy_state(void *dst_ctx, void *src_ctx)
-{
- memcpy(dst_ctx, src_ctx, sizeof(struct tee_gcm_state));
-}
-
-TEE_Result crypto_aes_gcm_init(void *ctx, TEE_OperationMode mode __unused,
- const uint8_t *key, size_t key_len,
- const uint8_t *nonce, size_t nonce_len,
- size_t tag_len)
-{
- TEE_Result res;
- int ltc_res;
- int ltc_cipherindex;
- struct tee_gcm_state *gcm = ctx;
-
- res = tee_algo_to_ltc_cipherindex(TEE_ALG_AES_GCM, &ltc_cipherindex);
- if (res != TEE_SUCCESS)
- return TEE_ERROR_NOT_SUPPORTED;
-
- /* reset the state */
- memset(gcm, 0, sizeof(struct tee_gcm_state));
- gcm->tag_len = tag_len;
-
- ltc_res = gcm_init(&gcm->ctx, ltc_cipherindex, key, key_len);
- if (ltc_res != CRYPT_OK)
- return TEE_ERROR_BAD_STATE;
-
- /* Add the IV */
- ltc_res = gcm_add_iv(&gcm->ctx, nonce, nonce_len);
- if (ltc_res != CRYPT_OK)
- return TEE_ERROR_BAD_STATE;
-
- return TEE_SUCCESS;
-}
-
-TEE_Result crypto_aes_gcm_update_aad(void *ctx, const uint8_t *data, size_t len)
-{
- struct tee_gcm_state *gcm = ctx;
- int ltc_res;
-
- /* Add the AAD (note: aad can be NULL if aadlen == 0) */
- ltc_res = gcm_add_aad(&gcm->ctx, data, len);
- if (ltc_res != CRYPT_OK)
- return TEE_ERROR_BAD_STATE;
-
- return TEE_SUCCESS;
-}
-
-TEE_Result crypto_aes_gcm_update_payload(void *ctx, TEE_OperationMode mode,
- const uint8_t *src_data,
- size_t len, uint8_t *dst_data)
-{
- TEE_Result res;
- int ltc_res, dir;
- struct tee_gcm_state *gcm = ctx;
- unsigned char *pt, *ct; /* the plain and the cipher text */
-
- if (mode == TEE_MODE_ENCRYPT) {
- pt = (unsigned char *)src_data;
- ct = dst_data;
- dir = GCM_ENCRYPT;
- } else {
- pt = dst_data;
- ct = (unsigned char *)src_data;
- dir = GCM_DECRYPT;
- }
-
- /* aad is optional ==> add one without length */
- if (gcm->ctx.mode == LTC_GCM_MODE_IV) {
- res = crypto_aes_gcm_update_aad(gcm, NULL, 0);
- if (res != TEE_SUCCESS)
- return res;
- }
-
- /* process the data */
- ltc_res = gcm_process(&gcm->ctx, pt, len, ct, dir);
- if (ltc_res != CRYPT_OK)
- return TEE_ERROR_BAD_STATE;
-
- return TEE_SUCCESS;
-}
-
-TEE_Result crypto_aes_gcm_enc_final(void *ctx, const uint8_t *src_data,
- size_t len, uint8_t *dst_data,
- uint8_t *dst_tag, size_t *dst_tag_len)
-{
- TEE_Result res;
- struct tee_gcm_state *gcm = ctx;
- int ltc_res;
-
- /* Finalize the remaining buffer */
- res = crypto_aes_gcm_update_payload(ctx, TEE_MODE_ENCRYPT, src_data,
- len, dst_data);
- if (res != TEE_SUCCESS)
- return res;
-
- /* Check the tag length */
- if (*dst_tag_len < gcm->tag_len) {
- *dst_tag_len = gcm->tag_len;
- return TEE_ERROR_SHORT_BUFFER;
- }
- *dst_tag_len = gcm->tag_len;
-
- /* Compute the tag */
- ltc_res = gcm_done(&gcm->ctx, dst_tag, (unsigned long *)dst_tag_len);
- if (ltc_res != CRYPT_OK)
- return TEE_ERROR_BAD_STATE;
-
- return TEE_SUCCESS;
-}
-
-TEE_Result crypto_aes_gcm_dec_final(void *ctx, const uint8_t *src_data,
- size_t len, uint8_t *dst_data,
- const uint8_t *tag, size_t tag_len)
-{
- TEE_Result res = TEE_ERROR_BAD_STATE;
- struct tee_gcm_state *gcm = ctx;
- int ltc_res;
- uint8_t dst_tag[TEE_GCM_TAG_MAX_LENGTH];
- unsigned long ltc_tag_len = tag_len;
-
- if (tag_len == 0)
- return TEE_ERROR_SHORT_BUFFER;
- if (tag_len > TEE_GCM_TAG_MAX_LENGTH)
- return TEE_ERROR_BAD_STATE;
-
- /* Process the last buffer, if any */
- res = crypto_aes_gcm_update_payload(ctx, TEE_MODE_DECRYPT, src_data,
- len, dst_data);
- if (res != TEE_SUCCESS)
- return res;
-
- /* Finalize the authentication */
- ltc_res = gcm_done(&gcm->ctx, dst_tag, &ltc_tag_len);
- if (ltc_res != CRYPT_OK)
- return TEE_ERROR_BAD_STATE;
-
- if (consttime_memcmp(dst_tag, tag, tag_len) != 0)
- res = TEE_ERROR_MAC_INVALID;
- else
- res = TEE_SUCCESS;
- return res;
-}
-
-void crypto_aes_gcm_final(void *ctx)
-{
- struct tee_gcm_state *gcm = ctx;
-
- gcm_reset(&gcm->ctx);
-}
-#endif /*CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB*/
-
TEE_Result crypto_init(void)
{
init_mp_tomcrypt();
diff --git a/core/lib/libtomcrypt/sub.mk b/core/lib/libtomcrypt/sub.mk
index 04637457..e9ed3841 100644
--- a/core/lib/libtomcrypt/sub.mk
+++ b/core/lib/libtomcrypt/sub.mk
@@ -14,3 +14,5 @@ srcs-$(CFG_CRYPTO_CBC) += cbc.c
srcs-$(CFG_CRYPTO_CTS) += cts.c
srcs-$(CFG_CRYPTO_CTR) += ctr.c
srcs-$(CFG_CRYPTO_XTS) += xts.c
+srcs-$(CFG_CRYPTO_CCM) += ccm.c
+srcs-$(CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB) += gcm.c