#include "atca_basic.h"
#include "atca_execution.h"
#include "host/atca_host.h"
ATCA_STATUS atcab_ecdh_base(uint8_t mode, uint16_t key_id, const uint8_t* public_key, uint8_t* pms, uint8_t* out_nonce)
{
ATCAPacket packet;
ATCA_STATUS status = ATCA_GEN_FAIL;
do
{
packet.param1 = mode;
packet.param2 = key_id;
memcpy(packet.data, public_key, ATCA_PUB_KEY_SIZE);
if ((status = atECDH(_gDevice->mCommands, &packet)) != ATCA_SUCCESS)
{
break;
}
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
{
break;
}
if (pms != NULL && packet.data[ATCA_COUNT_IDX] >= (3 + ATCA_KEY_SIZE))
{
memcpy(pms, &packet.data[ATCA_RSP_DATA_IDX], ATCA_KEY_SIZE);
}
if (out_nonce != NULL && packet.data[ATCA_COUNT_IDX] >= (3 + ATCA_KEY_SIZE * 2))
{
memcpy(out_nonce, &packet.data[ATCA_RSP_DATA_IDX + ATCA_KEY_SIZE], ATCA_KEY_SIZE);
}
}
while (0);
return status;
}
ATCA_STATUS atcab_ecdh(uint16_t key_id, const uint8_t* public_key, uint8_t* pms)
{
ATCA_STATUS status;
status = atcab_ecdh_base(ECDH_PREFIX_MODE, key_id, public_key, pms, NULL);
return status;
}
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
ATCA_STATUS atcab_ecdh_enc(uint16_t key_id, const uint8_t* public_key, uint8_t* pms, const uint8_t* read_key, uint16_t read_key_id)
#else
ATCA_STATUS atcab_ecdh_enc(uint16_t key_id, const uint8_t* public_key, uint8_t* pms, const uint8_t* read_key, uint16_t read_key_id, const uint8_t num_in[NONCE_NUMIN_SIZE])
#endif
{
ATCA_STATUS status = ATCA_SUCCESS;
do
{
if (public_key == NULL || pms == NULL || read_key == NULL)
{
status = ATCA_BAD_PARAM;
BREAK(status, "Bad input parameters");
}
if ((status = atcab_ecdh(key_id, public_key, NULL)) != ATCA_SUCCESS)
{
BREAK(status, "ECDH Failed");
}
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
if ((status = atcab_read_enc(key_id | 0x0001, 0, pms, read_key, read_key_id)) != ATCA_SUCCESS)
#else
if ((status = atcab_read_enc(key_id | 0x0001, 0, pms, read_key, read_key_id, num_in)) != ATCA_SUCCESS)
#endif
{
BREAK(status, "Encrypted read failed");
}
}
while (0);
return status;
}
ATCA_STATUS atcab_ecdh_ioenc(uint16_t key_id, const uint8_t* public_key, uint8_t* pms, const uint8_t* io_key)
{
uint8_t mode = ECDH_MODE_SOURCE_EEPROM_SLOT | ECDH_MODE_OUTPUT_ENC | ECDH_MODE_COPY_OUTPUT_BUFFER;
uint8_t out_nonce[ATCA_KEY_SIZE];
atca_io_decrypt_in_out_t io_dec_params;
ATCA_STATUS status = ATCA_GEN_FAIL;
status = atcab_ecdh_base(mode, key_id, public_key, pms, out_nonce);
if (status != ATCA_SUCCESS)
{
return status;
}
memset(&io_dec_params, 0, sizeof(io_dec_params));
io_dec_params.io_key = io_key;
io_dec_params.out_nonce = out_nonce;
io_dec_params.data = pms;
io_dec_params.data_size = 32;
status = atcah_io_decrypt(&io_dec_params);
if (status != ATCA_SUCCESS)
{
return status;
}
return status;
}
ATCA_STATUS atcab_ecdh_tempkey(const uint8_t* public_key, uint8_t* pms)
{
uint8_t mode = ECDH_MODE_SOURCE_TEMPKEY | ECDH_MODE_COPY_OUTPUT_BUFFER;
return atcab_ecdh_base(mode, 0x0000, public_key, pms, NULL);
}
ATCA_STATUS atcab_ecdh_tempkey_ioenc(const uint8_t* public_key, uint8_t* pms, const uint8_t* io_key)
{
uint8_t mode = ECDH_MODE_SOURCE_TEMPKEY | ECDH_MODE_OUTPUT_ENC | ECDH_MODE_COPY_OUTPUT_BUFFER;
uint8_t out_nonce[ATCA_KEY_SIZE];
atca_io_decrypt_in_out_t io_dec_params;
ATCA_STATUS status = ATCA_GEN_FAIL;
status = atcab_ecdh_base(mode, 0x0000, public_key, pms, out_nonce);
if (status != ATCA_SUCCESS)
{
return status;
}
memset(&io_dec_params, 0, sizeof(io_dec_params));
io_dec_params.io_key = io_key;
io_dec_params.out_nonce = out_nonce;
io_dec_params.data = pms;
io_dec_params.data_size = 32;
status = atcah_io_decrypt(&io_dec_params);
if (status != ATCA_SUCCESS)
{
return status;
}
return status;
}