поиск по сайту
Контроль целостности кода firmware в гарвардской архитектуре

Контроль целостности кода firmware в гарвардской архитектуре

М.М. Грунтович, ЗАО «ОКБ САПР»,
г. Пенза, gmm@okbsapr.ru

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

Классическое решение в фон-неймановской и модифицированной гарвардской архитектуре

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

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

Что же делать в случае, когда команды можно только исполнять, т.е. они не могут быть прочитаны по шине данных? Похоже на то, что решить поставленную задачу в рамках обычной вычислительной системы, процессор + долговременная память, не удастся. Но можно попробовать расширить либо постановку задачи, либо систему.

Расширение постановки задачи

Сначала поставим вопрос, зачем вообще нужен контроль целостности firmware? Видится, по крайней мере, два варианта ответа:

1) контроль целостности необходим самому firmware как этап проверки работоспособности изделия;

2) контроль целостности необходим внешнему проверяющему (пользователю, ревизору), для получения доверия к изделию.

В обоих случаях проверяющего интересует не собственно неизменность кода, а то, что он правильно выполняет заявленный функционал и не делает ничего больше. Значит, есть смысл контролировать именно это? Как проверить то, что устройство правильно работает, более-менее понятно: обычно его заставляют выполнять хитроумно придуманные тестовые задания. При этом доступ к коду firmware, как к данным, не требуется.

А вот как проверить то, что устройство не умеет делать еще что-то помимо того, что умеет делать эталон? Честно говоря, кроме традиционного предварительного анализа эталона и контроля целостности кода firmware, к сожалению, ничего в голову не приходит.

Итак, расширенная постановка задачи, похоже, не привела к успеху. Пробуем расширять объект исследования, т.е. вычислительную систему.

Расширение системы в классической гарвардской архитектуре

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

1. Наделим вычислитель еще одной функцией, выполняющей подсчет контрольной суммы области памяти кода. Сделать это можно либо путем модификации процессора за счет расширения системы команд, либо путем модификации расширенной машины, а именно, операционной системы, расширив ее функцией подсчета контрольных сумм областей памяти кода. Такое расширение системы не приведет к нарушению ее безопасности, однако позволит обойти запреты архитектуры. Глубина модификации зависит от уровня требований безопасности к системе. Использование системного программного обеспечения допустимо тогда, когда оно априори считается доверенным. При этом следует иметь в виду, что проверяющий может потребовать подтверждение неизменности уже этого кода.

2. Второй способ предполагает расширить систему, добавив в нее специализированный процессор, который имеет доступ к памяти команд на чтение, но уже как к данным. Чтобы чрезмерно не удорожать изделие, можно выбрать достаточно маломощный процессор. Однако его наличие позволит «добраться» до кода firmware, не внося уязвимости в вычислительную систему. В этом случае, правда, надо иметь в виду, что опять придется проверять целостность кода спецпроцессора.

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

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


ФорумФорум
Форум ОКБ САПР
Вопросы специалистовВопросы специалистов
Вопросы, которые нам присылают, и наши ответы на них