Итак, после всех тестов и манипуляций с микросхемой 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 аутентификация. Датчик