#include <stdlib.h>
#include <string.h>
#include "atca_command.h"
#include "atca_device.h"
#include "atca_execution.h"
#include "atca_devtypes.h"
#include "hal/atca_hal.h"
#ifndef ATCA_POLLING_INIT_TIME_MSEC
#define ATCA_POLLING_INIT_TIME_MSEC 1
#endif
#ifndef ATCA_POLLING_FREQUENCY_TIME_MSEC
#define ATCA_POLLING_FREQUENCY_TIME_MSEC 2
#endif
#ifndef ATCA_POLLING_MAX_TIME_MSEC
#define ATCA_POLLING_MAX_TIME_MSEC 2500
#endif
#ifdef ATCA_NO_POLL
static const device_execution_time_t device_execution_time_204[] = {
{ ATCA_CHECKMAC, 38},
{ ATCA_DERIVE_KEY, 62},
{ ATCA_GENDIG, 43},
{ ATCA_HMAC, 69},
{ ATCA_INFO, 2},
{ ATCA_LOCK, 24},
{ ATCA_MAC, 35},
{ ATCA_NONCE, 60},
{ ATCA_PAUSE, 2},
{ ATCA_RANDOM, 50},
{ ATCA_READ, 5},
{ ATCA_SHA, 22},
{ ATCA_UPDATE_EXTRA, 12},
{ ATCA_WRITE, 42}
};
static const device_execution_time_t device_execution_time_206[] = {
{ ATCA_DERIVE_KEY, 62},
{ ATCA_INFO, 2},
{ ATCA_MAC, 35},
{ ATCA_READ, 5},
{ ATCA_WRITE, 42}
};
static const device_execution_time_t device_execution_time_108[] = {
{ ATCA_CHECKMAC, 13},
{ ATCA_COUNTER, 20},
{ ATCA_DERIVE_KEY, 50},
{ ATCA_GENDIG, 11},
{ ATCA_GENKEY, 115},
{ ATCA_HMAC, 23},
{ ATCA_INFO, 2},
{ ATCA_LOCK, 32},
{ ATCA_MAC, 14},
{ ATCA_NONCE, 29},
{ ATCA_PAUSE, 3},
{ ATCA_PRIVWRITE, 48},
{ ATCA_RANDOM, 23},
{ ATCA_READ, 5},
{ ATCA_SHA, 9},
{ ATCA_SIGN, 60},
{ ATCA_UPDATE_EXTRA, 10},
{ ATCA_VERIFY, 72},
{ ATCA_WRITE, 26}
};
static const device_execution_time_t device_execution_time_508[] = {
{ ATCA_CHECKMAC, 13},
{ ATCA_COUNTER, 20},
{ ATCA_DERIVE_KEY, 50},
{ ATCA_ECDH, 58},
{ ATCA_GENDIG, 11},
{ ATCA_GENKEY, 115},
{ ATCA_HMAC, 23},
{ ATCA_INFO, 2},
{ ATCA_LOCK, 32},
{ ATCA_MAC, 14},
{ ATCA_NONCE, 29},
{ ATCA_PAUSE, 3},
{ ATCA_PRIVWRITE, 48},
{ ATCA_RANDOM, 23},
{ ATCA_READ, 5},
{ ATCA_SHA, 9},
{ ATCA_SIGN, 60},
{ ATCA_UPDATE_EXTRA, 10},
{ ATCA_VERIFY, 72},
{ ATCA_WRITE, 26}
};
static const device_execution_time_t device_execution_time_608_m0[] = {
{ ATCA_AES, 27},
{ ATCA_CHECKMAC, 40},
{ ATCA_COUNTER, 25},
{ ATCA_DERIVE_KEY, 50},
{ ATCA_ECDH, 75},
{ ATCA_GENDIG, 25},
{ ATCA_GENKEY, 115},
{ ATCA_INFO, 5},
{ ATCA_KDF, 165},
{ ATCA_LOCK, 35},
{ ATCA_MAC, 55},
{ ATCA_NONCE, 20},
{ ATCA_PRIVWRITE, 50},
{ ATCA_RANDOM, 23},
{ ATCA_READ, 5},
{ ATCA_SECUREBOOT, 80},
{ ATCA_SELFTEST, 250},
{ ATCA_SHA, 36},
{ ATCA_SIGN, 115},
{ ATCA_UPDATE_EXTRA, 10},
{ ATCA_VERIFY, 105},
{ ATCA_WRITE, 45}
};
static const device_execution_time_t device_execution_time_608_m1[] = {
{ ATCA_AES, 27},
{ ATCA_CHECKMAC, 40},
{ ATCA_COUNTER, 25},
{ ATCA_DERIVE_KEY, 50},
{ ATCA_ECDH, 172},
{ ATCA_GENDIG, 35},
{ ATCA_GENKEY, 215},
{ ATCA_INFO, 5},
{ ATCA_KDF, 165},
{ ATCA_LOCK, 35},
{ ATCA_MAC, 55},
{ ATCA_NONCE, 20},
{ ATCA_PRIVWRITE, 50},
{ ATCA_RANDOM, 23},
{ ATCA_READ, 5},
{ ATCA_SECUREBOOT, 160},
{ ATCA_SELFTEST, 625},
{ ATCA_SHA, 42},
{ ATCA_SIGN, 220},
{ ATCA_UPDATE_EXTRA, 10},
{ ATCA_VERIFY, 295},
{ ATCA_WRITE, 45}
};
static const device_execution_time_t device_execution_time_608_m2[] = {
{ ATCA_AES, 27},
{ ATCA_CHECKMAC, 40},
{ ATCA_COUNTER, 25},
{ ATCA_DERIVE_KEY, 50},
{ ATCA_ECDH, 531},
{ ATCA_GENDIG, 35},
{ ATCA_GENKEY, 653},
{ ATCA_INFO, 5},
{ ATCA_KDF, 165},
{ ATCA_LOCK, 35},
{ ATCA_MAC, 55},
{ ATCA_NONCE, 20},
{ ATCA_PRIVWRITE, 50},
{ ATCA_RANDOM, 23},
{ ATCA_READ, 5},
{ ATCA_SECUREBOOT, 480},
{ ATCA_SELFTEST, 2324},
{ ATCA_SHA, 75},
{ ATCA_SIGN, 665},
{ ATCA_UPDATE_EXTRA, 10},
{ ATCA_VERIFY, 1085},
{ ATCA_WRITE, 45}
};
#endif
#ifdef ATCA_NO_POLL
ATCA_STATUS atGetExecTime(uint8_t opcode, ATCACommand ca_cmd)
{
ATCA_STATUS status = ATCA_SUCCESS;
const device_execution_time_t *execution_times;
uint8_t i, no_of_commands;
switch (ca_cmd->dt)
{
case ATSHA204A:
execution_times = device_execution_time_204;
no_of_commands = sizeof(device_execution_time_204) / sizeof(device_execution_time_t);
break;
case ATSHA206A:
execution_times = device_execution_time_206;
no_of_commands = sizeof(device_execution_time_206) / sizeof(device_execution_time_t);
break;
case ATECC108A:
execution_times = device_execution_time_108;
no_of_commands = sizeof(device_execution_time_108) / sizeof(device_execution_time_t);
break;
case ATECC508A:
execution_times = device_execution_time_508;
no_of_commands = sizeof(device_execution_time_508) / sizeof(device_execution_time_t);
break;
case ATECC608A:
if (ca_cmd->clock_divider == ATCA_CHIPMODE_CLOCK_DIV_M1)
{
execution_times = device_execution_time_608_m1;
no_of_commands = sizeof(device_execution_time_608_m1) / sizeof(device_execution_time_t);
}
else if (ca_cmd->clock_divider == ATCA_CHIPMODE_CLOCK_DIV_M2)
{
execution_times = device_execution_time_608_m2;
no_of_commands = sizeof(device_execution_time_608_m2) / sizeof(device_execution_time_t);
}
else
{
execution_times = device_execution_time_608_m0;
no_of_commands = sizeof(device_execution_time_608_m0) / sizeof(device_execution_time_t);
}
break;
default:
no_of_commands = 0;
execution_times = NULL;
break;
}
ca_cmd->execution_time_msec = ATCA_UNSUPPORTED_CMD;
for (i = 0; i < no_of_commands; i++)
{
if (execution_times[i].opcode == opcode)
{
ca_cmd->execution_time_msec = execution_times[i].execution_time_msec;
break;
}
}
if (ca_cmd->execution_time_msec == ATCA_UNSUPPORTED_CMD)
{
status = ATCA_BAD_OPCODE;
}
return status;
}
#endif
ATCA_STATUS atca_execute_command(ATCAPacket* packet, ATCADevice device)
{
ATCA_STATUS status;
uint32_t execution_or_wait_time;
uint32_t max_delay_count;
uint16_t rxsize;
do
{
#ifdef ATCA_NO_POLL
if ((status = atGetExecTime(packet->opcode, device->mCommands)) != ATCA_SUCCESS)
{
return status;
}
execution_or_wait_time = device->mCommands->execution_time_msec;
max_delay_count = 0;
#else
execution_or_wait_time = ATCA_POLLING_INIT_TIME_MSEC;
max_delay_count = ATCA_POLLING_MAX_TIME_MSEC / ATCA_POLLING_FREQUENCY_TIME_MSEC;
#endif
if ((status = atwake(device->mIface)) != ATCA_SUCCESS)
{
break;
}
if ((status = atsend(device->mIface, (uint8_t*)packet, packet->txsize)) != ATCA_SUCCESS)
{
break;
}
atca_delay_ms(execution_or_wait_time);
do
{
memset(packet->data, 0, sizeof(packet->data));
rxsize = sizeof(packet->data);
if ((status = atreceive(device->mIface, packet->data, &rxsize)) == ATCA_SUCCESS)
{
break;
}
#ifndef ATCA_NO_POLL
atca_delay_ms(ATCA_POLLING_FREQUENCY_TIME_MSEC);
#endif
}
while (max_delay_count-- > 0);
if (status != ATCA_SUCCESS)
{
break;
}
if (rxsize < 4)
{
if (rxsize > 0)
{
status = ATCA_RX_FAIL;
}
else
{
status = ATCA_RX_NO_RESPONSE;
}
break;
}
if ((status = atCheckCrc(packet->data)) != ATCA_SUCCESS)
{
break;
}
if ((status = isATCAError(packet->data)) != ATCA_SUCCESS)
{
break;
}
}
while (0);
atidle(device->mIface);
return status;
}