1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#define pr_fmt(fmt) "blk-crypto: " fmt
30
31#include <linux/keyslot-manager.h>
32#include <linux/device.h>
33#include <linux/atomic.h>
34#include <linux/mutex.h>
35#include <linux/pm_runtime.h>
36#include <linux/wait.h>
37#include <linux/blkdev.h>
38
39struct blk_ksm_keyslot {
40 atomic_t slot_refs;
41 struct list_head idle_slot_node;
42 struct hlist_node hash_node;
43 const struct blk_crypto_key *key;
44 struct blk_keyslot_manager *ksm;
45};
46
47static inline void blk_ksm_hw_enter(struct blk_keyslot_manager *ksm)
48{
49
50
51
52
53
54 if (ksm->dev)
55 pm_runtime_get_sync(ksm->dev);
56 down_write(&ksm->lock);
57}
58
59static inline void blk_ksm_hw_exit(struct blk_keyslot_manager *ksm)
60{
61 up_write(&ksm->lock);
62 if (ksm->dev)
63 pm_runtime_put_sync(ksm->dev);
64}
65
66static inline bool blk_ksm_is_passthrough(struct blk_keyslot_manager *ksm)
67{
68 return ksm->num_slots == 0;
69}
70
71
72
73
74
75
76
77
78
79
80
81int blk_ksm_init(struct blk_keyslot_manager *ksm, unsigned int num_slots)
82{
83 unsigned int slot;
84 unsigned int i;
85 unsigned int slot_hashtable_size;
86
87 memset(ksm, 0, sizeof(*ksm));
88
89 if (num_slots == 0)
90 return -EINVAL;
91
92 ksm->slots = kvcalloc(num_slots, sizeof(ksm->slots[0]), GFP_KERNEL);
93 if (!ksm->slots)
94 return -ENOMEM;
95
96 ksm->num_slots = num_slots;
97
98 init_rwsem(&ksm->lock);
99
100 init_waitqueue_head(&ksm->idle_slots_wait_queue);
101 INIT_LIST_HEAD(&ksm->idle_slots);
102
103 for (slot = 0; slot < num_slots; slot++) {
104 ksm->slots[slot].ksm = ksm;
105 list_add_tail(&ksm->slots[slot].idle_slot_node,
106 &ksm->idle_slots);
107 }
108
109 spin_lock_init(&ksm->idle_slots_lock);
110
111 slot_hashtable_size = roundup_pow_of_two(num_slots);
112
113
114
115
116 if (slot_hashtable_size < 2)
117 slot_hashtable_size = 2;
118
119 ksm->log_slot_ht_size = ilog2(slot_hashtable_size);
120 ksm->slot_hashtable = kvmalloc_array(slot_hashtable_size,
121 sizeof(ksm->slot_hashtable[0]),
122 GFP_KERNEL);
123 if (!ksm->slot_hashtable)
124 goto err_destroy_ksm;
125 for (i = 0; i < slot_hashtable_size; i++)
126 INIT_HLIST_HEAD(&ksm->slot_hashtable[i]);
127
128 return 0;
129
130err_destroy_ksm:
131 blk_ksm_destroy(ksm);
132 return -ENOMEM;
133}
134EXPORT_SYMBOL_GPL(blk_ksm_init);
135
136static void blk_ksm_destroy_callback(void *ksm)
137{
138 blk_ksm_destroy(ksm);
139}
140
141
142
143
144
145
146
147
148
149
150
151
152int devm_blk_ksm_init(struct device *dev, struct blk_keyslot_manager *ksm,
153 unsigned int num_slots)
154{
155 int err = blk_ksm_init(ksm, num_slots);
156
157 if (err)
158 return err;
159
160 return devm_add_action_or_reset(dev, blk_ksm_destroy_callback, ksm);
161}
162EXPORT_SYMBOL_GPL(devm_blk_ksm_init);
163
164static inline struct hlist_head *
165blk_ksm_hash_bucket_for_key(struct blk_keyslot_manager *ksm,
166 const struct blk_crypto_key *key)
167{
168 return &ksm->slot_hashtable[hash_ptr(key, ksm->log_slot_ht_size)];
169}
170
171static void blk_ksm_remove_slot_from_lru_list(struct blk_ksm_keyslot *slot)
172{
173 struct blk_keyslot_manager *ksm = slot->ksm;
174 unsigned long flags;
175
176 spin_lock_irqsave(&ksm->idle_slots_lock, flags);
177 list_del(&slot->idle_slot_node);
178 spin_unlock_irqrestore(&ksm->idle_slots_lock, flags);
179}
180
181static struct blk_ksm_keyslot *blk_ksm_find_keyslot(
182 struct blk_keyslot_manager *ksm,
183 const struct blk_crypto_key *key)
184{
185 const struct hlist_head *head = blk_ksm_hash_bucket_for_key(ksm, key);
186 struct blk_ksm_keyslot *slotp;
187
188 hlist_for_each_entry(slotp, head, hash_node) {
189 if (slotp->key == key)
190 return slotp;
191 }
192 return NULL;
193}
194
195static struct blk_ksm_keyslot *blk_ksm_find_and_grab_keyslot(
196 struct blk_keyslot_manager *ksm,
197 const struct blk_crypto_key *key)
198{
199 struct blk_ksm_keyslot *slot;
200
201 slot = blk_ksm_find_keyslot(ksm, key);
202 if (!slot)
203 return NULL;
204 if (atomic_inc_return(&slot->slot_refs) == 1) {
205
206 blk_ksm_remove_slot_from_lru_list(slot);
207 }
208 return slot;
209}
210
211unsigned int blk_ksm_get_slot_idx(struct blk_ksm_keyslot *slot)
212{
213 return slot - slot->ksm->slots;
214}
215EXPORT_SYMBOL_GPL(blk_ksm_get_slot_idx);
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233blk_status_t blk_ksm_get_slot_for_key(struct blk_keyslot_manager *ksm,
234 const struct blk_crypto_key *key,
235 struct blk_ksm_keyslot **slot_ptr)
236{
237 struct blk_ksm_keyslot *slot;
238 int slot_idx;
239 int err;
240
241 *slot_ptr = NULL;
242
243 if (blk_ksm_is_passthrough(ksm))
244 return BLK_STS_OK;
245
246 down_read(&ksm->lock);
247 slot = blk_ksm_find_and_grab_keyslot(ksm, key);
248 up_read(&ksm->lock);
249 if (slot)
250 goto success;
251
252 for (;;) {
253 blk_ksm_hw_enter(ksm);
254 slot = blk_ksm_find_and_grab_keyslot(ksm, key);
255 if (slot) {
256 blk_ksm_hw_exit(ksm);
257 goto success;
258 }
259
260
261
262
263
264 if (!list_empty(&ksm->idle_slots))
265 break;
266
267 blk_ksm_hw_exit(ksm);
268 wait_event(ksm->idle_slots_wait_queue,
269 !list_empty(&ksm->idle_slots));
270 }
271
272 slot = list_first_entry(&ksm->idle_slots, struct blk_ksm_keyslot,
273 idle_slot_node);
274 slot_idx = blk_ksm_get_slot_idx(slot);
275
276 err = ksm->ksm_ll_ops.keyslot_program(ksm, key, slot_idx);
277 if (err) {
278 wake_up(&ksm->idle_slots_wait_queue);
279 blk_ksm_hw_exit(ksm);
280 return errno_to_blk_status(err);
281 }
282
283
284 if (slot->key)
285 hlist_del(&slot->hash_node);
286 slot->key = key;
287 hlist_add_head(&slot->hash_node, blk_ksm_hash_bucket_for_key(ksm, key));
288
289 atomic_set(&slot->slot_refs, 1);
290
291 blk_ksm_remove_slot_from_lru_list(slot);
292
293 blk_ksm_hw_exit(ksm);
294success:
295 *slot_ptr = slot;
296 return BLK_STS_OK;
297}
298
299
300
301
302
303
304
305void blk_ksm_put_slot(struct blk_ksm_keyslot *slot)
306{
307 struct blk_keyslot_manager *ksm;
308 unsigned long flags;
309
310 if (!slot)
311 return;
312
313 ksm = slot->ksm;
314
315 if (atomic_dec_and_lock_irqsave(&slot->slot_refs,
316 &ksm->idle_slots_lock, flags)) {
317 list_add_tail(&slot->idle_slot_node, &ksm->idle_slots);
318 spin_unlock_irqrestore(&ksm->idle_slots_lock, flags);
319 wake_up(&ksm->idle_slots_wait_queue);
320 }
321}
322
323
324
325
326
327
328
329
330
331
332
333bool blk_ksm_crypto_cfg_supported(struct blk_keyslot_manager *ksm,
334 const struct blk_crypto_config *cfg)
335{
336 if (!ksm)
337 return false;
338 if (!(ksm->crypto_modes_supported[cfg->crypto_mode] &
339 cfg->data_unit_size))
340 return false;
341 if (ksm->max_dun_bytes_supported < cfg->dun_bytes)
342 return false;
343 return true;
344}
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360int blk_ksm_evict_key(struct blk_keyslot_manager *ksm,
361 const struct blk_crypto_key *key)
362{
363 struct blk_ksm_keyslot *slot;
364 int err = 0;
365
366 if (blk_ksm_is_passthrough(ksm)) {
367 if (ksm->ksm_ll_ops.keyslot_evict) {
368 blk_ksm_hw_enter(ksm);
369 err = ksm->ksm_ll_ops.keyslot_evict(ksm, key, -1);
370 blk_ksm_hw_exit(ksm);
371 return err;
372 }
373 return 0;
374 }
375
376 blk_ksm_hw_enter(ksm);
377 slot = blk_ksm_find_keyslot(ksm, key);
378 if (!slot)
379 goto out_unlock;
380
381 if (WARN_ON_ONCE(atomic_read(&slot->slot_refs) != 0)) {
382 err = -EBUSY;
383 goto out_unlock;
384 }
385 err = ksm->ksm_ll_ops.keyslot_evict(ksm, key,
386 blk_ksm_get_slot_idx(slot));
387 if (err)
388 goto out_unlock;
389
390 hlist_del(&slot->hash_node);
391 slot->key = NULL;
392 err = 0;
393out_unlock:
394 blk_ksm_hw_exit(ksm);
395 return err;
396}
397
398
399
400
401
402
403
404
405
406
407void blk_ksm_reprogram_all_keys(struct blk_keyslot_manager *ksm)
408{
409 unsigned int slot;
410
411 if (blk_ksm_is_passthrough(ksm))
412 return;
413
414
415 down_write(&ksm->lock);
416 for (slot = 0; slot < ksm->num_slots; slot++) {
417 const struct blk_crypto_key *key = ksm->slots[slot].key;
418 int err;
419
420 if (!key)
421 continue;
422
423 err = ksm->ksm_ll_ops.keyslot_program(ksm, key, slot);
424 WARN_ON(err);
425 }
426 up_write(&ksm->lock);
427}
428EXPORT_SYMBOL_GPL(blk_ksm_reprogram_all_keys);
429
430void blk_ksm_destroy(struct blk_keyslot_manager *ksm)
431{
432 if (!ksm)
433 return;
434 kvfree(ksm->slot_hashtable);
435 kvfree_sensitive(ksm->slots, sizeof(ksm->slots[0]) * ksm->num_slots);
436 memzero_explicit(ksm, sizeof(*ksm));
437}
438EXPORT_SYMBOL_GPL(blk_ksm_destroy);
439
440bool blk_ksm_register(struct blk_keyslot_manager *ksm, struct request_queue *q)
441{
442 if (blk_integrity_queue_supports_integrity(q)) {
443 pr_warn("Integrity and hardware inline encryption are not supported together. Disabling hardware inline encryption.\n");
444 return false;
445 }
446 q->ksm = ksm;
447 return true;
448}
449EXPORT_SYMBOL_GPL(blk_ksm_register);
450
451void blk_ksm_unregister(struct request_queue *q)
452{
453 q->ksm = NULL;
454}
455
456
457
458
459
460
461
462
463
464
465
466
467void blk_ksm_intersect_modes(struct blk_keyslot_manager *parent,
468 const struct blk_keyslot_manager *child)
469{
470 if (child) {
471 unsigned int i;
472
473 parent->max_dun_bytes_supported =
474 min(parent->max_dun_bytes_supported,
475 child->max_dun_bytes_supported);
476 for (i = 0; i < ARRAY_SIZE(child->crypto_modes_supported);
477 i++) {
478 parent->crypto_modes_supported[i] &=
479 child->crypto_modes_supported[i];
480 }
481 } else {
482 parent->max_dun_bytes_supported = 0;
483 memset(parent->crypto_modes_supported, 0,
484 sizeof(parent->crypto_modes_supported));
485 }
486}
487EXPORT_SYMBOL_GPL(blk_ksm_intersect_modes);
488
489
490
491
492
493
494
495
496
497
498
499
500
501bool blk_ksm_is_superset(struct blk_keyslot_manager *ksm_superset,
502 struct blk_keyslot_manager *ksm_subset)
503{
504 int i;
505
506 if (!ksm_subset)
507 return true;
508
509 if (!ksm_superset)
510 return false;
511
512 for (i = 0; i < ARRAY_SIZE(ksm_superset->crypto_modes_supported); i++) {
513 if (ksm_subset->crypto_modes_supported[i] &
514 (~ksm_superset->crypto_modes_supported[i])) {
515 return false;
516 }
517 }
518
519 if (ksm_subset->max_dun_bytes_supported >
520 ksm_superset->max_dun_bytes_supported) {
521 return false;
522 }
523
524 return true;
525}
526EXPORT_SYMBOL_GPL(blk_ksm_is_superset);
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551void blk_ksm_update_capabilities(struct blk_keyslot_manager *target_ksm,
552 struct blk_keyslot_manager *reference_ksm)
553{
554 memcpy(target_ksm->crypto_modes_supported,
555 reference_ksm->crypto_modes_supported,
556 sizeof(target_ksm->crypto_modes_supported));
557
558 target_ksm->max_dun_bytes_supported =
559 reference_ksm->max_dun_bytes_supported;
560}
561EXPORT_SYMBOL_GPL(blk_ksm_update_capabilities);
562
563
564
565
566
567
568
569
570
571
572
573void blk_ksm_init_passthrough(struct blk_keyslot_manager *ksm)
574{
575 memset(ksm, 0, sizeof(*ksm));
576 init_rwsem(&ksm->lock);
577}
578EXPORT_SYMBOL_GPL(blk_ksm_init_passthrough);
579