diff options
Diffstat (limited to 'Documentation/security/keys-request-key.txt')
-rw-r--r-- | Documentation/security/keys-request-key.txt | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/Documentation/security/keys-request-key.txt b/Documentation/security/keys-request-key.txt new file mode 100644 index 000000000000..51987bfecfed --- /dev/null +++ b/Documentation/security/keys-request-key.txt | |||
@@ -0,0 +1,202 @@ | |||
1 | =================== | ||
2 | KEY REQUEST SERVICE | ||
3 | =================== | ||
4 | |||
5 | The key request service is part of the key retention service (refer to | ||
6 | Documentation/security/keys.txt). This document explains more fully how | ||
7 | the requesting algorithm works. | ||
8 | |||
9 | The process starts by either the kernel requesting a service by calling | ||
10 | request_key*(): | ||
11 | |||
12 | struct key *request_key(const struct key_type *type, | ||
13 | const char *description, | ||
14 | const char *callout_info); | ||
15 | |||
16 | or: | ||
17 | |||
18 | struct key *request_key_with_auxdata(const struct key_type *type, | ||
19 | const char *description, | ||
20 | const char *callout_info, | ||
21 | size_t callout_len, | ||
22 | void *aux); | ||
23 | |||
24 | or: | ||
25 | |||
26 | struct key *request_key_async(const struct key_type *type, | ||
27 | const char *description, | ||
28 | const char *callout_info, | ||
29 | size_t callout_len); | ||
30 | |||
31 | or: | ||
32 | |||
33 | struct key *request_key_async_with_auxdata(const struct key_type *type, | ||
34 | const char *description, | ||
35 | const char *callout_info, | ||
36 | size_t callout_len, | ||
37 | void *aux); | ||
38 | |||
39 | Or by userspace invoking the request_key system call: | ||
40 | |||
41 | key_serial_t request_key(const char *type, | ||
42 | const char *description, | ||
43 | const char *callout_info, | ||
44 | key_serial_t dest_keyring); | ||
45 | |||
46 | The main difference between the access points is that the in-kernel interface | ||
47 | does not need to link the key to a keyring to prevent it from being immediately | ||
48 | destroyed. The kernel interface returns a pointer directly to the key, and | ||
49 | it's up to the caller to destroy the key. | ||
50 | |||
51 | The request_key*_with_auxdata() calls are like the in-kernel request_key*() | ||
52 | calls, except that they permit auxiliary data to be passed to the upcaller (the | ||
53 | default is NULL). This is only useful for those key types that define their | ||
54 | own upcall mechanism rather than using /sbin/request-key. | ||
55 | |||
56 | The two async in-kernel calls may return keys that are still in the process of | ||
57 | being constructed. The two non-async ones will wait for construction to | ||
58 | complete first. | ||
59 | |||
60 | The userspace interface links the key to a keyring associated with the process | ||
61 | to prevent the key from going away, and returns the serial number of the key to | ||
62 | the caller. | ||
63 | |||
64 | |||
65 | The following example assumes that the key types involved don't define their | ||
66 | own upcall mechanisms. If they do, then those should be substituted for the | ||
67 | forking and execution of /sbin/request-key. | ||
68 | |||
69 | |||
70 | =========== | ||
71 | THE PROCESS | ||
72 | =========== | ||
73 | |||
74 | A request proceeds in the following manner: | ||
75 | |||
76 | (1) Process A calls request_key() [the userspace syscall calls the kernel | ||
77 | interface]. | ||
78 | |||
79 | (2) request_key() searches the process's subscribed keyrings to see if there's | ||
80 | a suitable key there. If there is, it returns the key. If there isn't, | ||
81 | and callout_info is not set, an error is returned. Otherwise the process | ||
82 | proceeds to the next step. | ||
83 | |||
84 | (3) request_key() sees that A doesn't have the desired key yet, so it creates | ||
85 | two things: | ||
86 | |||
87 | (a) An uninstantiated key U of requested type and description. | ||
88 | |||
89 | (b) An authorisation key V that refers to key U and notes that process A | ||
90 | is the context in which key U should be instantiated and secured, and | ||
91 | from which associated key requests may be satisfied. | ||
92 | |||
93 | (4) request_key() then forks and executes /sbin/request-key with a new session | ||
94 | keyring that contains a link to auth key V. | ||
95 | |||
96 | (5) /sbin/request-key assumes the authority associated with key U. | ||
97 | |||
98 | (6) /sbin/request-key execs an appropriate program to perform the actual | ||
99 | instantiation. | ||
100 | |||
101 | (7) The program may want to access another key from A's context (say a | ||
102 | Kerberos TGT key). It just requests the appropriate key, and the keyring | ||
103 | search notes that the session keyring has auth key V in its bottom level. | ||
104 | |||
105 | This will permit it to then search the keyrings of process A with the | ||
106 | UID, GID, groups and security info of process A as if it was process A, | ||
107 | and come up with key W. | ||
108 | |||
109 | (8) The program then does what it must to get the data with which to | ||
110 | instantiate key U, using key W as a reference (perhaps it contacts a | ||
111 | Kerberos server using the TGT) and then instantiates key U. | ||
112 | |||
113 | (9) Upon instantiating key U, auth key V is automatically revoked so that it | ||
114 | may not be used again. | ||
115 | |||
116 | (10) The program then exits 0 and request_key() deletes key V and returns key | ||
117 | U to the caller. | ||
118 | |||
119 | This also extends further. If key W (step 7 above) didn't exist, key W would | ||
120 | be created uninstantiated, another auth key (X) would be created (as per step | ||
121 | 3) and another copy of /sbin/request-key spawned (as per step 4); but the | ||
122 | context specified by auth key X will still be process A, as it was in auth key | ||
123 | V. | ||
124 | |||
125 | This is because process A's keyrings can't simply be attached to | ||
126 | /sbin/request-key at the appropriate places because (a) execve will discard two | ||
127 | of them, and (b) it requires the same UID/GID/Groups all the way through. | ||
128 | |||
129 | |||
130 | ==================================== | ||
131 | NEGATIVE INSTANTIATION AND REJECTION | ||
132 | ==================================== | ||
133 | |||
134 | Rather than instantiating a key, it is possible for the possessor of an | ||
135 | authorisation key to negatively instantiate a key that's under construction. | ||
136 | This is a short duration placeholder that causes any attempt at re-requesting | ||
137 | the key whilst it exists to fail with error ENOKEY if negated or the specified | ||
138 | error if rejected. | ||
139 | |||
140 | This is provided to prevent excessive repeated spawning of /sbin/request-key | ||
141 | processes for a key that will never be obtainable. | ||
142 | |||
143 | Should the /sbin/request-key process exit anything other than 0 or die on a | ||
144 | signal, the key under construction will be automatically negatively | ||
145 | instantiated for a short amount of time. | ||
146 | |||
147 | |||
148 | ==================== | ||
149 | THE SEARCH ALGORITHM | ||
150 | ==================== | ||
151 | |||
152 | A search of any particular keyring proceeds in the following fashion: | ||
153 | |||
154 | (1) When the key management code searches for a key (keyring_search_aux) it | ||
155 | firstly calls key_permission(SEARCH) on the keyring it's starting with, | ||
156 | if this denies permission, it doesn't search further. | ||
157 | |||
158 | (2) It considers all the non-keyring keys within that keyring and, if any key | ||
159 | matches the criteria specified, calls key_permission(SEARCH) on it to see | ||
160 | if the key is allowed to be found. If it is, that key is returned; if | ||
161 | not, the search continues, and the error code is retained if of higher | ||
162 | priority than the one currently set. | ||
163 | |||
164 | (3) It then considers all the keyring-type keys in the keyring it's currently | ||
165 | searching. It calls key_permission(SEARCH) on each keyring, and if this | ||
166 | grants permission, it recurses, executing steps (2) and (3) on that | ||
167 | keyring. | ||
168 | |||
169 | The process stops immediately a valid key is found with permission granted to | ||
170 | use it. Any error from a previous match attempt is discarded and the key is | ||
171 | returned. | ||
172 | |||
173 | When search_process_keyrings() is invoked, it performs the following searches | ||
174 | until one succeeds: | ||
175 | |||
176 | (1) If extant, the process's thread keyring is searched. | ||
177 | |||
178 | (2) If extant, the process's process keyring is searched. | ||
179 | |||
180 | (3) The process's session keyring is searched. | ||
181 | |||
182 | (4) If the process has assumed the authority associated with a request_key() | ||
183 | authorisation key then: | ||
184 | |||
185 | (a) If extant, the calling process's thread keyring is searched. | ||
186 | |||
187 | (b) If extant, the calling process's process keyring is searched. | ||
188 | |||
189 | (c) The calling process's session keyring is searched. | ||
190 | |||
191 | The moment one succeeds, all pending errors are discarded and the found key is | ||
192 | returned. | ||
193 | |||
194 | Only if all these fail does the whole thing fail with the highest priority | ||
195 | error. Note that several errors may have come from LSM. | ||
196 | |||
197 | The error priority is: | ||
198 | |||
199 | EKEYREVOKED > EKEYEXPIRED > ENOKEY | ||
200 | |||
201 | EACCES/EPERM are only returned on a direct search of a specific keyring where | ||
202 | the basal keyring does not grant Search permission. | ||