技术博客

05/07/2017 作者 Mikkel

构建并安装已签名Kvaser驱动程序模块与linuxcan下载


这是关于Linux安全启动和签名模块两篇系列文章的第2篇:

  1. Linux系统安全启动
  2. 构建并安装已签名Kvaser驱动程序模块

第一篇文章概述了安全启动的概念,以及它如何影响第三方模块。在本文中,我们将介绍如何构建和签名Kvaser驱动程序模块,以便能够在启用了安全启动的Linux计算机上使用它们。


Linux系统

我们准备好最新安装的Ubuntu16.04。

  $ uname -a
  Linux mypc 4.8.0-51-generic #54~16.04.1-Ubuntu SMP Wed Apr 26 16:00:28 UTC 2017
x86_64 x86_64 x86_64 GNU/Linux
  $ lsb_release -a
  No LSB modules are available.
  Distributor ID: Ubuntu
  Description:    Ubuntu 16.04.2 LTS
  Release:        16.04
  Codename:       xenial

创建证书和私钥

第一步是创建一个证书/私有RSA密钥对,稍后将用于对内核模块进行签名。

请注意由于私钥用于签署模块,病毒和恶意软件可能会使用私钥对模块进行签名并危及操作系统。要确保私钥安全。1

使用openssl命令,创建一个私钥和DER编码的证书。2 记住将公用名称(CN)字段(YOUR_NAME)设置为对访客有意义的文字。3 此例中我们使用kvaser.com作为公用名称。

  $ mkdir ~/sign_cert
  $ cd ~/sign_cert
  # Change YOUR_NAME below for identification purposes, we’ll use kvaser.com
  $ openssl req -new -x509 -newkey rsa:2048 -keyout modulesign.priv -outform DER
-out modulesign.der -nodes -days 36500 -subj "/CN=YOUR_NAME/"

现在出现两个文件。

$ ls
modulesign.der modulesign.priv

将公钥导入并注册到系统

下一步使用mokutil4命令导入公钥,让其可以被系统信任。这个过程需要两步,其中首先导入密钥,然后在下次启动机器时必须进行注册。简单的密码即可,因为只是临时使用。

$ sudo mokutil --import modulesign.der
input password:
input password again:

我们现在可以验证是否已导入正确的证书。 在这里我们也注意到上面使用的公用名称(CN)是kvaser.com。

$ sudo mokutil --list-new
[key 1]
SHA1 Fingerprint: 2c:d4:5b:a3:c6:34:3f:a6:1a:8f:e3:d3:23:8d:88:69:7d:33:ae:12
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 18315900181576503446 (0xfe2f262c60615096)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=kvaser.com
        Validity
            Not Before: May  9 07:52:56 2017 GMT
            Not After : Apr 15 07:52:56 2117 GMT
        Subject: CN=kvaser.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
:
:

现在重新启动机器。引导加载程序启动时,MOK管理器EFI实用程序应自动启动。在我的机器屏幕上出现浅蓝色背景的白色文字,提示要“点击任意键执行MOK管理”和“10秒后启动”5,YMMV。选择“注册MOK”,选择密钥,并注册密钥。在上述导入步骤中我们会被要求输入设置密码。完成注册步骤,然后继续启动。Linux内核将记录加载的密钥,我们可以使用dmesg命令查看我们自己的密钥。

  $ dmesg|grep ’EFI: Loaded cert’
  [    0.671897] EFI: Loaded cert ’Microsoft Windows Production PCA 2011:
a92902398e16c49778cd90f99e4f9ae17c55af53’ linked to ’.builtin_trusted_keys’
  [    0.671908] EFI: Loaded cert ’Microsoft Corporation UEFI CA 2011:
13adbf4309bd82709c8cd54f316ed522988a1bd4’ linked to ’.builtin_trusted_keys’
  [    0.673771] EFI: Loaded cert ’kvaser.com: 74fd8929d9e2fb64a9bd0abe3bdf
42d519b7382f’ linked to ’.builtin_trusted_keys’
  [    0.673902] EFI: Loaded cert ’Canonical Ltd. Master Certificate Authority:
ad91990bc22ab1f517048c23b6655a268e345a63’ linked to ’.builtin_trusted_keys’

我们现在还可以使用mokutil命令测试我们的证书是否已注册。

$ cd ~/sign_cert
$ mokutil --test-key modulesign.der
modulesign.der is already enrolled

构建,签名和安装模块

在构建之前,我们需要从Kvaser下载页面下载最新版本的linuxcan,截至到这篇文章撰稿最新版本是v5.20.。6

$ wget http://www.kvaser.com/software/7330130980754/V5_20_0/linuxcan.tar.gz
$ tar xvzf linuxcan.tar.gz
$ cd linuxcan

为了方便我们在正常构建过程中将文件签名,我们修改文件config.mak中的kv_module目标如下。7

# Target found in config.mak located in the top level directory of linuxcan
kv_module:
        @echo --------------------------------------------------------------------
        @echo "building $(KV_MODULE_NAME) $(IS_DEBUG)"
        @echo "Kernel src:" $(KV_KERNEL_SRC_DIR)
        $(MAKE) -C $(KV_KERNEL_SRC_DIR) SUBDIRS=$(PWD) modules
        @if [ "$(KV_SIGN_CERT_PATH)" != "" ] && [ "$(KV_SIGN_CERT_NAME)" != "" ]; then \
                echo "Signing module $(KV_MODULE_NAME).ko with $(KV_SIGN_CERT_PATH)/$(KV_SIGN_CERT_NAME)"; \
                $(KV_KERNEL_SRC_DIR)/scripts/sign-file sha256 $(KV_SIGN_CERT_PATH)/$(KV_SIGN_CERT_NAME).priv \
                $(KV_SIGN_CERT_PATH)/$(KV_SIGN_CERT_NAME).der $(KV_MODULE_NAME).ko; \
        fi
        @echo --------------------------------------------------------------------

现在可以通过添加两个环境变量KV_SIGN_CERT_PATHKV_SIGN_CERT_NAME,使用常见的make命令来构建和签名驱动程序模块。在构建后安装模块。

 # KV_SIGN_CERT_PATH is the path to your private key and certificate.
 # KV_SIGN_CERT_NAME is the base file name of your private key and
certificate, without suffix.
 $ make KV_SIGN_CERT_PATH=~/sign_cert KV_SIGN_CERT_NAME=modulesign
 $ sudo make install

为了验证已安装的模块是否正常工作,我们使用modprobe命令来手动加载模块并验证它是否已加载。8 我们要确保删除模块以免在Kvaser USB设备连接时自动加载。

$ sudo modprobe mhydra
$ lsmod | grep ’kvcommon\|mhydra’
mhydra                 45056  0
kvcommon               45056  1 mhydra

$ sudo modprobe -r mhydra kvcommon


脚注

1  有关保护私钥的注意事项可以在Linux内核文档中找到,网址为https://static.lwn.net/kerneldoc/admin-guide/module-signing.html#administering-protecting-the-private-key

2 您可以在SSL安装知识库中阅读有关不同X509文件扩展名(如DER)的更多信息,网址为https://support.ssl.com/Knowledgebase/Article/View/19/0/der-vs-crt-vs-cer-vs-pem-certificates-and-how-to-convert-them/.

3 有关公用名称重要性的说明,请参阅stackexchange文章中的详细内容https://security.stackexchange.com/questions/40026/openssl-x509-whats-the-significance-of-cn-common-name/.

4  使用mokutil命令来管理shim层使用的机主密钥(MOK),以验证grub2和内核映像。

5  如果您错过此超时,则需要重新运行mokutil --import命令并重新启动。

6  Kvaser下载页面https://www.kvaser.cn/downloads

7  调整后的makefile目标将被并入linuxcan的下一个版本

8  目前无法使用modinfo查看模块是否已经签名,详细信息请参阅github中所列的coreos问题,网址为https://github.com/coreos/bugs/issues/1054/

Author Image

Mikkel Gerdes