arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_fcs.c
Sieu Mun Tang 7facacec63 feat(intel): single certificate feature enablement
Extend the functionality of FPGA Crypto Service
(FCS) to support FPGA single certificate feature
so that the counter value can be updated with
only one preauthorized certificate

Signed-off-by: Boon Khai Ng <boon.khai.ng@intel.com>
Signed-off-by: Sieu Mun Tang <sieu.mun.tang@intel.com>
Change-Id: Ibde87e4ee46367cf7f27f7bb0172838ab8766340
2022-05-11 10:01:54 +08:00

351 lines
8.1 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"
bool is_size_4_bytes_aligned(uint32_t size)
{
if ((size % MBOX_WORD_BYTE) != 0U) {
return false;
} else {
return true;
}
}
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;
}
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);
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;
fcs_encrypt_payload payload = {
FCS_ENCRYPTION_DATA_0,
src_addr,
src_size,
dst_addr,
dst_size };
load_size = sizeof(payload) / 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;
}
if (!is_size_4_bytes_aligned(src_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
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;
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;
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;
}
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;
}
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_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;
}