密钥管理子系统添加了三个系统调用。
1.add_key
创建成功后,新密钥会被链接入参数keyring表示的钥匙环。
2.keyctl
系统调用keyctl的参数个数不定,第二个参数及后续参数是否存在,类型又是什么,由第一个参数cmd的取值决定。cmd的取值有:
(1)KEYCTL_GET_KEYRING_ID
系统调用keyctl的第二个参数是钥匙环的id。传入特殊的钥匙环的id(-1~-8),此次系统调用返回实际的钥匙环的序列号。
(2)KEYCTL_JOIN_SESSION_KEYRING
系统调用keyctl的第二个参数是一个指向字符串的指针,字符串表示会话钥匙环的名字description)。此次系统调用将调用进程的会话钥匙环设置为第二个参数所指的钥匙环。如果第二个参数是空指针,就创建一个匿名钥匙环作为进程的会话钥匙环。
(3)KEYCTL_UPDATE
系统调用keyctl的第二个参数是密钥的id,第三个参数是payload字符串,第四个参数是payload字符串的长度。此次系统调用更新密钥的payload。
(4)KEYCTL_REVOKE
系统调用keyctl的第二个参数是密钥的id。此次系统调用删除一个密钥。
(5)KEYCTL_DESCRIBE
系统调用keyctl的第二个参数是密钥的id,第三个参数是一个缓冲区指针,第四个参数是缓冲区长度。此次系统调用以“type;uid;gid;perm;description”格式将密钥信息填入缓冲区。
(6)KEYCTL_CLEAR
系统调用keyctl的第二个参数是钥匙环的id。此次系统调用将钥匙环清空。
(7)KEYCTL_LINK
系统调用keyctl的第二个参数是密钥的id,第三个参数是钥匙环的id。此次系统调用将密钥链接入钥匙环。
(8)KEYCTL_UNLINK
系统调用keyctl的第二个参数是密钥的id,第三个参数是钥匙环的id。此次系统调用从钥匙环中清除一个密钥的链接。
(9)KEYCTL_SEARCH
系统调用keyctl的第二个参数是搜索起始点的钥匙环的id,第三个参数是表示类型的字符串,第四个参数是表示名字(描述)的字符串,第五个参数是目的钥匙环的id。从搜索起始点钥匙环开始搜索指定类型和名字的密钥,如果目的钥匙环的id不是0,则将找到的密钥链接入目的钥匙环。
(10)KEYCTL_READ
系统调用keyctl的第二个参数是密钥的id,第三个参数为缓冲区指针,第四个参数是缓冲区长度。将密钥的payload放入缓冲区。
(11)KEYCTL_CHOWN
系统调用keyctl的第二个参数是密钥的id,第三个参数为用户id,第四个参数为组id。改变密钥的属主和属组。如果用户id或组id为-1,表示相应的id不变。
(12)KEYCTL_SETPERM
系统调用keyctl的第二个参数是密钥的id,第三个参数是一个整数,标识权限。改变密钥的存取权限。(www.xing528.com)
(13)KEYCTL_INSTANTIATE
系统调用keyctl的第二个参数是密钥的id,第三个参数是payload指针,第四个参数是payload长度,第五个参数是钥匙环的id。实例化一个密钥。
(14)KEYCTL_INSTANTIATE_IOV
同INSTANTIATE类似,只是系统调用keyctl的第三个输入参数的类型是iovec*,第四个参数是iovec的个数。KEY_INSTANTIATE和系统调用write类似,KEYCTL_INSTANTIATE_IOV和系统调用writev类似。
(15)KEYCTL_NEGATE
系统调用keyctl的第二个参数是密钥的id,第三个参数是时延(timeout)值,第四个参数是钥匙环的id。在时延内用户态进程查询这个密钥会得到ENOKEY的错误。如果钥匙环的id非零此次系统调用还会将密钥链接入第四个参数指定的钥匙环。KEYCTL_NEGATE的应用场景是,当进程暂时无法提供密钥的负载数据时,进程可以将密钥的状态通过KEYCTL_NEGATE置为“negative”,并给出时延。如果超出时延密钥的状态没有变化,内核就会删除密钥。
(16)KEYCTL_REJECT
系统调用keyctl的第二个参数是密钥的id,第三个参数是timeout值,第四个参数是错误码,第五个参数是钥匙环的id。同NEGATE类似,只是在此次系统调用后,进程查询此密钥会得到错误码所标识的错误。
(17)KEYCTL_SET_TIMEOUT
系统调用keyctl的第二个参数是密钥的id,第三个参数是timeout值。过timeout秒后,这个密钥将被清除。
(18)KEYCTL_INVALIDATE
系统调用keyctl的第二个参数是密钥的id。将密钥置为invalidated状态,后续内核垃圾回收机制会删除密钥并回收其资源。
(19)KEYCTL_GET_SECURITY
系统调用keyctl的第二个参数是密钥的id,第三个参数是缓冲区指针,第四个参数是缓冲区长度。将密钥的安全上下文(对SELinux来说就是五元组)转换为字符串存入缓冲区。
(20)KEYCTL_SESSION_TO_PARENT
无后续参数。用当前进程的会话钥匙环替换父进程的会话钥匙环。
(21)KEYCTL_GET_PERSISTENT
系统调用keyctl的第二个参数是用户id,第三个参数是钥匙环的id。找到和用户相关的一个钥匙环,如果内核uid是1000,此钥匙环的名字(描述)是“_persistent.1000”,把它链接入参数指定的钥匙环中。
(22)KEYCTL_SET_REQKEY_KEYRING
系统调用keyctl的第二个参数是一个表示jit_keyring的值。将进程的jit_keyring改为指定的新值并读出原来的jit_keyring值返回。jit_keyring的数据类型是“unsigned char”,它的取值有多个,下面列出三个:KEY_REQKEY_DEFL_NO_CHANGE、KEY_REQKEY_DEFL_ THREAD_KEYRING和KEY_REQKEY_DEFL_PROCESS_KEYRING。jit_keyring用来提供另一种指定钥匙串的方式。当下面要讲述的系统调用request_key的参数keyring为空时内核使用jit_keyring所指定的钥匙串。
(23)KEYCTL_ASSUME_AUTHORITY
系统调用keyctl的第二个参数是密钥的id。类型为key_serial_t。将进程的request_key_auth改为参数指定的key。如果id为0,就清除进程的request_key_auth。
3.request_key
用户态进程通过这个系统调用让内核查询一个密钥,并将其链接入参数指定的钥匙环。如果这个密钥已经存在,则这个系统调用的功能和keyctl(KEYCTL_SEARCH,……)几乎没有区别。如果这个密钥不存在,在这个系统调用中内核还要负责创建密钥。那么,密钥的payload在哪里?内核的做法是根据参数callout_info启动一个用户态进程,由这个用户态进程来具体创建并实例化这个密钥。实际中的问题是内核启动的这个进程本身可能还是无法创建密钥,它又要启动别的进程来做这个工作,如图16-3所示。
图16-3 request_key
在这种重复委托的情况下,有两个东西必须以某种方式传递:一个是密钥,这个密钥已经在内核中创建了,需要用户态进程来实例化;另一个是钥匙环,就是这个密钥在成功实例化后,需要被链接到哪一个钥匙环中。还有一个额外的数据,就是进程的凭证,helper 1或者helper 2或者helper n进程要为process 1进程实例化密钥,这些helper可能要查找process 1的一些和密钥相关的数据。内核引入了一种新的密钥类型:key_type_request_key_auth。这种类型的密钥不是用来加密数据的,而是用来在进程间传递实例化一个密钥所需的信息。在内核创建进程helper 1的时候,先创建一个key_type_request_key_auth类型的密钥,链接入helper 1进程的会话钥匙环。key_type_request_key_auth类型的密钥的payload的子成员data本是“void*”指针,其所指的实例的类型为request_key_auth。
前面说的三个信息这里面都有:target_key、dest_keyring、cred。helper 1进程启动后,就可以调用keyctl(KEYCTL_ASSUME_AUTHORITY,……),将这个key_type_request_key_auth类型的密钥置入自己的进程数据结构的request_key_auth。内核在做密钥相关的查找时,也会查找与request_key_auth中cred相关的密钥。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。