代码之家  ›  专栏  ›  技术社区  ›  Gerhardh

使用syscall()在initramfs中链接keyrings

  •  0
  • Gerhardh  · 技术社区  · 5 年前

    我想将IMA/EVM的证书加载到Linux密钥环中。

    ima_id=`keyctl newring _ima @u`
    evm_id=`keyctl newring _evm @u`
    evmctl import  /etc/keys/x509_ima.der $ima_id
    evmctl import  /etc/keys/x509_evm.der $evm_id
    

    这几乎可以工作,除了权限问题。

    # keyctl show @u
    Keyring
     272896171 --alswrv      0 65534  keyring: _uid.0
     406281657 --alswrv      0     0   \_ keyring: _ima
    keyctl_read: Permission denied
    

    我在网上搜索发现: https://github.com/systemd/systemd/issues/5522

    解决方法是连接钥匙圈:

    keyctl link @us @s
    

    # keyctl show @u
    Keyring
     272896171 --alswrv      0 65534  keyring: _uid.0
     406281657 --alswrv      0     0   \_ keyring: _ima
     647882074 --als--v      0     0   |   \_ asymmetric: abc: gerhard signing key: 15733607aff5480b5eb8b59b501760f9c5d33965
      19332842 --alswrv      0     0   \_ keyring: _evm
     470827275 --als--v      0     0       \_ asymmetric: abc: gerhard signing key: 7e5959ee64090c7fabb6dd803e7d1f48e83c5970
    

    到现在为止,一直都还不错。。。

    为了有用我需要把这些东西 initramfs 我正在处理的系统是一个嵌入式Linux,在这里我没有shell 初始化 .

    所以我用 syscall

    创建密钥环和导入密钥可以正常工作。 但是连接钥匙圈并不是。

    如果我手动输入 keyctl link @us @s 一切又恢复了。

    初始化 但我抓不住。

    这个 我用于链接的如下:

    ret = syscall(__NR_keyctl, KEYCTL_LINK, KEY_SPEC_USER_SESSION_KEYRING, KEY_SPEC_SESSION_KEYRING, 0, 0);
    

    我没有从电话里得到任何负面的结果。

    我在这一页找到了一些提示: https://mjg59.dreamwidth.org/37333.html

    $ keyctl add user testkey testdata @s
    $ keyctl setperm 678913344 0x3f3f0000
    $ keyctl link 678913344 @u
    $ keyctl unlink 678913344 @s
    

    这对键有效,但据我所知,它也应该对键环有效。

    static void create_ima_keyring(void)
    {
        char *name = "_ima";
        char *filename = "/etc/keys/x509_ima.der";
    
        int ringid = syscall(__NR_add_key, "keyring", name, NULL, 0, KEY_SPEC_SESSION_KEYRING);
        {
            // Set permission for keyring ...
            int ret = syscall(__NR_keyctl, KEYCTL_SETPERM, ringid, 0x3f3f0000, 0, 0);
    
            // ... and link to @u
            syscall(__NR_keyctl, KEYCTL_LINK, ringid, KEY_SPEC_USER_KEYRING);
    
            int len;
            unsigned char *pub = file2bin(filename, &len);
            if (pub != NULL)
            {
                int keyid = syscall(__NR_add_key, "asymmetric", NULL, pub, len, ringid);
                if (keyid >= 0)
                {
                    int ret = syscall(__NR_keyctl, KEYCTL_SETPERM, keyid, 0x3f3f0000, 0, 0);
                }
                free(pub);
            }
    
            // TODO: Unlink from @s
        }
    }
    

    对于本例,错误处理被剥离。我没有得到任何错误结果。

    现在我得到了预期的结果 keyctl show @u 执行签名文件将再次导致错误消息:

    digsig: no _ima keyring: -126
    
    0 回复  |  直到 5 年前
        1
  •  1
  •   l.k    5 年前

    我不完全清楚您为填充initramfs所采取的实际步骤。。。尝试检查内容:(假设gzip压缩,也可以尝试xz/lz4/none)

    gzip -dkcq -S img '/path/to/initramfs.img' | cpio -t

    我的第一个猜测是你会发现 /etc/keys/x509-blahblah 在IMITRAFS IMG中不存在。尤其是因为它们在启动时“找不到”,但在登录后才工作。它还可能缺少必要的二进制文件/libs或内核模块。

    如果它需要你手工添加密码模块,你可能会在一个非常有趣的时间。

    内核(2.something?)也可以接受多个initramfs文件,它将合并这些文件。上次我看了大多数桌面引导程序 有办法做到这一点,完整的文件沉默的问题,尽管。。。只需在initramfs映像中构建一个单独的密钥并同时传递这两个密钥就足够了。下面应该可以创建一个。

    cd /etc/keys
    mkdir mkimg
    find ./ -maxdepth 1 -type f | 
       sed 's/^[.]\///' |
       cpio -o -H newc --no-absolute-filenames --renumber-inodes |
       gzip -9qc - > ./mkimg/bootkeys.img'
    

    按照我写的方式,密钥在启动时会被转储到initramfs的根目录中,根据我的经验,这比尝试合并目录要简单,但是如果你愿意的话,可以更改它。

        2
  •  0
  •   Gerhardh    5 年前

    在对配置进行更多的阅读和研究之后,发现需要一个额外的配置标志。

    我必须使 CONFIG_PERSISTENT_KEYRINGS=y initramfs 登录后再使用。