Personalization sketch for ATSHA204

This sketch is used to personalize the ATSHA204 crypto
circuit.
This is required in order to use the device for secure
communication.

The sketch also supports random key generation.

To personalize a ATSHA204 device, do the following:
1. Ensure the correct pin is used for the ATSHA204.
2. Execute the sketch without other changes to verify
   that it can communicate properly with the device.
3g. For a device used in a gateway:
    Enable LOCK_CONFIGURATION to lock the configuration
    and enable random key generation as well as key storage.
4g. Execute the sketch to lock the configuration and obtain
    a unique key. Be sure to note down the key printed in the
    UART log as it has been stored in the chip and will never
    be accessible again (a new key is calculated on subsequent
    runs).
    The key can still be changed.
5g. Enable SKIP_KEY_STORAGE to prevent generating new random
    keys on sketch re-execution.
3n. For a device used as a node:
    Enable USER_KEY_DATA and enter your private key data
    in user_key_data.
    Then enable LOCK_CONFIGURATION to lock the configuration
4n. Execute the sketch to lock the configuration and store
    the user-supplied key.
5n. Optionally: Enable SKIP_KEY_STORAGE to prevent re-writing
    the user supplied key on sketch re-execution.
6.  Optionally: Enable LOCK_DATA to prevent the key to be
    changed.
This commit is contained in:
Patrick Fallberg
2015-01-10 19:57:09 +01:00
parent 963a756605
commit 6aa370d6f2
@@ -0,0 +1,947 @@
/* SHA204 personalization sketch
by: Patrick Fallberg
date: January 10, 2015
This sketch will write factory default settings to the configuration zone
and then lock it.
It will then either
a. Generate a random value to use as a key which will be stored in
slot 0. The key is printed on UART (115200) in clear text for the user to be
able to use it as a user-supplied key in other personalization executions
where the same key is needed.
b. Use a user-supplied value to use as a key which will be stored in
slot 0.
Finally it will lock the data zone.
By default, no locking is performed. User have to manually enable the flags that
turn on the locking. Furthermore, user have to send a SPACE character on serial
console when prompted to do any locking.
Default settings use ATSHA204 on pin 7.
*/
#include <sha204_library.h>
#include <sha204_lib_return_codes.h>
// The pin the ATSHA204 is connected on
#define ATSHA204_PIN 7
// Uncomment this to enable locking the configuration zone.
// *** BE AWARE THAT THIS PREVENTS ANY FUTURE CONFIGURATION CHANGE TO THE CHIP ***
// It is still possible to change the key, and this also enable random key generation
//#define LOCK_CONFIGURATION
// Uncomment this to enable locking the data zone.
// *** BE AWARE THAT THIS PREVENTS THE KEY TO BE CHANGED ***
// It is not required to lock data, key cannot be retrieved anyway, but by locking
// data, it can be guaranteed that nobody even with physical access to the chip,
// will be able to change the key.
//#define LOCK_DATA
// Uncomment this to skip key storage (typically once key has been written once)
//#define SKIP_KEY_STORAGE
// Uncomment this to skip key data storage (once configuration is locked, key
// will aways randomize )
// Uncomment this to skip key generation and use 'user_key_data' as key instead.
//#define USER_KEY_DATA
#ifdef USER_KEY_DATA
const uint8_t user_key_data[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#endif
const int sha204Pin = ATSHA204_PIN;
atsha204Class sha204(sha204Pin);
void halt()
{
Serial.println(F("Halting!"));
while(1);
}
uint16_t write_config_and_get_crc()
{
uint16_t crc = 0;
uint8_t config_word[4];
uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
uint8_t ret_code;
bool do_write;
// We will set default settings from datasheet on all slots. This means that we can use slot 0 for the key
// as that slot will not be readable (key will therefore be secure) and slot 8 for the payload digest
// calculationon as that slot can be written in clear text even when the datazone is locked.
// Other settings which are not relevant are kept as is.
for (int i=0; i < 88; i += 4)
{
do_write = true;
if (i == 20)
{
config_word[0] = 0x8F;
config_word[1] = 0x80;
config_word[2] = 0x80;
config_word[3] = 0xA1;
}
else if (i == 24)
{
config_word[0] = 0x82;
config_word[1] = 0xE0;
config_word[2] = 0xA3;
config_word[3] = 0x60;
}
else if (i == 28)
{
config_word[0] = 0x94;
config_word[1] = 0x40;
config_word[2] = 0xA0;
config_word[3] = 0x85;
}
else if (i == 32)
{
config_word[0] = 0x86;
config_word[1] = 0x40;
config_word[2] = 0x87;
config_word[3] = 0x07;
}
else if (i == 36)
{
config_word[0] = 0x0F;
config_word[1] = 0x00;
config_word[2] = 0x89;
config_word[3] = 0xF2;
}
else if (i == 40)
{
config_word[0] = 0x8A;
config_word[1] = 0x7A;
config_word[2] = 0x0B;
config_word[3] = 0x8B;
}
else if (i == 44)
{
config_word[0] = 0x0C;
config_word[1] = 0x4C;
config_word[2] = 0xDD;
config_word[3] = 0x4D;
}
else if (i == 48)
{
config_word[0] = 0xC2;
config_word[1] = 0x42;
config_word[2] = 0xAF;
config_word[3] = 0x8F;
}
else if (i == 52 || i == 56 || i == 60 || i == 64)
{
config_word[0] = 0xFF;
config_word[1] = 0x00;
config_word[2] = 0xFF;
config_word[3] = 0x00;
}
else if (i == 68 || i == 72 || i == 76 || i == 80)
{
config_word[0] = 0xFF;
config_word[1] = 0xFF;
config_word[2] = 0xFF;
config_word[3] = 0xFF;
}
else
{
// All other configs are untouched
ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, i);
if (ret_code != SHA204_SUCCESS)
{
Serial.print(F("Failed to read config. Response: ")); Serial.println(ret_code, HEX);
halt();
}
// Set config_word to the read data
config_word[0] = rx_buffer[SHA204_BUFFER_POS_DATA+0];
config_word[1] = rx_buffer[SHA204_BUFFER_POS_DATA+1];
config_word[2] = rx_buffer[SHA204_BUFFER_POS_DATA+2];
config_word[3] = rx_buffer[SHA204_BUFFER_POS_DATA+3];
do_write = false;
}
// Update crc with CRC for the current word
crc = sha204.calculateAndUpdateCrc(4, config_word, crc);
// Write config word
if (do_write)
{
ret_code = sha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_CONFIG,
i >> 2, 4, config_word, 0, NULL, 0, NULL,
WRITE_COUNT_SHORT, tx_buffer, WRITE_RSP_SIZE, rx_buffer);
if (ret_code != SHA204_SUCCESS)
{
Serial.print(F("Failed to write config word at address ")); Serial.print(i);
Serial.print(F(". Response: ")); Serial.println(ret_code, HEX);
halt();
}
}
}
return crc;
}
void write_key(uint8_t* key)
{
uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
uint8_t ret_code;
// Write key to slot 0
ret_code = sha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG,
0, SHA204_ZONE_ACCESS_32, key, 0, NULL, 0, NULL,
WRITE_COUNT_LONG, tx_buffer, WRITE_RSP_SIZE, rx_buffer);
if (ret_code != SHA204_SUCCESS)
{
Serial.print(F("Failed to write key to slot 0. Response: ")); Serial.println(ret_code, HEX);
halt();
}
}
void dump_configuration()
{
uint8_t config_word[4];
uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
uint8_t ret_code;
for (int i=0; i < 88; i += 4)
{
ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, i);
if (ret_code != SHA204_SUCCESS)
{
Serial.print(F("Failed to read config. Response: ")); Serial.println(ret_code, HEX);
halt();
}
if (i == 0x00)
{
Serial.print(F(" SN[0:1] | SN[2:3] | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j == 1)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x04)
{
Serial.print(F(" Revnum | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
Serial.print(F(" "));
}
Serial.println();
}
else if (i == 0x08)
{
Serial.print(F(" SN[4:7] | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
Serial.print(F(" "));
}
Serial.println();
}
else if (i == 0x0C)
{
Serial.print(F(" SN[8] | Reserved13 | I2CEnable | Reserved15 | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j < 3)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x10)
{
Serial.print(F(" I2CAddress | TempOffset | OTPmode | SelectorMode | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j < 3)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x14)
{
Serial.print(F(" SlotConfig00 | SlotConfig01 | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j == 1)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x18)
{
Serial.print(F(" SlotConfig02 | SlotConfig03 | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j == 1)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x1C)
{
Serial.print(F(" SlotConfig04 | SlotConfig05 | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j == 1)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x20)
{
Serial.print(F(" SlotConfig06 | SlotConfig07 | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j == 1)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x24)
{
Serial.print(F(" SlotConfig08 | SlotConfig09 | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j == 1)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x28)
{
Serial.print(F(" SlotConfig0A | SlotConfig0B | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j == 1)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x2C)
{
Serial.print(F(" SlotConfig0C | SlotConfig0D | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j == 1)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x30)
{
Serial.print(F(" SlotConfig0E | SlotConfig0F | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j == 1)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x34)
{
Serial.print(F(" UseFlag00 | UpdateCount00 | UseFlag01 | UpdateCount01 | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j < 3)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x38)
{
Serial.print(F(" UseFlag02 | UpdateCount02 | UseFlag03 | UpdateCount03 | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j < 3)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x3C)
{
Serial.print(F(" UseFlag04 | UpdateCount04 | UseFlag05 | UpdateCount05 | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j < 3)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x40)
{
Serial.print(F(" UseFlag06 | UpdateCount06 | UseFlag07 | UpdateCount07 | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j < 3)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
else if (i == 0x44)
{
Serial.print(F(" LastKeyUse[0:3] | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
Serial.print(F(" "));
}
Serial.println();
}
else if (i == 0x48)
{
Serial.print(F(" LastKeyUse[4:7] | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
Serial.print(F(" "));
}
Serial.println();
}
else if (i == 0x4C)
{
Serial.print(F(" LastKeyUse[8:B] | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
Serial.print(F(" "));
}
Serial.println();
}
else if (i == 0x50)
{
Serial.print(F(" LastKeyUse[C:F] | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
Serial.print(F(" "));
}
Serial.println();
}
else if (i == 0x54)
{
Serial.print(F(" UserExtra | Selector | LockValue | LockConfig | "));
for (int j=0; j<4; j++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
if (j < 3)
{
Serial.print(F(" | "));
}
else
{
Serial.print(F(" "));
}
}
Serial.println();
}
}
}
void setup()
{
uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
uint8_t key[32];
uint8_t ret_code;
uint8_t lockConfig = 0;
uint8_t lockValue = 0;
uint16_t crc;
Serial.begin(115200);
Serial.println(F("ATSHA204 personalization sketch for MySensors usage."));
Serial.println(F("----------------------------------------------------"));
// Wake device before starting operations
ret_code = sha204.sha204c_wakeup(rx_buffer);
if (ret_code != SHA204_SUCCESS)
{
Serial.print(F("Failed to wake device. Response: ")); Serial.println(ret_code, HEX);
halt();
}
// Output device revision on console
ret_code = sha204.sha204m_dev_rev(tx_buffer, rx_buffer);
if (ret_code != SHA204_SUCCESS)
{
Serial.print(F("Failed to determine device revision. Response: ")); Serial.println(ret_code, HEX);
halt();
}
else
{
Serial.print(F("Device revision: "));
for (int i=0; i<4; i++)
{
if (rx_buffer[SHA204_BUFFER_POS_DATA+i] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+i], HEX);
}
Serial.println();
}
// Output serial number on console
ret_code = sha204.getSerialNumber(rx_buffer);
if (ret_code != SHA204_SUCCESS)
{
Serial.print(F("Failed to obtain device serial number. Response: ")); Serial.println(ret_code, HEX);
halt();
}
else
{
Serial.print(F("Device serial: "));
for (int i=0; i<9; i++)
{
if (rx_buffer[i] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(rx_buffer[i], HEX);
}
Serial.println();
}
// Read out lock config bits to determine if locking is possible
ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2);
if (ret_code != SHA204_SUCCESS)
{
Serial.print(F("Failed to determine device lock status. Response: ")); Serial.println(ret_code, HEX);
halt();
}
else
{
lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3];
lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2];
}
if (lockConfig != 0x00)
{
// Write config and get CRC for the updated config
crc = write_config_and_get_crc();
// List current configuration before attempting to lock
Serial.println(F("Chip configuration:"));
dump_configuration();
#ifdef LOCK_CONFIGURATION
// Purge serial input buffer
while (Serial.available())
{
Serial.read();
}
Serial.println(F("Send SPACE character now to lock the configuration..."));
while (Serial.available() == 0);
if (Serial.read() == ' ')
{
Serial.println(F("Locking configuration..."));
// Correct sequence, resync chip
ret_code = sha204.sha204c_resync(SHA204_RSP_SIZE_MAX, rx_buffer);
if (ret_code != SHA204_SUCCESS && ret_code != SHA204_RESYNC_WITH_WAKEUP)
{
Serial.print(F("Resync failed. Response: ")); Serial.println(ret_code, HEX);
halt();
}
// Lock configuration zone
ret_code = sha204.sha204m_execute(SHA204_LOCK, SHA204_ZONE_CONFIG,
crc, 0, NULL, 0, NULL, 0, NULL,
LOCK_COUNT, tx_buffer, LOCK_RSP_SIZE, rx_buffer);
if (ret_code != SHA204_SUCCESS)
{
Serial.print(F("Configuration lock failed. Response: ")); Serial.println(ret_code, HEX);
halt();
}
else
{
Serial.println(F("Configuration locked."));
// Update lock flags after locking
ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2);
if (ret_code != SHA204_SUCCESS)
{
Serial.print(F("Failed to determine device lock status. Response: ")); Serial.println(ret_code, HEX);
halt();
}
else
{
lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3];
lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2];
}
}
}
else
{
Serial.println(F("Unexpected answer. Skipping lock."));
}
#else //LOCK_CONFIGURATION
Serial.println(F("Dry-run. Configuration not locked. Define LOCK_CONFIGURATION to lock for real."));
#endif
}
else
{
Serial.println(F("Skipping configuration write and lock (configuration already locked)."));
Serial.println(F("Chip configuration:"));
dump_configuration();
}
#ifdef SKIP_KEY_STORAGE
Serial.println(F("Disable SKIP_KEY_STORAGE to store key."));
#else
#ifdef USER_KEY_DATA
memcpy(key, user_key_data, 32);
Serial.print(F("Using this user supplied key: "));
#else
// Retrieve random value to use as key
ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE);
if (ret_code != SHA204_SUCCESS)
{
Serial.print(F("Random key generation failed. Response: ")); Serial.println(ret_code, HEX);
halt();
}
else
{
memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32);
}
if (lockConfig == 0x00)
{
Serial.println(F("Take note of this key, it will never be the shown again:"));
}
else
{
Serial.println(F("Key is not randomized (configuration not locked):"));
}
#endif
for (int i=0; i<32; i++)
{
if (key[i] < 0x10)
{
Serial.print('0'); // Because Serial.print does not 0-pad HEX
}
Serial.print(key[i], HEX);
}
Serial.println();
// It will not be possible to write the key if the configuration zone is unlocked
if (lockConfig == 0x00)
{
// Write the key to the appropriate slot in the data zone
Serial.println(F("Writing key to slot 0..."));
write_key(key);
}
else
{
Serial.println(F("Skipping key storage (configuration not locked)."));
Serial.println(F("The configuration must be locked to be able to write a key."));
}
#endif
if (lockValue != 0x00)
{
#ifdef LOCK_DATA
while (Serial.available())
{
Serial.read();
}
Serial.println(F("Send SPACE character to lock data..."));
while (Serial.available() == 0);
if (Serial.read() == ' ')
{
// Correct sequence, resync chip
ret_code = sha204.sha204c_resync(SHA204_RSP_SIZE_MAX, rx_buffer);
if (ret_code != SHA204_SUCCESS && ret_code != SHA204_RESYNC_WITH_WAKEUP)
{
Serial.print(F("Resync failed. Response: ")); Serial.println(ret_code, HEX);
halt();
}
// If configuration is unlocked, key is not updated. Locking data in this case will cause
// slot 0 to contain an unknown (or factory default) key, and this is in practically any
// usecase not the desired behaviour, so ask for additional confirmation in this case.
if (lockConfig != 0x00)
{
while (Serial.available())
{
Serial.read();
}
Serial.println(F("*** ATTENTION ***"));
Serial.println(F("Configuration is not locked. Are you ABSULOUTELY SURE you want to lock data?"));
Serial.println(F("Locking data at this stage will cause slot 0 to contain a factory default key"));
Serial.println(F("which cannot be change after locking is done. This is in practically any usecase"));
Serial.println(F("NOT the desired behavour. Send SPACE character now to lock data anyway..."));
while (Serial.available() == 0);
if (Serial.read() != ' ')
{
Serial.println(F("Unexpected answer. Skipping lock."));
halt();
}
}
// Lock data zone
ret_code = sha204.sha204m_execute(SHA204_LOCK, SHA204_ZONE_DATA | LOCK_ZONE_NO_CRC,
0x0000, 0, NULL, 0, NULL, 0, NULL,
LOCK_COUNT, tx_buffer, LOCK_RSP_SIZE, rx_buffer);
if (ret_code != SHA204_SUCCESS)
{
Serial.print(F("Data lock failed. Response: ")); Serial.println(ret_code, HEX);
halt();
}
else
{
Serial.println(F("Data locked."));
// Update lock flags after locking
ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2);
if (ret_code != SHA204_SUCCESS)
{
Serial.print(F("Failed to determine device lock status. Response: ")); Serial.println(ret_code, HEX);
halt();
}
else
{
lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3];
lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2];
}
}
}
else
{
Serial.println(F("Unexpected answer. Skipping lock."));
}
#else //LOCK_DATA
Serial.println(F("Dry-run. Data not locked. Define LOCK_DATA to lock for real."));
#endif
}
else
{
Serial.println(F("Skipping OTP/data zone lock (zone already locked)."));
}
Serial.println(F("--------------------------------"));
Serial.println(F("Personalization is now complete."));
Serial.print(F("Configuration is "));
if (lockConfig == 0x00)
{
Serial.println("LOCKED");
}
else
{
Serial.println("UNLOCKED");
}
Serial.print(F("Data is "));
if (lockValue == 0x00)
{
Serial.println("LOCKED");
}
else
{
Serial.println("UNLOCKED");
}
}
void loop()
{
}