arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_fcs.c
Jit Loon Lim e8a3454cb7 fix(intel): update fcs functions to check ddr range
The src addr and dest addr of fcs functions are not checked against
their valid ddr range. Thus adding the ddr range checking to avoid
overlap/overwritten ddr address.

Signed-off-by: Jit Loon Lim <jit.loon.lim@intel.com>
Signed-off-by: Sieu Mun Tang <sieu.mun.tang@intel.com>
Change-Id: I9b4d4155dd16d9d5d36e0c91e4a2600c17867daf
2023-12-15 01:48:04 +08:00

2318 lines
58 KiB
C

/*
* Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <lib/mmio.h>
#include "socfpga_fcs.h"
#include "socfpga_mailbox.h"
#include "socfpga_sip_svc.h"
/* FCS static variables */
static fcs_crypto_service_aes_data fcs_aes_init_payload;
static fcs_crypto_service_data fcs_sha_get_digest_param;
static fcs_crypto_service_data fcs_sha_mac_verify_param;
static fcs_crypto_service_data fcs_ecdsa_hash_sign_param;
static fcs_crypto_service_data fcs_ecdsa_hash_sig_verify_param;
static fcs_crypto_service_data fcs_sha2_data_sign_param;
static fcs_crypto_service_data fcs_sha2_data_sig_verify_param;
static fcs_crypto_service_data fcs_ecdsa_get_pubkey_param;
static fcs_crypto_service_data fcs_ecdh_request_param;
bool is_size_4_bytes_aligned(uint32_t size)
{
if ((size % MBOX_WORD_BYTE) != 0U) {
return false;
} else {
return true;
}
}
static bool is_8_bytes_aligned(uint32_t data)
{
if ((data % (MBOX_WORD_BYTE * 2U)) != 0U) {
return false;
} else {
return true;
}
}
static bool is_32_bytes_aligned(uint32_t data)
{
if ((data % (8U * MBOX_WORD_BYTE)) != 0U) {
return false;
} else {
return true;
}
}
static int intel_fcs_crypto_service_init(uint32_t session_id,
uint32_t context_id, uint32_t key_id,
uint32_t param_size, uint64_t param_data,
fcs_crypto_service_data *data_addr,
uint32_t *mbox_error)
{
if (mbox_error == NULL) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (param_size != 4) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
memset(data_addr, 0, sizeof(fcs_crypto_service_data));
data_addr->session_id = session_id;
data_addr->context_id = context_id;
data_addr->key_id = key_id;
data_addr->crypto_param_size = param_size;
data_addr->crypto_param = param_data;
data_addr->is_updated = 0;
*mbox_error = 0;
return INTEL_SIP_SMC_STATUS_OK;
}
uint32_t intel_fcs_random_number_gen(uint64_t addr, uint64_t *ret_size,
uint32_t *mbox_error)
{
int status;
unsigned int i;
unsigned int resp_len = FCS_RANDOM_WORD_SIZE;
uint32_t random_data[FCS_RANDOM_WORD_SIZE] = {0U};
if (!is_address_in_ddr_range(addr, FCS_RANDOM_BYTE_SIZE)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_RANDOM_GEN, NULL, 0U,
CMD_CASUAL, random_data, &resp_len);
if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
if (resp_len != FCS_RANDOM_WORD_SIZE) {
*mbox_error = GENERIC_RESPONSE_ERROR;
return INTEL_SIP_SMC_STATUS_ERROR;
}
*ret_size = FCS_RANDOM_BYTE_SIZE;
for (i = 0U; i < FCS_RANDOM_WORD_SIZE; i++) {
mmio_write_32(addr, random_data[i]);
addr += MBOX_WORD_BYTE;
}
flush_dcache_range(addr - *ret_size, *ret_size);
return INTEL_SIP_SMC_STATUS_OK;
}
int intel_fcs_random_number_gen_ext(uint32_t session_id, uint32_t context_id,
uint32_t size, uint32_t *send_id)
{
int status;
uint32_t payload_size;
uint32_t crypto_header;
if (size > (FCS_RANDOM_EXT_MAX_WORD_SIZE *
MBOX_WORD_BYTE) || size == 0U) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_size_4_bytes_aligned(size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
crypto_header = (FCS_CS_FIELD_FLAG_INIT | FCS_CS_FIELD_FLAG_FINALIZE) <<
FCS_CS_FIELD_FLAG_OFFSET;
fcs_rng_payload payload = {
session_id,
context_id,
crypto_header,
size
};
payload_size = sizeof(payload) / MBOX_WORD_BYTE;
status = mailbox_send_cmd_async(send_id, MBOX_FCS_RANDOM_GEN,
(uint32_t *) &payload, payload_size,
CMD_INDIRECT);
if (status < 0) {
return INTEL_SIP_SMC_STATUS_ERROR;
}
return INTEL_SIP_SMC_STATUS_OK;
}
uint32_t intel_fcs_send_cert(uint64_t addr, uint64_t size,
uint32_t *send_id)
{
int status;
if (!is_address_in_ddr_range(addr, size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_size_4_bytes_aligned(size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
status = mailbox_send_cmd_async(send_id, MBOX_CMD_VAB_SRC_CERT,
(uint32_t *)addr, size / MBOX_WORD_BYTE,
CMD_DIRECT);
flush_dcache_range(addr, size);
if (status < 0) {
return INTEL_SIP_SMC_STATUS_ERROR;
}
return INTEL_SIP_SMC_STATUS_OK;
}
uint32_t intel_fcs_get_provision_data(uint32_t *send_id)
{
int status;
status = mailbox_send_cmd_async(send_id, MBOX_FCS_GET_PROVISION,
NULL, 0U, CMD_DIRECT);
if (status < 0) {
return INTEL_SIP_SMC_STATUS_ERROR;
}
return INTEL_SIP_SMC_STATUS_OK;
}
uint32_t intel_fcs_cntr_set_preauth(uint8_t counter_type, int32_t counter_value,
uint32_t test_bit, uint32_t *mbox_error)
{
int status;
uint32_t first_word;
uint32_t payload_size;
if ((test_bit != MBOX_TEST_BIT) &&
(test_bit != 0)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if ((counter_type < FCS_BIG_CNTR_SEL) ||
(counter_type > FCS_SVN_CNTR_3_SEL)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if ((counter_type == FCS_BIG_CNTR_SEL) &&
(counter_value > FCS_BIG_CNTR_VAL_MAX)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if ((counter_type >= FCS_SVN_CNTR_0_SEL) &&
(counter_type <= FCS_SVN_CNTR_3_SEL) &&
(counter_value > FCS_SVN_CNTR_VAL_MAX)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
first_word = test_bit | counter_type;
fcs_cntr_set_preauth_payload payload = {
first_word,
counter_value
};
payload_size = sizeof(payload) / MBOX_WORD_BYTE;
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_CNTR_SET_PREAUTH,
(uint32_t *) &payload, payload_size,
CMD_CASUAL, NULL, NULL);
if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
return INTEL_SIP_SMC_STATUS_OK;
}
uint32_t intel_fcs_encryption(uint32_t src_addr, uint32_t src_size,
uint32_t dst_addr, uint32_t dst_size, uint32_t *send_id)
{
int status;
uint32_t load_size;
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_size_4_bytes_aligned(src_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
fcs_encrypt_payload payload = {
FCS_ENCRYPTION_DATA_0,
src_addr,
src_size,
dst_addr,
dst_size };
load_size = sizeof(payload) / MBOX_WORD_BYTE;
status = mailbox_send_cmd_async(send_id, MBOX_FCS_ENCRYPT_REQ,
(uint32_t *) &payload, load_size,
CMD_INDIRECT);
inv_dcache_range(dst_addr, dst_size);
if (status < 0) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
return INTEL_SIP_SMC_STATUS_OK;
}
uint32_t intel_fcs_decryption(uint32_t src_addr, uint32_t src_size,
uint32_t dst_addr, uint32_t dst_size, uint32_t *send_id)
{
int status;
uint32_t load_size;
uintptr_t id_offset;
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_size_4_bytes_aligned(src_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
inv_dcache_range(src_addr, src_size); /* flush cache before mmio read to avoid reading old values */
id_offset = src_addr + FCS_OWNER_ID_OFFSET;
fcs_decrypt_payload payload = {
FCS_DECRYPTION_DATA_0,
{mmio_read_32(id_offset),
mmio_read_32(id_offset + MBOX_WORD_BYTE)},
src_addr,
src_size,
dst_addr,
dst_size };
load_size = sizeof(payload) / MBOX_WORD_BYTE;
status = mailbox_send_cmd_async(send_id, MBOX_FCS_DECRYPT_REQ,
(uint32_t *) &payload, load_size,
CMD_INDIRECT);
inv_dcache_range(dst_addr, dst_size);
if (status < 0) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
return INTEL_SIP_SMC_STATUS_OK;
}
int intel_fcs_encryption_ext(uint32_t session_id, uint32_t context_id,
uint32_t src_addr, uint32_t src_size,
uint32_t dst_addr, uint32_t *dst_size, uint32_t *mbox_error)
{
int status;
uint32_t payload_size;
uint32_t resp_len = FCS_CRYPTION_RESP_WORD_SIZE;
uint32_t resp_data[FCS_CRYPTION_RESP_WORD_SIZE] = {0U};
if ((dst_size == NULL) || (mbox_error == NULL)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_size_4_bytes_aligned(src_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
fcs_encrypt_ext_payload payload = {
session_id,
context_id,
FCS_CRYPTION_CRYPTO_HEADER,
src_addr,
src_size,
dst_addr,
*dst_size
};
payload_size = sizeof(payload) / MBOX_WORD_BYTE;
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_ENCRYPT_REQ,
(uint32_t *) &payload, payload_size,
CMD_CASUAL, resp_data, &resp_len);
if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
if (resp_len != FCS_CRYPTION_RESP_WORD_SIZE) {
*mbox_error = MBOX_RET_ERROR;
return INTEL_SIP_SMC_STATUS_ERROR;
}
*dst_size = resp_data[FCS_CRYPTION_RESP_SIZE_OFFSET];
inv_dcache_range(dst_addr, *dst_size);
return INTEL_SIP_SMC_STATUS_OK;
}
int intel_fcs_decryption_ext(uint32_t session_id, uint32_t context_id,
uint32_t src_addr, uint32_t src_size,
uint32_t dst_addr, uint32_t *dst_size, uint32_t *mbox_error)
{
int status;
uintptr_t id_offset;
uint32_t payload_size;
uint32_t resp_len = FCS_CRYPTION_RESP_WORD_SIZE;
uint32_t resp_data[FCS_CRYPTION_RESP_WORD_SIZE] = {0U};
if ((dst_size == NULL) || (mbox_error == NULL)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_size_4_bytes_aligned(src_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
inv_dcache_range(src_addr, src_size); /* flush cache before mmio read to avoid reading old values */
id_offset = src_addr + FCS_OWNER_ID_OFFSET;
fcs_decrypt_ext_payload payload = {
session_id,
context_id,
FCS_CRYPTION_CRYPTO_HEADER,
{mmio_read_32(id_offset),
mmio_read_32(id_offset + MBOX_WORD_BYTE)},
src_addr,
src_size,
dst_addr,
*dst_size
};
payload_size = sizeof(payload) / MBOX_WORD_BYTE;
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_DECRYPT_REQ,
(uint32_t *) &payload, payload_size,
CMD_CASUAL, resp_data, &resp_len);
if (status == MBOX_RET_SDOS_DECRYPTION_ERROR_102 ||
status == MBOX_RET_SDOS_DECRYPTION_ERROR_103) {
*mbox_error = -status;
} else if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
if (resp_len != FCS_CRYPTION_RESP_WORD_SIZE) {
*mbox_error = MBOX_RET_ERROR;
return INTEL_SIP_SMC_STATUS_ERROR;
}
*dst_size = resp_data[FCS_CRYPTION_RESP_SIZE_OFFSET];
inv_dcache_range(dst_addr, *dst_size);
return INTEL_SIP_SMC_STATUS_OK;
}
int intel_fcs_sigma_teardown(uint32_t session_id, uint32_t *mbox_error)
{
int status;
if ((session_id != PSGSIGMA_SESSION_ID_ONE) &&
(session_id != PSGSIGMA_UNKNOWN_SESSION)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
psgsigma_teardown_msg message = {
RESERVED_AS_ZERO,
PSGSIGMA_TEARDOWN_MAGIC,
session_id
};
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_PSG_SIGMA_TEARDOWN,
(uint32_t *) &message, sizeof(message) / MBOX_WORD_BYTE,
CMD_CASUAL, NULL, NULL);
if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
return INTEL_SIP_SMC_STATUS_OK;
}
int intel_fcs_chip_id(uint32_t *id_low, uint32_t *id_high, uint32_t *mbox_error)
{
int status;
uint32_t load_size;
uint32_t chip_id[2];
load_size = sizeof(chip_id) / MBOX_WORD_BYTE;
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_GET_CHIPID, NULL,
0U, CMD_CASUAL, (uint32_t *) chip_id, &load_size);
if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
*id_low = chip_id[0];
*id_high = chip_id[1];
return INTEL_SIP_SMC_STATUS_OK;
}
int intel_fcs_attestation_subkey(uint64_t src_addr, uint32_t src_size,
uint64_t dst_addr, uint32_t *dst_size, uint32_t *mbox_error)
{
int status;
uint32_t send_size = src_size / MBOX_WORD_BYTE;
uint32_t ret_size = *dst_size / MBOX_WORD_BYTE;
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_ATTESTATION_SUBKEY,
(uint32_t *) src_addr, send_size, CMD_CASUAL,
(uint32_t *) dst_addr, &ret_size);
if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
*dst_size = ret_size * MBOX_WORD_BYTE;
flush_dcache_range(dst_addr, *dst_size);
return INTEL_SIP_SMC_STATUS_OK;
}
int intel_fcs_get_measurement(uint64_t src_addr, uint32_t src_size,
uint64_t dst_addr, uint32_t *dst_size, uint32_t *mbox_error)
{
int status;
uint32_t send_size = src_size / MBOX_WORD_BYTE;
uint32_t ret_size = *dst_size / MBOX_WORD_BYTE;
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_MEASUREMENT,
(uint32_t *) src_addr, send_size, CMD_CASUAL,
(uint32_t *) dst_addr, &ret_size);
if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
*dst_size = ret_size * MBOX_WORD_BYTE;
flush_dcache_range(dst_addr, *dst_size);
return INTEL_SIP_SMC_STATUS_OK;
}
uint32_t intel_fcs_get_rom_patch_sha384(uint64_t addr, uint64_t *ret_size,
uint32_t *mbox_error)
{
int status;
unsigned int resp_len = FCS_SHA384_WORD_SIZE;
if (!is_address_in_ddr_range(addr, FCS_SHA384_BYTE_SIZE)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_ROM_PATCH_SHA384, NULL, 0U,
CMD_CASUAL, (uint32_t *) addr, &resp_len);
if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
if (resp_len != FCS_SHA384_WORD_SIZE) {
*mbox_error = GENERIC_RESPONSE_ERROR;
return INTEL_SIP_SMC_STATUS_ERROR;
}
*ret_size = FCS_SHA384_BYTE_SIZE;
flush_dcache_range(addr, *ret_size);
return INTEL_SIP_SMC_STATUS_OK;
}
int intel_fcs_get_attestation_cert(uint32_t cert_request, uint64_t dst_addr,
uint32_t *dst_size, uint32_t *mbox_error)
{
int status;
uint32_t ret_size = *dst_size / MBOX_WORD_BYTE;
if (mbox_error == NULL) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (cert_request < FCS_ATTEST_FIRMWARE_CERT ||
cert_request > FCS_ATTEST_CERT_MAX_REQ_PARAM) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_ATTESTATION_CERT,
(uint32_t *) &cert_request, 1U, CMD_CASUAL,
(uint32_t *) dst_addr, &ret_size);
if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
*dst_size = ret_size * MBOX_WORD_BYTE;
flush_dcache_range(dst_addr, *dst_size);
return INTEL_SIP_SMC_STATUS_OK;
}
int intel_fcs_create_cert_on_reload(uint32_t cert_request,
uint32_t *mbox_error)
{
int status;
if (mbox_error == NULL) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (cert_request < FCS_ATTEST_FIRMWARE_CERT ||
cert_request > FCS_ATTEST_CERT_MAX_REQ_PARAM) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_CREATE_CERT_ON_RELOAD,
(uint32_t *) &cert_request, 1U, CMD_CASUAL,
NULL, NULL);
if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
return INTEL_SIP_SMC_STATUS_OK;
}
int intel_fcs_open_crypto_service_session(uint32_t *session_id,
uint32_t *mbox_error)
{
int status;
uint32_t resp_len = 1U;
if ((session_id == NULL) || (mbox_error == NULL)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_OPEN_CS_SESSION,
NULL, 0U, CMD_CASUAL, session_id, &resp_len);
if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
return INTEL_SIP_SMC_STATUS_OK;
}
int intel_fcs_close_crypto_service_session(uint32_t session_id,
uint32_t *mbox_error)
{
int status;
if (mbox_error == NULL) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_CLOSE_CS_SESSION,
&session_id, 1U, CMD_CASUAL, NULL, NULL);
if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
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) {
inv_dcache_range(dst_addr, (resp_len * MBOX_WORD_BYTE)); /* flush cache before mmio read to avoid reading old values */
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;
}
int intel_fcs_get_digest_init(uint32_t session_id, uint32_t context_id,
uint32_t key_id, uint32_t param_size,
uint64_t param_data, uint32_t *mbox_error)
{
return intel_fcs_crypto_service_init(session_id, context_id,
key_id, param_size, param_data,
(void *) &fcs_sha_get_digest_param,
mbox_error);
}
int intel_fcs_get_digest_update_finalize(uint32_t session_id,
uint32_t context_id, uint32_t src_addr,
uint32_t src_size, uint64_t dst_addr,
uint32_t *dst_size, uint8_t is_finalised,
uint32_t *mbox_error)
{
int status;
uint32_t i;
uint32_t flag;
uint32_t crypto_header;
uint32_t resp_len;
uint32_t payload[FCS_GET_DIGEST_CMD_MAX_WORD_SIZE] = {0U};
if (dst_size == NULL || mbox_error == NULL) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (fcs_sha_get_digest_param.session_id != session_id ||
fcs_sha_get_digest_param.context_id != context_id) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
/* Source data must be 8 bytes aligned */
if (!is_8_bytes_aligned(src_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
resp_len = *dst_size / MBOX_WORD_BYTE;
/* Prepare crypto header */
flag = 0;
if (fcs_sha_get_digest_param.is_updated) {
fcs_sha_get_digest_param.crypto_param_size = 0;
} else {
flag |= FCS_CS_FIELD_FLAG_INIT;
}
if (is_finalised != 0U) {
flag |= FCS_CS_FIELD_FLAG_FINALIZE;
} else {
flag |= FCS_CS_FIELD_FLAG_UPDATE;
fcs_sha_get_digest_param.is_updated = 1;
}
crypto_header = ((flag << FCS_CS_FIELD_FLAG_OFFSET) |
(fcs_sha_get_digest_param.crypto_param_size &
FCS_CS_FIELD_SIZE_MASK));
/* Prepare command payload */
i = 0;
payload[i] = fcs_sha_get_digest_param.session_id;
i++;
payload[i] = fcs_sha_get_digest_param.context_id;
i++;
payload[i] = crypto_header;
i++;
if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
FCS_CS_FIELD_FLAG_INIT) {
payload[i] = fcs_sha_get_digest_param.key_id;
i++;
/* Crypto parameters */
payload[i] = fcs_sha_get_digest_param.crypto_param
& INTEL_SIP_SMC_FCS_SHA_MODE_MASK;
payload[i] |= ((fcs_sha_get_digest_param.crypto_param
>> INTEL_SIP_SMC_FCS_DIGEST_SIZE_OFFSET)
& INTEL_SIP_SMC_FCS_DIGEST_SIZE_MASK)
<< FCS_SHA_HMAC_CRYPTO_PARAM_SIZE_OFFSET;
i++;
}
/* Data source address and size */
payload[i] = src_addr;
i++;
payload[i] = src_size;
i++;
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_GET_DIGEST_REQ,
payload, i, CMD_CASUAL,
(uint32_t *) dst_addr, &resp_len);
if (is_finalised != 0U) {
memset((void *)&fcs_sha_get_digest_param, 0,
sizeof(fcs_crypto_service_data));
}
if (status < 0) {
*mbox_error = -status;
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;
}
int intel_fcs_get_digest_smmu_update_finalize(uint32_t session_id,
uint32_t context_id, uint32_t src_addr,
uint32_t src_size, uint64_t dst_addr,
uint32_t *dst_size, uint8_t is_finalised,
uint32_t *mbox_error, uint32_t *send_id)
{
int status;
uint32_t i;
uint32_t flag;
uint32_t crypto_header;
uint32_t resp_len;
uint32_t payload[FCS_GET_DIGEST_CMD_MAX_WORD_SIZE] = {0U};
/* Source data must be 8 bytes aligned */
if (dst_size == NULL || mbox_error == NULL ||
!is_8_bytes_aligned(src_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (fcs_sha_get_digest_param.session_id != session_id ||
fcs_sha_get_digest_param.context_id != context_id) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
resp_len = *dst_size / MBOX_WORD_BYTE;
/* Prepare crypto header */
flag = 0;
if (fcs_sha_get_digest_param.is_updated) {
fcs_sha_get_digest_param.crypto_param_size = 0;
} else {
flag |= FCS_CS_FIELD_FLAG_INIT;
}
if (is_finalised != 0U) {
flag |= FCS_CS_FIELD_FLAG_FINALIZE;
} else {
flag |= FCS_CS_FIELD_FLAG_UPDATE;
fcs_sha_get_digest_param.is_updated = 1;
}
crypto_header = ((flag << FCS_CS_FIELD_FLAG_OFFSET) |
(fcs_sha_get_digest_param.crypto_param_size &
FCS_CS_FIELD_SIZE_MASK));
/* Prepare command payload */
i = 0;
payload[i] = fcs_sha_get_digest_param.session_id;
i++;
payload[i] = fcs_sha_get_digest_param.context_id;
i++;
payload[i] = crypto_header;
i++;
if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
FCS_CS_FIELD_FLAG_INIT) {
payload[i] = fcs_sha_get_digest_param.key_id;
i++;
/* Crypto parameters */
payload[i] = fcs_sha_get_digest_param.crypto_param
& INTEL_SIP_SMC_FCS_SHA_MODE_MASK;
payload[i] |= ((fcs_sha_get_digest_param.crypto_param
>> INTEL_SIP_SMC_FCS_DIGEST_SIZE_OFFSET)
& INTEL_SIP_SMC_FCS_DIGEST_SIZE_MASK)
<< FCS_SHA_HMAC_CRYPTO_PARAM_SIZE_OFFSET;
i++;
}
/* Data source address and size */
payload[i] = src_addr;
i++;
payload[i] = src_size;
i++;
status = mailbox_send_cmd_async(send_id, MBOX_FCS_GET_DIGEST_REQ,
payload, i, CMD_INDIRECT);
if (is_finalised != 0U) {
memset((void *)&fcs_sha_get_digest_param, 0,
sizeof(fcs_crypto_service_data));
}
if (status < 0) {
*mbox_error = -status;
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;
}
int intel_fcs_mac_verify_init(uint32_t session_id, uint32_t context_id,
uint32_t key_id, uint32_t param_size,
uint64_t param_data, uint32_t *mbox_error)
{
return intel_fcs_crypto_service_init(session_id, context_id,
key_id, param_size, param_data,
(void *) &fcs_sha_mac_verify_param,
mbox_error);
}
int intel_fcs_mac_verify_update_finalize(uint32_t session_id,
uint32_t context_id, uint32_t src_addr,
uint32_t src_size, uint64_t dst_addr,
uint32_t *dst_size, uint32_t data_size,
uint8_t is_finalised, uint32_t *mbox_error)
{
int status;
uint32_t i;
uint32_t flag;
uint32_t crypto_header;
uint32_t resp_len;
uint32_t payload[FCS_MAC_VERIFY_CMD_MAX_WORD_SIZE] = {0U};
uintptr_t mac_offset;
uint32_t dst_size_check = 0;
if (dst_size == NULL || mbox_error == NULL) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (fcs_sha_mac_verify_param.session_id != session_id ||
fcs_sha_mac_verify_param.context_id != context_id) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (data_size > src_size) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_size_4_bytes_aligned(src_size) ||
!is_8_bytes_aligned(data_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
dst_size_check = *dst_size;
if ((dst_size_check > FCS_MAX_DATA_SIZE ||
dst_size_check < FCS_MIN_DATA_SIZE) ||
(src_size > FCS_MAX_DATA_SIZE ||
src_size < FCS_MIN_DATA_SIZE)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
resp_len = *dst_size / MBOX_WORD_BYTE;
/* Prepare crypto header */
flag = 0;
if (fcs_sha_mac_verify_param.is_updated) {
fcs_sha_mac_verify_param.crypto_param_size = 0;
} else {
flag |= FCS_CS_FIELD_FLAG_INIT;
}
if (is_finalised) {
flag |= FCS_CS_FIELD_FLAG_FINALIZE;
} else {
flag |= FCS_CS_FIELD_FLAG_UPDATE;
fcs_sha_mac_verify_param.is_updated = 1;
}
crypto_header = ((flag << FCS_CS_FIELD_FLAG_OFFSET) |
(fcs_sha_mac_verify_param.crypto_param_size &
FCS_CS_FIELD_SIZE_MASK));
/* Prepare command payload */
i = 0;
payload[i] = fcs_sha_mac_verify_param.session_id;
i++;
payload[i] = fcs_sha_mac_verify_param.context_id;
i++;
payload[i] = crypto_header;
i++;
if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
FCS_CS_FIELD_FLAG_INIT) {
payload[i] = fcs_sha_mac_verify_param.key_id;
i++;
/* Crypto parameters */
payload[i] = ((fcs_sha_mac_verify_param.crypto_param
>> INTEL_SIP_SMC_FCS_DIGEST_SIZE_OFFSET)
& INTEL_SIP_SMC_FCS_DIGEST_SIZE_MASK)
<< FCS_SHA_HMAC_CRYPTO_PARAM_SIZE_OFFSET;
i++;
}
/* Data source address and size */
payload[i] = src_addr;
i++;
payload[i] = data_size;
i++;
if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
FCS_CS_FIELD_FLAG_FINALIZE) {
/* Copy mac data to command */
mac_offset = src_addr + data_size;
if ((i + ((src_size - data_size) / MBOX_WORD_BYTE)) >
FCS_MAC_VERIFY_CMD_MAX_WORD_SIZE) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
memcpy((uint8_t *) &payload[i], (uint8_t *) mac_offset,
src_size - data_size);
i += (src_size - data_size) / MBOX_WORD_BYTE;
}
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_MAC_VERIFY_REQ,
payload, i, CMD_CASUAL,
(uint32_t *) dst_addr, &resp_len);
if (is_finalised) {
memset((void *)&fcs_sha_mac_verify_param, 0,
sizeof(fcs_crypto_service_data));
}
if (status < 0) {
*mbox_error = -status;
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;
}
int intel_fcs_mac_verify_smmu_update_finalize(uint32_t session_id,
uint32_t context_id, uint32_t src_addr,
uint32_t src_size, uint64_t dst_addr,
uint32_t *dst_size, uint32_t data_size,
uint8_t is_finalised, uint32_t *mbox_error,
uint32_t *send_id)
{
int status;
uint32_t i;
uint32_t flag;
uint32_t crypto_header;
uint32_t resp_len;
uint32_t payload[FCS_MAC_VERIFY_CMD_MAX_WORD_SIZE] = {0U};
uintptr_t mac_offset;
uint32_t dst_size_check = 0;
/*
* Source data must be 4 bytes aligned
* User data must be 8 bytes aligned
*/
if (dst_size == NULL || mbox_error == NULL ||
!is_size_4_bytes_aligned(src_size) ||
!is_8_bytes_aligned(data_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (data_size > src_size) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (fcs_sha_mac_verify_param.session_id != session_id ||
fcs_sha_mac_verify_param.context_id != context_id) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
dst_size_check = *dst_size;
if ((dst_size_check > FCS_MAX_DATA_SIZE ||
dst_size_check < FCS_MIN_DATA_SIZE) ||
(src_size > FCS_MAX_DATA_SIZE ||
src_size < FCS_MIN_DATA_SIZE)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
resp_len = *dst_size / MBOX_WORD_BYTE;
/* Prepare crypto header */
flag = 0;
if (fcs_sha_mac_verify_param.is_updated) {
fcs_sha_mac_verify_param.crypto_param_size = 0;
} else {
flag |= FCS_CS_FIELD_FLAG_INIT;
}
if (is_finalised) {
flag |= FCS_CS_FIELD_FLAG_FINALIZE;
} else {
flag |= FCS_CS_FIELD_FLAG_UPDATE;
fcs_sha_mac_verify_param.is_updated = 1;
}
crypto_header = ((flag << FCS_CS_FIELD_FLAG_OFFSET) |
(fcs_sha_mac_verify_param.crypto_param_size &
FCS_CS_FIELD_SIZE_MASK));
/* Prepare command payload */
i = 0;
payload[i] = fcs_sha_mac_verify_param.session_id;
i++;
payload[i] = fcs_sha_mac_verify_param.context_id;
i++;
payload[i] = crypto_header;
i++;
if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
FCS_CS_FIELD_FLAG_INIT) {
payload[i] = fcs_sha_mac_verify_param.key_id;
i++;
/* Crypto parameters */
payload[i] = ((fcs_sha_mac_verify_param.crypto_param
>> INTEL_SIP_SMC_FCS_DIGEST_SIZE_OFFSET)
& INTEL_SIP_SMC_FCS_DIGEST_SIZE_MASK)
<< FCS_SHA_HMAC_CRYPTO_PARAM_SIZE_OFFSET;
i++;
}
/* Data source address and size */
payload[i] = src_addr;
i++;
payload[i] = data_size;
i++;
if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
FCS_CS_FIELD_FLAG_FINALIZE) {
/* Copy mac data to command
* Using dst_addr (physical address) to store mac_offset
* mac_offset = MAC data
*/
mac_offset = dst_addr;
if ((i + ((src_size - data_size) / MBOX_WORD_BYTE)) >
FCS_MAC_VERIFY_CMD_MAX_WORD_SIZE) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
memcpy((uint8_t *) &payload[i], (uint8_t *) mac_offset,
src_size - data_size);
memset((void *) dst_addr, 0, *dst_size);
i += (src_size - data_size) / MBOX_WORD_BYTE;
}
status = mailbox_send_cmd_async(send_id, MBOX_FCS_MAC_VERIFY_REQ,
payload, i, CMD_INDIRECT);
if (is_finalised) {
memset((void *)&fcs_sha_mac_verify_param, 0,
sizeof(fcs_crypto_service_data));
}
if (status < 0) {
*mbox_error = -status;
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;
}
int intel_fcs_ecdsa_hash_sign_init(uint32_t session_id, uint32_t context_id,
uint32_t key_id, uint32_t param_size,
uint64_t param_data, uint32_t *mbox_error)
{
return intel_fcs_crypto_service_init(session_id, context_id,
key_id, param_size, param_data,
(void *) &fcs_ecdsa_hash_sign_param,
mbox_error);
}
int intel_fcs_ecdsa_hash_sign_finalize(uint32_t session_id, uint32_t context_id,
uint32_t src_addr, uint32_t src_size,
uint64_t dst_addr, uint32_t *dst_size,
uint32_t *mbox_error)
{
int status;
uint32_t i;
uint32_t payload[FCS_ECDSA_HASH_SIGN_CMD_MAX_WORD_SIZE] = {0U};
uint32_t resp_len;
uintptr_t hash_data_addr;
uint32_t dst_size_check = 0;
if ((dst_size == NULL) || (mbox_error == NULL)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (fcs_ecdsa_hash_sign_param.session_id != session_id ||
fcs_ecdsa_hash_sign_param.context_id != context_id) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
dst_size_check = *dst_size;
if ((dst_size_check > FCS_MAX_DATA_SIZE ||
dst_size_check < FCS_MIN_DATA_SIZE) ||
(src_size > FCS_MAX_DATA_SIZE ||
src_size < FCS_MIN_DATA_SIZE)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
resp_len = *dst_size / MBOX_WORD_BYTE;
/* Prepare command payload */
/* Crypto header */
i = 0;
payload[i] = fcs_ecdsa_hash_sign_param.session_id;
i++;
payload[i] = fcs_ecdsa_hash_sign_param.context_id;
i++;
payload[i] = fcs_ecdsa_hash_sign_param.crypto_param_size
& FCS_CS_FIELD_SIZE_MASK;
payload[i] |= (FCS_CS_FIELD_FLAG_INIT | FCS_CS_FIELD_FLAG_UPDATE
| FCS_CS_FIELD_FLAG_FINALIZE)
<< FCS_CS_FIELD_FLAG_OFFSET;
i++;
payload[i] = fcs_ecdsa_hash_sign_param.key_id;
/* Crypto parameters */
i++;
payload[i] = fcs_ecdsa_hash_sign_param.crypto_param
& INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
/* Hash Data */
i++;
hash_data_addr = src_addr;
if ((i + ((src_size) / MBOX_WORD_BYTE)) >
FCS_ECDSA_HASH_SIGN_CMD_MAX_WORD_SIZE) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
memcpy((uint8_t *) &payload[i], (uint8_t *) hash_data_addr,
src_size);
i += src_size / MBOX_WORD_BYTE;
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_ECDSA_HASH_SIGN_REQ,
payload, i, CMD_CASUAL, (uint32_t *) dst_addr,
&resp_len);
memset((void *) &fcs_ecdsa_hash_sign_param,
0, sizeof(fcs_crypto_service_data));
if (status < 0) {
*mbox_error = -status;
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;
}
int intel_fcs_ecdsa_hash_sig_verify_init(uint32_t session_id, uint32_t context_id,
uint32_t key_id, uint32_t param_size,
uint64_t param_data, uint32_t *mbox_error)
{
return intel_fcs_crypto_service_init(session_id, context_id,
key_id, param_size, param_data,
(void *) &fcs_ecdsa_hash_sig_verify_param,
mbox_error);
}
int intel_fcs_ecdsa_hash_sig_verify_finalize(uint32_t session_id, uint32_t context_id,
uint32_t src_addr, uint32_t src_size,
uint64_t dst_addr, uint32_t *dst_size,
uint32_t *mbox_error)
{
int status;
uint32_t i = 0;
uint32_t payload[FCS_ECDSA_HASH_SIG_VERIFY_CMD_MAX_WORD_SIZE] = {0U};
uint32_t resp_len;
uintptr_t hash_sig_pubkey_addr;
uint32_t dst_size_check = 0;
if ((dst_size == NULL) || (mbox_error == NULL)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (fcs_ecdsa_hash_sig_verify_param.session_id != session_id ||
fcs_ecdsa_hash_sig_verify_param.context_id != context_id) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
dst_size_check = *dst_size;
if ((dst_size_check > FCS_MAX_DATA_SIZE ||
dst_size_check < FCS_MIN_DATA_SIZE) ||
(src_size > FCS_MAX_DATA_SIZE ||
src_size < FCS_MIN_DATA_SIZE)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
resp_len = *dst_size / MBOX_WORD_BYTE;
/* Prepare command payload */
/* Crypto header */
i = 0;
payload[i] = fcs_ecdsa_hash_sig_verify_param.session_id;
i++;
payload[i] = fcs_ecdsa_hash_sig_verify_param.context_id;
i++;
payload[i] = fcs_ecdsa_hash_sig_verify_param.crypto_param_size
& FCS_CS_FIELD_SIZE_MASK;
payload[i] |= (FCS_CS_FIELD_FLAG_INIT | FCS_CS_FIELD_FLAG_UPDATE
| FCS_CS_FIELD_FLAG_FINALIZE)
<< FCS_CS_FIELD_FLAG_OFFSET;
i++;
payload[i] = fcs_ecdsa_hash_sig_verify_param.key_id;
/* Crypto parameters */
i++;
payload[i] = fcs_ecdsa_hash_sig_verify_param.crypto_param
& INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
/* Hash Data Word, Signature Data Word and Public Key Data word */
i++;
hash_sig_pubkey_addr = src_addr;
if ((i + ((src_size) / MBOX_WORD_BYTE)) >
FCS_ECDSA_HASH_SIG_VERIFY_CMD_MAX_WORD_SIZE) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
memcpy((uint8_t *) &payload[i],
(uint8_t *) hash_sig_pubkey_addr, src_size);
i += (src_size / MBOX_WORD_BYTE);
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_ECDSA_HASH_SIG_VERIFY,
payload, i, CMD_CASUAL, (uint32_t *) dst_addr,
&resp_len);
memset((void *)&fcs_ecdsa_hash_sig_verify_param,
0, sizeof(fcs_crypto_service_data));
if (status < 0) {
*mbox_error = -status;
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;
}
int intel_fcs_ecdsa_sha2_data_sign_init(uint32_t session_id,
uint32_t context_id, uint32_t key_id,
uint32_t param_size, uint64_t param_data,
uint32_t *mbox_error)
{
return intel_fcs_crypto_service_init(session_id, context_id,
key_id, param_size, param_data,
(void *) &fcs_sha2_data_sign_param,
mbox_error);
}
int intel_fcs_ecdsa_sha2_data_sign_update_finalize(uint32_t session_id,
uint32_t context_id, uint32_t src_addr,
uint32_t src_size, uint64_t dst_addr,
uint32_t *dst_size, uint8_t is_finalised,
uint32_t *mbox_error)
{
int status;
int i;
uint32_t flag;
uint32_t crypto_header;
uint32_t payload[FCS_ECDSA_SHA2_DATA_SIGN_CMD_MAX_WORD_SIZE] = {0U};
uint32_t resp_len;
if ((dst_size == NULL) || (mbox_error == NULL)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (fcs_sha2_data_sign_param.session_id != session_id ||
fcs_sha2_data_sign_param.context_id != context_id) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
/* Source data must be 8 bytes aligned */
if (!is_8_bytes_aligned(src_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
resp_len = *dst_size / MBOX_WORD_BYTE;
/* Prepare crypto header */
flag = 0;
if (fcs_sha2_data_sign_param.is_updated) {
fcs_sha2_data_sign_param.crypto_param_size = 0;
} else {
flag |= FCS_CS_FIELD_FLAG_INIT;
}
if (is_finalised != 0U) {
flag |= FCS_CS_FIELD_FLAG_FINALIZE;
} else {
flag |= FCS_CS_FIELD_FLAG_UPDATE;
fcs_sha2_data_sign_param.is_updated = 1;
}
crypto_header = (flag << FCS_CS_FIELD_FLAG_OFFSET) |
fcs_sha2_data_sign_param.crypto_param_size;
/* Prepare command payload */
i = 0;
payload[i] = fcs_sha2_data_sign_param.session_id;
i++;
payload[i] = fcs_sha2_data_sign_param.context_id;
i++;
payload[i] = crypto_header;
i++;
if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
FCS_CS_FIELD_FLAG_INIT) {
payload[i] = fcs_sha2_data_sign_param.key_id;
/* Crypto parameters */
i++;
payload[i] = fcs_sha2_data_sign_param.crypto_param
& INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
i++;
}
/* Data source address and size */
payload[i] = src_addr;
i++;
payload[i] = src_size;
i++;
status = mailbox_send_cmd(MBOX_JOB_ID,
MBOX_FCS_ECDSA_SHA2_DATA_SIGN_REQ, payload,
i, CMD_CASUAL, (uint32_t *) dst_addr,
&resp_len);
if (is_finalised != 0U) {
memset((void *)&fcs_sha2_data_sign_param, 0,
sizeof(fcs_crypto_service_data));
}
if (status < 0) {
*mbox_error = -status;
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;
}
int intel_fcs_ecdsa_sha2_data_sign_smmu_update_finalize(uint32_t session_id,
uint32_t context_id, uint32_t src_addr,
uint32_t src_size, uint64_t dst_addr,
uint32_t *dst_size, uint8_t is_finalised,
uint32_t *mbox_error, uint32_t *send_id)
{
int status;
int i;
uint32_t flag;
uint32_t crypto_header;
uint32_t payload[FCS_ECDSA_SHA2_DATA_SIGN_CMD_MAX_WORD_SIZE] = {0U};
uint32_t resp_len;
/* Source data must be 8 bytes aligned */
if ((dst_size == NULL) || (mbox_error == NULL ||
!is_8_bytes_aligned(src_size))) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (fcs_sha2_data_sign_param.session_id != session_id ||
fcs_sha2_data_sign_param.context_id != context_id) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
resp_len = *dst_size / MBOX_WORD_BYTE;
/* Prepare crypto header */
flag = 0;
if (fcs_sha2_data_sign_param.is_updated) {
fcs_sha2_data_sign_param.crypto_param_size = 0;
} else {
flag |= FCS_CS_FIELD_FLAG_INIT;
}
if (is_finalised != 0U) {
flag |= FCS_CS_FIELD_FLAG_FINALIZE;
} else {
flag |= FCS_CS_FIELD_FLAG_UPDATE;
fcs_sha2_data_sign_param.is_updated = 1;
}
crypto_header = (flag << FCS_CS_FIELD_FLAG_OFFSET) |
fcs_sha2_data_sign_param.crypto_param_size;
/* Prepare command payload */
i = 0;
payload[i] = fcs_sha2_data_sign_param.session_id;
i++;
payload[i] = fcs_sha2_data_sign_param.context_id;
i++;
payload[i] = crypto_header;
i++;
if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
FCS_CS_FIELD_FLAG_INIT) {
payload[i] = fcs_sha2_data_sign_param.key_id;
/* Crypto parameters */
i++;
payload[i] = fcs_sha2_data_sign_param.crypto_param
& INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
i++;
}
/* Data source address and size */
payload[i] = src_addr;
i++;
payload[i] = src_size;
i++;
status = mailbox_send_cmd_async(send_id,
MBOX_FCS_ECDSA_SHA2_DATA_SIGN_REQ,
payload, i, CMD_INDIRECT);
if (is_finalised != 0U) {
memset((void *)&fcs_sha2_data_sign_param, 0,
sizeof(fcs_crypto_service_data));
}
if (status < 0) {
*mbox_error = -status;
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;
}
int intel_fcs_ecdsa_sha2_data_sig_verify_init(uint32_t session_id,
uint32_t context_id, uint32_t key_id,
uint32_t param_size, uint64_t param_data,
uint32_t *mbox_error)
{
return intel_fcs_crypto_service_init(session_id, context_id,
key_id, param_size, param_data,
(void *) &fcs_sha2_data_sig_verify_param,
mbox_error);
}
int intel_fcs_ecdsa_sha2_data_sig_verify_update_finalize(uint32_t session_id,
uint32_t context_id, uint32_t src_addr,
uint32_t src_size, uint64_t dst_addr,
uint32_t *dst_size, uint32_t data_size,
uint8_t is_finalised, uint32_t *mbox_error)
{
int status;
uint32_t i;
uint32_t flag;
uint32_t crypto_header;
uint32_t payload[FCS_ECDSA_SHA2_DATA_SIG_VERIFY_CMD_MAX_WORD_SIZE] = {0U};
uint32_t resp_len;
uintptr_t sig_pubkey_offset;
uint32_t dst_size_check = 0;
if ((dst_size == NULL) || (mbox_error == NULL)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (fcs_sha2_data_sig_verify_param.session_id != session_id ||
fcs_sha2_data_sig_verify_param.context_id != context_id) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (data_size > src_size) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_size_4_bytes_aligned(src_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_8_bytes_aligned(data_size) ||
!is_8_bytes_aligned(src_addr)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
dst_size_check = *dst_size;
if ((dst_size_check > FCS_MAX_DATA_SIZE ||
dst_size_check < FCS_MIN_DATA_SIZE) ||
(src_size > FCS_MAX_DATA_SIZE ||
src_size < FCS_MIN_DATA_SIZE)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
resp_len = *dst_size / MBOX_WORD_BYTE;
/* Prepare crypto header */
flag = 0;
if (fcs_sha2_data_sig_verify_param.is_updated)
fcs_sha2_data_sig_verify_param.crypto_param_size = 0;
else
flag |= FCS_CS_FIELD_FLAG_INIT;
if (is_finalised != 0U)
flag |= FCS_CS_FIELD_FLAG_FINALIZE;
else {
flag |= FCS_CS_FIELD_FLAG_UPDATE;
fcs_sha2_data_sig_verify_param.is_updated = 1;
}
crypto_header = (flag << FCS_CS_FIELD_FLAG_OFFSET) |
fcs_sha2_data_sig_verify_param.crypto_param_size;
/* Prepare command payload */
i = 0;
payload[i] = fcs_sha2_data_sig_verify_param.session_id;
i++;
payload[i] = fcs_sha2_data_sig_verify_param.context_id;
i++;
payload[i] = crypto_header;
i++;
if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
FCS_CS_FIELD_FLAG_INIT) {
payload[i] = fcs_sha2_data_sig_verify_param.key_id;
i++;
/* Crypto parameters */
payload[i] = fcs_sha2_data_sig_verify_param.crypto_param
& INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
i++;
}
/* Data source address and size */
payload[i] = src_addr;
i++;
payload[i] = data_size;
i++;
if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
FCS_CS_FIELD_FLAG_FINALIZE) {
/* Signature + Public Key Data */
sig_pubkey_offset = src_addr + data_size;
if ((i + ((src_size - data_size) / MBOX_WORD_BYTE)) >
FCS_ECDSA_SHA2_DATA_SIG_VERIFY_CMD_MAX_WORD_SIZE) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
memcpy((uint8_t *) &payload[i], (uint8_t *) sig_pubkey_offset,
src_size - data_size);
i += (src_size - data_size) / MBOX_WORD_BYTE;
}
status = mailbox_send_cmd(MBOX_JOB_ID,
MBOX_FCS_ECDSA_SHA2_DATA_SIGN_VERIFY, payload, i,
CMD_CASUAL, (uint32_t *) dst_addr, &resp_len);
if (is_finalised != 0U) {
memset((void *) &fcs_sha2_data_sig_verify_param, 0,
sizeof(fcs_crypto_service_data));
}
if (status < 0) {
*mbox_error = -status;
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;
}
int intel_fcs_ecdsa_sha2_data_sig_verify_smmu_update_finalize(uint32_t session_id,
uint32_t context_id, uint32_t src_addr,
uint32_t src_size, uint64_t dst_addr,
uint32_t *dst_size, uint32_t data_size,
uint8_t is_finalised, uint32_t *mbox_error,
uint32_t *send_id)
{
int status;
uint32_t i;
uint32_t flag;
uint32_t crypto_header;
uint32_t payload[FCS_ECDSA_SHA2_DATA_SIG_VERIFY_CMD_MAX_WORD_SIZE] = {0U};
uint32_t resp_len;
uintptr_t sig_pubkey_offset;
uint32_t dst_size_check = 0;
/*
* Source data must be 4 bytes aligned
* Source address must be 8 bytes aligned
* User data must be 8 bytes aligned
*/
if ((dst_size == NULL) || (mbox_error == NULL) ||
!is_size_4_bytes_aligned(src_size) ||
!is_8_bytes_aligned(src_addr) ||
!is_8_bytes_aligned(data_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (fcs_sha2_data_sig_verify_param.session_id != session_id ||
fcs_sha2_data_sig_verify_param.context_id != context_id) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (data_size > src_size) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
dst_size_check = *dst_size;
if ((dst_size_check > FCS_MAX_DATA_SIZE ||
dst_size_check < FCS_MIN_DATA_SIZE) ||
(src_size > FCS_MAX_DATA_SIZE ||
src_size < FCS_MIN_DATA_SIZE)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
resp_len = *dst_size / MBOX_WORD_BYTE;
/* Prepare crypto header */
flag = 0;
if (fcs_sha2_data_sig_verify_param.is_updated)
fcs_sha2_data_sig_verify_param.crypto_param_size = 0;
else
flag |= FCS_CS_FIELD_FLAG_INIT;
if (is_finalised != 0U)
flag |= FCS_CS_FIELD_FLAG_FINALIZE;
else {
flag |= FCS_CS_FIELD_FLAG_UPDATE;
fcs_sha2_data_sig_verify_param.is_updated = 1;
}
crypto_header = (flag << FCS_CS_FIELD_FLAG_OFFSET) |
fcs_sha2_data_sig_verify_param.crypto_param_size;
/* Prepare command payload */
i = 0;
payload[i] = fcs_sha2_data_sig_verify_param.session_id;
i++;
payload[i] = fcs_sha2_data_sig_verify_param.context_id;
i++;
payload[i] = crypto_header;
i++;
if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
FCS_CS_FIELD_FLAG_INIT) {
payload[i] = fcs_sha2_data_sig_verify_param.key_id;
i++;
/* Crypto parameters */
payload[i] = fcs_sha2_data_sig_verify_param.crypto_param
& INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
i++;
}
/* Data source address and size */
payload[i] = src_addr;
i++;
payload[i] = data_size;
i++;
if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
FCS_CS_FIELD_FLAG_FINALIZE) {
/* Copy mac data to command
* Using dst_addr (physical address) to store sig_pubkey_offset
* sig_pubkey_offset is Signature + Public Key Data
*/
sig_pubkey_offset = dst_addr;
if ((i + ((src_size - data_size) / MBOX_WORD_BYTE)) >
FCS_ECDSA_SHA2_DATA_SIG_VERIFY_CMD_MAX_WORD_SIZE) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
memcpy((uint8_t *) &payload[i], (uint8_t *) sig_pubkey_offset,
src_size - data_size);
memset((void *) dst_addr, 0, *dst_size);
i += (src_size - data_size) / MBOX_WORD_BYTE;
}
status = mailbox_send_cmd_async(send_id,
MBOX_FCS_ECDSA_SHA2_DATA_SIGN_VERIFY,
payload, i, CMD_INDIRECT);
if (is_finalised != 0U) {
memset((void *) &fcs_sha2_data_sig_verify_param, 0,
sizeof(fcs_crypto_service_data));
}
if (status < 0) {
*mbox_error = -status;
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;
}
int intel_fcs_ecdsa_get_pubkey_init(uint32_t session_id, uint32_t context_id,
uint32_t key_id, uint32_t param_size,
uint64_t param_data, uint32_t *mbox_error)
{
return intel_fcs_crypto_service_init(session_id, context_id,
key_id, param_size, param_data,
(void *) &fcs_ecdsa_get_pubkey_param,
mbox_error);
}
int intel_fcs_ecdsa_get_pubkey_finalize(uint32_t session_id, uint32_t context_id,
uint64_t dst_addr, uint32_t *dst_size,
uint32_t *mbox_error)
{
int status;
int i;
uint32_t crypto_header;
uint32_t ret_size;
uint32_t payload[FCS_ECDSA_GET_PUBKEY_MAX_WORD_SIZE] = {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;
}
if (fcs_ecdsa_get_pubkey_param.session_id != session_id ||
fcs_ecdsa_get_pubkey_param.context_id != context_id) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
ret_size = *dst_size / MBOX_WORD_BYTE;
crypto_header = ((FCS_CS_FIELD_FLAG_INIT |
FCS_CS_FIELD_FLAG_UPDATE |
FCS_CS_FIELD_FLAG_FINALIZE) <<
FCS_CS_FIELD_FLAG_OFFSET) |
fcs_ecdsa_get_pubkey_param.crypto_param_size;
i = 0;
/* Prepare command payload */
payload[i] = session_id;
i++;
payload[i] = context_id;
i++;
payload[i] = crypto_header;
i++;
payload[i] = fcs_ecdsa_get_pubkey_param.key_id;
i++;
payload[i] = (uint32_t) fcs_ecdsa_get_pubkey_param.crypto_param &
INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
i++;
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_ECDSA_GET_PUBKEY,
payload, i, CMD_CASUAL,
(uint32_t *) dst_addr, &ret_size);
memset((void *) &fcs_ecdsa_get_pubkey_param, 0,
sizeof(fcs_crypto_service_data));
if (status < 0) {
*mbox_error = -status;
return INTEL_SIP_SMC_STATUS_ERROR;
}
*dst_size = ret_size * MBOX_WORD_BYTE;
flush_dcache_range(dst_addr, *dst_size);
return INTEL_SIP_SMC_STATUS_OK;
}
int intel_fcs_ecdh_request_init(uint32_t session_id, uint32_t context_id,
uint32_t key_id, uint32_t param_size,
uint64_t param_data, uint32_t *mbox_error)
{
return intel_fcs_crypto_service_init(session_id, context_id,
key_id, param_size, param_data,
(void *) &fcs_ecdh_request_param,
mbox_error);
}
int intel_fcs_ecdh_request_finalize(uint32_t session_id, uint32_t context_id,
uint32_t src_addr, uint32_t src_size,
uint64_t dst_addr, uint32_t *dst_size,
uint32_t *mbox_error)
{
int status;
uint32_t i;
uint32_t payload[FCS_ECDH_REQUEST_CMD_MAX_WORD_SIZE] = {0U};
uint32_t resp_len;
uintptr_t pubkey;
uint32_t dst_size_check = 0;
if ((dst_size == NULL) || (mbox_error == NULL)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (fcs_ecdh_request_param.session_id != session_id ||
fcs_ecdh_request_param.context_id != context_id) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_address_in_ddr_range(src_addr, src_size) ||
!is_address_in_ddr_range(dst_addr, *dst_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
dst_size_check = *dst_size;
if ((dst_size_check > FCS_MAX_DATA_SIZE ||
dst_size_check < FCS_MIN_DATA_SIZE) ||
(src_size > FCS_MAX_DATA_SIZE ||
src_size < FCS_MIN_DATA_SIZE)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
resp_len = *dst_size / MBOX_WORD_BYTE;
/* Prepare command payload */
i = 0;
/* Crypto header */
payload[i] = fcs_ecdh_request_param.session_id;
i++;
payload[i] = fcs_ecdh_request_param.context_id;
i++;
payload[i] = fcs_ecdh_request_param.crypto_param_size
& FCS_CS_FIELD_SIZE_MASK;
payload[i] |= (FCS_CS_FIELD_FLAG_INIT | FCS_CS_FIELD_FLAG_UPDATE
| FCS_CS_FIELD_FLAG_FINALIZE)
<< FCS_CS_FIELD_FLAG_OFFSET;
i++;
payload[i] = fcs_ecdh_request_param.key_id;
i++;
/* Crypto parameters */
payload[i] = fcs_ecdh_request_param.crypto_param
& INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
i++;
/* Public key data */
pubkey = src_addr;
if ((i + ((src_size) / MBOX_WORD_BYTE)) >
FCS_ECDH_REQUEST_CMD_MAX_WORD_SIZE) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
memcpy((uint8_t *) &payload[i], (uint8_t *) pubkey, src_size);
i += src_size / MBOX_WORD_BYTE;
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_ECDH_REQUEST,
payload, i, CMD_CASUAL, (uint32_t *) dst_addr,
&resp_len);
memset((void *)&fcs_ecdh_request_param, 0,
sizeof(fcs_crypto_service_data));
if (status < 0) {
*mbox_error = -status;
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;
}
int intel_fcs_aes_crypt_init(uint32_t session_id, uint32_t context_id,
uint32_t key_id, uint64_t param_addr,
uint32_t param_size, uint32_t *mbox_error)
{
/* ptr to get param_addr value */
uint64_t *param_addr_ptr;
param_addr_ptr = (uint64_t *) param_addr;
/*
* Since crypto param size vary between mode.
* Check ECB here and limit to size 12 bytes
*/
if (((*param_addr_ptr & FCS_CRYPTO_BLOCK_MODE_MASK) == FCS_CRYPTO_ECB_MODE) &&
(param_size > FCS_CRYPTO_ECB_BUFFER_SIZE)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
/*
* Since crypto param size vary between mode.
* Check CBC/CTR here and limit to size 28 bytes
*/
if ((((*param_addr_ptr & FCS_CRYPTO_BLOCK_MODE_MASK) == FCS_CRYPTO_CBC_MODE) ||
((*param_addr_ptr & FCS_CRYPTO_BLOCK_MODE_MASK) == FCS_CRYPTO_CTR_MODE)) &&
(param_size > FCS_CRYPTO_CBC_CTR_BUFFER_SIZE)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (mbox_error == NULL) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
memset((void *)&fcs_aes_init_payload, 0U, sizeof(fcs_aes_init_payload));
fcs_aes_init_payload.session_id = session_id;
fcs_aes_init_payload.context_id = context_id;
fcs_aes_init_payload.param_size = param_size;
fcs_aes_init_payload.key_id = key_id;
memcpy((uint8_t *) fcs_aes_init_payload.crypto_param,
(uint8_t *) param_addr, param_size);
fcs_aes_init_payload.is_updated = 0;
*mbox_error = 0;
return INTEL_SIP_SMC_STATUS_OK;
}
int intel_fcs_aes_crypt_update_finalize(uint32_t session_id,
uint32_t context_id, uint64_t src_addr,
uint32_t src_size, uint64_t dst_addr,
uint32_t dst_size, uint8_t is_finalised,
uint32_t *send_id)
{
int status;
int i;
uint32_t flag;
uint32_t crypto_header;
uint32_t fcs_aes_crypt_payload[FCS_AES_CMD_MAX_WORD_SIZE];
if (fcs_aes_init_payload.session_id != session_id ||
fcs_aes_init_payload.context_id != context_id) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if ((!is_8_bytes_aligned(src_addr)) ||
(!is_32_bytes_aligned(src_size)) ||
(!is_address_in_ddr_range(src_addr, src_size))) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if ((!is_8_bytes_aligned(dst_addr)) ||
(!is_32_bytes_aligned(dst_size)) ||
(!is_address_in_ddr_range(dst_addr, dst_size))) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if ((dst_size > FCS_AES_MAX_DATA_SIZE ||
dst_size < FCS_AES_MIN_DATA_SIZE) ||
(src_size > FCS_AES_MAX_DATA_SIZE ||
src_size < FCS_AES_MIN_DATA_SIZE)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
/* Prepare crypto header*/
flag = 0;
if (fcs_aes_init_payload.is_updated) {
fcs_aes_init_payload.param_size = 0;
} else {
flag |= FCS_CS_FIELD_FLAG_INIT;
}
if (is_finalised != 0U) {
flag |= FCS_CS_FIELD_FLAG_FINALIZE;
} else {
flag |= FCS_CS_FIELD_FLAG_UPDATE;
fcs_aes_init_payload.is_updated = 1;
}
crypto_header = (flag << FCS_CS_FIELD_FLAG_OFFSET) |
fcs_aes_init_payload.param_size;
i = 0U;
fcs_aes_crypt_payload[i] = session_id;
i++;
fcs_aes_crypt_payload[i] = context_id;
i++;
fcs_aes_crypt_payload[i] = crypto_header;
i++;
if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
FCS_CS_FIELD_FLAG_INIT) {
fcs_aes_crypt_payload[i] = fcs_aes_init_payload.key_id;
i++;
if ((i + ((fcs_aes_init_payload.param_size) / MBOX_WORD_BYTE)) >
FCS_AES_CMD_MAX_WORD_SIZE) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
memcpy((uint8_t *) &fcs_aes_crypt_payload[i],
(uint8_t *) fcs_aes_init_payload.crypto_param,
fcs_aes_init_payload.param_size);
i += fcs_aes_init_payload.param_size / MBOX_WORD_BYTE;
}
fcs_aes_crypt_payload[i] = (uint32_t) src_addr;
i++;
fcs_aes_crypt_payload[i] = src_size;
i++;
fcs_aes_crypt_payload[i] = (uint32_t) dst_addr;
i++;
fcs_aes_crypt_payload[i] = dst_size;
i++;
status = mailbox_send_cmd_async(send_id, MBOX_FCS_AES_CRYPT_REQ,
fcs_aes_crypt_payload, i,
CMD_INDIRECT);
if (is_finalised != 0U) {
memset((void *)&fcs_aes_init_payload, 0,
sizeof(fcs_aes_init_payload));
}
if (status < 0U) {
return INTEL_SIP_SMC_STATUS_ERROR;
}
return INTEL_SIP_SMC_STATUS_OK;
}