KEYRINGS - Linux手册页

时间:2019-08-20 18:01:58  来源:igfitidea点击:

Linux程序员手册 第7部分
更新日期: 2020-08-13

名称

密钥环-内核内密钥管理和保留功能

说明

Linux密钥管理工具主要是各种内核组件在内核中保留或缓存安全数据,身份验证密钥,加密密钥和其他数据的一种方式。

提供系统调用接口,以便用户空间程序可以管理那些对象,也可以将其用于自己的目的。请参阅add_key(2),request_key(2)和keyctl(2)。

提供了一个库和一些用户空间实用程序以允许访问该设施。有关更多信息,请参见keyctl(1),keyctl(3)和keyutils(7)。

Keys

密钥具有以下属性:

Serial number (ID)

这是唯一的整数句柄,在系统调用中通过该句柄引用键。有时将序列号同义地称为密钥ID。通过编程,密钥序列号使用key_serial_t类型表示。

Type

密钥的类型定义了密钥中可以保存哪种数据,如何解析密钥的建议内容以及如何使用有效负载。

有许多通用类型可用,以及由特定内核组件定义的一些专家类型。

Description (name)

键说明是一个可打印的字符串,用作键的搜索项(与键类型结合使用)以及显示名称。在搜索过程中,描述可能会部分匹配或完全匹配。

Payload (data)

有效负载是密钥的实际内容。通常在创建密钥时进行设置,但是如果内核在请求密钥时还不知道该密钥,则内核有可能向上调用用户空间以完成密钥的实例化。有关更多详细信息,请参见request_key(2)。

如果密钥类型支持密钥的有效负载,并且已将适当的权限授予调用者,则可以读取和更新密钥的有效负载。

Access rights

就像文件一样,每个密钥都有一个拥有的用户ID,拥有的组ID和安全标签。每个键也具有一组权限,尽管除了普通的UNIX文件外,还具有更多的权限,并且除了普通的用户,组和其他用户之外,还有一个附加的类别(拥有者)(请参见下面的所有权)。

请注意,密钥受配额控制,因为它们需要不可交换的内核内存。拥有的用户ID指定要借记其配额的用户。

Expiration time

每个密钥可以设置一个到期时间。达到该时间后,该密钥将标记为已过期,并且访问失败,并显示错误EKEYEXPIRED。如果未删除,更新或替换,则在设置的时间后,将自动删除过期的密钥(收集垃圾)以及所有指向它的链接,并且尝试访问该密钥失败,并显示错误ENOKEY。

Reference count

每个键都有一个参考计数。密钥由密钥环,当前活动的用户以及进程的凭据引用。当引用计数达到零时,将调度该键进行垃圾回收。

Key types

内核提供了几种基本类型的密钥:

keyring

密钥环是特殊密钥,用于存储指向其他密钥(包括其他密钥环)的一组链接,类似于包含指向文件链接的目录。密钥环的主要目的是防止垃圾回收其他密钥,因为没有东西引用它们。

具有以句点(aq.aq)开头的描述(名称)的密钥环保留给实现。

user

这是通用密钥类型。密钥完全保留在内核内存中。有效载荷可以由用户空间应用程序读取和更新。

此类密钥的有效载荷是最多32,767字节的任意数据的blob。

该描述可以是任何有效的字符串,尽管最好以冒号分隔的前缀开头,该前缀代表密钥所关注的服务(例如,afs:mykey)。

logon(since Linux 3.3)

此密钥类型与用户基本相同,但不提供读取功能(即keyctl(2)KEYCTL_READ操作),这意味着密钥有效载荷永远不会在用户空间中可见。这适用于存储用户空间不可读的用户名-密码对。

登录密钥的描述必须以非空的冒号分隔的前缀开头,其目的是识别密钥所属的服务。 (请注意,这与用户类型的键不同,在用户类型的键中建议添加前缀但不强制使用。)

big_key(since Linux 3.13)

此密钥类型与用户密钥类型相似,但是它可以容纳最大1 MiB的有效负载。此密钥类型可用于保持Kerberos票证高速缓存之类的目的。

如果数据大小超出了将数据存储在文件系统中的开销,则可以将有效负载数据存储在tmpfs文件系统中,而不是存储在内核内存中。 (将数据存储在文件系统中需要在内核中分配文件系统结构。这些结构的大小决定了使用tmpfs存储方法的大小阈值。)从Linux 4.8开始,有效载荷数据在存储在tmpfs中时会被加密,从而防止将其未加密地写入交换空间。

还可以使用更多专门的密钥类型,但是这里不讨论它们,因为它们不适合正常的用户空间使用。

以句点(aq.aq)开头的键类型名称保留给实现。

Keyrings

如前所述,密钥环是一种特殊类型的密钥,其中包含指向其他密钥的链接(可能包括其他密钥环)。密钥可以通过多个密钥环链接到。密钥环可被视为类似于UNIX目录,其中每个目录都包含一组指向文件的硬链接。

各种操作(系统调用)只能应用于密钥环:

Adding

可以通过创建密钥的系统调用将密钥添加到密钥环。这样可以防止在系统调用释放对密钥的最后引用时立即删除新密钥。

Linking

可以将链接添加到指向已知密钥的密钥环,前提是这不会创建自引用循环。

Unlinking

可以从钥匙圈中删除链接。当最后一个指向键的链接被删除时,该键将被安排为由垃圾回收器删除。

Clearing

所有链接都可以从钥匙圈中删除。

Searching

密匙环可被视为树或子树的根,其中密匙环形成分支而非密匙叶。可以在该树中搜索与特定类型和描述匹配的密钥。

有关更多信息,请参见keyctl_clear(3),keyctl_link(3),keyctl_search(3)和keyctl_unlink(3)。

Anchoring keys

为防止密钥被垃圾回收,当内核不对其进行主动使用时,必须对其进行锚定以保持其引用计数增加。

密钥环用于锚定其他密钥:每个链接都是密钥上的引用。请注意,密钥环本身只是密钥,并且还必须遵循相同的锚定要求,以防止被垃圾回收。

内核提供了许多锚键环。请注意,其中某些钥匙圈仅在首次访问时才会创建。

Process keyrings

流程凭证本身使用特定的语义引用密钥环。只要存在凭据集(通常只要存在该过程),就会固定这些密钥环。

共有三个具有不同继承/共享规则的密钥环:session-keyring(7)(由所有子进程继承和共享),process-keyring(7)(由进程中的所有线程共享)和thread-keyring( 7)(特定于特定线程)。

作为使用实际密钥环ID的替代方法,在对add_key(2),keyctl(2)和request_key(2)的调用中,特殊密钥环值KEY_SPEC_SESSION_KEYRING,KEY_SPEC_PROCESS_KEYRING和KEY_SPEC_THREAD_KEYRING可以用于引用调用者自己的实例这些钥匙扣。

User keyrings

内核已知的每个UID都有一条包含两个密钥环的记录:user-keyring(7)和user-session-keyring(7)。只要内核中的UID记录存在,它们就存在。

作为使用实际密钥环ID的替代方法,在对add_key(2),keyctl(2)和request_key(2)的调用中,特殊密钥环值KEY_SPEC_USER_KEYRING和KEY_SPEC_USER_SESSION_KEYRING可用于引用调用者自己的这些密钥环实例。

启动新的登录会话时,通过pam_keyinit(8)将指向用户密钥环的链接放置在新的会话密钥环中。

Persistent keyrings

对于系统已知的每个UID,都有一个persistent-keyring(7)。它可能会持续到前面提到的UID记录的寿命之外,但是设置了到期时间,以便在设置的时间后自动清除它。持久密钥环允许例如cron(8)脚本使用用户注销后保留在持久密钥环中的凭据。

请注意,每次请求持久密钥时,都会重置持久密钥环的到期时间。

Special keyrings

内核拥有一些特殊的密钥环,可以为特殊目的锚定密钥。例如,系统密钥环用于保存用于模块签名验证的加密密钥。

这些特殊的密钥环通常是封闭的,以便用户空间直接进行更改。

到目前为止,尚未实现用于存储与内核已知的每个GID相关联的密钥的最初计划的"组密钥环"。但是,已为此密钥环定义了常量KEY_SPEC_GROUP_KEYRING。

Possession

拥有概念对于理解密钥环安全模型很重要。线程是否拥有密钥由以下规则确定:

(1)

在以下所有规则中,将忽略任何未授予呼叫者搜索权限的密钥或密钥环。

(2)

线程直接拥有其会话密钥(7),进程密钥(7)和线程密钥(7),因为这些密钥环由其凭据引用。

(3)

如果拥有钥匙圈,那么它链接到的任何钥匙也都拥有。

(4)

如果密钥环链接到的任何密钥本身就是密钥环,则规则(3)递归适用。

(5)

如果从内核调用了一个过程以实例化一个密钥(请参阅request_key(2)),则它也像规则(1)一样拥有请求者的密钥环,就好像它是请求者一样。

注意,拥有不是密钥的基本属性,而是每次需要密钥时都必须计算。

拥有权旨在允许从用户外壳运行的设置用户ID程序访问用户的键。向密钥所有者授予许可权,同时拒绝密钥所有者和密钥组许可,则可以防止基于UID和GID匹配访问密钥。

当创建会话密钥环时,pam_keyinit(8)将一个链接添加到user-keyring(7),从而使用户密钥环及其包含的任何内容默认都具有。

Access rights

每个密钥具有以下与安全性相关的属性:

*

拥有的用户ID

*

允许访问密钥的组的ID

*

安全标签

*

权限掩码

权限掩码包含四组权限。前三套是互斥的。一项访问检查将仅执行一次。按照优先级从高到低的顺序,这三组分别是:

user

如果密钥的用户ID与调用者的文件系统用户ID相匹配,则该集合指定授予的权限。

group

如果用户ID不匹配且密钥的组ID与调用者的文件系统GID或调用者的补充组ID之一匹配,则该集合指定授予的权限。

other

该集合指定了密钥的用户ID和组ID都不匹配时授予的权限。

第四组权利是:

possessor

该集合指定如果确定调用者拥有密钥,则授予的权限。

密钥的完整权限集是适用的前三组中的哪一个加和(如果拥有密钥则适用第四组)。

可以在四个掩码中的每个掩码中授予的权限集如下:

view

可以读取密钥的属性。这包括类型,描述和访问权限(不包括安全标签)。

read

对于密钥:可以读取密钥的有效载荷。对于密钥环:可以读取该密钥环链接到的序列号(密钥)列表。

write

密钥的有效载荷可以被更新并且密钥可以被撤销。对于密钥环,可以将链接添加到密钥环或从密钥环中删除,并且可以完全清除密钥环(删除所有链接),

search

对于密钥(或密钥环):可以通过搜索找到密钥。对于密钥环:可以搜索由密钥环链接的密钥和密钥环。

link

可以从钥匙圈到钥匙创建链接。创建密钥时所建立的密钥的初始链接不需要此权限。

setattr

可以更改密钥的所有权详细信息和安全标签,可以设置密钥的到期时间,并且可以撤销密钥。

除了访问权限,如果其策略要求,任何活动的Linux安全模块(LSM)都可能会阻止访问密钥。 LSM可以为密钥提供安全标签或其他属性;可通过keyctl_get_security(3)检索此标签。

有关更多信息,请参见keyctl_chown(3),keyctl_describe(3),keyctl_get_security(3),keyctl_setperm(3)和selinux(8)。

Searching for keys

Linux密钥管理工具的关键功能之一是能够找到进程保留的密钥。 request_key(2)系统调用是用户空间应用程序查找密钥的主要访问点。 (在内部,内核有一些相似的东西可供使用键的内部组件使用。)

搜索算法的工作原理如下:

(1)

进程密钥环按以下顺序搜索:线程thread-keyring(7)(如果存在),process-keyring(7)(如果存在),然后session-keyring(7)(如果存在)或用户- session-keyring(7)(如果存在)。

(2)

如果调用方是由request_key(2)上调用机制调用的进程,则还将搜索request_key(2)的原始调用方的密钥环。

(3)

密钥环树的搜索按广度优先顺序进行:首先在每个密钥环中搜索匹配项,然后搜索该密钥环所引用的密钥环。

(4)

如果找到有效的匹配密钥,则搜索将终止并返回该密钥。

(5)

如果找到带有错误状态的匹配键,则会记录该错误状态并继续搜索。

(6)

如果找不到有效的匹配密钥,则返回第一个记录的错误状态;否则,返回错误状态。否则,将返回ENOKEY错误。

还可以搜索特定的钥匙圈,在这种情况下,仅适用步骤(3)至(6)。

有关更多信息,请参见request_key(2)和keyctl_search(3)。

On-demand key creation

如果找不到密钥,则在给定callout_info参数的情况下,request_key(2)将创建一个新密钥,然后向上调用用户空间以实例化该密钥。这样就可以根据需要创建密钥。

通常,这将涉及内核创建一个新进程,该进程执行request-key(8)程序,然后该程序将根据其配置执行适当的处​​理程序。

向处理程序传递一个特殊的授权密钥,该密钥允许它并且只有它才能实例化新密钥。这也用于允许由处理程序执行的搜索也搜索请求者的密钥环。

有关更多信息,请参见request_key(2),keyctl_assume_authority(3),keyctl_instantiate(3),keyctl_negate(3),keyctl_reject(3),request-key(8)和request-key.conf(5)。

/proc files

内核提供各种/ proc文件,这些文件公开有关密钥的信息或定义密钥使用限制。

/proc/keys(since Linux 2.6.10)

该文件公开了读取线程具有查看权限的键列表,并提供了有关每个键的各种信息。线程不需要拥有密钥,该密钥在此文件中可见。

列表中包括的唯一键是那些授予阅读过程查看权限的键(无论它是否拥有它们)。 LSM安全检查仍在执行,并且可能会过滤掉该进程无权查看的其他密钥。

下面是一个可能在此文件中看到的数据示例(其列编号为便于参考)如下:

(1)     (2)     (3)(4)    (5)     (6)   (7)   (8)        (9)
009a2028 I--Q---   1 perm 3f010000  1000  1000 user     krb_ccache:primary: 12
1806c4ba I--Q---   1 perm 3f010000  1000  1000 keyring  _pid: 2
25d3a08f I--Q---   1 perm 1f3f0000  1000 65534 keyring  _uid_ses.1000: 1
28576bd8 I--Q---   3 perm 3f010000  1000  1000 keyring  _krb: 1
2c546d21 I--Q--- 190 perm 3f030000  1000  1000 keyring  _ses: 2
30a4e0be I------   4   2d 1f030000  1000 65534 keyring  _persistent.1000: 1
32100fab I--Q---   4 perm 1f3f0000  1000 65534 keyring  _uid.1000: 2
32a387ea I--Q---   1 perm 3f010000  1000  1000 keyring  _pid: 2
3ce56aea I--Q---   5 perm 3f030000  1000  1000 keyring  _ses: 1

该文件每一行中显示的字段如下:

ID (1)

密钥的ID(序列号),以十六进制表示。

Flags (2)

一组描述密钥状态的标志:

I

密钥已实例化。

R

密钥已被撤消。

D

密钥已失效(即密钥类型尚未注册)。 (在垃圾回收期间,密钥可能会短暂处于此状态。)

Q

密钥有助于用户的配额。

U

密钥是通过回调用户空间来构造的。请参阅request-key(2)。

N

密钥被否定化。

i

密钥已失效。

Usage (3)

这是固定该密钥的内核凭证结构的数量的计数(大约:引用该密钥的线程和打开文件引用的数量)。

Timeout (4)

密钥到期之前的时间,以人类可读的形式表示(周,日,小时,分钟和秒)。这里的字符串perm表示密钥是永久性的(无超时)。字符串expd表示密钥已经过期,但是尚未被垃圾回收。

Permissions (5)

密钥权限,表示为四个十六进制字节,从左到右包含所有者,用户,组和其他权限。在每个字节内,权限位如下:

0x01

视图

Ox02

0x04

0x08

搜索

0x10

链接

0x20

定居者

UID (6)

密钥所有者的用户标识。

GID (7)

密钥的组ID。这里的值-1表示密钥没有组ID;在某些情况下,内核创建的密钥可能会发生这种情况。

Type (8)

密钥类型(用户,密钥环等)

Description (9)

密钥描述(名称)。该字段包含有关密钥的描述性信息。对于大多数键类型,它具有以下形式

名称[:Extra-info]

The name

subfield is the key's description (name).
The optional
extra-info

field provides some further information about the key.
The information that appears here depends on the key type, as follows:

userand logon

密钥有效负载的字节大小(以十进制表示)。

keyring

链接到密钥环的密钥数;如果没有链接到密钥环的字符串,则为空字符串。

big_key

有效载荷大小(以字节为单位),如果关键有效载荷超过阈值,则后跟字符串[file],这意味着有效载荷存储在(可交换的)tmpfs(5)文件系统中;否则,字符串[buff]指示密钥足够小,可以驻留在内核内存中。

对于.request_key_auth密钥类型(授权密钥;请参阅request_key(2)),描述字段的格式如下例所示:

密钥:c9a9b19 pid:28880 ci:10

三个子字段如下:

key

在请求程序中实例化的密钥的十六进制ID。

pid

请求程序的PID。

ci

用来实例化所请求密钥的标注数据的长度(即与授权密钥关联的有效负载的长度)。

/proc/key-users(since Linux 2.6.10)

该文件列出了在系统上至少具有一个密钥的每个用户ID的各种信息。下面是一个可能在此文件中看到的数据示例:

0:    10 9/9 2/1000000 22/25000000
  42:     9 9/9 8/200 106/20000
1000:    11 11/11 10/200 271/20000

每行中显示的字段如下:

uid

用户ID。

usage

这是用于记录关键用户的内核结构的内核内部使用计数。

nkeys/nikeys

用户拥有的密钥总数,以及已实例化的那些密钥的数量。

qnkeys/maxkeys

用户拥有的密钥数量,以及用户可能拥有的最大密钥数量。

qnbytes/maxbytes

该用户拥有的密钥的有效载荷中消耗的字节数,以及该用户的密钥有效载荷中的字节数上限。

/proc/sys/kernel/keys/gc_delay(since Linux 2.6.32)

此文件中的值指定间隔(以秒为单位),在此间隔之后将对垃圾桶中已撤销和过期的密钥进行回收。设置此间隔的目的是,在一个时间窗口内,用户空间可以看到指示密钥发生了什么的错误(分别为EKEYREVOKED和EKEYEXPIRED)。

此文件的默认值为300(即5分钟)。

/proc/sys/kernel/keys/persistent_keyring_expiry(since Linux 3.13)

该文件定义了一个时间间隔(以秒为单位),每次访问密钥环时(通过keyctl_get_persistent(3)或keyctl(2)KEYCTL_GET_PERSISTENT操作),都会重置永久密钥环的到期计时器。

该文件的默认值为259200(即3天)。

以下文件(特权进程可写)用于对可存储在密钥有效负载中的密钥数和数据字节数实施配额:

/proc/sys/kernel/keys/maxbytes(since Linux 2.6.26)

这是非root用户可以在用户拥有的密钥的有效负载中保留的最大数据字节数。

该文件的默认值为20,000。

/proc/sys/kernel/keys/maxkeys(since Linux 2.6.26)

这是非root用户可能拥有的最大密钥数。

该文件的默认值为200。

/proc/sys/kernel/keys/root_maxbytes(since Linux 2.6.26)

这是root用户(root用户名称空间中的UID 0)可以在root拥有的键的有效负载中保留的最大数据字节数。

该文件的默认值为25,000,000(Linux 3.17之前为20,000)。

/proc/sys/kernel/keys/root_maxkeys(since Linux 2.6.26)

这是root用户(root用户名称空间中的UID 0)可以拥有的最大密钥数。

该文件的默认值为1,000,000(Linux 3.17之前为200)。

关于密钥环,请注意,密钥环中的每个链接消耗4个字节的密钥环有效载荷。

Users

Linux密钥管理工具具有许多用户和用法,但不仅限于已经存在的用户和用法。

此功能的内核用户包括:

Network filesystems - DNS

内核使用密钥提供的上行调用机制来上行调用用户空间以进行DNS查找,然后缓存结果。

AF_RXRPC and kAFS - Authentication

AF_RXRPC网络协议和内核AFS文件系统使用密钥存储进行安全或加密流量所需的票证。然后通过AF_RXRPC上的网络操作和kAFS上的文件系统操作来查找这些文件。

NFS - User ID mapping

NFS文件系统使用密钥来存储外部用户ID到本地用户ID的映射。

CIFS - Password

CIFS文件系统使用密钥存储用于访问远程共享的密码。

Module verification

可以进行内核构建过程以对模块进行密码签名。然后在加载模块时检查该签名。

此功能的用户空间用户包括:

Kerberos key storage

MIT Kerberos 5工具(libkrb5)可以使用密钥来存储身份验证令牌,可以使该令牌在用户最后一次使用它们后的指定时间自动清除,但是在此之前,它们会在用户注销后保持挂起状态,以便cron(8)脚本可以使用它们。

另外参见

keyctl(1),add_key(2),keyctl(2),request_key(2),keyctl(3),keyutils(7),持久密钥(7),进程密钥(7),会话密钥(7) ,线程密钥(7),用户密钥(7),用户会话密钥(7),pam_keyinit(8),请求密钥(8)

内核源文件Documentation / crypto / asymmetric-keys.txt和Documentation / security / keys下(或在Linux 4.13之前的文件Documentation / security / keys.txt中)。

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/