diff --git a/plat/intel/soc/common/include/socfpga_fcs.h b/plat/intel/soc/common/include/socfpga_fcs.h index 99421e6bf..294d1e5e8 100644 --- a/plat/intel/soc/common/include/socfpga_fcs.h +++ b/plat/intel/soc/common/include/socfpga_fcs.h @@ -48,6 +48,13 @@ #define FCS_ENROLL_SELF_SIGN_CERT 0x08 #define FCS_PLAT_KEY_CERT 0x10 +/* FCS Crypto Service */ + +#define FCS_CS_KEY_OBJ_MAX_WORD_SIZE 88U +#define FCS_CS_KEY_INFO_MAX_WORD_SIZE 36U +#define FCS_CS_KEY_RESP_STATUS_MASK 0xFF +#define FCS_CS_KEY_RESP_STATUS_OFFSET 16U + /* FCS Payload Structure */ typedef struct fcs_encrypt_payload_t { @@ -78,6 +85,13 @@ typedef struct fcs_cntr_set_preauth_payload_t { uint32_t counter_value; } fcs_cntr_set_preauth_payload; +typedef struct fcs_cs_key_payload_t { + uint32_t session_id; + uint32_t reserved0; + uint32_t reserved1; + uint32_t key_id; +} fcs_cs_key_payload; + /* Functions Definitions */ uint32_t intel_fcs_random_number_gen(uint64_t addr, uint64_t *ret_size, @@ -118,4 +132,15 @@ int intel_fcs_open_crypto_service_session(uint32_t *session_id, int intel_fcs_close_crypto_service_session(uint32_t session_id, uint32_t *mbox_error); +int intel_fcs_import_crypto_service_key(uint64_t src_addr, uint32_t src_size, + uint32_t *mbox_error); +int intel_fcs_export_crypto_service_key(uint32_t session_id, uint32_t key_id, + uint64_t dst_addr, uint32_t *dst_size, + uint32_t *mbox_error); +int intel_fcs_remove_crypto_service_key(uint32_t session_id, uint32_t key_id, + uint32_t *mbox_error); +int intel_fcs_get_crypto_service_key_info(uint32_t session_id, uint32_t key_id, + uint64_t dst_addr, uint32_t *dst_size, + uint32_t *mbox_error); + #endif /* SOCFPGA_FCS_H */ diff --git a/plat/intel/soc/common/include/socfpga_mailbox.h b/plat/intel/soc/common/include/socfpga_mailbox.h index b6903d87d..f969a353e 100644 --- a/plat/intel/soc/common/include/socfpga_mailbox.h +++ b/plat/intel/soc/common/include/socfpga_mailbox.h @@ -77,6 +77,10 @@ #define MBOX_FCS_RANDOM_GEN 0x80 #define MBOX_FCS_OPEN_CS_SESSION 0xA0 #define MBOX_FCS_CLOSE_CS_SESSION 0xA1 +#define MBOX_FCS_IMPORT_CS_KEY 0xA5 +#define MBOX_FCS_EXPORT_CS_KEY 0xA6 +#define MBOX_FCS_REMOVE_CS_KEY 0xA7 +#define MBOX_FCS_GET_CS_KEY_INFO 0xA8 /* PSG SIGMA Commands */ #define MBOX_PSG_SIGMA_TEARDOWN 0xD5 diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h index 90ea3be1e..fb0c6618d 100644 --- a/plat/intel/soc/common/include/socfpga_sip_svc.h +++ b/plat/intel/soc/common/include/socfpga_sip_svc.h @@ -88,6 +88,10 @@ #define INTEL_SIP_SMC_FCS_CREATE_CERT_ON_RELOAD 0xC2000069 #define INTEL_SIP_SMC_FCS_OPEN_CS_SESSION 0xC200006E #define INTEL_SIP_SMC_FCS_CLOSE_CS_SESSION 0xC200006F +#define INTEL_SIP_SMC_FCS_IMPORT_CS_KEY 0x42000070 +#define INTEL_SIP_SMC_FCS_EXPORT_CS_KEY 0xC2000071 +#define INTEL_SIP_SMC_FCS_REMOVE_CS_KEY 0xC2000072 +#define INTEL_SIP_SMC_FCS_GET_CS_KEY_INFO 0xC2000073 /* ECC DBE */ #define WARM_RESET_WFI_FLAG BIT(31) diff --git a/plat/intel/soc/common/sip/socfpga_sip_fcs.c b/plat/intel/soc/common/sip/socfpga_sip_fcs.c index f50795e9c..821beff50 100644 --- a/plat/intel/soc/common/sip/socfpga_sip_fcs.c +++ b/plat/intel/soc/common/sip/socfpga_sip_fcs.c @@ -462,3 +462,175 @@ int intel_fcs_close_crypto_service_session(uint32_t session_id, return INTEL_SIP_SMC_STATUS_OK; } + +int intel_fcs_import_crypto_service_key(uint64_t src_addr, uint32_t src_size, + uint32_t *send_id) +{ + int status; + + if (src_size > (FCS_CS_KEY_OBJ_MAX_WORD_SIZE * + MBOX_WORD_BYTE)) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + if (!is_address_in_ddr_range(src_addr, src_size)) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + status = mailbox_send_cmd_async(send_id, MBOX_FCS_IMPORT_CS_KEY, + (uint32_t *)src_addr, src_size / MBOX_WORD_BYTE, + CMD_INDIRECT); + + if (status < 0) { + return INTEL_SIP_SMC_STATUS_ERROR; + } + + return INTEL_SIP_SMC_STATUS_OK; +} + +int intel_fcs_export_crypto_service_key(uint32_t session_id, uint32_t key_id, + uint64_t dst_addr, uint32_t *dst_size, + uint32_t *mbox_error) +{ + int status; + uint32_t i; + uint32_t payload_size; + uint32_t resp_len = FCS_CS_KEY_OBJ_MAX_WORD_SIZE; + uint32_t resp_data[FCS_CS_KEY_OBJ_MAX_WORD_SIZE] = {0U}; + uint32_t op_status = 0U; + + if ((dst_size == NULL) || (mbox_error == NULL)) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + if (!is_address_in_ddr_range(dst_addr, *dst_size)) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + fcs_cs_key_payload payload = { + session_id, + RESERVED_AS_ZERO, + RESERVED_AS_ZERO, + key_id + }; + + payload_size = sizeof(payload) / MBOX_WORD_BYTE; + + status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_EXPORT_CS_KEY, + (uint32_t *) &payload, payload_size, + CMD_CASUAL, resp_data, &resp_len); + + if (resp_len > 0) { + op_status = resp_data[0] & FCS_CS_KEY_RESP_STATUS_MASK; + } + + if (status < 0) { + *mbox_error = (-status) | (op_status << FCS_CS_KEY_RESP_STATUS_OFFSET); + return INTEL_SIP_SMC_STATUS_ERROR; + } + + if (resp_len > 1) { + + /* Export key object is start at second response data */ + *dst_size = (resp_len - 1) * MBOX_WORD_BYTE; + + for (i = 1U; i < resp_len; i++) { + mmio_write_32(dst_addr, resp_data[i]); + dst_addr += MBOX_WORD_BYTE; + } + + flush_dcache_range(dst_addr - *dst_size, *dst_size); + + } else { + + /* Unexpected response, missing key object in response */ + *mbox_error = MBOX_RET_ERROR; + return INTEL_SIP_SMC_STATUS_ERROR; + } + + return INTEL_SIP_SMC_STATUS_OK; +} + +int intel_fcs_remove_crypto_service_key(uint32_t session_id, uint32_t key_id, + uint32_t *mbox_error) +{ + int status; + uint32_t payload_size; + uint32_t resp_len = 1U; + uint32_t resp_data = 0U; + uint32_t op_status = 0U; + + if (mbox_error == NULL) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + fcs_cs_key_payload payload = { + session_id, + RESERVED_AS_ZERO, + RESERVED_AS_ZERO, + key_id + }; + + payload_size = sizeof(payload) / MBOX_WORD_BYTE; + + status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_REMOVE_CS_KEY, + (uint32_t *) &payload, payload_size, + CMD_CASUAL, &resp_data, &resp_len); + + if (resp_len > 0) { + op_status = resp_data & FCS_CS_KEY_RESP_STATUS_MASK; + } + + if (status < 0) { + *mbox_error = (-status) | (op_status << FCS_CS_KEY_RESP_STATUS_OFFSET); + return INTEL_SIP_SMC_STATUS_ERROR; + } + + return INTEL_SIP_SMC_STATUS_OK; +} + +int intel_fcs_get_crypto_service_key_info(uint32_t session_id, uint32_t key_id, + uint64_t dst_addr, uint32_t *dst_size, + uint32_t *mbox_error) +{ + int status; + uint32_t payload_size; + uint32_t resp_len = FCS_CS_KEY_INFO_MAX_WORD_SIZE; + uint32_t op_status = 0U; + + if ((dst_size == NULL) || (mbox_error == NULL)) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + if (!is_address_in_ddr_range(dst_addr, *dst_size)) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + fcs_cs_key_payload payload = { + session_id, + RESERVED_AS_ZERO, + RESERVED_AS_ZERO, + key_id + }; + + payload_size = sizeof(payload) / MBOX_WORD_BYTE; + + status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_GET_CS_KEY_INFO, + (uint32_t *) &payload, payload_size, + CMD_CASUAL, (uint32_t *) dst_addr, &resp_len); + + if (resp_len > 0) { + op_status = mmio_read_32(dst_addr) & + FCS_CS_KEY_RESP_STATUS_MASK; + } + + if (status < 0) { + *mbox_error = (-status) | (op_status << FCS_CS_KEY_RESP_STATUS_OFFSET); + return INTEL_SIP_SMC_STATUS_ERROR; + } + + *dst_size = resp_len * MBOX_WORD_BYTE; + flush_dcache_range(dst_addr, *dst_size); + + return INTEL_SIP_SMC_STATUS_OK; +} diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c index c85fda478..cdb71bf6f 100644 --- a/plat/intel/soc/common/socfpga_sip_svc.c +++ b/plat/intel/soc/common/socfpga_sip_svc.c @@ -843,6 +843,25 @@ uintptr_t sip_smc_handler(uint32_t smc_fid, status = intel_fcs_close_crypto_service_session(x1, &mbox_error); SMC_RET2(handle, status, mbox_error); + case INTEL_SIP_SMC_FCS_IMPORT_CS_KEY: + status = intel_fcs_import_crypto_service_key(x1, x2, &send_id); + SMC_RET1(handle, status); + + case INTEL_SIP_SMC_FCS_EXPORT_CS_KEY: + status = intel_fcs_export_crypto_service_key(x1, x2, x3, + (uint32_t *) &x4, &mbox_error); + SMC_RET4(handle, status, mbox_error, x3, x4); + + case INTEL_SIP_SMC_FCS_REMOVE_CS_KEY: + status = intel_fcs_remove_crypto_service_key(x1, x2, + &mbox_error); + SMC_RET2(handle, status, mbox_error); + + case INTEL_SIP_SMC_FCS_GET_CS_KEY_INFO: + status = intel_fcs_get_crypto_service_key_info(x1, x2, x3, + (uint32_t *) &x4, &mbox_error); + SMC_RET4(handle, status, mbox_error, x3, x4); + case INTEL_SIP_SMC_GET_ROM_PATCH_SHA384: status = intel_fcs_get_rom_patch_sha384(x1, &retval64, &mbox_error);