logo
+7 (495) 997-37-74
Москва, ул.Международная, 15

ATSHA204A — Работа с зонами памяти

После блокировки зоны конфигурации микросхемы ATSHA204A наступает этап, когда вы можете сохранять нужные вам данные (ключи, пароли, хеши, счётчики и т. п.) в зоне данных (Data Zone) и зоне OTP (One Time Programmable). Для грамотной и осмысленной работы с ATSHA204A нужно хорошо понимать назначение и организацию всех её зон памяти, без этого работа с криптомикросхемой ATSHA204A просто невозможна.

В этой статье мы подробно рассмотрим организацию и работу различных зон памяти ATSHA204A и приведём практические примеры кода работы с памятью этой микросхемы.

Организация памяти

ATSHA204A содержит два вида памяти — энергонезависимую EEPROM и оперативную SRAM. Оперативная память используется для хранения ключей и данных в процессе работы микросхемы, а энергонезависимая EEPROM — для долговременного хранения ключей и различной секретной информации. В этой статье мы будем рассматривать только работу с энергонезависимой EEPROM памятью.

Всего EEPROM содержит 664 байта (5312 бит), разделённые на несколько зон.

Зона 1: Data. 512 байт (4096 бит), разбитые на 16 слотов по 32 байта. Доступ на чтение или чтение/запись этих слотов можно устанавливать программным способом при конфигурировании устройства. Эта зона используется для хранения ключей, конфигурационных данных, серийных номеров устройств и для т. п. целей.

Зона 2: Configuration. 88 байт (704 бита) — это зона конфигурационных данных ATSHA204A. Она содержит серийный номер и другие идентификационные данные микросхемы ATSHA204A, а также информацию о разрешении доступа для каждого слота данных и прочие настройки.

Зона 3: OTP (One Time Programmable). 64 байта (512 бит). Это зона, которая используется для хранения данных только для чтения или одноразовой установки. До блокировки зоны OTP биты могут быть свободно записаны с использованием стандартной процедуры записи.

Режимы доступа

Работа и доступ ко всем трём зонам памяти (Data, Configuration, OTP) является довольно запутанным нетривиальным вопросом. В даташите ATSHA204A описана весьма сложная схема как доступа к самим зонам памяти, так и схема взаимовлияния настроек отдельных зон друг на друга.

Кроме того, функции доступа к зонам памяти на запись и чтение изобилуют множеством дополнительных параметров и сам доступ регламентируется как по битности (4 или 32-бит), так и по блокам/слотам и смещением (offset) в этих блоках. Плюс всё это обильно сдобрено битовой математикой и множеством правил чтения/записи.

В общем, для того, чтобы во всём этом разобраться, требуется довольно серьёзная квалификация в программировании. С другой стороны, не понимая все эти детали, вы просто не сможете сколько-нибудь эффективно использовать ATSHA204A. А скорее всего просто не сможете с ней работать.

Поэтому мы здесь попробуем простыми словами объяснить все эти тонкости работы с ATSHA204A.

Блокировка зон

Для работы с ATSHA204A прежде всего необходимо чётко представлять себе иерархию режимов блокировки зон памяти этой микросхемы и её свойства (функционал) на различных этапах.

Общий принцип сводится к тому, что вначале мы устанавливаем необходимые нам настройки в конфигурационной зоне, затем блокируем конфигурационную зону и вносим нужные нам данные в Data и OTP зоны и затем блокируем их тоже и только после этого можем использовать ATSHA204A в своих устройствах.

Упрощённо последовательность работы с ATSHA204A можно представить следующим образом:

  1. Запись Config зоны
  2. Блокировка Config зоны
  3. Запись Data зоны
  4. Запись OTP зоны
  5. Блокировка Data Lock
  6. Чтение Data/OTP

Вот таблица с наглядным представлением этапов блокировки различных зон памяти ATSHA204A и свойствами чтения/записи этих зон на различных этапах.

Это общая таблица, не в полной мере отражающая различные нюансы доступа к памяти ATSHA204A, описанные в даташите, но в целом очень полезная для понимания принципов работы с ATSHA204A.

Первая строка таблицы — это начальное состояние ATSHA204A, когда конфигурационная зона не заблокирована и доступна для чтения и записи, а Data/OTP зоны недоступны ни для чтения, ни для записи.

Вторая строка — это состояние ATSHA204A после блокировки конфигурационной зоны. На этом этапе запись в эту зону заблокирована (за исключением Extra команд), а запись в зоны Data/OTP разрешена.

Третья строка — это состояние после Data Lock, когда становится возможным чтение из Data/OTP зон и частичная, в соответствии с установленными ранее правилами, запись в эти зоны.

Организация слотов (блоков)

Вся память микросхемы ATSHA204A разбита на слоты (блоки) и различные зоны памяти содержат разное количество этих слотов. Внутри слоты по 32 байта разбиты на «смещения» (offsets) по 4 байта. Вот таблица из даташита, которая описывает организацию слотов и доступ к ним в зависимости от режима.

Обращение к различным данным внутри зон памяти на чтение и запись происходит в нотации Block-Offset (см. таблицу ниже). Обращение это двухбайтовое, где старший байт всегда равен нулю, а младший формируется в зависимости от зоны.

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

В даташите также регламентируются дополнительные правила и ограничения работы с блоками (слотами) памяти ATSHA204A.

Теперь давайте составим таблицы слотов (blocks) и смещений (offsets) для всех зон памяти ATSHA204A.

Configuration Zone

Начнём с конфигурационной зоны (Configuration Zone). Согласно вышеприведённых таблиц из даташита, конфигурационная зона состоит из 3-х слотов (блоков), причём первые два блока являются полностью доступными для чтения и записи (в соответствующих режимах), а третий блок является доступным только частично. В целом, в конфигурационной зоне доступны только 88 байт, о назначении которых было подробно рассказано в предыдущих статьях этого цикла.

Сложность понимания работы с зонами памяти обусловлена ещё и тем, что в различных режимах и различных частях документации (даташита) одни и те же участки памяти упоминаются по разному: в одних местах говорится о значении ячеек памяти в десятичном формате, в других — в шестнадцатеричном, в третьих — нотация идёт в «словах» (WORD), в четвёртых — в шестнадцатеричных словах (WORD-HEX), в пятых — в нотации Block-Offset и т. д. и т. п., причём в разных случаях речь может идти как о 4-байтовом, так и 32-байтовом доступе.

В общем, разобраться во всём этом многообразии очень и очень непросто, поэтому, для лучшего понимания, мы составили подробные таблицы распределения байтов, слотов и смещений для каждой из зон ATSHA204A.

Начнём с таблицы доступа к конфигурационной зоне:

Используя эту таблицу, вам будет значительно легче разбираться с тем, что написано в даташите и с её помощью вы сможете осмысленно создавать запросы на запись и чтение данных из ATSHA204A.

Зона данных (Data Zone)

Зона данных ATSHA204A организована несколько по другому. Здесь присутствуют 16 слотов (блоков) памяти по 32 бита, каждый из которых, в свою очередь разбит на 8 смещений (offset) по 4 байта. Здесь нет неполных слотов, доступных для чтения/записи только частично, все слоты могут быть записаны и прочитаны в соответствующих режимах.

Таблица доступа к зоне данных:

OTP зона

OTP (One Time Programmable) зона состоит из 2-х блоков по 32 бита. Читается и пишется эта зона в соответствии с вышеприведёнными правилами, а значения по умолчанию всех байтов этой зоны равны 0xFF, то есть все биты выставлены в 1.

Таблица доступа к OTP зоне:

Это тот самый минимум информации, который необходим вам для понимания того как устроена и работает EEPROM память микросхемы ATSHA204A. Но без вдумчивого чтения и анализа того, что написано в даташите вам не обойтись — ATSHA204A имеет слишком развитую, изощрённую и неочевидную логику работы.

Запись ключей в Data зону

Теперь, вооружившись знаниям, представленными в этой статье, давайте попробуем создать скетч, который будет записывать 16 ключей в Data зону микросхемы ATSHA204A. В качестве основы мы возьмём скетч из предыдущей статьи и соответствующим образом его модернизируем.

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

Сначала полный код скетча ATSHA204 Data Zone Write Keys, а потом подробный разбор его работы.

/* 
  ATSHA204 Data Zone Write Keys
*/

#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[16][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},
  {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},
  {0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02},
  {0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03},
  {0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04},
  {0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05},
  {0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06},
  {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07},
  {0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08},
  {0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09},
  {0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A},
  {0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B},
  {0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C},
  {0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D},
  {0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E},
  {0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F},
};

atsha204Class sha204(ATSHA204_PIN);

void setup() {
  Serial.begin(115200);
  Serial.println(F("ATSHA204 Data Zone Write Keys..."));

  for (byte i = 0; i < 16; i++) {
    storeHmacKey(i, hmacKey[i]);
  }
}

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(byte slt, uint8_t* key) {
  Serial.print("Slot");
  if (slt < 10) {Serial.print('0');}
  Serial.print(slt);
  Serial.print(": ");
  
  printBuffer(key, 32);
  
  retCode = sha204.sha204m_execute(SHA204_WRITE,
                                   SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, slt << 3,
                                   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() {

}

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

uint8_t hmacKey[16][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},
  {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},
  {0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02},
  {0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03},
  {0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04},
  {0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05},
  {0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06},
  {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07},
  {0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08},
  {0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09},
  {0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A},
  {0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B},
  {0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C},
  {0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D},
  {0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E},
  {0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F},
};

Затем 16 раз вызываем функцию storeHmacKey(), передавая ей в качестве параметров текущий номер слота (0–15) и соответствующий 32-битный ключ из массива hmacKey.

  for (byte i = 0; i < 16; i++) {
    storeHmacKey(i, hmacKey[i]);
  }

Далее, в функции storeHmacKey() выводим вспомогательную информацию

  Serial.print("Slot");
  if (slt < 10) {Serial.print('0');}
  Serial.print(slt);
  Serial.print(": ");
  
  printBuffer(key, 32);

и результат проведения операции записи очередного ключа в Data зону ATSHA204A

  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, slt << 3,
                                   SHA204_ZONE_ACCESS_32, key,
                                   0, NULL,
                                   0, NULL,
                                   WRITE_COUNT_LONG, bufTx,
                                   WRITE_RSP_SIZE,   bufRx);

Для нас, в контексте этой статьи, будет важна строка

                                   SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, slt << 3,

в которой определяется место (зона) записи

                                   SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG

и адрес в нотации блок (слот) плюс нулевое смещение (offset) с битовым сдвигом на 3 позиции влево, согласно правилам доступа к памяти ATSHA204A, рассмотренным в начале этой статьи.

slt << 3

В результате работы нашего скетча мы можем видеть в Serial сообщение об удачной записи всех 16-и ключей в Data зону микросхемы ATSHA204A.

Заключение

Как вы видите, чип ATSHA204A является поистине неисчерпаемым источником технических спецификаций и криптографических возможностей и в следующих статьях мы продолжим увлекательный процесс знакомства с этой микросхемой.

Ссылки по теме

Работа с SHA-256

ATSHA204 - Обзор

ATSHA204 - Спецификации

ATSHA204 - Библиотека и примеры

ATSHA204A - Чтение зоны конфигурации 1

ATSHA204A - Чтение зоны конфигурации 2

ATSHA204A - Чтение зоны конфигурации 3

ATSHA204A - Запись конфигурации 1

ATSHA204A - Запись конфигурации 2

ATSHA204A - Запись конфигурации 3

ATSHA204A - Запись конфигурации 4

ATSHA204A - Config Lock

ATSHA204A - Работа в режиме Config Lock

ATSHA204A - Запись зоны OTP

ATSHA204A - Data Lock

ATSHA204A - Чтение Data и OTP зон памяти

ATSHA204A - Команда MAC

ATSHA204A - Аутентификация. Базовый блок

ATSHA204A - Аутентификация. Датчик