Краткое резюме

Фотонная микроскопия позволила локализовать регистр, отвечающий за включение функций отладки на микроконтроллере Raspberry Pi.

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

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

Атака требует физического доступа, деструктивной подготовки и примерно $250 000 лабораторного оборудования.

Модель безопасности RP2350

RP2350 — это двухядерный микроконтроллер Raspberry Pi, каждый слот процессора может выбрать либо ядро Arm Cortex-M33, либо ядро RISC-V Hazard3 при загрузке. Его функции аппаратной безопасности включают:

  • Защищённую загрузку, которая аутентифицирует подписанную прошивку по отпечаткам открытого ключа, подготовленным в память One-Time Programmable (OTP)
  • Armv8-M TrustZone, разделяющую защищённое и незащищённое состояния выполнения
  • Постоянные параметры отключения отладки
  • Детекторы глитчей для обнаружения нарушений синхронизации, вызванных манипуляцией тактовой частотой или питанием

Raspberry Pi активно приглашает исследователей оценить эту защиту через RP2350 Hacking Challenges. Первый конкурс проходил с августа по декабрь 2024 года на оригинальном чипе. После исправления нескольких проблем Raspberry Pi выпустила ревизию A4 — версию, которую мы тестировали.

Постоянная конфигурация безопасности и отпечатки открытого ключа загрузки хранятся в памяти с однократной записью (OTP): каждый бит может быть переключён с 0 на 1 один раз и никогда не вернётся, поэтому всё записанное туда существует всё время жизни чипа.

OTP организована в 128-байтовые страницы, защищённые двумя постоянными, или жёсткими, строками блокировки: для страницы n, PAGEn_LOCK0 настраивает опциональные ключи чтения и записи и поведение при отсутствии ключа, тогда как PAGEn_LOCK1 содержит принудительно применяемые на аппаратном уровне разрешения LOCK_S и LOCK_NS. Эти состояния могут переходить от чтения-записи только к чтению или недоступным, но не могут становиться более разрешающими.

Подсистема OTP использует избыточное кодирование для полей, критических с точки зрения безопасности: критические флаги закодированы с трёхкратным голосованием из восьми в восьми последовательных строках OTP, а биты блокировки OTP используют тройную избыточность с голосованием по большинству, согласно даташиту RP2350.

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

Внешний отладчик взаимодействует с RP2350 через интерфейс Arm Serial Wire Debug (SWD). Запросы сначала достигают Serial Wire Debug Port (SW-DP), а затем маршрутизируются к портам доступа. В конфигурации Cortex-M33, используемой здесь, каждое ядро имеет порт доступа к памяти (Mem-AP), подключённый к его системной шине; включённый Mem-AP позволяет отладчику читать и записывать разрешённую память и периферийные устройства. Отдельный всегда включённый порт доступа, RP-AP, предоставляет небольшой набор управления сбросом и восстановлением.

Защищённая отладка — это доступ Mem-AP с атрибутом Security. Отладчик может затем осуществлять транзакции с защищёнными ресурсами, отображёнными в памяти, которые позволяет логика управления доступом, и останавливать или проверять ядро, работающее в защищённом состоянии.

Постоянный флаг CRIT1.DEBUG_DISABLE предназначен для закрытия этого пути. Когда он установлен, он устанавливает сигналы включения для Mem-AP обоих ядер на ноль, что предотвращает доступ APs к системной шине вообще, и отключает фабричный интерфейс JTAG и порт доступа модуля отладки RISC-V. SW-DP и RP-AP всё ещё отвечают, но ни один Mem-AP ядра не может получить доступ к системной шине.

Однако существует переопределение: регистр, отображённый в памяти, DEBUGEN позволяет защищённому программному обеспечению повторно включить Mem-AP каждого ядра и, отдельно, защищённый доступ через него. Даташит указывает, что DEBUG_DISABLE может быть полностью переопределён установкой всех битов этого регистра.

Это критическое переопределение в цепи принудительного применения было тем, что сделало интерфейс отладки нашей целью. Получение доступа к защищённой отладке на Mem-AP — это универсальный примитив для чтения и записи защищённой памяти, остановки и пошагового выполнения ядра и проверки его регистров. Вопрос в том, может ли этот регистр быть установлен в результате ошибки, — это то, на что отвечает оставшаяся часть этого поста.

Экспериментальная установка

Конфигурация целевого устройства

RP2350 Hacking Challenge от Raspberry Pi попросила участников извлечь 128-битный секрет, хранящийся в OTP1. При запуске подписанная прошивка задачи убеждается, что страница 48 имеет ожидаемую постоянную блокировку, затем применяет блокировку среды выполнения, которая отрицает как защищённый, так и незащищённый доступ к секрету до следующего сброса OTP.

Мы воспроизвели эту конфигурацию, определённую поставщиком, на нашем устройстве ревизии A4:

  • Запрограммировали отпечаток SHA-256 нашего открытого ключа в BOOTKEY0
  • Установили BOOT_FLAGS1.KEY_VALID в 0x1 и BOOT_FLAGS1.KEY_INVALID в 0xe
  • Включили защищённую загрузку (CRIT1.SECURE_BOOT_ENABLE = 1)
  • Постоянно отключили отладку (CRIT1.DEBUG_DISABLE = 1)
  • Включили детекторы глитчей с максимальной чувствительностью (CRIT1.GLITCH_DETECTOR_ENABLE = 1, CRIT1.GLITCH_DETECTOR_SENS = 3)
  • Настроили постоянные блокировки для страниц 1 и 2 в соответствии с конфигурацией задачи
  • Установили блокировку страницы 48 в PAGE48_LOCK1 = 0x3c3c3c, которая отрицала незащищённый доступ (LOCK_NS = INACCESSIBLE) при сохранении защищённого доступа на чтение-запись (LOCK_S = READ_WRITE)

Включение защищённой загрузки разрешает только ядра Cortex-M33, поэтому оба слота процессора использовали Arm для этих экспериментов.

Подготовка образца и стенд

Устройство было вскрыто со спины, так чтобы инфракрасный свет достигал транзисторов через кремниевую подложку, а не блокировался металлическими слоями спереди. Чип затем припаян обратно на дочернюю плату, подключённую к Scaffold, платформе Ledger Donjon с открытым исходным кодом для управления и мониторинга устройств под тестом. Удаление рамки выводов на спине чипа разрывает его соединение GND, поэтому медный провод восстанавливает его2.

RP2350 со вскрытой спиной, смонтированный на дочерней плате анализа
RP2350 со вскрытой спиной, смонтированный на дочерней плате анализа
Экспериментальный стенд, используемый для атаки
Экспериментальный стенд, используемый для атаки

DEBUGEN: переопределение постоянного отключения отладки

DEBUGEN имеет пять функциональных битов:

БитИмяЭффект
0PROC0Включить порт доступа к памяти ядра 0
1PROC0_SECUREРазрешить защищённый доступ через порт доступа к памяти ядра 0
2PROC1Включить порт доступа к памяти ядра 1
3PROC1_SECUREРазрешить защищённый доступ через порт доступа к памяти ядра 1
8MISCВключить дополнительные компоненты отладки, включая интерфейс кросс-триггера и порт доступа модуля отладки RISC-V

Защищённая отладка ядра требует обоих его битов: того, который включает Mem-AP, и того, который разрешает защищённый доступ через него.

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

Мы поэтому проверили, могут ли лазерные импульсы установить биты DEBUGEN на защищённом устройстве, описанном выше.

Локализация, управляемая фотонной эмиссией

Этот тест сначала требует знать, где целиться. Установка отдельного бита DEBUGEN означает попадание в хранилище одного бита регистра, иголку в стоге сена. Это более сложная задача нацеливания, чем пропуск инструкций, общие при лазерной инъекции ошибок, где нарушение любого из многих триггеров в конвейере ядра может произвести тот же пропуск: это распространяет чувствительную область достаточно широко, чтобы случайное сканирование её нашло. Слепое сканирование для одного бита DEBUGEN непрактично.

Переключающиеся транзисторы испускают слабые ближние инфракрасные фотоны, коррелирующие с их активностью, поэтому сбор этой эмиссии при повторном выполнении может выявить, где выбранное управление меняет состояние. Это сделало микроскопию фотонной эмиссии (PEM) хорошо подходящей для DEBUGEN: как регистр, отображённый в памяти, защищённое программное обеспечение может переключать точные биты в цикле, управляя повторными изменениями состояния, которые требует измерение. Мы использовали её как первый этап локализации, и полученная карта ограничила последующее лазерное сканирование областью из нескольких микрометров.

Мы сравнили циклы, которые повторно переключали выбранные биты DEBUGEN вперёд и назад, отличающиеся только в целевых битах. Эмиссия фотонов регистра тусклая рядом с собственным шумом камеры и чувствительна к медленно дрейфующим условиям окружающей среды, таким как температура, поэтому один кадр ничего не показывает. Усреднение многих кадров каждого цикла подавило случайный шум датчика, и вычитание двух средних стеков отменило всё, что циклы совместно использовали: статический фон, смещение датчика, тепловую эмиссию и переключение, не связанное с выбранными битами. Чередование двух значений во время захвата помешало медленному дрейфу смещать это вычитание. Остаток был эмиссией, которая отслеживала выбранные биты.

Средние стеки 200 полных вид захватов фотонной эмиссии для масок DEBUGEN 0x3 и 0xc, за которыми следует их знаковая разница.
Средние стеки всех 200 захватов маски 0x3 и маски 0xc, за которыми следует их знаковая разница. Красный указывает положительное значение, показывающее большую эмиссию для 0x3; синий указывает отрицательное значение, показывающее большую эмиссию для 0xc. Карты локализации ниже дополнительно уравновешивают порядок захвата перед объединением согласованных разностей.

Повторные сравнения по разным маскам битов выявили компактные участки, связанные с битами DEBUGEN 0–3 в трёх регионах поля зрения камеры.

Инфракрасный обзор матрицы с тремя отмеченными областями, плюс увеличения этих областей, наложенные цветными местоположениями битов DEBUGEN.
Инфракрасный обзор поля зрения камеры с тремя отмеченными областями. Цветные пиксели отмечают участки, связанные с битами `DEBUGEN` 0-3.

Эти зоны показывают активность переключения, связанную с каждым битом DEBUGEN; они не напрямую определяют ячейки хранения. Множественные горячие точки, наблюдаемые для каждого бита, могут возникать из элемента хранения или из связанной логики. Без данных макета мы не можем различить между ними. Однако эти зоны по-прежнему значительно сокращают пространство поиска.

Вывод 1 — ошибка DEBUGEN даёт защищённую отладку

Для лазерной инъекции ошибок (LFI) мы использовали импульсный лазер на 980 нм с максимальной оптической мощностью 2,97 Вт, работающий примерно на 40% (около 1,2 Вт), с шириной импульса 100 нс через объектив 50x. После каждого импульса мы зондировали порты доступа отладки через SWD.

В области, найденной из PEM, мы запустили сканирование LFI и использовали обратную связь SWD для калибровки двух реактивных позиций на расстоянии нескольких микрометров. В одной позиции импульсы включали доступ к шине через Mem-AP ядра 1, указывая, что был установлен PROC1. В другой, Control/Status Word Mem-AP сообщал SDeviceEn = 1, сигнал управления состояния, что вероятно был установлен PROC1_SECURE. Мы проверили оба индикатора после каждого импульса.

Рядом инфракрасные вид с местами PEM немного слева и точками LFI немного справа.
Слева: участки PEM, связанные с битами `DEBUGEN`. Справа: точки лазерных ошибок в инфракрасном обзоре LFI.

Импульс, который установил один бит, мог очистить другой, поэтому установка обоих требовала итерационную последовательность. Наш скрипт пульсировал позицию PROC1 до тех пор, пока доступ к шине был доступен, затем пульсировал позицию PROC1_SECURE до SDeviceEn = 1, возвращаясь к первой позиции всякий раз, когда доступ к шине был потерян. После калибровки позиций и параметров импульса последовательность включала защищённую отладку за несколько секунд. Интересно, что мы не могли воспроизвести эту последовательность, используя объектив 20x. Поскольку две позиции находятся только на расстоянии нескольких микрометров, эта более широкая точка вероятно попала как в область, которая устанавливает бит, так и в область, которая его очищает, поэтому не было возможно получить правильное значение.

Как только оба бита были установлены, они оставались установленными без дальнейших импульсов или записей программного обеспечения. Чтение защищённого регистра DEBUGEN через Mem-AP ядра 1 затем вернул 0xc; поскольку DEBUGEN защищён, это успешное чтение подтверждает, что транзакция была защищено-приписана.

Включение защищённого доступа через Mem-AP ядра 1 позволяет отладчику читать и писать ресурсы, отображённые в памяти, чьи разрешения ACCESSCTRL допускают отладчика как менеджера шины и чьи управления, специфичные для цели, допускают защищённые AHB транзакции. Независимо от этих прямых чтений, отладчик может остановить и пошагово выполнить ядро и проверить или изменить его регистры, нарушая изоляцию TrustZone во время выполнения через извлечение, опосредованное защищённым ядром. Это не делает boot ROM приемлемой неаутентифицированной прошивкой: когда прошивка загружается нормально, защищённая загрузка по-прежнему аутентифицирует её, но не может защитить состояние во время выполнения, которое остаётся доступным для отладчика после проверки.

Приложение к конфигурации задачи взлома

Доступ Mem-AP с защищённой атрибуцией, описанный выше, раскрывает защищённое состояние во время выполнения, но блокировка страницы 48 во время выполнения в задаче по-прежнему предотвращает доступ к секрету после запуска прошивки. Постоянная блокировка страницы, PAGE48_LOCK1 = 0x3c3c3c, отрицает незащищённые чтения, но оставляет LOCK_S в READ_WRITE, поэтому она остаётся доступна для чтения через защищённо-приписанные доступы до того, как блокировка во время выполнения затянется.

При каждой загрузке прошивка записывает самое ограничивающее двоичное значение, 0b1111, в блокировку во время выполнения otp_hw->sw_lock[48]. Этот регистр затем делает страницу недоступной как для защищённого, так и для незащищённого доступа, включая защищённую отладку, и поэтому предотвращает защищённые транзакции от Mem-AP читать секрет.

Как документировано, программные блокировки инициализируются из страниц блокировки OTP при сбросе, и запись только продвигает состояние до следующего сброса. Сброс блока OTP отбрасывает 0b1111 и восстанавливает значение, полученное из PAGE48_LOCK1, для которого LOCK_S = READ_WRITE.

Оставшийся вопрос в том, как сбросить заблокированный чип без разрешения прошивке повторно применить блокировку во время выполнения. RP-AP остаётся всегда доступным, даже когда внешняя отладка отключена. Установка CTRL.RESCUE_RESTART запускает сброс спасения: полный системный сброс, который также флагирует boot ROM для остановки перед любым пользовательским программным обеспечением.

Boot ROM проверяет POWMAN_CHIP_RESET.RESCUE_FLAG перед загрузкой из watchdog, flash или USB, очищает его, затем держит ядро 0 в отключённом от прерывания цикле ожидания и ядро 1 в его пути ожидания вектора3. Даташит не документирует никакое ограничение на CTRL.RESCUE_RESTART.

Мы продолжили в следующей последовательности:

  1. Сброс спасения. Установить CTRL.RESCUE_RESTART в 1, затем очистить его в 0 через RP-AP. Чип сбрасывается и остаётся в путях ожидания boot ROM. Подписанная прошивка никогда не запускается, поэтому sw_lock[48] никогда не затягивается и остаётся при разрешающем значении, полученном из PAGE48_LOCK1LOCK_S = READ_WRITE.
  2. Ошибка DEBUGEN в 0xc. С обоими ядрами в путях ожидания boot ROM, установить PROC1 и PROC1_SECURE, как описано выше; эти два установленных бита дают значение 0xc.
  3. Остановить ядро 1 через его Debug Halting Control and Status Register (DHCSR) через теперь-защищённый Mem-AP.
  4. Прочитать секрет из строк OTP 0xc080xc0f через охраняемый интерфейс чтения.

Мы запустили эту последовательность на тестируемом устройстве и восстановили полный секрет задачи.

DEBUGEN_LOCK не предотвращает изменения, вызванные лазером

DEBUGEN_LOCK блокирует программные записи в соответствующие биты DEBUGEN: каждый бит блокировки является записью 1 для блокировки [.] бита DEBUGEN. Не может быть очищена после установки. Даташит представляет это как способ избежать случайных записей.

При испытаниях с целевым битом DEBUGEN на 0 и его битом блокировки на 1, импульс всё ещё мог установить DEBUGEN, в то время как блокировка оставалась 1. Импульсы также устанавливали биты блокировки, с или без соответствующего изменения DEBUGEN. В успешных последовательностях все пять функциональных битов блокировки были 1 к моменту, когда PROC1 и PROC1_SECURE были установлены. Мы никогда не видели, чтобы бит блокировки вернулся с 1 на 0, поэтому более позднее написание DEBUGEN = 0 не может восстановить отключённое состояние, как только ошибка установила соответствующую блокировку.

Ограничения смягчений на основе программного обеспечения

Как только защищённый доступ через Mem-AP включён, одна защищённая атрибуция больше не отделяет отладчика от защищённой прошивки. Этот доступ не переопределяет жёсткие блокировки OTP или управления, специфичные для периферии. ACCESSCTRL может заблокировать прямые транзакции менеджера отладчика к конкретным целям, но сам по себе не предотвращает отладчик управления защищённым ядром от вызова ядром-происходящих доступов или извлечения загруженных значений через регистры ядра. После сброса спасения ACCESSCTRL возвращается к его полностью открытым по умолчанию во время сброса перед тем, как прошивка может переконфигурировать его. ACCESSCTRL поэтому снижает прямую экспозицию Mem-AP, а не формирует автономную границу конфиденциальности.

Прошивка может тем не менее снизить экспозицию после загрузки, отрицая отладчику доступ к чувствительным целям в ACCESSCTRL, затем устанавливая бит отладчика в ACCESSCTRL.LOCK так, чтобы отладчик транзакции не смогли переоткрыть эти разрешения. Защищённая прошивка также может периодически проверять DEBUGEN и, при неожиданном значении, запустить отказоустойчивый сброс, который очищает процессор-холодный сброс домен. Эти меры являются смягчениями во время выполнения лучшего усилия: включённый отладчик может остановить ядро перед следующей проверкой, и сброс спасения останавливается перед тем, как прошивка может настроить ACCESSCTRL или запустить монитор. Они поэтому не предотвращают чтение до прошивки демонстрируемого здесь секрета.

Документированный поток загрузки RP2350 с шифрованием иллюстрирует ограничение до прошивки блокировок во время выполнения и ограничение после загрузки фильтрации менеджера отладчика в двух различных состояниях машины. После сброса спасения boot ROM останавливается перед расшифровкой: открытая нагрузка не существует ещё, но ключ расшифровки может быть напрямую доступен, если постоянные разрешения страницы OTP разрешают защищённый доступ и никакое другое управление целью не блокирует транзакцию. После нормальной загрузки с шифрованием открытый текст существует в SRAM: прямые чтения Mem-AP зависят от разрешений менеджера отладчика в ACCESSCTRL, в то время как управление защищённым ядром может разрешить извлечение, опосредованное ядром, даже когда прямые чтения отрицаются. Это архитектурный анализ, не тестируемый результат загрузки с шифрованием; загрузка с шифрованием по-прежнему защищает внешнюю flash от автономной проверки.

Влияние и требования атаки

Продемонстрированная последовательность предоставляет защищённо-приписанный доступ к памяти, управление защищённо-мировым выполнением и доступ к секрету задачи после сброса его блокировки во время выполнения. Для этого требуются следующие ресурсы:

  • Деструктивный физический доступ. Вскрытие со спины постоянно изменяет корпус и оставляет матрицу открытой.
  • Специализированное лабораторное оборудование. Полная установка, описанная выше, стоит примерно $250 000.
  • Знание безопасности аппаратного обеспечения. Процедура требует подготовки образца, навигации матрицы, выбора параметров лазера и скоординированного управления лазером, позиционирования этапа и измерения SWD.

Заключение

RP2350 кодирует критические флаги отключения отладки в OTP с избыточным голосованием, но DEBUGEN может переопределить их эффект и не имеет эквивалентной защиты, документируемой в даташите. В наших экспериментах лазерные импульсы изменили DEBUGEN, несмотря на DEBUGEN_LOCK и могли установить бит блокировки, который предотвращал прошивку от восстановления отключённого значения. Отдельно, сброс спасения RP-AP восстановил блокировку страницы во время выполнения задачи к её постоянному значению при предотвращении выполнения пользовательской прошивки. Механизмы, видимые программным обеспечением, выполняли каждый свою документируемую функцию, но их взаимодействие с ошибкой лазера включило защищённую отладку и восстановление секрета задачи. Дифференциальная PEM сначала изолировала зависимую от бита активность DEBUGEN и управляла LFI, преобразовав эту пространственную подсказку в постоянную защищённую отладку. Урок на уровне системы состоит в том, что анализ безопасности должен охватывать полный путь принудительного применения, от постоянной конфигурации OTP через изменяемые регистры управления и поведение сброса, потому что безопасность системы зависит от этого пути, а не от отдельных механизмов в изоляции.

Раскрытие информации и благодарности

Мы раскрыли эту ошибку Raspberry Pi 28 июля 2026 года. Благодарим команду Raspberry Pi за их участие в дискуссиях раскрытия информации и за их прозрачный подход к исследованию безопасности.

Антуан Плин, стажёр аппаратной безопасности в Ledger Donjon

Сноски

  1. https://github.com/raspberrypi/rp2350_hacking_challenge Хранилище RP2350 Hacking Challenge, содержащее конфигурацию блокировки и прошивку ссылок, которую мы воспроизвели.

  2. Courk, Лазерная инъекция ошибок на бюджет: RP2350 Edition.

  3. Проверка спасения — шаг 1 пути загрузки ядра 0 в src/main/arm/varm_boot_path.c; в src/main/arm/arm8_bootrom_rt0.S, varm_wait_rescue входит в отключённый от прерывания цикл varm_dead_quiet WFI, а ядро 1 остаётся в пути ожидания вектора boot ROM.