diff --git a/core/arch/arm/plat-versal/conf.mk b/core/arch/arm/plat-versal/conf.mk index 645462d49ba..799a842e1b2 100644 --- a/core/arch/arm/plat-versal/conf.mk +++ b/core/arch/arm/plat-versal/conf.mk @@ -6,7 +6,11 @@ CFG_MMAP_REGIONS ?= 24 $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) +ifeq ($(PLATFORM_FLAVOR),net) +$(call force,CFG_TEE_CORE_NB_CORE,16) +else $(call force,CFG_TEE_CORE_NB_CORE,2) +endif $(call force,CFG_ARM_GICV3,y) $(call force,CFG_PL011,y) $(call force,CFG_GIC,y) @@ -23,10 +27,18 @@ CFG_CORE_DYN_SHM ?= y CFG_WITH_STATS ?= y CFG_ARM64_core ?= y +# Default memory allocation +ifeq ($(PLATFORM_FLAVOR),net) +CFG_TZDRAM_START ?= 0x22200000 +CFG_TZDRAM_SIZE ?= 0x2700000 +CFG_SHMEM_START ?= 0x24900000 +CFG_SHMEM_SIZE ?= 0x1800000 +else CFG_TZDRAM_START ?= 0x60000000 CFG_TZDRAM_SIZE ?= 0x10000000 CFG_SHMEM_START ?= 0x70000000 CFG_SHMEM_SIZE ?= 0x10000000 +endif ifeq ($(CFG_ARM64_core),y) $(call force,CFG_CORE_ARM64_PA_BITS,43) @@ -34,6 +46,12 @@ else $(call force,CFG_ARM32_core,y) endif +ifeq ($(PLATFORM_FLAVOR),net) +CFG_RPMB_FS ?= n +CFG_RPMB_TESTKEY ?= y +CFG_RPMB_WRITE_KEY ?= $(CFG_RPMB_TESTKEY) +endif + # GPIO CFG_VERSAL_GPIO ?= y @@ -44,17 +62,34 @@ CFG_VERSAL_TRACE_PLM ?= n $(call force, CFG_VERSAL_MBOX,y) # MBOX configuration +ifeq ($(PLATFORM_FLAVOR),net) +CFG_VERSAL_MBOX_IPI_ID ?= 1 +else CFG_VERSAL_MBOX_IPI_ID ?= 3 +endif +CFG_VERSAL_MBOX_TIMEOUT ?= 1000 + +# PM driver +CFG_VERSAL_PM ?= y +# TRNG driver $(call force, CFG_VERSAL_RNG_DRV,y) $(call force, CFG_WITH_SOFTWARE_PRNG,n) +ifeq ($(PLATFORM_FLAVOR),net) +$(call force,CFG_VERSAL_RNG_PLM,y) +endif + # TRNG configuration CFG_VERSAL_TRNG_SEED_LIFE ?= 3 CFG_VERSAL_TRNG_DF_MUL ?= 2 # eFuse and BBRAM driver +ifeq ($(PLATFORM_FLAVOR),net) +$(call force, CFG_VERSAL_NET_NVM,y) +else $(call force, CFG_VERSAL_NVM,y) +endif # Crypto driver CFG_VERSAL_CRYPTO_DRIVER ?= y @@ -62,18 +97,25 @@ ifeq ($(CFG_VERSAL_CRYPTO_DRIVER),y) # Disable Fault Mitigation: triggers false positives due to # the driver's software fallback operations - need further work CFG_FAULT_MITIGATION ?= n + +ifeq ($(PLATFORM_FLAVOR),net) +CFG_VERSAL_PKI_DRIVER ?= y + +ifeq ($(CFG_VERSAL_PKI_DRIVER),y) +CFG_VERSAL_PKI_COUNTER_MEASURES ?= n +CFG_VERSAL_PKI_PWCT ?= y +endif +endif # PLATFORM_FLAVOR is net endif # SHA3-384 crypto engine CFG_VERSAL_SHA3_384 ?= y -# PM driver -CFG_VERSAL_PM ?= y - # Physical Unclonable Function CFG_VERSAL_PUF ?= y # Enable Hardware Unique Key driver +CFG_VERSAL_DUMMY_DNA ?= n CFG_VERSAL_HUK ?= y # AES-GCM supported key sources for HUK: # 6 : eFUSE USR 0 @@ -85,4 +127,8 @@ ifneq ($(CFG_VERSAL_HUK_KEY),$(filter 6 7 11 12,$(firstword $(CFG_VERSAL_HUK_KEY $(error Invalid value: CFG_VERSAL_HUK_KEY=$(CFG_VERSAL_HUK_KEY)) endif +ifeq ($(PLATFORM_FLAVOR),net) +CFG_VERSAL_FPGA_LOADER_PTA ?= y +endif + CFG_CORE_HEAP_SIZE ?= 262144 diff --git a/core/arch/arm/plat-versal/main.c b/core/arch/arm/plat-versal/main.c index b443269bd4a..5b487b3e8ed 100644 --- a/core/arch/arm/plat-versal/main.c +++ b/core/arch/arm/plat-versal/main.c @@ -87,7 +87,7 @@ static TEE_Result platform_banner(void) return TEE_SUCCESS; } -#if defined(CFG_RPMB_FS) +#if defined(CFG_RPMB_FS) && !defined(CFG_RPMB_TESTKEY) bool plat_rpmb_key_is_ready(void) { vaddr_t plm_rtca = (vaddr_t)phys_to_virt(PLM_RTCA, MEM_AREA_IO_SEC, diff --git a/core/arch/arm/plat-versal/platform_config.h b/core/arch/arm/plat-versal/platform_config.h index 8f9b3674be8..61f4bce69bd 100644 --- a/core/arch/arm/plat-versal/platform_config.h +++ b/core/arch/arm/plat-versal/platform_config.h @@ -12,11 +12,11 @@ #define CACHELINE_LEN 64 #define STACK_ALIGNMENT CACHELINE_LEN -#if defined(PLATFORM_FLAVOR_generic) - #define PLM_RTCA 0xF2014000 #define PLM_RTCA_LEN 0x1000 +#if defined(PLATFORM_FLAVOR_generic) + #define GIC_BASE 0xF9000000 #define UART0_BASE 0xFF000000 #define UART1_BASE 0xFF010000 @@ -44,6 +44,35 @@ #define GICD_OFFSET 0 #define GICC_OFFSET 0x40000 +#elif defined(PLATFORM_FLAVOR_net) + +#define GIC_BASE 0xE2000000 +#define UART0_BASE 0xF1920000 +#define UART1_BASE 0xF1930000 + +#define IT_UART0 57 +#define IT_UART1 58 + +#define UART0_CLK_IN_HZ 100000000 +#define UART1_CLK_IN_HZ 100000000 +#define CONSOLE_UART_BASE UART0_BASE +#define IT_CONSOLE_UART IT_UART0 +#define CONSOLE_UART_CLK_IN_HZ UART0_CLK_IN_HZ + +#define DRAM0_BASE 0 +#define DRAM0_SIZE 0x7FF00000 + +#ifdef ARM64 +/* DDR High area base is only available when compiling for 64 bits */ +#define DRAM1_BASE 0x800000000 +#define DRAM1_SIZE 0x800000000 +#define DRAM2_BASE 0xC000000000 +#define DRAM2_SIZE 0x4000000000 +#endif + +#define GICD_OFFSET 0 +#define GICC_OFFSET 0x40000 + #else #error "Unknown platform flavor" #endif diff --git a/core/drivers/crypto/versal/authenc.c b/core/drivers/crypto/versal/authenc.c index 8776dac5670..9fc3215aea6 100644 --- a/core/drivers/crypto/versal/authenc.c +++ b/core/drivers/crypto/versal/authenc.c @@ -343,7 +343,9 @@ static TEE_Result do_init(struct drvcrypt_authenc_init *dinit) } /* Write the key */ - versal_mbox_alloc(dinit->key.length, dinit->key.data, &key); + ret = versal_mbox_alloc(dinit->key.length, dinit->key.data, &key); + if (ret) + return ret; arg.data[arg.dlen++] = key_len; arg.data[arg.dlen++] = engine.key_src; @@ -358,8 +360,12 @@ static TEE_Result do_init(struct drvcrypt_authenc_init *dinit) memset(&arg, 0, sizeof(arg)); /* Send the initialization structure */ - versal_mbox_alloc(sizeof(*init), NULL, &init_buf); - versal_mbox_alloc(dinit->nonce.length, dinit->nonce.data, &nonce); + ret = versal_mbox_alloc(sizeof(*init), NULL, &init_buf); + if (ret) + goto error; + ret = versal_mbox_alloc(dinit->nonce.length, dinit->nonce.data, &nonce); + if (ret) + goto error; init = init_buf.buf; init->iv_addr = virt_to_phys(nonce.buf); @@ -400,9 +406,9 @@ static TEE_Result do_init(struct drvcrypt_authenc_init *dinit) return TEE_SUCCESS; error: - free(key.buf); - free(init_buf.buf); - free(nonce.buf); + versal_mbox_free(&nonce); + versal_mbox_free(&init_buf); + versal_mbox_free(&key); return ret; } @@ -427,7 +433,9 @@ static TEE_Result do_update_aad(struct drvcrypt_authenc_update_aad *dupdate) if (engine.state == FINALIZED) do_replay(); - versal_mbox_alloc(dupdate->aad.length, dupdate->aad.data, &p); + ret = versal_mbox_alloc(dupdate->aad.length, dupdate->aad.data, &p); + if (ret) + return ret; arg.data[arg.dlen++] = p.len % 16 ? p.alloc_len : p.len; arg.ibuf[0].mem = p; @@ -455,7 +463,7 @@ static TEE_Result do_update_aad(struct drvcrypt_authenc_update_aad *dupdate) return TEE_SUCCESS; error: - free(p.buf); + versal_mbox_free(&p); return ret; } @@ -481,9 +489,15 @@ update_payload(struct drvcrypt_authenc_update_payload *dupdate, bool is_last) return TEE_ERROR_BAD_PARAMETERS; } - versal_mbox_alloc(dupdate->src.length, dupdate->src.data, &p); - versal_mbox_alloc(dupdate->dst.length, NULL, &q); - versal_mbox_alloc(sizeof(*input), NULL, &input_cmd); + ret = versal_mbox_alloc(dupdate->src.length, dupdate->src.data, &p); + if (ret) + return ret; + ret = versal_mbox_alloc(dupdate->dst.length, NULL, &q); + if (ret) + goto out; + ret = versal_mbox_alloc(sizeof(*input), NULL, &input_cmd); + if (ret) + goto out; input = input_cmd.buf; input->input_addr = virt_to_phys(p.buf); @@ -528,9 +542,9 @@ update_payload(struct drvcrypt_authenc_update_payload *dupdate, bool is_last) return TEE_SUCCESS; } out: - free(p.buf); - free(q.buf); - free(input_cmd.buf); + versal_mbox_free(&input_cmd); + versal_mbox_free(&q); + versal_mbox_free(&p); return ret; } @@ -594,7 +608,9 @@ static TEE_Result do_enc_final(struct drvcrypt_authenc_final *dfinal) memcpy(dfinal->dst.data, last.dst.data, dfinal->dst.length); - versal_mbox_alloc(GCM_TAG_LEN, NULL, &p); + ret = versal_mbox_alloc(GCM_TAG_LEN, NULL, &p); + if (ret) + return ret; arg.ibuf[0].mem = p; if (versal_crypto_request(VERSAL_AES_ENCRYPT_FINAL, &arg, &err)) { @@ -606,7 +622,7 @@ static TEE_Result do_enc_final(struct drvcrypt_authenc_final *dfinal) memcpy(dfinal->tag.data, p.buf, GCM_TAG_LEN); dfinal->tag.length = GCM_TAG_LEN; out: - free(p.buf); + versal_mbox_free(&p); if (refcount_val(&engine.refc) > 1) engine.state = FINALIZED; @@ -646,7 +662,10 @@ static TEE_Result do_dec_final(struct drvcrypt_authenc_final *dfinal) if (ret) return ret; - versal_mbox_alloc(dfinal->tag.length, dfinal->tag.data, &p); + ret = versal_mbox_alloc(dfinal->tag.length, dfinal->tag.data, &p); + if (ret) + return ret; + arg.ibuf[0].mem = p; if (versal_crypto_request(VERSAL_AES_DECRYPT_FINAL, &arg, &err)) { @@ -659,7 +678,7 @@ static TEE_Result do_dec_final(struct drvcrypt_authenc_final *dfinal) memcpy(dfinal->tag.data, p.buf, GCM_TAG_LEN); dfinal->tag.length = GCM_TAG_LEN; out: - free(p.buf); + versal_mbox_free(&p); if (refcount_val(&engine.refc) > 1) engine.state = FINALIZED; @@ -687,19 +706,19 @@ static void do_free(void *ctx) release = true; refcount_set(&engine.refc, 1); engine.state = READY; - free(engine.init.init_buf.buf); - free(engine.init.nonce.buf); - free(engine.init.key.buf); + versal_mbox_free(&engine.init.init_buf); + versal_mbox_free(&engine.init.nonce); + versal_mbox_free(&engine.init.key); memset(&engine.init, 0, sizeof(engine.init)); STAILQ_FOREACH_SAFE(node, &engine.replay_list, link, next) { STAILQ_REMOVE(&engine.replay_list, node, versal_node, link); if (node->is_aad) { - free(node->aad.mem.buf); + versal_mbox_free(&node->aad.mem); } else { - free(node->payload.dst.buf); - free(node->payload.src.buf); - free(node->payload.input_cmd.buf); + versal_mbox_free(&node->payload.dst); + versal_mbox_free(&node->payload.src); + versal_mbox_free(&node->payload.input_cmd); } free(node); } diff --git a/core/drivers/crypto/versal/ecc.c b/core/drivers/crypto/versal/ecc.c index 64a919e218f..8fd0441209f 100644 --- a/core/drivers/crypto/versal/ecc.c +++ b/core/drivers/crypto/versal/ecc.c @@ -4,86 +4,35 @@ * Author: Jorge Ramirez */ +#include +#include #include #include -#include +#include #include -#include +#include +#include #include #include +#include #include #include #include #include -/* AMD/Xilinx Versal's Known Answer Tests */ -#define XSECURE_ECDSA_KAT_NIST_P384 0 -#define XSECURE_ECDSA_KAT_NIST_P521 2 - /* Software based ECDSA operations */ static const struct crypto_ecc_keypair_ops *pair_ops; static const struct crypto_ecc_public_ops *pub_ops; -enum versal_ecc_err { - KAT_KEY_NOTVALID_ERROR = 0xC0, - KAT_FAILED_ERROR, - NON_SUPPORTED_CURVE, - KEY_ZERO, - KEY_WRONG_ORDER, - KEY_NOT_ON_CURVE, - BAD_SIGN, - GEN_SIGN_INCORRECT_HASH_LEN, - VER_SIGN_INCORRECT_HASH_LEN, - GEN_SIGN_BAD_RAND_NUM, - GEN_KEY_ERR, - INVALID_PARAM, - VER_SIGN_R_ZERO, - VER_SIGN_S_ZERO, - VER_SIGN_R_ORDER_ERROR, - VER_SIGN_S_ORDER_ERROR, - KAT_INVLD_CRV_ERROR, -}; - -#define VERSAL_ECC_ERROR(m) { .error = (m), .name = TO_STR(m) } - -static const char *versal_ecc_error(uint8_t err) -{ - struct { - enum versal_ecc_err error; - const char *name; - } elist[] = { - VERSAL_ECC_ERROR(KAT_KEY_NOTVALID_ERROR), - VERSAL_ECC_ERROR(KAT_FAILED_ERROR), - VERSAL_ECC_ERROR(NON_SUPPORTED_CURVE), - VERSAL_ECC_ERROR(KEY_ZERO), - VERSAL_ECC_ERROR(KEY_WRONG_ORDER), - VERSAL_ECC_ERROR(KEY_NOT_ON_CURVE), - VERSAL_ECC_ERROR(BAD_SIGN), - VERSAL_ECC_ERROR(GEN_SIGN_INCORRECT_HASH_LEN), - VERSAL_ECC_ERROR(VER_SIGN_INCORRECT_HASH_LEN), - VERSAL_ECC_ERROR(GEN_SIGN_BAD_RAND_NUM), - VERSAL_ECC_ERROR(GEN_KEY_ERR), - VERSAL_ECC_ERROR(INVALID_PARAM), - VERSAL_ECC_ERROR(VER_SIGN_R_ZERO), - VERSAL_ECC_ERROR(VER_SIGN_S_ZERO), - VERSAL_ECC_ERROR(VER_SIGN_R_ORDER_ERROR), - VERSAL_ECC_ERROR(VER_SIGN_S_ORDER_ERROR), - VERSAL_ECC_ERROR(KAT_INVLD_CRV_ERROR), - }; - - if (err <= KAT_INVLD_CRV_ERROR && err >= KAT_KEY_NOTVALID_ERROR) { - if (elist[err - KAT_KEY_NOTVALID_ERROR].name) - return elist[err - KAT_KEY_NOTVALID_ERROR].name; - - return "Invalid"; - } - - return "Unknown"; -} - -static TEE_Result ecc_get_key_size(uint32_t curve, size_t *bytes, size_t *bits) +TEE_Result versal_ecc_get_key_size(uint32_t curve, size_t *bytes, size_t *bits) { switch (curve) { +#if defined(CFG_VERSAL_PKI_DRIVER) + case TEE_ECC_CURVE_NIST_P256: + *bits = 256; + *bytes = 32; + break; +#endif case TEE_ECC_CURVE_NIST_P384: *bits = 384; *bytes = 48; @@ -99,7 +48,7 @@ static TEE_Result ecc_get_key_size(uint32_t curve, size_t *bytes, size_t *bits) return TEE_SUCCESS; } -static void memcpy_swp(uint8_t *to, const uint8_t *from, size_t len) +void versal_memcpy_swp(uint8_t *to, const uint8_t *from, size_t len) { size_t i = 0; @@ -107,217 +56,53 @@ static void memcpy_swp(uint8_t *to, const uint8_t *from, size_t len) to[i] = from[len - 1 - i]; } -static void crypto_bignum_bn2bin_eswap(uint32_t curve, - struct bignum *from, uint8_t *to) +void versal_crypto_bignum_bn2bin_eswap(uint32_t curve, struct bignum *from, + uint8_t *to) { uint8_t pad[66] = { 0 }; size_t len = crypto_bignum_num_bytes(from); size_t bytes = 0; size_t bits = 0; - if (ecc_get_key_size(curve, &bytes, &bits)) + if (versal_ecc_get_key_size(curve, &bytes, &bits)) panic(); crypto_bignum_bn2bin(from, pad + bytes - len); - memcpy_swp(to, pad, bytes); + versal_memcpy_swp(to, pad, bytes); } -static TEE_Result ecc_prepare_msg(uint32_t algo, const uint8_t *msg, - size_t msg_len, struct versal_mbox_mem *p) +void versal_crypto_bignum_bin2bn_eswap(const uint8_t *from, size_t sz, + struct bignum *to) { - uint8_t swp[TEE_SHA512_HASH_SIZE + 2] = { 0 }; - size_t len = 0; + uint8_t pad[66] = { 0 }; + + assert(sz <= sizeof(pad)); + + versal_memcpy_swp(pad, from, sz); + crypto_bignum_bin2bn(pad, sz, to); +} +TEE_Result versal_ecc_prepare_msg(uint32_t algo, const uint8_t *msg, + size_t msg_len, size_t *len, uint8_t *buf) +{ if (msg_len > TEE_SHA512_HASH_SIZE + 2) return TEE_ERROR_BAD_PARAMETERS; if (algo == TEE_ALG_ECDSA_SHA384) - len = TEE_SHA384_HASH_SIZE; + *len = TEE_SHA384_HASH_SIZE; else if (algo == TEE_ALG_ECDSA_SHA512) - len = TEE_SHA512_HASH_SIZE + 2; + *len = TEE_SHA512_HASH_SIZE + 2; +#if defined(PLATFORM_FLAVOR_net) + else if (algo == TEE_ALG_ECDSA_SHA256) + *len = TEE_SHA256_HASH_SIZE; +#endif else return TEE_ERROR_NOT_SUPPORTED; /* Swap the hash/message and pad if necessary */ - memcpy_swp(swp, msg, msg_len); - return versal_mbox_alloc(len, swp, p); -} - -static TEE_Result verify(uint32_t algo, struct ecc_public_key *key, - const uint8_t *msg, size_t msg_len, - const uint8_t *sig, size_t sig_len) -{ - TEE_Result ret = TEE_SUCCESS; - struct versal_ecc_verify_param *cmd = NULL; - struct versal_cmd_args arg = { }; - struct versal_mbox_mem x = { }; - struct versal_mbox_mem s = { }; - struct versal_mbox_mem p = { }; - struct versal_mbox_mem cmd_buf = { }; - uint32_t err = 0; - size_t bytes = 0; - size_t bits = 0; - - if (sig_len % 2) - return TEE_ERROR_SIGNATURE_INVALID; - - ret = ecc_get_key_size(key->curve, &bytes, &bits); - if (ret != TEE_SUCCESS) { - if (ret != TEE_ERROR_NOT_SUPPORTED) - return ret; - - /* Fallback to software */ - return pub_ops->verify(algo, key, msg, msg_len, sig, sig_len); - } - - ret = ecc_prepare_msg(algo, msg, msg_len, &p); - if (ret) - return ret; - - versal_mbox_alloc(bytes * 2, NULL, &x); - crypto_bignum_bn2bin_eswap(key->curve, key->x, x.buf); - crypto_bignum_bn2bin_eswap(key->curve, key->y, - (uint8_t *)x.buf + bytes); - /* Validate the public key for the curve */ - arg.data[0] = key->curve; - arg.dlen = 1; - arg.ibuf[0].mem = x; - if (versal_crypto_request(VERSAL_ELLIPTIC_VALIDATE_PUBLIC_KEY, - &arg, &err)) { - EMSG("Versal ECC: %s", versal_ecc_error(err)); - ret = TEE_ERROR_GENERIC; - goto out; - } - memset(&arg, 0, sizeof(arg)); - - versal_mbox_alloc(sig_len, NULL, &s); - /* Swap the {R,S} components */ - memcpy_swp(s.buf, sig, sig_len / 2); - memcpy_swp((uint8_t *)s.buf + sig_len / 2, sig + sig_len / 2, - sig_len / 2); - versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); - - cmd = cmd_buf.buf; - cmd->signature_addr = virt_to_phys(s.buf); - cmd->pub_key_addr = virt_to_phys(x.buf); - cmd->hash_addr = virt_to_phys(p.buf); - cmd->hash_len = p.len; - cmd->curve = key->curve; - - arg.ibuf[0].mem = cmd_buf; - arg.ibuf[1].mem = p; - arg.ibuf[1].only_cache = true; - arg.ibuf[2].mem = x; - arg.ibuf[3].mem = s; - - if (versal_crypto_request(VERSAL_ELLIPTIC_VERIFY_SIGN, &arg, &err)) { - EMSG("Versal ECC: %s", versal_ecc_error(err)); - ret = TEE_ERROR_GENERIC; - } -out: - free(p.buf); - free(x.buf); - free(s.buf); - free(cmd); - - return ret; -} - -static TEE_Result sign(uint32_t algo, struct ecc_keypair *key, - const uint8_t *msg, size_t msg_len, - uint8_t *sig, size_t *sig_len) -{ - struct versal_ecc_sign_param *cmd = NULL; - struct versal_mbox_mem cmd_buf = { }; - struct ecc_keypair ephemeral = { }; - struct versal_cmd_args arg = { }; - struct versal_mbox_mem p = { }; - struct versal_mbox_mem k = { }; - struct versal_mbox_mem d = { }; - struct versal_mbox_mem s = { }; - TEE_Result ret = TEE_SUCCESS; - uint32_t err = 0; - size_t bytes = 0; - size_t bits = 0; - - ret = ecc_get_key_size(key->curve, &bytes, &bits); - if (ret != TEE_SUCCESS) { - if (ret != TEE_ERROR_NOT_SUPPORTED) - return ret; - - /* Fallback to software */ - return pair_ops->sign(algo, key, msg, msg_len, sig, sig_len); - } + versal_memcpy_swp(buf, msg, msg_len); - /* Hash and update the length */ - ret = ecc_prepare_msg(algo, msg, msg_len, &p); - if (ret) - return ret; - - /* Ephemeral private key */ - ret = drvcrypt_asym_alloc_ecc_keypair(&ephemeral, - TEE_TYPE_ECDSA_KEYPAIR, bits); - if (ret) { - EMSG("Versal, can't allocate the ephemeral key"); - return ret; - } - - ephemeral.curve = key->curve; - ret = crypto_acipher_gen_ecc_key(&ephemeral, bits); - if (ret) { - EMSG("Versal, can't generate the ephemeral key"); - return ret; - } - - versal_mbox_alloc(bytes, NULL, &k); - crypto_bignum_bn2bin_eswap(key->curve, ephemeral.d, k.buf); - crypto_bignum_free(&ephemeral.d); - crypto_bignum_free(&ephemeral.x); - crypto_bignum_free(&ephemeral.y); - - /* Private key*/ - versal_mbox_alloc(bytes, NULL, &d); - crypto_bignum_bn2bin_eswap(key->curve, key->d, d.buf); - - /* Signature */ - versal_mbox_alloc(*sig_len, NULL, &s); - - /* IPI command */ - versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); - - cmd = cmd_buf.buf; - cmd->priv_key_addr = virt_to_phys(d.buf); - cmd->epriv_key_addr = virt_to_phys(k.buf); - cmd->hash_addr = virt_to_phys(p.buf); - cmd->hash_len = p.len; - cmd->curve = key->curve; - - arg.ibuf[0].mem = cmd_buf; - arg.ibuf[1].mem = s; - arg.ibuf[2].mem = k; - arg.ibuf[3].mem = d; - arg.ibuf[4].mem = p; - - if (versal_crypto_request(VERSAL_ELLIPTIC_GENERATE_SIGN, &arg, &err)) { - EMSG("Versal ECC: %s", versal_ecc_error(err)); - ret = TEE_ERROR_GENERIC; - goto out; - } - - *sig_len = 2 * bytes; - - /* Swap the {R,S} components */ - memcpy_swp(sig, s.buf, *sig_len / 2); - memcpy_swp(sig + *sig_len / 2, (uint8_t *)s.buf + *sig_len / 2, - *sig_len / 2); -out: - free(cmd); - free(k.buf); - free(p.buf); - free(s.buf); - free(d.buf); - - return ret; + return TEE_SUCCESS; } static TEE_Result shared_secret(struct ecc_keypair *private_key, @@ -338,32 +123,68 @@ static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata) static TEE_Result do_sign(struct drvcrypt_sign_data *sdata) { - return sign(sdata->algo, - sdata->key, - sdata->message.data, - sdata->message.length, - sdata->signature.data, - &sdata->signature.length); + TEE_Result ret = TEE_SUCCESS; + + ret = versal_ecc_sign(sdata->algo, + sdata->key, + sdata->message.data, + sdata->message.length, + sdata->signature.data, + &sdata->signature.length); + + if (ret == TEE_ERROR_NOT_SUPPORTED) { + /* Fallback to software */ + return pair_ops->sign(sdata->algo, sdata->key, + sdata->message.data, + sdata->message.length, + sdata->signature.data, + &sdata->signature.length); + } + + return ret; } static TEE_Result do_verify(struct drvcrypt_sign_data *sdata) { - return verify(sdata->algo, - sdata->key, - sdata->message.data, - sdata->message.length, - sdata->signature.data, - sdata->signature.length); + TEE_Result ret = TEE_SUCCESS; + + ret = versal_ecc_verify(sdata->algo, + sdata->key, + sdata->message.data, + sdata->message.length, + sdata->signature.data, + sdata->signature.length); + + if (ret == TEE_ERROR_NOT_SUPPORTED) { + /* Fallback to software */ + return pub_ops->verify(sdata->algo, sdata->key, + sdata->message.data, + sdata->message.length, + sdata->signature.data, + sdata->signature.length); + } + + return ret; } static TEE_Result do_gen_keypair(struct ecc_keypair *s, size_t size_bits) { - /* - * Versal requires little endian so need to memcpy_swp on Versal IP ops. - * We chose not to do it here because some tests might be using - * their own keys - */ - return pair_ops->generate(s, size_bits); + TEE_Result ret = versal_ecc_gen_keypair(s); + + if (ret == TEE_ERROR_NOT_SUPPORTED) + return pair_ops->generate(s, size_bits); + +#ifdef CFG_VERSAL_PKI_PWCT + if (ret != TEE_SUCCESS) + return ret; + + /* Perform a pairwise consistencty test on the generated key pair */ + ret = versal_ecc_keypair_pwct(s); + if (ret) + DMSG("Pair-wise consistency test failed (0x%" PRIx32 ")", ret); +#endif + + return ret; } static TEE_Result do_alloc_keypair(struct ecc_keypair *s, @@ -431,24 +252,19 @@ static struct drvcrypt_ecc driver_ecc = { static TEE_Result ecc_init(void) { - struct versal_cmd_args arg = { }; - uint32_t err = 0; - - arg.data[arg.dlen++] = XSECURE_ECDSA_KAT_NIST_P384; - if (versal_crypto_request(VERSAL_ELLIPTIC_KAT, &arg, &err)) { - EMSG("Versal KAG NIST_P384: %s", versal_ecc_error(err)); - return TEE_ERROR_GENERIC; - } + TEE_Result ret = TEE_SUCCESS; - /* Clean previous request */ - arg.dlen = 0; + /* HW initialization if needed */ + ret = versal_ecc_hw_init(); + if (ret != TEE_SUCCESS) + return ret; - arg.data[arg.dlen++] = XSECURE_ECDSA_KAT_NIST_P521; - if (versal_crypto_request(VERSAL_ELLIPTIC_KAT, &arg, &err)) { - EMSG("Versal KAG NIST_P521 %s", versal_ecc_error(err)); - return TEE_ERROR_GENERIC; - } + /* Run KAT self-tests */ + ret = versal_ecc_kat_test(); + if (ret != TEE_SUCCESS) + return ret; + /* Fall back to software implementations if needed */ pair_ops = crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDSA_KEYPAIR); if (!pair_ops) return TEE_ERROR_GENERIC; diff --git a/core/drivers/crypto/versal/ecc_mbox.c b/core/drivers/crypto/versal/ecc_mbox.c new file mode 100644 index 00000000000..bf0a9c3f721 --- /dev/null +++ b/core/drivers/crypto/versal/ecc_mbox.c @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2022. + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum versal_ecc_err { + KAT_KEY_NOTVALID_ERROR = 0xC0, + KAT_FAILED_ERROR, + NON_SUPPORTED_CURVE, + KEY_ZERO, + KEY_WRONG_ORDER, + KEY_NOT_ON_CURVE, + BAD_SIGN, + GEN_SIGN_INCORRECT_HASH_LEN, + VER_SIGN_INCORRECT_HASH_LEN, + GEN_SIGN_BAD_RAND_NUM, + GEN_KEY_ERR, + INVALID_PARAM, + VER_SIGN_R_ZERO, + VER_SIGN_S_ZERO, + VER_SIGN_R_ORDER_ERROR, + VER_SIGN_S_ORDER_ERROR, + KAT_INVLD_CRV_ERROR, +}; + +#define VERSAL_ECC_ERROR(m) { .error = (m), .name = TO_STR(m) } + +static const char *versal_ecc_error(uint8_t err) +{ + struct { + enum versal_ecc_err error; + const char *name; + } elist[] = { + VERSAL_ECC_ERROR(KAT_KEY_NOTVALID_ERROR), + VERSAL_ECC_ERROR(KAT_FAILED_ERROR), + VERSAL_ECC_ERROR(NON_SUPPORTED_CURVE), + VERSAL_ECC_ERROR(KEY_ZERO), + VERSAL_ECC_ERROR(KEY_WRONG_ORDER), + VERSAL_ECC_ERROR(KEY_NOT_ON_CURVE), + VERSAL_ECC_ERROR(BAD_SIGN), + VERSAL_ECC_ERROR(GEN_SIGN_INCORRECT_HASH_LEN), + VERSAL_ECC_ERROR(VER_SIGN_INCORRECT_HASH_LEN), + VERSAL_ECC_ERROR(GEN_SIGN_BAD_RAND_NUM), + VERSAL_ECC_ERROR(GEN_KEY_ERR), + VERSAL_ECC_ERROR(INVALID_PARAM), + VERSAL_ECC_ERROR(VER_SIGN_R_ZERO), + VERSAL_ECC_ERROR(VER_SIGN_S_ZERO), + VERSAL_ECC_ERROR(VER_SIGN_R_ORDER_ERROR), + VERSAL_ECC_ERROR(VER_SIGN_S_ORDER_ERROR), + VERSAL_ECC_ERROR(KAT_INVLD_CRV_ERROR), + }; + + if (err <= KAT_INVLD_CRV_ERROR && err >= KAT_KEY_NOTVALID_ERROR) { + if (elist[err - KAT_KEY_NOTVALID_ERROR].name) + return elist[err - KAT_KEY_NOTVALID_ERROR].name; + + return "Invalid"; + } + + return "Unknown"; +} + +TEE_Result versal_ecc_verify(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + TEE_Result ret = TEE_SUCCESS; + uint8_t swp[TEE_SHA512_HASH_SIZE + 2] = { 0 }; + size_t len = 0; + struct versal_ecc_verify_param *cmd = NULL; + struct versal_cmd_args arg = { }; + struct versal_mbox_mem x = { }; + struct versal_mbox_mem s = { }; + struct versal_mbox_mem p = { }; + struct versal_mbox_mem cmd_buf = { }; + uint32_t err = 0; + size_t bytes = 0; + size_t bits = 0; + + if (sig_len % 2) + return TEE_ERROR_SIGNATURE_INVALID; + + ret = versal_ecc_get_key_size(key->curve, &bytes, &bits); + if (ret) + return ret; + + ret = versal_ecc_prepare_msg(algo, msg, msg_len, &len, (uint8_t *)&swp); + if (ret) + return ret; + + ret = versal_mbox_alloc(len, swp, &p); + if (ret) + return ret; + + ret = versal_mbox_alloc(bytes * 2, NULL, &x); + if (ret) + goto out1; + + versal_crypto_bignum_bn2bin_eswap(key->curve, key->x, x.buf); + versal_crypto_bignum_bn2bin_eswap(key->curve, key->y, + (uint8_t *)x.buf + bytes); + /* Validate the public key for the curve */ + arg.data[0] = key->curve; + arg.dlen = 1; + arg.ibuf[0].mem = x; + if (versal_crypto_request(VERSAL_ELLIPTIC_VALIDATE_PUBLIC_KEY, + &arg, &err)) { + EMSG("Versal ECC: %s", versal_ecc_error(err)); + ret = TEE_ERROR_GENERIC; + goto out2; + } + memset(&arg, 0, sizeof(arg)); + + ret = versal_mbox_alloc(sig_len, NULL, &s); + if (ret) + goto out2; + + /* Swap the {R,S} components */ + versal_memcpy_swp(s.buf, sig, sig_len / 2); + versal_memcpy_swp((uint8_t *)s.buf + sig_len / 2, sig + sig_len / 2, + sig_len / 2); + + ret = versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); + if (ret) + goto out3; + + cmd = cmd_buf.buf; + cmd->signature_addr = virt_to_phys(s.buf); + cmd->pub_key_addr = virt_to_phys(x.buf); + cmd->hash_addr = virt_to_phys(p.buf); + cmd->hash_len = p.len; + cmd->curve = key->curve; + + arg.ibuf[0].mem = cmd_buf; + arg.ibuf[1].mem = p; + arg.ibuf[1].only_cache = true; + arg.ibuf[2].mem = x; + arg.ibuf[3].mem = s; + + if (versal_crypto_request(VERSAL_ELLIPTIC_VERIFY_SIGN, &arg, &err)) { + EMSG("Versal ECC: %s", versal_ecc_error(err)); + ret = TEE_ERROR_GENERIC; + } + + versal_mbox_free(&cmd_buf); +out3: + versal_mbox_free(&s); +out2: + versal_mbox_free(&x); +out1: + versal_mbox_free(&p); + + return ret; +} + +TEE_Result versal_ecc_sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + uint8_t swp[TEE_SHA512_HASH_SIZE + 2] = { 0 }; + size_t len = 0; + struct versal_ecc_sign_param *cmd = NULL; + struct versal_mbox_mem cmd_buf = { }; + struct ecc_keypair ephemeral = { }; + struct versal_cmd_args arg = { }; + struct versal_mbox_mem p = { }; + struct versal_mbox_mem k = { }; + struct versal_mbox_mem d = { }; + struct versal_mbox_mem s = { }; + TEE_Result ret = TEE_SUCCESS; + uint32_t err = 0; + size_t bytes = 0; + size_t bits = 0; + + ret = versal_ecc_get_key_size(key->curve, &bytes, &bits); + if (ret) + return ret; + + /* Hash and update the length */ + ret = versal_ecc_prepare_msg(algo, msg, msg_len, &len, (uint8_t *)&swp); + if (ret) + return ret; + ret = versal_mbox_alloc(len, swp, &p); + if (ret) + return ret; + + /* Ephemeral private key */ + ret = drvcrypt_asym_alloc_ecc_keypair(&ephemeral, + TEE_TYPE_ECDSA_KEYPAIR, bits); + if (ret) { + EMSG("Versal, can't allocate the ephemeral key"); + goto out; + } + + ephemeral.curve = key->curve; + ret = crypto_acipher_gen_ecc_key(&ephemeral, bits); + if (ret) { + EMSG("Versal, can't generate the ephemeral key"); + goto out; + } + + ret = versal_mbox_alloc(bytes, NULL, &k); + if (ret) + goto out; + + versal_crypto_bignum_bn2bin_eswap(key->curve, ephemeral.d, k.buf); + + /* Private key*/ + ret = versal_mbox_alloc(bytes, NULL, &d); + if (ret) + goto out; + versal_crypto_bignum_bn2bin_eswap(key->curve, key->d, d.buf); + + /* Signature */ + ret = versal_mbox_alloc(*sig_len, NULL, &s); + if (ret) + goto out; + + /* IPI command */ + ret = versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); + if (ret) + goto out; + + cmd = cmd_buf.buf; + cmd->priv_key_addr = virt_to_phys(d.buf); + cmd->epriv_key_addr = virt_to_phys(k.buf); + cmd->hash_addr = virt_to_phys(p.buf); + cmd->hash_len = p.len; + cmd->curve = key->curve; + + arg.ibuf[0].mem = cmd_buf; + arg.ibuf[1].mem = s; + arg.ibuf[2].mem = k; + arg.ibuf[3].mem = d; + arg.ibuf[4].mem = p; + + if (versal_crypto_request(VERSAL_ELLIPTIC_GENERATE_SIGN, &arg, &err)) { + EMSG("Versal ECC: %s", versal_ecc_error(err)); + ret = TEE_ERROR_GENERIC; + goto out; + } + + *sig_len = 2 * bytes; + + /* Swap the {R,S} components */ + versal_memcpy_swp(sig, s.buf, *sig_len / 2); + versal_memcpy_swp(sig + *sig_len / 2, (uint8_t *)s.buf + *sig_len / 2, + *sig_len / 2); + +out: + crypto_bignum_free(&ephemeral.d); + crypto_bignum_free(&ephemeral.x); + crypto_bignum_free(&ephemeral.y); + + versal_mbox_free(&cmd_buf); + versal_mbox_free(&s); + versal_mbox_free(&d); + versal_mbox_free(&k); + versal_mbox_free(&p); + + return ret; +} + +/* AMD/Xilinx Versal's Known Answer Tests */ +#define XSECURE_ECDSA_KAT_NIST_P384 0 + +TEE_Result versal_ecc_kat_test(void) +{ + struct versal_cmd_args arg = { }; + uint32_t err = 0; + + arg.data[arg.dlen++] = VERSAL_ELLIPTIC_SIGN_GEN_KAT; + arg.data[arg.dlen++] = XSECURE_ECDSA_KAT_NIST_P384; + if (versal_crypto_request(VERSAL_KAT, &arg, &err)) { + EMSG("Versal KAG NIST_P384: %s", versal_ecc_error(err)); + return TEE_ERROR_GENERIC; + } + + /* Clean previous request */ + arg.dlen = 0; + + arg.data[arg.dlen++] = VERSAL_ELLIPTIC_SIGN_VERIFY_KAT; + arg.data[arg.dlen++] = XSECURE_ECDSA_KAT_NIST_P384; + if (versal_crypto_request(VERSAL_KAT, &arg, &err)) { + EMSG("Versal KAG NIST_P521 %s", versal_ecc_error(err)); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +TEE_Result versal_ecc_gen_keypair(struct ecc_keypair *s __maybe_unused) +{ + /* + * Versal requires little endian so need to versal_memcpy_swp on Versal + * IP ops. We chose not to do it here because some tests might be using + * their own keys + */ + + return TEE_ERROR_NOT_SUPPORTED; +} + +TEE_Result versal_ecc_hw_init(void) +{ + return TEE_SUCCESS; +} diff --git a/core/drivers/crypto/versal/include/ecc.h b/core/drivers/crypto/versal/include/ecc.h new file mode 100644 index 00000000000..dc8afcaeed2 --- /dev/null +++ b/core/drivers/crypto/versal/include/ecc.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) ProvenRun SAS, 2023 + */ + +#ifndef ECC_H +#define ECC_H + +#include +#include +#include +#include + +TEE_Result versal_ecc_get_key_size(uint32_t curve, size_t *bytes, size_t *bits); +TEE_Result versal_ecc_prepare_msg(uint32_t algo, const uint8_t *msg, + size_t msg_len, size_t *len, uint8_t *buf); + +TEE_Result versal_ecc_hw_init(void); +TEE_Result versal_ecc_kat_test(void); + +TEE_Result versal_ecc_gen_keypair(struct ecc_keypair *s); +#ifdef CFG_VERSAL_PKI_PWCT +TEE_Result versal_ecc_keypair_pwct(struct ecc_keypair *s); +#endif +TEE_Result versal_ecc_verify(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len); +TEE_Result versal_ecc_sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len); +TEE_Result versal_ecc_sign_ephemeral(uint32_t algo, size_t bytes, + struct ecc_keypair *key, + struct ecc_keypair *ephemeral, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len); + +void versal_memcpy_swp(uint8_t *to, const uint8_t *from, size_t len); +void versal_crypto_bignum_bn2bin_eswap(uint32_t curve, struct bignum *from, + uint8_t *to); +void versal_crypto_bignum_bin2bn_eswap(const uint8_t *from, size_t sz, + struct bignum *to); + +#endif diff --git a/core/drivers/crypto/versal/include/ipi.h b/core/drivers/crypto/versal/include/ipi.h index 2c92a1a9bc1..2c3c08ec2d8 100644 --- a/core/drivers/crypto/versal/include/ipi.h +++ b/core/drivers/crypto/versal/include/ipi.h @@ -57,15 +57,12 @@ enum versal_crypto_api { VERSAL_RSA_SIGN_VERIFY, VERSAL_RSA_PUBLIC_ENCRYPT, VERSAL_RSA_PRIVATE_DECRYPT, - VERSAL_RSA_KAT, - VERSAL_SHA3_UPDATE = 32U, - VERSAL_SHA3_KAT, - VERSAL_ELLIPTIC_GENERATE_PUBLIC_KEY = 64U, + VERSAL_SHA3_UPDATE, + VERSAL_ELLIPTIC_GENERATE_PUBLIC_KEY, VERSAL_ELLIPTIC_GENERATE_SIGN, VERSAL_ELLIPTIC_VALIDATE_PUBLIC_KEY, VERSAL_ELLIPTIC_VERIFY_SIGN, - VERSAL_ELLIPTIC_KAT, - VERSAL_AES_INIT = 96U, + VERSAL_AES_INIT, VERSAL_AES_OP_INIT, VERSAL_AES_UPDATE_AAD, VERSAL_AES_ENCRYPT_UPDATE, @@ -77,11 +74,25 @@ enum versal_crypto_api { VERSAL_AES_LOCK_USER_KEY, VERSAL_AES_KEK_DECRYPT, VERSAL_AES_SET_DPA_CM, - VERSAL_AES_DECRYPT_KAT, - VERSAL_AES_DECRYPT_CM_KAT, + VERSAL_KAT, + VERSAL_TRNG_GENERATE, + VERSAL_AES_PERFORM_OPERATION, VERSAL_CRYPTO_API_MAX }; +enum versal_crypto_kat { + VERSAL_AES_DECRYPT_KAT = 0U, + VERSAL_AES_DECRYPT_CM_KAT, + VERSAL_RSA_PUB_ENC_KAT, + VERSAL_ELLIPTIC_SIGN_VERIFY_KAT, + VERSAL_SHA3_KAT, + VERSAL_AES_ENCRYPT_KAT, + VERSAL_RSA_PRIVATE_DEC_KAT, + VERSAL_ELLIPTIC_SIGN_GEN_KAT, + VERSAL_TRNG_KAT, + VERSAL_UPDATE_KAT_STATUS, +}; + #define VERSAL_MAX_IPI_REGS 6 struct versal_cmd_args { diff --git a/core/drivers/crypto/versal/ipi.c b/core/drivers/crypto/versal/ipi.c index ba2b636bdf4..a7cbe686955 100644 --- a/core/drivers/crypto/versal/ipi.c +++ b/core/drivers/crypto/versal/ipi.c @@ -44,7 +44,7 @@ static TEE_Result versal_sha3_request(enum versal_crypto_api id, cmd.ibuf[0].mem = arg->ibuf[0].mem; } - return versal_mbox_notify(&cmd, NULL, NULL); + return versal_mbox_notify_pmc(&cmd, NULL, NULL); } static TEE_Result versal_aes_update_aad_request(enum versal_crypto_api id, @@ -63,7 +63,7 @@ static TEE_Result versal_aes_update_aad_request(enum versal_crypto_api id, cmd.ibuf[0].mem = arg->ibuf[0].mem; - return versal_mbox_notify(&cmd, NULL, NULL); + return versal_mbox_notify_pmc(&cmd, NULL, NULL); } TEE_Result versal_crypto_request(enum versal_crypto_api id, @@ -106,5 +106,5 @@ TEE_Result versal_crypto_request(enum versal_crypto_api id, for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) cmd.ibuf[i].mem = arg->ibuf[i].mem; notify: - return versal_mbox_notify(&cmd, NULL, err); + return versal_mbox_notify_pmc(&cmd, NULL, err); } diff --git a/core/drivers/crypto/versal/pki/ecc_pki_engine.c b/core/drivers/crypto/versal/pki/ecc_pki_engine.c new file mode 100644 index 00000000000..dca9696d6d8 --- /dev/null +++ b/core/drivers/crypto/versal/pki/ecc_pki_engine.c @@ -0,0 +1,858 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) ProvenRun SAS 2023. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* PKI Engine TRNG driver */ +#define TRNG_BASE UINT64_C(0x20400051000) +#define TRNG_SIZE 0x10000 + +static struct versal_trng ecc_pki_trng = { + .cfg.base = TRNG_BASE, + .cfg.len = TRNG_SIZE, +}; + +static TEE_Result versal_ecc_trng_init(void) +{ + const uint8_t pers_str[TRNG_PERS_STR_LEN] = { + 0xB2, 0x80, 0x7E, 0x4C, 0xD0, 0xE4, 0xE2, 0xA9, + 0x2F, 0x1F, 0x5D, 0xC1, 0xA2, 0x1F, 0x40, 0xFC, + 0x1F, 0x24, 0x5D, 0x42, 0x61, 0x80, 0xE6, 0xE9, + 0x71, 0x05, 0x17, 0x5B, 0xAF, 0x70, 0x30, 0x18, + 0xBC, 0x23, 0x18, 0x15, 0xCB, 0xB8, 0xA6, 0x3E, + 0x83, 0xB8, 0x4A, 0xFE, 0x38, 0xFC, 0x25, 0x87, + }; + + /* configure in hybrid mode with derivative function enabled */ + struct trng_usr_cfg usr_cfg = { + .mode = TRNG_HRNG, + .seed_life = CFG_VERSAL_TRNG_SEED_LIFE, + .predict_en = false, + .df_disable = false, + .dfmul = CFG_VERSAL_TRNG_DF_MUL, + .iseed_en = false, + .pstr_en = true, + }; + + memcpy(usr_cfg.pstr, pers_str, TRNG_PERS_STR_LEN); + + return versal_trng_hw_init(&ecc_pki_trng, &usr_cfg); +} + +static TEE_Result versal_ecc_trng_get_random_bytes(void *buf, size_t len) +{ + return versal_trng_get_random_bytes(&ecc_pki_trng, buf, len); +} + +#define FPD_PKI_CRYPTO_BASEADDR UINT64_C(0x20400000000) +#define FPD_PKI_CTRLSTAT_BASEADDR UINT64_C(0x20400050000) + +#define FPD_PKI_SIZE 0x10000 + +#define PKI_ENGINE_GEN_CTRL_OFFSET UINT64_C(0x00000000) +#define PKI_ENGINE_GEN_CTRL_TZ 0x100 + +#define PKI_ENGINE_CTRL_OFFSET UINT64_C(0x00000C00) +#define PKI_ENGINE_CTRL_CM_MASK 0x1 + +#define PKI_CRYPTO_SOFT_RESET_OFFSET UINT64_C(0x00000038) +#define PKI_CRYPTO_IRQ_STATUS_OFFSET UINT64_C(0x00000088) +#define PKI_CRYPTO_IRQ_ENABLE_OFFSET UINT64_C(0x00000090) +#define PKI_CRYPTO_IRQ_RESET_OFFSET UINT64_C(0x000000A0) +#define PKI_RQ_CFG_PAGE_ADDR_IN_OFFSET UINT64_C(0x00000100) +#define PKI_RQ_CFG_PAGE_ADDR_OUT_OFFSET UINT64_C(0x00000108) +#define PKI_RQ_CFG_PAGE_SIZE_OFFSET UINT64_C(0x00000120) +#define PKI_RQ_CFG_CQID_OFFSET UINT64_C(0x00000128) +#define PKI_RQ_CFG_PERMISSIONS_OFFSET UINT64_C(0x00000130) +#define PKI_RQ_CFG_QUEUE_DEPTH_OFFSET UINT64_C(0x00000140) +#define PKI_CQ_CFG_ADDR_OFFSET UINT64_C(0x00001100) +#define PKI_CQ_CFG_SIZE_OFFSET UINT64_C(0x00001108) +#define PKI_CQ_CFG_IRQ_IDX_OFFSET UINT64_C(0x00001110) +#define PKI_RQ_CTL_NEW_REQUEST_OFFSET UINT64_C(0x00002000) +#define PKI_CQ_CTL_TRIGPOS_OFFSET UINT64_C(0x00002028) + +#define PKI_RQ_CFG_PERMISSIONS_SAFE 0x0 +#define PKI_RQ_CFG_PAGE_SIZE_1024 0x10 +#define PKI_RQ_CFG_CQID 0x0 +#define PKI_CQ_CFG_SIZE_4096 0xC +#define PKI_CQ_CFG_IRQ_ID_VAL 0x0 +#define PKI_RQ_CFG_QUEUE_DEPTH_VAL 0x80 +#define PKI_IRQ_ENABLE_VAL 0xFFFF +#define PKI_CQ_CTL_TRIGPOS_VAL 0x201 + +#define PKI_IRQ_DONE_STATUS_VAL 0x1 + +#define PKI_NEW_REQUEST_MASK 0x00000FFF + +#define PKI_MAX_RETRY_COUNT 10000 + +#define PKI_QUEUE_BUF_SIZE 0x1000 + +struct versal_pki { + vaddr_t regs; + + uint8_t *rq_in; + uint8_t *rq_out; + uint8_t *cq; +}; + +static struct versal_pki versal_pki; + +/* + * PKI Engine Descriptors + */ + +#define PKI_DESC_LEN_BYTES 0x20 + +#define PKI_DESC_TAG_START 0x00000002 +#define PKI_DESC_TAG_TFRI(sz) ((sz) << 16 | 0x0006) +#define PKI_DESC_TAG_TFRO(sz) ((sz) << 16 | 0x000E) +#define PKI_DESC_TAG_NTFY(id) ((id) << 16 | 0x0016) + +#define PKI_DESC_OPTYPE_MOD_ADD 0x01 +#define PKI_DESC_OPTYPE_ECC_POINTMUL 0x22 +#define PKI_DESC_OPTYPE_ECDSA_SIGN 0x30 +#define PKI_DESC_OPTYPE_ECDSA_VERIFY 0x31 + +#define PKI_DESC_ECC_FIELD_GFP 0x0 + +#define PKI_DESC_OPSIZE_P256 0x1F +#define PKI_DESC_OPSIZE_P384 0x2F +#define PKI_DESC_OPSIZE_P521 0x41 + +#define PKI_DESC_SELCURVE_P256 0x1 +#define PKI_DESC_SELCURVE_P384 0x2 +#define PKI_DESC_SELCURVE_P521 0x3 + +#define PKI_DESC_TAG_START_CMD(op, opsize, selcurve, field) \ + ((op) | ((field) << 7) | ((opsize) << 8) | ((selcurve) << 20)) + +#define PKI_SIGN_INPUT_OP_COUNT 3 +#define PKI_VERIFY_INPUT_OP_COUNT 5 +#define PKI_MOD_ADD_INPUT_OP_COUNT 3 +#define PKI_ECC_POINTMUL_INPUT_OP_COUNT 3 + +#define PKI_SIGN_OUTPUT_OP_COUNT 2 +#define PKI_VERIFY_OUTPUT_OP_COUNT 0 +#define PKI_MOD_ADD_OUTPUT_OP_COUNT 1 +#define PKI_ECC_POINTMUL_OUTPUT_OP_COUNT 2 + +#define PKI_SIGN_P521_PADD_BYTES 2 +#define PKI_VERIFY_P521_PADD_BYTES 6 + +#define PKI_DEFAULT_REQID UINT16_C(0xB04EU) + +#define PKI_EXPECTED_CQ_STATUS 0 +#define PKI_EXPECTED_CQ_VALUE (SHIFT_U32(PKI_DEFAULT_REQID, 16) | 0x1) + +#define PKI_RESET_DELAY_US 10 + +static TEE_Result pki_get_opsize(uint32_t curve, uint32_t op, size_t *in_sz, + size_t *out_sz) +{ + TEE_Result ret = TEE_SUCCESS; + size_t bits = 0; + size_t bytes = 0; + + ret = versal_ecc_get_key_size(curve, &bytes, &bits); + if (ret) + return ret; + + switch (op) { + case PKI_DESC_OPTYPE_ECDSA_SIGN: + *in_sz = bytes * PKI_SIGN_INPUT_OP_COUNT; + *out_sz = bytes * PKI_SIGN_OUTPUT_OP_COUNT; + break; + case PKI_DESC_OPTYPE_ECDSA_VERIFY: + *in_sz = bytes * PKI_VERIFY_INPUT_OP_COUNT; + *out_sz = bytes * PKI_VERIFY_OUTPUT_OP_COUNT; + break; + case PKI_DESC_OPTYPE_MOD_ADD: + *in_sz = bytes * PKI_MOD_ADD_INPUT_OP_COUNT; + *out_sz = bytes * PKI_MOD_ADD_OUTPUT_OP_COUNT; + break; + case PKI_DESC_OPTYPE_ECC_POINTMUL: + *in_sz = bytes * PKI_ECC_POINTMUL_INPUT_OP_COUNT; + *out_sz = bytes * PKI_ECC_POINTMUL_OUTPUT_OP_COUNT; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +static TEE_Result pki_build_descriptors(uint32_t curve, uint32_t op, + uint32_t *descs) +{ + TEE_Result ret = TEE_SUCCESS; + size_t in_sz = 0; + size_t out_sz = 0; + uint32_t opsize = 0; + uint32_t selcurve = 0; + + ret = pki_get_opsize(curve, op, &in_sz, &out_sz); + if (ret) + return ret; + + switch (curve) { + case TEE_ECC_CURVE_NIST_P256: + opsize = PKI_DESC_OPSIZE_P256; + selcurve = PKI_DESC_SELCURVE_P256; + break; + case TEE_ECC_CURVE_NIST_P384: + opsize = PKI_DESC_OPSIZE_P384; + selcurve = PKI_DESC_SELCURVE_P384; + break; + case TEE_ECC_CURVE_NIST_P521: + opsize = PKI_DESC_OPSIZE_P521; + selcurve = PKI_DESC_SELCURVE_P521; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + /* SelCurve must be zero for ModAdd */ + if (op == PKI_DESC_OPTYPE_MOD_ADD) + selcurve = 0; + + descs[0] = PKI_DESC_TAG_START; + descs[1] = PKI_DESC_TAG_START_CMD(op, opsize, selcurve, + PKI_DESC_ECC_FIELD_GFP); + descs[2] = PKI_DESC_TAG_TFRI(in_sz); + descs[3] = 0; + descs[4] = PKI_DESC_TAG_TFRO(out_sz); + descs[5] = 0x10000; + descs[6] = PKI_DESC_TAG_NTFY(PKI_DEFAULT_REQID); + descs[7] = 0; + + return TEE_SUCCESS; +} + +static TEE_Result pki_start_operation(uint32_t reqval) +{ + uint32_t retries = PKI_MAX_RETRY_COUNT; + + /* Soft reset */ + io_write32(versal_pki.regs + PKI_CRYPTO_SOFT_RESET_OFFSET, 1); + udelay(PKI_RESET_DELAY_US); + io_write32(versal_pki.regs + PKI_CRYPTO_SOFT_RESET_OFFSET, 0); + + cache_operation(TEE_CACHEFLUSH, versal_pki.rq_in, PKI_QUEUE_BUF_SIZE); + cache_operation(TEE_CACHEFLUSH, versal_pki.rq_out, PKI_QUEUE_BUF_SIZE); + cache_operation(TEE_CACHEFLUSH, versal_pki.cq, PKI_QUEUE_BUF_SIZE); + + io_write32(versal_pki.regs + PKI_RQ_CFG_PERMISSIONS_OFFSET, + PKI_RQ_CFG_PERMISSIONS_SAFE); + io_write64(versal_pki.regs + PKI_RQ_CFG_PAGE_ADDR_IN_OFFSET, + virt_to_phys(versal_pki.rq_in)); + io_write64(versal_pki.regs + PKI_RQ_CFG_PAGE_ADDR_OUT_OFFSET, + virt_to_phys(versal_pki.rq_out)); + io_write64(versal_pki.regs + PKI_CQ_CFG_ADDR_OFFSET, + virt_to_phys(versal_pki.cq)); + io_write32(versal_pki.regs + PKI_RQ_CFG_PAGE_SIZE_OFFSET, + PKI_RQ_CFG_PAGE_SIZE_1024); + io_write32(versal_pki.regs + PKI_RQ_CFG_CQID_OFFSET, PKI_RQ_CFG_CQID); + io_write32(versal_pki.regs + PKI_CQ_CFG_SIZE_OFFSET, + PKI_CQ_CFG_SIZE_4096); + io_write32(versal_pki.regs + PKI_CQ_CFG_IRQ_IDX_OFFSET, + PKI_CQ_CFG_IRQ_ID_VAL); + io_write32(versal_pki.regs + PKI_RQ_CFG_QUEUE_DEPTH_OFFSET, + PKI_RQ_CFG_QUEUE_DEPTH_VAL); + io_write64(versal_pki.regs + PKI_CRYPTO_IRQ_ENABLE_OFFSET, + PKI_IRQ_ENABLE_VAL); + + io_write32(versal_pki.regs + PKI_CQ_CTL_TRIGPOS_OFFSET, + PKI_CQ_CTL_TRIGPOS_VAL); + io_write64(versal_pki.regs + PKI_RQ_CTL_NEW_REQUEST_OFFSET, reqval); + + /* Wait for completion */ + while (retries--) { + uint64_t irq_status = io_read64(versal_pki.regs + + PKI_CRYPTO_IRQ_STATUS_OFFSET); + if (irq_status == PKI_IRQ_DONE_STATUS_VAL) { + io_write64(versal_pki.regs + + PKI_CRYPTO_IRQ_RESET_OFFSET, + PKI_IRQ_DONE_STATUS_VAL); + return TEE_SUCCESS; + } + } + + return TEE_ERROR_TIMEOUT; +} + +static TEE_Result pki_check_status(void) +{ + uint32_t cq_status = 0; + uint32_t cq_value = 0; + + cache_operation(TEE_CACHEFLUSH, versal_pki.cq, PKI_QUEUE_BUF_SIZE); + + cq_status = io_read32((vaddr_t)versal_pki.cq); + cq_value = io_read32((vaddr_t)versal_pki.cq + 4); + + if (cq_status != PKI_EXPECTED_CQ_STATUS || + cq_value != PKI_EXPECTED_CQ_VALUE) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +TEE_Result versal_ecc_verify(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + TEE_Result ret = TEE_SUCCESS; + size_t bits = 0; + size_t bytes = 0; + size_t len = 0; + uint8_t *addr = versal_pki.rq_in; + uint32_t descriptors[8] = { }; + + ret = versal_ecc_get_key_size(key->curve, &bytes, &bits); + if (ret) + return ret; + + /* Copy public key */ + versal_crypto_bignum_bn2bin_eswap(key->curve, key->x, addr); + addr += bytes; + versal_crypto_bignum_bn2bin_eswap(key->curve, key->y, addr); + addr += bytes; + + /* Copy signature */ + versal_memcpy_swp(addr, sig, sig_len / 2); + addr += sig_len / 2; + versal_memcpy_swp(addr, sig + sig_len / 2, sig_len / 2); + addr += sig_len / 2; + + /* Copy hash */ + ret = versal_ecc_prepare_msg(algo, msg, msg_len, &len, addr); + if (ret) + return ret; + if (len < bytes) + memset(addr + len, 0, bytes - len); + addr += bytes; + + if (key->curve == TEE_ECC_CURVE_NIST_P521) { + memset((uint8_t *)addr, 0, PKI_VERIFY_P521_PADD_BYTES); + addr += PKI_VERIFY_P521_PADD_BYTES; + } + + /* Build descriptors */ + if (!IS_ALIGNED_WITH_TYPE(addr, uint32_t)) + return TEE_ERROR_BAD_PARAMETERS; + + ret = pki_build_descriptors(key->curve, PKI_DESC_OPTYPE_ECDSA_VERIFY, + descriptors); + if (ret) + return ret; + + ret = pki_start_operation(PKI_NEW_REQUEST_MASK & ((uintptr_t)addr + 1)); + if (ret) + return ret; + + ret = pki_check_status(); + if (ret) + return ret; + + /* Clear memory */ + memset(versal_pki.rq_in, 0, PKI_QUEUE_BUF_SIZE); + memset(versal_pki.cq, 0, PKI_QUEUE_BUF_SIZE); + + return TEE_SUCCESS; +} + +TEE_Result versal_ecc_sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + TEE_Result ret = TEE_SUCCESS; + size_t bits = 0; + size_t bytes = 0; + struct ecc_keypair ephemeral = { }; + + ret = versal_ecc_get_key_size(key->curve, &bytes, &bits); + if (ret) + return ret; + + /* Ephemeral private key */ + ret = drvcrypt_asym_alloc_ecc_keypair(&ephemeral, + TEE_TYPE_ECDSA_KEYPAIR, bits); + if (ret) { + EMSG("Versal, can't allocate the ephemeral key"); + return ret; + } + + ephemeral.curve = key->curve; + ret = versal_ecc_gen_keypair(&ephemeral); + if (ret) { + EMSG("Versal, can't generate the ephemeral key"); + goto out; + } + + ret = versal_ecc_sign_ephemeral(algo, bytes, key, &ephemeral, msg, + msg_len, sig, sig_len); + +out: + crypto_bignum_free(&ephemeral.d); + crypto_bignum_free(&ephemeral.x); + crypto_bignum_free(&ephemeral.y); + + return ret; +} + +TEE_Result versal_ecc_sign_ephemeral(uint32_t algo, size_t bytes, + struct ecc_keypair *key, + struct ecc_keypair *ephemeral, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + TEE_Result ret = TEE_SUCCESS; + size_t len = 0; + uintptr_t addr = (uintptr_t)versal_pki.rq_in; + + /* Copy private key */ + versal_crypto_bignum_bn2bin_eswap(key->curve, key->d, (uint8_t *)addr); + addr += bytes; + + /* Copy ephemeral key */ + versal_crypto_bignum_bn2bin_eswap(key->curve, ephemeral->d, + (uint8_t *)addr); + addr += bytes; + + /* Copy hash */ + ret = versal_ecc_prepare_msg(algo, msg, msg_len, &len, (uint8_t *)addr); + if (ret) + return ret; + if (len < bytes) + memset((uint8_t *)addr + len, 0, bytes - len); + addr += bytes; + + if (key->curve == TEE_ECC_CURVE_NIST_P521) { + memset((uint8_t *)addr, 0, PKI_SIGN_P521_PADD_BYTES); + addr += PKI_SIGN_P521_PADD_BYTES; + } + + /* Build descriptors */ + ret = pki_build_descriptors(key->curve, PKI_DESC_OPTYPE_ECDSA_SIGN, + (uint32_t *)addr); + if (ret) + return ret; + + ret = pki_start_operation(PKI_NEW_REQUEST_MASK & (addr + 1)); + if (ret) + return ret; + + ret = pki_check_status(); + if (ret) + return ret; + + /* Copy signature back */ + *sig_len = 2 * bytes; + + cache_operation(TEE_CACHEFLUSH, versal_pki.rq_out, PKI_QUEUE_BUF_SIZE); + + versal_memcpy_swp(sig, versal_pki.rq_out, bytes); + versal_memcpy_swp(sig + bytes, versal_pki.rq_out + bytes, bytes); + + /* Clear memory */ + memset(versal_pki.rq_in, 0, PKI_QUEUE_BUF_SIZE); + memset(versal_pki.rq_out, 0, PKI_QUEUE_BUF_SIZE); + memset(versal_pki.cq, 0, PKI_QUEUE_BUF_SIZE); + + return ret; +} + +static const uint8_t order_p256[] = { + 0x51, 0x25, 0x63, 0xfc, 0xc2, 0xca, 0xb9, 0xf3, + 0x84, 0x9e, 0x17, 0xa7, 0xad, 0xfa, 0xe6, 0xbc, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +}; + +static const uint8_t order_p384[] = { + 0x73, 0x29, 0xc5, 0xcc, 0x6a, 0x19, 0xec, 0xec, + 0x7a, 0xa7, 0xb0, 0x48, 0xb2, 0x0d, 0x1a, 0x58, + 0xdf, 0x2d, 0x37, 0xf4, 0x81, 0x4d, 0x63, 0xc7, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +static const uint8_t order_p521[] = { + 0x09, 0x64, 0x38, 0x91, 0x1e, 0xb7, 0x6f, 0xbb, + 0xae, 0x47, 0x9c, 0x89, 0xb8, 0xc9, 0xb5, 0x3b, + 0xd0, 0xa5, 0x09, 0xf7, 0x48, 0x01, 0xcc, 0x7f, + 0x6b, 0x96, 0x2f, 0xbf, 0x83, 0x87, 0x86, 0x51, + 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01 +}; + +static const uint8_t ecdsa_gpoint_p256_gx[] = { + 0x96, 0xc2, 0x98, 0xd8, 0x45, 0x39, 0xa1, 0xf4, + 0xa0, 0x33, 0xeb, 0x2d, 0x81, 0x7d, 0x03, 0x77, + 0xf2, 0x40, 0xa4, 0x63, 0xe5, 0xe6, 0xbc, 0xf8, + 0x47, 0x42, 0x2c, 0xe1, 0xf2, 0xd1, 0x17, 0x6b +}; + +static const uint8_t ecdsa_gpoint_p256_gy[] = { + 0xf5, 0x51, 0xbf, 0x37, 0x68, 0x40, 0xb6, 0xcb, + 0xce, 0x5e, 0x31, 0x6b, 0x57, 0x33, 0xce, 0x2b, + 0x16, 0x9e, 0x0f, 0x7c, 0x4a, 0xeb, 0xe7, 0x8e, + 0x9b, 0x7f, 0x1a, 0xfe, 0xe2, 0x42, 0xe3, 0x4f +}; + +static const uint8_t ecdsa_gpoint_p384_gx[] = { + 0xb7, 0x0a, 0x76, 0x72, 0x38, 0x5e, 0x54, 0x3a, + 0x6c, 0x29, 0x55, 0xbf, 0x5d, 0xf2, 0x02, 0x55, + 0x38, 0x2a, 0x54, 0x82, 0xe0, 0x41, 0xf7, 0x59, + 0x98, 0x9b, 0xa7, 0x8b, 0x62, 0x3b, 0x1d, 0x6e, + 0x74, 0xad, 0x20, 0xf3, 0x1e, 0xc7, 0xb1, 0x8e, + 0x37, 0x05, 0x8b, 0xbe, 0x22, 0xca, 0x87, 0xaa +}; + +static const uint8_t ecdsa_gpoint_p384_gy[] = { + 0x5f, 0x0e, 0xea, 0x90, 0x7c, 0x1d, 0x43, 0x7a, + 0x9d, 0x81, 0x7e, 0x1d, 0xce, 0xb1, 0x60, 0x0a, + 0xc0, 0xb8, 0xf0, 0xb5, 0x13, 0x31, 0xda, 0xe9, + 0x7c, 0x14, 0x9a, 0x28, 0xbd, 0x1d, 0xf4, 0xf8, + 0x29, 0xdc, 0x92, 0x92, 0xbf, 0x98, 0x9e, 0x5d, + 0x6f, 0x2c, 0x26, 0x96, 0x4a, 0xde, 0x17, 0x36 +}; + +static const uint8_t ecdsa_gpoint_p521_gx[] = { + 0x66, 0xbd, 0xe5, 0xc2, 0x31, 0x7e, 0x7e, 0xf9, + 0x9b, 0x42, 0x6a, 0x85, 0xc1, 0xb3, 0x48, 0x33, + 0xde, 0xa8, 0xff, 0xa2, 0x27, 0xc1, 0x1d, 0xfe, + 0x28, 0x59, 0xe7, 0xef, 0x77, 0x5e, 0x4b, 0xa1, + 0xba, 0x3d, 0x4d, 0x6b, 0x60, 0xaf, 0x28, 0xf8, + 0x21, 0xb5, 0x3f, 0x05, 0x39, 0x81, 0x64, 0x9c, + 0x42, 0xb4, 0x95, 0x23, 0x66, 0xcb, 0x3e, 0x9e, + 0xcd, 0xe9, 0x04, 0x04, 0xb7, 0x06, 0x8e, 0x85, + 0xc6, 0x00 +}; + +static const uint8_t ecdsa_gpoint_p521_gy[] = { + 0x50, 0x66, 0xd1, 0x9f, 0x76, 0x94, 0xbe, 0x88, + 0x40, 0xc2, 0x72, 0xa2, 0x86, 0x70, 0x3c, 0x35, + 0x61, 0x07, 0xad, 0x3f, 0x01, 0xb9, 0x50, 0xc5, + 0x40, 0x26, 0xf4, 0x5e, 0x99, 0x72, 0xee, 0x97, + 0x2c, 0x66, 0x3e, 0x27, 0x17, 0xbd, 0xaf, 0x17, + 0x68, 0x44, 0x9b, 0x57, 0x49, 0x44, 0xf5, 0x98, + 0xd9, 0x1b, 0x7d, 0x2c, 0xb4, 0x5f, 0x8a, 0x5c, + 0x04, 0xc0, 0x3b, 0x9a, 0x78, 0x6a, 0x29, 0x39, + 0x18, 0x01 +}; + +static TEE_Result versal_ecc_gen_private_key(uint32_t curve, uint8_t *priv, + size_t bytes) +{ + TEE_Result ret = TEE_SUCCESS; + const uint8_t *order = NULL; + uintptr_t addr = (uintptr_t)versal_pki.rq_in; + + switch (curve) { + case TEE_ECC_CURVE_NIST_P256: + order = order_p256; + break; + case TEE_ECC_CURVE_NIST_P384: + order = order_p384; + break; + case TEE_ECC_CURVE_NIST_P521: + order = order_p521; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + /* Copy curve order N */ + memcpy((uint8_t *)addr, order, bytes); + addr += bytes; + + /* Copy A = random */ + ret = versal_ecc_trng_get_random_bytes((uint8_t *)addr, bytes); + if (ret) + return ret; + addr += bytes; + + /* Copy B = 1 */ + memset((uint8_t *)addr, 1, 1); + memset((uint8_t *)addr + 1, 0, bytes - 1); + addr += bytes; + + if (curve == TEE_ECC_CURVE_NIST_P521) { + memset((uint8_t *)addr, 0, PKI_SIGN_P521_PADD_BYTES); + addr += PKI_SIGN_P521_PADD_BYTES; + } + + /* Build descriptors */ + ret = pki_build_descriptors(curve, PKI_DESC_OPTYPE_MOD_ADD, + (uint32_t *)addr); + if (ret) + return ret; + + /* Use PKI engine to compute A+B mod N */ + ret = pki_start_operation(PKI_NEW_REQUEST_MASK & (addr + 1)); + if (ret) + return ret; + + ret = pki_check_status(); + if (ret) + return ret; + + cache_operation(TEE_CACHEFLUSH, versal_pki.rq_out, PKI_QUEUE_BUF_SIZE); + + /* Copy back result */ + memcpy(priv, versal_pki.rq_out, bytes); + + return TEE_SUCCESS; +} + +TEE_Result versal_ecc_gen_keypair(struct ecc_keypair *s) +{ + TEE_Result ret = TEE_SUCCESS; + size_t bytes = 0; + size_t bits = 0; + const uint8_t *gx = NULL; + const uint8_t *gy = NULL; + uintptr_t addr = (uintptr_t)versal_pki.rq_in; + + ret = versal_ecc_get_key_size(s->curve, &bytes, &bits); + if (ret) + return ret; + + switch (s->curve) { + case TEE_ECC_CURVE_NIST_P256: + gx = ecdsa_gpoint_p256_gx; + gy = ecdsa_gpoint_p256_gy; + break; + case TEE_ECC_CURVE_NIST_P384: + gx = ecdsa_gpoint_p384_gx; + gy = ecdsa_gpoint_p384_gy; + break; + case TEE_ECC_CURVE_NIST_P521: + gx = ecdsa_gpoint_p521_gx; + gy = ecdsa_gpoint_p521_gy; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + /* Generate private key */ + ret = versal_ecc_gen_private_key(s->curve, (uint8_t *)addr, bytes); + if (ret) + return ret; + addr += bytes; + + /* Copy generator point x coordinate */ + memcpy((uint8_t *)addr, gx, bytes); + addr += bytes; + + /* Copy generator point y coordinate */ + memcpy((uint8_t *)addr, gy, bytes); + addr += bytes; + + if (s->curve == TEE_ECC_CURVE_NIST_P521) { + memset((uint8_t *)addr, 0, PKI_SIGN_P521_PADD_BYTES); + addr += PKI_SIGN_P521_PADD_BYTES; + } + + /* Build descriptors */ + ret = pki_build_descriptors(s->curve, PKI_DESC_OPTYPE_ECC_POINTMUL, + (uint32_t *)addr); + if (ret) + return ret; + + /* Use PKI engine to compute Q = priv * G */ + ret = pki_start_operation(PKI_NEW_REQUEST_MASK & (addr + 1)); + if (ret) + return ret; + + ret = pki_check_status(); + if (ret) + return ret; + + cache_operation(TEE_CACHEFLUSH, versal_pki.rq_out, PKI_QUEUE_BUF_SIZE); + + /* Copy private and public keys back */ + versal_crypto_bignum_bin2bn_eswap(versal_pki.rq_in, bytes, s->d); + versal_crypto_bignum_bin2bn_eswap(versal_pki.rq_out, bytes, s->x); + versal_crypto_bignum_bin2bn_eswap(versal_pki.rq_out + bytes, + bytes, s->y); + + /* Clear memory */ + memset(versal_pki.rq_in, 0, PKI_QUEUE_BUF_SIZE); + memset(versal_pki.rq_out, 0, PKI_QUEUE_BUF_SIZE); + memset(versal_pki.cq, 0, PKI_QUEUE_BUF_SIZE); + + return TEE_SUCCESS; +} + +#define PSX_CRF_RST_PKI 0xEC200340 + +#define PKI_ASSERT_RESET 1 +#define PKI_DEASSERT_RESET 0 + +static TEE_Result versal_pki_engine_reset(void) +{ + vaddr_t reset = 0; + + /* Reset the PKI engine */ + reset = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, + PSX_CRF_RST_PKI, + SMALL_PAGE_SIZE); + if (!reset) + return TEE_ERROR_GENERIC; + + io_write32(reset, PKI_ASSERT_RESET); + udelay(PKI_RESET_DELAY_US); + io_write32(reset, PKI_DEASSERT_RESET); + + core_mmu_remove_mapping(MEM_AREA_IO_SEC, (void *)reset, + SMALL_PAGE_SIZE); + + return TEE_SUCCESS; +} + +#define FPD_SLCR_BASEADDR 0xEC8C0000 +#define FPD_SLCR_SIZE 0x4000 + +#define FPD_SLCR_WPROT0_OFFSET 0x00000000 +#define FPD_SLCR_PKI_MUX_SEL_OFFSET 0x00002000 + +#define FPD_CLEAR_WRITE_PROTECT 0 +#define FPD_ENABLE_WRITE_PROTECT 1 + +#define PKI_MUX_SEL_MASK 0x00000001 +#define PKI_MUX_SELECT 0x00000001 + +static TEE_Result versal_pki_engine_slcr_config(void) +{ + vaddr_t fpd_slcr = 0; + + fpd_slcr = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, + FPD_SLCR_BASEADDR, + FPD_SLCR_SIZE); + if (!fpd_slcr) + return TEE_ERROR_GENERIC; + + /* Clear FPD SCLR write protect reg */ + io_write32(fpd_slcr + FPD_SLCR_WPROT0_OFFSET, + FPD_CLEAR_WRITE_PROTECT); + + /* PKI mux selection */ + io_mask32(fpd_slcr + FPD_SLCR_PKI_MUX_SEL_OFFSET, + PKI_MUX_SELECT, PKI_MUX_SEL_MASK); + + /* Re-enable FPD SCLR write protect */ + io_write32(fpd_slcr + FPD_SLCR_WPROT0_OFFSET, + FPD_ENABLE_WRITE_PROTECT); + + core_mmu_remove_mapping(MEM_AREA_IO_SEC, + (void *)fpd_slcr, FPD_SLCR_SIZE); + + return TEE_SUCCESS; +} + +static TEE_Result versal_pki_engine_config(void) +{ + vaddr_t regs = 0; + uint64_t val = 0; + + regs = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, + FPD_PKI_CTRLSTAT_BASEADDR, + FPD_PKI_SIZE); + if (!regs) + return TEE_ERROR_GENERIC; + + /* Counter-measures configuration */ + val = io_read64(regs + PKI_ENGINE_CTRL_OFFSET); + if (IS_ENABLED(CFG_VERSAL_PKI_COUNTER_MEASURES)) + val &= ~PKI_ENGINE_CTRL_CM_MASK; + else + val |= PKI_ENGINE_CTRL_CM_MASK; + io_write64(regs + PKI_ENGINE_CTRL_OFFSET, val); + + /* Mark PKI engine transactions as secure */ + val = io_read64(regs + PKI_ENGINE_GEN_CTRL_OFFSET); + val &= ~PKI_ENGINE_GEN_CTRL_TZ; + io_write64(regs + PKI_ENGINE_GEN_CTRL_OFFSET, val); + + core_mmu_remove_mapping(MEM_AREA_IO_SEC, + (void *)regs, FPD_PKI_SIZE); + + return TEE_SUCCESS; +} + +TEE_Result versal_ecc_hw_init(void) +{ + TEE_Result ret = TEE_SUCCESS; + + ret = versal_pki_engine_slcr_config(); + if (ret != TEE_SUCCESS) + return ret; + + ret = versal_pki_engine_reset(); + if (ret != TEE_SUCCESS) + return ret; + + ret = versal_pki_engine_config(); + if (ret != TEE_SUCCESS) + return ret; + + ret = versal_ecc_trng_init(); + if (ret != TEE_SUCCESS) + return ret; + + versal_pki.regs = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, + FPD_PKI_CRYPTO_BASEADDR, + FPD_PKI_SIZE); + if (!versal_pki.regs) + return TEE_ERROR_GENERIC; + + /* Allocate queues */ + versal_pki.rq_in = memalign(CACHELINE_LEN, PKI_QUEUE_BUF_SIZE); + if (!versal_pki.rq_in) + goto error; + + versal_pki.rq_out = memalign(CACHELINE_LEN, PKI_QUEUE_BUF_SIZE); + if (!versal_pki.rq_out) + goto error; + + versal_pki.cq = memalign(CACHELINE_LEN, PKI_QUEUE_BUF_SIZE); + if (!versal_pki.cq) + goto error; + + return TEE_SUCCESS; + +error: + free(versal_pki.rq_in); + free(versal_pki.rq_out); + + core_mmu_remove_mapping(MEM_AREA_IO_SEC, + (void *)versal_pki.regs, FPD_PKI_SIZE); + + return TEE_ERROR_GENERIC; +} diff --git a/core/drivers/crypto/versal/pki/ecc_pki_kat.c b/core/drivers/crypto/versal/pki/ecc_pki_kat.c new file mode 100644 index 00000000000..0e11a89ac19 --- /dev/null +++ b/core/drivers/crypto/versal/pki/ecc_pki_kat.c @@ -0,0 +1,474 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) ProvenRun SAS 2023. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const uint8_t pubkey_qx_p256[] = { + 0xb7, 0xe0, 0x8a, 0xfd, 0xfe, 0x94, 0xba, 0xd3, + 0xf1, 0xdc, 0x8c, 0x73, 0x47, 0x98, 0xba, 0x1c, + 0x62, 0xb3, 0xa0, 0xad, 0x1e, 0x9e, 0xa2, 0xa3, + 0x82, 0x01, 0xcd, 0x08, 0x89, 0xbc, 0x7a, 0x19 +}; + +static const uint8_t pubkey_qy_p256[] = { + 0x36, 0x03, 0xf7, 0x47, 0x95, 0x9d, 0xbf, 0x7a, + 0x4b, 0xb2, 0x26, 0xe4, 0x19, 0x28, 0x72, 0x90, + 0x63, 0xad, 0xc7, 0xae, 0x43, 0x52, 0x9e, 0x61, + 0xb5, 0x63, 0xbb, 0xc6, 0x06, 0xcc, 0x5e, 0x09, +}; + +static const uint8_t pubkey_qx_p384[] = { + 0x3b, 0xf7, 0x01, 0xbc, 0x9e, 0x9d, 0x36, 0xb4, + 0xd5, 0xf1, 0x45, 0x53, 0x43, 0xf0, 0x91, 0x26, + 0xf2, 0x56, 0x43, 0x90, 0xf2, 0xb4, 0x87, 0x36, + 0x50, 0x71, 0x24, 0x3c, 0x61, 0xe6, 0x47, 0x1f, + 0xb9, 0xd2, 0xab, 0x74, 0x65, 0x7b, 0x82, 0xf9, + 0x08, 0x64, 0x89, 0xd9, 0xef, 0x0f, 0x5c, 0xb5, +}; + +static const uint8_t pubkey_qy_p384[] = { + 0xd1, 0xa3, 0x58, 0xea, 0xfb, 0xf9, 0x52, 0xe6, + 0x8d, 0x53, 0x38, 0x55, 0xcc, 0xbd, 0xaa, 0x6f, + 0xf7, 0x5b, 0x13, 0x7a, 0x51, 0x01, 0x44, 0x31, + 0x99, 0x32, 0x55, 0x83, 0x55, 0x2a, 0x62, 0x95, + 0xff, 0xe5, 0x38, 0x2d, 0x00, 0xcf, 0xcd, 0xa3, + 0x03, 0x44, 0xa9, 0xb5, 0xb6, 0x8d, 0xb8, 0x55, +}; + +static const uint8_t pubkey_qx_p521[] = { + 0x00, 0x98, 0xe9, 0x1e, 0xef, 0x9a, 0x68, 0x45, + 0x28, 0x22, 0x30, 0x9c, 0x52, 0xfa, 0xb4, 0x53, + 0xf5, 0xf1, 0x17, 0xc1, 0xda, 0x8e, 0xd7, 0x96, + 0xb2, 0x55, 0xe9, 0xab, 0x8f, 0x64, 0x10, 0xcc, + 0xa1, 0x6e, 0x59, 0xdf, 0x40, 0x3a, 0x6b, 0xdc, + 0x6c, 0xa4, 0x67, 0xa3, 0x70, 0x56, 0xb1, 0xe5, + 0x4b, 0x30, 0x05, 0xd8, 0xac, 0x03, 0x0d, 0xec, + 0xfe, 0xb6, 0x8d, 0xf1, 0x8b, 0x17, 0x18, 0x85, + 0xd5, 0xc4, +}; + +static const uint8_t pubkey_qy_p521[] = { + 0x01, 0x64, 0x35, 0x0c, 0x32, 0x1a, 0xec, 0xfc, + 0x1c, 0xca, 0x1b, 0xa4, 0x36, 0x4c, 0x9b, 0x15, + 0x65, 0x61, 0x50, 0xb4, 0xb7, 0x8d, 0x6a, 0x48, + 0xd7, 0xd2, 0x8e, 0x7f, 0x31, 0x98, 0x5e, 0xf1, + 0x7b, 0xe8, 0x55, 0x43, 0x76, 0xb7, 0x29, 0x00, + 0x71, 0x2c, 0x4b, 0x83, 0xad, 0x66, 0x83, 0x27, + 0x23, 0x15, 0x26, 0xe3, 0x13, 0xf5, 0xf0, 0x92, + 0x99, 0x9a, 0x46, 0x32, 0xfd, 0x50, 0xd9, 0x46, + 0xbc, 0x2e, +}; + +/* Signature */ +static const uint8_t sign_r_p256[] = { + 0x2b, 0x42, 0xf5, 0x76, 0xd0, 0x7f, 0x41, 0x65, + 0xff, 0x65, 0xd1, 0xf3, 0xb1, 0x50, 0x0f, 0x81, + 0xe4, 0x4c, 0x31, 0x6f, 0x1f, 0x0b, 0x3e, 0xf5, + 0x73, 0x25, 0xb6, 0x9a, 0xca, 0x46, 0x10, 0x4f, +}; + +static const uint8_t sign_s_p256[] = { + 0xdc, 0x42, 0xc2, 0x12, 0x2d, 0x63, 0x92, 0xcd, + 0x3e, 0x3a, 0x99, 0x3a, 0x89, 0x50, 0x2a, 0x81, + 0x98, 0xc1, 0x88, 0x6f, 0xe6, 0x9d, 0x26, 0x2c, + 0x4b, 0x32, 0x9b, 0xdb, 0x6b, 0x63, 0xfa, 0xf1, +}; + +static const uint8_t sign_r_p384[] = { + 0x30, 0xea, 0x51, 0x4f, 0xc0, 0xd3, 0x8d, 0x82, + 0x08, 0x75, 0x6f, 0x06, 0x81, 0x13, 0xc7, 0xca, + 0xda, 0x9f, 0x66, 0xa3, 0xb4, 0x0e, 0xa3, 0xb3, + 0x13, 0xd0, 0x40, 0xd9, 0xb5, 0x7d, 0xd4, 0x1a, + 0x33, 0x27, 0x95, 0xd0, 0x2c, 0xc7, 0xd5, 0x07, + 0xfc, 0xef, 0x9f, 0xaf, 0x01, 0xa2, 0x70, 0x88, +}; + +static const uint8_t sign_s_p384[] = { + 0xcc, 0x80, 0x8e, 0x50, 0x4b, 0xe4, 0x14, 0xf4, + 0x6c, 0x90, 0x27, 0xbc, 0xbf, 0x78, 0xad, 0xf0, + 0x67, 0xa4, 0x39, 0x22, 0xd6, 0xfc, 0xaa, 0x66, + 0xc4, 0x47, 0x68, 0x75, 0xfb, 0xb7, 0xb9, 0x4e, + 0xfd, 0x1f, 0x7d, 0x5d, 0xbe, 0x62, 0x0b, 0xfb, + 0x82, 0x1c, 0x46, 0xd5, 0x49, 0x68, 0x3a, 0xd8, +}; + +static const uint8_t sign_r_p521[] = { + 0x01, 0x40, 0xc8, 0xed, 0xca, 0x57, 0x10, 0x8c, + 0xe3, 0xf7, 0xe7, 0xa2, 0x40, 0xdd, 0xd3, 0xad, + 0x74, 0xd8, 0x1e, 0x2d, 0xe6, 0x24, 0x51, 0xfc, + 0x1d, 0x55, 0x8f, 0xdc, 0x79, 0x26, 0x9a, 0xda, + 0xcd, 0x1c, 0x25, 0x26, 0xee, 0xee, 0xf3, 0x2f, + 0x8c, 0x04, 0x32, 0xa9, 0xd5, 0x6e, 0x2b, 0x4a, + 0x8a, 0x73, 0x28, 0x91, 0xc3, 0x7c, 0x9b, 0x96, + 0x64, 0x1a, 0x92, 0x54, 0xcc, 0xfe, 0x5d, 0xc3, + 0xe2, 0xba, +}; + +static const uint8_t sign_s_p521[] = { + 0x00, 0xb2, 0x51, 0x88, 0x49, 0x2d, 0x58, 0xe8, + 0x08, 0xed, 0xeb, 0xd7, 0xbf, 0x44, 0x0e, 0xd2, + 0x0d, 0xb7, 0x71, 0xca, 0x7c, 0x61, 0x85, 0x95, + 0xd5, 0x39, 0x8e, 0x1b, 0x1c, 0x00, 0x98, 0xe3, + 0x00, 0xd8, 0xc8, 0x03, 0xec, 0x69, 0xec, 0x5f, + 0x46, 0xc8, 0x4f, 0xc6, 0x19, 0x67, 0xa3, 0x02, + 0xd3, 0x66, 0xc6, 0x27, 0xfc, 0xfa, 0x56, 0xf8, + 0x7f, 0x24, 0x1e, 0xf9, 0x21, 0xb6, 0xe6, 0x27, + 0xad, 0xbf, +}; + +static const uint8_t d_p256[] = { + 0xc4, 0x77, 0xf9, 0xf6, 0x5c, 0x22, 0xcc, 0xe2, + 0x06, 0x57, 0xfa, 0xa5, 0xb2, 0xd1, 0xd8, 0x12, + 0x23, 0x36, 0xf8, 0x51, 0xa5, 0x08, 0xa1, 0xed, + 0x04, 0xe4, 0x79, 0xc3, 0x49, 0x85, 0xbf, 0x96, +}; + +static const uint8_t d_p384[] = { + 0xf9, 0x2c, 0x02, 0xed, 0x62, 0x9e, 0x4b, 0x48, + 0xc0, 0x58, 0x4b, 0x1c, 0x6c, 0xe3, 0xa3, 0xe3, + 0xb4, 0xfa, 0xae, 0x4a, 0xfc, 0x6a, 0xcb, 0x04, + 0x55, 0xe7, 0x3d, 0xfc, 0x39, 0x2e, 0x6a, 0x0a, + 0xe3, 0x93, 0xa8, 0x56, 0x5e, 0x6b, 0x97, 0x14, + 0xd1, 0x22, 0x4b, 0x57, 0xd8, 0x3f, 0x8a, 0x08, +}; + +static const uint8_t d_p521[] = { + 0x01, 0x00, 0x08, 0x5f, 0x47, 0xb8, 0xe1, 0xb8, + 0xb1, 0x1b, 0x7e, 0xb3, 0x30, 0x28, 0xc0, 0xb2, + 0x88, 0x8e, 0x30, 0x4b, 0xfc, 0x98, 0x50, 0x19, + 0x55, 0xb4, 0x5b, 0xba, 0x14, 0x78, 0xdc, 0x18, + 0x4e, 0xee, 0xdf, 0x09, 0xb8, 0x6a, 0x5f, 0x7c, + 0x21, 0x99, 0x44, 0x06, 0x07, 0x27, 0x87, 0x20, + 0x5e, 0x69, 0xa6, 0x37, 0x09, 0xfe, 0x35, 0xaa, + 0x93, 0xba, 0x33, 0x35, 0x14, 0xb2, 0x4f, 0x96, + 0x17, 0x22, +}; + +static const uint8_t k_p256[] = { + 0x7a, 0x1a, 0x7e, 0x52, 0x79, 0x7f, 0xc8, 0xca, + 0xaa, 0x43, 0x5d, 0x2a, 0x4d, 0xac, 0xe3, 0x91, + 0x58, 0x50, 0x4b, 0xf2, 0x04, 0xfb, 0xe1, 0x9f, + 0x14, 0xdb, 0xb4, 0x27, 0xfa, 0xee, 0x50, 0xae, +}; + +static const uint8_t k_p384[] = { + 0x2e, 0x44, 0xef, 0x1f, 0x8c, 0x0b, 0xea, 0x83, + 0x94, 0xe3, 0xdd, 0xa8, 0x1e, 0xc6, 0xa7, 0x84, + 0x2a, 0x45, 0x9b, 0x53, 0x47, 0x01, 0x74, 0x9e, + 0x2e, 0xd9, 0x5f, 0x05, 0x4f, 0x01, 0x37, 0x68, + 0x08, 0x78, 0xe0, 0x74, 0x9f, 0xc4, 0x3f, 0x85, + 0xed, 0xca, 0xe0, 0x6c, 0xc2, 0xf4, 0x3f, 0xef, +}; + +static const uint8_t k_p521[] = { + 0x00, 0x00, 0xc9, 0x1e, 0x23, 0x49, 0xef, 0x6c, + 0xa2, 0x2d, 0x2d, 0xe3, 0x9d, 0xd5, 0x18, 0x19, + 0xb6, 0xaa, 0xd9, 0x22, 0xd3, 0xae, 0xcd, 0xea, + 0xb4, 0x52, 0xba, 0x17, 0x2f, 0x7d, 0x63, 0xe3, + 0x70, 0xce, 0xcd, 0x70, 0x57, 0x5f, 0x59, 0x7c, + 0x09, 0xa1, 0x74, 0xba, 0x76, 0xbe, 0xd0, 0x5a, + 0x48, 0xe5, 0x62, 0xbe, 0x06, 0x25, 0x33, 0x6d, + 0x16, 0xb8, 0x70, 0x31, 0x47, 0xa6, 0xa2, 0x31, + 0xd6, 0xbf, +}; + +static const uint8_t h_p256[] = { + 0xa4, 0x1a, 0x41, 0xa1, 0x2a, 0x79, 0x95, 0x48, + 0x21, 0x1c, 0x41, 0x0c, 0x65, 0xd8, 0x13, 0x3a, + 0xfd, 0xe3, 0x4d, 0x28, 0xbd, 0xd5, 0x42, 0xe4, + 0xb6, 0x80, 0xcf, 0x28, 0x99, 0xc8, 0xa8, 0xc4, +}; + +static const uint8_t h_p384[] = { + 0x5a, 0xea, 0x18, 0x7d, 0x1c, 0x4f, 0x6e, 0x1b, + 0x35, 0x05, 0x7d, 0x20, 0x12, 0x6d, 0x83, 0x6c, + 0x6a, 0xdb, 0xbc, 0x70, 0x49, 0xee, 0x02, 0x99, + 0xc9, 0x52, 0x9f, 0x5e, 0x0b, 0x3f, 0x8b, 0x5a, + 0x74, 0x11, 0x14, 0x9d, 0x6c, 0x30, 0xd6, 0xcb, + 0x2b, 0x8a, 0xf7, 0x0e, 0x0a, 0x78, 0x1e, 0x89, +}; + +static const uint8_t h_p521[] = { + 0x00, 0x00, 0xef, 0x88, 0xfb, 0x5a, 0xc0, 0x1f, + 0x35, 0xf5, 0xcb, 0x8a, 0x1b, 0x00, 0x8e, 0x80, + 0x11, 0x46, 0xc1, 0x39, 0x83, 0xcf, 0x8c, 0x2c, + 0xcf, 0x1d, 0x88, 0xaf, 0xa8, 0xe9, 0xfe, 0xde, + 0x12, 0x1c, 0x11, 0xfe, 0x82, 0x9d, 0x41, 0xb4, + 0x02, 0xb3, 0x2a, 0xdf, 0xde, 0x20, 0x67, 0x9c, + 0x3f, 0x4d, 0x91, 0x01, 0xa3, 0xc4, 0x07, 0x3a, + 0x2e, 0x49, 0x03, 0x9f, 0x5d, 0x38, 0x06, 0x1c, + 0xdb, 0xcc, +}; + +static TEE_Result versal_ecc_sign_kat(uint32_t curve) +{ + TEE_Result ret = TEE_SUCCESS; + size_t bytes = 0; + size_t bits = 0; + struct ecc_keypair key = { }; + struct ecc_keypair ephemeral = { }; + uint32_t algo = 0; + const uint8_t *d = NULL; + const uint8_t *k = NULL; + const uint8_t *sign_r = NULL; + const uint8_t *sign_s = NULL; + const uint8_t *hash = NULL; + uint8_t sig[(TEE_SHA512_HASH_SIZE + 2) * 2] = { }; + size_t sig_len = 0; + + switch (curve) { + case TEE_ECC_CURVE_NIST_P256: + algo = TEE_ALG_ECDSA_SHA256; + d = d_p256; + k = k_p256; + sign_r = sign_r_p256; + sign_s = sign_s_p256; + hash = h_p256; + break; + case TEE_ECC_CURVE_NIST_P384: + algo = TEE_ALG_ECDSA_SHA384; + d = d_p384; + k = k_p384; + sign_r = sign_r_p384; + sign_s = sign_s_p384; + hash = h_p384; + break; + case TEE_ECC_CURVE_NIST_P521: + algo = TEE_ALG_ECDSA_SHA512; + d = d_p521; + k = k_p521; + sign_r = sign_r_p521; + sign_s = sign_s_p521; + hash = h_p521; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + ret = versal_ecc_get_key_size(curve, &bytes, &bits); + if (ret) + return ret; + + /* Prepare private key */ + ret = crypto_asym_alloc_ecc_keypair(&key, TEE_TYPE_ECDSA_KEYPAIR, bits); + if (ret) + return ret; + key.curve = curve; + + ret = crypto_bignum_bin2bn(d, bytes, key.d); + if (ret) + goto end; + + /* Prepare ephemeral key */ + ret = crypto_asym_alloc_ecc_keypair(&ephemeral, TEE_TYPE_ECDSA_KEYPAIR, + bits); + if (ret) + goto end; + + ret = crypto_bignum_bin2bn(k, bytes, ephemeral.d); + if (ret) + goto endk; + + /* Call PKI hW */ + ret = versal_ecc_sign_ephemeral(algo, bytes, &key, &ephemeral, hash, + bytes, sig, &sig_len); + if (ret == TEE_SUCCESS) { + /* Check generated signature */ + if ((memcmp((uint8_t *)sig, sign_r, bytes) != 0) || + (memcmp((uint8_t *)sig + bytes, sign_s, bytes) != 0)) + ret = TEE_ERROR_SIGNATURE_INVALID; + } + +endk: + crypto_bignum_free(&ephemeral.x); + crypto_bignum_free(&ephemeral.y); + crypto_bignum_free(&ephemeral.d); +end: + crypto_bignum_free(&key.x); + crypto_bignum_free(&key.y); + crypto_bignum_free(&key.d); + + return ret; +} + +static TEE_Result versal_ecc_verify_kat(uint32_t curve) +{ + TEE_Result ret = TEE_SUCCESS; + size_t bytes = 0; + size_t bits = 0; + struct ecc_public_key pkey = { }; + uint32_t algo = 0; + const uint8_t *qx = NULL; + const uint8_t *qy = NULL; + const uint8_t *sign_r = NULL; + const uint8_t *sign_s = NULL; + const uint8_t *hash = NULL; + uint8_t sig[(TEE_SHA512_HASH_SIZE + 2) * 2] = { }; + + switch (curve) { + case TEE_ECC_CURVE_NIST_P256: + algo = TEE_ALG_ECDSA_SHA256; + qx = pubkey_qx_p256; + qy = pubkey_qy_p256; + sign_r = sign_r_p256; + sign_s = sign_s_p256; + hash = h_p256; + break; + case TEE_ECC_CURVE_NIST_P384: + algo = TEE_ALG_ECDSA_SHA384; + qx = pubkey_qx_p384; + qy = pubkey_qy_p384; + sign_r = sign_r_p384; + sign_s = sign_s_p384; + hash = h_p384; + break; + case TEE_ECC_CURVE_NIST_P521: + algo = TEE_ALG_ECDSA_SHA512; + qx = pubkey_qx_p521; + qy = pubkey_qy_p521; + sign_r = sign_r_p521; + sign_s = sign_s_p521; + hash = h_p521; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + ret = versal_ecc_get_key_size(curve, &bytes, &bits); + if (ret) + return ret; + + /* Prepare public key */ + ret = crypto_asym_alloc_ecc_public_key(&pkey, TEE_TYPE_ECDSA_PUBLIC_KEY, + bits); + if (ret) + return ret; + pkey.curve = curve; + + ret = crypto_bignum_bin2bn(qx, bytes, pkey.x); + if (ret) + goto end; + ret = crypto_bignum_bin2bn(qy, bytes, pkey.y); + if (ret) + goto end; + + /* Prepare signature to verify */ + memcpy((uint8_t *)sig, sign_r, bytes); + memcpy((uint8_t *)sig + bytes, sign_s, bytes); + + /* Call PKI hW */ + ret = versal_ecc_verify(algo, &pkey, hash, bytes, sig, 2 * bytes); + +end: + crypto_bignum_free(&pkey.x); + crypto_bignum_free(&pkey.y); + return ret; +} + +TEE_Result versal_ecc_kat_test(void) +{ + TEE_Result ret = TEE_SUCCESS; + + ret = versal_ecc_sign_kat(TEE_ECC_CURVE_NIST_P256); + if (ret) + return ret; + + ret = versal_ecc_verify_kat(TEE_ECC_CURVE_NIST_P256); + if (ret) + return ret; + + ret = versal_ecc_sign_kat(TEE_ECC_CURVE_NIST_P384); + if (ret) + return ret; + + ret = versal_ecc_verify_kat(TEE_ECC_CURVE_NIST_P384); + if (ret) + return ret; + + ret = versal_ecc_sign_kat(TEE_ECC_CURVE_NIST_P521); + if (ret) + return ret; + + ret = versal_ecc_verify_kat(TEE_ECC_CURVE_NIST_P521); + if (ret) + return ret; + + return ret; +} + +#ifdef CFG_VERSAL_PKI_PWCT +TEE_Result versal_ecc_keypair_pwct(struct ecc_keypair *s) +{ + TEE_Result ret = TEE_SUCCESS; + struct ecc_public_key pkey = { }; + uint32_t algo = 0; + size_t bytes = 0; + size_t bits = 0; + size_t len = 0; + + uint8_t msg[TEE_SHA512_HASH_SIZE + 2] = { }; + uint8_t sig[(TEE_SHA512_HASH_SIZE + 2) * 2] = { }; + + switch (s->curve) { + case TEE_ECC_CURVE_NIST_P256: + algo = TEE_ALG_ECDSA_SHA256; + break; + case TEE_ECC_CURVE_NIST_P384: + algo = TEE_ALG_ECDSA_SHA384; + break; + case TEE_ECC_CURVE_NIST_P521: + algo = TEE_ALG_ECDSA_SHA512; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + ret = versal_ecc_get_key_size(s->curve, &bytes, &bits); + if (ret) + return ret; + + len = bytes * 2; + + ret = versal_ecc_sign(algo, s, msg, bytes, sig, &len); + if (ret) { + DMSG("Error signing message 0x%" PRIx32, ret); + return ret; + } + + ret = crypto_acipher_alloc_ecc_public_key(&pkey, + TEE_TYPE_ECDSA_PUBLIC_KEY, + bits); + if (ret) { + DMSG("Error allocating ECDSA public key 0x%" PRIx32, ret); + return ret; + } + + crypto_bignum_free(&pkey.x); + crypto_bignum_free(&pkey.y); + pkey.x = s->x; + pkey.y = s->y; + pkey.curve = s->curve; + + ret = versal_ecc_verify(algo, &pkey, msg, bytes, sig, bytes * 2); + if (ret) + DMSG("Error verifying signature 0x%" PRIx32, ret); + + return ret; +} +#endif diff --git a/core/drivers/crypto/versal/pki/sub.mk b/core/drivers/crypto/versal/pki/sub.mk new file mode 100644 index 00000000000..27083570893 --- /dev/null +++ b/core/drivers/crypto/versal/pki/sub.mk @@ -0,0 +1,4 @@ +incdirs-y += ../include + +srcs-y += ecc_pki_engine.c +srcs-y += ecc_pki_kat.c diff --git a/core/drivers/crypto/versal/rsa.c b/core/drivers/crypto/versal/rsa.c index bbfe979128d..232c0dec62c 100644 --- a/core/drivers/crypto/versal/rsa.c +++ b/core/drivers/crypto/versal/rsa.c @@ -72,15 +72,25 @@ static TEE_Result do_encrypt(struct drvcrypt_rsa_ed *rsa_data) assert(0); } - versal_mbox_alloc(RSA_MAX_MOD_LEN + RSA_MAX_PUB_EXP_LEN, NULL, &key); - crypto_bignum_bn2bin_pad(rsa_data->key.n_size, p->n, key.buf); - crypto_bignum_bn2bin_pad(RSA_MAX_PUB_EXP_LEN, - p->e, (uint8_t *)key.buf + RSA_MAX_MOD_LEN); + ret = versal_mbox_alloc(RSA_MAX_MOD_LEN + RSA_MAX_PUB_EXP_LEN, + NULL, &key); + if (ret) + return ret; - versal_mbox_alloc(rsa_data->message.length, rsa_data->message.data, - &msg); - versal_mbox_alloc(rsa_data->cipher.length, NULL, &cipher); - versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); + crypto_bignum_bn2bin_pad(rsa_data->key.n_size, p->n, key.buf); + crypto_bignum_bn2bin_pad(RSA_MAX_PUB_EXP_LEN, p->e, + (uint8_t *)key.buf + rsa_data->key.n_size); + + ret = versal_mbox_alloc(rsa_data->message.length, + rsa_data->message.data, &msg); + if (ret) + goto out; + ret = versal_mbox_alloc(rsa_data->cipher.length, NULL, &cipher); + if (ret) + goto out; + ret = versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); + if (ret) + goto out; cmd = cmd_buf.buf; cmd->key_len = rsa_data->key.n_size; @@ -107,10 +117,11 @@ static TEE_Result do_encrypt(struct drvcrypt_rsa_ed *rsa_data) memcpy(rsa_data->cipher.data, cipher.buf, rsa_data->key.n_size); } - free(cipher.buf); - free(cmd); - free(msg.buf); - free(key.buf); +out: + versal_mbox_free(&cmd_buf); + versal_mbox_free(&cipher); + versal_mbox_free(&msg); + versal_mbox_free(&key); return ret; } @@ -161,15 +172,25 @@ static TEE_Result do_decrypt(struct drvcrypt_rsa_ed *rsa_data) assert(0); } - versal_mbox_alloc(RSA_MAX_MOD_LEN + RSA_MAX_PRIV_EXP_LEN, NULL, &key); + ret = versal_mbox_alloc(RSA_MAX_MOD_LEN + RSA_MAX_PRIV_EXP_LEN, + NULL, &key); + if (ret) + return ret; + crypto_bignum_bn2bin_pad(rsa_data->key.n_size, p->n, key.buf); crypto_bignum_bn2bin_pad(rsa_data->key.n_size, p->d, - (uint8_t *)key.buf + RSA_MAX_MOD_LEN); - - versal_mbox_alloc(rsa_data->cipher.length, rsa_data->cipher.data, - &cipher); - versal_mbox_alloc(rsa_data->message.length, NULL, &msg); - versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); + (uint8_t *)key.buf + rsa_data->key.n_size); + + ret = versal_mbox_alloc(rsa_data->cipher.length, rsa_data->cipher.data, + &cipher); + if (ret) + goto out; + ret = versal_mbox_alloc(rsa_data->message.length, NULL, &msg); + if (ret) + goto out; + ret = versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); + if (ret) + goto out; cmd = cmd_buf.buf; cmd->key_len = rsa_data->key.n_size; @@ -192,10 +213,11 @@ static TEE_Result do_decrypt(struct drvcrypt_rsa_ed *rsa_data) memcpy(rsa_data->message.data, msg.buf, rsa_data->key.n_size); } - free(cipher.buf); - free(cmd); - free(key.buf); - free(msg.buf); +out: + versal_mbox_free(&cmd_buf); + versal_mbox_free(&msg); + versal_mbox_free(&cipher); + versal_mbox_free(&key); return ret; } @@ -333,10 +355,31 @@ static struct drvcrypt_rsa driver_rsa = { static TEE_Result rsa_init(void) { + uint32_t err = 0; struct versal_cmd_args arg = { }; - if (versal_crypto_request(VERSAL_RSA_KAT, &arg, NULL)) + arg.data[arg.dlen++] = VERSAL_RSA_PUB_ENC_KAT; + + if (versal_crypto_request(VERSAL_KAT, &arg, &err)) + return TEE_ERROR_GENERIC; + + if (err) { + DMSG("RSA_PUB_ENC_KAT returned 0x%" PRIx32, err); return TEE_ERROR_GENERIC; + } + + /* Clear previous request */ + arg.dlen = 0; + + arg.data[arg.dlen++] = VERSAL_RSA_PRIVATE_DEC_KAT; + + if (versal_crypto_request(VERSAL_KAT, &arg, &err)) + return TEE_ERROR_GENERIC; + + if (err) { + DMSG("RSA_PRIVATE_DEC_KAT returned 0x%" PRIx32, err); + return TEE_ERROR_GENERIC; + } return drvcrypt_register_rsa(&driver_rsa); } diff --git a/core/drivers/crypto/versal/sub.mk b/core/drivers/crypto/versal/sub.mk index 56184690001..b4cc1bbc165 100644 --- a/core/drivers/crypto/versal/sub.mk +++ b/core/drivers/crypto/versal/sub.mk @@ -3,4 +3,9 @@ incdirs-y += include srcs-y += ipi.c srcs-y += authenc.c srcs-y += ecc.c +ifeq ($(CFG_VERSAL_PKI_DRIVER),y) +subdirs-y += pki +else +srcs-y += ecc_mbox.c +endif srcs-y += rsa.c diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk index 8788e5f2d61..04255624bee 100644 --- a/core/drivers/sub.mk +++ b/core/drivers/sub.mk @@ -72,6 +72,7 @@ srcs-$(CFG_VERSAL_PM) += versal_pm.c srcs-$(CFG_STM32MP15_HUK) += stm32mp15_huk.c srcs-$(CFG_VERSAL_RNG_DRV) += versal_trng.c srcs-$(CFG_VERSAL_NVM) += versal_nvm.c +srcs-$(CFG_VERSAL_NET_NVM) += versal_net_nvm.c srcs-$(CFG_VERSAL_SHA3_384) += versal_sha3_384.c srcs-$(CFG_VERSAL_PUF) += versal_puf.c srcs-$(CFG_VERSAL_HUK) += versal_huk.c diff --git a/core/drivers/versal_gpio.c b/core/drivers/versal_gpio.c index 514ee405b4b..e4147c5f63a 100644 --- a/core/drivers/versal_gpio.c +++ b/core/drivers/versal_gpio.c @@ -56,7 +56,11 @@ static const struct versal_gpio_platform_data versal_gpio_pmc_def = { * 00 - 25, Bank 0 * 26 - 57, Bank 3 */ +#if defined(PLATFORM_FLAVOR_net) +#define VERSAL_GPIO_PS_BASE 0xf19d0000 +#else #define VERSAL_GPIO_PS_BASE 0xff0b0000 +#endif #define VERSAL_GPIO_PS_NR_GPIOS 58 #define VERSAL_GPIO_PS_MAX_BANK 4 diff --git a/core/drivers/versal_huk.c b/core/drivers/versal_huk.c index 1260c026cb1..1ccc7b1e0e3 100644 --- a/core/drivers/versal_huk.c +++ b/core/drivers/versal_huk.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include @@ -56,7 +56,7 @@ enum versal_aes_key_src { }; enum versal_crypto_api { - VERSAL_AES_INIT = 96U, + VERSAL_AES_INIT = 9U, VERSAL_AES_OP_INIT, VERSAL_AES_UPDATE_AAD, VERSAL_AES_ENCRYPT_UPDATE, @@ -68,8 +68,6 @@ enum versal_crypto_api { VERSAL_AES_LOCK_USER_KEY, VERSAL_AES_KEK_DECRYPT, VERSAL_AES_SET_DPA_CM, - VERSAL_AES_DECRYPT_KAT, - VERSAL_AES_DECRYPT_CM_KAT, }; struct versal_aes_input_param { @@ -110,6 +108,13 @@ struct versal_aes_init { 0xa1, 0x33, \ } +#ifdef CFG_VERSAL_DUMMY_DNA +static uint8_t dummy_dna[EFUSE_DNA_LEN] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, +}; +#endif + static bool versal_persistent_key(enum versal_aes_key_src src, bool *secure) { struct versal_efuse_puf_sec_ctrl_bits puf_ctrl = { }; @@ -186,7 +191,7 @@ static TEE_Result aes_gcm_encrypt(uint8_t *src, size_t src_len, return TEE_ERROR_BAD_PARAMETERS; cmd.data[0] = API_ID(VERSAL_AES_INIT); - if (versal_mbox_notify(&cmd, NULL, NULL)) { + if (versal_mbox_notify_pmc(&cmd, NULL, NULL)) { EMSG("AES_INIT error"); return TEE_ERROR_GENERIC; } @@ -195,18 +200,21 @@ static TEE_Result aes_gcm_encrypt(uint8_t *src, size_t src_len, for (i = 0; i < ARRAY_SIZE(key_data); i++) key_data[i] = TEE_U32_BSWAP(key_data[i]); - versal_mbox_alloc(key_len, key_data, &p); + ret = versal_mbox_alloc(key_len, key_data, &p); + if (ret) + return ret; + cmd.data[0] = API_ID(VERSAL_AES_WRITE_KEY); cmd.data[1] = VERSAL_AES_KEY_SIZE_256; cmd.data[2] = key_id; reg_pair_from_64(virt_to_phys(p.buf), &cmd.data[4], &cmd.data[3]); cmd.ibuf[0].mem = p; - if (versal_mbox_notify(&cmd, NULL, NULL)) { + if (versal_mbox_notify_pmc(&cmd, NULL, NULL)) { EMSG("AES_WRITE_KEY error"); ret = TEE_ERROR_GENERIC; } - free(p.buf); + versal_mbox_free(&p); memset(&cmd, 0, sizeof(cmd)); if (ret) return ret; @@ -215,8 +223,15 @@ static TEE_Result aes_gcm_encrypt(uint8_t *src, size_t src_len, /* Trace indication that it is safe to generate a RPMB key */ IMSG("Using %s HUK", secure ? "Production" : "Development"); - versal_mbox_alloc(sizeof(*init), NULL, &init_buf); - versal_mbox_alloc(nce_len, nce_data, &p); + ret = versal_mbox_alloc(sizeof(*init), NULL, &init_buf); + if (ret) + return ret; + ret = versal_mbox_alloc(nce_len, nce_data, &p); + if (ret) { + versal_mbox_free(&init_buf); + return ret; + } + init = init_buf.buf; init->operation = VERSAL_AES_GCM_ENCRYPT; init->key_len = VERSAL_AES_KEY_SIZE_256; @@ -226,17 +241,20 @@ static TEE_Result aes_gcm_encrypt(uint8_t *src, size_t src_len, reg_pair_from_64(virt_to_phys(init), &cmd.data[2], &cmd.data[1]); cmd.ibuf[0].mem = init_buf; cmd.ibuf[1].mem = p; - if (versal_mbox_notify(&cmd, NULL, NULL)) { + if (versal_mbox_notify_pmc(&cmd, NULL, NULL)) { EMSG("AES_OP_INIT error"); ret = TEE_ERROR_GENERIC; } - free(init); - free(p.buf); + versal_mbox_free(&init_buf); + versal_mbox_free(&p); memset(&cmd, 0, sizeof(cmd)); if (ret) return ret; - versal_mbox_alloc(aad_len, aad_data, &p); + ret = versal_mbox_alloc(aad_len, aad_data, &p); + if (ret) + return ret; + cmd.data[0] = API_ID(VERSAL_AES_UPDATE_AAD); reg_pair_from_64(virt_to_phys(p.buf), &cmd.data[2], &cmd.data[1]); if (p.len % 16) @@ -244,18 +262,30 @@ static TEE_Result aes_gcm_encrypt(uint8_t *src, size_t src_len, else cmd.data[3] = p.len; cmd.ibuf[0].mem = p; - if (versal_mbox_notify(&cmd, NULL, NULL)) { + if (versal_mbox_notify_pmc(&cmd, NULL, NULL)) { EMSG("AES_UPDATE_AAD error"); ret = TEE_ERROR_GENERIC; } - free(p.buf); + versal_mbox_free(&p); memset(&cmd, 0, sizeof(cmd)); if (ret) return ret; - versal_mbox_alloc(sizeof(*input), NULL, &input_cmd); - versal_mbox_alloc(src_len, src, &p); - versal_mbox_alloc(dst_len, NULL, &q); + ret = versal_mbox_alloc(sizeof(*input), NULL, &input_cmd); + if (ret) + return ret; + ret = versal_mbox_alloc(src_len, src, &p); + if (ret) { + versal_mbox_free(&input_cmd); + return ret; + } + ret = versal_mbox_alloc(dst_len, NULL, &q); + if (ret) { + versal_mbox_free(&input_cmd); + versal_mbox_free(&p); + return ret; + } + input = input_cmd.buf; input->input_addr = virt_to_phys(p.buf); input->input_len = p.len; @@ -266,26 +296,28 @@ static TEE_Result aes_gcm_encrypt(uint8_t *src, size_t src_len, cmd.ibuf[0].mem = input_cmd; cmd.ibuf[1].mem = p; cmd.ibuf[2].mem = q; - if (versal_mbox_notify(&cmd, NULL, NULL)) { + if (versal_mbox_notify_pmc(&cmd, NULL, NULL)) { EMSG("AES_UPDATE_PAYLOAD error"); ret = TEE_ERROR_GENERIC; } memcpy(dst, q.buf, dst_len); - free(input); - free(p.buf); - free(q.buf); + versal_mbox_free(&input_cmd); + versal_mbox_free(&p); + versal_mbox_free(&q); memset(&cmd, 0, sizeof(cmd)); if (ret) return ret; - versal_mbox_alloc(16, NULL, &p); + ret = versal_mbox_alloc(16, NULL, &p); + if (ret) + return ret; cmd.data[0] = API_ID(VERSAL_AES_ENCRYPT_FINAL); reg_pair_from_64(virt_to_phys(p.buf), &cmd.data[2], &cmd.data[1]); - if (versal_mbox_notify(&cmd, NULL, NULL)) { + if (versal_mbox_notify_pmc(&cmd, NULL, NULL)) { EMSG("AES_ENCRYPT_FINAL error"); ret = TEE_ERROR_GENERIC; } - free(p.buf); + versal_mbox_free(&p); memzero_explicit(&cmd, sizeof(cmd)); return ret; @@ -301,8 +333,12 @@ TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) if (huk.ready) goto out; +#ifdef CFG_VERSAL_DUMMY_DNA + memcpy(dna, dummy_dna, EFUSE_DNA_LEN); +#else if (versal_efuse_read_dna(dna, sizeof(dna))) return TEE_ERROR_GENERIC; +#endif if (versal_sha3_384((uint8_t *)dna, sizeof(dna), sha, sizeof(sha))) { ret = TEE_ERROR_GENERIC; @@ -314,8 +350,15 @@ TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) goto cleanup; } - if (tee_hash_createdigest(TEE_ALG_SHA256, enc_data, sizeof(enc_data), - huk.key, sizeof(huk.key))) { + /* + * Use RFC 5869 HKDF to derive a key from HUK-seed: + * HUK-seed = AES-GCM-encrypt(K, DNA) + * where K is either PUF KEK or eFuse User Keys 0 or 1 + * + * HKDF salt and info are set empty for now + */ + if (tee_cryp_hkdf(TEE_MAIN_ALGO_SHA256, enc_data, sizeof(enc_data), + NULL, 0, NULL, 0, huk.key, sizeof(huk.key))) { ret = TEE_ERROR_GENERIC; goto cleanup; } diff --git a/core/drivers/versal_mbox.c b/core/drivers/versal_mbox.c index 2f276276e6a..356509a2cfd 100644 --- a/core/drivers/versal_mbox.c +++ b/core/drivers/versal_mbox.c @@ -2,9 +2,13 @@ /* * Copyright (C) 2022 Foundries.io Ltd * Jorge Ramirez-Ortiz + * + * Copyright (C) 2023 ProvenRun S.A.S */ +#include #include +#include #include #include #include @@ -12,59 +16,127 @@ #include #include "drivers/versal_mbox.h" -#define PM_SIP_SVC 0xc2000000 - -/* IPI targets */ -#define IPI_ID_PMC 1 -#define IPI_ID_0 2 -#define IPI_ID_RPU0 3 -#define IPI_ID_RPU1 4 -#define IPI_ID_3 5 -#define IPI_ID_4 6 -#define IPI_ID_5 7 +#if defined(PLATFORM_FLAVOR_net) +#define IPI_REGS_BASEADDR 0xEB300000 +#define IPI_BUFFER_BASEADDR 0xEB3F0000 +#else +#define IPI_REGS_BASEADDR 0xFF300000 +#define IPI_BUFFER_BASEADDR 0xFF3F0000 +#endif + +#define IPI_SIZE 0x10000 + +#define IPI_TRIG_OFFSET 0x00 +#define IPI_OBR_OFFSET 0x04 +#define IPI_ISR_OFFSET 0x10 +#define IPI_IMR_OFFSET 0x14 +#define IPI_IER_OFFSET 0x18 +#define IPI_IDR_OFFSET 0x1C + +#define IPI_PMC_TRIG_BIT BIT(1) +#define IPI0_TRIG_BIT BIT(2) +#define IPI1_TRIG_BIT BIT(3) +#define IPI2_TRIG_BIT BIT(4) +#define IPI3_TRIG_BIT BIT(5) +#define IPI4_TRIG_BIT BIT(6) +#define IPI5_TRIG_BIT BIT(7) + +/* Interrupt Config Registers */ +#define IPI_PMC_REG_BASE (IPI_REGS_BASEADDR + 0x20000) +#define IPI0_REG_BASE (IPI_REGS_BASEADDR + 0x30000) +#define IPI1_REG_BASE (IPI_REGS_BASEADDR + 0x40000) +#define IPI2_REG_BASE (IPI_REGS_BASEADDR + 0x50000) +#define IPI3_REG_BASE (IPI_REGS_BASEADDR + 0x60000) +#define IPI4_REG_BASE (IPI_REGS_BASEADDR + 0x70000) +#define IPI5_REG_BASE (IPI_REGS_BASEADDR + 0x80000) /* Buffers */ -#define IPI_BUFFER_BASEADDR 0xFF3F0000 +#define IPI_BUFFER_PMC_BASE (IPI_BUFFER_BASEADDR + 0x200) #define IPI_BUFFER_APU_ID_0_BASE (IPI_BUFFER_BASEADDR + 0x400) +#define IPI_BUFFER_APU_ID_1_BASE (IPI_BUFFER_BASEADDR + 0x600) +#define IPI_BUFFER_APU_ID_2_BASE (IPI_BUFFER_BASEADDR + 0x800) #define IPI_BUFFER_APU_ID_3_BASE (IPI_BUFFER_BASEADDR + 0xA00) #define IPI_BUFFER_APU_ID_4_BASE (IPI_BUFFER_BASEADDR + 0xC00) #define IPI_BUFFER_APU_ID_5_BASE (IPI_BUFFER_BASEADDR + 0xE00) -#define IPI_BUFFER_PMC_BASE (IPI_BUFFER_BASEADDR + 0x200) -#define IPI_BUFFER_TARGET_APU_OFFSET 0x80 + #define IPI_BUFFER_TARGET_PMC_OFFSET 0x40 +#define IPI_BUFFER_TARGET_ID_0_OFFSET 0x80 +#define IPI_BUFFER_TARGET_ID_1_OFFSET 0xC0 +#define IPI_BUFFER_TARGET_ID_2_OFFSET 0x100 +#define IPI_BUFFER_TARGET_ID_3_OFFSET 0x140 +#define IPI_BUFFER_TARGET_ID_4_OFFSET 0x180 +#define IPI_BUFFER_TARGET_ID_5_OFFSET 0x1C0 + #define IPI_BUFFER_REQ_OFFSET 0x0 #define IPI_BUFFER_RESP_OFFSET 0x20 -#define IPI_BUFFER_LOCAL_OFFSET IPI_BUFFER_TARGET_APU_OFFSET -#define IPI_BUFFER_REMOTE_OFFSET IPI_BUFFER_TARGET_PMC_OFFSET - -#define IPI_BLOCK 1 -#define IPI_NON_BLOCK 0 - -/* Mailbox api */ -enum versal_ipi_api_id { - IPI_MAILBOX_OPEN = 0x1000, - IPI_MAILBOX_RELEASE, - IPI_MAILBOX_STATUS_ENQUIRY, - IPI_MAILBOX_NOTIFY, - IPI_MAILBOX_ACK, - IPI_MAILBOX_ENABLE_IRQ, - IPI_MAILBOX_DISABLE_IRQ +static const struct versal_ipi_config { + uint32_t ipi_bit_mask; + uint32_t ipi_reg_base; + uint32_t ipi_buf_base; + uint32_t ipi_remote_offset; +} versal_ipi_table[] = { + /* PMC IPI */ + [IPI_ID_PMC] = { + .ipi_bit_mask = IPI_PMC_TRIG_BIT, + .ipi_reg_base = IPI_PMC_REG_BASE, + .ipi_buf_base = IPI_BUFFER_PMC_BASE, + .ipi_remote_offset = IPI_BUFFER_TARGET_PMC_OFFSET, + }, + + /* IPI0 IPI */ + [IPI_ID_0] = { + .ipi_bit_mask = IPI0_TRIG_BIT, + .ipi_reg_base = IPI0_REG_BASE, + .ipi_buf_base = IPI_BUFFER_APU_ID_0_BASE, + .ipi_remote_offset = IPI_BUFFER_TARGET_ID_0_OFFSET, + }, + + /* IPI1 IPI */ + [IPI_ID_1] = { + .ipi_bit_mask = IPI1_TRIG_BIT, + .ipi_reg_base = IPI1_REG_BASE, + .ipi_buf_base = IPI_BUFFER_APU_ID_1_BASE, + .ipi_remote_offset = IPI_BUFFER_TARGET_ID_1_OFFSET, + }, + + /* IPI2 IPI */ + [IPI_ID_2] = { + .ipi_bit_mask = IPI2_TRIG_BIT, + .ipi_reg_base = IPI2_REG_BASE, + .ipi_buf_base = IPI_BUFFER_APU_ID_2_BASE, + .ipi_remote_offset = IPI_BUFFER_TARGET_ID_2_OFFSET, + }, + + /* IPI3 IPI */ + [IPI_ID_3] = { + .ipi_bit_mask = IPI3_TRIG_BIT, + .ipi_reg_base = IPI3_REG_BASE, + .ipi_buf_base = IPI_BUFFER_APU_ID_3_BASE, + .ipi_remote_offset = IPI_BUFFER_TARGET_ID_3_OFFSET, + }, + + /* IPI4 IPI */ + [IPI_ID_4] = { + .ipi_bit_mask = IPI4_TRIG_BIT, + .ipi_reg_base = IPI4_REG_BASE, + .ipi_buf_base = IPI_BUFFER_APU_ID_4_BASE, + .ipi_remote_offset = IPI_BUFFER_TARGET_ID_4_OFFSET, + }, + + /* IPI5 IPI */ + [IPI_ID_5] = { + .ipi_bit_mask = IPI5_TRIG_BIT, + .ipi_reg_base = IPI5_REG_BASE, + .ipi_buf_base = IPI_BUFFER_APU_ID_5_BASE, + .ipi_remote_offset = IPI_BUFFER_TARGET_ID_5_OFFSET, + }, }; -static struct versal_ipi { - uint32_t lcl; - const uint32_t rmt; - paddr_t buf; - /* Exclusive access to the IPI shared buffer */ - struct mutex lock; - void *rsp; - void *req; -} ipi = { - .buf = IPI_BUFFER_APU_ID_3_BASE, - .rmt = IPI_ID_PMC, - .lcl = IPI_ID_3, -}; +#define IPI_REG_BASE(I) (versal_ipi_table[I].ipi_reg_base) +#define IPI_BIT_MASK(I) (versal_ipi_table[I].ipi_bit_mask) +#define IPI_BUF_BASE(I) (versal_ipi_table[I].ipi_buf_base) +#define IPI_REMOTE_OFFSET(I) (versal_ipi_table[I].ipi_remote_offset) static const char *const nvm_id[] = { [0] = "API_FEATURES", @@ -73,6 +145,38 @@ static const char *const nvm_id[] = { [3] = "BBRAM_WRITE_USER_DATA", [4] = "BBRAM_READ_USER_DATA", [5] = "BBRAM_LOCK_WRITE_USER_DATA", +#ifdef PLATFORM_FLAVOR_net + [6] = "BBRAM_WRITE_AES_KEY_FROM_PLOAD", + [7] = "EFUSE_WRITE_AES_KEY", + [8] = "EFUSE_WRITE_AES_KEY_FROM_PLOAD", + [9] = "EFUSE_WRITE_PPK_HASH", + [10] = "EFUSE_WRITE_PPK_HASH_FROM_PLOAD", + [11] = "EFUSE_WRITE_IV", + [12] = "EFUSE_WRITE_IV_FROM_PLOAD", + [13] = "EFUSE_WRITE_GLITCH_CONFIG", + [14] = "EFUSE_WRITE_DEC_ONLY", + [15] = "EFUSE_WRITE_REVOCATION_ID", + [16] = "EFUSE_WRITE_OFFCHIP_REVOKE_ID", + [17] = "EFUSE_WRITE_MISC_CTRL_BITS", + [18] = "EFUSE_WRITE_SEC_CTRL_BITS", + [19] = "EFUSE_WRITE_MISC1_CTRL_BITS", + [20] = "EFUSE_WRITE_BOOT_ENV_CTRL_BITS", + [21] = "EFUSE_WRITE_FIPS_INFO", + [22] = "EFUSE_WRITE_UDS_FROM_PLOAD", + [23] = "EFUSE_WRITE_DME_KEY_FROM_PLOAD", + [24] = "EFUSE_WRITE_DME_REVOKE", + [25] = "EFUSE_WRITE_PLM_UPDATE", + [26] = "EFUSE_WRITE_BOOT_MODE_DISABLE", + [27] = "EFUSE_WRITE_CRC", + [28] = "EFUSE_WRITE_DME_MODE", + [29] = "EFUSE_WRITE_PUF_HD_FROM_PLOAD", + [30] = "EFUSE_WRITE_PUF", + [31] = "EFUSE_WRITE_ROM_RSVD", + [32] = "EFUSE_WRITE_PUF_CTRL_BITS", + [33] = "EFUSE_READ_CACHE", + [34] = "EFUSE_RELOAD_N_PRGM_PROT_BITS", + [35] = "EFUSE_INVALID", +#else [6] = "EFUSE_WRITE", [7] = "EFUSE_WRITE_PUF", [8] = "EFUSE_PUF_USER_FUSE_WRITE", @@ -91,6 +195,7 @@ static const char *const nvm_id[] = { [21] = "EFUSE_READ_PUF_USER_FUSES", [22] = "EFUSE_READ_PUF", [23] = "EFUSE_INVALID", +#endif }; static const char *const crypto_id[] = { @@ -98,29 +203,27 @@ static const char *const crypto_id[] = { [1] = "RSA_SIGN_VERIFY", [2] = "RSA_PUBLIC_ENCRYPT", [3] = "RSA_PRIVATE_DECRYPT", - [4] = "RSA_KAT", - [32] = "SHA3_UPDATE", - [33] = "SHA3_KAT", - [64] = "ELLIPTIC_GENERATE_PUBLIC_KEY", - [65] = "ELLIPTIC_GENERATE_SIGN", - [66] = "ELLIPTIC_VALIDATE_PUBLIC_KEY", - [67] = "ELLIPTIC_VERIFY_SIGN", - [68] = "ELLIPTIC_KAT", - [96] = "AES_INIT", - [97] = "AES_OP_INIT", - [98] = "AES_UPDATE_AAD", - [99] = "AES_ENCRYPT_UPDATE", - [100] = "AES_ENCRYPT_FINAL", - [101] = "AES_DECRYPT_UPDATE", - [102] = "AES_DECRYPT_FINAL", - [103] = "AES_KEY_ZERO", - [104] = "AES_WRITE_KEY", - [105] = "AES_LOCK_USER_KEY", - [106] = "AES_KEK_DECRYPT", - [107] = "AES_SET_DPA_CM", - [108] = "AES_DECRYPT_KAT", - [109] = "AES_DECRYPT_CM_KAT", - [110] = "MAX", + [4] = "SHA3_UPDATE", + [5] = "ELLIPTIC_GENERATE_PUBLIC_KEY", + [6] = "ELLIPTIC_GENERATE_SIGN", + [7] = "ELLIPTIC_VALIDATE_PUBLIC_KEY", + [8] = "ELLIPTIC_VERIFY_SIGN", + [9] = "AES_INIT", + [10] = "AES_OP_INIT", + [11] = "AES_UPDATE_AAD", + [12] = "AES_ENCRYPT_UPDATE", + [13] = "AES_ENCRYPT_FINAL", + [14] = "AES_DECRYPT_UPDATE", + [15] = "AES_DECRYPT_FINAL", + [16] = "AES_KEY_ZERO", + [17] = "AES_WRITE_KEY", + [18] = "AES_LOCK_USER_KEY", + [19] = "AES_KEK_DECRYPT", + [20] = "AES_SET_DPA_CM", + [21] = "KAT", + [22] = "TRNG_GENERATE", + [23] = "AES_PERFORM_OPERATION", + [24] = "MAX", }; static const char *const puf_id[] = { @@ -176,31 +279,14 @@ static void versal_mbox_call_trace(uint32_t call) val ? val : "Invalid"); }; -static TEE_Result mbox_call(enum versal_ipi_api_id id, uint32_t blocking_call) -{ - struct thread_smc_args args = { - .a0 = PM_SIP_SVC | id, - .a1 = reg_pair_to_64(0, ipi.lcl), - .a2 = reg_pair_to_64(0, ipi.rmt), - .a3 = reg_pair_to_64(0, blocking_call), - }; - - thread_smccc(&args); - - /* Give the PLM time to access the console */ - if (IS_ENABLED(CFG_VERSAL_TRACE_PLM)) - mdelay(500); - - if (args.a0) - return TEE_ERROR_GENERIC; - - return TEE_SUCCESS; -} - -static TEE_Result versal_mbox_write_req(struct versal_ipi_cmd *cmd) +static TEE_Result versal_mbox_write_req(struct versal_ipi *ipi, + struct versal_ipi_cmd *cmd) { size_t i = 0; + assert(ipi); + assert(cmd); + for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) { if (!cmd->ibuf[i].mem.buf) continue; @@ -222,30 +308,34 @@ static TEE_Result versal_mbox_write_req(struct versal_ipi_cmd *cmd) cmd->ibuf[i].mem.alloc_len); } - memcpy(ipi.req, cmd->data, sizeof(cmd->data)); + memcpy(ipi->req, cmd->data, sizeof(cmd->data)); /* Cache operation on the IPI buffer is safe */ - cache_operation(TEE_CACHEFLUSH, ipi.req, sizeof(cmd->data)); + cache_operation(TEE_CACHEFLUSH, ipi->req, sizeof(cmd->data)); return TEE_SUCCESS; } -static TEE_Result versal_mbox_read_rsp(struct versal_ipi_cmd *cmd, +static TEE_Result versal_mbox_read_rsp(struct versal_ipi *ipi, + struct versal_ipi_cmd *cmd, struct versal_ipi_cmd *rsp, uint32_t *status) { size_t i = 0; + assert(ipi); + assert(cmd); + /* Cache operation on the IPI buffer is safe */ - cache_operation(TEE_CACHEINVALIDATE, ipi.rsp, sizeof(rsp->data)); + cache_operation(TEE_CACHEINVALIDATE, ipi->rsp, sizeof(rsp->data)); - *status = *(uint32_t *)ipi.rsp; + *status = *(uint32_t *)ipi->rsp; if (*status) return TEE_ERROR_GENERIC; if (rsp) - memcpy(rsp->data, ipi.rsp, sizeof(rsp->data)); + memcpy(rsp->data, ipi->rsp, sizeof(rsp->data)); for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) { if (!cmd->ibuf[i].mem.buf) @@ -272,12 +362,57 @@ static TEE_Result versal_mbox_read_rsp(struct versal_ipi_cmd *cmd, return TEE_SUCCESS; } +TEE_Result versal_mbox_open(uint32_t local, uint32_t remote, + struct versal_ipi *ipi) +{ + assert(ipi); + + ipi->regs = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, + IPI_REG_BASE(local), + IPI_SIZE); + + ipi->req = core_mmu_add_mapping(MEM_AREA_IO_SEC, + IPI_BUF_BASE(local) + + IPI_REMOTE_OFFSET(remote) + + IPI_BUFFER_REQ_OFFSET, + sizeof(struct versal_ipi_cmd)); + + ipi->rsp = core_mmu_add_mapping(MEM_AREA_IO_SEC, + IPI_BUF_BASE(local) + + IPI_REMOTE_OFFSET(remote) + + IPI_BUFFER_RESP_OFFSET, + sizeof(struct versal_ipi_cmd)); + + ipi->lcl = local; + ipi->rmt = remote; + + if (!ipi->regs || !ipi->req || !ipi->rsp) + panic(); + + mutex_init(&ipi->lock); + + io_write32(ipi->regs + IPI_IDR_OFFSET, IPI_BIT_MASK(remote)); + io_write32(ipi->regs + IPI_ISR_OFFSET, IPI_BIT_MASK(remote)); + + return TEE_SUCCESS; +} + +TEE_Result versal_mbox_close(struct versal_ipi *ipi) +{ + assert(ipi); + + io_write32(ipi->regs + IPI_IDR_OFFSET, + IPI_BIT_MASK(ipi->rmt)); + + return TEE_SUCCESS; +} + TEE_Result versal_mbox_alloc(size_t len, const void *init, struct versal_mbox_mem *mem) { mem->buf = memalign(CACHELINE_LEN, ROUNDUP(len, CACHELINE_LEN)); if (!mem->buf) - panic(); + return TEE_ERROR_OUT_OF_MEMORY; memset(mem->buf, 0, ROUNDUP(len, CACHELINE_LEN)); @@ -290,89 +425,113 @@ TEE_Result versal_mbox_alloc(size_t len, const void *init, return TEE_SUCCESS; } -TEE_Result versal_mbox_notify(struct versal_ipi_cmd *cmd, +TEE_Result versal_mbox_free(struct versal_mbox_mem *mem) +{ + if (!mem) + return TEE_ERROR_BAD_PARAMETERS; + + free(mem->buf); + mem->buf = NULL; + + return TEE_SUCCESS; +} + +TEE_Result versal_mbox_notify(struct versal_ipi *ipi, + struct versal_ipi_cmd *cmd, struct versal_ipi_cmd *rsp, uint32_t *err) { TEE_Result ret = TEE_SUCCESS; - uint32_t remote_status = 0; + uint32_t status = 0; - mutex_lock(&ipi.lock); + mutex_lock(&ipi->lock); - ret = versal_mbox_write_req(cmd); + ret = versal_mbox_write_req(ipi, cmd); if (ret) { EMSG("Can't write the request command"); goto out; } - if (IS_ENABLED(CFG_VERSAL_TRACE_MBOX)) - versal_mbox_call_trace(cmd->data[0]); + /* Trigger interrupt to remote */ + io_write32(ipi->regs + IPI_TRIG_OFFSET, IPI_BIT_MASK(ipi->rmt)); - ret = mbox_call(IPI_MAILBOX_NOTIFY, IPI_BLOCK); - if (ret) { - EMSG("IPI error"); + /* Wait for remote to acknowledge the interrupt */ + if (IO_READ32_POLL_TIMEOUT(ipi->regs + IPI_OBR_OFFSET, status, + status & IPI_BIT_MASK(ipi->rmt), 0, + CFG_VERSAL_MBOX_TIMEOUT)) { + ret = TEE_ERROR_GENERIC; goto out; } - ret = versal_mbox_read_rsp(cmd, rsp, &remote_status); + ret = versal_mbox_read_rsp(ipi, cmd, rsp, &status); if (ret) EMSG("Can't read the remote response"); - if (remote_status) { + if (status) { if (err) - *err = remote_status; + *err = status; + + ret = TEE_ERROR_GENERIC; + } +out: + mutex_unlock(&ipi->lock); + + return ret; +} + +static struct versal_ipi ipi_pmc; + +TEE_Result versal_mbox_notify_pmc(struct versal_ipi_cmd *cmd, + struct versal_ipi_cmd *rsp, uint32_t *err) +{ + TEE_Result ret = TEE_SUCCESS; + + if (IS_ENABLED(CFG_VERSAL_TRACE_MBOX)) + versal_mbox_call_trace(cmd->data[0]); + + ret = versal_mbox_notify(&ipi_pmc, cmd, rsp, err); + + if (ret != TEE_SUCCESS && err) { /* * Check the remote code (FSBL repository) in xplmi_status.h * and the relevant service error (ie, xsecure_error.h) for * detailed information. */ DMSG("PLM: plm status = 0x%" PRIx32 ", lib_status = 0x%" PRIx32, - (remote_status & 0xFFFF0000) >> 16, - (remote_status & 0x0000FFFF)); - - ret = TEE_ERROR_GENERIC; + (*err & 0xFFFF0000) >> 16, + (*err & 0x0000FFFF)); } -out: - mutex_unlock(&ipi.lock); return ret; } static TEE_Result versal_mbox_init(void) { + uint32_t lcl = 0; + switch (CFG_VERSAL_MBOX_IPI_ID) { case 0: - ipi.buf = IPI_BUFFER_APU_ID_0_BASE; - ipi.lcl = IPI_ID_0; + lcl = IPI_ID_0; + break; + case 1: + lcl = IPI_ID_1; + break; + case 2: + lcl = IPI_ID_2; break; case 3: + lcl = IPI_ID_3; break; case 4: - ipi.buf = IPI_BUFFER_APU_ID_4_BASE; - ipi.lcl = IPI_ID_4; + lcl = IPI_ID_4; break; case 5: - ipi.buf = IPI_BUFFER_APU_ID_5_BASE; - ipi.lcl = IPI_ID_5; + lcl = IPI_ID_5; break; default: EMSG("Invalid IPI requested"); return TEE_ERROR_GENERIC; } - ipi.req = core_mmu_add_mapping(MEM_AREA_RAM_SEC, - ipi.buf + IPI_BUFFER_REMOTE_OFFSET + - IPI_BUFFER_REQ_OFFSET, - sizeof(struct versal_ipi_cmd)); - - ipi.rsp = core_mmu_add_mapping(MEM_AREA_RAM_SEC, - ipi.buf + IPI_BUFFER_REMOTE_OFFSET + - IPI_BUFFER_RESP_OFFSET, - sizeof(struct versal_ipi_cmd)); - if (!ipi.req || !ipi.rsp) - panic(); - - mutex_init(&ipi.lock); - - return mbox_call(IPI_MAILBOX_OPEN, IPI_BLOCK); + return versal_mbox_open(lcl, IPI_ID_PMC, &ipi_pmc); } early_init(versal_mbox_init); diff --git a/core/drivers/versal_net_nvm.c b/core/drivers/versal_net_nvm.c new file mode 100644 index 00000000000..2b402cf7141 --- /dev/null +++ b/core/drivers/versal_net_nvm.c @@ -0,0 +1,1086 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2022 Foundries.io Ltd + * Jorge Ramirez-Ortiz + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NVM_WORD_LEN 4 + +/* Protocol API with the remote processor */ +#define NVM_MODULE_SHIFT 8 +#define NVM_MODULE 11 +#define NVM_API_ID(_id) (SHIFT_U32(NVM_MODULE, NVM_MODULE_SHIFT) | (_id)) + +#define __aligned_efuse __aligned(CACHELINE_LEN) + +/* Internal */ +struct versal_efuse_puf_fuse_addr { + uint64_t data_addr; + uint32_t start_row; + uint32_t num_rows; + uint8_t env_monitor_dis; + uint8_t prgm_puf_fuse; + uint8_t pad[46]; +}; + +/* + * Max size of the buffer needed for the remote processor to DMA efuse _data_ + * to/from + */ +#define EFUSE_MAX_LEN (EFUSE_MAX_USER_FUSES * sizeof(uint32_t)) + +enum versal_nvm_api_id { + API_FEATURES = 0, + BBRAM_WRITE_AES_KEY = 1, + BBRAM_ZEROIZE = 2, + BBRAM_WRITE_USER_DATA = 3, + BBRAM_READ_USER_DATA = 4, + BBRAM_LOCK_WRITE_USER_DATA = 5, + BBRAM_WRITE_AES_KEY_FROM_PLOAD = 6, + EFUSE_WRITE_AES_KEY = 7, + EFUSE_WRITE_AES_KEY_FROM_PLOAD = 8, + EFUSE_WRITE_PPK_HASH = 9, + EFUSE_WRITE_PPK_HASH_FROM_PLOAD = 10, + EFUSE_WRITE_IV = 11, + EFUSE_WRITE_IV_FROM_PLOAD = 12, + EFUSE_WRITE_GLITCH_CONFIG = 13, + EFUSE_WRITE_DEC_ONLY = 14, + EFUSE_WRITE_REVOCATION_ID = 15, + EFUSE_WRITE_OFFCHIP_REVOKE_ID = 16, + EFUSE_WRITE_MISC_CTRL_BITS = 17, + EFUSE_WRITE_SEC_CTRL_BITS = 18, + EFUSE_WRITE_MISC1_CTRL_BITS = 19, + EFUSE_WRITE_BOOT_ENV_CTRL_BITS = 20, + EFUSE_WRITE_FIPS_INFO = 21, + EFUSE_WRITE_UDS_FROM_PLOAD = 22, + EFUSE_WRITE_DME_KEY_FROM_PLOAD = 23, + EFUSE_WRITE_DME_REVOKE = 24, + EFUSE_WRITE_PLM_UPDATE = 25, + EFUSE_WRITE_BOOT_MODE_DISABLE = 26, + EFUSE_WRITE_CRC = 27, + EFUSE_WRITE_DME_MODE = 28, + EFUSE_WRITE_PUF_HD_FROM_PLOAD = 29, + EFUSE_WRITE_PUF = 30, + EFUSE_WRITE_ROM_RSVD = 31, + EFUSE_WRITE_PUF_CTRL_BITS = 32, + EFUSE_READ_CACHE = 33, + EFUSE_RELOAD_N_PRGM_PROT_BITS = 34, + EFUSE_INVALID = 35, +}; + +/* uint64_t are memory addresses */ +struct versal_efuse_data { + uint64_t env_mon_dis_flag; + uint64_t aes_key_addr; + uint64_t ppk_hash_addr; + uint64_t dec_only_addr; + uint64_t sec_ctrl_addr; + uint64_t misc_ctrl_addr; + uint64_t revoke_id_addr; + uint64_t iv_addr; + uint64_t user_fuse_addr; + uint64_t glitch_cfg_addr; + uint64_t boot_env_ctrl_addr; + uint64_t misc1_ctrl_addr; + uint64_t offchip_id_addr; + uint8_t pad[24]; +}; + +/* Helper read and write requests (not part of the protocol) */ +struct versal_nvm_buf { + size_t len; + void *buf; +}; + +struct versal_nvm_read_req { + enum versal_nvm_api_id efuse_id; + enum versal_nvm_ppk_type ppk_type; + enum versal_nvm_iv_type iv_type; + struct versal_nvm_buf ibuf[VERSAL_MAX_IPI_BUF]; +}; + +struct versal_bbram_data { + size_t aes_key_len; + uint32_t user_data; +}; + +struct versal_nvm_write_req { + struct versal_efuse_data data; + struct versal_bbram_data bbram; + struct versal_nvm_buf ibuf[VERSAL_MAX_IPI_BUF]; + enum versal_nvm_api_id efuse_id; +}; + +static TEE_Result +prepare_cmd(struct versal_ipi_cmd *cmd, enum versal_nvm_api_id efuse, + struct versal_nvm_buf *ibufs, uint32_t *arg) +{ + uint32_t a = 0; + uint32_t b = 0; + size_t i = 0; + + cmd->data[i++] = NVM_API_ID(efuse); + if (arg) + cmd->data[i++] = *arg; + + if (!ibufs[0].buf) + return TEE_SUCCESS; + + reg_pair_from_64(virt_to_phys(ibufs[0].buf), &b, &a); + + cmd->data[i++] = a; + cmd->data[i++] = b; + + for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) { + cmd->ibuf[i].mem.alloc_len = ibufs[i].len; + cmd->ibuf[i].mem.buf = ibufs[i].buf; + } + + return TEE_SUCCESS; +} + +static TEE_Result efuse_req(enum versal_nvm_api_id efuse, + struct versal_nvm_buf *ibufs, uint32_t *arg) +{ + struct versal_ipi_cmd cmd = { }; + TEE_Result ret = TEE_SUCCESS; + + ret = prepare_cmd(&cmd, efuse, ibufs, arg); + if (ret) + return ret; + + ret = versal_mbox_notify_pmc(&cmd, NULL, NULL); + if (ret) + EMSG("Mailbox error"); + + return ret; +} + +static TEE_Result versal_alloc_read_buffer(struct versal_nvm_read_req *req) +{ + assert(req); + req->ibuf[0].len = 1024; + req->ibuf[0].buf = alloc_cache_aligned(req->ibuf[0].len); + if (!req->ibuf[0].buf) + return TEE_ERROR_OUT_OF_MEMORY; + + return TEE_SUCCESS; +} + +static void versal_free_read_buffer(struct versal_nvm_read_req *req) +{ + assert(req); + free(req->ibuf[0].buf); + req->ibuf[0].buf = NULL; +} + +static void *versal_get_read_buffer(struct versal_nvm_read_req *req) +{ + assert(req); + return req->ibuf[0].buf; +} + +static TEE_Result versal_nvm_read(struct versal_nvm_read_req *req) +{ + if (!req) + return TEE_ERROR_GENERIC; + + switch (req->efuse_id) { + case EFUSE_READ_CACHE: + case BBRAM_READ_USER_DATA: + break; + default: + return TEE_ERROR_GENERIC; + } + + return efuse_req(req->efuse_id, req->ibuf, NULL); +} + +static TEE_Result versal_nvm_write(struct versal_nvm_write_req *req) +{ + uint32_t *arg = NULL; + uint32_t val = 0; + + switch (req->efuse_id) { + case BBRAM_WRITE_AES_KEY: + val = req->bbram.aes_key_len; + arg = &val; + break; + case BBRAM_WRITE_USER_DATA: + val = req->bbram.user_data; + arg = &val; + break; + case BBRAM_ZEROIZE: + break; + default: + return TEE_ERROR_GENERIC; + } + + return efuse_req(req->efuse_id, req->ibuf, arg); +} + +TEE_Result versal_bbram_write_aes_key(uint8_t *key, size_t len) +{ + struct versal_nvm_write_req req __aligned_efuse = { + .efuse_id = BBRAM_WRITE_AES_KEY, + .bbram.aes_key_len = len, + }; + void *buf = NULL; + + if (len != 32) + return TEE_ERROR_BAD_PARAMETERS; + + buf = alloc_cache_aligned(1024); + if (!buf) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(buf, key, len); + + req.ibuf[0].buf = buf; + req.ibuf[0].len = 1024; + + if (versal_nvm_write(&req)) { + free(buf); + return TEE_ERROR_GENERIC; + } + free(buf); + + return TEE_SUCCESS; +} + +TEE_Result versal_bbram_zeroize(void) +{ + struct versal_nvm_write_req req __aligned_efuse = { + .efuse_id = BBRAM_ZEROIZE, + }; + + if (versal_nvm_write(&req)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +TEE_Result versal_bbram_write_user_data(uint32_t data) +{ + struct versal_nvm_write_req req __aligned_efuse = { + .efuse_id = BBRAM_WRITE_USER_DATA, + .bbram.user_data = data, + }; + + if (versal_nvm_write(&req)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +TEE_Result versal_bbram_read_user_data(uint32_t *data) +{ + struct versal_nvm_read_req req = { + .efuse_id = BBRAM_READ_USER_DATA, + }; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (versal_nvm_read(&req)) { + versal_free_read_buffer(&req); + return TEE_ERROR_GENERIC; + } + + memcpy(data, versal_get_read_buffer(&req), sizeof(*data)); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +TEE_Result versal_bbram_lock_write_user_data(void) +{ + struct versal_nvm_write_req req __aligned_efuse = { + .efuse_id = BBRAM_LOCK_WRITE_USER_DATA, + }; + + if (versal_nvm_write(&req)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result versal_efuse_read_cache(uint16_t off, uint16_t num, + uint32_t *buf, size_t len) +{ + struct versal_ipi_cmd cmd = { }; + struct versal_mbox_mem p = { }; + TEE_Result ret = TEE_SUCCESS; + uint32_t a = 0; + uint32_t b = 0; + + if (!buf) + return TEE_ERROR_BAD_PARAMETERS; + + if (len < num * NVM_WORD_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + ret = versal_mbox_alloc(num * NVM_WORD_LEN, NULL, &p); + if (ret) + return ret; + + reg_pair_from_64(virt_to_phys(p.buf), &b, &a); + + cmd.data[0] = NVM_API_ID(EFUSE_READ_CACHE); + cmd.data[1] = SHIFT_U32(num, 16) | off; + cmd.data[2] = a; + cmd.data[3] = b; + + cmd.ibuf[0].mem = p; + + ret = versal_mbox_notify_pmc(&cmd, NULL, NULL); + if (ret) + EMSG("Mailbox error"); + else + memcpy(buf, p.buf, num * NVM_WORD_LEN); + + versal_mbox_free(&p); + return ret; +} + +#define EFUSE_CACHE_DNA_OFFSET 0x20 +#define EFUSE_CACHE_BOOT_ENV_CTRL_OFFSET 0x94 +#define EFUSE_CACHE_MISC_CTRL_OFFSET 0xA0 +#define EFUSE_CACHE_PUF_ECC_CTRL_OFFSET 0xA4 +#define EFUSE_CACHE_PUF_CHASH_OFFSET 0xA8 +#define EFUSE_CACHE_SEC_CTRL_OFFSET 0xAC +#define EFUSE_CACHE_REVOCATION_ID0_OFFSET 0xB0 +#define EFUSE_CACHE_SEC_MISC0_OFFSET 0xE4 +#define EFUSE_CACHE_SEC_MISC1_OFFSET 0xE8 +#define EFUSE_CACHE_PPK0_OFFSET 0x100 +#define EFUSE_CACHE_PPK1_OFFSET 0x120 +#define EFUSE_CACHE_PPK2_OFFSET 0x140 +#define EFUSE_CACHE_OFFCHIP_REVOKE_ID0_OFFSET 0x160 +#define EFUSE_CACHE_METAHEADER_IV_RANGE0_OFFSET 0x180 +#define EFUSE_CACHE_BLACK_IV0_OFFSET 0x1D0 +#define EFUSE_CACHE_PLM_IV_RANGE0_OFFSET 0x1DC +#define EFUSE_CACHE_DATA_PARTITION_IV_RANGE0_OFFSET 0x1E8 +#define EFUSE_CACHE_USER0_OFFSET 0x240 +#define EFUSE_CACHE_PUF_SYN0_OFFSET 0x300 + +TEE_Result versal_efuse_read_dna(uint32_t *buf, size_t len) +{ + if (len < EFUSE_DNA_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + return versal_efuse_read_cache(EFUSE_CACHE_DNA_OFFSET, + EFUSE_DNA_LEN / NVM_WORD_LEN, buf, len); +} + +TEE_Result versal_efuse_read_user_data(uint32_t *buf, size_t len, + uint32_t first, size_t num) +{ + uint16_t offset = 0; + + if (first + num > EFUSE_MAX_USER_FUSES || len < num * NVM_WORD_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + offset = EFUSE_CACHE_USER0_OFFSET + first * NVM_WORD_LEN; + + return versal_efuse_read_cache(offset, num, buf, len); +} + +TEE_Result versal_efuse_read_iv(uint32_t *buf, size_t len, + enum versal_nvm_iv_type type) +{ + uint16_t offset = 0; + + switch (type) { + case EFUSE_META_HEADER_IV_RANGE: + offset = EFUSE_CACHE_METAHEADER_IV_RANGE0_OFFSET; + break; + case EFUSE_BLACK_IV: + offset = EFUSE_CACHE_BLACK_IV0_OFFSET; + break; + case EFUSE_PLM_IV_RANGE: + offset = EFUSE_CACHE_PLM_IV_RANGE0_OFFSET; + break; + case EFUSE_DATA_PARTITION_IV_RANGE: + offset = EFUSE_CACHE_DATA_PARTITION_IV_RANGE0_OFFSET; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return versal_efuse_read_cache(offset, EFUSE_IV_LEN / NVM_WORD_LEN, + buf, len); +} + +TEE_Result versal_efuse_read_ppk(uint32_t *buf, size_t len, + enum versal_nvm_ppk_type type) +{ + uint16_t offset = 0; + + switch (type) { + case EFUSE_PPK0: + offset = EFUSE_CACHE_PPK0_OFFSET; + break; + case EFUSE_PPK1: + offset = EFUSE_CACHE_PPK1_OFFSET; + break; + case EFUSE_PPK2: + offset = EFUSE_CACHE_PPK2_OFFSET; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return versal_efuse_read_cache(offset, EFUSE_PPK_LEN / NVM_WORD_LEN, + buf, len); +} + +TEE_Result versal_efuse_read_revoke_id(uint32_t *buf, size_t len, uint32_t id) +{ + uint32_t reg = EFUSE_CACHE_REVOCATION_ID0_OFFSET; + + if (id < VERSAL_NET_REVOKE_EFUSE_MIN || + id > VERSAL_NET_REVOKE_EFUSE_MAX) + return TEE_ERROR_BAD_PARAMETERS; + + reg += (id - 1) / 8; + + return versal_efuse_read_cache(reg, + EFUSE_REVOCATION_ID_LEN / NVM_WORD_LEN, + buf, len); +} + +TEE_Result versal_efuse_read_misc_ctrl(struct versal_efuse_misc_ctrl_bits *buf) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t misc_ctrl = 0; + + if (!buf) + return TEE_ERROR_BAD_PARAMETERS; + + ret = versal_efuse_read_cache(EFUSE_CACHE_MISC_CTRL_OFFSET, 1, + &misc_ctrl, sizeof(misc_ctrl)); + if (ret) + return ret; + + buf->glitch_det_halt_boot_en = (misc_ctrl & GENMASK_32(31, 30)) >> 30; + buf->glitch_det_rom_monitor_en = (misc_ctrl & BIT(29)) >> 29; + buf->halt_boot_error = (misc_ctrl & GENMASK_32(22, 21)) >> 21; + buf->halt_boot_env = (misc_ctrl & GENMASK_32(20, 19)) >> 19; + buf->crypto_kat_en = (misc_ctrl & BIT(15)) >> 15; + buf->lbist_en = (misc_ctrl & BIT(14)) >> 14; + buf->safety_mission_en = (misc_ctrl & BIT(8)) >> 8; + buf->ppk0_invalid = (misc_ctrl & GENMASK_32(7, 6)) >> 6; + buf->ppk1_invalid = (misc_ctrl & GENMASK_32(5, 4)) >> 4; + buf->ppk2_invalid = (misc_ctrl & GENMASK_32(3, 2)) >> 2; + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_sec_ctrl(struct versal_efuse_sec_ctrl_bits *buf) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t sec_ctrl = 0; + + if (!buf) + return TEE_ERROR_BAD_PARAMETERS; + + ret = versal_efuse_read_cache(EFUSE_CACHE_SEC_CTRL_OFFSET, 1, + &sec_ctrl, sizeof(sec_ctrl)); + if (ret) + return ret; + + buf->aes_dis = sec_ctrl & BIT(0); + buf->jtag_err_out_dis = (sec_ctrl & BIT(1)) >> 1; + buf->jtag_dis = (sec_ctrl & BIT(2)) >> 2; + buf->ppk0_wr_lk = (sec_ctrl & BIT(6)) >> 6; + buf->ppk1_wr_lk = (sec_ctrl & BIT(7)) >> 7; + buf->ppk2_wr_lk = (sec_ctrl & BIT(8)) >> 8; + buf->aes_crc_lk = (sec_ctrl & GENMASK_32(10, 9)) >> 9; + buf->aes_wr_lk = (sec_ctrl & BIT(11)) >> 11; + buf->user_key0_crc_lk = (sec_ctrl & BIT(12)) >> 12; + buf->user_key0_wr_lk = (sec_ctrl & BIT(13)) >> 13; + buf->user_key1_crc_lk = (sec_ctrl & BIT(14)) >> 14; + buf->user_key1_wr_lk = (sec_ctrl & BIT(15)) >> 15; + buf->sec_dbg_dis = (sec_ctrl & GENMASK_32(20, 19)) >> 19; + buf->sec_lock_dbg_dis = (sec_ctrl & GENMASK_32(22, 21)) >> 21; + buf->boot_env_wr_lk = (sec_ctrl & BIT(28)) >> 28; + buf->reg_init_dis = (sec_ctrl & GENMASK_32(31, 30)) >> 30; + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_sec_misc1(struct versal_efuse_sec_misc1_bits *buf) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t sec_misc1 = 0; + + if (!buf) + return TEE_ERROR_BAD_PARAMETERS; + + ret = versal_efuse_read_cache(EFUSE_CACHE_SEC_MISC1_OFFSET, 1, + &sec_misc1, sizeof(sec_misc1)); + if (ret) + return ret; + + buf->lpd_mbist_en = (sec_misc1 & GENMASK_32(12, 10)) >> 10; + buf->pmc_mbist_en = (sec_misc1 & GENMASK_32(9, 7)) >> 7; + buf->lpd_noc_sc_en = (sec_misc1 & GENMASK_32(6, 4)) >> 4; + buf->sysmon_volt_mon_en = (sec_misc1 & GENMASK_32(3, 2)) >> 2; + buf->sysmon_temp_mon_en = sec_misc1 & GENMASK_32(1, 0); + + return TEE_SUCCESS; +} + +TEE_Result +versal_efuse_read_boot_env_ctrl(struct versal_efuse_boot_env_ctrl_bits *buf) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t boot_env_ctrl = 0; + + if (!buf) + return TEE_ERROR_BAD_PARAMETERS; + + ret = versal_efuse_read_cache(EFUSE_CACHE_BOOT_ENV_CTRL_OFFSET, 1, + &boot_env_ctrl, sizeof(boot_env_ctrl)); + if (ret) + return ret; + + buf->sysmon_temp_en = (boot_env_ctrl & BIT(21)) >> 21; + buf->sysmon_volt_en = (boot_env_ctrl & BIT(20)) >> 20; + buf->sysmon_temp_hot = (boot_env_ctrl & GENMASK_32(18, 17)) >> 17; + buf->sysmon_volt_pmc = (boot_env_ctrl & GENMASK_32(13, 12)) >> 12; + buf->sysmon_volt_pslp = (boot_env_ctrl & GENMASK_32(11, 10)) >> 10; + buf->sysmon_volt_soc = (boot_env_ctrl & GENMASK_32(9, 8)) >> 8; + buf->sysmon_temp_cold = boot_env_ctrl & GENMASK_32(1, 0); + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_offchip_revoke_id(uint32_t *buf, size_t len, + uint32_t id) +{ + uint32_t reg = EFUSE_CACHE_OFFCHIP_REVOKE_ID0_OFFSET; + + if (id < VERSAL_NET_REVOKE_EFUSE_MIN || + id > VERSAL_NET_REVOKE_EFUSE_MAX) + return TEE_ERROR_BAD_PARAMETERS; + + reg += (id - 1) / 8; + + return versal_efuse_read_cache(reg, + EFUSE_REVOCATION_ID_LEN / NVM_WORD_LEN, + buf, len); +} + +TEE_Result versal_efuse_read_dec_only(uint32_t *buf, size_t len) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t sec_misc0 = 0; + + if (len < EFUSE_DEC_ONLY_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + ret = versal_efuse_read_cache(EFUSE_CACHE_SEC_MISC0_OFFSET, 1, + &sec_misc0, sizeof(sec_misc0)); + if (ret) + return ret; + + sec_misc0 &= GENMASK_32(15, 0); + + memcpy(buf, &sec_misc0, EFUSE_DEC_ONLY_LEN); + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_puf_sec_ctrl(struct versal_efuse_puf_sec_ctrl_bits + *buf) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t puf_ctrl = 0; + uint32_t sec_ctrl = 0; + + if (!buf) + return TEE_ERROR_BAD_PARAMETERS; + + ret = versal_efuse_read_cache(EFUSE_CACHE_PUF_ECC_CTRL_OFFSET, 1, + &puf_ctrl, sizeof(puf_ctrl)); + if (ret) + return ret; + + /* + * Some fuses have moved from PUF_ECC_CTRL to SECURITY_CTRL + */ + ret = versal_efuse_read_cache(EFUSE_CACHE_SEC_CTRL_OFFSET, 1, + &sec_ctrl, sizeof(sec_ctrl)); + if (ret) + return ret; + + buf->puf_regen_dis = (puf_ctrl & BIT(31)) >> 31; + buf->puf_hd_invalid = (puf_ctrl & BIT(30)) >> 30; + buf->puf_test2_dis = (puf_ctrl & BIT(29)) >> 29; + buf->puf_dis = (sec_ctrl & BIT(18)) >> 18; + buf->puf_syn_lk = (sec_ctrl & BIT(16)) >> 16; + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_puf(struct versal_efuse_puf_header *buf) +{ + TEE_Result ret = TEE_SUCCESS; + + if (!buf) + return TEE_ERROR_BAD_PARAMETERS; + + ret = versal_efuse_read_puf_sec_ctrl(&buf->sec_ctrl); + if (ret) + return ret; + + ret = versal_efuse_read_cache(EFUSE_CACHE_SEC_CTRL_OFFSET, 1, + &buf->aux, sizeof(uint32_t)); + if (ret) + return ret; + + buf->aux &= GENMASK_32(23, 0); + + ret = versal_efuse_read_cache(EFUSE_CACHE_PUF_CHASH_OFFSET, 1, + &buf->chash, sizeof(uint32_t)); + if (ret) + return ret; + + return versal_efuse_read_cache(EFUSE_CACHE_PUF_SYN0_OFFSET, + PUF_SYN_DATA_WORDS, buf->efuse_syn_data, + PUF_SYN_DATA_WORDS * NVM_WORD_LEN); +} + +TEE_Result +versal_efuse_read_puf_as_user_fuse(struct versal_efuse_puf_user_fuse + *p __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result versal_efuse_write_user_data(uint32_t *buf __unused, + size_t len __unused, + uint32_t first __unused, + size_t num __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +#define EFUSE_ENV_DIS_FLAG 0 + +#define EFUSE_AES_KEY_ID 0 +#define EFUSE_USER_KEY0_ID 1 +#define EFUSE_USER_KEY1_ID 2 + +static TEE_Result do_write_efuses_buffer(enum versal_nvm_api_id id, + uint16_t type, uint32_t *buf, + size_t len) +{ + struct versal_ipi_cmd cmd = { }; + struct versal_mbox_mem p = { }; + TEE_Result ret = TEE_SUCCESS; + uint32_t a = 0; + uint32_t b = 0; + + ret = versal_mbox_alloc(len, buf, &p); + if (ret) + return ret; + + reg_pair_from_64(virt_to_phys(p.buf), &b, &a); + + cmd.data[0] = NVM_API_ID(id); + cmd.data[1] = (type << 16) | EFUSE_ENV_DIS_FLAG; + cmd.data[2] = a; + cmd.data[3] = b; + + cmd.ibuf[0].mem = p; + + ret = versal_mbox_notify_pmc(&cmd, NULL, NULL); + + versal_mbox_free(&p); + return ret; +} + +static TEE_Result do_write_efuses_value(enum versal_nvm_api_id id, uint32_t val) +{ + struct versal_ipi_cmd cmd = { }; + + cmd.data[0] = NVM_API_ID(id); + cmd.data[1] = EFUSE_ENV_DIS_FLAG; + cmd.data[2] = val; + + return versal_mbox_notify_pmc(&cmd, NULL, NULL); +} + +static TEE_Result do_write_efuses(enum versal_nvm_api_id id) +{ + return do_write_efuses_value(id, 0); +} + +TEE_Result versal_efuse_write_aes_keys(struct versal_efuse_aes_keys *keys) +{ + TEE_Result res = TEE_SUCCESS; + TEE_Result res2 = TEE_SUCCESS; + + if (!keys) + return TEE_ERROR_BAD_PARAMETERS; + + if (keys->prgm_aes_key) { + res2 = do_write_efuses_buffer(EFUSE_WRITE_AES_KEY, + EFUSE_AES_KEY_ID, + keys->aes_key, EFUSE_AES_KEY_LEN); + if (res2) { + DMSG("Error programming AES key (0x%" PRIx32 ")", res2); + res = TEE_ERROR_GENERIC; + } + } + + if (keys->prgm_user_key0) { + res2 = do_write_efuses_buffer(EFUSE_WRITE_AES_KEY, + EFUSE_USER_KEY0_ID, + keys->user_key0, + EFUSE_AES_KEY_LEN); + if (res2) { + DMSG("Error programming User key 0 (0x%" PRIx32 ")", + res2); + res = TEE_ERROR_GENERIC; + } + } + + if (keys->prgm_user_key1) { + res2 = do_write_efuses_buffer(EFUSE_WRITE_AES_KEY, + EFUSE_USER_KEY1_ID, + keys->user_key1, + EFUSE_AES_KEY_LEN); + if (res2) { + DMSG("Error programming User key 1 (0x%" PRIx32 ")", + res2); + res = TEE_ERROR_GENERIC; + } + } + + return res; +} + +TEE_Result versal_efuse_write_ppk_hash(struct versal_efuse_ppk_hash *hash) +{ + TEE_Result res = TEE_SUCCESS; + TEE_Result res2 = TEE_SUCCESS; + + if (!hash) + return TEE_ERROR_BAD_PARAMETERS; + + if (hash->prgm_ppk0_hash) { + res2 = do_write_efuses_buffer(EFUSE_WRITE_PPK_HASH, EFUSE_PPK0, + hash->ppk0_hash, EFUSE_PPK_LEN); + if (res2) { + DMSG("Error programming PPK hash 0 (0x%" PRIx32 ")", + res2); + res = TEE_ERROR_GENERIC; + } + } + + if (hash->prgm_ppk1_hash) { + res2 = do_write_efuses_buffer(EFUSE_WRITE_PPK_HASH, EFUSE_PPK1, + hash->ppk1_hash, EFUSE_PPK_LEN); + if (res2) { + DMSG("Error programming PPK hash 1 (0x%" PRIx32 ")", + res2); + res = TEE_ERROR_GENERIC; + } + } + + if (hash->prgm_ppk2_hash) { + res2 = do_write_efuses_buffer(EFUSE_WRITE_PPK_HASH, EFUSE_PPK2, + hash->ppk2_hash, EFUSE_PPK_LEN); + if (res2) { + DMSG("Error programming PPK hash 2 (0x%" PRIx32 ")", + res2); + res = TEE_ERROR_GENERIC; + } + } + + return res; +} + +TEE_Result versal_efuse_write_iv(struct versal_efuse_ivs *p) +{ + TEE_Result res = TEE_SUCCESS; + TEE_Result res2 = TEE_SUCCESS; + + if (!p) + return TEE_ERROR_BAD_PARAMETERS; + + if (p->prgm_meta_header_iv) { + res2 = do_write_efuses_buffer(EFUSE_WRITE_IV, + EFUSE_META_HEADER_IV_RANGE, + p->meta_header_iv, EFUSE_IV_LEN); + if (res2) { + DMSG("Error programming meta header IV (0x%" PRIx32 ")", + res2); + res = TEE_ERROR_GENERIC; + } + } + + if (p->prgm_blk_obfus_iv) { + res2 = do_write_efuses_buffer(EFUSE_WRITE_IV, EFUSE_BLACK_IV, + p->blk_obfus_iv, EFUSE_IV_LEN); + if (res2) { + DMSG("Error programming black IV (0x%" PRIx32 ")", + res2); + res = TEE_ERROR_GENERIC; + } + } + + if (p->prgm_plm_iv) { + res2 = do_write_efuses_buffer(EFUSE_WRITE_IV, + EFUSE_PLM_IV_RANGE, + p->plm_iv, EFUSE_IV_LEN); + if (res2) { + DMSG("Error programming plm IV (0x%" PRIx32 ")", res2); + res = TEE_ERROR_GENERIC; + } + } + + if (p->prgm_data_partition_iv) { + res2 = do_write_efuses_buffer(EFUSE_WRITE_IV, + EFUSE_DATA_PARTITION_IV_RANGE, + p->data_partition_iv, + EFUSE_IV_LEN); + if (res2) { + DMSG("Error programming data IV (0x%" PRIx32 ")", res2); + res = TEE_ERROR_GENERIC; + } + } + + return res; +} + +TEE_Result versal_efuse_write_dec_only(struct versal_efuse_dec_only *p) +{ + if (!p) + return TEE_ERROR_BAD_PARAMETERS; + + if (!p->prgm_dec_only) + return TEE_SUCCESS; + + return do_write_efuses(EFUSE_WRITE_DEC_ONLY); +} + +TEE_Result versal_efuse_write_sec(struct versal_efuse_sec_ctrl_bits *p) +{ + uint32_t val = 0; + + if (!p) + return TEE_ERROR_BAD_PARAMETERS; + + val = SHIFT_U32(p->reg_init_dis & 0x3, 30) | + SHIFT_U32(p->boot_env_wr_lk & 0x1, 28) | + SHIFT_U32(p->sec_lock_dbg_dis & 0x3, 21) | + SHIFT_U32(p->sec_dbg_dis & 0x3, 19) | + SHIFT_U32(p->user_key1_wr_lk & 0x1, 15) | + SHIFT_U32(p->user_key1_crc_lk & 0x1, 14) | + SHIFT_U32(p->user_key0_wr_lk & 0x1, 13) | + SHIFT_U32(p->user_key0_crc_lk & 0x1, 12) | + SHIFT_U32(p->aes_wr_lk & 0x1, 11) | + SHIFT_U32(p->aes_crc_lk & 0x3, 9) | + SHIFT_U32(p->ppk2_wr_lk & 0x1, 8) | + SHIFT_U32(p->ppk1_wr_lk & 0x1, 7) | + SHIFT_U32(p->ppk0_wr_lk & 0x1, 6) | + SHIFT_U32(p->jtag_dis & 0x1, 2) | + SHIFT_U32(p->jtag_err_out_dis & 0x1, 1) | + (p->aes_dis & 0x1); + + return do_write_efuses_value(EFUSE_WRITE_SEC_CTRL_BITS, val); +} + +TEE_Result versal_efuse_write_misc(struct versal_efuse_misc_ctrl_bits *p) +{ + uint32_t val = 0; + + if (!p) + return TEE_ERROR_BAD_PARAMETERS; + + val = SHIFT_U32(p->glitch_det_halt_boot_en & 0x3, 30) | + SHIFT_U32(p->glitch_det_rom_monitor_en & 0x1, 29) | + SHIFT_U32(p->halt_boot_error & 0x3, 21) | + SHIFT_U32(p->halt_boot_env & 0x3, 19) | + SHIFT_U32(p->crypto_kat_en & 0x1, 15) | + SHIFT_U32(p->lbist_en & 0x1, 14) | + SHIFT_U32(p->safety_mission_en & 0x1, 8) | + SHIFT_U32(p->ppk2_invalid & 0x3, 6) | + SHIFT_U32(p->ppk1_invalid & 0x3, 4) | + SHIFT_U32(p->ppk0_invalid & 0x3, 2); + + return do_write_efuses_value(EFUSE_WRITE_MISC_CTRL_BITS, val); +} + +TEE_Result +versal_efuse_write_glitch_cfg(struct versal_efuse_glitch_cfg_bits *p) +{ + uint32_t val = 0; + + if (!p) + return TEE_ERROR_BAD_PARAMETERS; + + if (!p->prgm_glitch) + return TEE_SUCCESS; + + val = SHIFT_U32(p->glitch_det_wr_lk & 0x1, 31) | p->glitch_det_trim; + + return do_write_efuses_value(EFUSE_WRITE_GLITCH_CONFIG, val); +} + +TEE_Result +versal_efuse_write_boot_env(struct versal_efuse_boot_env_ctrl_bits *p) +{ + uint32_t val = 0; + + if (!p) + return TEE_ERROR_BAD_PARAMETERS; + + val = SHIFT_U32(p->sysmon_temp_en & 0x1, 21) | + SHIFT_U32(p->sysmon_volt_en & 0x1, 20) | + SHIFT_U32(p->sysmon_temp_hot & 0x3, 17) | + SHIFT_U32(p->sysmon_volt_pmc & 0x3, 12) | + SHIFT_U32(p->sysmon_volt_pslp & 0x3, 10) | + SHIFT_U32(p->sysmon_volt_soc & 0x3, 8) | + (p->sysmon_temp_cold & 0x2); + + return do_write_efuses_value(EFUSE_WRITE_BOOT_ENV_CTRL_BITS, val); +} + +TEE_Result versal_efuse_write_sec_misc1(struct versal_efuse_sec_misc1_bits *p) +{ + uint32_t val = 0; + + if (!p) + return TEE_ERROR_BAD_PARAMETERS; + + val = SHIFT_U32(p->lpd_mbist_en & 0x7, 10) | + SHIFT_U32(p->pmc_mbist_en & 0x7, 7) | + SHIFT_U32(p->lpd_noc_sc_en & 0x7, 4) | + SHIFT_U32(p->sysmon_volt_mon_en & 0x3, 2) | + (p->sysmon_temp_mon_en & 0x3); + + return do_write_efuses_value(EFUSE_WRITE_MISC1_CTRL_BITS, val); +} + +/* + * versal_efuse_write_offchip_ids expects an efuse identifier between + * 1 and 256. + */ +TEE_Result versal_efuse_write_offchip_ids(uint32_t id) +{ + if (id < VERSAL_NET_REVOKE_EFUSE_MIN || + id > VERSAL_NET_REVOKE_EFUSE_MAX) + return TEE_ERROR_BAD_PARAMETERS; + + return do_write_efuses_value(EFUSE_WRITE_OFFCHIP_REVOKE_ID, id); +} + +TEE_Result versal_efuse_write_revoke_ppk(enum versal_nvm_ppk_type type) +{ + struct versal_efuse_misc_ctrl_bits misc_ctrl = {}; + + switch (type) { + case EFUSE_PPK0: + misc_ctrl.ppk0_invalid = 0x3; + break; + case EFUSE_PPK1: + misc_ctrl.ppk1_invalid = 0x3; + break; + case EFUSE_PPK2: + misc_ctrl.ppk2_invalid = 0x3; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return versal_efuse_write_misc(&misc_ctrl); +} + +/* + * versal_efuse_write_revoke_id expects an efuse identifier between + * 1 and 256. + */ +TEE_Result versal_efuse_write_revoke_id(uint32_t id) +{ + if (id < VERSAL_NET_REVOKE_EFUSE_MIN || + id > VERSAL_NET_REVOKE_EFUSE_MAX) + return TEE_ERROR_BAD_PARAMETERS; + + return do_write_efuses_value(EFUSE_WRITE_REVOCATION_ID, id); +} + +TEE_Result versal_efuse_write_puf_as_user_fuse(struct versal_efuse_puf_user_fuse + *p __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +#define EFUSE_WRITE_PUF_DATA_WORDS (PUF_SYN_DATA_WORDS + 6) + +struct versal_efuse_write_puf_data { + uint32_t sec_ctrl; + uint32_t prgm_puf_helper_data; + uint32_t env_monitor_dis; + uint32_t syn[PUF_SYN_DATA_WORDS]; + uint32_t chash; + uint32_t aux; + uint32_t ro_swap; +}; + +TEE_Result versal_efuse_write_puf(struct versal_efuse_puf_header *buf) +{ + struct versal_ipi_cmd cmd = { }; + struct versal_mbox_mem p = { }; + TEE_Result ret = TEE_SUCCESS; + uint32_t a = 0; + uint32_t b = 0; + struct versal_efuse_write_puf_data *data = NULL; + + if (!buf) + return TEE_ERROR_BAD_PARAMETERS; + + ret = versal_mbox_alloc(EFUSE_WRITE_PUF_DATA_WORDS * NVM_WORD_LEN, + NULL, &p); + if (ret) + return ret; + + data = p.buf; + + data->sec_ctrl = 0; + data->prgm_puf_helper_data = buf->prmg_puf_helper_data; + data->env_monitor_dis = buf->env_monitor_dis; + memcpy(data->syn, buf->efuse_syn_data, + PUF_SYN_DATA_WORDS * NVM_WORD_LEN); + data->chash = buf->chash; + data->aux = buf->aux; + data->ro_swap = 0; + + reg_pair_from_64(virt_to_phys(p.buf), &b, &a); + + cmd.data[0] = NVM_API_ID(EFUSE_WRITE_PUF); + cmd.data[2] = a; + cmd.data[3] = b; + + cmd.ibuf[0].mem = p; + + ret = versal_mbox_notify_pmc(&cmd, NULL, NULL); + + versal_mbox_free(&p); + return ret; +} diff --git a/core/drivers/versal_nvm.c b/core/drivers/versal_nvm.c index b17ae632d29..657dfa93494 100644 --- a/core/drivers/versal_nvm.c +++ b/core/drivers/versal_nvm.c @@ -151,7 +151,7 @@ static TEE_Result efuse_req(enum versal_nvm_api_id efuse, if (ret) return ret; - ret = versal_mbox_notify(&cmd, NULL, NULL); + ret = versal_mbox_notify_pmc(&cmd, NULL, NULL); if (ret) EMSG("Mailbox error"); diff --git a/core/drivers/versal_pm.c b/core/drivers/versal_pm.c index 84b1cbec5a3..c1215da658f 100644 --- a/core/drivers/versal_pm.c +++ b/core/drivers/versal_pm.c @@ -19,10 +19,17 @@ #include /* VERSAL_SIP_UID: 2ab9e4ec-93b9-11e7-a019dfe0dbad0ae0 */ +#if defined(PLATFORM_FLAVOR_net) +#define VERSAL_SIP_UID_0 U(0x5ac2d480) +#define VERSAL_SIP_UID_1 U(0xeb11afeb) +#define VERSAL_SIP_UID_2 U(0x4e0b6894) +#define VERSAL_SIP_UID_3 U(0x60c38f3b) +#else #define VERSAL_SIP_UID_0 U(0xece4b92a) #define VERSAL_SIP_UID_1 U(0xe711b993) #define VERSAL_SIP_UID_2 U(0xe0df19a0) #define VERSAL_SIP_UID_3 U(0xe00aaddb) +#endif #define VERSAL_SIP_MAJOR 0 #define VERSAL_SIP_MINOR 1 @@ -36,8 +43,8 @@ #define PM_MODULE_SHIFT 8 #define PM_MODULE 2 #define PM_API_ID(x) ((PM_MODULE << PM_MODULE_SHIFT) | (x)) -#define VERSAL_PM_MAJOR 0 -#define VERSAL_PM_MINOR 1 +#define VERSAL_PM_MAJOR 1 +#define VERSAL_PM_MINOR 0 /* PM API ids */ #define PM_GET_API_VERSION 1 @@ -140,7 +147,7 @@ TEE_Result versal_write_fpga(paddr_t pa) cmd.data[1] = PDI_SRC_DDR; reg_pair_from_64(pa, &cmd.data[2], &cmd.data[3]); - if (versal_mbox_notify(&cmd, NULL, NULL)) + if (versal_mbox_notify_pmc(&cmd, NULL, NULL)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; @@ -199,12 +206,12 @@ static TEE_Result versal_check_pm_abi(void) } cmd.data[0] = PM_API_ID(PM_GET_API_VERSION); - if (versal_mbox_notify(&cmd, &rsp, NULL)) + if (versal_mbox_notify_pmc(&cmd, &rsp, NULL)) return TEE_ERROR_GENERIC; - major = rsp.data[1] & 0xFFFF; - minor = rsp.data[1] >> 16; - if (major != VERSAL_PM_MAJOR || minor < VERSAL_PM_MINOR) { + minor = rsp.data[1] & 0xFFFF; + major = rsp.data[1] >> 16; + if (major != VERSAL_PM_MAJOR || minor != VERSAL_PM_MINOR) { EMSG("Invalid PM version: Major %d, Minor %d", major, minor); return TEE_ERROR_GENERIC; } diff --git a/core/drivers/versal_puf.c b/core/drivers/versal_puf.c index d65cbe1965d..3f4ccf8e57e 100644 --- a/core/drivers/versal_puf.c +++ b/core/drivers/versal_puf.c @@ -112,13 +112,23 @@ TEE_Result versal_puf_register(struct versal_puf_data *buf, TEE_Result ret = TEE_SUCCESS; uint32_t err = 0; - versal_mbox_alloc(sizeof(buf->puf_id), buf->puf_id, &puf_id_addr); - versal_mbox_alloc(sizeof(buf->chash), &buf->chash, &hash_addr); - versal_mbox_alloc(sizeof(buf->aux), &buf->aux, &aux_addr); - versal_mbox_alloc(sizeof(buf->efuse_syn_data), buf->efuse_syn_data, - &efuse_syn_data_addr); - versal_mbox_alloc(sizeof(buf->syndrome_data), buf->syndrome_data, - &syndrome_data_addr); + ret = versal_mbox_alloc(sizeof(buf->puf_id), buf->puf_id, &puf_id_addr); + if (ret) + return ret; + ret = versal_mbox_alloc(sizeof(buf->chash), &buf->chash, &hash_addr); + if (ret) + goto out; + ret = versal_mbox_alloc(sizeof(buf->aux), &buf->aux, &aux_addr); + if (ret) + goto out; + ret = versal_mbox_alloc(sizeof(buf->efuse_syn_data), + buf->efuse_syn_data, &efuse_syn_data_addr); + if (ret) + goto out; + ret = versal_mbox_alloc(sizeof(buf->syndrome_data), buf->syndrome_data, + &syndrome_data_addr); + if (ret) + goto out; arg.ibuf[0].mem = request; arg.ibuf[1].mem = syndrome_data_addr; @@ -143,7 +153,7 @@ TEE_Result versal_puf_register(struct versal_puf_data *buf, reg_pair_from_64(virt_to_phys(arg.ibuf[0].mem.buf), &arg.data[2], &arg.data[1]); - if (versal_mbox_notify(&arg, NULL, &err)) { + if (versal_mbox_notify_pmc(&arg, NULL, &err)) { EMSG("Versal, failed to register the PUF [%s]", versal_puf_error(err)); @@ -159,11 +169,12 @@ TEE_Result versal_puf_register(struct versal_puf_data *buf, memcpy(buf->syndrome_data, syndrome_data_addr.buf, sizeof(buf->syndrome_data)); - free(syndrome_data_addr.buf); - free(hash_addr.buf); - free(aux_addr.buf); - free(puf_id_addr.buf); - free(efuse_syn_data_addr.buf); +out: + versal_mbox_free(&syndrome_data_addr); + versal_mbox_free(&efuse_syn_data_addr); + versal_mbox_free(&aux_addr); + versal_mbox_free(&hash_addr); + versal_mbox_free(&puf_id_addr); return ret; } @@ -192,13 +203,23 @@ TEE_Result versal_puf_regenerate(struct versal_puf_data *buf, TEE_Result ret = TEE_SUCCESS; uint32_t err = 0; - versal_mbox_alloc(sizeof(buf->puf_id), buf->puf_id, &puf_id_addr); - versal_mbox_alloc(sizeof(buf->chash), &buf->chash, &hash_addr); - versal_mbox_alloc(sizeof(buf->aux), &buf->aux, &aux_addr); - versal_mbox_alloc(sizeof(buf->efuse_syn_data), buf->efuse_syn_data, - &efuse_syn_data_addr); - versal_mbox_alloc(sizeof(buf->syndrome_data), buf->syndrome_data, - &syndrome_data_addr); + ret = versal_mbox_alloc(sizeof(buf->puf_id), buf->puf_id, &puf_id_addr); + if (ret) + return ret; + ret = versal_mbox_alloc(sizeof(buf->chash), &buf->chash, &hash_addr); + if (ret) + goto out; + ret = versal_mbox_alloc(sizeof(buf->aux), &buf->aux, &aux_addr); + if (ret) + goto out; + ret = versal_mbox_alloc(sizeof(buf->efuse_syn_data), + buf->efuse_syn_data, &efuse_syn_data_addr); + if (ret) + goto out; + ret = versal_mbox_alloc(sizeof(buf->syndrome_data), buf->syndrome_data, + &syndrome_data_addr); + if (ret) + goto out; arg.ibuf[0].mem = request; arg.ibuf[1].mem = syndrome_data_addr; @@ -223,7 +244,7 @@ TEE_Result versal_puf_regenerate(struct versal_puf_data *buf, reg_pair_from_64(virt_to_phys(arg.ibuf[0].mem.buf), &arg.data[2], &arg.data[1]); - if (versal_mbox_notify(&arg, NULL, &err)) { + if (versal_mbox_notify_pmc(&arg, NULL, &err)) { EMSG("Versal, failed to regenerate the PUF [%s]", versal_puf_error(err)); @@ -233,11 +254,12 @@ TEE_Result versal_puf_regenerate(struct versal_puf_data *buf, /* Return the updated PUF_ID */ memcpy(buf->puf_id, puf_id_addr.buf, sizeof(buf->puf_id)); - free(syndrome_data_addr.buf); - free(hash_addr.buf); - free(aux_addr.buf); - free(puf_id_addr.buf); - free(efuse_syn_data_addr.buf); +out: + versal_mbox_free(&syndrome_data_addr); + versal_mbox_free(&efuse_syn_data_addr); + versal_mbox_free(&aux_addr); + versal_mbox_free(&hash_addr); + versal_mbox_free(&puf_id_addr); return ret; } @@ -253,7 +275,7 @@ TEE_Result versal_puf_clear_id(void) arg.data[0] = PUF_API_ID(VERSAL_PUF_CLEAR_ID); - if (versal_mbox_notify(&arg, NULL, NULL)) { + if (versal_mbox_notify_pmc(&arg, NULL, NULL)) { EMSG("Versal, failed to clear the PUF_ID"); return TEE_ERROR_GENERIC; @@ -270,7 +292,7 @@ TEE_Result versal_puf_check_api(enum versal_puf_api id) arg.data[0] = PUF_API_ID(VERSAL_PUF_API_FEATURES); arg.data[1] = id; - if (versal_mbox_notify(&arg, NULL, NULL)) + if (versal_mbox_notify_pmc(&arg, NULL, NULL)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; diff --git a/core/drivers/versal_sha3_384.c b/core/drivers/versal_sha3_384.c index 3a46db00114..10520890a7c 100644 --- a/core/drivers/versal_sha3_384.c +++ b/core/drivers/versal_sha3_384.c @@ -28,15 +28,20 @@ static TEE_Result input_plaintext(const uint8_t *src, size_t src_len) while (src_len && !ret) { len = MIN(src_len, SMALL_PAGE_SIZE); src_len -= len; - versal_mbox_alloc(len, src + i * SMALL_PAGE_SIZE, &p); + ret = versal_mbox_alloc(len, src + i * SMALL_PAGE_SIZE, &p); + if (ret) + return ret; arg.data[0] = first | VERSAL_SHA3_384_NEXT_PACKET | len; arg.ibuf[0].mem = p; ret = versal_crypto_request(VERSAL_SHA3_UPDATE, &arg, NULL); - if (ret) + if (ret) { EMSG("VERSAL_SHA3_UPDATE [%ld, len = %zu]", i, len); + versal_mbox_free(&p); + break; + } - free(p.buf); + versal_mbox_free(&p); first = 0; i++; } @@ -50,7 +55,9 @@ static TEE_Result get_ciphertext(uint8_t *dst, size_t dst_len) struct versal_mbox_mem p = { }; TEE_Result ret = TEE_SUCCESS; - versal_mbox_alloc(TEE_SHA384_HASH_SIZE, NULL, &p); + ret = versal_mbox_alloc(TEE_SHA384_HASH_SIZE, NULL, &p); + if (ret) + return ret; arg.ibuf[0].mem = p; ret = versal_crypto_request(VERSAL_SHA3_UPDATE, &arg, NULL); @@ -59,7 +66,7 @@ static TEE_Result get_ciphertext(uint8_t *dst, size_t dst_len) else EMSG("VERSAL_SHA3_UPDATE final"); - free(p.buf); + versal_mbox_free(&p); return ret; } @@ -88,13 +95,21 @@ TEE_Result versal_sha3_384(const uint8_t *src, size_t src_len, static TEE_Result versal_sha3_384_init(void) { + uint32_t err = 0; struct versal_cmd_args arg = { }; TEE_Result ret = TEE_SUCCESS; - ret = versal_crypto_request(VERSAL_SHA3_KAT, &arg, NULL); + arg.data[arg.dlen++] = VERSAL_SHA3_KAT; + + ret = versal_crypto_request(VERSAL_KAT, &arg, &err); if (!ret) engine_ready = true; + if (err) { + DMSG("SHA3 KAT returned 0x%" PRIx32, err); + return TEE_ERROR_GENERIC; + } + return ret; } diff --git a/core/drivers/versal_trng.c b/core/drivers/versal_trng.c index 792c46a25e3..6d9d18b9c19 100644 --- a/core/drivers/versal_trng.c +++ b/core/drivers/versal_trng.c @@ -58,15 +58,15 @@ #include #include #include +#include #include #include #include #include #include #include - -#define TRNG_BASE 0xF1230000 -#define TRNG_SIZE 0x10000 +#include +#include #define TRNG_STATUS 0x04 #define TRNG_STATUS_QCNT_SHIFT 9 @@ -134,87 +134,12 @@ #define PRNGMODE_GEN TRNG_CTRL_PRNGMODE_MASK #define RESET_DELAY 10 #define TRNG_SEC_STRENGTH_LEN 32 -#define TRNG_PERS_STR_REGS 12 -#define TRNG_PERS_STR_LEN 48 #define TRNG_SEED_REGS 12 -#define TRNG_SEED_LEN 48 #define TRNG_GEN_LEN 32 -#define RAND_BUF_LEN 4 #define BYTES_PER_BLOCK 16 #define ALL_A_PATTERN_32 0xAAAAAAAA #define ALL_5_PATTERN_32 0x55555555 -/* Derivative function helper macros */ -#define DF_SEED 0 -#define DF_RAND 1 -#define DF_IP_IV_LEN 4 -#define DF_PAD_DATA_LEN 8 -#define MAX_PRE_DF_LEN 160 -#define MAX_PRE_DF_LEN_WORDS 40 -#define DF_PERS_STR_LEN TRNG_PERS_STR_LEN -#define DF_PAD_VAL 0x80 -#define DF_KEY_LEN 32 -#define BLK_SIZE 16 -#define MAX_ROUNDS 14 - -enum trng_status { - TRNG_UNINITIALIZED = 0, - TRNG_HEALTHY, - TRNG_ERROR, - TRNG_CATASTROPHIC -}; - -enum trng_mode { - TRNG_HRNG = 0, - TRNG_DRNG, - TRNG_PTRNG -}; - -struct trng_cfg { - paddr_t base; - vaddr_t addr; - size_t len; -}; - -struct trng_usr_cfg { - enum trng_mode mode; - uint64_t seed_life; /* number of TRNG requests per seed */ - bool predict_en; /* enable prediction resistance */ - bool pstr_en; /* enable personalization string */ - uint32_t pstr[TRNG_PERS_STR_REGS]; - bool iseed_en; /* enable an initial seed */ - uint32_t init_seed[MAX_PRE_DF_LEN_WORDS]; - uint32_t df_disable; /* disable the derivative function */ - uint32_t dfmul; /* derivative function multiplier */ -}; - -struct trng_stats { - uint64_t bytes; - uint64_t bytes_reseed; - uint64_t elapsed_seed_life; -}; - -/* block cipher derivative function algorithm */ -struct trng_dfin { - uint32_t ivc[DF_IP_IV_LEN]; - uint32_t val1; - uint32_t val2; - uint8_t entropy[MAX_PRE_DF_LEN]; /* input entropy */ - uint8_t pstr[DF_PERS_STR_LEN]; /* personalization string */ - uint8_t pad_data[DF_PAD_DATA_LEN]; /* pad to multiples of 16 bytes*/ -}; - -struct versal_trng { - struct trng_cfg cfg; - struct trng_usr_cfg usr_cfg; - struct trng_stats stats; - enum trng_status status; - uint32_t buf[RAND_BUF_LEN]; /* buffer of random bits */ - size_t len; - struct trng_dfin dfin; - uint8_t dfout[TRNG_SEED_LEN]; /* output of the DF operation */ -}; - /* Derivative function variables */ static unsigned char sbx1[256]; static unsigned char sbx2[256]; @@ -1061,25 +986,21 @@ static TEE_Result trng_kat_test(struct versal_trng *trng) return TEE_ERROR_GENERIC; } -static struct versal_trng versal_trng = { - .cfg.base = TRNG_BASE, - .cfg.len = TRNG_SIZE, -}; - -TEE_Result hw_get_random_bytes(void *buf, size_t len) +TEE_Result versal_trng_get_random_bytes(struct versal_trng *trng, + void *buf, size_t len) { uint8_t random[TRNG_SEC_STRENGTH_LEN] = { 0 }; uint8_t *p = buf; size_t i = 0; for (i = 0; i < len / TRNG_SEC_STRENGTH_LEN; i++) { - if (trng_generate(&versal_trng, p + i * TRNG_SEC_STRENGTH_LEN, + if (trng_generate(trng, p + i * TRNG_SEC_STRENGTH_LEN, TRNG_SEC_STRENGTH_LEN, false)) panic(); } if (len % TRNG_SEC_STRENGTH_LEN) { - if (trng_generate(&versal_trng, random, TRNG_SEC_STRENGTH_LEN, + if (trng_generate(trng, random, TRNG_SEC_STRENGTH_LEN, false)) panic(); memcpy(p + i * TRNG_SEC_STRENGTH_LEN, random, @@ -1089,8 +1010,52 @@ TEE_Result hw_get_random_bytes(void *buf, size_t len) return TEE_SUCCESS; } -void plat_rng_init(void) +TEE_Result versal_trng_hw_init(struct versal_trng *trng, + struct trng_usr_cfg *usr_cfg) { + trng->cfg.addr = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, + trng->cfg.base, + trng->cfg.len); + if (!trng->cfg.addr) { + EMSG("Failed to map TRNG"); + panic(); + } + + if (trng_kat_test(trng)) { + EMSG("KAT Failed"); + panic(); + } + + if (trng_health_test(trng)) { + EMSG("RunHealthTest Failed"); + panic(); + } + + if (trng_instantiate(trng, usr_cfg)) { + EMSG("Driver instantiation Failed"); + panic(); + } + + if (trng_reseed(trng, NULL, usr_cfg->dfmul)) { + EMSG("Reseed Failed"); + panic(); + } + + return TEE_SUCCESS; +} + +#ifndef CFG_VERSAL_RNG_PLM +#define TRNG_BASE 0xF1230000 +#define TRNG_SIZE 0x10000 + +static struct versal_trng versal_trng = { + .cfg.base = TRNG_BASE, + .cfg.len = TRNG_SIZE, +}; + +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + return versal_trng_get_random_bytes(&versal_trng, buf, len); } static TEE_Result trng_hrng_mode_init(void) @@ -1103,6 +1068,7 @@ static TEE_Result trng_hrng_mode_init(void) 0xBC, 0x23, 0x18, 0x15, 0xCB, 0xB8, 0xA6, 0x3E, 0x83, 0xB8, 0x4A, 0xFE, 0x38, 0xFC, 0x25, 0x87, }; + /* configure in hybrid mode with derivative function enabled */ struct trng_usr_cfg usr_cfg = { .mode = TRNG_HRNG, @@ -1115,35 +1081,77 @@ static TEE_Result trng_hrng_mode_init(void) }; memcpy(usr_cfg.pstr, pers_str, TRNG_PERS_STR_LEN); - versal_trng.cfg.addr = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, - versal_trng.cfg.base, - versal_trng.cfg.len); - if (!versal_trng.cfg.addr) { - EMSG("Failed to map TRNG"); - panic(); - } - if (trng_kat_test(&versal_trng)) { - EMSG("KAT Failed"); - panic(); - } + return versal_trng_hw_init(&versal_trng, &usr_cfg); +} - if (trng_health_test(&versal_trng)) { - EMSG("RunHealthTest Failed"); - panic(); - } +driver_init(trng_hrng_mode_init); +#else +#define SEC_MODULE_SHIFT 8 +#define SEC_MODULE_ID 5 - if (trng_instantiate(&versal_trng, &usr_cfg)) { - EMSG("Driver instantiation Failed"); - panic(); - } +#define CRYPTO_API_ID(__x) ((SEC_MODULE_ID << SEC_MODULE_SHIFT) | (__x)) - if (trng_reseed(&versal_trng, NULL, usr_cfg.dfmul)) { - EMSG("Reseed Failed"); - panic(); +#define VERSAL_TRNG_GENERATE 22 + +#define VERSAL_TRNG_SEC_STRENGTH_IN_BYTES 32 + +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + uint32_t a = 0; + uint32_t b = 0; + struct versal_ipi_cmd cmd = { }; + struct versal_mbox_mem p = { }; + TEE_Result ret = TEE_SUCCESS; + uint32_t status = 0; + uint32_t offset = 0; + + ret = versal_mbox_alloc(len, NULL, &p); + if (ret) + return ret; + + cmd.data[0] = CRYPTO_API_ID(VERSAL_TRNG_GENERATE); + cmd.ibuf[0].mem = p; + + while (len > VERSAL_TRNG_SEC_STRENGTH_IN_BYTES) { + reg_pair_from_64(virt_to_phys(p.buf) + offset, &b, &a); + + cmd.data[1] = a; + cmd.data[2] = b; + cmd.data[3] = (uint32_t)VERSAL_TRNG_SEC_STRENGTH_IN_BYTES; + + ret = versal_mbox_notify_pmc(&cmd, NULL, &status); + if (!ret) { + memcpy((uint8_t *)buf + offset, + (uint8_t *)p.buf + offset, + VERSAL_TRNG_SEC_STRENGTH_IN_BYTES); + } else { + DMSG("Getting randomness returned 0x%" PRIx32, status); + goto out; + } + + offset += VERSAL_TRNG_SEC_STRENGTH_IN_BYTES; + len -= VERSAL_TRNG_SEC_STRENGTH_IN_BYTES; } - return TEE_SUCCESS; + reg_pair_from_64(virt_to_phys(p.buf) + offset, &b, &a); + + cmd.data[1] = a; + cmd.data[2] = b; + cmd.data[3] = (uint32_t)len; + + ret = versal_mbox_notify_pmc(&cmd, NULL, &status); + if (!ret) + memcpy((uint8_t *)buf + offset, (uint8_t *)p.buf + offset, len); + else + DMSG("Getting randomness returned 0x%" PRIx32, status); + +out: + versal_mbox_free(&p); + return ret; } +#endif -driver_init(trng_hrng_mode_init); +void plat_rng_init(void) +{ +} diff --git a/core/include/drivers/versal_mbox.h b/core/include/drivers/versal_mbox.h index 04e0c092f6b..1835f3f8ceb 100644 --- a/core/include/drivers/versal_mbox.h +++ b/core/include/drivers/versal_mbox.h @@ -5,6 +5,7 @@ #ifndef __DRIVERS_VERSAL_MBOX_H #define __DRIVERS_VERSAL_MBOX_H +#include #include #include #include @@ -27,8 +28,41 @@ struct versal_ipi_cmd { struct versal_ipi_buf ibuf[VERSAL_MAX_IPI_BUF]; }; -TEE_Result versal_mbox_notify(struct versal_ipi_cmd *cmd, +struct versal_ipi { + uint32_t lcl; + uint32_t rmt; + + /* Exclusive access to the IPI shared buffer */ + struct mutex lock; + + vaddr_t regs; + + void *rsp; + void *req; +}; + +/* IPI IDs */ +#define IPI_ID_PMC 1 +#define IPI_ID_0 2 +#define IPI_ID_1 3 +#define IPI_ID_2 4 +#define IPI_ID_3 5 +#define IPI_ID_4 6 +#define IPI_ID_5 7 + +TEE_Result versal_mbox_open(uint32_t local, uint32_t remote, + struct versal_ipi *ipi); +TEE_Result versal_mbox_close(struct versal_ipi *ipi); + +TEE_Result versal_mbox_notify(struct versal_ipi *ipi, + struct versal_ipi_cmd *cmd, struct versal_ipi_cmd *rsp, uint32_t *err); + +TEE_Result versal_mbox_notify_pmc(struct versal_ipi_cmd *cmd, + struct versal_ipi_cmd *rsp, uint32_t *err); + TEE_Result versal_mbox_alloc(size_t len, const void *init, struct versal_mbox_mem *mem); +TEE_Result versal_mbox_free(struct versal_mbox_mem *mem); + #endif /* __DRIVERS_VERSAL_MBOX_H */ diff --git a/core/include/drivers/versal_nvm.h b/core/include/drivers/versal_nvm.h index 948ebb27125..8ce9fb7254d 100644 --- a/core/include/drivers/versal_nvm.h +++ b/core/include/drivers/versal_nvm.h @@ -14,7 +14,12 @@ #define PUF_EFUSES_WORDS (128) #define PUF_SYN_DATA_WORDS (127) + +#if defined(PLATFORM_FLAVOR_net) +#define EFUSE_MAX_USER_FUSES (48) +#else #define EFUSE_MAX_USER_FUSES (64) +#endif #define EFUSE_OFFCHIP_REVOCATION_ID_LEN (4) #define EFUSE_REVOCATION_ID_LEN (4) @@ -22,6 +27,7 @@ #define EFUSE_DNA_LEN (16) #define EFUSE_PPK_LEN (32) #define EFUSE_IV_LEN (12) +#define EFUSE_AES_KEY_LEN (32) enum versal_nvm_iv_type { EFUSE_META_HEADER_IV_RANGE = 0, @@ -36,6 +42,14 @@ enum versal_nvm_ppk_type { EFUSE_PPK2 }; +/* + * The Versal Net PLM API expects efuse values between 1 and 256 rather than + * the enumeration values defined for the original Versal port. + */ +#if defined(PLATFORM_FLAVOR_net) +#define VERSAL_NET_REVOKE_EFUSE_MIN 1 +#define VERSAL_NET_REVOKE_EFUSE_MAX 256 +#else enum versal_nvm_revocation_id { EFUSE_REVOCATION_ID_0 = 0, EFUSE_REVOCATION_ID_1, @@ -58,6 +72,7 @@ enum versal_nvm_offchip_id { EFUSE_OFFCHIP_REVOKE_ID_6, EFUSE_OFFCHIP_REVOKE_ID_7 }; +#endif /* * All structures mapped to the PLM processor must be address_and_size aligned @@ -243,18 +258,25 @@ TEE_Result versal_efuse_write_glitch_cfg(struct versal_efuse_glitch_cfg_bits TEE_Result versal_efuse_write_boot_env(struct versal_efuse_boot_env_ctrl_bits *p); TEE_Result versal_efuse_write_sec_misc1(struct versal_efuse_sec_misc1_bits *p); +#if defined(PLATFORM_FLAVOR_net) +TEE_Result versal_efuse_write_offchip_ids(uint32_t id); +TEE_Result versal_efuse_read_offchip_revoke_id(uint32_t *buf, size_t len, + uint32_t id); +TEE_Result versal_efuse_read_revoke_id(uint32_t *buf, size_t len, uint32_t id); +#else TEE_Result versal_efuse_write_offchip_ids(struct versal_efuse_offchip_ids *p); -TEE_Result versal_efuse_write_revoke_ppk(enum versal_nvm_ppk_type type); -TEE_Result versal_efuse_write_revoke_id(uint32_t id); +TEE_Result versal_efuse_read_offchip_revoke_id(uint32_t *buf, size_t len, + enum versal_nvm_offchip_id id); TEE_Result versal_efuse_read_revoke_id(uint32_t *buf, size_t len, enum versal_nvm_revocation_id id); +#endif +TEE_Result versal_efuse_write_revoke_ppk(enum versal_nvm_ppk_type type); +TEE_Result versal_efuse_write_revoke_id(uint32_t id); TEE_Result versal_efuse_read_misc_ctrl(struct versal_efuse_misc_ctrl_bits *buf); TEE_Result versal_efuse_read_sec_ctrl(struct versal_efuse_sec_ctrl_bits *buf); TEE_Result versal_efuse_read_sec_misc1(struct versal_efuse_sec_misc1_bits *buf); TEE_Result versal_efuse_read_boot_env_ctrl(struct versal_efuse_boot_env_ctrl_bits *buf); -TEE_Result versal_efuse_read_offchip_revoke_id(uint32_t *buf, size_t len, - enum versal_nvm_offchip_id id); TEE_Result versal_efuse_read_dec_only(uint32_t *buf, size_t len); TEE_Result versal_efuse_read_puf_sec_ctrl(struct versal_efuse_puf_sec_ctrl_bits *buf); diff --git a/core/include/drivers/versal_trng.h b/core/include/drivers/versal_trng.h new file mode 100644 index 00000000000..d3eff4ee06b --- /dev/null +++ b/core/include/drivers/versal_trng.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023 ProvenRun SAS. + */ + +#ifndef __DRIVERS_VERSAL_TRNG_H +#define __DRIVERS_VERSAL_TRNG_H + +#include +#include +#include +#include +#include + +#define TRNG_SEED_LEN 48 +#define TRNG_PERS_STR_REGS 12 +#define TRNG_PERS_STR_LEN 48 +#define RAND_BUF_LEN 4 + +/* Derivative function helper macros */ +#define DF_SEED 0 +#define DF_RAND 1 +#define DF_IP_IV_LEN 4 +#define DF_PAD_DATA_LEN 8 +#define MAX_PRE_DF_LEN 160 +#define MAX_PRE_DF_LEN_WORDS 40 +#define DF_PERS_STR_LEN TRNG_PERS_STR_LEN +#define DF_PAD_VAL 0x80 +#define DF_KEY_LEN 32 +#define BLK_SIZE 16 +#define MAX_ROUNDS 14 + +enum trng_status { + TRNG_UNINITIALIZED = 0, + TRNG_HEALTHY, + TRNG_ERROR, + TRNG_CATASTROPHIC +}; + +enum trng_mode { + TRNG_HRNG = 0, + TRNG_DRNG, + TRNG_PTRNG +}; + +struct trng_cfg { + paddr_t base; + vaddr_t addr; + size_t len; +}; + +struct trng_usr_cfg { + enum trng_mode mode; + uint64_t seed_life; /* number of TRNG requests per seed */ + bool predict_en; /* enable prediction resistance */ + bool pstr_en; /* enable personalization string */ + uint32_t pstr[TRNG_PERS_STR_REGS]; + bool iseed_en; /* enable an initial seed */ + uint32_t init_seed[MAX_PRE_DF_LEN_WORDS]; + uint32_t df_disable; /* disable the derivative function */ + uint32_t dfmul; /* derivative function multiplier */ +}; + +struct trng_stats { + uint64_t bytes; + uint64_t bytes_reseed; + uint64_t elapsed_seed_life; +}; + +/* block cipher derivative function algorithm */ +struct trng_dfin { + uint32_t ivc[DF_IP_IV_LEN]; + uint32_t val1; + uint32_t val2; + uint8_t entropy[MAX_PRE_DF_LEN]; /* input entropy */ + uint8_t pstr[DF_PERS_STR_LEN]; /* personalization string */ + uint8_t pad_data[DF_PAD_DATA_LEN]; /* pad to multiples of 16 bytes*/ +}; + +struct versal_trng { + struct trng_cfg cfg; + struct trng_usr_cfg usr_cfg; + struct trng_stats stats; + enum trng_status status; + uint32_t buf[RAND_BUF_LEN]; /* buffer of random bits */ + size_t len; + struct trng_dfin dfin; + uint8_t dfout[TRNG_SEED_LEN]; /* output of the DF operation */ +}; + +TEE_Result versal_trng_hw_init(struct versal_trng *trng, + struct trng_usr_cfg *usr_cfg); +TEE_Result versal_trng_get_random_bytes(struct versal_trng *trng, + void *buf, size_t len); + +#endif /* __DRIVERS_VERSAL_TRNG_H */ diff --git a/core/pta/sub.mk b/core/pta/sub.mk index 1cb148a32c1..96337b8cac5 100644 --- a/core/pta/sub.mk +++ b/core/pta/sub.mk @@ -19,6 +19,7 @@ subdirs-y += bcm subdirs-y += stm32mp subdirs-y += imx subdirs-y += k3 +subdirs-y += versal ifeq ($(CFG_REMOTEPROC_PTA),y) gensrcs-y += rproc_pub_key diff --git a/core/pta/versal/fpga_pta.c b/core/pta/versal/fpga_pta.c new file mode 100644 index 00000000000..923ef482304 --- /dev/null +++ b/core/pta/versal/fpga_pta.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2023 ProvenRun SAS + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define FPGA_PTA_NAME "fpga.pta" + +static TEE_Result pta_versal_fpga_write(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result ret = TEE_SUCCESS; + uint8_t *buf = NULL; + size_t bufsize = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + bufsize = ROUNDUP(params[0].memref.size, CACHELINE_LEN); + + buf = memalign(CACHELINE_LEN, bufsize); + if (!buf) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(buf, params[0].memref.buffer, bufsize); + cache_operation(TEE_CACHEFLUSH, buf, bufsize); + + ret = versal_write_fpga(virt_to_phys(buf)); + + free(buf); + + return ret; +} + +static TEE_Result invoke_command(void *sess_ctx __unused, + uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd_id) { + case PTA_VERSAL_FPGA_WRITE: + return pta_versal_fpga_write(param_types, params); + default: + return TEE_ERROR_NOT_SUPPORTED; + } +} + +pseudo_ta_register(.uuid = PTA_VERSAL_FPGA_UUID, .name = FPGA_PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invoke_command); diff --git a/core/pta/versal/sub.mk b/core/pta/versal/sub.mk new file mode 100644 index 00000000000..f31de801902 --- /dev/null +++ b/core/pta/versal/sub.mk @@ -0,0 +1 @@ +srcs-$(CFG_VERSAL_FPGA_LOADER_PTA) += fpga_pta.c diff --git a/lib/libutee/include/pta_versal_fpga.h b/lib/libutee/include/pta_versal_fpga.h new file mode 100644 index 00000000000..ed1b3920f47 --- /dev/null +++ b/lib/libutee/include/pta_versal_fpga.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023, ProvenRun SAS + */ + +#ifndef __PTA_VERSAL_FPGA_H +#define __PTA_VERSAL_FPGA_H + +#define PTA_VERSAL_FPGA_UUID { 0xa6b493c0, 0xe100, 0x4a13, \ + { 0x9b, 0x00, 0xbc, 0xe4, 0x2d, 0x53, 0xce, 0xd8 } } + +/** + * Write FPGA bitstream + * + * [in] memref[0] FPGA bitstream buffer + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_OUT_OF_MEMORY - Could not alloc internal buffer + */ +#define PTA_VERSAL_FPGA_WRITE 0x0 + + #endif /* __PTA_VERSAL_FPGA_H */