LINUX.ORG.RU

Механизм верификации файлов прошивки перед их использованием

 , ,


0

1

Всем привет!

Работаю над софтом для некоего (пока не серийного) устройства. Внутре устройства обычный промышленный комп x86 с Дебианом на борту, софт на Qt. Думаю, как решить задачу обновления ПО будущими пользователями устройства.

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

Скоро закончу делать функционал работы с флешками из софтового GUI и возникает вопрос, как бы распознать файлы моего софта среди прочих файлов.

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

Может кто подскажет, как обычно решаются задачи подобного рода?


с точки зрения защиты/формата файла - не знаю, но с точки зрения обновлений - может просто документировать что файл должен иметь имя начинающееся с «mytool-firmware», и не важно какое у него расширение?

А в качестве помощи пользователю - при вставке флегки с таким файлом (банально проверяем раз в секунду) - показывать окно выбора «Вставлена флешка с пакетом обновоения имя файла. Оно булет применено при слелующей загрузке. Перезагрузить сейчас»?

Сам мезанизм обновления оставляем на этапе загрузки

Но такое графическое предупреждение:

  • подтвердит обновляющемуся пользователю что он верно подготовил флешку
  • если вставили флешку со случайно забытым старым файлом обновления - предупредит о том что «тут обновление вообще-то есть, оно применится»

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

GPFault ★★★
()
Ответ на: комментарий от GPFault

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

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

Как эти проверки делаются обычно? Велосипедить – последнее дело, поэтому и интересуюсь у сообщества.

s3rjke
() автор топика

Если у обновлений уникальный формат, то можно проверять магическое число типа файла

    // Определение принадлежности файла к qcow2 по "Magic number"
    // https://www.ijrte.org/wp-content/uploads/papers/v8i5/E5606018520.pdf
    // 514649FB - магическое число qcow2 файлов (см. табл. 2)

    bool vmImage = false;
    QFile file(imageFullName);

    QByteArray header = file.read(4);
    
    if (header == QByteArray::fromHex("514649FB")){
       vmImage = true;
    }

Jurik_Phys ★★★★★
()
Последнее исправление: Jurik_Phys (всего исправлений: 1)

я бы делал так:

  1. создать свою подписью, см. https://blog.packagecloud.io/how-to-gpg-sign-and-verify-deb-packages-and-apt-repositories/
  2. именовал бы их как myapp_somename_ver.deb
  3. после создания очередной версии deb - подпись его через dpkg-sig
  4. в интерфейсе отображать файлы с именем myapp_*
  5. перед установкой проверка через debsig-verify
x905 ★★★★★
()

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

не твори велосипед без лишней на то необходимости.

вариант2: системы деплоя данных на боевые сервера. тож самое, но другое.

если у тебя прошивка, и меняется вся система/прошивка в целом, то используй два корня + систему обновлений A/B. еще и резерв появится с возможностью отката.

pfg ★★★★★
()
Последнее исправление: pfg (всего исправлений: 2)

Может кто подскажет, как обычно решаются задачи подобного рода?

Так и решаются, ты же всё описал уже.

firkax ★★★★★
()
Ответ на: комментарий от s3rjke

С чего это он что-то затрёт? Подпись не подходит - отклоняем. Ну и ещё лучше бы проверить что версия нового файла больше версии имеющейся прошивки (ну или не проверять если не надо).

firkax ★★★★★
()

как бы распознать файлы моего софта среди прочих файлов.

По содержимому. Когда подписываешь файл gpg, можно не создавать отсоединённую подпись, а вставить внутрь и получить файл с подписью.

Осталось проверить подпись — не подходит, выкидываем, подходит — распаковываем, получаем tar(или не tar, да хоть zip) в /tmp и копируем файлы в нужные места.

Aceler ★★★★★
()

собрать deb пакет и пусть apt сам всем занимается

Silerus ★★★★
()

Просто сделай свой deb-репозиторий и сделай пакет для своей программки. Там всё уже придумали за тебя.

vbr ★★★★★
()

Может кто подскажет, как обычно решаются задачи подобного рода?

Конкретно обновления решаются специальным ПО, сделанным для обновления embedded-систем:

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

Вы, насколько я понял, хотите сделать kiosk/appliance, т.е. бытовое устройство с одной функцией (поищите информацию по этим ключевым словам)
Для этого крайне желательно собрать собственный образ файловой системы, и на вашем месте я бы сделал его неизменяемым (immutable) — так вы сможете контролировать поставку целиком и быть уверены, что конкретная версия ПО соответствует конкретному набору системных библиотек, ядра, загрузчика, и т.п., но и за любыми обновлениями (безопасности) следить придётся также вам — предполагается, что сам пользователь не должен лезть в недра и не может самостоятельно обслужить такую систему.

Образ файловой системы прямо для физической машины можно собрать с помощью mkosi (пользуюсь сам, но едва ли рекомендую — самое несовместимое ПО, что я знаю, ломают совместимость даже в минорных версиях), packer, bootc.
Вот здесь и здесь еще куча альтернатив, правда, не все их них подходят именно для физических машин, большинство заточено под контейнеры.

В systemd есть куча встроенных функции по работе с условно-embedded-системами: автообнаружение разделов, увеличение разделов по размеру флеш-памяти, сброс на настройки по умолчанию, логическое разделение на первый запуск и последующие, и другие опции:

Ничем из этого не пользовался, не могу сказать, насколько подходит для применения.

Своё ПО вам следует либо собрать как .deb-пакет (сама процедура несложная и dev-скрипты автоматизируют почти всё от начала до конца, но документация плохая), и включать его в состав образа ОС, либо, например, как systemd sysext-пакет, который находится в отдельном файле (squashfs) и монтируется поверх основной ФС: https://man7.org/linux/man-pages/man8/systemd-sysext.8.html — так вы сможете обновлять только ПО в immutable-образе штатными средствами.

Также обратите внимание, что в Debian могут быть функции, подразумевающие наличие оператора с клавиатурой. Например, если система «не загрузилась», GRUB выдаст окно выбора элемента при следующей загрузке и будет ждать подтверждения (или хотя бы покажет это окно с таймаутом). Я для своего устройства сделал собственные загрузчик и initramfs, без использования Debian-скриптов.
Не помню, как конкретно в Debian это реализовано, но в Fedora запускается по таймеру на 2 минуты user service после логина в сессию, изменяющий переменные GRUB, а если не вошел (или перезагрузился ранее, чем через 2 минуты), то система считается «не загрузилась».

ValdikSS ★★★★★
()
Ответ на: комментарий от s3rjke

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

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

Iron_Bug ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.