Linux内核模块签名技术

📅 2026/6/16 10:17:53
Linux内核模块签名技术
inux 内核运行在系统的最高特权级别Ring 0。为了防止恶意代码如 Rootkit通过内核模块.ko文件直接侵入系统核心Linux 引入了内核模块签名技术Kernel Module Signing。下面为您详细拆解该技术的核心原理、签名流程以及内核运行时的验签过程。一、 核心技术原理Linux 内核模块签名其本质是非对称加密算法如 RSA 或 ECDSA与散列算法如 SHA-256的结合应用。1. 密钥对分工私钥Private Key保留在构建服务器编译内核的主机上用于对生成的内核模块进行数字签名。私钥绝对不能泄露甚至可以在签名完成后立即销毁。公钥Public Key包装在 X.509 证书中直接编译进内核镜像vmlinuz。内核在运行时只认这个内置的公钥。2. 追加式签名结构Appended Signature普通的数字签名如 GPG 签名通常会生成一个独立的.sig文件但 Linux 内核模块采用的是追加签名的方式。签名工具计算完.ko文件的哈希并用私钥加密后会把这段签名二进制数据PKCS#7 格式直接强行追加到.ko文件的末尾。在文件最末尾还会追加一个固定的魔法字符串Magic String~Module signature appended~以及一个描述签名大小的特殊结构体。这样内核读取文件末尾时就能瞬间判断该模块是否已被签名。二、 模块签名过程编译期 / Build Time签名过程发生在内核或模块编译完成之后、发布之前。通常由内核源码树自带的脚本工具sign-file自动化完成。[编译出的未签名 driver.ko] │ ▼ (使用 SHA-256 计算文件哈希值) [Hash Value] │ ▼ (使用 私钥 MOK.priv 进行加密) [PKCS#7 签名数据] │ ▼ (将签名数据 魔法字符串追加到原文件末尾) [已签名的 driver.ko]详细步骤内核编译系统生成密钥对如果内核配置了自动签名编译时会在内核根目录下自动生成signing_key.pem私钥和signing_key.x509包含公钥的证书。提取公钥编译系统将signing_key.x509证书中的公钥硬编码嵌入到内核镜像的.builtin_trusted_keys密钥环中。计算哈希签名工具sign-file读取编译好的.ko文件不含末尾使用指定的散列算法如 SHA-256计算出整个模块的哈希值。生成并追加签名工具使用私钥对哈希值进行非对称加密生成符合 PKCS#7 规范的签名数据块并将其以及魔法字符串~Module signature appended~写入.ko文件的尾部。三、 模块验签过程运行期 / Runtime当管理员或系统服务执行modprobe或insmod命令加载模块时系统会发起finit_module或init_module系统调用将模块数据读入内核空间随后内核展开验签逻辑。详细步骤检测签名标记内核模块加载器首先将指针移到读入内存的模块数据末尾检查是否存在~Module signature appended~魔法字符串。如果没有说明这是个未签名模块内核转入“无签名处理策略”。如果有内核根据末尾的结构体解析出签名数据的长度将签名块和原本的 ELF 模块数据分离。提取公钥内核前往自身的受信任密钥环Keyring中查找匹配的公钥证书。解密与比对验签内核使用公钥解密签名块得到由编译期计算的原始哈希值 H_1。内核使用相同的散列算法如 SHA-256重新计算当前接收到的 ELF 模块数据的当前哈希值 H_2。比对二者如果H_1 H_2则验签成功说明模块来源可信且在传输/存储过程中未被篡改如果H_1 ! H_2则验签失败。四、 验签失败或无签名时的内核策略内核验证完签名后会根据 Linux 内核编译配置文件.config中的安全策略以及是否开启了 UEFI 安全启动Secure Boot来决定模块的命运场景 / 内核配置策略类型验签通过无签名 / 验签失败CONFIG_MODULE_SIGy(未开启强制)宽松/审计模式正常加载。允许加载但内核会在日志dmesg中抛出严重警告并将内核状态标记为Tainted受污染。CONFIG_MODULE_SIG_FORCEy(开启强制)强制锁定模式正常加载。直接拒绝加载。系统调用返回错误通常提示Required key not available或Key was rejected by service。开启 UEFI Secure Boot最高安全模式正常加载。此时无论内核如何配置内核都会强制自动升级为锁定模式任何签名不对或无签名的模块绝对无法加载。