#include "atca_host.h"
#include "crypto/atca_crypto_sw_sha2.h"
uint8_t *atcah_include_data(struct atca_include_data_in_out *param)
{
if (param->mode & MAC_MODE_INCLUDE_OTP_88)
{
memcpy(param->p_temp, param->otp, 11); param->p_temp += 11;
}
else
{
if (param->mode & MAC_MODE_INCLUDE_OTP_64)
{
memcpy(param->p_temp, param->otp, 8); }
else
{
memset(param->p_temp, 0, 8); }
param->p_temp += 8;
memset(param->p_temp, 0, 3); param->p_temp += 3;
}
*param->p_temp++ = param->sn[8];
if (param->mode & MAC_MODE_INCLUDE_SN)
{
memcpy(param->p_temp, ¶m->sn[4], 4); }
else
{
memset(param->p_temp, 0, 4); }
param->p_temp += 4;
*param->p_temp++ = param->sn[0];
*param->p_temp++ = param->sn[1];
if (param->mode & MAC_MODE_INCLUDE_SN)
{
memcpy(param->p_temp, ¶m->sn[2], 2); }
else
{
memset(param->p_temp, 0, 2); }
param->p_temp += 2;
return param->p_temp;
}
ATCA_STATUS atcah_nonce(struct atca_nonce_in_out *param)
{
uint8_t temporary[ATCA_MSG_SIZE_NONCE];
uint8_t *p_temp;
uint8_t calc_mode = param->mode & NONCE_MODE_MASK;
if (param->temp_key == NULL || param->num_in == NULL)
{
return ATCA_BAD_PARAM;
}
if ((calc_mode == NONCE_MODE_SEED_UPDATE) || (calc_mode == NONCE_MODE_NO_SEED_UPDATE))
{
if (param->rand_out == NULL)
{
return ATCA_BAD_PARAM;
}
if ((param->zero & NONCE_ZERO_CALC_MASK) == NONCE_ZERO_CALC_TEMPKEY)
{
memcpy(param->temp_key->value, param->rand_out, 32);
}
else
{
p_temp = temporary;
memcpy(p_temp, param->rand_out, RANDOM_NUM_SIZE);
p_temp += RANDOM_NUM_SIZE;
memcpy(p_temp, param->num_in, NONCE_NUMIN_SIZE);
p_temp += NONCE_NUMIN_SIZE;
*p_temp++ = ATCA_NONCE;
*p_temp++ = param->mode;
*p_temp++ = 0x00;
atcac_sw_sha2_256(temporary, ATCA_MSG_SIZE_NONCE, param->temp_key->value);
param->temp_key->source_flag = 0; param->temp_key->key_id = 0;
param->temp_key->gen_dig_data = 0;
param->temp_key->no_mac_flag = 0;
param->temp_key->valid = 1;
}
param->temp_key->is_64 = 0;
}
else if ((param->mode & NONCE_MODE_MASK) == NONCE_MODE_PASSTHROUGH)
{
if ((param->mode & NONCE_MODE_TARGET_MASK) == NONCE_MODE_TARGET_TEMPKEY)
{
if ((param->mode & NONCE_MODE_INPUT_LEN_MASK) == NONCE_MODE_INPUT_LEN_64)
{
memcpy(param->temp_key->value, param->num_in, 64);
param->temp_key->is_64 = 1;
}
else
{
memcpy(param->temp_key->value, param->num_in, 32);
param->temp_key->is_64 = 0;
}
param->temp_key->source_flag = 1; param->temp_key->key_id = 0;
param->temp_key->gen_dig_data = 0;
param->temp_key->no_mac_flag = 0;
param->temp_key->valid = 1;
}
else {
param->temp_key->source_flag = 1; param->temp_key->key_id = 0;
param->temp_key->gen_dig_data = 0;
param->temp_key->no_mac_flag = 0;
param->temp_key->valid = 0;
}
}
else
{
return ATCA_BAD_PARAM;
}
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_io_decrypt(struct atca_io_decrypt_in_out *param)
{
atcac_sha2_256_ctx ctx;
uint8_t key[ATCA_KEY_SIZE];
size_t block = 0;
int i;
if (param == NULL || param->io_key == NULL || param->out_nonce == NULL || param->data == NULL)
{
return ATCA_BAD_PARAM;
}
if (param->data_size % ATCA_BLOCK_SIZE != 0)
{
return ATCA_BAD_PARAM;
}
for (block = 0; block < param->data_size / ATCA_BLOCK_SIZE; block++)
{
atcac_sw_sha2_256_init(&ctx);
atcac_sw_sha2_256_update(&ctx, param->io_key, 32);
atcac_sw_sha2_256_update(&ctx, ¶m->out_nonce[block * 16], 16);
atcac_sw_sha2_256_finish(&ctx, key);
for (i = 0; i < ATCA_BLOCK_SIZE; i++)
{
param->data[block * ATCA_BLOCK_SIZE + i] ^= key[i];
}
}
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_verify_mac(atca_verify_mac_in_out_t *param)
{
uint8_t verify_mode = (param->mode & VERIFY_MODE_MASK);
uint8_t verify_source = (param->mode & VERIFY_MODE_SOURCE_MASK);
atcac_sha2_256_ctx ctx;
uint8_t message[32];
const uint8_t* nonce = NULL;
uint8_t input_params[4];
const uint8_t sign_opcode = ATCA_SIGN;
if (param->signature == NULL || param->msg_dig_buf == NULL || param->io_key == NULL)
{
return ATCA_BAD_PARAM;
}
if (verify_mode == VERIFY_MODE_VALIDATE || verify_mode == VERIFY_MODE_INVALIDATE)
{
if (param->other_data == NULL || param->temp_key == NULL || param->sn == NULL)
{
return ATCA_BAD_PARAM;
}
atcac_sw_sha2_256_init(&ctx);
atcac_sw_sha2_256_update(&ctx, param->temp_key->value, 32);
atcac_sw_sha2_256_update(&ctx, &sign_opcode, 1);
atcac_sw_sha2_256_update(&ctx, ¶m->other_data[0], 10);
atcac_sw_sha2_256_update(&ctx, ¶m->sn[8], 1);
atcac_sw_sha2_256_update(&ctx, ¶m->other_data[10], 4);
atcac_sw_sha2_256_update(&ctx, ¶m->sn[0], 2);
atcac_sw_sha2_256_update(&ctx, ¶m->other_data[14], 5);
atcac_sw_sha2_256_finish(&ctx, message);
}
else if (verify_source == VERIFY_MODE_SOURCE_MSGDIGBUF)
{
memcpy(message, param->msg_dig_buf, 32);
}
else
{
if (param->temp_key == NULL)
{
return ATCA_BAD_PARAM;
}
memcpy(message, param->temp_key->value, 32);
}
if (verify_source == VERIFY_MODE_SOURCE_MSGDIGBUF)
{
nonce = ¶m->msg_dig_buf[32]; }
else
{
nonce = ¶m->msg_dig_buf[0];
}
atcac_sw_sha2_256_init(&ctx);
atcac_sw_sha2_256_update(&ctx, param->io_key, ATCA_KEY_SIZE); atcac_sw_sha2_256_update(&ctx, message, 32); atcac_sw_sha2_256_update(&ctx, nonce, 32); atcac_sw_sha2_256_update(&ctx, param->signature, 64);
input_params[0] = ATCA_VERIFY; input_params[1] = param->mode; input_params[2] = (uint8_t)(param->key_id >> 0); input_params[3] = (uint8_t)(param->key_id >> 8); atcac_sw_sha2_256_update(&ctx, input_params, sizeof(input_params));
atcac_sw_sha2_256_finish(&ctx, param->mac);
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_secureboot_enc(atca_secureboot_enc_in_out_t* param)
{
atcac_sha2_256_ctx ctx;
size_t i;
if (param->digest == NULL || param->temp_key == NULL || param->hashed_key == NULL || param->io_key == NULL || param->digest_enc == NULL)
{
return ATCA_BAD_PARAM;
}
atcac_sw_sha2_256_init(&ctx);
atcac_sw_sha2_256_update(&ctx, param->io_key, ATCA_KEY_SIZE);
atcac_sw_sha2_256_update(&ctx, param->temp_key->value, ATCA_KEY_SIZE);
atcac_sw_sha2_256_finish(&ctx, param->hashed_key);
for (i = 0; i < SECUREBOOT_DIGEST_SIZE; i++)
{
param->digest_enc[i] = param->digest[i] ^ param->hashed_key[i];
}
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_secureboot_mac(atca_secureboot_mac_in_out_t *param)
{
atcac_sha2_256_ctx ctx;
uint8_t input_params[4];
if (param->hashed_key == NULL || param->digest == NULL || param->mac == NULL)
{
return ATCA_BAD_PARAM;
}
atcac_sw_sha2_256_init(&ctx);
atcac_sw_sha2_256_update(&ctx, param->hashed_key, ATCA_KEY_SIZE);
atcac_sw_sha2_256_update(&ctx, param->digest, SECUREBOOT_DIGEST_SIZE);
if (!((param->mode & SECUREBOOT_MODE_MASK) == SECUREBOOT_MODE_FULL_STORE &&
(param->secure_boot_config & SECUREBOOTCONFIG_MODE_MASK) == SECUREBOOTCONFIG_MODE_FULL_DIG))
{
if (param->signature == NULL)
{
return ATCA_BAD_PARAM;
}
atcac_sw_sha2_256_update(&ctx, param->signature, SECUREBOOT_SIGNATURE_SIZE);
}
input_params[0] = ATCA_SECUREBOOT; input_params[1] = param->mode; input_params[2] = (uint8_t)(param->param2 >> 0); input_params[3] = (uint8_t)(param->param2 >> 8); atcac_sw_sha2_256_update(&ctx, input_params, sizeof(input_params));
atcac_sw_sha2_256_finish(&ctx, param->mac);
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_mac(struct atca_mac_in_out *param)
{
uint8_t temporary[ATCA_MSG_SIZE_MAC];
uint8_t *p_temp;
struct atca_include_data_in_out include_data;
include_data.otp = param->otp;
include_data.sn = param->sn;
include_data.mode = param->mode;
if (!param->response
|| (param->mode & ~MAC_MODE_MASK)
|| (!(param->mode & MAC_MODE_BLOCK1_TEMPKEY) && !param->key)
|| (!(param->mode & MAC_MODE_BLOCK2_TEMPKEY) && !param->challenge)
|| ((param->mode & MAC_MODE_USE_TEMPKEY_MASK) && !param->temp_key)
|| (((param->mode & MAC_MODE_INCLUDE_OTP_64) || (param->mode & MAC_MODE_INCLUDE_OTP_88)) && !param->otp)
|| ((param->mode & MAC_MODE_INCLUDE_SN) && !param->sn)
)
{
return ATCA_BAD_PARAM;
}
if (((param->mode & MAC_MODE_USE_TEMPKEY_MASK) != 0)
&& (param->temp_key->no_mac_flag || (param->temp_key->valid != 1)
|| (!(param->mode & MAC_MODE_SOURCE_FLAG_MATCH) != !(param->temp_key->source_flag)))
)
{
param->temp_key->valid = 0;
return ATCA_EXECUTION_ERROR;
}
p_temp = temporary;
memcpy(p_temp, param->mode & MAC_MODE_BLOCK1_TEMPKEY ? param->temp_key->value : param->key, ATCA_KEY_SIZE); p_temp += ATCA_KEY_SIZE;
memcpy(p_temp, param->mode & MAC_MODE_BLOCK2_TEMPKEY ? param->temp_key->value : param->challenge, ATCA_KEY_SIZE); p_temp += ATCA_KEY_SIZE;
*p_temp++ = ATCA_MAC;
*p_temp++ = param->mode;
*p_temp++ = param->key_id & 0xFF;
*p_temp++ = (param->key_id >> 8) & 0xFF;
include_data.p_temp = p_temp;
atcah_include_data(&include_data);
atcac_sw_sha2_256(temporary, ATCA_MSG_SIZE_MAC, param->response);
if (param->temp_key)
{
param->temp_key->valid = 0;
}
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_check_mac(struct atca_check_mac_in_out *param)
{
uint8_t msg[ATCA_MSG_SIZE_MAC];
bool is_temp_key_req = false;
if (param == NULL || param->other_data == NULL || param->sn == NULL || param->client_resp == NULL)
{
return ATCA_BAD_PARAM;
}
if ((param->mode & CHECKMAC_MODE_BLOCK1_TEMPKEY) || (param->mode & CHECKMAC_MODE_BLOCK2_TEMPKEY))
{
is_temp_key_req = true; }
else if ((param->mode == 0x01 || param->mode == 0x05) && param->target_key != NULL)
{
is_temp_key_req = true;
}
if (is_temp_key_req && param->temp_key == NULL)
{
return ATCA_BAD_PARAM;
}
if (!(param->mode & CHECKMAC_MODE_BLOCK1_TEMPKEY) && param->slot_key == NULL)
{
return ATCA_BAD_PARAM;
}
if (!(param->mode & CHECKMAC_MODE_BLOCK2_TEMPKEY) && param->client_chal == NULL)
{
return ATCA_BAD_PARAM;
}
if ((param->mode & CHECKMAC_MODE_INCLUDE_OTP_64) && param->otp == NULL)
{
return ATCA_BAD_PARAM;
}
if ((param->mode & CHECKMAC_MODE_BLOCK1_TEMPKEY) || (param->mode & CHECKMAC_MODE_BLOCK2_TEMPKEY))
{
if (!param->temp_key->valid)
{
return ATCA_EXECUTION_ERROR; }
if (((param->mode >> 2) & 0x01) != param->temp_key->source_flag)
{
return ATCA_EXECUTION_ERROR; }
}
memset(msg, 0, sizeof(msg));
if (param->mode & CHECKMAC_MODE_BLOCK1_TEMPKEY)
{
memcpy(&msg[0], param->temp_key->value, 32);
}
else
{
memcpy(&msg[0], param->slot_key, 32);
}
if (param->mode & CHECKMAC_MODE_BLOCK2_TEMPKEY)
{
memcpy(&msg[32], param->temp_key->value, 32);
}
else
{
memcpy(&msg[32], param->client_chal, 32);
}
memcpy(&msg[64], ¶m->other_data[0], 4);
if (param->mode & CHECKMAC_MODE_INCLUDE_OTP_64)
{
memcpy(&msg[68], param->otp, 8);
}
memcpy(&msg[76], ¶m->other_data[4], 3);
msg[79] = param->sn[8];
memcpy(&msg[80], ¶m->other_data[7], 4);
memcpy(&msg[84], ¶m->sn[0], 2);
memcpy(&msg[86], ¶m->other_data[11], 2);
atcac_sw_sha2_256(msg, sizeof(msg), param->client_resp);
if ((param->mode == 0x01 || param->mode == 0x05) && param->target_key != NULL)
{
memcpy(param->temp_key->value, param->target_key, ATCA_KEY_SIZE);
param->temp_key->gen_dig_data = 0;
param->temp_key->source_flag = 1;
param->temp_key->valid = 1;
}
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_hmac(struct atca_hmac_in_out *param)
{
struct atca_include_data_in_out include_data;
uint8_t temporary[HMAC_BLOCK_SIZE + ATCA_MSG_SIZE_HMAC];
uint8_t i = 0;
uint8_t *p_temp = NULL;
if (!param->response || !param->key || !param->temp_key
|| (param->mode & ~HMAC_MODE_MASK)
|| (((param->mode & MAC_MODE_INCLUDE_OTP_64) || (param->mode & MAC_MODE_INCLUDE_OTP_88)) && !param->otp)
|| (!param->sn)
)
{
return ATCA_BAD_PARAM;
}
if ( param->temp_key->no_mac_flag || (param->temp_key->valid != 1)
|| (!(param->mode & MAC_MODE_SOURCE_FLAG_MATCH) != !(param->temp_key->source_flag))
)
{
param->temp_key->valid = 0;
return ATCA_EXECUTION_ERROR;
}
p_temp = temporary;
for (i = 0; i < ATCA_KEY_SIZE; i++)
{
*p_temp++ = param->key[i] ^ 0x36;
}
memset(p_temp, 0x36, HMAC_BLOCK_SIZE - ATCA_KEY_SIZE);
p_temp += HMAC_BLOCK_SIZE - ATCA_KEY_SIZE;
memset(p_temp, 0, ATCA_KEY_SIZE);
p_temp += ATCA_KEY_SIZE;
memcpy(p_temp, param->temp_key->value, ATCA_KEY_SIZE);
p_temp += ATCA_KEY_SIZE;
*p_temp++ = ATCA_HMAC;
*p_temp++ = param->mode;
*p_temp++ = (uint8_t)(param->key_id >> 0);
*p_temp++ = (uint8_t)(param->key_id >> 8);
include_data.otp = param->otp;
include_data.sn = param->sn;
include_data.mode = param->mode;
include_data.p_temp = p_temp;
atcah_include_data(&include_data);
atcac_sw_sha2_256(temporary, HMAC_BLOCK_SIZE + ATCA_MSG_SIZE_HMAC, param->response);
p_temp = temporary;
for (i = 0; i < ATCA_KEY_SIZE; i++)
{
*p_temp++ = param->key[i] ^ 0x5C;
}
memset(p_temp, 0x5C, HMAC_BLOCK_SIZE - ATCA_KEY_SIZE);
p_temp += HMAC_BLOCK_SIZE - ATCA_KEY_SIZE;
memcpy(p_temp, param->response, ATCA_SHA_DIGEST_SIZE);
p_temp += ATCA_SHA_DIGEST_SIZE;
atcac_sw_sha2_256(temporary, HMAC_BLOCK_SIZE + ATCA_SHA_DIGEST_SIZE, param->response);
param->temp_key->valid = 0;
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_gen_dig(struct atca_gen_dig_in_out *param)
{
uint8_t temporary[ATCA_MSG_SIZE_GEN_DIG];
uint8_t *p_temp;
if (param->sn == NULL || param->temp_key == NULL)
{
return ATCA_BAD_PARAM;
}
if ((param->zone <= GENDIG_ZONE_DATA) && (param->stored_value == NULL))
{
return ATCA_BAD_PARAM; }
if ((param->zone == GENDIG_ZONE_SHARED_NONCE || (param->zone == GENDIG_ZONE_DATA && param->is_key_nomac)) && param->other_data == NULL)
{
return ATCA_BAD_PARAM; }
if (param->zone > 5)
{
return ATCA_BAD_PARAM;
}
p_temp = temporary;
if (param->zone == GENDIG_ZONE_SHARED_NONCE)
{
if (param->key_id & 0x8000)
{
memcpy(p_temp, param->temp_key->value, ATCA_KEY_SIZE); }
else
{
memcpy(p_temp, param->other_data, ATCA_KEY_SIZE);
}
}
else if (param->zone == GENDIG_ZONE_COUNTER || param->zone == GENDIG_ZONE_KEY_CONFIG)
{
memset(p_temp, 0x00, ATCA_KEY_SIZE);
}
else
{
memcpy(p_temp, param->stored_value, ATCA_KEY_SIZE);
}
p_temp += ATCA_KEY_SIZE;
if (param->zone == GENDIG_ZONE_DATA && param->is_key_nomac)
{
memcpy(p_temp, param->other_data, 4);
p_temp += 4;
}
else
{
*p_temp++ = ATCA_GENDIG;
*p_temp++ = param->zone;
*p_temp++ = (uint8_t)(param->key_id & 0xFF);
if (param->zone == GENDIG_ZONE_SHARED_NONCE)
{
*p_temp++ = 0;
}
else
{
*p_temp++ = (uint8_t)(param->key_id >> 8);
}
}
*p_temp++ = param->sn[8];
*p_temp++ = param->sn[0];
*p_temp++ = param->sn[1];
if (param->zone == GENDIG_ZONE_COUNTER)
{
*p_temp++ = 0;
*p_temp++ = (uint8_t)(param->counter & 0xFF); *p_temp++ = (uint8_t)(param->counter >> 8);
*p_temp++ = (uint8_t)(param->counter >> 16);
*p_temp++ = (uint8_t)(param->counter >> 24);
memset(p_temp, 0x00, 20); p_temp += 20;
}
else if (param->zone == GENDIG_ZONE_KEY_CONFIG)
{
*p_temp++ = 0;
*p_temp++ = param->slot_conf & 0xFF; *p_temp++ = (uint8_t)(param->slot_conf >> 8);
*p_temp++ = param->key_conf & 0xFF;
*p_temp++ = (uint8_t)(param->key_conf >> 8);
*p_temp++ = param->slot_locked;
memset(p_temp, 0x00, 19); p_temp += 19;
}
else
{
memset(p_temp, 0, ATCA_GENDIG_ZEROS_SIZE); p_temp += ATCA_GENDIG_ZEROS_SIZE;
}
if (param->zone == GENDIG_ZONE_SHARED_NONCE && (param->key_id & 0x8000))
{
memcpy(p_temp, param->other_data, ATCA_KEY_SIZE); p_temp += ATCA_KEY_SIZE;
}
else
{
memcpy(p_temp, param->temp_key->value, ATCA_KEY_SIZE); p_temp += ATCA_KEY_SIZE;
}
atcac_sw_sha2_256(temporary, (p_temp - temporary), param->temp_key->value);
param->temp_key->valid = 1;
if ((param->zone == GENDIG_ZONE_DATA) && (param->key_id <= 15))
{
param->temp_key->gen_dig_data = 1;
param->temp_key->key_id = (param->key_id & 0xF); if (param->is_key_nomac == 1)
{
param->temp_key->no_mac_flag = 1;
}
}
else
{
param->temp_key->gen_dig_data = 0;
param->temp_key->key_id = 0;
}
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_gen_mac(struct atca_gen_dig_in_out *param)
{
uint8_t temporary[ATCA_MSG_SIZE_GEN_DIG];
uint8_t *p_temp;
if (!param->stored_value || !param->temp_key)
{
return ATCA_BAD_PARAM;
}
if ( param->temp_key->no_mac_flag || (param->temp_key->valid != 1)
)
{
param->temp_key->valid = 0;
return ATCA_EXECUTION_ERROR;
}
p_temp = temporary;
memcpy(p_temp, param->temp_key->value, ATCA_KEY_SIZE);
p_temp += ATCA_KEY_SIZE;
*p_temp++ = ATCA_WRITE;
*p_temp++ = param->zone;
*p_temp++ = param->key_id & 0xFF;
*p_temp++ = (param->key_id >> 8) & 0xFF;
*p_temp++ = param->sn[8];
*p_temp++ = param->sn[0];
*p_temp++ = param->sn[1];
memset(p_temp, 0, ATCA_GENDIG_ZEROS_SIZE);
p_temp += ATCA_GENDIG_ZEROS_SIZE;
memcpy(p_temp, param->stored_value, ATCA_KEY_SIZE);
atcac_sw_sha2_256(temporary, ATCA_MSG_SIZE_GEN_DIG, param->temp_key->value);
param->temp_key->valid = 1;
if ((param->zone == GENDIG_ZONE_DATA) && (param->key_id <= 15))
{
param->temp_key->gen_dig_data = 1;
param->temp_key->key_id = (param->key_id & 0xF); }
else
{
param->temp_key->gen_dig_data = 0;
param->temp_key->key_id = 0;
}
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_write_auth_mac(struct atca_write_mac_in_out *param)
{
uint8_t mac_input[ATCA_MSG_SIZE_ENCRYPT_MAC];
uint8_t i;
uint8_t *p_temp;
if (!param->input_data || !param->temp_key)
{
return ATCA_BAD_PARAM;
}
if ( param->temp_key->no_mac_flag || (param->temp_key->valid != 1)
)
{
param->temp_key->valid = 0;
return ATCA_EXECUTION_ERROR;
}
for (i = 0; i < 32; i++)
{
param->encrypted_data[i] = param->input_data[i] ^ param->temp_key->value[i];
}
if (param->auth_mac)
{
p_temp = mac_input;
memcpy(p_temp, param->temp_key->value, ATCA_KEY_SIZE);
p_temp += ATCA_KEY_SIZE;
*p_temp++ = ATCA_WRITE;
*p_temp++ = param->zone;
*p_temp++ = param->key_id & 0xFF;
*p_temp++ = (param->key_id >> 8) & 0xFF;
*p_temp++ = param->sn[8];
*p_temp++ = param->sn[0];
*p_temp++ = param->sn[1];
memset(p_temp, 0, ATCA_WRITE_MAC_ZEROS_SIZE);
p_temp += ATCA_WRITE_MAC_ZEROS_SIZE;
memcpy(p_temp, param->input_data, ATCA_KEY_SIZE);
atcac_sw_sha2_256(mac_input, sizeof(mac_input), param->auth_mac);
}
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_privwrite_auth_mac(struct atca_write_mac_in_out *param)
{
uint8_t mac_input[ATCA_MSG_SIZE_PRIVWRITE_MAC];
uint8_t i = 0;
uint8_t *p_temp = NULL;
uint8_t session_key2[32];
if (!param->input_data || !param->temp_key)
{
return ATCA_BAD_PARAM;
}
if ( param->temp_key->no_mac_flag || (param->temp_key->valid != 1)
)
{
param->temp_key->valid = 0;
return ATCA_EXECUTION_ERROR;
}
for (i = 0; i < 32; i++)
{
param->encrypted_data[i] = param->input_data[i] ^ param->temp_key->value[i];
}
atcac_sw_sha2_256(param->temp_key->value, 32, session_key2);
for (i = 32; i < 36; i++)
{
param->encrypted_data[i] = param->input_data[i] ^ session_key2[i - 32];
}
if (param->auth_mac)
{
p_temp = mac_input;
memcpy(p_temp, param->temp_key->value, ATCA_KEY_SIZE);
p_temp += ATCA_KEY_SIZE;
*p_temp++ = ATCA_PRIVWRITE;
*p_temp++ = param->zone;
*p_temp++ = param->key_id & 0xFF;
*p_temp++ = (param->key_id >> 8) & 0xFF;
*p_temp++ = param->sn[8];
*p_temp++ = param->sn[0];
*p_temp++ = param->sn[1];
memset(p_temp, 0, ATCA_PRIVWRITE_MAC_ZEROS_SIZE);
p_temp += ATCA_PRIVWRITE_MAC_ZEROS_SIZE;
memcpy(p_temp, param->input_data, ATCA_PRIVWRITE_PLAIN_TEXT_SIZE);
atcac_sw_sha2_256(mac_input, sizeof(mac_input), param->auth_mac);
}
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_derive_key(struct atca_derive_key_in_out *param)
{
uint8_t temporary[ATCA_MSG_SIZE_DERIVE_KEY];
uint8_t *p_temp;
if (!param->parent_key || !param->target_key || !param->temp_key
|| (param->mode & ~DERIVE_KEY_RANDOM_FLAG) || (param->target_key_id > ATCA_KEY_ID_MAX))
{
return ATCA_BAD_PARAM;
}
if ( param->temp_key->no_mac_flag || (param->temp_key->valid != 1)
|| (!(param->mode & DERIVE_KEY_RANDOM_FLAG) != !(param->temp_key->source_flag))
)
{
param->temp_key->valid = 0;
return ATCA_EXECUTION_ERROR;
}
p_temp = temporary;
memcpy(p_temp, param->parent_key, ATCA_KEY_SIZE);
p_temp += ATCA_KEY_SIZE;
*p_temp++ = ATCA_DERIVE_KEY;
*p_temp++ = param->mode;
*p_temp++ = param->target_key_id & 0xFF;
*p_temp++ = (param->target_key_id >> 8) & 0xFF;
*p_temp++ = param->sn[8];
*p_temp++ = param->sn[0];
*p_temp++ = param->sn[1];
memset(p_temp, 0, ATCA_DERIVE_KEY_ZEROS_SIZE);
p_temp += ATCA_DERIVE_KEY_ZEROS_SIZE;
memcpy(p_temp, param->temp_key->value, ATCA_KEY_SIZE);
p_temp += ATCA_KEY_SIZE;
atcac_sw_sha2_256(temporary, ATCA_MSG_SIZE_DERIVE_KEY, param->target_key);
param->temp_key->valid = 0;
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_derive_key_mac(struct atca_derive_key_mac_in_out *param)
{
uint8_t temporary[ATCA_MSG_SIZE_DERIVE_KEY_MAC];
uint8_t *p_temp;
if (!param->parent_key || !param->mac || (param->mode & ~DERIVE_KEY_RANDOM_FLAG)
|| (param->target_key_id > ATCA_KEY_ID_MAX))
{
return ATCA_BAD_PARAM;
}
p_temp = temporary;
memcpy(p_temp, param->parent_key, ATCA_KEY_SIZE);
p_temp += ATCA_KEY_SIZE;
*p_temp++ = ATCA_DERIVE_KEY;
*p_temp++ = param->mode;
*p_temp++ = param->target_key_id & 0xFF;
*p_temp++ = (param->target_key_id >> 8) & 0xFF;
*p_temp++ = param->sn[8];
*p_temp++ = param->sn[0];
*p_temp++ = param->sn[1];
atcac_sw_sha2_256(temporary, ATCA_MSG_SIZE_DERIVE_KEY_MAC, param->mac);
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_decrypt(struct atca_decrypt_in_out *param)
{
uint8_t i;
if (!param->crypto_data || !param->temp_key)
{
return ATCA_BAD_PARAM;
}
if ( param->temp_key->no_mac_flag
|| (param->temp_key->valid != 1)
|| (param->temp_key->gen_dig_data != 1)
|| param->temp_key->source_flag
)
{
param->temp_key->valid = 0;
return ATCA_EXECUTION_ERROR;
}
for (i = 0; i < ATCA_KEY_SIZE; i++)
{
param->crypto_data[i] ^= param->temp_key->value[i];
}
param->temp_key->valid = 0;
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_sha256(int32_t len, const uint8_t *message, uint8_t *digest)
{
return atcac_sw_sha2_256(message, len, digest);
}
ATCA_STATUS atcah_gen_key_msg(struct atca_gen_key_in_out *param)
{
uint8_t msg[128];
if (param == NULL || param->public_key == NULL || param->sn == NULL || param->temp_key == NULL)
{
return ATCA_BAD_PARAM;
}
if (param->public_key_size == 0 || param->public_key_size > 88)
{
return ATCA_BAD_PARAM;
}
memset(msg, 0, sizeof(msg));
memcpy(&msg[0], param->temp_key->value, 32);
msg[32] = ATCA_GENKEY;
if (param->mode & GENKEY_MODE_PUBKEY_DIGEST)
{
if (param->other_data == NULL)
{
return ATCA_BAD_PARAM;
}
memcpy(&msg[33], param->other_data, 3); }
else if (param->mode & GENKEY_MODE_DIGEST)
{
msg[33] = param->mode;
msg[34] = (uint8_t)(param->key_id >> 0);
msg[35] = (uint8_t)(param->key_id >> 8);
}
else
{
return ATCA_SUCCESS;
}
msg[36] = param->sn[8];
memcpy(&msg[37], ¶m->sn[0], 2);
memcpy(&msg[sizeof(msg) - param->public_key_size], param->public_key, param->public_key_size);
atcac_sw_sha2_256(msg, sizeof(msg), param->temp_key->value);
param->temp_key->gen_dig_data = 0;
param->temp_key->gen_key_data = 1;
param->temp_key->key_id = param->key_id;
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_config_to_sign_internal(ATCADeviceType device_type, struct atca_sign_internal_in_out *param, const uint8_t* config)
{
const uint8_t* value = NULL;
uint16_t slot_locked = 0;
if (param == NULL || config == NULL || param->temp_key == NULL)
{
return ATCA_BAD_PARAM;
}
value = &config[20 + param->temp_key->key_id * 2];
param->slot_config = (uint16_t)value[0] | ((uint16_t)value[1] << 8);
value = &config[96 + param->temp_key->key_id * 2];
param->key_config = (uint16_t)value[0] | ((uint16_t)value[1] << 8);
if (device_type == ATECC108A && param->temp_key->key_id < 8)
{
value = &config[52 + param->temp_key->key_id * 2];
param->use_flag = value[0];
param->update_count = value[1];
}
else
{
param->use_flag = 0x00;
param->update_count = 0x00;
}
slot_locked = (uint16_t)config[88] | ((uint16_t)config[89] << 8);
param->is_slot_locked = (slot_locked & (1 << param->temp_key->key_id)) ? false : true;
return ATCA_SUCCESS;
}
ATCA_STATUS atcah_sign_internal_msg(ATCADeviceType device_type, struct atca_sign_internal_in_out *param)
{
uint8_t msg[55];
if (param == NULL || param->temp_key == NULL || param->sn == NULL)
{
return ATCA_BAD_PARAM;
}
memset(msg, 0, sizeof(msg));
memcpy(&msg[0], param->temp_key->value, 32);
msg[32] = ATCA_SIGN; msg[33] = param->mode; msg[34] = (uint8_t)(param->key_id >> 0); msg[35] = (uint8_t)(param->key_id >> 8);
msg[36] = (uint8_t)(param->slot_config >> 0); msg[37] = (uint8_t)(param->slot_config >> 8);
msg[38] = (uint8_t)(param->key_config >> 0); msg[39] = (uint8_t)(param->key_config >> 8);
msg[40] |= ((param->temp_key->key_id & 0x0F) << 0);
msg[40] |= ((param->temp_key->source_flag & 0x01) << 4);
msg[40] |= ((param->temp_key->gen_dig_data & 0x01) << 5);
msg[40] |= ((param->temp_key->gen_key_data & 0x01) << 6);
msg[40] |= ((param->temp_key->no_mac_flag & 0x01) << 7);
if (device_type == ATECC108A && param->temp_key->key_id < 8)
{
msg[41] = param->use_flag; msg[42] = param->update_count; }
else
{
msg[41] = 0x00;
msg[42] = 0x00;
}
msg[43] = param->sn[8];
memcpy(&msg[48], ¶m->sn[0], 2);
if (param->mode & SIGN_MODE_INCLUDE_SN)
{
memcpy(&msg[44], ¶m->sn[4], 4);
memcpy(&msg[50], ¶m->sn[2], 2);
}
msg[52] = param->is_slot_locked ? 0x00 : 0x01;
msg[53] = param->for_invalidate ? 0x01 : 0x00;
msg[54] = 0x00;
if (param->message)
{
memcpy(param->message, msg, sizeof(msg));
}
if (param->verify_other_data)
{
memcpy(¶m->verify_other_data[0], &msg[33], 10);
memcpy(¶m->verify_other_data[10], &msg[44], 4);
memcpy(¶m->verify_other_data[14], &msg[50], 5);
}
if (param->digest)
{
return atcac_sw_sha2_256(msg, sizeof(msg), param->digest);
}
else
{
return ATCA_SUCCESS;
}
}
ATCA_STATUS atcah_encode_counter_match(uint32_t counter_value, uint8_t * counter_match_value)
{
if ((counter_value > COUNTER_MAX_VALUE) || (counter_value % 32 != 0) || (counter_match_value == NULL))
{
return ATCA_BAD_PARAM;
}
counter_match_value[0] = (uint8_t)((counter_value >> 0) & 0xFF);
counter_match_value[1] = (uint8_t)((counter_value >> 8) & 0xFF);
counter_match_value[2] = (uint8_t)((counter_value >> 16) & 0xFF);
counter_match_value[3] = (uint8_t)((counter_value >> 24) & 0xFF);
memcpy(counter_match_value + 4, counter_match_value, 4);
return ATCA_SUCCESS;
}