.. SPDX-License-Identifier: GPL-2.0 .. include:: ../disclaimer-zh_CN.rst :Original: Documentation/admin-guide/module-signing.rst :翻译: 朱岩 Yan Zhu ================ 内核模块签名机制 ================ .. 目录 .. .. - 概述 .. - 配置模块签名 .. - 生成签名密钥 .. - 内核中的公钥 .. - 模块手动签名 .. - 已签名模块和剥离 .. - 加载已签名模块 .. - 无效签名和未签名模块 .. - 管理/保护私钥 概述 ==== 内核模块签名机制在安装过程中对模块进行加密签名,然后在加载模块时检查签名。这 通过禁止加载未签名的模块或使用无效密钥签名的模块来提高内核安全性。模块签名通 过使恶意模块更难加载到内核中来增加安全性。模块签名检查在内核中完成,因此不需 要受信任的用户空间位。 此机制使用 X.509 ITU-T 标准证书对涉及的公钥进行编码。签名本身不以任何工业标准 类型编码。内置机制目前仅支持 RSA、NIST P-384 ECDSA 和 NIST FIPS-204 ML-DSA 公钥签名标准(尽管它是可插拔的并允许使用其他标准)。对于 RSA 和 ECDSA,可以使 用的可能的哈希算法是大小为 256、384 和 512 的 SHA-2 和 SHA-3(算法由签名中的 数据选择);ML-DSA 会自行进行哈希运算,但允许与 SHA512 哈希算法结合用于签名属 性。 配置模块签名 ============ 通过进入内核配置的 :menuselection:`Enable Loadable Module Support` 菜单并打 开以下选项来启用模块签名机制:: CONFIG_MODULE_SIG "Module signature verification" 这有多个可用选项: (1) :menuselection:`Require modules to be validly signed` (``CONFIG_MODULE_SIG_FORCE``) 这指定了内核应如何处理其密钥未知或未签名的模块。 如果关闭(即"宽松模式"),则允许使用不可用密钥和未签名的模块,但内核将被 标记为受污染,并且相关模块将被标记为受污染,显示字符'E'。 如果打开(即"限制模式"),只有具有有效签名且可由内核拥有的公钥验证的模块 才会被加载。所有其他模块将生成错误。 无论此处的设置如何,如果模块的签名块无法解析,它将被直接拒绝。 (2) :menuselection:`Automatically sign all modules` (``CONFIG_MODULE_SIG_ALL``) 如果打开此选项,则在构建的 modules_install 阶段期间将自动签名模块。 如果关闭,则必须使用以下命令手动签名模块:: scripts/sign-file (3) :menuselection:`Which hash algorithm should modules be signed with?` 这提供了安装阶段将用于签名模块的哈希算法选择: =============================== ========================================== ``CONFIG_MODULE_SIG_SHA256`` :menuselection:`Sign modules with SHA-256` ``CONFIG_MODULE_SIG_SHA384`` :menuselection:`Sign modules with SHA-384` ``CONFIG_MODULE_SIG_SHA512`` :menuselection:`Sign modules with SHA-512` ``CONFIG_MODULE_SIG_SHA3_256`` :menuselection:`Sign modules with SHA3-256` ``CONFIG_MODULE_SIG_SHA3_384`` :menuselection:`Sign modules with SHA3-384` ``CONFIG_MODULE_SIG_SHA3_512`` :menuselection:`Sign modules with SHA3-512` =============================== ========================================== 此处选择的算法也将被构建到内核中(而不是作为模块),以便使用该算法签名的 模块可以在不导致循环依赖的情况下检查其签名。 (4) :menuselection:`File name or PKCS#11 URI of module signing key` (``CONFIG_MODULE_SIG_KEY``) 将此选项设置为除默认值 ``certs/signing_key.pem`` 之外的其他值将禁用签名 密钥的自动生成,并允许使用您选择的密钥对内核模块进行签名。提供的字符串应 标识包含私钥及其对应的 PEM 格式 X.509 证书的文件,或者在 OpenSSL ENGINE_pkcs11 功能正常的系统上,使用 RFC7512 定义的 PKCS#11 URI。在后一 种情况下,PKCS#11 URI 应引用证书和私钥。 如果包含私钥的 PEM 文件已加密,或者 PKCS#11 令牌需要 PIN,可以通过 ``KBUILD_SIGN_PIN`` 变量在构建时提供。 (5) :menuselection:`Additional X.509 keys for default system keyring` (``CONFIG_SYSTEM_TRUSTED_KEYS``) 此选项可设置为包含附加证书的 PEM 编码文件的文件名,这些证书将默认包含在 系统密钥环中。 请注意,启用模块签名会为内核构建过程添加对执行签名工具的 OpenSSL 开发包的依赖。 生成签名密钥 ============ 生成和检查签名需要加密密钥对。私钥用于生成签名,相应的公钥用于检查签名。私钥 仅在构建期间需要,之后可以删除或安全存储。公钥被构建到内核中,以便在加载模块 时可以使用它来检查签名。 在正常情况下,当 ``CONFIG_MODULE_SIG_KEY`` 保持默认值时,如果文件中不存在密 钥对,内核构建将使用 openssl 自动生成新的密钥对:: certs/signing_key.pem 在构建 vmlinux 期间(公钥需要构建到 vmlinux 中)使用参数:: certs/x509.genkey 文件(如果尚不存在也会生成)。 可以在 RSA(``MODULE_SIG_KEY_TYPE_RSA``)、 ECDSA(``MODULE_SIG_KEY_TYPE_ECDSA``)和 ML-DSA(``MODULE_SIG_KEY_TYPE_MLDSA_*``)之间选择生成 RSA 4k、NIST P-384 密钥对或 ML-DSA 44、65 或 87 密钥对。 强烈建议您提供自己的 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 也可以使用位于 Linux 内核源代码树根节点中的 x509.genkey 密钥生成配置文件和 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 查看的公钥环。它们在名为 ".builtin_trusted_keys" 的密 钥环中,可以通过以下方式查看:: [root@deneb ~]# cat /proc/keys ... 223c7853 I------ 1 perm 1f030000 0 0 keyring .builtin_trusted_keys: 1 302d2d52 I------ 1 perm 1f010000 0 0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 [] 除了专门为模块签名生成的公钥外,还可以在 ``CONFIG_SYSTEM_TRUSTED_KEYS`` 配置 选项引用的 PEM 编码文件中提供其他受信任的证书。 此外,架构代码可以从硬件存储中获取公钥并将其添加(例如从 UEFI 密钥数据库)。 最后,可以通过以下方式添加其他公钥:: keyctl padd asymmetric "" [.builtin_trusted_keys-ID] <[key-file] 例如:: keyctl padd asymmetric "" 0x223c7853