blob: 8209db5ab1e12983513359e2fd3c3593eb93d758 [file] [log] [blame]
xjb04a4022021-11-25 15:01:52 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2019 Google LLC
4 */
5
6/**
7 * DOC: The Keyslot Manager
8 *
9 * Many devices with inline encryption support have a limited number of "slots"
10 * into which encryption contexts may be programmed, and requests can be tagged
11 * with a slot number to specify the key to use for en/decryption.
12 *
13 * As the number of slots are limited, and programming keys is expensive on
14 * many inline encryption hardware, we don't want to program the same key into
15 * multiple slots - if multiple requests are using the same key, we want to
16 * program just one slot with that key and use that slot for all requests.
17 *
18 * The keyslot manager manages these keyslots appropriately, and also acts as
19 * an abstraction between the inline encryption hardware and the upper layers.
20 *
21 * Lower layer devices will set up a keyslot manager in their request queue
22 * and tell it how to perform device specific operations like programming/
23 * evicting keys from keyslots.
24 *
25 * Upper layers will call keyslot_manager_get_slot_for_key() to program a
26 * key into some slot in the inline encryption hardware.
27 */
28#include <crypto/algapi.h>
29#include <linux/keyslot-manager.h>
30#include <linux/atomic.h>
31#include <linux/mutex.h>
32#include <linux/wait.h>
33#include <linux/blkdev.h>
34
35struct keyslot {
36 atomic_t slot_refs;
37 struct list_head idle_slot_node;
38 struct hlist_node hash_node;
39 struct blk_crypto_key key;
40};
41
42struct keyslot_manager {
43 unsigned int num_slots;
44 struct keyslot_mgmt_ll_ops ksm_ll_ops;
45 unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX];
46 void *ll_priv_data;
47
48 /* Protects programming and evicting keys from the device */
49 struct rw_semaphore lock;
50
51 /* List of idle slots, with least recently used slot at front */
52 wait_queue_head_t idle_slots_wait_queue;
53 struct list_head idle_slots;
54 spinlock_t idle_slots_lock;
55
56 /*
57 * Hash table which maps key hashes to keyslots, so that we can find a
58 * key's keyslot in O(1) time rather than O(num_slots). Protected by
59 * 'lock'. A cryptographic hash function is used so that timing attacks
60 * can't leak information about the raw keys.
61 */
62 struct hlist_head *slot_hashtable;
63 unsigned int slot_hashtable_size;
64
65 /* Per-keyslot data */
66 struct keyslot slots[];
67};
68
69/**
70 * keyslot_manager_create() - Create a keyslot manager
71 * @num_slots: The number of key slots to manage.
72 * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops for the device that this keyslot
73 * manager will use to perform operations like programming and
74 * evicting keys.
75 * @crypto_mode_supported: Array of size BLK_ENCRYPTION_MODE_MAX of
76 * bitmasks that represents whether a crypto mode
77 * and data unit size are supported. The i'th bit
78 * of crypto_mode_supported[crypto_mode] is set iff
79 * a data unit size of (1 << i) is supported. We
80 * only support data unit sizes that are powers of
81 * 2.
82 * @ll_priv_data: Private data passed as is to the functions in ksm_ll_ops.
83 *
84 * Allocate memory for and initialize a keyslot manager. Called by e.g.
85 * storage drivers to set up a keyslot manager in their request_queue.
86 *
87 * Context: May sleep
88 * Return: Pointer to constructed keyslot manager or NULL on error.
89 */
90struct keyslot_manager *keyslot_manager_create(unsigned int num_slots,
91 const struct keyslot_mgmt_ll_ops *ksm_ll_ops,
92 const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
93 void *ll_priv_data)
94{
95 struct keyslot_manager *ksm;
96 unsigned int slot;
97 unsigned int i;
98
99 if (num_slots == 0)
100 return NULL;
101
102 /* Check that all ops are specified */
103 if (ksm_ll_ops->keyslot_program == NULL ||
104 ksm_ll_ops->keyslot_evict == NULL)
105 return NULL;
106
107 ksm = kvzalloc(struct_size(ksm, slots, num_slots), GFP_KERNEL);
108 if (!ksm)
109 return NULL;
110
111 ksm->num_slots = num_slots;
112 ksm->ksm_ll_ops = *ksm_ll_ops;
113 memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
114 sizeof(ksm->crypto_mode_supported));
115 ksm->ll_priv_data = ll_priv_data;
116
117 init_rwsem(&ksm->lock);
118
119 init_waitqueue_head(&ksm->idle_slots_wait_queue);
120 INIT_LIST_HEAD(&ksm->idle_slots);
121
122 for (slot = 0; slot < num_slots; slot++) {
123 list_add_tail(&ksm->slots[slot].idle_slot_node,
124 &ksm->idle_slots);
125 }
126
127 spin_lock_init(&ksm->idle_slots_lock);
128
129 ksm->slot_hashtable_size = roundup_pow_of_two(num_slots);
130 ksm->slot_hashtable = kvmalloc_array(ksm->slot_hashtable_size,
131 sizeof(ksm->slot_hashtable[0]),
132 GFP_KERNEL);
133 if (!ksm->slot_hashtable)
134 goto err_free_ksm;
135 for (i = 0; i < ksm->slot_hashtable_size; i++)
136 INIT_HLIST_HEAD(&ksm->slot_hashtable[i]);
137
138 return ksm;
139
140err_free_ksm:
141 keyslot_manager_destroy(ksm);
142 return NULL;
143}
144EXPORT_SYMBOL_GPL(keyslot_manager_create);
145
146static inline struct hlist_head *
147hash_bucket_for_key(struct keyslot_manager *ksm,
148 const struct blk_crypto_key *key)
149{
150 return &ksm->slot_hashtable[key->hash & (ksm->slot_hashtable_size - 1)];
151}
152
153static void remove_slot_from_lru_list(struct keyslot_manager *ksm, int slot)
154{
155 unsigned long flags;
156
157 spin_lock_irqsave(&ksm->idle_slots_lock, flags);
158 list_del(&ksm->slots[slot].idle_slot_node);
159 spin_unlock_irqrestore(&ksm->idle_slots_lock, flags);
160}
161
162static int find_keyslot(struct keyslot_manager *ksm,
163 const struct blk_crypto_key *key)
164{
165 const struct hlist_head *head = hash_bucket_for_key(ksm, key);
166 const struct keyslot *slotp;
167
168 hlist_for_each_entry(slotp, head, hash_node) {
169 if (slotp->key.hash == key->hash &&
170 slotp->key.crypto_mode == key->crypto_mode &&
171 slotp->key.size == key->size &&
172 slotp->key.data_unit_size == key->data_unit_size &&
173 !crypto_memneq(slotp->key.raw, key->raw, key->size))
174 return slotp - ksm->slots;
175 }
176 return -ENOKEY;
177}
178
179static int find_and_grab_keyslot(struct keyslot_manager *ksm,
180 const struct blk_crypto_key *key)
181{
182 int slot;
183
184 slot = find_keyslot(ksm, key);
185 if (slot < 0)
186 return slot;
187 if (atomic_inc_return(&ksm->slots[slot].slot_refs) == 1) {
188 /* Took first reference to this slot; remove it from LRU list */
189 remove_slot_from_lru_list(ksm, slot);
190 }
191 return slot;
192}
193
194/**
195 * keyslot_manager_get_slot_for_key() - Program a key into a keyslot.
196 * @ksm: The keyslot manager to program the key into.
197 * @key: Pointer to the key object to program, including the raw key, crypto
198 * mode, and data unit size.
199 *
200 * Get a keyslot that's been programmed with the specified key. If one already
201 * exists, return it with incremented refcount. Otherwise, wait for a keyslot
202 * to become idle and program it.
203 *
204 * Context: Process context. Takes and releases ksm->lock.
205 * Return: The keyslot on success, else a -errno value.
206 */
207int keyslot_manager_get_slot_for_key(struct keyslot_manager *ksm,
208 const struct blk_crypto_key *key)
209{
210 int slot;
211 int err;
212 struct keyslot *idle_slot;
213
214 down_read(&ksm->lock);
215 slot = find_and_grab_keyslot(ksm, key);
216 up_read(&ksm->lock);
217 if (slot != -ENOKEY)
218 return slot;
219
220 for (;;) {
221 down_write(&ksm->lock);
222 slot = find_and_grab_keyslot(ksm, key);
223 if (slot != -ENOKEY) {
224 up_write(&ksm->lock);
225 return slot;
226 }
227
228 /*
229 * If we're here, that means there wasn't a slot that was
230 * already programmed with the key. So try to program it.
231 */
232 if (!list_empty(&ksm->idle_slots))
233 break;
234
235 up_write(&ksm->lock);
236 wait_event(ksm->idle_slots_wait_queue,
237 !list_empty(&ksm->idle_slots));
238 }
239
240 idle_slot = list_first_entry(&ksm->idle_slots, struct keyslot,
241 idle_slot_node);
242 slot = idle_slot - ksm->slots;
243
244 err = ksm->ksm_ll_ops.keyslot_program(ksm, key, slot);
245 if (err) {
246 wake_up(&ksm->idle_slots_wait_queue);
247 up_write(&ksm->lock);
248 return err;
249 }
250
251 /* Move this slot to the hash list for the new key. */
252 if (idle_slot->key.crypto_mode != BLK_ENCRYPTION_MODE_INVALID)
253 hlist_del(&idle_slot->hash_node);
254 hlist_add_head(&idle_slot->hash_node, hash_bucket_for_key(ksm, key));
255
256 atomic_set(&idle_slot->slot_refs, 1);
257 idle_slot->key = *key;
258
259 remove_slot_from_lru_list(ksm, slot);
260
261 up_write(&ksm->lock);
262 return slot;
263}
264
265/**
266 * keyslot_manager_get_slot() - Increment the refcount on the specified slot.
267 * @ksm: The keyslot manager that we want to modify.
268 * @slot: The slot to increment the refcount of.
269 *
270 * This function assumes that there is already an active reference to that slot
271 * and simply increments the refcount. This is useful when cloning a bio that
272 * already has a reference to a keyslot, and we want the cloned bio to also have
273 * its own reference.
274 *
275 * Context: Any context.
276 */
277void keyslot_manager_get_slot(struct keyslot_manager *ksm, unsigned int slot)
278{
279 if (WARN_ON(slot >= ksm->num_slots))
280 return;
281
282 WARN_ON(atomic_inc_return(&ksm->slots[slot].slot_refs) < 2);
283}
284
285/**
286 * keyslot_manager_put_slot() - Release a reference to a slot
287 * @ksm: The keyslot manager to release the reference from.
288 * @slot: The slot to release the reference from.
289 *
290 * Context: Any context.
291 */
292void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot)
293{
294 unsigned long flags;
295
296 if (WARN_ON(slot >= ksm->num_slots))
297 return;
298
299 if (atomic_dec_and_lock_irqsave(&ksm->slots[slot].slot_refs,
300 &ksm->idle_slots_lock, flags)) {
301 list_add_tail(&ksm->slots[slot].idle_slot_node,
302 &ksm->idle_slots);
303 spin_unlock_irqrestore(&ksm->idle_slots_lock, flags);
304 wake_up(&ksm->idle_slots_wait_queue);
305 }
306}
307
308/**
309 * keyslot_manager_crypto_mode_supported() - Find out if a crypto_mode/data
310 * unit size combination is supported
311 * by a ksm.
312 * @ksm: The keyslot manager to check
313 * @crypto_mode: The crypto mode to check for.
314 * @data_unit_size: The data_unit_size for the mode.
315 *
316 * Calls and returns the result of the crypto_mode_supported function specified
317 * by the ksm.
318 *
319 * Context: Process context.
320 * Return: Whether or not this ksm supports the specified crypto_mode/
321 * data_unit_size combo.
322 */
323bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
324 enum blk_crypto_mode_num crypto_mode,
325 unsigned int data_unit_size)
326{
327 if (!ksm)
328 return false;
329 if (WARN_ON(crypto_mode >= BLK_ENCRYPTION_MODE_MAX))
330 return false;
331 if (WARN_ON(!is_power_of_2(data_unit_size)))
332 return false;
333 return ksm->crypto_mode_supported[crypto_mode] & data_unit_size;
334}
335
336/**
337 * keyslot_manager_evict_key() - Evict a key from the lower layer device.
338 * @ksm: The keyslot manager to evict from
339 * @key: The key to evict
340 *
341 * Find the keyslot that the specified key was programmed into, and evict that
342 * slot from the lower layer device if that slot is not currently in use.
343 *
344 * Context: Process context. Takes and releases ksm->lock.
345 * Return: 0 on success, -EBUSY if the key is still in use, or another
346 * -errno value on other error.
347 */
348int keyslot_manager_evict_key(struct keyslot_manager *ksm,
349 const struct blk_crypto_key *key)
350{
351 int slot;
352 int err;
353 struct keyslot *slotp;
354
355 down_write(&ksm->lock);
356 slot = find_keyslot(ksm, key);
357 if (slot < 0) {
358 err = slot;
359 goto out_unlock;
360 }
361 slotp = &ksm->slots[slot];
362
363 if (atomic_read(&slotp->slot_refs) != 0) {
364 err = -EBUSY;
365 goto out_unlock;
366 }
367 err = ksm->ksm_ll_ops.keyslot_evict(ksm, key, slot);
368 if (err)
369 goto out_unlock;
370
371 hlist_del(&slotp->hash_node);
372 memzero_explicit(&slotp->key, sizeof(slotp->key));
373 err = 0;
374out_unlock:
375 up_write(&ksm->lock);
376 return err;
377}
378
379/**
380 * keyslot_manager_reprogram_all_keys() - Re-program all keyslots.
381 * @ksm: The keyslot manager
382 *
383 * Re-program all keyslots that are supposed to have a key programmed. This is
384 * intended only for use by drivers for hardware that loses its keys on reset.
385 *
386 * Context: Process context. Takes and releases ksm->lock.
387 */
388void keyslot_manager_reprogram_all_keys(struct keyslot_manager *ksm)
389{
390 unsigned int slot;
391
392 down_write(&ksm->lock);
393 for (slot = 0; slot < ksm->num_slots; slot++) {
394 const struct keyslot *slotp = &ksm->slots[slot];
395 int err;
396
397 if (slotp->key.crypto_mode == BLK_ENCRYPTION_MODE_INVALID)
398 continue;
399
400 err = ksm->ksm_ll_ops.keyslot_program(ksm, &slotp->key, slot);
401 WARN_ON(err);
402 }
403 up_write(&ksm->lock);
404}
405EXPORT_SYMBOL_GPL(keyslot_manager_reprogram_all_keys);
406
407/**
408 * keyslot_manager_private() - return the private data stored with ksm
409 * @ksm: The keyslot manager
410 *
411 * Returns the private data passed to the ksm when it was created.
412 */
413void *keyslot_manager_private(struct keyslot_manager *ksm)
414{
415 return ksm->ll_priv_data;
416}
417EXPORT_SYMBOL_GPL(keyslot_manager_private);
418
419void keyslot_manager_destroy(struct keyslot_manager *ksm)
420{
421 if (ksm) {
422 kvfree(ksm->slot_hashtable);
423 memzero_explicit(ksm, struct_size(ksm, slots, ksm->num_slots));
424 kvfree(ksm);
425 }
426}
427EXPORT_SYMBOL_GPL(keyslot_manager_destroy);
428
429/**
430 * keyslot_manager_derive_raw_secret() - Derive software secret from wrapped key
431 * @ksm: The keyslot manager
432 * @wrapped_key: The wrapped key
433 * @wrapped_key_size: Size of the wrapped key in bytes
434 * @secret: (output) the software secret
435 * @secret_size: (output) the number of secret bytes to derive
436 *
437 * Given a hardware-wrapped key, ask the hardware to derive a secret which
438 * software can use for cryptographic tasks other than inline encryption. The
439 * derived secret is guaranteed to be cryptographically isolated from the key
440 * with which any inline encryption with this wrapped key would actually be
441 * done. I.e., both will be derived from the unwrapped key.
442 *
443 * Return: 0 on success, -EOPNOTSUPP if hardware-wrapped keys are unsupported,
444 * or another -errno code.
445 */
446int keyslot_manager_derive_raw_secret(struct keyslot_manager *ksm,
447 const u8 *wrapped_key,
448 unsigned int wrapped_key_size,
449 u8 *secret, unsigned int secret_size)
450{
451 int err;
452
453 down_write(&ksm->lock);
454 if (ksm->ksm_ll_ops.derive_raw_secret) {
455 err = ksm->ksm_ll_ops.derive_raw_secret(ksm, wrapped_key,
456 wrapped_key_size,
457 secret, secret_size);
458 } else {
459 err = -EOPNOTSUPP;
460 }
461 up_write(&ksm->lock);
462
463 return err;
464}
465EXPORT_SYMBOL_GPL(keyslot_manager_derive_raw_secret);