Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 1 | =================== |
| 2 | Key Request Service |
| 3 | =================== |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 4 | |
| 5 | The key request service is part of the key retention service (refer to |
Josh Holland | adf31ee | 2017-08-19 16:21:06 +0100 | [diff] [blame] | 6 | Documentation/security/core.rst). This document explains more fully how |
Randy Dunlap | d410fa4 | 2011-05-19 15:59:38 -0700 | [diff] [blame] | 7 | the requesting algorithm works. |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 8 | |
| 9 | The process starts by either the kernel requesting a service by calling |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 10 | ``request_key*()``:: |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 11 | |
| 12 | struct key *request_key(const struct key_type *type, |
| 13 | const char *description, |
David Howells | 4a38e12 | 2008-04-29 01:01:24 -0700 | [diff] [blame] | 14 | const char *callout_info); |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 15 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 16 | or:: |
David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 17 | |
| 18 | struct key *request_key_with_auxdata(const struct key_type *type, |
| 19 | const char *description, |
David Howells | 4a38e12 | 2008-04-29 01:01:24 -0700 | [diff] [blame] | 20 | const char *callout_info, |
| 21 | size_t callout_len, |
David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 22 | void *aux); |
| 23 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 24 | or:: |
David Howells | 76181c1 | 2007-10-16 23:29:46 -0700 | [diff] [blame] | 25 | |
| 26 | struct key *request_key_async(const struct key_type *type, |
| 27 | const char *description, |
David Howells | 4a38e12 | 2008-04-29 01:01:24 -0700 | [diff] [blame] | 28 | const char *callout_info, |
| 29 | size_t callout_len); |
David Howells | 76181c1 | 2007-10-16 23:29:46 -0700 | [diff] [blame] | 30 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 31 | or:: |
David Howells | 76181c1 | 2007-10-16 23:29:46 -0700 | [diff] [blame] | 32 | |
| 33 | struct key *request_key_async_with_auxdata(const struct key_type *type, |
| 34 | const char *description, |
David Howells | 4a38e12 | 2008-04-29 01:01:24 -0700 | [diff] [blame] | 35 | const char *callout_info, |
| 36 | size_t callout_len, |
David Howells | 76181c1 | 2007-10-16 23:29:46 -0700 | [diff] [blame] | 37 | void *aux); |
| 38 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 39 | Or by userspace invoking the request_key system call:: |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 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 | |
David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 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 | |
David Howells | 76181c1 | 2007-10-16 23:29:46 -0700 | [diff] [blame] | 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. |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 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 | |
David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 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 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 70 | The Process |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 71 | =========== |
| 72 | |
| 73 | A request proceeds in the following manner: |
| 74 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 75 | 1) Process A calls request_key() [the userspace syscall calls the kernel |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 76 | interface]. |
| 77 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 78 | 2) request_key() searches the process's subscribed keyrings to see if there's |
David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 79 | a suitable key there. If there is, it returns the key. If there isn't, |
| 80 | and callout_info is not set, an error is returned. Otherwise the process |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 81 | proceeds to the next step. |
| 82 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 83 | 3) request_key() sees that A doesn't have the desired key yet, so it creates |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 84 | two things: |
| 85 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 86 | a) An uninstantiated key U of requested type and description. |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 87 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 88 | b) An authorisation key V that refers to key U and notes that process A |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 89 | is the context in which key U should be instantiated and secured, and |
| 90 | from which associated key requests may be satisfied. |
| 91 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 92 | 4) request_key() then forks and executes /sbin/request-key with a new session |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 93 | keyring that contains a link to auth key V. |
| 94 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 95 | 5) /sbin/request-key assumes the authority associated with key U. |
David Howells | b5f545c | 2006-01-08 01:02:47 -0800 | [diff] [blame] | 96 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 97 | 6) /sbin/request-key execs an appropriate program to perform the actual |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 98 | instantiation. |
| 99 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 100 | 7) The program may want to access another key from A's context (say a |
David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 101 | Kerberos TGT key). It just requests the appropriate key, and the keyring |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 102 | search notes that the session keyring has auth key V in its bottom level. |
| 103 | |
| 104 | This will permit it to then search the keyrings of process A with the |
| 105 | UID, GID, groups and security info of process A as if it was process A, |
| 106 | and come up with key W. |
| 107 | |
Jonathan Corbet | 5ea787a | 2017-05-18 10:46:25 -0600 | [diff] [blame] | 108 | 8) The program then does what it must to get the data with which to |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 109 | instantiate key U, using key W as a reference (perhaps it contacts a |
| 110 | Kerberos server using the TGT) and then instantiates key U. |
| 111 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 112 | 9) Upon instantiating key U, auth key V is automatically revoked so that it |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 113 | may not be used again. |
| 114 | |
Jonathan Corbet | 5ea787a | 2017-05-18 10:46:25 -0600 | [diff] [blame] | 115 | 10) The program then exits 0 and request_key() deletes key V and returns key |
| 116 | U to the caller. |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 117 | |
David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 118 | This also extends further. If key W (step 7 above) didn't exist, key W would |
| 119 | be created uninstantiated, another auth key (X) would be created (as per step |
| 120 | 3) and another copy of /sbin/request-key spawned (as per step 4); but the |
| 121 | context specified by auth key X will still be process A, as it was in auth key |
| 122 | V. |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 123 | |
| 124 | This is because process A's keyrings can't simply be attached to |
| 125 | /sbin/request-key at the appropriate places because (a) execve will discard two |
| 126 | of them, and (b) it requires the same UID/GID/Groups all the way through. |
| 127 | |
| 128 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 129 | Negative Instantiation And Rejection |
David Howells | fdd1b94 | 2011-03-07 15:06:09 +0000 | [diff] [blame] | 130 | ==================================== |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 131 | |
| 132 | Rather than instantiating a key, it is possible for the possessor of an |
| 133 | authorisation key to negatively instantiate a key that's under construction. |
| 134 | This is a short duration placeholder that causes any attempt at re-requesting |
David Howells | fdd1b94 | 2011-03-07 15:06:09 +0000 | [diff] [blame] | 135 | the key whilst it exists to fail with error ENOKEY if negated or the specified |
| 136 | error if rejected. |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 137 | |
| 138 | This is provided to prevent excessive repeated spawning of /sbin/request-key |
| 139 | processes for a key that will never be obtainable. |
| 140 | |
| 141 | Should the /sbin/request-key process exit anything other than 0 or die on a |
| 142 | signal, the key under construction will be automatically negatively |
| 143 | instantiated for a short amount of time. |
| 144 | |
| 145 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 146 | The Search Algorithm |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 147 | ==================== |
| 148 | |
| 149 | A search of any particular keyring proceeds in the following fashion: |
| 150 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 151 | 1) When the key management code searches for a key (keyring_search_aux) it |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 152 | firstly calls key_permission(SEARCH) on the keyring it's starting with, |
| 153 | if this denies permission, it doesn't search further. |
| 154 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 155 | 2) It considers all the non-keyring keys within that keyring and, if any key |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 156 | matches the criteria specified, calls key_permission(SEARCH) on it to see |
David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 157 | if the key is allowed to be found. If it is, that key is returned; if |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 158 | not, the search continues, and the error code is retained if of higher |
| 159 | priority than the one currently set. |
| 160 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 161 | 3) It then considers all the keyring-type keys in the keyring it's currently |
David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 162 | searching. It calls key_permission(SEARCH) on each keyring, and if this |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 163 | grants permission, it recurses, executing steps (2) and (3) on that |
| 164 | keyring. |
| 165 | |
| 166 | The process stops immediately a valid key is found with permission granted to |
David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 167 | use it. Any error from a previous match attempt is discarded and the key is |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 168 | returned. |
| 169 | |
| 170 | When search_process_keyrings() is invoked, it performs the following searches |
| 171 | until one succeeds: |
| 172 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 173 | 1) If extant, the process's thread keyring is searched. |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 174 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 175 | 2) If extant, the process's process keyring is searched. |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 176 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 177 | 3) The process's session keyring is searched. |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 178 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 179 | 4) If the process has assumed the authority associated with a request_key() |
David Howells | b5f545c | 2006-01-08 01:02:47 -0800 | [diff] [blame] | 180 | authorisation key then: |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 181 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 182 | a) If extant, the calling process's thread keyring is searched. |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 183 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 184 | b) If extant, the calling process's process keyring is searched. |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 185 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 186 | c) The calling process's session keyring is searched. |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 187 | |
| 188 | The moment one succeeds, all pending errors are discarded and the found key is |
| 189 | returned. |
| 190 | |
| 191 | Only if all these fail does the whole thing fail with the highest priority |
David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 192 | error. Note that several errors may have come from LSM. |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 193 | |
Kees Cook | 3db38ed | 2017-05-13 04:51:52 -0700 | [diff] [blame] | 194 | The error priority is:: |
David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 195 | |
| 196 | EKEYREVOKED > EKEYEXPIRED > ENOKEY |
| 197 | |
| 198 | EACCES/EPERM are only returned on a direct search of a specific keyring where |
| 199 | the basal keyring does not grant Search permission. |