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