Знаете ли вы, что в eMMC есть специальный раздел под названием RPMB, который позволяет хранить данные с поддержкой целостности и подлинности?
RPMB был представлен в eMMC версии 4.4, и, поскольку в настоящее время многие встроенные конструкции Linux используют eMMC.
В этой статье мы узнаем, что такое раздел RPMB и как он работает, основные варианты его использования и как получить к нему доступ в Linux.

Что такое раздел RPMB?​

RPMB (блок памяти с защитой от воспроизведения) — это выделенный раздел, доступный на некоторых флэш-накопителях (eMMC, UFS, NVMe и т. д.), который позволяет хранить и извлекать данные с поддержкой целостности и аутентичности.

rpmb-partition.png


Интерфейс RPMB определяется организацией JEDEC , и доступ к нему возможен с помощью специального стандартизированного протокола безопасности, который имеет свои собственные команды и структуры данных. Он использует аутентификацию с симметричным ключом , при которой ключ аутентификации используется как хостом (например, ОС Linux), так и устройством (например, eMMC) для обмена аутентифицированными данными. Вкратце, это работает следующим образом:
  1. Ключ аутентификации сначала программируется хостом на устройстве хранения (это должно происходить в безопасной среде, обычно на производственной линии).
  2. При записи на устройство данные хешируются и подписываются ключом аутентификации, а запоминающее устройство примет операцию записи только после проверки подписи (эта подпись также называется кодом аутентификации сообщения или просто MAC).
  3. При чтении с устройства данные возвращаются вместе с MAC. Хост также может вычислить MAC и сравнить его с полученным, чтобы убедиться в подлинности сообщения.
Подробнее об этом процессе мы узнаем позже. А сейчас я хочу сосредоточиться на одном важном аспекте раздела RPMB — части «Защищенное воспроизведение»…

Что такое повторная атака?​

Атака повторного воспроизведения (или воспроизведения) происходит, когда программа копирует данные из законного взаимодействия с участием двух объектов, а затем повторно передает те же данные на более позднем этапе.
Поскольку исходная информация содержит правильные идентификаторы отправителя и получателя, а также подтверждение подлинности данных, повторно переданные данные (если не будут приняты меры против атаки повторного воспроизведения) будут приняты так же, как это было в первый раз, когда они были переданы. .
В качестве примера повторной атаки представьте себе гаражный пульт дистанционного управления. При нажатии кнопки пульта дистанционного управления в гаражную систему отправляется сообщение, и ворота гаража открываются.
Что, если «человек посередине» (MITM) сможет перехватить связь между пультом дистанционного управления и гаражной системой? Возможно, она сможет повторно отправить (воспроизвести) сообщение позже и, если не будут приняты меры против повторной атаки, открыть дверь гаража!
Так как же защитить систему от атаки повторного воспроизведения? Нам нужно убедиться, что каждое сообщение уникально.
В RPMB счетчик, доступный только для чтения, используется при каждой операции записи. Этот счетчик увеличивается после каждой операции записи и включается в расчет следующего отправляемого MAC-адреса. Таким образом, даже если кто-то сможет перехватить операцию записи, воспроизведение того же сообщения не сработает, поскольку это потребует повторного расчета MAC с новым счетчиком, а это может сделать только тот, у кого есть ключ аутентификации. !
Защита от повторных атак — очень полезная функция, которая делает раздел RPMB интересным решением в различных случаях использования.

Варианты использования RPMB​

Одним из распространенных вариантов использования раздела RPMB является аутентификация версий программного обеспечения для предотвращения атаки на понижение версии.
Подумайте о сценарии, в котором производитель может удаленно загружать обновления программного обеспечения на устройство:
  1. Во время обновления программное обеспечение записывается в основную область eMMC, а информация о версии сохраняется в RPMB.
  2. Производитель обнаруживает, что в версии программного обеспечения имеется ошибка безопасности.
  3. Производитель предлагает обновление программного обеспечения, чтобы решить проблему.
  4. Новое программное обеспечение записывается в основную область eMMC, а информация о версии обновляется в RPMB.
В этой ситуации злоумышленник может попытаться перехватить связь и имитировать процедуру, используемую производителем для распространения обновления, с целью понизить версию программного обеспечения и воспользоваться ошибкой безопасности в предыдущей версии.

Этому может помешать раздел RPMB. Поскольку у злоумышленника нет ключа аутентификации для обновления версии программного обеспечения в разделе RPMB, у злоумышленника нет возможности понизить версию программного обеспечения.
Наряду с шифрованием и аппаратными предохранителями, RPMB также можно использовать для создания доверенного решения хранения данных для доверенной среды выполнения (TEE) .
Раздел RPMB также можно использовать в качестве общего места хранения для записи «постоянных» или «запрограммированных» данных в системе без какого-либо программируемого ПЗУ.
Другие варианты использования могут включать проверку отпечатков пальцев и аутентификацию пользователей, управление цифровыми правами (DRM), безопасные платежи и т. д.
Теперь давайте углубимся в то, как работает раздел RPMB.

Глубокое погружение в RPMB​

RPMB — это небольшой раздел на запоминающем устройстве со следующей структурой:

РазделДоступРазмер
Ключ аутентификацииНапишите один раз (не стирается и не читается)32 байта
Счетчик записиТолько чтение4 байта
Область данных РПБМЧитай пишиКратный 128Кб

Фактический размер области данных зависит от реализации, но он должен быть кратен 128 КБ и максимум 16 МБ.
Протокол RPMB документирован в стандарте JEDEC № 220 .
Существует четыре команды для взаимодействия с разделом RPMB:
  • ПРОГРАММА_КЛЮЧ
  • GET_WRITE_COUNTER
  • ПИСАТЬ
  • ЧИТАТЬ
Давайте подробно узнаем, как работают эти команды.

Команда PROGRAM_KEY

Чтобы использовать раздел RPMB, нам нужно сначала запрограммировать ключ аутентификации с помощью команды PROGRAM_KEY .
Ключ аутентификации представляет собой 256-битный ключ, запрограммированный в области OTP (одноразово программируемый) eMMC. Это секретный ключ, который можно запрограммировать только один раз за весь срок службы устройства, и после программирования он невидим для любого программного обеспечения.
Этот ключ необходимо создать в безопасной среде, например, в OEM-производстве, записать на устройство RPMB и надежно хранить где-нибудь на целевой платформе.
Это означает, что для правильного использования раздела RPMB рекомендуется какое-то безопасное хранилище. Пример:
  1. Главный ключ генерируется и сохраняется на защищенном устройстве хранения ( TPM , безопасный элемент, CAAM на iMX SoC и т. д.).
  2. Когда генерируется ключ аутентификации RPMB, он шифруется этим главным ключом и сохраняется где-то в eMMC.
  3. Если требуется доступ к RPMB, главный ключ используется для расшифровки ключа аутентификации RPMB.
  4. Для большей безопасности эти операции обычно выполняются в доверенной среде выполнения.

Команда GET_WRITE_COUNTER

Для записи в раздел RPMB необходим счетчик записи, который можно получить с помощью команды GET_WRITE_COUNTER .
Счетчик записи представляет собой число размером 4 байта, поэтому он имеет ограничение в 4.294.967.296 записей.
Согласно спецификации, значение не может быть сброшено. После того, как счетчик достигнет максимального значения, он больше не будет увеличиваться (предотвращение переполнения).

Команда ЗАПИСАТЬ​

При выполнении команды WRITE MAC (код аутентификации сообщения) рассчитывается с помощью алгоритма HMAC SHA-256 , который принимает на вход:
  • Само сообщение (данные).
  • Ключ аутентификации.
  • Счетчик записи (для защиты от атак повторного воспроизведения).
Результирующий MAC представляет собой 256-битный (32 байта) шифр, встроенный в кадр данных RPMB и отправляемый вместе с сообщением.
Когда устройство хранения получает команду записи, оно проверяет подлинность команды, проверяя, что счетчик был увеличен и MAC, отправленный хостом, идентичен MAC, рассчитанному устройством.

rpmb-write.png

Команда ЧИТАТЬ​

При выполнении команды READ хост отправит запрос вместе с nonce (случайным числом) для защиты от атак повторного воспроизведения.
Устройство вернет данные вместе с MAC (кодом аутентификации сообщения), рассчитанным с использованием алгоритма HMAC SHA-256 , принимая в качестве входных данных:
  • Сообщение (данные).
  • Ключ аутентификации.
  • Одноразовый номер, отправленный хостом.
При получении данных хост должен проверить подлинность сообщения, вычислив MAC и сравнив его с возвращаемым устройством.
Без ключа RPMB доступ для чтения по-прежнему возможен, но считываемые данные могут быть неаутентичными (нет гарантии целостности/подлинности данных и защиты от повторного воспроизведения). Это также означает, что любой может прочитать RPMB, поэтому RPMB не обеспечивает конфиденциальность данных (при необходимости шифрование должно выполняться программным обеспечением).
Давайте теперь попрактикуемся…

Доступ к RPMB из Linux​

В своих тестах я использую SoM Colibri iMX6 от Toradex, работающий под управлением основного ядра Linux.

# cat /proc/device-tree/model
Toradex Colibri iMX6DL/S on Colibri Aster Board

# cat /proc/version
Linux version 6.2.0-rc3-labworks-00009-g49ed1130dcca (sprado@sprado-office) (arm-linux-gcc.br_real (Buildroot 2022.11) 11.3.0, GNU ld (GNU Binutils) 2.38) #9 SMP Sat Jun 3 10:39:09 -03 2023
Основная версия Linux уже имеет встроенную поддержку RPMB в нескольких подсистемах хранения, включая UFS и MMC.

Если у вас есть целевая платформа с устройством хранения данных eMMC, вы можете проверить, доступен ли раздел RPMB, выполнив поиск файла raw_rpmb_size_mult в /sys :

# find /sys -name raw_rpmb_size_mult 2>&-
/sys/devices/platform/soc/2100000.bus/2198000.mmc/mmc_host/mmc2/mmc2:0001/raw_rpmb_size_mult

# cat /sys/devices/platform/soc/2100000.bus/2198000.mmc/mmc_host/mmc2/mmc2:0001/raw_rpmb_size_mult
0x20
В этом примере устройство хранения данных mmc2 имеет раздел RPMB размером 4 МБ (0x20 * 128 КБ).

Доступ к разделу RPMB можно получить через блочное устройство:

# ls /dev/mmcblk2rpmb
Чтобы получить доступ к разделу RPMB, мы можем использовать команду mmc из пакета mmc-utils . Эта команда имеет подкоманду rpmb для связи с разделом RPMB:

# mmc -h
Usage:
...
mmc rpmb write-key <rpmb device> <key file>
Program authentication key which is 32 bytes length and stored
in the specified file. Also you can specify '-' instead of
key file path to read the key from stdin.
NOTE! This is a one-time programmable (unreversible) change.
Example:
$ echo -n AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH | \
mmc rpmb write-key /dev/mmcblk0rpmb -
mmc rpmb read-counter <rpmb device>
Counter value for the <rpmb device> will be read to stdout.
mmc rpmb read-block <rpmb device> <address> <blocks count> <output file> [key file]
Blocks of 256 bytes will be read from <rpmb device> to output
file or stdout if '-' is specified. If key is specified - read
data will be verified. Instead of regular path you can specify
'-' to read key from stdin.
Example:
$ echo -n AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH | \
mmc rpmb read-block /dev/mmcblk0rpmb 0x02 2 /tmp/block -
or read two blocks without verification
$ mmc rpmb read-block /dev/mmcblk0rpmb 0x02 2 /tmp/block
mmc rpmb write-block <rpmb device> <address> <256 byte data file> <key file>
Block of 256 bytes will be written from data file to
<rpmb device>. Also you can specify '-' instead of key
file path or data file to read the data from stdin.
Example:
$ (awk 'BEGIN {while (c++<256) printf "a"}' | \
echo -n AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH) | \
mmc rpmb write-block /dev/mmcblk0rpmb 0x02 - -
...
Первым шагом для доступа к разделу RPM является запись ключа.

В целях тестирования давайте создадим ключ с помощью OpenSSL и сохраним его в файле. Но помните, что этот ключ следует хранить на безопасном устройстве хранения, чтобы использовать функции безопасности раздела RPMB.

# openssl rand 32 > key
Теперь мы можем записать ключ к разделу RPMB. Имейте в виду, что это разовая операция!

# mmc rpmb write-key /dev/mmcblk2rpmb key
Теперь мы можем прочитать счетчик записи, который должен начинаться с нуля, поскольку мы только что настроили ключ:

# mmc rpmb read-counter /dev/mmcblk2rpmb
Counter value: 0x00000000
Давайте запишем некоторые данные в устройство.

Запись осуществляется командой mmc блоками по 256 байт. Итак, давайте создадим файл данных размером 256 байт, используя содержимое файла /proc/version .

# dd if=/proc/version of=data bs=256 count=1 conv=sync
Теперь мы можем записать данные. Запишем его в начало раздела RPMB:

# mmc rpmb write-block /dev/mmcblk2rpmb 0 data key
После записи данных мы можем подтвердить, что счетчик записи был увеличен:

# mmc rpmb read-counter /dev/mmcblk2rpmb
Counter value: 0x00000001
Можем прочитать с устройства и подтвердить, что данные записаны успешно (передавая ключ, также проверяется подлинность):

# mmc rpmb read-block /dev/mmcblk2rpmb 0 1 - key
Linux version 6.2.0-rc3-labworks-00009-g49ed1130dcca (sprado@sprado-office) (arm-linux-gcc.br_real (Buildroot 2022.11) 11.3.0, GNU ld (GNU Binutils) 2.38) #9 SMP Sat Jun 3 10:39:09 -03 2023
Чтение также работает без передачи ключа. В этом случае нет никакой гарантии целостности и подлинности возвращаемых данных:

# mmc rpmb read-block /dev/mmcblk2rpmb 0 1 -
Linux version 6.2.0-rc3-labworks-00009-g49ed1130dcca (sprado@sprado-office) (arm-linux-gcc.br_real (Buildroot 2022.11) 11.3.0, GNU ld (GNU Binutils) 2.38) #9 SMP Sat Jun 3 10:39:09 -03 2023
Что, если мы попытаемся прочитать, используя неправильный ключ? Как и ожидалось, код аутентификации не совпадет, и чтение не удастся!

# openssl rand 32 > wrong-key
# mmc rpmb read-block /dev/mmcblk2rpmb 0 1 - wrong-key
RPMB MAC missmatch
Выполнение всех этих операций в Linux может открыть поверхность атаки для злоумышленников, поскольку ключ аутентификации предоставляется для выполнения операций RPMB.
Вот почему обычно Trusted Execution Environment (TEE) заявляет право собственности на раздел RPMB, поэтому эти операции можно выполнять в безопасной среде.


Автор : Серджио Прадо