模块validation失败签名和/或所需密钥丢失

我正在研究一个内核模块,它工作正常。 但是,通过dmesg查看,我看到有关模块validation失败的消息(模块validation失败签名和/或缺少必需的密钥)。

我该如何解决这个问题? 如何让我的模块签名进行validation?

谢谢。

这里描述了您需要的所有内容

内核模块签名设施


内容

  • 概述。
  • 配置模块签名。
  • 生成签名密钥。
  • 内核中的公钥。
  • 手动签署模块。
  • 签名模块和剥离。
  • 加载已签名的模块
  • 无效签名和未签名模块。
  • 管理/保护私钥。

概述

内核模块签名工具在安装期间对模块进行加密签名,然后在加载模块时检查签名。 这允许通过禁止加载使用无效密钥签名的未签名模块或模块来提高内核安全性。 模块签名通过使恶意模块加载到内核更加困难来提高安全性。 模块签名检查由内核完成,因此不必具有可信用户空间位。

该工具使用X.509 ITU-T标准证书对所涉及的公钥进行编码。 签名本身不以任何工业标准类型编码。 该设施目前仅支持RSA公钥加密标准(尽管它是可插拔的,允许其他人使用)。 可以使用的哈希算法是SHA-1,SHA-224,SHA-256,SHA-384和SHA-512(该算法由签名中的数据选择)。


配置模块签名

通过转到内核配置的“启用可加载模块支持”部分并打开来启用模块签名工具

CONFIG_MODULE_SIG "Module signature verification" 

这有多种选择:

  1. “要求模块有效签名”(CONFIG_MODULE_SIG_FORCE)

    这指定了内核应如何处理具有未知密钥的签名的模块或未签名的模块。

    如果关闭(即“允许”),则允许密钥不可用的模块和未签名的模块,但内核将被标记为受污染,相关模块将被标记为污染,显示字符’E’。

    如果启用(即“限制”),则只会加载具有可由内核拥有的公钥validation的有效签名的模块。 所有其他模块都将生成错误。

    无论此处的设置如何,如果模块具有无法解析的签名块,它将被拒绝。

  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 / signing_key.pem”之外的其他选项将禁用签名密钥的自动生成,并允许使用您选择的密钥对内核模块进行签名。 提供的字符串应标识包含私钥及PEM格式的相应X.509证书的文件,或者 – 在OpenSSL ENGINE_pkcs11正常运行的系统上 – RFC7512定义的PKCS#11 URI。 在后一种情况下,PKCS#11 URI应引用证书和私钥。

    如果包含私钥的PEM文件已加密,或者PKCS#11令牌需要PIN,则可以在构建时通过KBUILD_SIGN_PIN变量提供。

  5. “用于默认系统密钥环的其他X.509密钥”(CONFIG_SYSTEM_TRUSTED_KEYS)

    此选项可以设置为包含其他证书的PEM编码文件的文件名,默认情况下将包含在系统密钥环中。

请注意,启用模块签名会将OpenSSL开发包的依赖性添加到执行签名的工具的内核构建过程。


生成签名密钥

需要加密密钥对来生成和检查签名。 私钥用于生成签名,相应的公钥用于检查签名。 只有在构建期间才需要私钥,之后可以安全地删除或存储私钥。 公钥内置于内核中,以便在加载模块时可以使用它来检查签名。

在正常情况下,当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 

也可以使用Linux内核源代码树的根节点和openssl命令中的x509.genkey密钥生成配置文件手动生成密钥私有/公共文件。 以下是生成公钥​​/私钥文件的示例:

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

然后,可以在CONFIG_MODULE_SIG_KEY选项中指定生成的kernel_key.pem文件的完整路径名,并使用其中的证书和密钥而不是自动生成的密钥对。


内核的公共钥匙

内核包含一个可以由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 [] ... 

除了专门为模块签名生成的公钥之外,还可以在CONFIG_SYSTEM_TRUSTED_KEYS配置选项引用的PEM编码文件中提供其他可信证书。

此外,体系结构代码可以从硬件存储中获取公钥并且还将其添加(例如,从UEFI密钥数据库)。

最后,可以通过执行以下操作添加其他公钥:

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

例如:

 keyctl padd asymmetric "" 0x223c7853  

但请注意, 如果新密钥的X.509包装器在添加密钥时已经驻留在.system_keyring中的密钥有效签名,则内核将仅允许将密钥添加到.system_keyring。


手动签署模块

要手动签署模块,请使用Linux内核源代码树中提供的脚本/签名文件工具。 该脚本需要4个参数:

 1. The hash algorithm (eg, 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或在内核命令行上提供了enforcemodulesig = 1,则内核将仅加载具有公钥的有效签名模块。 否则,它还将加载未签名的模块。 内核具有密钥但被certificate具有签名不匹配的任何模块都不允许加载。

任何具有不可解析签名的模块都将被拒绝。


管理/保护私钥

由于私钥用于对模块进行签名,因此病毒和恶意软件可以使用私钥对模块进行签名并危及操作系统。 私钥必须被销毁或移动到安全位置,而不能保存在内核源树的根节点中。

编辑./include/generated/autoconf.h并更改该行

 define CONFIG_MODULE_SIG 1 

 define CONFIG_MODULE_SIG 0