Skip to content

Commit

Permalink
Libcaliptra fixes
Browse files Browse the repository at this point in the history
- Fixes to checksum calculations for uninitialized cmd and resp buffers
- Adding missing dpe command structs
  • Loading branch information
nquarton authored and jhand2 committed Aug 26, 2024
1 parent 0343880 commit 197246c
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 44 deletions.
46 changes: 24 additions & 22 deletions libcaliptra/examples/generic/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ int rom_test_all_commands(const test_info* info)

// STASH_MEASUREMENT
struct caliptra_stash_measurement_req stash_req = {};
struct caliptra_stash_measurement_resp stash_resp = {};
struct caliptra_stash_measurement_resp stash_resp;

status = caliptra_stash_measurement(&stash_req, &stash_resp, false);

Expand All @@ -199,7 +199,7 @@ int rom_test_all_commands(const test_info* info)
}

// CAPABILITIES
struct caliptra_capabilities_resp cap_resp = {};
struct caliptra_capabilities_resp cap_resp;

status = caliptra_capabilities(&cap_resp, false);

Expand All @@ -212,7 +212,7 @@ int rom_test_all_commands(const test_info* info)
}

// FIPS_VERSION
struct caliptra_fips_version_resp version_resp = {};
struct caliptra_fips_version_resp version_resp;

status = caliptra_fips_version(&version_resp, false);

Expand Down Expand Up @@ -288,7 +288,7 @@ int rt_test_all_commands(const test_info* info)

// GET_IDEV_CERT
struct caliptra_get_idev_cert_req idev_cert_req = {};
struct caliptra_get_idev_cert_resp idev_cert_resp = {};
struct caliptra_get_idev_cert_resp idev_cert_resp;

status = caliptra_get_idev_cert(&idev_cert_req, &idev_cert_resp, false);

Expand All @@ -301,7 +301,7 @@ int rt_test_all_commands(const test_info* info)
}

// GET_IDEV_INFO
struct caliptra_get_idev_info_resp idev_info_resp = {};
struct caliptra_get_idev_info_resp idev_info_resp;

status = caliptra_get_idev_info(&idev_info_resp, false);

Expand All @@ -327,7 +327,7 @@ int rt_test_all_commands(const test_info* info)
}

// GET_LDEV_CERT
struct caliptra_get_ldev_cert_resp ldev_cert_resp = {};
struct caliptra_get_ldev_cert_resp ldev_cert_resp;

status = caliptra_get_ldev_cert(&ldev_cert_resp, false);

Expand All @@ -340,7 +340,7 @@ int rt_test_all_commands(const test_info* info)
}

// GET_FMC_ALIAS_CERT
struct caliptra_get_fmc_alias_cert_resp fmc_alias_cert_resp = {};
struct caliptra_get_fmc_alias_cert_resp fmc_alias_cert_resp;

status = caliptra_get_fmc_alias_cert(&fmc_alias_cert_resp, false);

Expand All @@ -353,7 +353,7 @@ int rt_test_all_commands(const test_info* info)
}

// GET_RT_ALIAS_CERT
struct caliptra_get_rt_alias_cert_resp rt_alias_cert_resp = {};
struct caliptra_get_rt_alias_cert_resp rt_alias_cert_resp;

status = caliptra_get_rt_alias_cert(&rt_alias_cert_resp, false);

Expand Down Expand Up @@ -403,7 +403,7 @@ int rt_test_all_commands(const test_info* info)

// STASH_MEASUREMENT
struct caliptra_stash_measurement_req stash_req = {};
struct caliptra_stash_measurement_resp stash_resp = {};
struct caliptra_stash_measurement_resp stash_resp;

status = caliptra_stash_measurement(&stash_req, &stash_resp, false);

Expand All @@ -416,18 +416,20 @@ int rt_test_all_commands(const test_info* info)
}

// INVOKE_DPE_COMMAND
// Using GET_PROFILE as an example command
// TODO: Coverage of other DPE commands should be added
struct caliptra_invoke_dpe_req dpe_req = {};
struct caliptra_invoke_dpe_resp dpe_resp = {};
struct caliptra_invoke_dpe_resp dpe_resp;

dpe_req.data_size = sizeof(struct dpe_get_profile_cmd);
dpe_req.get_profile_cmd.cmd_hdr.magic = DPE_MAGIC;
dpe_req.get_profile_cmd.cmd_hdr.cmd_id = DPE_GET_PROFILE;
dpe_req.get_profile_cmd.cmd_hdr.profile = 0x2;

status = caliptra_invoke_dpe_command(&dpe_req, &dpe_resp, false);

// Not testing for full success
// Instead, just want to see it give the right DPE-specific error
// This still proves the FW recognizes the message and request data and got to the right DPE code
uint32_t RUNTIME_DPE_COMMAND_DESERIALIZATION_FAILED = 0xe0027;
non_fatal_error = caliptra_read_fw_non_fatal_error();
if (status != MBX_STATUS_FAILED || non_fatal_error != RUNTIME_DPE_COMMAND_DESERIALIZATION_FAILED) {
printf("DPE Command unexpected result/failure: 0x%x\n", status);
if (status) {
printf("DPE Command failed: 0x%x\n", status);
dump_caliptra_error_codes();
failure = 1;
} else {
Expand All @@ -436,7 +438,7 @@ int rt_test_all_commands(const test_info* info)


// FW_INFO
struct caliptra_fw_info_resp fw_info_resp = {};
struct caliptra_fw_info_resp fw_info_resp;

status = caliptra_fw_info(&fw_info_resp, false);

Expand All @@ -463,7 +465,7 @@ int rt_test_all_commands(const test_info* info)

// DPE_GET_TAGGED_TCI
struct caliptra_get_tagged_tci_req get_tagged_tci_req = {};
struct caliptra_get_tagged_tci_resp get_tagged_tci_resp = {};
struct caliptra_get_tagged_tci_resp get_tagged_tci_resp;

status = caliptra_dpe_get_tagged_tci(&get_tagged_tci_req, &get_tagged_tci_resp, false);

Expand All @@ -490,7 +492,7 @@ int rt_test_all_commands(const test_info* info)

// Quote PCRs
struct caliptra_quote_pcrs_req quote_pcrs_req = {};
struct caliptra_quote_pcrs_resp quote_pcrs_resp = {};
struct caliptra_quote_pcrs_resp quote_pcrs_resp;

status = caliptra_quote_pcrs(&quote_pcrs_req, &quote_pcrs_resp, false);

Expand Down Expand Up @@ -534,7 +536,7 @@ int rt_test_all_commands(const test_info* info)
// Certify key extended
int caliptra_certify_key_extended(struct caliptra_certify_key_extended_req *req, struct caliptra_certify_key_extended_resp *resp, bool async);
struct caliptra_certify_key_extended_req certify_key_extended_req = {};
struct caliptra_certify_key_extended_resp certify_key_extended_resp = {};
struct caliptra_certify_key_extended_resp certify_key_extended_resp;

status = caliptra_certify_key_extended(&certify_key_extended_req, &certify_key_extended_resp, false);

Expand All @@ -548,7 +550,7 @@ int rt_test_all_commands(const test_info* info)


// FIPS_VERSION
struct caliptra_fips_version_resp version_resp = {};
struct caliptra_fips_version_resp version_resp;

status = caliptra_fips_version(&version_resp, false);

Expand Down
22 changes: 15 additions & 7 deletions libcaliptra/inc/caliptra_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,8 @@ struct caliptra_capabilities_resp {
uint8_t capabilities[16];
};

// The below fields are placeholders to set up the baseline
// required for communication of DPE commands to Caliptra
// firmware.
// DPE commands

#define DPE_DATA_MAX 512
#define DPE_MAGIC 0x44504543 // "DPEC"

struct dpe_cmd_hdr {
Expand Down Expand Up @@ -254,6 +251,10 @@ struct dpe_resp_hdr {
#endif

// GET_PROFILE
struct dpe_get_profile_cmd {
struct dpe_cmd_hdr cmd_hdr;
};

struct dpe_get_profile_response {
struct dpe_resp_hdr resp_hdr;
uint16_t profile_major_version;
Expand Down Expand Up @@ -344,7 +345,10 @@ struct dpe_rotate_context_handle_response {
struct dpe_destroy_context_cmd {
struct dpe_cmd_hdr cmd_hdr;
uint8_t context_handle[DPE_HANDLE_SIZE];
uint32_t flags;
};

struct dpe_destroy_context_response {
struct dpe_resp_hdr resp_hdr;
};

// GET_CERTIFICATE_CHAIN
Expand All @@ -365,28 +369,32 @@ struct caliptra_invoke_dpe_req {
struct caliptra_req_header hdr;
uint32_t data_size;
union {
struct dpe_cmd_hdr cmd_hdr;
struct dpe_get_profile_cmd get_profile_cmd;
struct dpe_initialize_context_cmd initialize_context_cmd;
struct dpe_derive_context_cmd derive_context_cmd;
struct dpe_certify_key_cmd certify_key_cmd;
struct dpe_sign_cmd sign_cmd;
struct dpe_rotate_context_handle_cmd rotate_context_handle_cmd;
struct dpe_destroy_context_cmd destroy_context_cmd;
struct dpe_get_certificate_chain_cmd get_certificate_chain_cmd;
uint8_t data[DPE_DATA_MAX];
uint8_t data[0];
};
};

struct caliptra_invoke_dpe_resp {
struct caliptra_resp_header cpl;
uint32_t data_size;
union {
struct dpe_resp_hdr resp_hdr;
struct dpe_get_profile_response get_profile_resp;
struct dpe_initialize_context_response initialize_context_resp;
struct dpe_derive_context_response derive_context_resp;
struct dpe_certify_key_response certify_key_resp;
struct dpe_sign_response sign_resp;
struct dpe_rotate_context_handle_response rotate_context_handle_resp;
struct dpe_destroy_context_response destroy_context_resp;
struct dpe_get_certificate_chain_response get_certificate_chain_resp;
uint8_t data[sizeof(struct dpe_certify_key_response)];
uint8_t data[0];
};
};
50 changes: 35 additions & 15 deletions libcaliptra/src/caliptra_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ bool caliptra_ready_for_firmware(void)
*
* Reports if the IDEVID CSR is ready
*
* @return bool True if ready, false otherwise
* @return bool True if ready, false otherwise
*/
bool caliptra_is_csr_ready(void)
{
Expand All @@ -369,7 +369,7 @@ bool caliptra_is_csr_ready(void)
{
return true;
}

return false;
}

Expand Down Expand Up @@ -441,17 +441,22 @@ static int caliptra_mailbox_write_fifo(const struct caliptra_buffer *buffer)
* HELPER - Read a mailbox FIFO into a buffer
*
* @param[out] buffer A pointer to a valid caliptra_buffer struct
* @param[out] bytes_read Pointer to dword to update with the number of bytes read (ignored if nullptr)
*
* @return 0 for success, non-zero for failure (see enum libcaliptra_error)
*/
static int caliptra_mailbox_read_fifo(struct caliptra_buffer *buffer)
static int caliptra_mailbox_read_fifo(struct caliptra_buffer *buffer, uint32_t *bytes_read)
{
uint32_t remaining_len = caliptra_mbox_read_dlen();

// Check that the buffer is not null
if (buffer == NULL)
return INVALID_PARAMS;

if (bytes_read) {
*bytes_read = 0;
}

// Check we have enough room in the buffer
if (buffer->len < remaining_len || !buffer->data)
return INVALID_PARAMS;
Expand All @@ -463,13 +468,19 @@ static int caliptra_mailbox_read_fifo(struct caliptra_buffer *buffer)
{
*data_dw++ = caliptra_mbox_read(MBOX_CSR_MBOX_DATAOUT);
remaining_len -= sizeof(uint32_t);
if (bytes_read) {
*bytes_read += 4;
}
}

// if un-aligned dword reminder...
if (remaining_len)
{
uint32_t data = caliptra_mbox_read(MBOX_CSR_MBOX_DATAOUT);
memcpy(data_dw, &data, remaining_len);
if (bytes_read) {
*bytes_read += remaining_len;
}
}
return 0;
}
Expand Down Expand Up @@ -509,11 +520,17 @@ int caliptra_mailbox_send(uint32_t cmd, const struct caliptra_buffer *mbox_tx_bu
* buffer with a response if applicable
*
* @param[out] mbox_rx_buffer Buffer for the response, NULL if no response is expected
* @param[out] bytes_read Pointer to dword to update with the number of bytes read
*
* @return 0 for success, non-zero for failure (see enum libcaliptra_error)
*/
int caliptra_check_status_get_response(struct caliptra_buffer *mbox_rx_buffer)
int caliptra_check_status_get_response(struct caliptra_buffer *mbox_rx_buffer, uint32_t *bytes_read)
{
// Only called internally, should always have a valid pointer
if (bytes_read == NULL) {
return API_INTERNAL_ERROR;
}

// Check the Mailbox Status
uint32_t mbx_status = caliptra_mbox_read_status();
if (mbx_status == CALIPTRA_MBOX_STATUS_CMD_FAILURE)
Expand All @@ -532,7 +549,7 @@ int caliptra_check_status_get_response(struct caliptra_buffer *mbox_rx_buffer)
}

// Read Buffer
int status = caliptra_mailbox_read_fifo(mbox_rx_buffer);
int status = caliptra_mailbox_read_fifo(mbox_rx_buffer, bytes_read);

// Execute False
caliptra_mbox_write_execute(false);
Expand All @@ -552,18 +569,18 @@ int caliptra_check_status_get_response(struct caliptra_buffer *mbox_rx_buffer)
* HELPER - Verifies the checksum and checks that the FIPS status is approved for the message response
*
* @param[in] buffer Buffer for the full response
* @param[in] buffer_size Size of the full response in bytes
* @param[in] response_size Size of the full response in bytes
*
* @return 0 for success, non-zero for failure (see enum libcaliptra_error)
*/
static inline int check_command_response(const uint8_t *buffer, const size_t buffer_size)
static inline int check_command_response(const uint8_t *buffer, const size_t response_size)
{
if (buffer_size < sizeof(struct caliptra_resp_header)) {
if (response_size < sizeof(struct caliptra_resp_header)) {
return MBX_RESP_NO_HEADER;
}
struct caliptra_resp_header *resp_hdr = (struct caliptra_resp_header*)buffer;

uint32_t calc_checksum = calculate_caliptra_checksum(0, buffer + sizeof(uint32_t), buffer_size - sizeof(uint32_t));
uint32_t calc_checksum = calculate_caliptra_checksum(0, buffer + sizeof(uint32_t), response_size - sizeof(uint32_t));

bool checksum_valid = !(resp_hdr->chksum - calc_checksum);
bool fips_approved = (resp_hdr->fips_status == FIPS_STATUS_APPROVED);
Expand Down Expand Up @@ -653,6 +670,8 @@ static int pack_and_execute_command(struct parcel *parcel, bool async)
};

// Calculate and populate the checksum field
// Clear the checksum field before calculating
*((caliptra_checksum*)tx_buf.data) = 0x0;
*((caliptra_checksum*)tx_buf.data) = calculate_caliptra_checksum(parcel->command, tx_buf.data, tx_buf.len);

return caliptra_mailbox_execute(parcel->command, &tx_buf, &rx_buf, async);
Expand Down Expand Up @@ -697,7 +716,8 @@ int caliptra_complete()
g_mbox_pending_rx_buffer = (struct caliptra_buffer){NULL, 0};

// Complete the transaction and read back a response if applicable
int status = caliptra_check_status_get_response(&rx_buffer);
uint32_t bytes_read = 0;
int status = caliptra_check_status_get_response(&rx_buffer, &bytes_read);

if (status)
{
Expand All @@ -706,7 +726,7 @@ int caliptra_complete()

// Verify the header data from the response
if (rx_buffer.data != NULL) {
return check_command_response(rx_buffer.data, rx_buffer.len);
return check_command_response(rx_buffer.data, bytes_read);
}

return 0;
Expand Down Expand Up @@ -1088,7 +1108,7 @@ int caliptra_capabilities(struct caliptra_capabilities_resp *resp, bool async)
return pack_and_execute_command(&p, async);
}

int caliptra_retrieve_idevid_csr(struct caliptra_buffer* caliptra_idevid_csr)
int caliptra_retrieve_idevid_csr(struct caliptra_buffer* caliptra_idevid_csr)
{
if (!caliptra_idevid_csr) {
return INVALID_PARAMS;
Expand All @@ -1098,10 +1118,10 @@ int caliptra_retrieve_idevid_csr(struct caliptra_buffer* caliptra_idevid_csr)
return IDEV_CSR_NOT_READY;
}

return caliptra_mailbox_read_fifo(caliptra_idevid_csr);
return caliptra_mailbox_read_fifo(caliptra_idevid_csr, NULL);
}

void caliptra_req_idev_csr_start()
void caliptra_req_idev_csr_start()
{
uint32_t dbg_manuf_serv_req;

Expand All @@ -1111,7 +1131,7 @@ void caliptra_req_idev_csr_start()
caliptra_write_u32(CALIPTRA_TOP_REG_GENERIC_AND_FUSE_REG_CPTRA_DBG_MANUF_SERVICE_REG, dbg_manuf_serv_req | 0x01);
}

void caliptra_req_idev_csr_complete()
void caliptra_req_idev_csr_complete()
{
uint32_t dbg_manuf_serv_req;

Expand Down

0 comments on commit 197246c

Please sign in to comment.