#include <string.h>
#include "secure_boot.h"
#include "io_protection_key.h"
#include "basic/atca_basic.h"
static ATCA_STATUS secure_boot_init(secure_boot_parameters* secure_boot_params);
static ATCA_STATUS secure_boot_calc_app_digest(secure_boot_parameters* secure_boot_params);
ATCA_STATUS secure_boot_process(void)
{
ATCA_STATUS status;
secure_boot_parameters secure_boot_params;
uint8_t secure_boot_mode;
bool secure_boot_app_valid = false;
if ((status = secure_boot_init(&secure_boot_params)) != ATCA_SUCCESS)
{
return status;
}
do
{
if ((status = secure_boot_calc_app_digest(&secure_boot_params)) != ATCA_SUCCESS)
{
break;
}
#if (SECURE_BOOT_CONFIGURATION == SECURE_BOOT_CONFIG_FULL_BOTH)
secure_boot_mode = SECUREBOOT_MODE_FULL;
#else
secure_boot_mode = SECUREBOOT_MODE_FULL_STORE;
#endif
#if SECURE_BOOT_UPGRADE_SUPPORT
if (false == secure_boot_check_full_copy_completion())
{
secure_boot_mode = SECUREBOOT_MODE_FULL_COPY;
}
#endif
#if SECURE_BOOT_DIGEST_ENCRYPT_ENABLED
if ((status = host_generate_random_number(secure_boot_params.randomnum)) != ATCA_SUCCESS)
{
return status;
}
if ((status = io_protection_get_key(secure_boot_params.io_protection_key)) != ATCA_SUCCESS)
{
return status;
}
if ((status = atcab_secureboot_mac(secure_boot_mode,
(const uint8_t*)&secure_boot_params.app_digest,
(const uint8_t*)&secure_boot_params.memory_params.signature,
(const uint8_t*)secure_boot_params.randomnum,
(const uint8_t*)secure_boot_params.io_protection_key,
&secure_boot_app_valid)) != ATCA_SUCCESS)
{
break;
}
#else
if ((status = atcab_secureboot(secure_boot_mode,
0,
(const uint8_t*)&secure_boot_params.app_digest,
(const uint8_t*)&secure_boot_params.memory_params.signature,
NULL)) != ATCA_SUCCESS)
{
break;
}
secure_boot_app_valid = true;
#endif
if (!secure_boot_app_valid)
{
status = ATCA_CHECKMAC_VERIFY_FAILED;
break;
}
if ((SECUREBOOT_MODE_FULL_COPY == secure_boot_mode) && ((status = secure_boot_mark_full_copy_completion()) != ATCA_SUCCESS))
{
break;
}
}
while (0);
secure_boot_deinit_memory(&secure_boot_params.memory_params);
return status;
}
static ATCA_STATUS secure_boot_init(secure_boot_parameters* secure_boot_params)
{
ATCA_STATUS status;
uint16_t secure_boot_config;
uint8_t buf[2];
memset((void*)secure_boot_params, 0, sizeof(secure_boot_parameters));
if ((status = atcab_read_bytes_zone(ATCA_ZONE_CONFIG, 0, SECUREBOOTCONFIG_OFFSET, buf, 2)) != ATCA_SUCCESS)
{
return status;
}
secure_boot_config = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
if ((secure_boot_config & SECUREBOOTCONFIG_MODE_MASK) != SECURE_BOOT_CONFIGURATION)
{
return ATCA_GEN_FAIL;
}
if ((status = secure_boot_init_memory(&secure_boot_params->memory_params)) != ATCA_SUCCESS)
{
return status;
}
return ATCA_SUCCESS;
}
static ATCA_STATUS secure_boot_calc_app_digest(secure_boot_parameters* secure_boot_params)
{
ATCA_STATUS status;
uint8_t sha_data[ATCA_SHA256_BLOCK_SIZE];
uint32_t total_data_count = 0;
uint32_t current_data_count;
if ((status = atcac_sw_sha2_256_init(&secure_boot_params->s_sha_context)) != ATCA_SUCCESS)
{
return status;
}
while (total_data_count < secure_boot_params->memory_params.memory_size)
{
current_data_count = sizeof(sha_data);
if ((total_data_count + current_data_count) > secure_boot_params->memory_params.memory_size)
{
current_data_count = secure_boot_params->memory_params.memory_size - total_data_count;
}
if ((status = secure_boot_read_memory(sha_data, ¤t_data_count)) != ATCA_SUCCESS)
{
return status;
}
total_data_count += current_data_count;
if ((status = atcac_sw_sha2_256_update(&secure_boot_params->s_sha_context, sha_data, current_data_count)) != ATCA_SUCCESS)
{
return status;
}
}
if ((status = atcac_sw_sha2_256_finish(&secure_boot_params->s_sha_context, secure_boot_params->app_digest)) != ATCA_SUCCESS)
{
return status;
}
return ATCA_SUCCESS;
}
ATCA_STATUS bind_host_and_secure_element_with_io_protection(uint16_t slot)
{
bool is_locked;
ATCA_STATUS status = ATCA_GEN_FAIL;
uint8_t io_prot_key[ATCA_KEY_SIZE];
do
{
if ((status = atcab_is_slot_locked(slot, &is_locked)) != ATCA_SUCCESS)
{
break;
}
if (is_locked)
{
status = ATCA_GEN_FAIL;
break;
}
if ((status = atcab_random(io_prot_key)) != ATCA_SUCCESS)
{
break;
}
if ((status = atcab_write_zone(ATCA_ZONE_DATA, slot, 0, 0, io_prot_key, ATCA_KEY_SIZE)) != ATCA_SUCCESS)
{
break;
}
if ((status = io_protection_set_key(io_prot_key)) != ATCA_SUCCESS)
{
break;
}
if ((status = atcab_lock_data_slot(slot)) != ATCA_SUCCESS)
{
break;
}
}
while (0);
return status;
}