diff --git a/MAINTAINERS b/MAINTAINERS index 5d7e04ced2c..e79d757e89c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -224,6 +224,7 @@ Marvell Armada 70x0, Armada 80x0, Armada 3700, OcteonTX2 CN96XX, OcteonTX2 CFN95 R: Tao Lu [@taovcu] S: Maintained F: core/arch/arm/plat-marvell/ +F: core/drivers/crypto/marvell/ MediaTek R: GM Lin [@p870613] diff --git a/core/drivers/crypto/marvell/authenc.c b/core/drivers/crypto/marvell/authenc.c new file mode 100644 index 00000000000..3d0998b4d03 --- /dev/null +++ b/core/drivers/crypto/marvell/authenc.c @@ -0,0 +1,497 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2026, Marvell + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mrvl_ehsm_cryp.h" + +struct mrvl_ae_ctx { + struct crypto_authenc_ctx a_ctx; + struct mrvl_cryp_context cryp_ctx; +}; + +static struct mrvl_ae_ctx *to_mrvl_ae_ctx(struct crypto_authenc_ctx *ctx) +{ + assert(ctx); + + return container_of(ctx, struct mrvl_ae_ctx, a_ctx); +} + +static TEE_Result mrvl_ae_initialize(struct drvcrypt_authenc_init *dinit) +{ + TEE_Result ret = TEE_SUCCESS; + struct mrvl_ae_ctx *c = to_mrvl_ae_ctx(dinit->ctx); + struct mrvl_cryp_context *ctx = &c->cryp_ctx; + + mrvl_ehsm_cryp_lock(); + + ctx->iv_len = dinit->nonce.length; + ctx->iv_data = mrvl_ehsm_mem_alloc(ctx->iv_len); + if (!ctx->iv_data) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + memcpy(ctx->iv_data, dinit->nonce.data, ctx->iv_len); + + ctx->aad_len = dinit->aad_len; + ctx->aad_cur_idx = 0; + ctx->aad_data = mrvl_ehsm_mem_alloc(ctx->aad_len); + if (!ctx->aad_data) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ctx->op_enc_dec = dinit->encrypt; + ctx->tag_len = dinit->tag_len; + + ctx->key_len = dinit->key.length; + ctx->key = mrvl_ehsm_mem_alloc(ctx->key_len); + if (!ctx->key) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + memcpy(ctx->key, dinit->key.data, ctx->key_len); + + ret = mrvl_ehsm_aes_gcm_init(ctx->op_enc_dec, (void *)ctx->key, + ctx->key_len, ctx->aad_len, + ctx->tag_len, ctx->iv_len, + ctx->iv_data, 0); + if (ret != TEE_SUCCESS) + goto out; + + ret = mrvl_ehsm_aes_context_store(&ctx->context_id); + if (ret != TEE_SUCCESS) + goto out; + + ctx->is_new = true; + +out: + if (ret != TEE_SUCCESS) { + mrvl_ehsm_mem_free(ctx->key); + mrvl_ehsm_mem_free(ctx->aad_data); + mrvl_ehsm_mem_free(ctx->iv_data); + ctx->key = NULL; + ctx->aad_data = NULL; + ctx->iv_data = NULL; + } + + mrvl_ehsm_cryp_unlock(); + + return ret; +} + +static TEE_Result +mrvl_ae_update_aad(struct drvcrypt_authenc_update_aad *dupdate) +{ + TEE_Result ret = TEE_SUCCESS; + struct mrvl_ae_ctx *c = to_mrvl_ae_ctx(dupdate->ctx); + struct mrvl_cryp_context *ctx = &c->cryp_ctx; + + if ((dupdate->aad.length + ctx->aad_cur_idx) <= ctx->aad_len) { + memcpy(ctx->aad_data + ctx->aad_cur_idx, dupdate->aad.data, + dupdate->aad.length); + ctx->aad_cur_idx += dupdate->aad.length; + } else { + ret = TEE_ERROR_BAD_PARAMETERS; + } + + return ret; +} + +static TEE_Result +mrvl_ae_update_payload(struct drvcrypt_authenc_update_payload *dupdate) +{ + TEE_Result ret = TEE_SUCCESS; + struct mrvl_ae_ctx *c = to_mrvl_ae_ctx(dupdate->ctx); + struct mrvl_cryp_context *ctx = &c->cryp_ctx; + uint8_t *payload_buf = NULL; + uint8_t *encdata_buf = NULL; + size_t payload_buf_len = 0; + size_t encdata_buf_len = 0; + uint32_t context_id = 0; + size_t iv = 0; + +#if defined(PLATFORM_FLAVOR_cn10ka) || defined(PLATFORM_FLAVOR_cn10kb) || \ + defined(PLATFORM_FLAVOR_cnf10ka) || defined(PLATFORM_FLAVOR_cnf10kb) + return TEE_ERROR_NOT_IMPLEMENTED; +#endif + mrvl_ehsm_cryp_lock(); + + ret = mrvl_ehsm_aes_context_load(ctx->context_id); + if (ret != TEE_SUCCESS) + goto out; + + if (ctx->is_new) { + /* IV is not 12-byte, load IV part of AES operation payload */ + if (ctx->iv_len != 12) + iv = ctx->iv_len; + else + iv = 0; + + payload_buf_len = iv + ctx->aad_len + dupdate->src.length; + + payload_buf = mrvl_ehsm_mem_alloc(payload_buf_len); + if (!payload_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + encdata_buf_len = iv + ctx->aad_len + dupdate->dst.length; + + encdata_buf = mrvl_ehsm_mem_alloc(encdata_buf_len); + if (!encdata_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + memcpy(payload_buf, ctx->iv_data, iv); + + memcpy(payload_buf + iv, ctx->aad_data, ctx->aad_cur_idx); + memcpy(payload_buf + iv + ctx->aad_cur_idx, dupdate->src.data, + dupdate->src.length); + + ret = mrvl_ehsm_aes_gcm_update_payload(payload_buf, + dupdate->src.length, + encdata_buf, + dupdate->dst.length, + ctx->is_new); + + if (ret != TEE_SUCCESS) + goto out; + + memcpy(dupdate->dst.data, encdata_buf + iv + ctx->aad_cur_idx, + dupdate->dst.length); + + ctx->is_new = false; + + context_id = ctx->context_id; + ret = mrvl_ehsm_aes_context_store(&ctx->context_id); + if (ret != TEE_SUCCESS) + goto out; + + ret = mrvl_ehsm_aes_context_release(context_id); + if (ret != TEE_SUCCESS) + goto out; + + } else { + payload_buf = mrvl_ehsm_mem_alloc(dupdate->src.length); + if (!payload_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + encdata_buf = mrvl_ehsm_mem_alloc(dupdate->dst.length); + if (!encdata_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + memcpy(payload_buf, dupdate->src.data, dupdate->src.length); + + ret = mrvl_ehsm_aes_gcm_update_payload(payload_buf, + dupdate->src.length, + encdata_buf, + dupdate->dst.length, + ctx->is_new); + + if (ret != TEE_SUCCESS) + goto out; + + memcpy(dupdate->dst.data, encdata_buf, dupdate->dst.length); + } + +out: + mrvl_ehsm_mem_free(encdata_buf); + mrvl_ehsm_mem_free(payload_buf); + + mrvl_ehsm_cryp_unlock(); + + return ret; +} + +static TEE_Result mrvl_ae_enc_final(struct drvcrypt_authenc_final *dfinal) +{ + TEE_Result ret = TEE_SUCCESS; + struct mrvl_ae_ctx *c = to_mrvl_ae_ctx(dfinal->ctx); + struct mrvl_cryp_context *ctx = &c->cryp_ctx; + uint8_t *payload_buf = NULL; + uint8_t *encdata_buf = NULL; + size_t payload_buf_len = 0; + size_t encdata_buf_len = 0; + size_t iv = 0; + + mrvl_ehsm_cryp_lock(); + + ret = mrvl_ehsm_aes_context_load(ctx->context_id); + if (ret != TEE_SUCCESS) + goto out; + + if (ctx->is_new) { + /* IV is not 12-byte, load IV part of AES operation payload */ + if (ctx->iv_len != 12) + iv = ctx->iv_len; + else + iv = 0; + + payload_buf_len = iv + ctx->aad_len + dfinal->src.length; + + payload_buf = mrvl_ehsm_mem_alloc(payload_buf_len); + if (!payload_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + encdata_buf_len = iv + ctx->aad_len + dfinal->dst.length + + dfinal->tag.length; + + encdata_buf = mrvl_ehsm_mem_alloc(encdata_buf_len); + if (!encdata_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + memcpy(payload_buf, ctx->iv_data, iv); + + memcpy(payload_buf + iv, ctx->aad_data, ctx->aad_cur_idx); + memcpy(payload_buf + iv + ctx->aad_cur_idx, dfinal->src.data, + dfinal->src.length); + + ret = mrvl_ehsm_aes_gcm_final(payload_buf, dfinal->src.length, + encdata_buf, dfinal->dst.length, + ctx->is_new); + + if (ret != TEE_SUCCESS) + goto out; + + memcpy(dfinal->dst.data, encdata_buf + iv + ctx->aad_cur_idx, + dfinal->dst.length); + memcpy(dfinal->tag.data, encdata_buf + iv + ctx->aad_cur_idx + + dfinal->dst.length, dfinal->tag.length); + + } else { + payload_buf_len = dfinal->src.length; + + payload_buf = mrvl_ehsm_mem_alloc(payload_buf_len); + if (!payload_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + encdata_buf_len = dfinal->dst.length + dfinal->tag.length; + + encdata_buf = mrvl_ehsm_mem_alloc(encdata_buf_len); + if (!encdata_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + memcpy(payload_buf, dfinal->src.data, dfinal->src.length); + + ret = mrvl_ehsm_aes_gcm_final(payload_buf, dfinal->src.length, + encdata_buf, dfinal->dst.length, + ctx->is_new); + + if (ret != TEE_SUCCESS) + goto out; + + memcpy(dfinal->dst.data, encdata_buf, dfinal->dst.length); + memcpy(dfinal->tag.data, encdata_buf + dfinal->dst.length, + dfinal->tag.length); + } +out: + mrvl_ehsm_mem_free(encdata_buf); + mrvl_ehsm_mem_free(payload_buf); + + mrvl_ehsm_cryp_unlock(); + + return ret; +} + +static TEE_Result mrvl_ae_dec_final(struct drvcrypt_authenc_final *dfinal) +{ + TEE_Result ret = TEE_SUCCESS; + struct mrvl_ae_ctx *c = to_mrvl_ae_ctx(dfinal->ctx); + struct mrvl_cryp_context *ctx = &c->cryp_ctx; + uint8_t *encdata_buf = NULL; + uint8_t *decdata_buf = NULL; + size_t buf_len = 0; + size_t iv = 0; + + mrvl_ehsm_cryp_lock(); + + ret = mrvl_ehsm_aes_context_load(ctx->context_id); + if (ret != TEE_SUCCESS) + goto out; + + if (ctx->is_new) { + if (ctx->iv_len != 12) + iv = ctx->iv_len; + else + iv = 0; + + buf_len = iv + ctx->aad_len + dfinal->src.length + + dfinal->tag.length; + + encdata_buf = mrvl_ehsm_mem_alloc(buf_len); + if (!encdata_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + decdata_buf = mrvl_ehsm_mem_alloc(buf_len); + if (!decdata_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + memcpy(encdata_buf, ctx->iv_data, iv); + + memcpy(encdata_buf + iv, ctx->aad_data, ctx->aad_cur_idx); + memcpy(encdata_buf + iv + ctx->aad_cur_idx, dfinal->src.data, + dfinal->src.length); + memcpy(encdata_buf + iv + ctx->aad_cur_idx + dfinal->src.length, + dfinal->tag.data, dfinal->tag.length); + + ret = mrvl_ehsm_aes_gcm_final(encdata_buf, dfinal->src.length, + decdata_buf, dfinal->dst.length, + ctx->is_new); + + if (ret != TEE_SUCCESS) + goto out; + + memcpy(dfinal->dst.data, decdata_buf + iv + ctx->aad_cur_idx, + dfinal->dst.length); + + } else { + buf_len = dfinal->src.length + dfinal->tag.length; + + encdata_buf = mrvl_ehsm_mem_alloc(buf_len); + if (!encdata_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + decdata_buf = mrvl_ehsm_mem_alloc(buf_len); + if (!decdata_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + memcpy(encdata_buf, dfinal->src.data, dfinal->src.length); + memcpy(encdata_buf + dfinal->src.length, dfinal->tag.data, + dfinal->tag.length); + + ret = mrvl_ehsm_aes_gcm_final(encdata_buf, dfinal->src.length, + decdata_buf, dfinal->dst.length, + ctx->is_new); + + if (ret != TEE_SUCCESS) + goto out; + + memcpy(dfinal->dst.data, decdata_buf, dfinal->dst.length); + } + +out: + mrvl_ehsm_mem_free(decdata_buf); + mrvl_ehsm_mem_free(encdata_buf); + + mrvl_ehsm_cryp_unlock(); + + return ret; +} + +static void mrvl_ae_final(void *ctx __unused) +{ +} + +static void mrvl_ae_free(void *ctx) +{ + struct mrvl_ae_ctx *c = to_mrvl_ae_ctx(ctx); + struct mrvl_cryp_context *cryp_ctx = &c->cryp_ctx; + + mrvl_ehsm_cryp_lock(); + mrvl_ehsm_aes_context_release(cryp_ctx->context_id); + mrvl_ehsm_cryp_unlock(); + + mrvl_ehsm_aes_cryp_put(); + + mrvl_ehsm_mem_free(cryp_ctx->iv_data); + mrvl_ehsm_mem_free(cryp_ctx->aad_data); + mrvl_ehsm_mem_free(cryp_ctx->key); + + free(c); +} + +static void mrvl_ae_copy_state(void *dst_ctx, void *src_ctx) +{ + struct mrvl_ae_ctx *src = to_mrvl_ae_ctx(src_ctx); + struct mrvl_ae_ctx *dst = to_mrvl_ae_ctx(dst_ctx); + + memcpy(dst, src, sizeof(*dst)); +} + +/* + * Allocate the SW authenc data context + * + * @ctx [out] Caller context variable + * @algo Algorithm ID of the context + */ +static TEE_Result mrvl_ae_allocate(void **ctx, uint32_t algo) +{ + struct mrvl_ae_ctx *c = NULL; + + if (algo != TEE_ALG_AES_GCM) + return TEE_ERROR_NOT_IMPLEMENTED; + + if (!mrvl_ehsm_aes_cryp_get()) { + DMSG("%s ehsm aes busy, algo: %x\n", __func__, algo); + return TEE_ERROR_NOT_IMPLEMENTED; + } + + c = calloc(1, sizeof(*c)); + if (!c) { + mrvl_ehsm_aes_cryp_put(); + return TEE_ERROR_OUT_OF_MEMORY; + } + + *ctx = &c->a_ctx; + + return TEE_SUCCESS; +} + +/* + * Registration of the Authenc Driver + */ +static struct drvcrypt_authenc mrvl_gcm = { + .alloc_ctx = &mrvl_ae_allocate, + .update_aad = &mrvl_ae_update_aad, + .update_payload = &mrvl_ae_update_payload, + .enc_final = &mrvl_ae_enc_final, + .dec_final = &mrvl_ae_dec_final, + .free_ctx = &mrvl_ae_free, + .init = &mrvl_ae_initialize, + .final = &mrvl_ae_final, + .copy_state = &mrvl_ae_copy_state, +}; + +static TEE_Result mrvl_register_authenc(void) +{ + return drvcrypt_register_authenc(&mrvl_gcm); +} + +early_init(mrvl_register_authenc); diff --git a/core/drivers/crypto/marvell/cipher.c b/core/drivers/crypto/marvell/cipher.c new file mode 100644 index 00000000000..448353aba92 --- /dev/null +++ b/core/drivers/crypto/marvell/cipher.c @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2026, Marvell + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mrvl_ehsm_cryp.h" + +struct mrvl_cipher_ctx { + struct crypto_cipher_ctx a_ctx; + struct mrvl_cryp_context cryp_ctx; + enum mrvl_cryp_algo_mode algo; +}; + +static struct mrvl_cipher_ctx *to_mrvl_cipher_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx); + + return container_of(ctx, struct mrvl_cipher_ctx, a_ctx); +} + +static TEE_Result mrvl_cipher_initialize(struct drvcrypt_cipher_init *dinit) +{ + TEE_Result ret = TEE_SUCCESS; + struct mrvl_cipher_ctx *c = to_mrvl_cipher_ctx(dinit->ctx); + struct mrvl_cryp_context *ctx = &c->cryp_ctx; + + mrvl_ehsm_cryp_lock(); + + /* if already initialized free the previous content and context */ + if (ctx->initialized) { + mrvl_ehsm_mem_free(ctx->iv_data); + mrvl_ehsm_mem_free(ctx->key); + mrvl_ehsm_mem_free(ctx->key2); + ctx->iv_data = NULL; + ctx->key = NULL; + ctx->key2 = NULL; + + if (ctx->context_id != 0) { + ret = mrvl_ehsm_aes_context_release(ctx->context_id); + if (ret != TEE_SUCCESS) + goto out; + } + } + + ctx->iv_len = dinit->iv.length; + ctx->iv_data = mrvl_ehsm_mem_alloc(ctx->iv_len); + if (!ctx->iv_data) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + memcpy(ctx->iv_data, dinit->iv.data, ctx->iv_len); + + ctx->op_enc_dec = dinit->encrypt; + + ctx->key_len = dinit->key1.length; + ctx->key = mrvl_ehsm_mem_alloc(ctx->key_len); + if (!ctx->key) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + memcpy(ctx->key, dinit->key1.data, ctx->key_len); + + if (dinit->key2.length) { + ctx->key2_len = dinit->key2.length; + ctx->key2 = mrvl_ehsm_mem_alloc(ctx->key2_len); + if (!ctx->key2) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + memcpy(ctx->key2, dinit->key2.data, ctx->key2_len); + } + + ret = mrvl_ehsm_aes_init(c->algo, ctx->op_enc_dec, (void *)ctx->key, + ctx->key_len, (void *)ctx->key2, ctx->key2_len, + ctx->iv_data, 0); + if (ret != TEE_SUCCESS) + goto out; + + ret = mrvl_ehsm_aes_context_store(&ctx->context_id); + if (ret != TEE_SUCCESS) + goto out; + + ctx->is_new = true; + ctx->initialized = true; + +out: + if (ret != TEE_SUCCESS) { + mrvl_ehsm_mem_free(ctx->key2); + mrvl_ehsm_mem_free(ctx->key); + mrvl_ehsm_mem_free(ctx->iv_data); + ctx->key2 = NULL; + ctx->key = NULL; + ctx->iv_data = NULL; + } + + mrvl_ehsm_cryp_unlock(); + + return ret; +} + +static TEE_Result mrvl_cipher_update(struct drvcrypt_cipher_update *dupdate) +{ + TEE_Result ret = TEE_SUCCESS; + struct mrvl_cipher_ctx *c = to_mrvl_cipher_ctx(dupdate->ctx); + struct mrvl_cryp_context *ctx = &c->cryp_ctx; + size_t payload_len = dupdate->src.length; + size_t dstdata_len = dupdate->dst.length; + uint8_t *payload_buf = NULL; + uint8_t *dstdata_buf = NULL; + + mrvl_ehsm_cryp_lock(); + + ret = mrvl_ehsm_aes_context_load(ctx->context_id); + if (ret != TEE_SUCCESS) + goto out; + + payload_buf = mrvl_ehsm_mem_alloc(payload_len); + if (!payload_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + dstdata_buf = mrvl_ehsm_mem_alloc(dstdata_len); + if (!dstdata_buf) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + memcpy(payload_buf, dupdate->src.data, payload_len); + + ret = mrvl_ehsm_aes_update_payload(payload_buf, payload_len, + dstdata_buf, dstdata_len, + ctx->is_new, dupdate->last); + + if (ret != TEE_SUCCESS) + goto out; + + memcpy(dupdate->dst.data, dstdata_buf, dstdata_len); + + ctx->is_new = false; + +out: + mrvl_ehsm_mem_free(dstdata_buf); + mrvl_ehsm_mem_free(payload_buf); + + mrvl_ehsm_cryp_unlock(); + + return ret; +} + +static void mrvl_cipher_final(void *ctx __unused) +{ +} + +static void mrvl_cipher_free(void *ctx) +{ + struct mrvl_cipher_ctx *c = to_mrvl_cipher_ctx(ctx); + struct mrvl_cryp_context *cryp_ctx = &c->cryp_ctx; + + mrvl_ehsm_cryp_lock(); + mrvl_ehsm_aes_context_release(cryp_ctx->context_id); + mrvl_ehsm_cryp_unlock(); + + mrvl_ehsm_aes_cryp_put(); + + mrvl_ehsm_mem_free(cryp_ctx->iv_data); + mrvl_ehsm_mem_free(cryp_ctx->key); + mrvl_ehsm_mem_free(cryp_ctx->key2); + + free(c); +} + +static void mrvl_cipher_copy_state(void *dst_ctx, void *src_ctx) +{ + struct mrvl_cipher_ctx *src = to_mrvl_cipher_ctx(src_ctx); + struct mrvl_cipher_ctx *dst = to_mrvl_cipher_ctx(dst_ctx); + + memcpy(dst, src, sizeof(*dst)); +} + +static TEE_Result alloc_ctx(void **ctx, enum mrvl_cryp_algo_mode algo) +{ + struct mrvl_cipher_ctx *c = NULL; + + if (!mrvl_ehsm_aes_cryp_get()) { + DMSG("%s ehsm aes is busy, algo: %x\n", __func__, algo); + return TEE_ERROR_NOT_IMPLEMENTED; + } + + c = calloc(1, sizeof(*c)); + if (!c) { + mrvl_ehsm_aes_cryp_put(); + return TEE_ERROR_OUT_OF_MEMORY; + } + + c->algo = algo; + *ctx = &c->a_ctx; + + return TEE_SUCCESS; +} + +/* + * Allocate the SW authenc data context + * + * @ctx [out] Caller context variable + * @algo Algorithm ID of the context + */ +static TEE_Result mrvl_cipher_allocate(void **ctx, uint32_t algo) +{ + /* + * Convert TEE_ALGO id to internal id + */ + switch (algo) { + case TEE_ALG_AES_ECB_NOPAD: + return alloc_ctx(ctx, MRVL_CRYP_MODE_AES_ECB); + case TEE_ALG_AES_CBC_NOPAD: + return alloc_ctx(ctx, MRVL_CRYP_MODE_AES_CBC); + case TEE_ALG_AES_CTR: + return alloc_ctx(ctx, MRVL_CRYP_MODE_AES_CTR); + case TEE_ALG_AES_XTS: + return alloc_ctx(ctx, MRVL_CRYP_MODE_AES_XTS); + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } +} + +/* + * Registration of the Cipher Driver + */ +static struct drvcrypt_cipher mrvl_cipher = { + .alloc_ctx = &mrvl_cipher_allocate, + .update = &mrvl_cipher_update, + .free_ctx = &mrvl_cipher_free, + .init = &mrvl_cipher_initialize, + .final = &mrvl_cipher_final, + .copy_state = &mrvl_cipher_copy_state, +}; + +static TEE_Result mrvl_register_cipher(void) +{ + return drvcrypt_register_cipher(&mrvl_cipher); +} + +early_init(mrvl_register_cipher); diff --git a/core/drivers/crypto/marvell/crypto.mk b/core/drivers/crypto/marvell/crypto.mk new file mode 100644 index 00000000000..f1a82830fe5 --- /dev/null +++ b/core/drivers/crypto/marvell/crypto.mk @@ -0,0 +1,12 @@ +ifeq ($(CFG_MARVELL_CRYPTO_DRIVER),y) +# Enable Marvell eHSM crypto engine +$(call force,CFG_MARVELL_EHSM_CRYPTO,y) + +# Enable the crypto driver +$(call force,CFG_CRYPTO_DRIVER,y) + +CFG_CRYPTO_DRIVER_DEBUG ?= 0 + +$(call force,CFG_CRYPTO_DRV_AUTHENC,y) +$(call force,CFG_CRYPTO_DRV_CIPHER,y) +endif diff --git a/core/drivers/crypto/marvell/ehsm/ehsm-aes.c b/core/drivers/crypto/marvell/ehsm/ehsm-aes.c new file mode 100644 index 00000000000..b126ac4d2a4 --- /dev/null +++ b/core/drivers/crypto/marvell/ehsm/ehsm-aes.c @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2026 Marvell. + */ + +#include + +#include "ehsm.h" +#include "ehsm-aes.h" +#include "ehsm-hal.h" +#include "ehsm-security.h" +/* hw_status sentinel: hardware was not invoked */ +#define EHSM_STATUS_NOT_CALLED ((enum ehsm_status)-1) + +struct ehsm_result ehsm_aes_zeroize(struct ehsm_handle *handle) +{ + struct ehsm_command cmd = { }; + enum ehsm_status estat = STATUS_SUCCESS; + + cmd.opcode = BCM_AES_ZEROIZE; + estat = ehsm_command(handle, &cmd); + return (struct ehsm_result){ .sec_ret = (estat == STATUS_SUCCESS) ? + SEC_NO_ERROR : SEC_HW_FAILURE, + .hw_status = estat }; +} + +struct ehsm_result ehsm_aes_init(struct ehsm_handle *handle, + bool decrypt, + enum ehsm_aes_key_size key_size, + enum ehsm_aes_mode aes_mode, + uint8_t ctr_modular, + bool endian_swap) +{ + struct ehsm_command cmd = { }; + enum ehsm_status estat = STATUS_SUCCESS; + + if (aes_mode == EHSM_AES_MODE_CTR) { + if (ctr_modular >= 128) + return (struct ehsm_result){ + .sec_ret = SEC_INVALID_PARAMETER, + .hw_status = EHSM_STATUS_NOT_CALLED, + }; + } else if (aes_mode == EHSM_AES_MODE_GCM) { + return (struct ehsm_result){ + .sec_ret = SEC_INVALID_PARAMETER, + .hw_status = EHSM_STATUS_NOT_CALLED, + }; + } else if (ctr_modular != 0) { + return (struct ehsm_result){ + .sec_ret = SEC_INVALID_PARAMETER, + .hw_status = EHSM_STATUS_NOT_CALLED, + }; + } + + switch (key_size) { + case EHSM_AES_KEY_128: + case EHSM_AES_KEY_192: + case EHSM_AES_KEY_256: + break; + default: + return (struct ehsm_result){ + .sec_ret = SEC_INVALID_PARAMETER, + .hw_status = EHSM_STATUS_NOT_CALLED, + }; + } + + cmd.args[0] = decrypt; + cmd.args[1] = key_size; + cmd.args[2] = aes_mode; + cmd.args[3] = ctr_modular; + cmd.args[8] = endian_swap; + cmd.opcode = BCM_AES_INIT; + estat = ehsm_command(handle, &cmd); + return (struct ehsm_result){ .sec_ret = (estat == STATUS_SUCCESS) ? + SEC_NO_ERROR : SEC_HW_FAILURE, + .hw_status = estat }; +} + +struct ehsm_result ehsm_aes_gcm_init(struct ehsm_handle *handle, + bool decrypt, + uint32_t aad_size, + uint32_t tag_size, + uint32_t iv_size, + const uint32_t *iv, + bool endian_swap) +{ + struct ehsm_command cmd = { }; + enum ehsm_status estat = STATUS_SUCCESS; + + cmd.args[0] = decrypt; + cmd.args[1] = aad_size; + if (tag_size < 1 || tag_size > 16) + return (struct ehsm_result){ + .sec_ret = SEC_INVALID_PARAMETER, + .hw_status = EHSM_STATUS_NOT_CALLED, + }; + cmd.args[2] = tag_size; + cmd.args[3] = iv_size; + if (iv_size == 0) { +#ifdef CFG_MARVELL_EHSM_CN10K + cmd.args[4] = iv[0]; + cmd.args[5] = iv[1]; + cmd.args[6] = iv[2]; +#else + cmd.args[4] = iv[2]; + cmd.args[5] = iv[1]; + cmd.args[6] = iv[0]; +#endif + } + cmd.args[7] = endian_swap; + cmd.opcode = BCM_AES_GCM_INIT; + estat = ehsm_command(handle, &cmd); + return (struct ehsm_result){ .sec_ret = (estat == STATUS_SUCCESS) ? + SEC_NO_ERROR : SEC_HW_FAILURE, + .hw_status = estat }; +} + +struct ehsm_result ehsm_aes_load_key(struct ehsm_handle *handle, + enum ehsm_aes_key_size key_size, + const void *key, + bool secondary_key, + bool endian_swap) +{ + struct ehsm_command cmd = { }; + enum ehsm_status estat = STATUS_SUCCESS; + + cmd.args[0] = key_size; + cmd.args[1] = ehsm_addr_low(key); + cmd.args[2] = ehsm_addr_hi(key); + cmd.args[3] = secondary_key; + cmd.args[5] = endian_swap; + cmd.opcode = BCM_AES_LOAD_KEY; + estat = ehsm_command(handle, &cmd); + return (struct ehsm_result){ .sec_ret = (estat == STATUS_SUCCESS) ? + SEC_NO_ERROR : SEC_HW_FAILURE, + .hw_status = estat }; +} + +struct ehsm_result ehsm_aes_load_iv(struct ehsm_handle *handle, + const void *iv, + bool endian_swap) +{ + struct ehsm_command cmd = { }; + enum ehsm_status estat = STATUS_SUCCESS; + + cmd.args[0] = ehsm_addr_low(iv); + cmd.args[1] = ehsm_addr_hi(iv); + cmd.args[3] = endian_swap; + cmd.opcode = BCM_AES_LOAD_IV; + estat = ehsm_command(handle, &cmd); + return (struct ehsm_result){ .sec_ret = (estat == STATUS_SUCCESS) ? + SEC_NO_ERROR : SEC_HW_FAILURE, + .hw_status = estat }; +} + +struct ehsm_result ehsm_aes_process(struct ehsm_handle *handle, + const void *src, + void *dest, + uint64_t payload_len_byte, + uint32_t timeout, + bool is_new, + bool is_final, + bool block_tag_gen __maybe_unused, + struct ehsm_dtd *src_list, + struct ehsm_dtd *dest_list) +{ + struct ehsm_command cmd = { }; + enum ehsm_status estat = STATUS_SUCCESS; + + if (src) { + cmd.args[0] = ehsm_addr_low(src); + cmd.args[1] = ehsm_addr_hi(src); + } + if (dest) { + cmd.args[2] = ehsm_addr_low(dest); + cmd.args[3] = ehsm_addr_hi(dest); + } + + reg_pair_from_64(payload_len_byte, &cmd.args[5], &cmd.args[4]); + cmd.args[6] = is_new; + cmd.args[8] = timeout; + cmd.args[10] = is_final; +#ifdef CFG_MARVELL_EHSM_CN20K + cmd.args[11] = block_tag_gen; +#endif + if (src_list) { + cmd.args[12] = ehsm_addr_low(src_list); + cmd.args[13] = ehsm_addr_hi(src_list); + } + if (dest_list) { + cmd.args[14] = ehsm_addr_low(dest_list); + cmd.args[15] = ehsm_addr_hi(dest_list); + } + cmd.opcode = BCM_AES_PROCESS; + estat = ehsm_command(handle, &cmd); + return (struct ehsm_result){ .sec_ret = (estat == STATUS_SUCCESS) ? + SEC_NO_ERROR : SEC_HW_FAILURE, + .hw_status = estat }; +} + +#ifdef CFG_EHSM_CONTEXT_STORE_SUPPORT +struct ehsm_result ehsm_context_store(struct ehsm_handle *handle, + enum context_engine_id engine_id, + const void *pcontextid, + const void *ptoken) +{ + struct ehsm_command cmd = { }; + enum ehsm_status estat = STATUS_SUCCESS; + + cmd.args[0] = engine_id; + + if (pcontextid) { + cmd.args[1] = ehsm_addr_low(pcontextid); + cmd.args[2] = ehsm_addr_hi(pcontextid); + } + if (ptoken) { + cmd.args[3] = ehsm_addr_low(ptoken); + cmd.args[4] = ehsm_addr_hi(ptoken); + } + cmd.opcode = EHSM_CONTEXT_STORE; + estat = ehsm_command(handle, &cmd); + return (struct ehsm_result){ .sec_ret = (estat == STATUS_SUCCESS) ? + SEC_NO_ERROR : SEC_HW_FAILURE, + .hw_status = estat }; +} + +struct ehsm_result ehsm_context_load(struct ehsm_handle *handle, + enum context_engine_id engine_id, + uint32_t context_id, + const void *ptoken) +{ + struct ehsm_command cmd = { }; + enum ehsm_status estat = STATUS_SUCCESS; + + cmd.args[0] = engine_id; + cmd.args[1] = context_id; + + if (ptoken) { + cmd.args[2] = ehsm_addr_low(ptoken); + cmd.args[3] = ehsm_addr_hi(ptoken); + } + cmd.opcode = EHSM_CONTEXT_LOAD; + estat = ehsm_command(handle, &cmd); + return (struct ehsm_result){ .sec_ret = (estat == STATUS_SUCCESS) ? + SEC_NO_ERROR : SEC_HW_FAILURE, + .hw_status = estat }; +} + +struct ehsm_result ehsm_context_release(struct ehsm_handle *handle, + enum context_engine_id engine_id, + uint32_t context_id, + const void *ptoken) +{ + struct ehsm_command cmd = { }; + enum ehsm_status estat = STATUS_SUCCESS; + + cmd.args[0] = engine_id; + cmd.args[1] = context_id; + + if (ptoken) { + cmd.args[2] = ehsm_addr_low(ptoken); + cmd.args[3] = ehsm_addr_hi(ptoken); + } + cmd.opcode = EHSM_CONTEXT_RELEASE; + estat = ehsm_command(handle, &cmd); + return (struct ehsm_result){ .sec_ret = (estat == STATUS_SUCCESS) ? + SEC_NO_ERROR : SEC_HW_FAILURE, + .hw_status = estat }; +} +#endif diff --git a/core/drivers/crypto/marvell/ehsm/ehsm.c b/core/drivers/crypto/marvell/ehsm/ehsm.c new file mode 100644 index 00000000000..c843713b758 --- /dev/null +++ b/core/drivers/crypto/marvell/ehsm/ehsm.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2026 Marvell. + */ + +#include +#include +#include +#include +#include + +#include "ehsm.h" +#include "ehsm-hal.h" +#include "ehsm-security.h" + +/** Offset to mailbox registers */ +static const size_t ehsm_mailbox_offsets[EHSM_NUM_MAILBOXES] = { + EHSM_INPUT_ARG0, + EHSM_CORE1_INPUT_ARG0, +#ifdef CFG_MARVELL_EHSM_CN20K + EHSM_CORE2_INPUT_ARG0, +#endif +}; + +static const size_t ehsm_host_int_reg[EHSM_NUM_MAILBOXES] = { + EHSM_CORE0_HOST_INT_RST_REG, + EHSM_CORE1_HOST_INT_RST_REG, +#ifdef CFG_MARVELL_EHSM_CN20K + EHSM_CORE2_HOST_INT_RST_REG, +#endif +}; + +static const size_t ehsm_cmd_status_reg[EHSM_NUM_MAILBOXES] = { + EHSM_CMD_RET_STATUS, + EHSM_CORE1_CMD_RET_STATUS, +#ifdef CFG_MARVELL_EHSM_CN20K + EHSM_CORE2_CMD_RET_STATUS, +#endif +}; + +static const uint32_t +ehsm_cmd_fifo_status_buf_full_mask[EHSM_NUM_MAILBOXES] = { + EHSM_CMD_FIFO_STATUS_CORE0_CMD_STATUS_BUFFER_FULL, + EHSM_CMD_FIFO_STATUS_CORE1_CMD_STATUS_BUFFER_FULL, +#ifdef CFG_MARVELL_EHSM_CN20K + EHSM_CMD_FIFO_STATUS_CORE2_CMD_STATUS_BUFFER_FULL, +#endif +}; + +/* + * Prepare the device for access to the eHSM. + */ +register_phys_mem_pgdir(MEM_AREA_IO_SEC, EHSM_BASE_ADDR, CORE_MMU_PGDIR_SIZE); + +int ehsm_initialize(struct ehsm_handle *handle, unsigned int mbox) +{ + ehsm_debug("%s(%p, %u)\n", __func__, handle, mbox); + memset(handle, 0, sizeof(*handle)); + ehsm_debug("Preparing CSR access\n"); + + if (mbox >= EHSM_NUM_MAILBOXES) { + ehsm_printf("Error: mailbox %u out of range 0..%u\n", mbox, + EHSM_NUM_MAILBOXES - 1); + return SEC_INVALID_MAILBOX; + } + + handle->mbox_offset = ehsm_mailbox_offsets[mbox]; + handle->ehsm_cmd = (struct ehsm_command *)(handle->mbox_offset); + + handle->host_int_reg = ehsm_host_int_reg[mbox]; + handle->cmd_buf_full_mask = ehsm_cmd_fifo_status_buf_full_mask[mbox]; + handle->cmd_status_reg = ehsm_cmd_status_reg[mbox]; + + handle->mbox = mbox; + ehsm_prepare_csr_access(handle); + + /* Make sure to disable interrupts */ + ehsm_write_csr(handle, handle->host_int_reg, + ehsm_read_csr(handle, handle->host_int_reg) | + EHSM_CMD_CPL_STS_BIT); + + handle->initialized = true; + + return SEC_NO_ERROR; +} + +enum ehsm_status ehsm_command(struct ehsm_handle *handle, + struct ehsm_command *cmd) +{ + struct ehsm_command *hcmd = handle->ehsm_cmd; + uint32_t int_status = 0; + uint32_t fifo_status = 0; + uint32_t rparam = 0; + unsigned int i = 0; + uint64_t timeout = timeout_init_us(EHSM_CRYP_TIMEOUT_US); + +#if DEBUG_EHSM + ehsm_debug("%s: opcode: %u\n", __func__, cmd->opcode); + for (i = 0; i < EHSM_NUM_ARGS; i++) + ehsm_debug("arg[%d]: 0x%"PRIx32"\n", i, cmd->args[i]); +#endif + + if (!handle->ehsm_ready) { + while (!(ehsm_read_csr(handle, EHSM_CMD_FIFO_STATUS) & + EHSM_CMD_FIFO_STATUS_READY)) + if (timeout_elapsed(timeout)) + goto err_timeout; + + int_status = ehsm_read_csr(handle, handle->host_int_reg); + ehsm_write_csr(handle, handle->host_int_reg, + int_status | EHSM_CMD_CPL_STS_BIT); + + handle->ehsm_ready = true; + } + + /* Wait for command fifo to empty */ + timeout = timeout_init_us(EHSM_CRYP_TIMEOUT_US); + do { + if (timeout_elapsed(timeout)) + goto err_timeout; + + fifo_status = ehsm_read_csr(handle, EHSM_CMD_FIFO_STATUS); + } while (fifo_status & handle->cmd_buf_full_mask); + + for (i = 0; i < EHSM_NUM_ARGS; i++) + ehsm_write_csr(handle, ehsm_ptr_to_reg(&hcmd->args[i]), + cmd->args[i]); + + ehsm_write_csr(handle, ehsm_ptr_to_reg(&hcmd->opcode), cmd->opcode); + + timeout = timeout_init_us(EHSM_CRYP_TIMEOUT_US); + do { + if (timeout_elapsed(timeout)) + goto err_timeout; + + int_status = ehsm_read_csr(handle, handle->host_int_reg); + } while (!(int_status & EHSM_CMD_CPL_STS_BIT)); + + ehsm_write_csr(handle, handle->host_int_reg, + int_status | EHSM_CMD_CPL_STS_BIT); + + /* Get status */ + cmd->ret_status = ehsm_read_csr(handle, handle->cmd_status_reg); + for (i = 0; i < EHSM_NUM_ARGS; i++) { + rparam = ehsm_read_csr(handle, + ehsm_ptr_to_reg(&hcmd->ret_params[i])); + cmd->ret_params[i] = rparam; + } + +#if DEBUG_EHSM + ehsm_debug("%s: Return status: 0x%x\n", __func__, cmd->ret_status); + + for (i = 0; i < EHSM_NUM_ARGS; i++) + ehsm_debug("ret_params[%u]: 0x%"PRIx32"\n", i, + cmd->ret_params[i]); +#endif + + handle->last_ehsm_status = cmd->ret_status; + return (enum ehsm_status)cmd->ret_status; + +err_timeout: + return STATUS_FAILURE; +} + +void ehsm_clear_command(struct ehsm_command *cmd) +{ + memset(cmd->args, 0, sizeof(cmd->args)); + memset(cmd->ret_params, 0, sizeof(cmd->ret_params)); + + cmd->opcode = 0; + cmd->ret_status = 0; +} diff --git a/core/drivers/crypto/marvell/ehsm/include/ehsm-aes.h b/core/drivers/crypto/marvell/ehsm/include/ehsm-aes.h new file mode 100644 index 00000000000..58f622aa0d4 --- /dev/null +++ b/core/drivers/crypto/marvell/ehsm/include/ehsm-aes.h @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2026 Marvell. + */ + +#ifndef __EHSM_AES_H__ +#define __EHSM_AES_H__ +#include +#include + +#include "ehsm.h" +#include "ehsm-security.h" + +struct ehsm_result { + enum sec_return sec_ret; + enum ehsm_status hw_status; +}; + +enum ehsm_aes_mode { + EHSM_AES_MODE_ECB = 0, + EHSM_AES_MODE_CBC = 1, + EHSM_AES_MODE_CTR = 2, + EHSM_AES_MODE_XTS = 3, + EHSM_AES_MODE_KEY_WRAP = 4, + EHSM_AES_MODE_CFB = 5, + EHSM_AES_MODE_OFB = 6, + EHSM_AES_MODE_GCM = 7, +}; + +enum ehsm_aes_key_size { + EHSM_AES_KEY_128 = 128, + EHSM_AES_KEY_192 = 192, + EHSM_AES_KEY_256 = 256, +}; + +/* + * Reset AES engine and zeroize key registers + * + * @param handle Pointer to EHSM handle + * + * @return SEC_NO_ERROR + */ +struct ehsm_result ehsm_aes_zeroize(struct ehsm_handle *handle); + +/* + * Initialize AES engine for non-GCM mode + * + * @param handle Pointer to EHSM handle + * @param decrypt True to decrypt, false to encrypt + * @param key_size Key size, 128, 192, or 256 + * @param aes_mode AES encryption mode to use + * @param ctr_modular Used in AES_CTR mode, + * 0-15 - use 128 bit counter, + * 16-127 - Use specified counter + * @param endian_swap Set true for big-endian mode + * + * @return SEC_NO_ERROR or SEC_INVALID_PARAMETER + */ +struct ehsm_result ehsm_aes_init(struct ehsm_handle *handle, + bool decrypt, + enum ehsm_aes_key_size key_size, + enum ehsm_aes_mode aes_mode, + uint8_t ctr_modular, + bool endian_swap); + +/* + * Initialize AES engine for GCM mode + * + * @param handle Pointer to EHSM handle + * @param decrypt True to decrypt, false to encrypt + * @param aad_size Additional authentication data size in bytes + * @param tag_size Authenticated tag size [1-16] + * @param iv_size IV size in bytes 0 use 12 bytes from IV + * @param[in] iv Initialization vector + * @param endian_swap Use big endian data + * + * @return SEC_NO_ERROR or STATUS_INVALID_TAG_SIZE + */ +struct ehsm_result ehsm_aes_gcm_init(struct ehsm_handle *handle, + bool decrypt, + uint32_t aad_size, + uint32_t tag_size, + uint32_t iv_size, + const uint32_t *iv, + bool endian_swap); + +/* + * Load a plaintext key into the EHSM register bank + * + * @param handle EHSM handle pointer + * @param key_size 128, 192, or 256 + * @param[in] key Key pointer + * @param secondary_key Load key into secondary registers + * @param endian_swap Set true for big endian + * + * @return SEC_NO_ERROR, STATUS_DISABLED_IN_FIPS_MODE, + * STATUS_UNSUPPORTED_PARAMETER, STATUS_NULL_POINTER, + * STATUS_DMA_BUFFER_UNALIGNED, STATUS_DATA_BUFFER_UNALIGNED + */ +struct ehsm_result ehsm_aes_load_key(struct ehsm_handle *handle, + enum ehsm_aes_key_size key_size, + const void *key, + bool secondary_key, + bool endian_swap); + +/* + * Load initialization vector + * + * @param handle Pointer to EHSM pointer + * @param[in] iv Pointer to initialization vector + * @param endian_swap True for big endian + * + * @return SEC_NO_ERROR, STATUS_NULL_POINTER, STATUS_DMA_BUFFER_UNALIGNED + */ +struct ehsm_result ehsm_aes_load_iv(struct ehsm_handle *handle, + const void *iv, + bool endian_swap); + +/* + * Perform AES encryption/decryption + * + * @param handle Pointer to EHSM handle + * @param[in] src Pointer to source data, can be NULL + * @param[out] dest Encrypted/decrypted data + * @param payload_len_byte Number of bytes to encrypt/decrypt + * @param timeout Number of rounds to poll DMA for completion, + * If 0, 10^^9 + * @param is_new Set true to begin a new encryption round, + * false to continue existing round. + * @param is_final Set true if end of data, false if more data + * @param block_tag_gen Block generation of GCM TAG, + * Only if is_final = 1 + * @param[in] src_list List of source data, can be NULL of src set + * @param[out] dest_list List of destination data, can be NULL if + * dest is set. + * + * @return SEC_NO_ERROR, STATUS_NULL_POINTER, + * STATUS_DMA_DATA_BUFFER_UNALIGNED, + * STATUS_DMA_LINKED_LIST_UNALIGNED, + * STATUS_INVALID_REQUEST, STATUS_MSG_LENGTH_OVERFLOW + * + */ +struct ehsm_result ehsm_aes_process(struct ehsm_handle *handle, + const void *src, + void *dest, + uint64_t payload_len_byte, + uint32_t timeout, + bool is_new, + bool is_final, + bool block_tag_gen, + struct ehsm_dtd *src_list, + struct ehsm_dtd *dest_list); + +#ifdef CFG_EHSM_CONTEXT_STORE_SUPPORT +/* + * Stores the engine context + * + * @param handle Pointer to EHSM handle + * @param engine_id Context engine id type + * @param pcontextid Pointer to store context ID + * @param ptoken Pointer to store the token + * + * @return STATUS_NULL_POINTER, STATUS_DMA_DATA_BUFFER_UNALIGNED, + * STATUS_BAD_ENGINE_ID, STATUS_INTERNAL_CONTEXT_SLOT_RUN_OUT, + * STATUS_INVALID_REQUEST, STATUS_INVALID_LENGTH, SEC_NO_ERROR + */ +struct ehsm_result ehsm_context_store(struct ehsm_handle *handle, + enum context_engine_id engine_id, + const void *pcontextid, + const void *ptoken); + +/* + * Loads the engine context + * + * @param handle Pointer to EHSM handle + * @param engine_id Context engine id type + * @param contextid Context ID + * @param ptoken Pointer to store the token + * + * @return STATUS_NULL_POINTER, STATUS_DMA_DATA_BUFFER_UNALIGNED, + * STATUS_BAD_ENGINE_ID, STATUS_INTERNAL_CONTEXT_SLOT_RUN_OUT, + * STATUS_INVALID_REQUEST, STATUS_INVALID_LENGTH, SEC_NO_ERROR + */ +struct ehsm_result ehsm_context_load(struct ehsm_handle *handle, + enum context_engine_id engine_id, + uint32_t context_id, + const void *ptoken); + +/* + * Releases the engine context + * + * @param handle Pointer to EHSM handle + * @param engine_id Context engine id type + * @param contextid Context ID + * @param ptoken Pointer to store the token + * + * @return STATUS_NULL_POINTER, STATUS_DMA_DATA_BUFFER_UNALIGNED, + * STATUS_BAD_ENGINE_ID, STATUS_INTERNAL_CONTEXT_SLOT_RUN_OUT, + * STATUS_INVALID_REQUEST, STATUS_INVALID_LENGTH, SEC_NO_ERROR + */ +struct ehsm_result ehsm_context_release(struct ehsm_handle *handle, + enum context_engine_id engine_id, + uint32_t context_id, + const void *ptoken); +#endif +#endif /* __EHSM_AES_H__ */ diff --git a/core/drivers/crypto/marvell/ehsm/include/ehsm-hal.h b/core/drivers/crypto/marvell/ehsm/include/ehsm-hal.h new file mode 100644 index 00000000000..4d7da99fe3a --- /dev/null +++ b/core/drivers/crypto/marvell/ehsm/include/ehsm-hal.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2026 Marvell. + */ + +#ifndef __EHSM_HAL_H__ +#define __EHSM_HAL_H__ + +#include +#include +#include +#include +#include + +#include "ehsm.h" + +#define ehsm_printf(fmt, ...) DMSG(fmt, ##__VA_ARGS__) + +#define DEBUG_EHSM 0 + +#if (DEBUG_EHSM) +#define ehsm_debug(fmt, ...) ehsm_printf(fmt, ##__VA_ARGS__) +#else +#define ehsm_debug(fmt, ...) +#endif + +#ifdef CFG_MARVELL_EHSM_CN10K +/* + * Base address for eHSM standard registers. + */ +#define EHSM_BASE_ADDR (0x80B000000000ULL) + +/* + * eHSM mailbox for AES crypto operations + */ +#define EHSM_CRYPTO_MAILBOX EHSM_MAILBOX0 +#endif + +#ifdef CFG_MARVELL_EHSM_CN20K +/* + * Base address for eHSM standard registers. + */ +#define EHSM_BASE_ADDR (0xC01700000000ULL) + +/* + * eHSM mailbox for AES crypto operations + */ +#define EHSM_CRYPTO_MAILBOX EHSM_MAILBOX1 +#endif + +static inline void ehsm_prepare_csr_access(struct ehsm_handle *handle) +{ + handle->ehsm_base = (uint32_t *)phys_to_virt_io(EHSM_BASE_ADDR, + CORE_MMU_PGDIR_SIZE); +} + +static inline uint32_t ehsm_ptr_to_reg(void *ptr) +{ + return (uint32_t)((unsigned long)ptr & 0xffffffff); +} + +static inline uint32_t ehsm_read_csr(const struct ehsm_handle *handle, + size_t reg) +{ + return io_read32((vaddr_t)(handle->ehsm_base + reg / 4)); +} + +static inline void ehsm_write_csr(struct ehsm_handle *handle, + size_t reg, uint32_t value) +{ + io_write32((vaddr_t)(handle->ehsm_base + reg / 4), value); +} + +static inline uint32_t ehsm_addr_low(const void *ptr) +{ + return (uint32_t)(unsigned long)ptr & 0xFFFFFFFFUL; +} + +static inline uint32_t ehsm_addr_hi(const void *ptr) +{ + return (((unsigned long)ptr) >> 32) & 0xFFFFFFFF; +} +#endif /* __EHSM_HAL_H__ */ diff --git a/core/drivers/crypto/marvell/ehsm/include/ehsm-security.h b/core/drivers/crypto/marvell/ehsm/include/ehsm-security.h new file mode 100644 index 00000000000..900d0aafb88 --- /dev/null +++ b/core/drivers/crypto/marvell/ehsm/include/ehsm-security.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2026 Marvell. + */ + +#ifndef __EHSM_SECURITY_H__ +#define __EHSM_SECURITY_H__ + +/* Security specific errors. */ +enum sec_return { + SEC_NO_ERROR = 0, + SEC_INVALID_PARAMETER = 1028, + SEC_INVALID_MAILBOX = 2030, + SEC_HW_FAILURE = 3001, +}; +#endif /* __EHSM_SECURITY_H__ */ diff --git a/core/drivers/crypto/marvell/ehsm/include/ehsm.h b/core/drivers/crypto/marvell/ehsm/include/ehsm.h new file mode 100644 index 00000000000..ba5860aebb6 --- /dev/null +++ b/core/drivers/crypto/marvell/ehsm/include/ehsm.h @@ -0,0 +1,759 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2026 Marvell. + */ + +#ifndef __EHSM_H__ +#define __EHSM_H__ + +#include +#include +#include + +#ifdef CFG_MARVELL_EHSM_CN20K +/* Number of mailboxes available in eHSM */ +#define EHSM_NUM_MAILBOXES 3 + +/* Maximum number of context slots allowed in eHSM */ +#define EHSM_AES_MAX_CONTEXT_SLOTS 9 +#endif + +#ifdef CFG_MARVELL_EHSM_CN10K +/* Number of mailboxes available in eHSM */ +#define EHSM_NUM_MAILBOXES 2 +#endif + +enum ehsm_mailboxes { + EHSM_MAILBOX0 = 0, + EHSM_MAILBOX1 = 1, + EHSM_MAILBOX2 = 2, +}; + +#define EHSM_NUM_ARGS 16 +#define EHSM_ALIGNMENT 32UL +#define EHSM_CRYP_TIMEOUT_US 1000000UL + +enum ehsm_regs { + /* Request input registers */ + EHSM_INPUT_ARG0 = 0x0, + EHSM_INPUT_ARG1 = 0x4, + EHSM_INPUT_ARG2 = 0x8, + EHSM_INPUT_ARG3 = 0xc, + EHSM_INPUT_ARG4 = 0x10, + EHSM_INPUT_ARG5 = 0x14, + EHSM_INPUT_ARG6 = 0x18, + EHSM_INPUT_ARG7 = 0x1c, + EHSM_INPUT_ARG8 = 0x20, + EHSM_INPUT_ARG9 = 0x24, + EHSM_INPUT_ARG10 = 0x28, + EHSM_INPUT_ARG11 = 0x2c, + EHSM_INPUT_ARG12 = 0x30, + EHSM_INPUT_ARG13 = 0x34, + EHSM_INPUT_ARG14 = 0x38, + EHSM_INPUT_ARG15 = 0x3c, + EHSM_INPUT_CMD = 0x40, + + /* Request output registers */ + EHSM_CMD_RET_STATUS = 0x80, + EHSM_CMD_RET_PARAMETER0 = 0x84, + EHSM_CMD_RET_PARAMETER1 = 0x88, + EHSM_CMD_RET_PARAMETER2 = 0x8c, + EHSM_CMD_RET_PARAMETER3 = 0x90, + EHSM_CMD_RET_PARAMETER4 = 0x94, + EHSM_CMD_RET_PARAMETER5 = 0x98, + EHSM_CMD_RET_PARAMETER6 = 0x9c, + EHSM_CMD_RET_PARAMETER7 = 0xa0, + EHSM_CMD_RET_PARAMETER8 = 0xa4, + EHSM_CMD_RET_PARAMETER9 = 0xa8, + EHSM_CMD_RET_PARAMETER10 = 0xac, + EHSM_CMD_RET_PARAMETER11 = 0xb0, + EHSM_CMD_RET_PARAMETER12 = 0xb4, + EHSM_CMD_RET_PARAMETER13 = 0xb8, + EHSM_CMD_RET_PARAMETER14 = 0xbc, + EHSM_CMD_RET_PARAMETER15 = 0xc0, + + /* Status register */ +#define EHSM_CMD_FIFO_STATUS_CORE0_CMD_STATUS_BUFFER_FULL BIT(4) +#define EHSM_CMD_FIFO_STATUS_CORE1_CMD_STATUS_BUFFER_FULL BIT(5) +#define EHSM_CMD_FIFO_STATUS_CORE2_CMD_STATUS_BUFFER_FULL BIT(6) +#define EHSM_CMD_FIFO_STATUS_READY BIT(8) +#define EHSM_CMD_FIFO_STATUS_CMD_EXE_CORE_ID BIT(16) +#define EHSM_CMD_FIFO_STATUS_CORE0_CMD_STATUS_READ_DONE BIT(18) +#define EHSM_CMD_FIFO_STATUS_CORE1_CMD_STATUS_READ_DONE BIT(19) +#define EHSM_CMD_FIFO_STATUS_CORE2_CMD_STATUS_READ_DONE BIT(20) + + EHSM_CMD_FIFO_STATUS = 0xc4, + + /* Host interrupt reset register */ + EHSM_CORE0_HOST_INT_RST_REG = 0xc8, +#define EHSM_CMD_CPL_STS_BIT BIT(0) + EHSM_CORE0_HOST_INT_MASK_REG = 0xcc, + + /* Shadow register definitions */ +#define EHSM_LCS_REG_VALID 1 +#define EHSM_PERMANENT_SOC_JTAG_STATE 5 +#define EHSM_DIS_UART_STATE 7 +#define EHSM_DIS_SOC_JTAG_STATE 8 +#define EHSM_LCS_STATE_MASK 0xF +#define EHSM_RAW_STATE 0x0 +#define EHSM_PROVISION_STATE 0x1 +#define EHSM_DEPLOY_STATE 0x3 +#define EHSM_FA_STATE 0x7 +#define EHSM_SHADOW_REGS_VALID_BIT 1 + EHSM_SHADOW_REG_STATUS = 0x100, + + /* UUID registers */ + EHSM_UUID0 = 0x104, + EHSM_UUID1 = 0x108, + EHSM_UUID2 = 0x10c, + + /* Shadow registers */ + EHSM_LCS_DEBUG_STATUS = 0x114, +#define EHSM_DISABLE_BOOT_STRAP0 0 +#define EHSM_DISABLE_BOOT_STRAP1 1 +#define EHSM_DISABLE_BOOT_STRAP2 2 +#define EHSM_DISABLE_BOOT_STRAP3 3 +#define EHSM_DISABLE_BOOT_STRAP4 4 +#define EHSM_DISABLE_BOOT_STRAP5 5 +#define EHSM_DISABLE_BOOT_STRAP6 6 +#define EHSM_SECURE_BOOT 7 +#define EHSM_ENCRYPTED_BOOT 8 +#define EHSM_MEASURED_BOOT 9 +#define EHSM_SECURE_BOOT_LOCK 10 +#define EHSM_ENCRYPTED_BOOT_LOCK 11 +#define EHSM_MEASURED_BOOT_LOCK 12 +#define EHSM_SCHEME_ID_MASK 0x0000F0000 +#define EHSM_SCHEME_ID_SHIFT 16 +#define EHSM_SCHEME_ID(X) (((X) << EHSM_SCHEME_ID_SHIFT) & \ + EHSM_SCHEME_ID_MASK) +#define EHSM_SCHEME_ID_SET(X, V) (((X) & ~EHSM_SCHEME_ID_MASK) | \ + EHSM_SCHEME_ID(V)) + EHSM_BOOTROM_STATUS = 0x118, + EHSM_ROOT_TRUST_STATUS = 0x11c, +#define EHSM_KEY_REV_CONTROL_SHIFT 16 +#define EHSM_KEY_REV_CONTROL_MASK 0x00070000 +#define EHSM_KEY_REV_CONTROL(X) (((X) << EHSM_KEY_REV_CONTROL_SHIFT) & \ + EHSM_KEY_REV_CONTROL_MASK) + EHSM_KEY_REVOC_STATUS = 0x120, +#define EHSM_LOADER_FW_MASK 0x0000000F +#define EHSM_LOADER_FW(X) ((X) & EHSM_LOADER_FW_MASK) + EHSM_SEC_VER_REG = 0x124, + EHSM_BOOTSTRAP_PIN_STATUS = 0x128, + EHSM_REMAINING_CONFIG_STATUS = 0x12c, + EHSM_CHAIN_OF_TRUST_STATUS = 0x130, + +#ifdef CFG_MARVELL_EHSM_CN10K + /* Request input registers */ + EHSM_CORE1_INPUT_ARG0 = 0x140, + EHSM_CORE1_INPUT_ARG1 = 0x144, + EHSM_CORE1_INPUT_ARG2 = 0x148, + EHSM_CORE1_INPUT_ARG3 = 0x14c, + EHSM_CORE1_INPUT_ARG4 = 0x150, + EHSM_CORE1_INPUT_ARG5 = 0x154, + EHSM_CORE1_INPUT_ARG6 = 0x158, + EHSM_CORE1_INPUT_ARG7 = 0x15c, + EHSM_CORE1_INPUT_ARG8 = 0x160, + EHSM_CORE1_INPUT_ARG9 = 0x164, + EHSM_CORE1_INPUT_ARG10 = 0x168, + EHSM_CORE1_INPUT_ARG11 = 0x16c, + EHSM_CORE1_INPUT_ARG12 = 0x170, + EHSM_CORE1_INPUT_ARG13 = 0x174, + EHSM_CORE1_INPUT_ARG14 = 0x178, + EHSM_CORE1_INPUT_ARG15 = 0x17c, + EHSM_CORE1_INPUT_CMD = 0x180, + + /* Request output registers */ + EHSM_CORE1_CMD_RET_STATUS = 0x1a0, + EHSM_CORE1_CMD_RET_PARAMETER0 = 0x1a4, + EHSM_CORE1_CMD_RET_PARAMETER1 = 0x1a8, + EHSM_CORE1_CMD_RET_PARAMETER2 = 0x1ac, + EHSM_CORE1_CMD_RET_PARAMETER3 = 0x1b0, + EHSM_CORE1_CMD_RET_PARAMETER4 = 0x1b4, + EHSM_CORE1_CMD_RET_PARAMETER5 = 0x1b8, + EHSM_CORE1_CMD_RET_PARAMETER6 = 0x1bc, + EHSM_CORE1_CMD_RET_PARAMETER7 = 0x1c0, + EHSM_CORE1_CMD_RET_PARAMETER8 = 0x1c4, + EHSM_CORE1_CMD_RET_PARAMETER9 = 0x1c8, + EHSM_CORE1_CMD_RET_PARAMETER10 = 0x1cc, + EHSM_CORE1_CMD_RET_PARAMETER11 = 0x1d0, + EHSM_CORE1_CMD_RET_PARAMETER12 = 0x1d4, + EHSM_CORE1_CMD_RET_PARAMETER13 = 0x1d8, + EHSM_CORE1_CMD_RET_PARAMETER14 = 0x1dc, + EHSM_CORE1_CMD_RET_PARAMETER15 = 0x1e0, + + /* Host interrupt reset register */ + EHSM_CORE1_HOST_INT_RST_REG = 0x1e4, + EHSM_CORE1_HOST_INT_MASK_REG = 0x1e8, +#endif +#ifdef CFG_MARVELL_EHSM_CN20K + /* Request input registers */ + EHSM_CORE1_INPUT_ARG0 = 0x400, + EHSM_CORE1_INPUT_ARG1 = 0x404, + EHSM_CORE1_INPUT_ARG2 = 0x408, + EHSM_CORE1_INPUT_ARG3 = 0x40c, + EHSM_CORE1_INPUT_ARG4 = 0x410, + EHSM_CORE1_INPUT_ARG5 = 0x414, + EHSM_CORE1_INPUT_ARG6 = 0x418, + EHSM_CORE1_INPUT_ARG7 = 0x41c, + EHSM_CORE1_INPUT_ARG8 = 0x420, + EHSM_CORE1_INPUT_ARG9 = 0x424, + EHSM_CORE1_INPUT_ARG10 = 0x428, + EHSM_CORE1_INPUT_ARG11 = 0x42c, + EHSM_CORE1_INPUT_ARG12 = 0x430, + EHSM_CORE1_INPUT_ARG13 = 0x434, + EHSM_CORE1_INPUT_ARG14 = 0x438, + EHSM_CORE1_INPUT_ARG15 = 0x43c, + EHSM_CORE1_INPUT_CMD = 0x440, + + /* Request output registers */ + EHSM_CORE1_CMD_RET_STATUS = 0x480, + EHSM_CORE1_CMD_RET_PARAMETER0 = 0x484, + EHSM_CORE1_CMD_RET_PARAMETER1 = 0x488, + EHSM_CORE1_CMD_RET_PARAMETER2 = 0x48c, + EHSM_CORE1_CMD_RET_PARAMETER3 = 0x490, + EHSM_CORE1_CMD_RET_PARAMETER4 = 0x494, + EHSM_CORE1_CMD_RET_PARAMETER5 = 0x498, + EHSM_CORE1_CMD_RET_PARAMETER6 = 0x49c, + EHSM_CORE1_CMD_RET_PARAMETER7 = 0x4a0, + EHSM_CORE1_CMD_RET_PARAMETER8 = 0x4a4, + EHSM_CORE1_CMD_RET_PARAMETER9 = 0x4a8, + EHSM_CORE1_CMD_RET_PARAMETER10 = 0x4ac, + EHSM_CORE1_CMD_RET_PARAMETER11 = 0x4b0, + EHSM_CORE1_CMD_RET_PARAMETER12 = 0x4b4, + EHSM_CORE1_CMD_RET_PARAMETER13 = 0x4b8, + EHSM_CORE1_CMD_RET_PARAMETER14 = 0x4bc, + EHSM_CORE1_CMD_RET_PARAMETER15 = 0x4c0, + + /* Host interrupt reset register */ + EHSM_CORE1_HOST_INT_RST_REG = 0x4c8, + EHSM_CORE1_HOST_INT_MASK_REG = 0x4cc, + + /* Request input registers */ + EHSM_CORE2_INPUT_ARG0 = 0x500, + EHSM_CORE2_INPUT_ARG1 = 0x504, + EHSM_CORE2_INPUT_ARG2 = 0x508, + EHSM_CORE2_INPUT_ARG3 = 0x50c, + EHSM_CORE2_INPUT_ARG4 = 0x510, + EHSM_CORE2_INPUT_ARG5 = 0x514, + EHSM_CORE2_INPUT_ARG6 = 0x518, + EHSM_CORE2_INPUT_ARG7 = 0x51c, + EHSM_CORE2_INPUT_ARG8 = 0x520, + EHSM_CORE2_INPUT_ARG9 = 0x524, + EHSM_CORE2_INPUT_ARG10 = 0x528, + EHSM_CORE2_INPUT_ARG11 = 0x52c, + EHSM_CORE2_INPUT_ARG12 = 0x530, + EHSM_CORE2_INPUT_ARG13 = 0x534, + EHSM_CORE2_INPUT_ARG14 = 0x538, + EHSM_CORE2_INPUT_ARG15 = 0x53c, + EHSM_CORE2_INPUT_CMD = 0x540, + + /* Request output registers */ + EHSM_CORE2_CMD_RET_STATUS = 0x580, + EHSM_CORE2_CMD_RET_PARAMETER0 = 0x584, + EHSM_CORE2_CMD_RET_PARAMETER1 = 0x588, + EHSM_CORE2_CMD_RET_PARAMETER2 = 0x58c, + EHSM_CORE2_CMD_RET_PARAMETER3 = 0x590, + EHSM_CORE2_CMD_RET_PARAMETER4 = 0x594, + EHSM_CORE2_CMD_RET_PARAMETER5 = 0x598, + EHSM_CORE2_CMD_RET_PARAMETER6 = 0x59c, + EHSM_CORE2_CMD_RET_PARAMETER7 = 0x5a0, + EHSM_CORE2_CMD_RET_PARAMETER8 = 0x5a4, + EHSM_CORE2_CMD_RET_PARAMETER9 = 0x5a8, + EHSM_CORE2_CMD_RET_PARAMETER10 = 0x5ac, + EHSM_CORE2_CMD_RET_PARAMETER11 = 0x5b0, + EHSM_CORE2_CMD_RET_PARAMETER12 = 0x5b4, + EHSM_CORE2_CMD_RET_PARAMETER13 = 0x5b8, + EHSM_CORE2_CMD_RET_PARAMETER14 = 0x5bc, + EHSM_CORE2_CMD_RET_PARAMETER15 = 0x5c0, + + /* Host interrupt reset register */ + EHSM_CORE2_HOST_INT_RST_REG = 0x5c8, + EHSM_CORE2_HOST_INT_MASK_REG = 0x5cc, +#endif +}; + +enum ehsm_status { + STATUS_SUCCESS = 0, + + STATUS_APB_MISCOMPARE = 6, + STATUS_APB_SLAVE_ERROR = 7, + STATUS_MAILBOX_MISCOMPARE = 8, + STATUS_BAD_XBAR_PATH = 9, + STATUS_BAD_SP_ACCESS_MODE = 10, + STATUS_BAD_CRYPT_ENGINE = 11, + STATUS_BAD_AES_MODE = 12, + STATUS_BAD_HASH_ALGORITHM = 13, + STATUS_BAD_ZMODP_ALGORITHM = 14, + STATUS_BAD_ECP_ALGORITHM = 15, + STATUS_BAD_ECP_BIT_STRENGTH = 16, + STATUS_OTP_CORRUPTED = 17, + STATUS_SCRATCHPAD_OVERFLOW = 18, + STATUS_BAD_SIGNATURE_LENGTH = 19, + STATUS_SIGNATURE_LENGTH_OVERFLOW = 20, + STATUS_HASH_UPDATE_LENGTH_ERROR = 21, + + STATUS_FAILURE = 255, + STATUS_NO_RESOURCES = 257, + STATUS_BAD_DEVICE = 258, + STATUS_NULL_BUFFER = 259, + STATUS_UNSUPPORTED_FUNCTION = 262, + STATUS_UNSUPPORTED_PARAMETER = 263, + STATUS_ILLEGAL_BLOCK_SIZE = 267, + STATUS_PARAMETER_OUT_OF_RANGE = 269, + STATUS_NULL_POINTER = 270, + STATUS_OVERRUN_ERROR = 275, + STATUS_OFFSET_ERROR = 276, + STATUS_BAD_TRANSFER_SIZE = 286, + STATUS_FATAL_INTERNAL_ERROR = 288, + STATUS_INVALID_SIGNATURE = 292, + STATUS_INTEGER_TOO_LARGE = 296, + STATUS_DMA_TIMEOUT = 299, + STATUS_DMA_BUS_ERROR = 300, + STATUS_DMA_PARITY_ERROR = 301, + STATUS_DMA_LINKED_LIST_ACCESS_ERROR = 302, + STATUS_DMA_PAUSE_COMPLETION_TIMEOUT = 303, + STATUS_DMA_IDIOPATHIC_ERROR = 304, + STATUS_HASH_TIMEOUT = 305, + STATUS_AES_TIMEOUT = 306, + STATUS_ZMODP_TIMEOUT = 307, + STATUS_EC_TIMEOUT = 308, + STATUS_MCT_TIMEOUT = 312, + STATUS_EBG_TIMEOUT = 313, + STATUS_OTP_TIMEOUT = 314, + STATUS_BUS_ERROR = 317, + STATUS_DIGEST_MISMATCH = 320, + STATUS_INSUFFICIENT_PRIVILEGE = 321, + STATUS_BAD_ENGINE_ID = 354, + STATUS_INVALID_TOKEN = 359, + STATUS_EROM_ALREADY_LOADED = 365, + STATUS_BIU_MAILBOX_OVERRUN = 366, + STATUS_INVALID_OTP_FIELD = 367, + STATUS_PATCH_EROM_ALREADY_LOADED = 368, + STATUS_APB_ENGINE_ERROR = 369, + STATUS_APB_TIMEOUT = 370, + STATUS_MCT_OVERFLOW = 371, + STATUS_MSG_LENGTH_OVERFLOW = 372, + STATUS_ECP_INVALID_DOMAIN_PARAMETER = 380, + STATUS_EXCEED_MAX_NUM_TRIAL = 381, + STATUS_BIG_NUMBER_OVERFLOW = 382, + STATUS_PER_MSG_NONCE_GEN_FAIL = 383, + STATUS_CRC_TIMEOUT = 384, + + STATUS_ECDSA_VERIFY_FAILED = 512, + STATUS_INVALID_LENGTH = 513, + STATUS_INVALID_KEY_LENGTH = 514, + STATUS_NULL_ENTROPY = 515, + STATUS_NULL_NONCE = 516, + STATUS_INVALID_ENTROPY_LENGTH = 517, + STATUS_INVALID_HANDLE = 518, + STATUS_UNINITIALIZED_INSTANCE = 519, + STATUS_NULL_INTERNAL_POINTER = 520, + STATUS_CORRUPTED_HANDLE = 521, + STATUS_INVALID_HANDLE_INDEX = 522, + STATUS_INVALID_HANDLE_COUNT = 523, + STATUS_INVALID_HANDLE_OFFSET = 524, + STATUS_INVALID_STRING_LENGTH = 525, + STATUS_STRING_UNDERFLOW = 526, + STATUS_STRING_OVERFLOW = 527, + STATUS_NULL_ENTROPY_BUFFER = 528, + STATUS_REQUESTED_LENGTH_TOO_LARGE = 529, + STATUS_DRBG_CATASTROPHIC_ERROR = 530, + STATUS_DRBG_ERROR = 531, + STATUS_NOT_IMPLEMENTED = 532, + STATUS_INT_TIMEOUT = 533, + STATUS_GHASH_TIMEOUT = 534, + + STATUS_AES_LENGTH_ERROR = 535, + STATUS_AES_GCM_TAG_ERROR = 536, + STATUS_AES_DATA_TRANSFER_ERROR = 537, + STATUS_ZMODP_INVALID_OPERAND = 538, + STATUS_ZMODP_DATA_TRANSFER_ERROR = 539, + STATUS_RC4_TIMEOUT = 540, + STATUS_DES_TIMEOUT = 541, + STATUS_RC4_DATA_TRANSFER_ERROR = 542, + STATUS_DES_DATA_TRANSFER_ERROR = 543, + STATUS_DES_LENGTH_ERROR = 544, + STATUS_NULL_ECP_PRIME = 545, + STATUS_ECP_INVALID_MODE = 546, + STATUS_ECP_INVALID_ZERO = 547, + STATUS_ECP_ZERO_OUTPUT = 548, + STATUS_ECP_ZERO_INVERSE = 549, + + STATUS_OTP_UNCORRECTABLE_ERROR = 550, + STATUS_OTP_RKEK_UNAVAILABLE = 551, + STATUS_AUTHENTICATION_TOKEN_MISMATCH = 552, + STATUS_CODE_BINDING_DIGEST_MISMATCH = 553, + STATUS_INVALID_PAYLOAD_COMMAND = 554, + STATUS_NOT_HD_EFUSE_OTP = 555, + + STATUS_UNKNOWN_AES_ERROR = 556, + STATUS_UNKNOWN_DES_ERROR = 558, + STATUS_UNKNOWN_HASH_ERROR = 559, + STATUS_UNKNOWN_ZMODP_ERROR = 560, + STATUS_UNKNOWN_ECP_ERROR = 561, + STATUS_RSA_LENGTH_MISMATCH_ERROR = 562, + STATUS_INVALID_ARGUMENT = 563, + STATUS_INVALID_TAG_SIZE = 564, + STATUS_MNK_ECC_ERROR = 565, + STATUS_INDIVIDUAL_UUID_MISMATCH = 566, + + /* Additional OTP errors */ + STATUS_INVALID_REQUEST = 601, + STATUS_INVALID_KEY = 602, + STATUS_INVALID_KEY_ID = 603, + STATUS_INVALID_SCHEME_ID = 604, + STATUS_LIFECYCLE_POLICY_VIOLATION = 605, + STATUS_OTP_PROVISION_HW_FAILURE = 606, + STATUS_OTP_FIELD_LOCKED = 607, + STATUS_OTP_FIELD_READ_DISABLED = 608, + STATUS_OTP_FIELD_ALREADY_PROVISIONED = 609, + STATUS_OTP_FIELD_NOT_PROVISIONED = 610, + STATUS_OTP_SHADOW_REG_MISMATCH = 611, + STATUS_OTP_ECC_TIMEOUT = 612, + STATUS_OTP_SHADOWING_TIMEOUT = 613, + STATUS_OTP_ECC_UNCORRECTABLE_ERROR = 614, + STATUS_KEY_ID3_MISSING = 615, + STATUS_OTP_ENABLE_DISABLE_EXHAUSTED = 616, + STATUS_OTP_UUID_NOT_PROVISIONED = 617, + STATUS_UNSUPPORTED_KEY_PROVISION_OPTION = 618, + + /* puf related errors */ + STATUS_PUF_UDS_NOT_INSTANTIATED = 620, + STATUS_PUF_UDS_INSTANTIATED = 621, + STATUS_PUF_HW_ERROR_STATE = 622, + STATUS_PUF_HW_TIMEOUT = 623, + STATUS_PUF_KEY_QUALITY_CHECK_FAILURE = 624, + STATUS_PUF_INSTANTIATE_FAILURE = 625, + STATUS_PUF_KEY_GEN_FAILURE = 626, + STATUS_PUF_HEALTH_TEST_FAILURE = 627, + STATUS_PUF_INVALIDATE_FAILURE = 628, + STATUS_PUF_AGING_TEST_TIMEOUT = 629, + STATUS_PUF_REAGENT_MISMATCH = 630, + STATUS_PUF_REAGENT_UNCORRETABLE = 631, + + /* Additional encrypted boot and measured boot errors */ + STATUS_KM_VERSION_MISMATCH = 640, + STATUS_INVALID_CSK_KEY_ID = 641, + STATUS_SCHEME_ID_MISMATCH = 642, + STATUS_UDS_LOAD_DISABLE = 643, + + STATUS_KEY_MANIFEST_NOT_LOADED = 644, + STATUS_KEY_MANIFEST_ALREADY_LOADED = 645, + STATUS_KEY_MANIFEST_OVERSIZE = 646, + STATUS_AUTH_KEY_BIND_UNPROVISIONED = 647, + STATUS_CHALLENGE_MISMATCH = 648, + STATUS_INVALID_TOKEN_SIZE = 649, + STATUS_DMA_UNALIGNED_ADDRESS = 650, + STATUS_KAK_UNPROVISIONED = 651, + STATUS_ZERO_TOKEN = 652, + STATUS_INVALID_KC_ID = 653, + /* KM = key manifest */ + STATUS_INVALID_KM_VERSION = 654, + + STATUS_SIDE_LOAD_KEY_FAILURE = 655, + STATUS_UNSUPPORTED_DIGEST_TYPE = 656, + STATUS_INVALID_EC_POINT = 657, + STATUS_EC521_POINT_PADDDING_ERROR = 658, + STATUS_PIE_OVERSIZE = 659, + STATUS_HEAP_OVERFLOW = 660, + STATUS_INVALID_PM_STATUS = 661, + STATUS_ECP_DISABLED = 662, + STATUS_INVALID_CHECKSUM = 663, + STATUS_INVALID_AUTH_CMD_PACKAGE = 664, + STATUS_KEY_MANIFEST_LOCKED = 665, + STATUS_DISABLED_IN_FIPS_MODE = 666, + STATUS_DMA_LINKED_LIST_UNALIGNED = 667, + STATUS_DMA_LINKED_LIST_TRAS_OVERSIZE = 668, + + /* new SHA3 and SHAKE exclusive errors */ + STATUS_INVALID_SHAKE_DIGEST_LENGTH = 670, + STATUS_HMAC_SHALL_NOT_USE_SHAKE = 671, + STATUS_SHA3_CONTEXT_REG_ACCESS_ERROR = 672, + + STATUS_MEMORY_U32_ACCESS_VIOLATION = 673, + STATUS_EBG_HEALTH_TEST_FAILURE = 674, + STATUS_EBG_CONTINUOUS_HEALTH_TEST_FAILURE = 675, + STATUS_EBG_REPETITION_COUNT_TEST_FAILURE = 676, + STATUS_EBG_ADAPTIVE_PROPORTION_TEST_FAILURE = 677, + + STATUS_FIPS_POLICY_VIOLATION = 700, + STATUS_CRYPTO_DISABLE = 701, + STATUS_SYMMETRIC_KEY_READ_BAN = 702, + + /* JTAG tap handler status */ + STATUS_INVALID_TAP_REQUEST = 800, + STATUS_INVALID_FSM_TRANSITION = 801, + + STATUS_USER_DEFINED = 4096, + STATUS_LAST_ONE +}; + +enum ehsm_opcodes { + BCM_CANT_USE = 0, + BCM_GET_VERSION_INFO = 2, + BCM_RESET = 3, + BCM_SELF_TEST = 4, + BCM_CONFIGURE_DMA = 6, + BCM_GET_SYSTEM_STATE = 7, + BCM_GET_CONTEXT_INFO = 8, + BCM_LOAD_ENGINE_CONTEXT = 9, + BCM_STORE_ENGINE_CONTEXT = 10, + BCM_PURGE_CONTEXT_CACHE = 11, + BCM_AES_INIT = 12, + BCM_AES_ZEROIZE = 13, + BCM_AES_PROCESS = 14, + BCM_AES_LOAD_IV = 15, + BCM_AES_LOAD_KEY = 16, + BCM_AES_KEY_GEN = 17, + BCM_HASH_INIT = 18, + BCM_HASH_ZEROIZE = 19, + BCM_HASH_UPDATE = 20, + BCM_HASH_FINAL = 21, + BCM_HMAC_INIT = 22, + BCM_HMAC_ZEROIZE = 23, + BCM_HMAC_UPDATE = 24, + BCM_HMAC_FINAL = 25, + BCM_HMAC_LOAD_KEY = 26, + BCM_HMAC_KEY_GEN = 27, + BCM_DRBG_GEN_RAN_BITS = 28, + + BCM_DRBG_RESEED = 30, + BCM_OTP_WRITE = 31, + BCM_OTP_READ = 32, + BCM_RSASSA_PKCS_V15_VERIFY_INIT = 33, + BCM_RSASSA_PKCS_V15_VERIFY_UPDATE = 34, + BCM_RSASSA_PKCS_V15_VERIFY_FINAL = 35, + BCM_RSASSA_PKCS_V15_VERIFY = 36, + BCM_MC_INIT = 37, + BCM_MC_READ = 39, + CM_FW_AUTHORIZE = 41, + BCM_EC_ZEROIZE = 42, + BCM_EC_POINT_MULTIPLY = 49, + BCM_EC_POINT_ADD = 50, + BCM_EC_POINT_SUBTRACT = 51, + BCM_EC_ADDITIVE_INVERSION = 52, + BCM_EC_POINT_DOUBLE = 53, + BCM_ZMODP_ZEROIZE = 54, + BCM_ZMODP_PRECOMP_PARAM = 56, + BCM_ZMODP_MULT_INVERSE = 58, + BCM_ZMODP_MODULAR_MULTIPLY = 59, + BCM_ZMODP_MODULAR_EXPONENTIATE = 60, + BCM_SLEEP = 61, + BCM_ZMODP_MODULAR_ADD = 62, + BCM_ZMODP_MODULAR_SUBTRACT = 63, + BCM_DRBG_INSTANTIATE = 64, + BCM_DRBG_GENERATE = 65, + BCM_RESUME = 66, + BCM_AESX_LOAD_KEY = 67, + BCM_AESX_LOAD_IV = 68, + BCM_AESX_INIT = 69, + BCM_AESX_PROCESS = 71, + BCM_AUTHENTICATED_COMMAND = 75, + BCM_TWO_FACTOR_FW_AUTHORIZE = 76, + BCM_RSASSA_PKCS1_V15_TWO_FACTOR_VERIFY = 77, + BCM_PLATFORM_GET_VERSION_INFO = 79, + BCM_AES_KEYWRAP_ENCRYPT_PROCESS = 130, + BCM_AES_KEYWRAP_DECRYPT_PROCESS = 131, + BCM_ECDSA_SIGN = 135, + BCM_ECDSA_VERIFY = 136, + + BCM_DES_INIT = 157, + BCM_DES_LOAD_IV = 158, + BCM_DES_LOAD_KEY = 159, + BCM_DES_PROCESS = 160, + BCM_DES_ZEROIZE = 161, + BCM_AES_GCM_INIT = 162, + + /* PIE KEM OTP Provision Service */ + PIE_RKEK_PROTECTED_PROVISION = 201, + PIE_RSA_OAEP_ENCRYPT = 202, + PIE_RSA_OAEP_ENCRYPT_SESSION_KEY = 203, + PIE_RSA_OAEP_DECRYPT = 204, + + BCM_DRBG_UNINSTANTIATE_CMD = 300, + BCM_GET_ENTROPY = 301, + + BCM_RSADSA_PSS_SIGN = 312, + + BCM_RSADSA_PSS_VERIFY = 314, + + EHSM_LCS_ADVANCE = 500, + EHSM_RKEK_PROVISION = 501, + EHSM_BOOT_PORT_DISABLE = 502, + EHSM_SECURE_BOOT_PROVISION = 503, + EHSM_ENCRYPTED_BOOT_PROVISION = 504, + EHSM_MEASURED_BOOT_PROVISION = 505, + EHSM_DEBUG_PORT_DISABLE = 506, + EHSM_IROM_SECURITY_MODE_PROVISION = 507, + EHSM_IROMM_BOOT_CONFIG_PROVISION = 508, + EHSM_OEM_BLOCK_PROVISION = 509, + EHSM_OEM_BLOCK_LOCK = 510, + EHSM_OEM_BLOCK_READ = 511, + EHSM_EBG_HEALTH_TEST_CUTOFF_VALUE_PROVISION = 512, + EHSM_SET_OTP_PROGRAMMING_DURATION = 513, + EHSM_PUF_UDS_ACTIVATION = 514, + EHSM_BOOTROM_RESERVED_PARAMETER_PROVISION = 515, + EHSM_DEVICE_KEY_MIXER_PROVISION = 516, + EHSM_DEVICE_KEY_MIXER_DISABLE = 517, + EHSM_EFUSE_DISABLE = 518, + EHSM_PUF_OTP_DUMP = 519, + + /* Primitives for encrypted boot */ + EHSM_ENCRYPTED_BOOT_LOAD_KEY = 530, + EHSM_ENCRYPTED_BOOT_INIT = 531, + EHSM_ENCRYPTED_BOOT_UNWRAP_KEY = 532, + + /* Primitives for measured boot */ + EHSM_MEASURED_BOOT_LOAD_UDS = 540, + EHSM_MEASURED_BOOT_LOAD_UDS_LOCK = 541, + EHSM_DICE_INIT = 542, + EHSM_DICE_UPDATE = 543, + EHSM_DICE_FINAL = 544, + EHSM_GET_MEASUREMENT_DIGESTS = 545, + EHSM_GET_MEASUREMENTS = 546, + + EHSM_SECURE_BOOT_AUTHENTICATION = 550, + EHSM_PIE_SECURE_LOAD = 551, + EHSM_PIE_UNLOAD = 552, + EHSM_KEY_MANIFEST_INSTALL = 553, + EHSM_GET_CHALLENGE = 554, + EHSM_AUTH_CMD = 555, + EHSM_KEY_MANIFEST_LOCK = 556, + EHSM_GET_CMD_PACKET_SIZE = 558, + EHSM_PIE_LOCK = 559, + + EHSM_SHAKE_INIT = 570, + EHSM_SHAKE_UPDATE = 571, + EHSM_SHAKE_FINAL = 572, + EHSM_SHAKE_ZEROIZE = 573, + EHSM_HASH_ALL_IN_ONE = 574, + EHSM_HMAC_ALL_IN_ONE = 575, + + BCM_SM4_INIT = 576, + BCM_SM4_ZEROIZE = 577, + BCM_SM4_PROCESS = 578, + BCM_SM4_LOAD_IV = 579, + BCM_SM4_LOAD_KEY = 580, + BCM_SM4_KEY_GEN = 581, + +#ifdef CFG_EHSM_CONTEXT_STORE_SUPPORT + EHSM_CONTEXT_STORE = 590, + EHSM_CONTEXT_LOAD = 591, + EHSM_CONTEXT_RELEASE = 592, + EHSM_CONTEXT_WRAP = 593, + EHSM_CONTEXT_UNWRAP = 594, +#endif + + EHSM_OTP_RESET = 700, + EHSM_AMC_PLAINTEXT_KEY_LOAD = 701, + EHSM_DUMMY_CMD = 0xFFFFFFFF, +}; + +#ifdef CFG_EHSM_CONTEXT_STORE_SUPPORT +enum context_engine_id { + CONTEXT_AES = 0, + CONTEXT_DES = 1, + CONTEXT_SM4 = 2, + CONTEXT_HASH = 3, + CONTEXT_HMAC = 4 +}; +#endif + +struct ehsm_command { + uint32_t args[EHSM_NUM_ARGS]; + uint32_t opcode; + uint32_t reserved[15]; + uint32_t ret_status; + uint32_t ret_params[EHSM_NUM_ARGS]; +}; + +/* Linked-list struct */ +struct ehsm_dtd { + unsigned long transfer_addr; + unsigned long transfer_size; + struct ehsm_dtd *next; + uint64_t reserved2; +}; + +struct ehsm_handle { + /* Base register address for EHSM */ + uint32_t *ehsm_base; + uint32_t last_ehsm_status; + uint32_t mbox; /* Mailbox number */ + uintptr_t mbox_offset; + struct ehsm_command *ehsm_cmd; + uintptr_t host_int_reg; + uintptr_t cmd_status_reg; + uint32_t cmd_buf_full_mask; + unsigned int ehsm_ready:1; + unsigned int initialized:1; +}; + +/* + * @param[in] addr + * @return 1 if aligned, 0 if not aligned + */ +static inline int ehsm_is_aligned(uint32_t addr) +{ + return !(addr % EHSM_ALIGNMENT); +} + +/* + * @param[in] handle Pointer to eHSM handle + * + * @return 32-bit status code output by eHSM hardware + */ +static inline uint32_t ehsm_get_last_status(const struct ehsm_handle *handle) +{ + return handle->last_ehsm_status; +} + +/* + * @param[in] ptr + * @return 1 if aligned, 0 if not aligned + */ +static inline int ehsm_ptr_is_aligned(const void *ptr) +{ + return !((unsigned long)ptr % EHSM_ALIGNMENT); +} + +/* + * Initializes the handle and prepares the eHSM for access + * + * @param[out] handle pointer to handle + * @param mbox number to use + * + * @return status + */ +int ehsm_initialize(struct ehsm_handle *handle, unsigned int mbox); + +/* + * Returns if the handle has been initialized or not. + * + * @param[in] handle handle to check + * + * @returns 0 if not initialized, 1 if initialized + */ +static inline int ehsm_is_initialized(const struct ehsm_handle *handle) +{ + return handle->initialized; +} + +/* + * clear a command to the eHSM + * + * @param cmd pointer to command data structure + */ +void ehsm_clear_command(struct ehsm_command *cmd); + +/* + * Send a command to the eHSM and wait for a response + * + * @param handle pointer to eHSM handle + * @param cmd pointer to command data structure + * + * @return Return status of command from the hardware + */ +enum ehsm_status ehsm_command(struct ehsm_handle *handle, + struct ehsm_command *cmd); +#endif /* __EHSM_H__ */ diff --git a/core/drivers/crypto/marvell/mrvl_ehsm_cryp.c b/core/drivers/crypto/marvell/mrvl_ehsm_cryp.c new file mode 100644 index 00000000000..4e944570933 --- /dev/null +++ b/core/drivers/crypto/marvell/mrvl_ehsm_cryp.c @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2026, Marvell + */ + +#include +#include +#include + +#include "ehsm.h" +#include "ehsm-aes.h" +#include "mrvl_ehsm_cryp.h" + +static struct mutex ehsm_lock = MUTEX_INITIALIZER; + +static struct mrvl_ehsm_engine engine = { + .lock = &ehsm_lock, + .context_count = 0 +}; + +void mrvl_ehsm_cryp_lock(void) +{ + mutex_lock(engine.lock); +} + +void mrvl_ehsm_cryp_unlock(void) +{ + mutex_unlock(engine.lock); +} + +#ifdef CFG_EHSM_CONTEXT_STORE_SUPPORT +bool mrvl_ehsm_aes_cryp_get(void) +{ + bool cryp_allowed = false; + + mutex_lock(engine.lock); + if (engine.context_count < EHSM_AES_MAX_CONTEXT_SLOTS) { + cryp_allowed = true; + engine.context_count++; + } + mutex_unlock(engine.lock); + + return cryp_allowed; +} + +void mrvl_ehsm_aes_cryp_put(void) +{ + mutex_lock(engine.lock); + assert(engine.context_count); + engine.context_count--; + mutex_unlock(engine.lock); +} + +TEE_Result mrvl_ehsm_aes_context_store(uint32_t *pcontext_id) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t *ehsm_pcontext = NULL; + struct ehsm_result r = {}; + + ehsm_pcontext = mrvl_ehsm_mem_alloc(sizeof(uint32_t)); + if (!ehsm_pcontext) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + r = ehsm_context_store(&engine.ehandle, CONTEXT_AES, + ehsm_pcontext, NULL); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM aes context store failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + goto out; + } else { + FMSG("eHSM aes context store passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + + *pcontext_id = *ehsm_pcontext; + +out: + mrvl_ehsm_mem_free(ehsm_pcontext); + + return res; +} + +TEE_Result mrvl_ehsm_aes_context_load(uint32_t context_id) +{ + TEE_Result res = TEE_SUCCESS; + struct ehsm_result r = {}; + + r = ehsm_context_load(&engine.ehandle, CONTEXT_AES, context_id, NULL); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM aes context load failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + } else { + FMSG("eHSM aes context load passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + + return res; +} + +TEE_Result mrvl_ehsm_aes_context_release(uint32_t context_id) +{ + TEE_Result res = TEE_SUCCESS; + struct ehsm_result r = {}; + + r = ehsm_context_release(&engine.ehandle, CONTEXT_AES, + context_id, NULL); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM aes context free failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + } else { + FMSG("eHSM aes context free passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + + return res; +} +#else +bool ehsm_aes_engine_initialized; + +bool mrvl_ehsm_aes_cryp_get(void) +{ + bool cryp_allowed = false; + + mutex_lock(engine.lock); + if (!ehsm_aes_engine_initialized) { + ehsm_aes_engine_initialized = true; + cryp_allowed = true; + } + mutex_unlock(engine.lock); + + return cryp_allowed; +} + +void mrvl_ehsm_aes_cryp_put(void) +{ + mutex_lock(engine.lock); + ehsm_aes_engine_initialized = false; + mutex_unlock(engine.lock); +} + +TEE_Result mrvl_ehsm_aes_context_store(uint32_t *pcontext_id __maybe_unused) +{ + return TEE_SUCCESS; +} + +TEE_Result mrvl_ehsm_aes_context_load(uint32_t context_id __maybe_unused) +{ + return TEE_SUCCESS; +} + +TEE_Result mrvl_ehsm_aes_context_release(uint32_t context_id __maybe_unused) +{ + return TEE_SUCCESS; +} +#endif + +void *mrvl_ehsm_mem_alloc(size_t size) +{ + void *ptr = NULL; + size_t alloc_size = 0; + + if (ROUNDUP_OVERFLOW(size, EHSM_ALIGNMENT, &alloc_size)) + return NULL; + + ptr = memalign(EHSM_ALIGNMENT, alloc_size); + if (!ptr) + return NULL; + + memset(ptr, 0, size); + + return ptr; +} + +void mrvl_ehsm_mem_free(void *ptr) +{ + free(ptr); +} + +TEE_Result mrvl_ehsm_cryp_initialize(void) +{ + TEE_Result res = TEE_SUCCESS; + enum sec_return ret = SEC_NO_ERROR; + + ret = ehsm_initialize(&engine.ehandle, EHSM_CRYPTO_MAILBOX); + if (ret != SEC_NO_ERROR) { + EMSG("eHSM aes to initialize failed, ret : %u", ret); + res = TEE_ERROR_GENERIC; + } else { + FMSG("eHSM aes to initialize passed, ret : %u", ret); + } + + return res; +} + +TEE_Result mrvl_ehsm_aes_gcm_init(bool is_dec, void *key_data, size_t key_size, + uint32_t aad_size, uint32_t tag_size, + uint32_t iv_size, void *iv_data, + bool endian_swap) +{ + TEE_Result res = TEE_SUCCESS; + struct ehsm_result r = {}; + + res = mrvl_ehsm_cryp_initialize(); + if (res) + goto out; + + r = ehsm_aes_zeroize(&engine.ehandle); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM aes zeroize failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + goto out; + } else { + FMSG("eHSM aes zeroize passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + + r = ehsm_aes_load_key(&engine.ehandle, key_size * 8, key_data, 0, 0); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM load key failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + goto out; + } else { + FMSG("eHSM load key passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + + /* Special case (iv_size = 0) to capture a 12-bytes input IV. */ + if (iv_size == 12) + iv_size = 0; + + r = ehsm_aes_gcm_init(&engine.ehandle, !is_dec, aad_size, tag_size, + iv_size, iv_data, endian_swap); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM aes gcm init failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + goto out; + } else { + FMSG("eHSM aes gcm init passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + +out: + return res; +} + +TEE_Result mrvl_ehsm_aes_gcm_update_payload(const void *src, uint32_t src_len, + void *dst, uint32_t dst_len, + bool new) +{ + TEE_Result res = TEE_SUCCESS; + struct ehsm_result r = {}; + uint32_t len = MIN(src_len, dst_len); + + r = ehsm_aes_process(&engine.ehandle, src, dst, len, 0, new, 0, 0, + NULL, NULL); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM aes process failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + } else { + FMSG("eHSM aes process passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + + return res; +} + +TEE_Result mrvl_ehsm_aes_gcm_final(const void *src, uint32_t src_len, + void *dst, uint32_t dst_len, bool new) +{ + TEE_Result res = TEE_SUCCESS; + struct ehsm_result r = {}; + uint32_t len = MIN(src_len, dst_len); + + r = ehsm_aes_process(&engine.ehandle, src, dst, len, 0, new, 1, 0, + NULL, NULL); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM aes process failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + } else { + FMSG("eHSM aes process passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + + return res; +} + +TEE_Result mrvl_ehsm_aes_init(uint8_t aes_mode, bool is_dec, + void *key_data, size_t key_size, + void *key2_data, size_t key2_size, + uint8_t *iv_data, bool endian_swap) +{ + TEE_Result res = TEE_SUCCESS; + struct ehsm_result r = {}; + + res = mrvl_ehsm_cryp_initialize(); + if (res) + goto out; + + r = ehsm_aes_zeroize(&engine.ehandle); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM aes zeroize failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + goto out; + } else { + FMSG("eHSM aes zeroize passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + + r = ehsm_aes_load_key(&engine.ehandle, key_size * 8, key_data, 0, + endian_swap); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM load key failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + goto out; + } else { + FMSG("eHSM load key passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + + if (key2_size) { + r = ehsm_aes_load_key(&engine.ehandle, key2_size * 8, + key2_data, 1, endian_swap); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM load key2 failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + goto out; + } else { + FMSG("eHSM load key2 passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + } + + r = ehsm_aes_init(&engine.ehandle, !is_dec, key_size * 8, aes_mode, 0, + endian_swap); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM aes init failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + goto out; + } else { + FMSG("eHSM aes init passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + + r = ehsm_aes_load_iv(&engine.ehandle, iv_data, endian_swap); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM aes load iv failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + goto out; + } else { + FMSG("eHSM aes load iv passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + +out: + return res; +} + +TEE_Result mrvl_ehsm_aes_update_payload(const void *src, uint32_t src_len, + void *dst, uint32_t dst_len, + bool new, bool final) +{ + TEE_Result res = TEE_SUCCESS; + struct ehsm_result r = {}; + uint32_t len = MIN(src_len, dst_len); + + r = ehsm_aes_process(&engine.ehandle, src, dst, len, 0, new, final, 0, + NULL, NULL); + if (r.sec_ret != SEC_NO_ERROR) { + EMSG("eHSM aes update failed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + res = TEE_ERROR_GENERIC; + } else { + FMSG("eHSM aes update passed, sec_ret: %u hw_status: %u", + r.sec_ret, r.hw_status); + } + + return res; +} diff --git a/core/drivers/crypto/marvell/mrvl_ehsm_cryp.h b/core/drivers/crypto/marvell/mrvl_ehsm_cryp.h new file mode 100644 index 00000000000..6bfe97f9271 --- /dev/null +++ b/core/drivers/crypto/marvell/mrvl_ehsm_cryp.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2026, Marvell + */ + +#ifndef __MRVL_EHSM_CRYP_H__ +#define __MRVL_EHSM_CRYP_H__ +#include +#include + +#include "ehsm.h" +#include "ehsm-hal.h" + +enum mrvl_cryp_algo_mode { + MRVL_CRYP_MODE_AES_ECB, + MRVL_CRYP_MODE_AES_CBC, + MRVL_CRYP_MODE_AES_CTR, + MRVL_CRYP_MODE_AES_XTS, + MRVL_CRYP_MODE_AES_KEY_WRAP, + MRVL_CRYP_MODE_AES_CFB, + MRVL_CRYP_MODE_AES_OFB +}; + +/* + * eHSM crpto engine instance + * @ehandle - handle for HW instance + * @lock - lock protect cryp HW instance access + * @context_count - Counts used context slots + */ +struct mrvl_ehsm_engine { + struct ehsm_handle ehandle; + struct mutex *lock; /* lock crypto instance */ + uint8_t context_count; +}; + +struct mrvl_cryp_context { + bool initialized; + uint32_t context_id; + + bool op_enc_dec; + + uint8_t *key; + size_t key_len; + + uint8_t *key2; + size_t key2_len; + + uint8_t *aad_data; + size_t aad_cur_idx; + size_t aad_len; + + uint8_t *iv_data; + size_t iv_len; + + size_t tag_len; + + bool is_new; +}; + +void mrvl_ehsm_cryp_lock(void); +void mrvl_ehsm_cryp_unlock(void); + +bool mrvl_ehsm_aes_cryp_get(void); +void mrvl_ehsm_aes_cryp_put(void); + +TEE_Result mrvl_ehsm_aes_context_store(uint32_t *pcontext_id __maybe_unused); +TEE_Result mrvl_ehsm_aes_context_load(uint32_t context_id __maybe_unused); +TEE_Result mrvl_ehsm_aes_context_release(uint32_t context_id __maybe_unused); + +void *mrvl_ehsm_mem_alloc(size_t size); +void mrvl_ehsm_mem_free(void *ptr); + +TEE_Result mrvl_ehsm_cryp_initialize(void); +TEE_Result mrvl_ehsm_aes_gcm_init(bool is_dec, void *key_data, size_t key_size, + uint32_t aad_size, uint32_t tag_size, + uint32_t iv_size, void *iv_data, + bool endian_swap); +TEE_Result mrvl_ehsm_aes_gcm_update_payload(const void *src, uint32_t src_len, + void *dest, uint32_t dst_len, + bool new); +TEE_Result mrvl_ehsm_aes_gcm_final(const void *src, uint32_t src_len, + void *dest, uint32_t dst_len, bool new); +TEE_Result mrvl_ehsm_aes_init(uint8_t aes_mode, bool is_dec, + void *key_data, size_t key_size, + void *key2_data, size_t key2_size, + uint8_t *iv_data, bool endian_swap); +TEE_Result mrvl_ehsm_aes_update_payload(const void *src, uint32_t src_len, + void *dst, uint32_t dst_len, + bool new, bool final); +#endif /*__MRVL_EHSM_CRYP_H__*/ diff --git a/core/drivers/crypto/marvell/sub.mk b/core/drivers/crypto/marvell/sub.mk new file mode 100644 index 00000000000..7975993ac80 --- /dev/null +++ b/core/drivers/crypto/marvell/sub.mk @@ -0,0 +1,21 @@ +srcs-$(CFG_CRYPTO_DRV_AUTHENC) += authenc.c +srcs-$(CFG_CRYPTO_DRV_CIPHER) += cipher.c + +ifeq ($(CFG_MARVELL_EHSM_CRYPTO),y) +srcs-y += mrvl_ehsm_cryp.c + +srcs-y += ehsm/ehsm.c ehsm/ehsm-aes.c +incdirs-y += ehsm/include + +ifneq (,$(filter $(PLATFORM_FLAVOR),cn10ka cn10kb cnf10ka cnf10kb)) +$(call force,CFG_MARVELL_EHSM_CN10K,y) +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR), cn20ka cnf20ka)) +$(call force,CFG_MARVELL_EHSM_CN20K,y) + +# eHSM crypto engine context store/load support +$(call force,CFG_EHSM_CONTEXT_STORE_SUPPORT,y) +endif +endif + diff --git a/core/drivers/crypto/sub.mk b/core/drivers/crypto/sub.mk index 31f1d7cc26f..8f0ca4eb235 100644 --- a/core/drivers/crypto/sub.mk +++ b/core/drivers/crypto/sub.mk @@ -19,3 +19,5 @@ subdirs-$(CFG_HISILICON_CRYPTO_DRIVER) += hisilicon subdirs-$(CFG_IMX_ELE) += ele subdirs-$(CFG_QCOM_HWKM) += qcom + +subdirs-$(CFG_MARVELL_CRYPTO_DRIVER) += marvell