blob: 6841931f1baac74230fec0a449cb3a3e5e433234 [file] [log] [blame]
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -07001// SPDX-License-Identifier: GPL-2.0
2/*
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -07003 * 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 */
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -080028#include <crypto/algapi.h>
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -070029#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;
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -080038 struct hlist_node hash_node;
39 struct blk_crypto_key key;
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -070040};
41
42struct keyslot_manager {
43 unsigned int num_slots;
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -070044 struct keyslot_mgmt_ll_ops ksm_ll_ops;
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -080045 unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX];
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -070046 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
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -080056 /*
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
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -070065 /* Per-keyslot data */
66 struct keyslot slots[];
67};
68
Satya Tangiralac7da3f42020-01-21 09:27:43 -080069static inline bool keyslot_manager_is_passthrough(struct keyslot_manager *ksm)
70{
71 return ksm->num_slots == 0;
72}
73
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -070074/**
75 * keyslot_manager_create() - Create a keyslot manager
76 * @num_slots: The number of key slots to manage.
77 * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops for the device that this keyslot
78 * manager will use to perform operations like programming and
79 * evicting keys.
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -080080 * @crypto_mode_supported: Array of size BLK_ENCRYPTION_MODE_MAX of
81 * bitmasks that represents whether a crypto mode
82 * and data unit size are supported. The i'th bit
83 * of crypto_mode_supported[crypto_mode] is set iff
84 * a data unit size of (1 << i) is supported. We
85 * only support data unit sizes that are powers of
86 * 2.
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -070087 * @ll_priv_data: Private data passed as is to the functions in ksm_ll_ops.
88 *
89 * Allocate memory for and initialize a keyslot manager. Called by e.g.
90 * storage drivers to set up a keyslot manager in their request_queue.
91 *
92 * Context: May sleep
93 * Return: Pointer to constructed keyslot manager or NULL on error.
94 */
95struct keyslot_manager *keyslot_manager_create(unsigned int num_slots,
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -080096 const struct keyslot_mgmt_ll_ops *ksm_ll_ops,
97 const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
98 void *ll_priv_data)
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -070099{
100 struct keyslot_manager *ksm;
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800101 unsigned int slot;
102 unsigned int i;
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700103
104 if (num_slots == 0)
105 return NULL;
106
107 /* Check that all ops are specified */
108 if (ksm_ll_ops->keyslot_program == NULL ||
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800109 ksm_ll_ops->keyslot_evict == NULL)
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700110 return NULL;
111
112 ksm = kvzalloc(struct_size(ksm, slots, num_slots), GFP_KERNEL);
113 if (!ksm)
114 return NULL;
115
116 ksm->num_slots = num_slots;
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700117 ksm->ksm_ll_ops = *ksm_ll_ops;
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800118 memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
119 sizeof(ksm->crypto_mode_supported));
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700120 ksm->ll_priv_data = ll_priv_data;
121
122 init_rwsem(&ksm->lock);
123
124 init_waitqueue_head(&ksm->idle_slots_wait_queue);
125 INIT_LIST_HEAD(&ksm->idle_slots);
126
127 for (slot = 0; slot < num_slots; slot++) {
128 list_add_tail(&ksm->slots[slot].idle_slot_node,
129 &ksm->idle_slots);
130 }
131
132 spin_lock_init(&ksm->idle_slots_lock);
133
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800134 ksm->slot_hashtable_size = roundup_pow_of_two(num_slots);
135 ksm->slot_hashtable = kvmalloc_array(ksm->slot_hashtable_size,
136 sizeof(ksm->slot_hashtable[0]),
137 GFP_KERNEL);
138 if (!ksm->slot_hashtable)
139 goto err_free_ksm;
140 for (i = 0; i < ksm->slot_hashtable_size; i++)
141 INIT_HLIST_HEAD(&ksm->slot_hashtable[i]);
142
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700143 return ksm;
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800144
145err_free_ksm:
146 keyslot_manager_destroy(ksm);
147 return NULL;
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700148}
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800149EXPORT_SYMBOL_GPL(keyslot_manager_create);
150
151static inline struct hlist_head *
152hash_bucket_for_key(struct keyslot_manager *ksm,
153 const struct blk_crypto_key *key)
154{
155 return &ksm->slot_hashtable[key->hash & (ksm->slot_hashtable_size - 1)];
156}
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700157
158static void remove_slot_from_lru_list(struct keyslot_manager *ksm, int slot)
159{
160 unsigned long flags;
161
162 spin_lock_irqsave(&ksm->idle_slots_lock, flags);
163 list_del(&ksm->slots[slot].idle_slot_node);
164 spin_unlock_irqrestore(&ksm->idle_slots_lock, flags);
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700165}
166
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800167static int find_keyslot(struct keyslot_manager *ksm,
168 const struct blk_crypto_key *key)
169{
170 const struct hlist_head *head = hash_bucket_for_key(ksm, key);
171 const struct keyslot *slotp;
172
173 hlist_for_each_entry(slotp, head, hash_node) {
174 if (slotp->key.hash == key->hash &&
175 slotp->key.crypto_mode == key->crypto_mode &&
Barani Muthukumarand7394742020-01-02 11:57:39 -0800176 slotp->key.size == key->size &&
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800177 slotp->key.data_unit_size == key->data_unit_size &&
178 !crypto_memneq(slotp->key.raw, key->raw, key->size))
179 return slotp - ksm->slots;
180 }
181 return -ENOKEY;
182}
183
184static int find_and_grab_keyslot(struct keyslot_manager *ksm,
185 const struct blk_crypto_key *key)
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700186{
187 int slot;
188
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800189 slot = find_keyslot(ksm, key);
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700190 if (slot < 0)
191 return slot;
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700192 if (atomic_inc_return(&ksm->slots[slot].slot_refs) == 1) {
193 /* Took first reference to this slot; remove it from LRU list */
194 remove_slot_from_lru_list(ksm, slot);
195 }
196 return slot;
197}
198
199/**
200 * keyslot_manager_get_slot_for_key() - Program a key into a keyslot.
201 * @ksm: The keyslot manager to program the key into.
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800202 * @key: Pointer to the key object to program, including the raw key, crypto
203 * mode, and data unit size.
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700204 *
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800205 * Get a keyslot that's been programmed with the specified key. If one already
206 * exists, return it with incremented refcount. Otherwise, wait for a keyslot
207 * to become idle and program it.
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700208 *
209 * Context: Process context. Takes and releases ksm->lock.
210 * Return: The keyslot on success, else a -errno value.
211 */
212int keyslot_manager_get_slot_for_key(struct keyslot_manager *ksm,
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800213 const struct blk_crypto_key *key)
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700214{
215 int slot;
216 int err;
217 struct keyslot *idle_slot;
218
Satya Tangiralac7da3f42020-01-21 09:27:43 -0800219 if (keyslot_manager_is_passthrough(ksm))
220 return 0;
221
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700222 down_read(&ksm->lock);
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800223 slot = find_and_grab_keyslot(ksm, key);
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700224 up_read(&ksm->lock);
225 if (slot != -ENOKEY)
226 return slot;
227
228 for (;;) {
229 down_write(&ksm->lock);
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800230 slot = find_and_grab_keyslot(ksm, key);
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700231 if (slot != -ENOKEY) {
232 up_write(&ksm->lock);
233 return slot;
234 }
235
236 /*
237 * If we're here, that means there wasn't a slot that was
238 * already programmed with the key. So try to program it.
239 */
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800240 if (!list_empty(&ksm->idle_slots))
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700241 break;
242
243 up_write(&ksm->lock);
244 wait_event(ksm->idle_slots_wait_queue,
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800245 !list_empty(&ksm->idle_slots));
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700246 }
247
248 idle_slot = list_first_entry(&ksm->idle_slots, struct keyslot,
249 idle_slot_node);
250 slot = idle_slot - ksm->slots;
251
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800252 err = ksm->ksm_ll_ops.keyslot_program(ksm, key, slot);
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700253 if (err) {
254 wake_up(&ksm->idle_slots_wait_queue);
255 up_write(&ksm->lock);
256 return err;
257 }
258
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800259 /* Move this slot to the hash list for the new key. */
260 if (idle_slot->key.crypto_mode != BLK_ENCRYPTION_MODE_INVALID)
261 hlist_del(&idle_slot->hash_node);
262 hlist_add_head(&idle_slot->hash_node, hash_bucket_for_key(ksm, key));
263
264 atomic_set(&idle_slot->slot_refs, 1);
265 idle_slot->key = *key;
266
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700267 remove_slot_from_lru_list(ksm, slot);
268
269 up_write(&ksm->lock);
270 return slot;
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700271}
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700272
273/**
274 * keyslot_manager_get_slot() - Increment the refcount on the specified slot.
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800275 * @ksm: The keyslot manager that we want to modify.
276 * @slot: The slot to increment the refcount of.
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700277 *
278 * This function assumes that there is already an active reference to that slot
279 * and simply increments the refcount. This is useful when cloning a bio that
280 * already has a reference to a keyslot, and we want the cloned bio to also have
281 * its own reference.
282 *
283 * Context: Any context.
284 */
285void keyslot_manager_get_slot(struct keyslot_manager *ksm, unsigned int slot)
286{
Satya Tangiralac7da3f42020-01-21 09:27:43 -0800287 if (keyslot_manager_is_passthrough(ksm))
288 return;
289
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700290 if (WARN_ON(slot >= ksm->num_slots))
291 return;
292
293 WARN_ON(atomic_inc_return(&ksm->slots[slot].slot_refs) < 2);
294}
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700295
296/**
297 * keyslot_manager_put_slot() - Release a reference to a slot
298 * @ksm: The keyslot manager to release the reference from.
299 * @slot: The slot to release the reference from.
300 *
301 * Context: Any context.
302 */
303void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot)
304{
305 unsigned long flags;
306
Satya Tangiralac7da3f42020-01-21 09:27:43 -0800307 if (keyslot_manager_is_passthrough(ksm))
308 return;
309
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700310 if (WARN_ON(slot >= ksm->num_slots))
311 return;
312
313 if (atomic_dec_and_lock_irqsave(&ksm->slots[slot].slot_refs,
314 &ksm->idle_slots_lock, flags)) {
315 list_add_tail(&ksm->slots[slot].idle_slot_node,
316 &ksm->idle_slots);
317 spin_unlock_irqrestore(&ksm->idle_slots_lock, flags);
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700318 wake_up(&ksm->idle_slots_wait_queue);
319 }
320}
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700321
322/**
323 * keyslot_manager_crypto_mode_supported() - Find out if a crypto_mode/data
324 * unit size combination is supported
325 * by a ksm.
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800326 * @ksm: The keyslot manager to check
327 * @crypto_mode: The crypto mode to check for.
328 * @data_unit_size: The data_unit_size for the mode.
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700329 *
330 * Calls and returns the result of the crypto_mode_supported function specified
331 * by the ksm.
332 *
333 * Context: Process context.
334 * Return: Whether or not this ksm supports the specified crypto_mode/
335 * data_unit_size combo.
336 */
337bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
338 enum blk_crypto_mode_num crypto_mode,
339 unsigned int data_unit_size)
340{
341 if (!ksm)
342 return false;
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800343 if (WARN_ON(crypto_mode >= BLK_ENCRYPTION_MODE_MAX))
344 return false;
345 if (WARN_ON(!is_power_of_2(data_unit_size)))
346 return false;
347 return ksm->crypto_mode_supported[crypto_mode] & data_unit_size;
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700348}
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700349
350/**
351 * keyslot_manager_evict_key() - Evict a key from the lower layer device.
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800352 * @ksm: The keyslot manager to evict from
353 * @key: The key to evict
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700354 *
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800355 * Find the keyslot that the specified key was programmed into, and evict that
356 * slot from the lower layer device if that slot is not currently in use.
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700357 *
358 * Context: Process context. Takes and releases ksm->lock.
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800359 * Return: 0 on success, -EBUSY if the key is still in use, or another
360 * -errno value on other error.
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700361 */
362int keyslot_manager_evict_key(struct keyslot_manager *ksm,
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800363 const struct blk_crypto_key *key)
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700364{
365 int slot;
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800366 int err;
367 struct keyslot *slotp;
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700368
Satya Tangiralac7da3f42020-01-21 09:27:43 -0800369 if (keyslot_manager_is_passthrough(ksm)) {
370 if (ksm->ksm_ll_ops.keyslot_evict) {
371 down_write(&ksm->lock);
372 err = ksm->ksm_ll_ops.keyslot_evict(ksm, key, -1);
373 up_write(&ksm->lock);
374 return err;
375 }
376 return 0;
377 }
378
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700379 down_write(&ksm->lock);
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800380 slot = find_keyslot(ksm, key);
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700381 if (slot < 0) {
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800382 err = slot;
383 goto out_unlock;
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700384 }
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800385 slotp = &ksm->slots[slot];
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700386
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800387 if (atomic_read(&slotp->slot_refs) != 0) {
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700388 err = -EBUSY;
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800389 goto out_unlock;
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700390 }
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800391 err = ksm->ksm_ll_ops.keyslot_evict(ksm, key, slot);
392 if (err)
393 goto out_unlock;
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700394
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800395 hlist_del(&slotp->hash_node);
396 memzero_explicit(&slotp->key, sizeof(slotp->key));
397 err = 0;
398out_unlock:
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700399 up_write(&ksm->lock);
400 return err;
401}
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800402
403/**
404 * keyslot_manager_reprogram_all_keys() - Re-program all keyslots.
405 * @ksm: The keyslot manager
406 *
407 * Re-program all keyslots that are supposed to have a key programmed. This is
408 * intended only for use by drivers for hardware that loses its keys on reset.
409 *
410 * Context: Process context. Takes and releases ksm->lock.
411 */
412void keyslot_manager_reprogram_all_keys(struct keyslot_manager *ksm)
413{
414 unsigned int slot;
415
Satya Tangiralac7da3f42020-01-21 09:27:43 -0800416 if (WARN_ON(keyslot_manager_is_passthrough(ksm)))
417 return;
418
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800419 down_write(&ksm->lock);
420 for (slot = 0; slot < ksm->num_slots; slot++) {
421 const struct keyslot *slotp = &ksm->slots[slot];
422 int err;
423
424 if (slotp->key.crypto_mode == BLK_ENCRYPTION_MODE_INVALID)
425 continue;
426
427 err = ksm->ksm_ll_ops.keyslot_program(ksm, &slotp->key, slot);
428 WARN_ON(err);
429 }
430 up_write(&ksm->lock);
431}
432EXPORT_SYMBOL_GPL(keyslot_manager_reprogram_all_keys);
433
434/**
435 * keyslot_manager_private() - return the private data stored with ksm
436 * @ksm: The keyslot manager
437 *
438 * Returns the private data passed to the ksm when it was created.
439 */
440void *keyslot_manager_private(struct keyslot_manager *ksm)
441{
442 return ksm->ll_priv_data;
443}
444EXPORT_SYMBOL_GPL(keyslot_manager_private);
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700445
446void keyslot_manager_destroy(struct keyslot_manager *ksm)
447{
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800448 if (ksm) {
449 kvfree(ksm->slot_hashtable);
450 memzero_explicit(ksm, struct_size(ksm, slots, ksm->num_slots));
451 kvfree(ksm);
452 }
Satya Tangiralaaac6c3d2019-10-24 14:44:23 -0700453}
Satya Tangiralacfd7e6c2019-12-17 14:26:29 -0800454EXPORT_SYMBOL_GPL(keyslot_manager_destroy);
Barani Muthukumaran1daa0582020-01-02 12:01:34 -0800455
456/**
Satya Tangiralac7da3f42020-01-21 09:27:43 -0800457 * keyslot_manager_create_passthrough() - Create a passthrough keyslot manager
458 * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops
459 * @crypto_mode_supported: Bitmasks for supported encryption modes
460 * @ll_priv_data: Private data passed as is to the functions in ksm_ll_ops.
461 *
462 * Allocate memory for and initialize a passthrough keyslot manager.
463 * Called by e.g. storage drivers to set up a keyslot manager in their
464 * request_queue, when the storage driver wants to manage its keys by itself.
465 * This is useful for inline encryption hardware that don't have a small fixed
466 * number of keyslots, and for layered devices.
467 *
468 * See keyslot_manager_create() for more details about the parameters.
469 *
470 * Context: This function may sleep
471 * Return: Pointer to constructed keyslot manager or NULL on error.
472 */
473struct keyslot_manager *keyslot_manager_create_passthrough(
474 const struct keyslot_mgmt_ll_ops *ksm_ll_ops,
475 const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
476 void *ll_priv_data)
477{
478 struct keyslot_manager *ksm;
479
480 ksm = kzalloc(sizeof(*ksm), GFP_KERNEL);
481 if (!ksm)
482 return NULL;
483
484 ksm->ksm_ll_ops = *ksm_ll_ops;
485 memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
486 sizeof(ksm->crypto_mode_supported));
487 ksm->ll_priv_data = ll_priv_data;
488
489 init_rwsem(&ksm->lock);
490
491 return ksm;
492}
493EXPORT_SYMBOL_GPL(keyslot_manager_create_passthrough);
494
495/**
Barani Muthukumaran1daa0582020-01-02 12:01:34 -0800496 * keyslot_manager_derive_raw_secret() - Derive software secret from wrapped key
497 * @ksm: The keyslot manager
498 * @wrapped_key: The wrapped key
499 * @wrapped_key_size: Size of the wrapped key in bytes
500 * @secret: (output) the software secret
501 * @secret_size: (output) the number of secret bytes to derive
502 *
503 * Given a hardware-wrapped key, ask the hardware to derive a secret which
504 * software can use for cryptographic tasks other than inline encryption. The
505 * derived secret is guaranteed to be cryptographically isolated from the key
506 * with which any inline encryption with this wrapped key would actually be
507 * done. I.e., both will be derived from the unwrapped key.
508 *
509 * Return: 0 on success, -EOPNOTSUPP if hardware-wrapped keys are unsupported,
510 * or another -errno code.
511 */
512int keyslot_manager_derive_raw_secret(struct keyslot_manager *ksm,
513 const u8 *wrapped_key,
514 unsigned int wrapped_key_size,
515 u8 *secret, unsigned int secret_size)
516{
517 int err;
518
519 down_write(&ksm->lock);
520 if (ksm->ksm_ll_ops.derive_raw_secret) {
521 err = ksm->ksm_ll_ops.derive_raw_secret(ksm, wrapped_key,
522 wrapped_key_size,
523 secret, secret_size);
524 } else {
525 err = -EOPNOTSUPP;
526 }
527 up_write(&ksm->lock);
528
529 return err;
530}
531EXPORT_SYMBOL_GPL(keyslot_manager_derive_raw_secret);