| David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 1 | 			      =================== | 
 | 2 | 			      KEY REQUEST SERVICE | 
 | 3 | 			      =================== | 
 | 4 |  | 
 | 5 | The key request service is part of the key retention service (refer to | 
| David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 6 | Documentation/keys.txt).  This document explains more fully how the requesting | 
 | 7 | 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 | 
| David Howells | 4e54f08 | 2006-06-29 02:24:28 -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 |  | 
| David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 16 | or: | 
 | 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 |  | 
| David Howells | 76181c1 | 2007-10-16 23:29:46 -0700 | [diff] [blame] | 24 | or: | 
 | 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 |  | 
 | 31 | or: | 
 | 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 |  | 
| David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 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 |  | 
| 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 |  | 
| David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 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 | 
| David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 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 | 
| David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 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 |  | 
| David Howells | b5f545c | 2006-01-08 01:02:47 -0800 | [diff] [blame] | 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 | 
| David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 99 |      instantiation. | 
 | 100 |  | 
| David Howells | b5f545c | 2006-01-08 01:02:47 -0800 | [diff] [blame] | 101 |  (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] | 102 |      Kerberos TGT key).  It just requests the appropriate key, and the keyring | 
| David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 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 |  | 
| David Howells | b5f545c | 2006-01-08 01:02:47 -0800 | [diff] [blame] | 109 |  (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] | 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 |  | 
| David Howells | b5f545c | 2006-01-08 01:02:47 -0800 | [diff] [blame] | 113 |  (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] | 114 |      may not be used again. | 
 | 115 |  | 
| David Howells | b5f545c | 2006-01-08 01:02:47 -0800 | [diff] [blame] | 116 | (10) The program then exits 0 and request_key() deletes key V and returns key | 
| David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 117 |      U to the caller. | 
 | 118 |  | 
| David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 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. | 
| David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 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 |  | 
| David Howells | fdd1b94 | 2011-03-07 15:06:09 +0000 | [diff] [blame] | 130 | ==================================== | 
 | 131 | NEGATIVE INSTANTIATION AND REJECTION | 
 | 132 | ==================================== | 
| David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 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 | 
| David Howells | fdd1b94 | 2011-03-07 15:06:09 +0000 | [diff] [blame] | 137 | the key whilst it exists to fail with error ENOKEY if negated or the specified | 
 | 138 | error if rejected. | 
| David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 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 | 
| David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 160 |      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] | 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 | 
| David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 165 |      searching.  It calls key_permission(SEARCH) on each keyring, and if this | 
| David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 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 | 
| David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 170 | 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] | 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 |  | 
| David Howells | b5f545c | 2006-01-08 01:02:47 -0800 | [diff] [blame] | 182 |  (4) If the process has assumed the authority associated with a request_key() | 
 | 183 |      authorisation key then: | 
| David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 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 | 
| David Howells | 4e54f08 | 2006-06-29 02:24:28 -0700 | [diff] [blame] | 195 | error.  Note that several errors may have come from LSM. | 
| David Howells | f1a9bad | 2005-10-07 15:04:52 +0100 | [diff] [blame] | 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. |