проверка модуля не прошла подпись и / или отсутствует требуемый ключ

10

Я работаю над модулем ядра, который работает нормально. Однако, просматривая dmesg, я вижу сообщение, касающееся моего модуля, о том, что проверка модуля завершилась неудачно (не удалось выполнить проверку модуля и / или отсутствует требуемый ключ).

Как я могу решить эту проблему? Как мне подписать мой модуль для проверки?

Спасибо.

user2000888
источник

Ответы:

3

Все, что вам нужно, описано здесь

МОДУЛЬ КЕРНЕЛЯ, ПОДПИСЫВАЮЩИЙ ОБЪЕКТ


СОДЕРЖАНИЕ

  • Обзор.
  • Настройка модуля подписи.
  • Генерация подписывающих ключей.
  • Открытые ключи в ядре.
  • Подписание модулей вручную.
  • Подписанные модули и зачистки.
  • Загрузка подписанных модулей.
  • Недействительные подписи и неподписанные модули.
  • Администрирование / защита закрытого ключа.

ОБЗОР

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

Это средство использует сертификаты стандарта МСЭ-Т X.509 для кодирования задействованных открытых ключей. Сигнатуры сами по себе не кодируются каким-либо промышленным стандартом. В настоящее время средство поддерживает только стандарт шифрования с открытым ключом RSA (хотя он является подключаемым и позволяет использовать другие). Возможные алгоритмы хэширования: SHA-1, SHA-224, SHA-256, SHA-384 и SHA-512 (алгоритм выбирается по данным в подписи).


НАСТРОЙКА МОДУЛЯ ПОДПИСАНИЯ

Функция подписи модуля включена, перейдя в раздел «Enable Loadable Module Support» конфигурации ядра и включив

CONFIG_MODULE_SIG   "Module signature verification"

У этого есть много доступных вариантов:

  1. «Требовать, чтобы модули были правильно подписаны» (CONFIG_MODULE_SIG_FORCE)

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

    Если это отключено (т.е. «разрешающий»), то модули, для которых ключ недоступен, и модули, которые не подписаны, разрешены, но ядро ​​будет помечено как испорченное, а соответствующие модули будут помечены как испорченные, показано с символом «Е».

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

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

  2. «Автоматически подписывать все модули» (CONFIG_MODULE_SIG_ALL)

    Если это включено, то модули будут автоматически подписаны во время фазы modules_install сборки. Если это отключено, то модули должны быть подписаны вручную, используя:

    scripts/sign-file
    
  3. "С каким алгоритмом хеширования должны подписываться модули?"

    Здесь представлен выбор алгоритма хеширования, на котором фаза установки подпишет модули:

    CONFIG_MODULE_SIG_SHA1      "Sign modules with SHA-1"
    CONFIG_MODULE_SIG_SHA224    "Sign modules with SHA-224"
    CONFIG_MODULE_SIG_SHA256    "Sign modules with SHA-256"
    CONFIG_MODULE_SIG_SHA384    "Sign modules with SHA-384"
    CONFIG_MODULE_SIG_SHA512    "Sign modules with SHA-512"
    

    Выбранный здесь алгоритм также будет встроен в ядро ​​(а не в модуль), так что модули, подписанные этим алгоритмом, могут проверять свои сигнатуры, не вызывая петли зависимостей.

  4. «Имя файла или PKCS # 11 URI ключа подписи модуля» (CONFIG_MODULE_SIG_KEY)

    Установка этого параметра в значение, отличное от значения по умолчанию «certs / signature_key.pem», отключит автогенерацию ключей подписи и позволит подписывать модули ядра ключом по вашему выбору. Предоставленная строка должна идентифицировать файл, содержащий как закрытый ключ, так и соответствующий ему сертификат X.509 в форме PEM, или - в системах, где функционирует OpenSSL ENGINE_pkcs11 - URI PKCS # 11, как определено в RFC7512. В последнем случае URI PKCS # 11 должен ссылаться как на сертификат, так и на закрытый ключ.

    Если PEM-файл, содержащий закрытый ключ, зашифрован или токен PKCS # 11 запрашивает PIN-код, это может быть предоставлено во время сборки с помощью переменной KBUILD_SIGN_PIN.

  5. «Дополнительные ключи X.509 для системного набора ключей по умолчанию» (CONFIG_SYSTEM_TRUSTED_KEYS)

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

Обратите внимание, что включение подписи модуля добавляет зависимость от пакетов OpenSSL devel к процессам сборки ядра для инструмента, который выполняет подпись.


Генерирующие подписывающие клавиши

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

При нормальных условиях, когда CONFIG_MODULE_SIG_KEY не отличается от значения по умолчанию, сборка ядра автоматически генерирует новую пару ключей, используя openssl, если она не существует в файле:

certs/signing_key.pem

во время сборки vmlinux (публичная часть ключа должна быть встроена в vmlinux) с использованием параметров в:

certs/x509.genkey

файл (который также генерируется, если он еще не существует).

Настоятельно рекомендуется предоставить собственный файл x509.genkey.

В частности, в файле x509.genkey раздел req_distinguished_name должен быть изменен по умолчанию:

[ req_distinguished_name ]
#O = Unspecified company
CN = Build time autogenerated kernel key
#emailAddress = unspecified.user@unspecified.company

Сгенерированный размер ключа RSA также можно установить с помощью:

[ req ]
default_bits = 4096

Также возможно вручную сгенерировать ключевые личные / публичные файлы, используя файл конфигурации генерации ключа x509.genkey в корневом узле дерева исходных текстов ядра Linux и команду openssl. Ниже приведен пример создания файлов открытого / закрытого ключа:

openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
   -config x509.genkey -outform PEM -out kernel_key.pem \
   -keyout kernel_key.pem

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


ОБЩЕСТВЕННЫЕ КЛЮЧИ В ЯДРЕ

Ядро содержит набор открытых ключей, которые могут быть просмотрены пользователем root. Они находятся в связке ключей с именем ".system_keyring", которую можно увидеть по:

[root@deneb ~]# cat /proc/keys
...
223c7853 I------     1 perm 1f030000     0     0 keyring   .system_keyring: 1
302d2d52 I------     1 perm 1f010000     0     0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 []
...

Помимо открытого ключа, сгенерированного специально для подписи модуля, дополнительные доверенные сертификаты могут быть предоставлены в PEM-кодированном файле, на который ссылается опция конфигурации CONFIG_SYSTEM_TRUSTED_KEYS.

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

Наконец, можно добавить дополнительные открытые ключи, выполнив:

keyctl padd asymmetric "" [.system_keyring-ID] <[key-file]

например:

keyctl padd asymmetric "" 0x223c7853 <my_public_key.x509

Однако обратите внимание, что ядро ​​разрешит добавление ключей в .system_keyring только в том случае, если оболочка X.509 нового ключа достоверно подписана ключом, который уже находится в .system_keyring на момент добавления ключа.


РУЧНОЙ ПОДПИСАНИЕ МОДУЛЕЙ

Чтобы вручную подписать модуль, используйте инструмент scripts / sign-file, доступный в дереве исходного кода ядра Linux. Сценарий требует 4 аргумента:

1.  The hash algorithm (e.g., sha256)
2.  The private key filename or PKCS#11 URI
3.  The public key filename
4.  The kernel module to be signed

Ниже приведен пример для подписи модуля ядра:

scripts/sign-file sha512 kernel-signkey.priv \
    kernel-signkey.x509 module.ko

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

Если для закрытого ключа требуется пароль или PIN-код, его можно указать в переменной среды $ KBUILD_SIGN_PIN.


ПОДПИСАННЫЕ МОДУЛИ И ПОЛОСЫ

Подписанный модуль имеет цифровую подпись, просто добавляемую в конце. Строка "~ Подпись модуля добавлена ​​~." в конце файла модуля подтверждает, что подпись присутствует, но это не подтверждает, что подпись действительна!

Подписанные модули являются BRITTLE, поскольку подпись находится за пределами определенного контейнера ELF. Таким образом, они НЕ МОГУТ быть удалены после того, как подпись вычислена и приложена. Обратите внимание, что весь модуль представляет собой подписанную полезную нагрузку, включая любую и всю отладочную информацию, присутствующую на момент подписания.


ЗАГРУЗКА ПОДПИСАННЫХ МОДУЛЕЙ

Модули загружаются с помощью insmod, modprobe, init_module () или finit_module (), точно так же, как и для неподписанных модулей, поскольку в пользовательском пространстве обработка не производится. Проверка подписи выполняется в ядре.


НЕ ДЕЙСТВУЮЩИЕ ПОДПИСИ И НЕ ПОДПИСАННЫЕ МОДУЛИ

Если параметр CONFIG_MODULE_SIG_FORCE включен или в файле командной строки ядра указано значение forcecemodulesig = 1, ядро ​​будет загружать только правильно подписанные модули, для которых у него есть открытый ключ. В противном случае он также будет загружать неподписанные модули. Любой модуль, для которого ядро ​​имеет ключ, но который имеет несоответствие сигнатур, загружаться не будет.

Любой модуль, имеющий непарсируемую подпись, будет отклонен.


АДМИНИСТРИРОВАНИЕ / ЗАЩИТА ЧАСТНОГО КЛЮЧА

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

AB
источник
Спасибо, но я уже видел этот текст раньше. Проблема, с которой я сталкиваюсь, заключается в том, что, хотя я могу подписать свой файл, я не могу загрузить файл по-прежнему, потому что: «ядро будет разрешать добавление ключей в .system_keyring только в том случае, если оболочка X.509 нового ключа правильно подписана ключ, который уже находится в .system_keyring на момент добавления ключа. "
OmnipotentEntity
Я тоже видел это несколько раз, но это не помогает. В Ubuntu есть ошибка, которая затрагивает все материнские платы, которые не поддерживают uefi: bugs.launchpad.net/ubuntu/+source/linux-lts-xenial/+bug/1656670
musbach
0

Изменить ./include/generated/autoconf.hи изменить строку

define CONFIG_MODULE_SIG 1

в

define CONFIG_MODULE_SIG 0
Даниил
источник