
Итак, после всех тестов и манипуляций с микросхемой ATSHA204A, описанных в предыдущих статьях, мы имеем чип с заблокированной конфигурационной зоной и разблокированными зонами данных (Data Zone) и зоной OTP.
В этой статье мы исследуем работу ATSHA204A в этом режиме и подробно разберём её поведение и открывшиеся, в связи с блокировкой, возможности. Это довольно нетривиальная информация и хорошее понимание всех описанных в этой статье вопросов необходимо вам для грамотной и осмысленной работы с ATSHA204A.
Начнём мы с генератора случайных чисел.
Генератор случайных чисел (RNG)
Микросхема ATSHA204A содержит высококачественный генератор случайных 32-байтных чисел (RNG), который используется в работе с криптографическими функциями, а также может быть использован вами в ваших проектах. Но в работе этого генератора есть некоторые неочевидные нюансы.
Как уже было отмечено выше, свойства и функции микросхемы ATSHA204A зависят от состояния блокировки её зон памяти. Работа генератора случайных чисел также зависит от этих блокировок, в частности, генератор начинает работать только после блокировки конфигурационной зоны микросхемы ATSHA204A.
Об этом будет рассказано чуть ниже, а пока код скетча генератора случайных чисел на ATSHA204A:
/*
ATSHA204 Random (RNG)
*/
#include <sha204_library.h>
#define ATSHA204_PIN A3
atsha204Class sha204(ATSHA204_PIN);
void setup() {
Serial.begin(115200);
Serial.println("ATSHA204 Random start...");
}
void printArray(byte arr[], byte len) {
for (byte i = 0; i < len; i++) {
if (arr[i] < 16) {Serial.print('0');}
Serial.print(arr[i], HEX); Serial.print(' ');
}
}
void randomExample() {
uint8_t response[RANDOM_RSP_SIZE];
uint8_t tx_buffer[12] = {0};
byte res = sha204.sha204m_random(tx_buffer, response, RANDOM_NO_SEED_UPDATE);
printArray(response, RANDOM_RSP_SIZE);
Serial.println();
}
void loop() {
randomExample();
delay(1000);
}
Работа по получению случайных чисел от микросхемы ATSHA204A выполняется библиотечной функцией sha204.sha204m_random()
byte res = sha204.sha204m_random(tx_buffer, response, RANDOM_NO_SEED_UPDATE);
и далее случайные 32-байтные числа, полученные от ATSHA204A, в бесконечном цикле выводятся в Serial
void loop() {
randomExample();
delay(1000);
}
Если запустить этот скетч на микросхеме с незаблокированной конфигурационной зоной (её изначальное состояние), то вместо случайных чисел генерируется специальная тестовая последовательность (которую, естественно, нельзя использовать в реальной работе).

При запуске скетча на ATSHA204A с заблокированной конфигурационной зоной, тот же скетч выдаёт уже полноценные случайные 32-битные числа, которые вы можете использовать в своих проектах для любых целей.

Запись в заблокированную зону
Теперь давайте проверим функцию записи в заблокированную зону и попытаемся изменить байт I2C Address в конфигурационной зоне нашей микросхемы. Для этого воспользуемся несколько модернизированным скетчем из наших предыдущих статей.
/*
ATSHA204 Write Config I2C Address
*/
#include <sha204_library.h>
#define ATSHA204_PIN A3
byte bufTx[SHA204_CMD_SIZE_MAX];
byte bufRx[SHA204_RSP_SIZE_MAX];
byte slot = 4;
byte shift = 0;
byte addrDefault = 0xC8;
byte addrNew = 0x55;
#define SLOT_LEN 4
byte bufRead[SLOT_LEN];
byte bufWrite[SLOT_LEN];
atsha204Class sha204(ATSHA204_PIN);
void setup() {
Serial.begin(115200);
Serial.println(F("ATSHA204 Write Config I2C Address start..."));
Serial.print(F("Slot #")); Serial.println(slot);
readSlot();
seti2cAddress(addrNew);
writeConfig();
readSlot();
}
// Print
void printBuffer(byte* data, byte len) {
for (size_t i = 0; i < len; i++) {
if (data[i] < 10) {Serial.print('0');}
Serial.print(data[i], HEX);
if (i < len - 1) {Serial.print(' ');}
}
}
// Read
void copyReadToWrite() {
bufWrite[0] = bufRead[0];
bufWrite[1] = bufRead[1];
bufWrite[2] = bufRead[2];
bufWrite[3] = bufRead[3];
}
byte addr(byte slot) {
return slot * 4;
}
void readConf() {
byte retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
bufRead[0] = bufRx[SHA204_BUFFER_POS_DATA + 0];
bufRead[1] = bufRx[SHA204_BUFFER_POS_DATA + 1];
bufRead[2] = bufRx[SHA204_BUFFER_POS_DATA + 2];
bufRead[3] = bufRx[SHA204_BUFFER_POS_DATA + 3];
}
void readSlot() {
readConf();
copyReadToWrite();
Serial.print(F("Read: "));
printBuffer(bufRead, SLOT_LEN);
Serial.println();
}
// Write
void seti2cAddress(byte b) {
bufWrite[shift] = b;
}
void writeConfig() {
byte retCode = sha204.sha204m_execute(SHA204_WRITE,
SHA204_ZONE_CONFIG, slot,
4, bufWrite,
0, NULL,
0, NULL,
WRITE_COUNT_SHORT, bufTx,
WRITE_RSP_SIZE, bufRx);
if (retCode == 0) {Serial.println(F("Write Ok"));}
else {Serial.println(F("Write Error"));}
}
void loop() {
}
Запускаем скетч и видим ожидаемую реакцию системы — тот код, который отлично работает на новой микросхеме ATSHA204A, выдаёт ошибку при попытке изменить байт I2C Address в заблокированной конфигурационной зоне ATSHA204A.

Запись ключа в Data Zone
Теперь давайте перейдём ближе к практической плоскости и попробуем решить задачу записи ключа шифрования в зону данных (Data Zone) нашей микросхемы ATSHA204A. Это один из важных этапов работы потому, что в реальных проектах вам придётся сохранять ключи шифрования в памяти ATSHA204A.
Для примера мы выберем максимально упрощённую задачу: нам нужно будет сохранить 32-битный ключ hmacKey в нулевом слоте Data зоны микросхемы ATSHA204A. Поскольку это тестовый пример, байты ключа выбраны произвольным образом и равны 0x01.
uint8_t hmacKey[] = {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01};
Полный код скетча ATSHA204 Data Zone Write Key:/*
ATSHA204 Data Zone Write Key
*/
#include <sha204_library.h>
#define ATSHA204_PIN A3
byte bufTx[SHA204_CMD_SIZE_MAX];
byte bufRx[SHA204_RSP_SIZE_MAX];
byte retCode = 0;
uint8_t hmacKey[] = {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01};
atsha204Class sha204(ATSHA204_PIN);
void setup() {
Serial.begin(115200);
Serial.println(F("ATSHA204 Data Zone Write Key..."));
Serial.print(F("Key: "));
printBuffer(hmacKey, 32);
Serial.println();
storeHmacKey(hmacKey);
}
void printBuffer(byte* data, byte len) {
for (size_t i = 0; i < len; i++) {
if (data[i] < 16) {Serial.print('0');}
Serial.print(data[i], HEX);
if (i < len - 1) {Serial.print(' ');}
}
}
void storeHmacKey(uint8_t* key) {
retCode = 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, bufTx,
WRITE_RSP_SIZE, bufRx);
if (retCode == 0) {Serial.println(F("Write Ok"));}
else {Serial.println(F("Write Error"));}
}
void loop() {
}
Вначале мы объявляем массив с 32-я байтами ключа (в ваших реальных проектах это должны быть байты секретного крипто-ключа).
uint8_t hmacKey[] = {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01};
Затем функция storeHmacKey() сохраняет переданный ей ключ в микросхеме ATSHA204A.void storeHmacKey(uint8_t* key) {
retCode = 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, bufTx,
WRITE_RSP_SIZE, bufRx);
if (retCode == 0) {Serial.println(F("Write Ok"));}
else {Serial.println(F("Write Error"));}
}
И выводит результат проведения операции «Ok» или «Error».
if (retCode == 0) {Serial.println(F("Write Ok"));}
else {Serial.println(F("Write Error"));}
Саму работу по записи ключа осуществляет библиотечная функция sha204.sha204m_execute(). retCode = 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, bufTx,
WRITE_RSP_SIZE, bufRx);
Вот результат работы нашего скетча на экземпляре микросхемы ATSHA204A с заблокированной зоной конфигурации (и разблокированной Data Zone).

Как видите, запись ключа произведена успешно. Можно несколько раз запустить скетч и изменить байты ключа — операция записи также будет проходить успешно — до тех пор, пока не будет заблокирована зона данных, можно свободно перезаписывать сохранённый ключ.
Теперь для проверки попробуем запустить тот же скетч на микросхеме с незаблокированной конфигурационной зоной. Вот результат такой попытки:

Всё верно, как и ожидалось, попытка записать ключ в зону данных микросхемы ATSHA204A с незаблокированной конфигурационной зоной окончилась неудачей.
Обратите внимание, мы находимся на этапе, когда зона конфигурации заблокирована, а зона данных — нет и в этом состоянии мы не можем проверить правильность записи ключа в память ATSHA204A, мы можем только полагаться на код результата выполнения операции записи и доверять ему. Проверить и удостовериться, что ключ (ключи и прочие данные) корректно записаны в Data Zone мы сможем только после блокировки самой Data Zone.
Заключение
В этой статье мы рассмотрели работу с микросхемой ATSHA204A в режиме заблокированной конфигурационной зоны и незаблокированной Data Zone. Блокировка конфигурационной зоны позволяет включить некоторые функции ATSHA204A, а также открывает на запись зоны Data и OTP.
В следующих статьях мы подробно разберём организацию зон памяти ATSHA204A и приёмы сохранения в них ключей, паролей, секретных данных и счётчиков (counters) и прочих ресурсов.
Ссылки по теме
ATSHA204 - Библиотека и примеры
ATSHA204A - Чтение зоны конфигурации 1
ATSHA204A - Чтение зоны конфигурации 2
ATSHA204A - Чтение зоны конфигурации 3
ATSHA204A - Запись конфигурации 1
ATSHA204A - Запись конфигурации 2
ATSHA204A - Запись конфигурации 3
ATSHA204A - Запись конфигурации 4
ATSHA204A - Работа с зонами памяти
ATSHA204A - Чтение Data и OTP зон памяти
ATSHA204A - Аутентификация. Базовый блок
ATSHA204A - Аутентификация. Датчик
ATSHA204A - Криптография и команды
ATSHA204A - nRF24 аутентификация. База
ATSHA204A - nRF24 аутентификация. Датчик



