diff options
author | Jens Wiklander <jens.wiklander@linaro.org> | 2019-03-08 15:22:14 +0100 |
---|---|---|
committer | Jérôme Forissier <jerome.forissier@linaro.org> | 2019-03-11 17:58:04 +0100 |
commit | f1e9b21b29bdc21a51c6c1a4b8df7eb5e2bd5189 (patch) | |
tree | 3f7280058413d43e605e867b156f86bd6271941a /core/lib | |
parent | 96098f011f7cc334d2c9eb694e1cc45ded4f64cf (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.c | 226 | ||||
-rw-r--r-- | core/lib/libtomcrypt/gcm.c | 219 | ||||
-rw-r--r-- | core/lib/libtomcrypt/src/tee_ltc_provider.c | 419 | ||||
-rw-r--r-- | core/lib/libtomcrypt/sub.mk | 2 |
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, <c_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, <c_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, <c_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, <c_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, <c_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, <c_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 |