#include "atca_basic.h"
#include "atca_execution.h"
#include "host/atca_host.h"
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
ATCA_STATUS atcab_priv_write(uint16_t key_id, const uint8_t priv_key[36], uint16_t write_key_id, const uint8_t write_key[32])
{
uint8_t num_in[NONCE_NUMIN_SIZE] = { 0 };
#else
ATCA_STATUS atcab_priv_write(uint16_t key_id, const uint8_t priv_key[36], uint16_t write_key_id, const uint8_t write_key[32], const uint8_t num_in[NONCE_NUMIN_SIZE])
{
#endif
ATCAPacket packet;
ATCACommand ca_cmd = _gDevice->mCommands;
ATCA_STATUS status = ATCA_GEN_FAIL;
atca_nonce_in_out_t nonce_params;
atca_gen_dig_in_out_t gen_dig_param;
atca_write_mac_in_out_t host_mac_param;
atca_temp_key_t temp_key;
uint8_t serial_num[32]; uint8_t rand_out[RANDOM_NUM_SIZE] = { 0 };
uint8_t cipher_text[36] = { 0 };
uint8_t host_mac[MAC_SIZE] = { 0 };
uint8_t other_data[4] = { 0 };
if (key_id > 15 || priv_key == NULL)
{
return ATCA_BAD_PARAM;
}
do
{
if (write_key == NULL)
{
packet.param1 = 0x00; packet.param2 = key_id; memcpy(&packet.data[0], priv_key, 36); memset(&packet.data[36], 0, 32); }
else
{
if ((status = atcab_read_zone(ATCA_ZONE_CONFIG, 0, 0, 0, serial_num, 32)) != ATCA_SUCCESS)
{
break;
}
memmove(&serial_num[4], &serial_num[8], 5);
if ((status = atcab_nonce_rand(num_in, rand_out)) != ATCA_SUCCESS)
{
break;
}
memset(&temp_key, 0, sizeof(temp_key));
memset(&nonce_params, 0, sizeof(nonce_params));
nonce_params.mode = NONCE_MODE_SEED_UPDATE;
nonce_params.zero = 0;
nonce_params.num_in = &num_in[0];
nonce_params.rand_out = rand_out;
nonce_params.temp_key = &temp_key;
if ((status = atcah_nonce(&nonce_params)) != ATCA_SUCCESS)
{
break;
}
other_data[0] = ATCA_GENDIG;
other_data[1] = GENDIG_ZONE_DATA;
other_data[2] = (uint8_t)(write_key_id);
other_data[3] = (uint8_t)(write_key_id >> 8);
if ((status = atcab_gendig(GENDIG_ZONE_DATA, write_key_id, other_data, sizeof(other_data))) != ATCA_SUCCESS)
{
break;
}
memset(&gen_dig_param, 0, sizeof(gen_dig_param));
gen_dig_param.zone = GENDIG_ZONE_DATA;
gen_dig_param.sn = serial_num;
gen_dig_param.key_id = write_key_id;
gen_dig_param.is_key_nomac = false;
gen_dig_param.stored_value = write_key;
gen_dig_param.other_data = other_data;
gen_dig_param.temp_key = &temp_key;
if ((status = atcah_gen_dig(&gen_dig_param)) != ATCA_SUCCESS)
{
break;
}
memset(&host_mac_param, 0, sizeof(host_mac_param));
host_mac_param.zone = PRIVWRITE_MODE_ENCRYPT;
host_mac_param.key_id = key_id;
host_mac_param.sn = serial_num;
host_mac_param.input_data = &priv_key[0];
host_mac_param.encrypted_data = cipher_text;
host_mac_param.auth_mac = host_mac;
host_mac_param.temp_key = &temp_key;
if ((status = atcah_privwrite_auth_mac(&host_mac_param)) != ATCA_SUCCESS)
{
break;
}
packet.param1 = PRIVWRITE_MODE_ENCRYPT; packet.param2 = key_id; memcpy(&packet.data[0], cipher_text, sizeof(cipher_text));
memcpy(&packet.data[sizeof(cipher_text)], host_mac, sizeof(host_mac));
}
if ((status = atPrivWrite(ca_cmd, &packet)) != ATCA_SUCCESS)
{
break;
}
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
{
break;
}
}
while (0);
return status;
}