diff --git a/block/keyslot-manager.c b/block/keyslot-manager.c index 8209db5ab1e1..6841931f1baa 100644 --- a/block/keyslot-manager.c +++ b/block/keyslot-manager.c @@ -66,6 +66,11 @@ struct keyslot_manager { struct keyslot slots[]; }; +static inline bool keyslot_manager_is_passthrough(struct keyslot_manager *ksm) +{ + return ksm->num_slots == 0; +} + /** * keyslot_manager_create() - Create a keyslot manager * @num_slots: The number of key slots to manage. @@ -211,6 +216,9 @@ int keyslot_manager_get_slot_for_key(struct keyslot_manager *ksm, int err; struct keyslot *idle_slot; + if (keyslot_manager_is_passthrough(ksm)) + return 0; + down_read(&ksm->lock); slot = find_and_grab_keyslot(ksm, key); up_read(&ksm->lock); @@ -276,6 +284,9 @@ int keyslot_manager_get_slot_for_key(struct keyslot_manager *ksm, */ void keyslot_manager_get_slot(struct keyslot_manager *ksm, unsigned int slot) { + if (keyslot_manager_is_passthrough(ksm)) + return; + if (WARN_ON(slot >= ksm->num_slots)) return; @@ -293,6 +304,9 @@ void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot) { unsigned long flags; + if (keyslot_manager_is_passthrough(ksm)) + return; + if (WARN_ON(slot >= ksm->num_slots)) return; @@ -352,6 +366,16 @@ int keyslot_manager_evict_key(struct keyslot_manager *ksm, int err; struct keyslot *slotp; + if (keyslot_manager_is_passthrough(ksm)) { + if (ksm->ksm_ll_ops.keyslot_evict) { + down_write(&ksm->lock); + err = ksm->ksm_ll_ops.keyslot_evict(ksm, key, -1); + up_write(&ksm->lock); + return err; + } + return 0; + } + down_write(&ksm->lock); slot = find_keyslot(ksm, key); if (slot < 0) { @@ -389,6 +413,9 @@ void keyslot_manager_reprogram_all_keys(struct keyslot_manager *ksm) { unsigned int slot; + if (WARN_ON(keyslot_manager_is_passthrough(ksm))) + return; + down_write(&ksm->lock); for (slot = 0; slot < ksm->num_slots; slot++) { const struct keyslot *slotp = &ksm->slots[slot]; @@ -426,6 +453,45 @@ void keyslot_manager_destroy(struct keyslot_manager *ksm) } EXPORT_SYMBOL_GPL(keyslot_manager_destroy); +/** + * keyslot_manager_create_passthrough() - Create a passthrough keyslot manager + * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops + * @crypto_mode_supported: Bitmasks for supported encryption modes + * @ll_priv_data: Private data passed as is to the functions in ksm_ll_ops. + * + * Allocate memory for and initialize a passthrough keyslot manager. + * Called by e.g. storage drivers to set up a keyslot manager in their + * request_queue, when the storage driver wants to manage its keys by itself. + * This is useful for inline encryption hardware that don't have a small fixed + * number of keyslots, and for layered devices. + * + * See keyslot_manager_create() for more details about the parameters. + * + * Context: This function may sleep + * Return: Pointer to constructed keyslot manager or NULL on error. + */ +struct keyslot_manager *keyslot_manager_create_passthrough( + const struct keyslot_mgmt_ll_ops *ksm_ll_ops, + const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], + void *ll_priv_data) +{ + struct keyslot_manager *ksm; + + ksm = kzalloc(sizeof(*ksm), GFP_KERNEL); + if (!ksm) + return NULL; + + ksm->ksm_ll_ops = *ksm_ll_ops; + memcpy(ksm->crypto_mode_supported, crypto_mode_supported, + sizeof(ksm->crypto_mode_supported)); + ksm->ll_priv_data = ll_priv_data; + + init_rwsem(&ksm->lock); + + return ksm; +} +EXPORT_SYMBOL_GPL(keyslot_manager_create_passthrough); + /** * keyslot_manager_derive_raw_secret() - Derive software secret from wrapped key * @ksm: The keyslot manager diff --git a/include/linux/keyslot-manager.h b/include/linux/keyslot-manager.h index 17dfcaf208fb..85532baa89b2 100644 --- a/include/linux/keyslot-manager.h +++ b/include/linux/keyslot-manager.h @@ -64,6 +64,11 @@ void *keyslot_manager_private(struct keyslot_manager *ksm); void keyslot_manager_destroy(struct keyslot_manager *ksm); +struct keyslot_manager *keyslot_manager_create_passthrough( + const struct keyslot_mgmt_ll_ops *ksm_ops, + const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], + void *ll_priv_data); + int keyslot_manager_derive_raw_secret(struct keyslot_manager *ksm, const u8 *wrapped_key, unsigned int wrapped_key_size,