Для микроконтроллеров AVR, у которых интерфейс USB реализован на библиотеке V-USB, есть хороший загрузчик (bootloader) USBasp [1], эмулирующий поведение одноименного популярного программатора USBasp [2]. Изначально этот загрузчик принимает для прошивки незащищенные HEX-файлы, что иногда неприемлемо для коммерческого распространения обновлений firmware.
Есть возможность защитить содержимое кода, если применить шифрование распространяемой публично прошивки firmware (обычно это файл в формате Intel HEX). Простое и надежное шифрование - накладывание псевдослучайной маски XOR (сгенерированный ключ, обычно псевдослучайная последовательность байт) на данные прошивки. Как известно, логическая операция XOR это исключающее ИЛИ, в нашем случае исключающее ИЛИ между битами данных прошивки и битами данных псевдослучайного ключа. Чтобы расшифровать прошивку, бутлоадер при получении данных должен наложить по XOR точно такую же маску (такой же псевдослучайный ключ, который накладывался по XOR при шифровании). Пример XOR шифрования и дешифрования прошивки наглядно показан на картинке.
После окончания шифрования файл прошивки получается защищенным - его можно свободно передавать по открытым каналам связи (email, публикация на сайте и т. п.), причем для неавторизованных пользователей он будет бесполезен - его можно прошить только в те целевые устройства, в которых микроконтроллер имеет точно такой же алгоритм генерации псевдослучайной последовательности данных, которая была применена при шифровании прошивки.
Для генерации псевдослучайной последовательности байт могут использоваться различные известные алгоритмы [4]. В этой разработке использовался стандартный алгоритм на основе линейного регистра сдвига с обратной связью (Linear Feedback Shift Register, LFSR), его готовую 32-разрядную реализацию можно найти в [5]. Для того, чтобы шифрование и дешифрование проходило успешно, на стороне шифрования и дешифрования должен быть одинаковый алгоритм генерирования случайных чисел, с одинаковым значением ключа для инициализации алгоритма LFSR.
[Утилита XOR-firmware-cryptor.exe для шифрования прошивки]
Для шифрования прошивки (firmware микроконтроллера, которое загружает бутлоадер) написана (на Visual Studio C#) консольная утилита XOR-firmware-cryptor.exe [3], которая на входе принимает 3 параметра командной - имя входного HEX-файла шифруемой прошивки (опция -fi), имя выходного HEX-файла зашифрованной прошивки (опция -fo) и ключ шифрования (опция -seed). Пример вызова утилиты для генерации шифрованной прошивки:
XOR-firmware-cryptor.exe -fi:ATmega32-12MHz.hex -fo:crypted-ATmega32-12MHz.hex.hex -seed:1234
Для того, чтобы шифрование и дешифрование проходило успешно, на стороне шифрования и дешифрования должен быть одинаковый алгоритм генерирования случайных чисел, с одинаковым значением ключа для инициализации алгоритма LFSR. Ключ шифрования 1234 в этом примере используется для инициализации регистра сдвига генератора псевдослучайных чисел LFSR. Значение параметра для опции -seed может быть десятичным числом от 2 до 4294967295 (максимальное значение 2 в степени 32 минус 1, так как регистр сдвига LFSR 32-разрядный). Если указать для seed значения 0 или 1, то генератор LFSR работать не будет (вся генерируемая последовательность чисел будет нулевая: 0x00, 0x00, 0x00, ..). Это особенность используемого алгоритма LFSR.
Сам генератор LFSR утилиты шифрования реализован в виде отдельного класса C# LFSR32 (модуль LFSR32.cs). Класс имеет простые методы srand и rand:
void srand(UInt32 seed); //Инициализация LFSR (в нашем примере вызова
// XOR-firmware-cryptor.exe в параметр seed
// передано десятичное число 1234, которое
// будет загружено в регистр сдвига LFSR).
byte rand(); //Получение очередного случайного байта.
Разбором формата HEX занимается отдельный класс C# hexfirmware (модуль hexfirmware.cs). Он нужен для получения двоичных данных и адресов из исходного HEX-файла, и для сохранения шифрованного HEX-файла.
[Бутлоадер USBasp с функцией загрузки шифрованной прошивки]
Бутлоадер USBasp записан в секцию загрузки (bootloader section), выбранную установкой фьюзов AVR. Чтобы бутлоадер с поддержкой шифрования поместился в секцию, её размер должен быть выбран 4096 байт (2048 слов команд AVR). Такая секция есть только у микроконтроллеров AVR, имеющих объем памяти FLASH от 32 кбайт и более (например, ATmega32A, ATmega328P, ATmega64, ATmega128 и т. п.). На рисунке показан пример адресного пространства ATmega32A (этот микроконтроллер применен в макетной плате AVR-USB-MEGA16 [6]) - размещение секции бутлоадера и кода загружаемой программы.
Дешифрование прошивки в бутлоадере происходит точно по такому же алгоритму, как и шифрование - генерируется псевдослучайная последовательность байт на основе алгоритма LFSR (код реализован в модуле LFSR32.c). Значение ключа шифрования задана в файле bootloaderconfig.h, в параметре #define SEED 1234. Этот ключ жестко вшит в прошивку, и если нужно поменять значение SEED, то после исправления код бутлоадера нужно перекомпилировать.
Для того, чтобы загружаемую прошивку и код бутлоадера нельзя было прочитать, установите биты защиты (фьюзы Lock Bits). Например, байт установки битов защиты для ATmega32A должен быть равен 0xFC. Если биты защиты не установлены, то шифрование не имеет никакого смысла, так как прошивку и сам бутлоадер вместе с ключом шифрования SEED можно легко прочитать программатором ISP.
[Ссылки]
1. AVR-USB-MEGA16: USB bootloader USBasp для микроконтроллера ATmega32. 2. USBasp - USB programmer for Atmel AVR controllers site:fischl.de. 3. 130901USBasp-bootloader-XOR-crypt.zip - исходный код утилиты XOR-firmware-cryptor, инсталлятор для неё, исходный код и готовые прошивки бутлоадера USBasp с поддержкой XOR-шифрования (использовался ключ SEED 1234). 4. Генератор псевдослучайных чисел site:wikipedia.org. 5. Fast AVR 32-bit LFSR site:gist.github.com. 6. Макетная плата AVR-USB-MEGA16. 7. Intel HEX: описание формата файла. 8. Atmel AVR230: DES Bootloader. 9. Atmel AVR231: AES Bootloader. |
Комментарии
RSS лента комментариев этой записи