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 | |
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')
-rw-r--r-- | core/crypto/aes-gcm-ghash-tbl.c | 1 | ||||
-rw-r--r-- | core/crypto/aes-gcm.c | 82 | ||||
-rw-r--r-- | core/crypto/crypto.c | 237 | ||||
-rw-r--r-- | core/include/crypto/aes-ccm.h | 33 | ||||
-rw-r--r-- | core/include/crypto/aes-gcm.h | 31 | ||||
-rw-r--r-- | core/include/crypto/crypto_impl.h | 38 | ||||
-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 |
10 files changed, 613 insertions, 675 deletions
diff --git a/core/crypto/aes-gcm-ghash-tbl.c b/core/crypto/aes-gcm-ghash-tbl.c index 5e7965a9..203b5300 100644 --- a/core/crypto/aes-gcm-ghash-tbl.c +++ b/core/crypto/aes-gcm-ghash-tbl.c @@ -17,7 +17,6 @@ * limitations under the License. */ -#include <crypto/aes-gcm.h> #include <io.h> #include <kernel/panic.h> #include <string.h> diff --git a/core/crypto/aes-gcm.c b/core/crypto/aes-gcm.c index 0cc1e99f..c4aa1ff9 100644 --- a/core/crypto/aes-gcm.c +++ b/core/crypto/aes-gcm.c @@ -5,6 +5,7 @@ #include <assert.h> #include <crypto/internal_aes-gcm.h> +#include <crypto/crypto_impl.h> #include <io.h> #include <string_ext.h> #include <string.h> @@ -402,65 +403,104 @@ TEE_Result internal_aes_gcm_dec(const struct internal_aes_gcm_key *enc_key, #ifndef CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB -#include <crypto/aes-gcm.h> #include <stdlib.h> +#include <crypto/crypto.h> -TEE_Result crypto_aes_gcm_alloc_ctx(void **ctx_ret) +struct aes_gcm_ctx { + struct crypto_authenc_ctx aec; + struct internal_aes_gcm_ctx ctx; +}; + +static const struct crypto_authenc_ops aes_gcm_ops; + +static struct aes_gcm_ctx * +to_aes_gcm_ctx(struct crypto_authenc_ctx *aec) +{ + assert(aec->ops == &aes_gcm_ops); + + return container_of(aec, struct aes_gcm_ctx, aec); +} + +TEE_Result crypto_aes_gcm_alloc_ctx(struct crypto_authenc_ctx **ctx_ret) { - struct internal_aes_gcm_ctx *ctx = calloc(1, sizeof(*ctx)); + struct aes_gcm_ctx *ctx = calloc(1, sizeof(*ctx)); if (!ctx) return TEE_ERROR_OUT_OF_MEMORY; + ctx->aec.ops = &aes_gcm_ops; + + *ctx_ret = &ctx->aec; - *ctx_ret = ctx; return TEE_SUCCESS; } -void crypto_aes_gcm_free_ctx(void *ctx) +static void aes_gcm_free_ctx(struct crypto_authenc_ctx *aec) { - free(ctx); + free(to_aes_gcm_ctx(aec)); } -void crypto_aes_gcm_copy_state(void *dst_ctx, void *src_ctx) +static void aes_gcm_copy_state(struct crypto_authenc_ctx *dst_ctx, + struct crypto_authenc_ctx *src_ctx) { - memcpy(dst_ctx, src_ctx, sizeof(struct internal_aes_gcm_ctx)); + to_aes_gcm_ctx(dst_ctx)->ctx = to_aes_gcm_ctx(src_ctx)->ctx; } -TEE_Result crypto_aes_gcm_init(void *c, TEE_OperationMode mode, +static TEE_Result aes_gcm_init(struct crypto_authenc_ctx *aec, + TEE_OperationMode mode, const uint8_t *key, size_t key_len, const uint8_t *nonce, size_t nonce_len, - size_t tag_len) + size_t tag_len, size_t aad_len __unused, + size_t payload_len __unused) { - return internal_aes_gcm_init(c, mode, key, key_len, nonce, nonce_len, - tag_len); + return internal_aes_gcm_init(&to_aes_gcm_ctx(aec)->ctx, mode, key, + key_len, nonce, nonce_len, tag_len); } -TEE_Result crypto_aes_gcm_update_aad(void *c, const uint8_t *data, size_t len) +static TEE_Result aes_gcm_update_aad(struct crypto_authenc_ctx *aec, + const uint8_t *data, size_t len) { - return internal_aes_gcm_update_aad(c, data, len); + return internal_aes_gcm_update_aad(&to_aes_gcm_ctx(aec)->ctx, data, + len); } -TEE_Result crypto_aes_gcm_update_payload(void *c, TEE_OperationMode m, +static TEE_Result aes_gcm_update_payload(struct crypto_authenc_ctx *aec, + TEE_OperationMode m, const uint8_t *src, size_t len, uint8_t *dst) { - return internal_aes_gcm_update_payload(c, m, src, len, dst); + return internal_aes_gcm_update_payload(&to_aes_gcm_ctx(aec)->ctx, + m, src, len, dst); } -TEE_Result crypto_aes_gcm_enc_final(void *c, const uint8_t *src, size_t len, +static TEE_Result aes_gcm_enc_final(struct crypto_authenc_ctx *aec, + const uint8_t *src, size_t len, uint8_t *dst, uint8_t *tag, size_t *tag_len) { - return internal_aes_gcm_enc_final(c, src, len, dst, tag, tag_len); + return internal_aes_gcm_enc_final(&to_aes_gcm_ctx(aec)->ctx, src, len, + dst, tag, tag_len); } -TEE_Result crypto_aes_gcm_dec_final(void *c, const uint8_t *src, size_t len, +static TEE_Result aes_gcm_dec_final(struct crypto_authenc_ctx *aec, + const uint8_t *src, size_t len, uint8_t *dst, const uint8_t *tag, size_t tag_len) { - return internal_aes_gcm_dec_final(c, src, len, dst, tag, tag_len); + return internal_aes_gcm_dec_final(&to_aes_gcm_ctx(aec)->ctx, src, len, + dst, tag, tag_len); } -void crypto_aes_gcm_final(void *c __unused) +static void aes_gcm_final(struct crypto_authenc_ctx *aec __unused) { } + +static const struct crypto_authenc_ops aes_gcm_ops = { + .init = aes_gcm_init, + .update_aad = aes_gcm_update_aad, + .update_payload = aes_gcm_update_payload, + .enc_final = aes_gcm_enc_final, + .dec_final = aes_gcm_dec_final, + .final = aes_gcm_final, + .free_ctx = aes_gcm_free_ctx, + .copy_state = aes_gcm_copy_state, +}; #endif /*!CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB*/ diff --git a/core/crypto/crypto.c b/core/crypto/crypto.c index 32123a2d..a536046f 100644 --- a/core/crypto/crypto.c +++ b/core/crypto/crypto.c @@ -5,8 +5,6 @@ #include <assert.h> #include <compiler.h> -#include <crypto/aes-ccm.h> -#include <crypto/aes-gcm.h> #include <crypto/crypto.h> #include <crypto/crypto_impl.h> #include <kernel/panic.h> @@ -294,214 +292,113 @@ TEE_Result crypto_mac_final(void *ctx, uint32_t algo __unused, TEE_Result crypto_authenc_alloc_ctx(void **ctx, uint32_t algo) { - switch (algo) { -#if defined(CFG_CRYPTO_CCM) - case TEE_ALG_AES_CCM: - return crypto_aes_ccm_alloc_ctx(ctx); -#endif -#if defined(CFG_CRYPTO_GCM) - case TEE_ALG_AES_GCM: - return crypto_aes_gcm_alloc_ctx(ctx); -#endif - default: - return TEE_ERROR_NOT_IMPLEMENTED; - } -} + TEE_Result res = TEE_SUCCESS; + struct crypto_authenc_ctx *c = NULL; -void crypto_authenc_free_ctx(void *ctx, uint32_t algo) -{ switch (algo) { #if defined(CFG_CRYPTO_CCM) case TEE_ALG_AES_CCM: - crypto_aes_ccm_free_ctx(ctx); + res = crypto_aes_ccm_alloc_ctx(&c); break; #endif #if defined(CFG_CRYPTO_GCM) case TEE_ALG_AES_GCM: - crypto_aes_gcm_free_ctx(ctx); + res = crypto_aes_gcm_alloc_ctx(&c); break; #endif default: - if (ctx) - assert(0); + return TEE_ERROR_NOT_IMPLEMENTED; } + + if (!res) + *ctx = c; + + return res; } -void crypto_authenc_copy_state(void *dst_ctx, void *src_ctx, uint32_t algo) +static const struct crypto_authenc_ops *ae_ops(void *ctx) { - switch (algo) { -#if defined(CFG_CRYPTO_CCM) - case TEE_ALG_AES_CCM: - crypto_aes_ccm_copy_state(dst_ctx, src_ctx); - break; -#endif -#if defined(CFG_CRYPTO_GCM) - case TEE_ALG_AES_GCM: - crypto_aes_gcm_copy_state(dst_ctx, src_ctx); - break; -#endif - default: - assert(0); - } + struct crypto_authenc_ctx *c = ctx; + + assert(c && c->ops); + + return c->ops; } -TEE_Result crypto_authenc_init(void *ctx __maybe_unused, - uint32_t algo __maybe_unused, - TEE_OperationMode mode __maybe_unused, - const uint8_t *key __maybe_unused, - size_t key_len __maybe_unused, - const uint8_t *nonce __maybe_unused, - size_t nonce_len __maybe_unused, - size_t tag_len __maybe_unused, - size_t aad_len __maybe_unused, - size_t payload_len __maybe_unused) +TEE_Result crypto_authenc_init(void *ctx, uint32_t algo __unused, + TEE_OperationMode mode, + 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) { - switch (algo) { -#if defined(CFG_CRYPTO_CCM) - case TEE_ALG_AES_CCM: - return crypto_aes_ccm_init(ctx, mode, key, key_len, nonce, - nonce_len, tag_len, aad_len, - payload_len); -#endif -#if defined(CFG_CRYPTO_GCM) - case TEE_ALG_AES_GCM: - return crypto_aes_gcm_init(ctx, mode, key, key_len, nonce, - nonce_len, tag_len); -#endif - default: - return TEE_ERROR_NOT_IMPLEMENTED; - } + return ae_ops(ctx)->init(ctx, mode, key, key_len, nonce, nonce_len, + tag_len, aad_len, payload_len); } -TEE_Result crypto_authenc_update_aad(void *ctx __maybe_unused, - uint32_t algo __maybe_unused, +TEE_Result crypto_authenc_update_aad(void *ctx, uint32_t algo __unused, TEE_OperationMode mode __unused, - const uint8_t *data __maybe_unused, - size_t len __maybe_unused) + const uint8_t *data, size_t len) { - switch (algo) { -#if defined(CFG_CRYPTO_CCM) - case TEE_ALG_AES_CCM: - return crypto_aes_ccm_update_aad(ctx, data, len); -#endif -#if defined(CFG_CRYPTO_GCM) - case TEE_ALG_AES_GCM: - return crypto_aes_gcm_update_aad(ctx, data, len); -#endif - default: - return TEE_ERROR_NOT_IMPLEMENTED; - } + return ae_ops(ctx)->update_aad(ctx, data, len); } -TEE_Result crypto_authenc_update_payload(void *ctx __maybe_unused, - uint32_t algo __maybe_unused, - TEE_OperationMode mode __maybe_unused, - const uint8_t *src_data __maybe_unused, - size_t src_len __maybe_unused, - uint8_t *dst_data __maybe_unused, - size_t *dst_len __maybe_unused) -{ - size_t dl = *dst_len; - *dst_len = src_len; - if (dl < src_len) +TEE_Result crypto_authenc_update_payload(void *ctx, uint32_t algo __unused, + TEE_OperationMode mode, + const uint8_t *src_data, + size_t src_len, uint8_t *dst_data, + size_t *dst_len) +{ + if (*dst_len < src_len) return TEE_ERROR_SHORT_BUFFER; + *dst_len = src_len; - switch (algo) { -#if defined(CFG_CRYPTO_CCM) - case TEE_ALG_AES_CCM: - return crypto_aes_ccm_update_payload(ctx, mode, src_data, - src_len, dst_data); -#endif -#if defined(CFG_CRYPTO_GCM) - case TEE_ALG_AES_GCM: - return crypto_aes_gcm_update_payload(ctx, mode, src_data, - src_len, dst_data); -#endif - default: - return TEE_ERROR_NOT_IMPLEMENTED; - } + return ae_ops(ctx)->update_payload(ctx, mode, src_data, src_len, + dst_data); } -TEE_Result crypto_authenc_enc_final(void *ctx __maybe_unused, - uint32_t algo __maybe_unused, - const uint8_t *src_data __maybe_unused, - size_t src_len __maybe_unused, - uint8_t *dst_data __maybe_unused, - size_t *dst_len __maybe_unused, - uint8_t *dst_tag __maybe_unused, - size_t *dst_tag_len __maybe_unused) +TEE_Result crypto_authenc_enc_final(void *ctx, uint32_t algo __unused, + const uint8_t *src_data, size_t src_len, + uint8_t *dst_data, size_t *dst_len, + uint8_t *dst_tag, size_t *dst_tag_len) { - size_t dl = *dst_len; - - *dst_len = src_len; - if (dl < src_len) + if (*dst_len < src_len) return TEE_ERROR_SHORT_BUFFER; + *dst_len = src_len; - switch (algo) { -#if defined(CFG_CRYPTO_CCM) - case TEE_ALG_AES_CCM: - return crypto_aes_ccm_enc_final(ctx, src_data, src_len, - dst_data, dst_tag, dst_tag_len); -#endif -#if defined(CFG_CRYPTO_GCM) - case TEE_ALG_AES_GCM: - return crypto_aes_gcm_enc_final(ctx, src_data, src_len, - dst_data, dst_tag, dst_tag_len); -#endif - default: - return TEE_ERROR_NOT_IMPLEMENTED; - } + return ae_ops(ctx)->enc_final(ctx, src_data, src_len, dst_data, + dst_tag, dst_tag_len); } -TEE_Result crypto_authenc_dec_final(void *ctx __maybe_unused, - uint32_t algo __maybe_unused, - const uint8_t *src_data __maybe_unused, - size_t src_len __maybe_unused, - uint8_t *dst_data __maybe_unused, - size_t *dst_len __maybe_unused, - const uint8_t *tag __maybe_unused, - size_t tag_len __maybe_unused) +TEE_Result crypto_authenc_dec_final(void *ctx, uint32_t algo __unused, + const uint8_t *src_data, size_t src_len, + uint8_t *dst_data, size_t *dst_len, + const uint8_t *tag, size_t tag_len) { - size_t dl = *dst_len; - - *dst_len = src_len; - if (dl < src_len) + if (*dst_len < src_len) return TEE_ERROR_SHORT_BUFFER; + *dst_len = src_len; - switch (algo) { -#if defined(CFG_CRYPTO_CCM) - case TEE_ALG_AES_CCM: - return crypto_aes_ccm_dec_final(ctx, src_data, src_len, - dst_data, tag, tag_len); -#endif -#if defined(CFG_CRYPTO_GCM) - case TEE_ALG_AES_GCM: - return crypto_aes_gcm_dec_final(ctx, src_data, src_len, - dst_data, tag, tag_len); -#endif - default: - return TEE_ERROR_NOT_IMPLEMENTED; - } + return ae_ops(ctx)->dec_final(ctx, src_data, src_len, dst_data, tag, + tag_len); } -void crypto_authenc_final(void *ctx __maybe_unused, - uint32_t algo __maybe_unused) +void crypto_authenc_final(void *ctx, uint32_t algo __unused) { - switch (algo) { -#if defined(CFG_CRYPTO_CCM) - case TEE_ALG_AES_CCM: - crypto_aes_ccm_final(ctx); - break; -#endif -#if defined(CFG_CRYPTO_GCM) - case TEE_ALG_AES_GCM: - crypto_aes_gcm_final(ctx); - break; -#endif - default: - break; - } + ae_ops(ctx)->final(ctx); +} + +void crypto_authenc_free_ctx(void *ctx, uint32_t algo __unused) +{ + if (ctx) + ae_ops(ctx)->free_ctx(ctx); +} + +void crypto_authenc_copy_state(void *dst_ctx, void *src_ctx, + uint32_t algo __unused) +{ + ae_ops(dst_ctx)->copy_state(dst_ctx, src_ctx); } #if !defined(_CFG_CRYPTO_WITH_ACIPHER) diff --git a/core/include/crypto/aes-ccm.h b/core/include/crypto/aes-ccm.h deleted file mode 100644 index 365c6550..00000000 --- a/core/include/crypto/aes-ccm.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (c) 2017, Linaro Limited - */ - -#ifndef __CRYPTO_AES_CCM_H -#define __CRYPTO_AES_CCM_H - -#include <tee_api_types.h> - -TEE_Result crypto_aes_ccm_alloc_ctx(void **ctx); -TEE_Result crypto_aes_ccm_init(void *ctx, TEE_OperationMode mode, - 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 crypto_aes_ccm_update_aad(void *ctx, const uint8_t *data, - size_t len); -TEE_Result crypto_aes_ccm_update_payload(void *ctx, TEE_OperationMode mode, - const uint8_t *src_data, - size_t len, uint8_t *dst_data); -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 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); -void crypto_aes_ccm_final(void *ctx); -void crypto_aes_ccm_free_ctx(void *ctx); -void crypto_aes_ccm_copy_state(void *dst_ctx, void *src_ctx); - -#endif /*__CRYPTO_AES_CCM_H*/ - diff --git a/core/include/crypto/aes-gcm.h b/core/include/crypto/aes-gcm.h deleted file mode 100644 index f67fe1ea..00000000 --- a/core/include/crypto/aes-gcm.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (c) 2017, Linaro Limited - */ - -#ifndef __CRYPTO_AES_GCM_H -#define __CRYPTO_AES_GCM_H - -#include <tee_api_types.h> - -TEE_Result crypto_aes_gcm_alloc_ctx(void **ctx); -TEE_Result crypto_aes_gcm_init(void *ctx, TEE_OperationMode mode, - const uint8_t *key, size_t key_len, - const uint8_t *nonce, size_t nonce_len, - size_t tag_len); -TEE_Result crypto_aes_gcm_update_aad(void *ctx, const uint8_t *data, - size_t len); -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 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 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); -void crypto_aes_gcm_final(void *ctx); -void crypto_aes_gcm_free_ctx(void *ctx); -void crypto_aes_gcm_copy_state(void *dst_ctx, void *src_ctx); - -#endif /*__CRYPTO_AES_GCM_H*/ diff --git a/core/include/crypto/crypto_impl.h b/core/include/crypto/crypto_impl.h index dc07a72e..1ae9e7a3 100644 --- a/core/include/crypto/crypto_impl.h +++ b/core/include/crypto/crypto_impl.h @@ -194,4 +194,42 @@ TEE_Result crypto_des3_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx); CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des_cbc, cipher) CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des3_cbc, cipher) #endif + +/* + * The crypto context used by the crypto_authen_*() functions below is + * defined by struct crypto_authenc_ctx. + */ +struct crypto_authenc_ctx { + const struct crypto_authenc_ops *ops; +}; + +struct crypto_authenc_ops { + TEE_Result (*init)(struct crypto_authenc_ctx *ctx, + TEE_OperationMode mode, + 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 (*update_aad)(struct crypto_authenc_ctx *ctx, + const uint8_t *data, size_t len); + TEE_Result (*update_payload)(struct crypto_authenc_ctx *ctx, + TEE_OperationMode mode, + const uint8_t *src_data, size_t len, + uint8_t *dst_data); + TEE_Result (*enc_final)(struct crypto_authenc_ctx *ctx, + const uint8_t *src_data, size_t len, + uint8_t *dst_data, uint8_t *dst_tag, + size_t *dst_tag_len); + TEE_Result (*dec_final)(struct crypto_authenc_ctx *ctx, + const uint8_t *src_data, size_t len, + uint8_t *dst_data, const uint8_t *tag, + size_t tag_len); + void (*final)(struct crypto_authenc_ctx *ctx); + void (*free_ctx)(struct crypto_authenc_ctx *ctx); + void (*copy_state)(struct crypto_authenc_ctx *dst_ctx, + struct crypto_authenc_ctx *src_ctx); +}; + +TEE_Result crypto_aes_ccm_alloc_ctx(struct crypto_authenc_ctx **ctx); +TEE_Result crypto_aes_gcm_alloc_ctx(struct crypto_authenc_ctx **ctx); #endif /*__CRYPTO_CRYPTO_IMPL_H*/ 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 |