// SPDX-License-Identifier: GPL-2.0 /* * Copyright 2019 Google LLC */ /* * Refer to Documentation/block/inline-encryption.rst for detailed explanation. */ #define pr_fmt(fmt) "blk-crypto: " fmt #include #include #include #include #include #include "blk-crypto-internal.h" const struct blk_crypto_mode blk_crypto_modes[] = { [BLK_ENCRYPTION_MODE_AES_256_XTS] = { .cipher_str = "xts(aes)", .keysize = 64, .ivsize = 16, }, [BLK_ENCRYPTION_MODE_AES_128_CBC_ESSIV] = { .cipher_str = "essiv(cbc(aes),sha256)", .keysize = 16, .ivsize = 16, }, [BLK_ENCRYPTION_MODE_ADIANTUM] = { .cipher_str = "adiantum(xchacha12,aes)", .keysize = 32, .ivsize = 32, }, }; /* Check that all I/O segments are data unit aligned */ static int bio_crypt_check_alignment(struct bio *bio) { const unsigned int data_unit_size = bio->bi_crypt_context->bc_key->data_unit_size; struct bvec_iter iter; struct bio_vec bv; bio_for_each_segment(bv, bio, iter) { if (!IS_ALIGNED(bv.bv_len | bv.bv_offset, data_unit_size)) return -EIO; } return 0; } /** * blk_crypto_submit_bio - handle submitting bio for inline encryption * * @bio_ptr: pointer to original bio pointer * * If the bio doesn't have inline encryption enabled or the submitter already * specified a keyslot for the target device, do nothing. Else, a raw key must * have been provided, so acquire a device keyslot for it if supported. Else, * use the crypto API fallback. * * When the crypto API fallback is used for encryption, blk-crypto may choose to * split the bio into 2 - the first one that will continue to be processed and * the second one that will be resubmitted via generic_make_request. * A bounce bio will be allocated to encrypt the contents of the aforementioned * "first one", and *bio_ptr will be updated to this bounce bio. * * Return: 0 if bio submission should continue; nonzero if bio_endio() was * already called so bio submission should abort. */ int blk_crypto_submit_bio(struct bio **bio_ptr) { struct bio *bio = *bio_ptr; struct request_queue *q; struct bio_crypt_ctx *bc = bio->bi_crypt_context; int err; if (!bc || !bio_has_data(bio)) return 0; /* * When a read bio is marked for fallback decryption, its bi_iter is * saved so that when we decrypt the bio later, we know what part of it * was marked for fallback decryption (when the bio is passed down after * blk_crypto_submit bio, it may be split or advanced so we cannot rely * on the bi_iter while decrypting in blk_crypto_endio) */ if (bio_crypt_fallback_crypted(bc)) return 0; err = bio_crypt_check_alignment(bio); if (err) { bio->bi_status = BLK_STS_IOERR; goto out; } q = bio->bi_disk->queue; if (bc->bc_ksm) { /* Key already programmed into device? */ if (q->ksm == bc->bc_ksm) return 0; /* Nope, release the existing keyslot. */ bio_crypt_ctx_release_keyslot(bc); } /* Get device keyslot if supported */ if (keyslot_manager_crypto_mode_supported(q->ksm, bc->bc_key->crypto_mode, blk_crypto_key_dun_bytes(bc->bc_key), bc->bc_key->data_unit_size, bc->bc_key->is_hw_wrapped)) { err = bio_crypt_ctx_acquire_keyslot(bc, q->ksm); if (!err) return 0; pr_warn_once("Failed to acquire keyslot for %s (err=%d). Falling back to crypto API.\n", bio->bi_disk->disk_name, err); } /* Fallback to crypto API */ err = blk_crypto_fallback_submit_bio(bio_ptr); if (err) goto out; return 0; out: bio_endio(*bio_ptr); return err; } /** * blk_crypto_endio - clean up bio w.r.t inline encryption during bio_endio * * @bio: the bio to clean up * * If blk_crypto_submit_bio decided to fallback to crypto API for this bio, * we queue the bio for decryption into a workqueue and return false, * and call bio_endio(bio) at a later time (after the bio has been decrypted). * * If the bio is not to be decrypted by the crypto API, this function releases * the reference to the keyslot that blk_crypto_submit_bio got. * * Return: true if bio_endio should continue; false otherwise (bio_endio will * be called again when bio has been decrypted). */ bool blk_crypto_endio(struct bio *bio) { struct bio_crypt_ctx *bc = bio->bi_crypt_context; if (!bc) return true; if (bio_crypt_fallback_crypted(bc)) { /* * The only bios who's crypto is handled by the blk-crypto * fallback when they reach here are those with * bio_data_dir(bio) == READ, since WRITE bios that are * encrypted by the crypto API fallback are handled by * blk_crypto_encrypt_endio(). */ return !blk_crypto_queue_decrypt_bio(bio); } if (bc->bc_keyslot >= 0) bio_crypt_ctx_release_keyslot(bc); return true; } /** * blk_crypto_init_key() - Prepare a key for use with blk-crypto * @blk_key: Pointer to the blk_crypto_key to initialize. * @raw_key: Pointer to the raw key. * @raw_key_size: Size of raw key. Must be at least the required size for the * chosen @crypto_mode; see blk_crypto_modes[]. (It's allowed * to be longer than the mode's actual key size, in order to * support inline encryption hardware that accepts wrapped keys. * @is_hw_wrapped has to be set for such keys) * @is_hw_wrapped: Denotes @raw_key is wrapped. * @crypto_mode: identifier for the encryption algorithm to use * @dun_bytes: number of bytes that will be used to specify the DUN when this * key is used * @data_unit_size: the data unit size to use for en/decryption * * Return: The blk_crypto_key that was prepared, or an ERR_PTR() on error. When * done using the key, it must be freed with blk_crypto_free_key(). */ int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key, unsigned int raw_key_size, bool is_hw_wrapped, enum blk_crypto_mode_num crypto_mode, unsigned int dun_bytes, unsigned int data_unit_size) { const struct blk_crypto_mode *mode; static siphash_key_t hash_key; u32 hash; memset(blk_key, 0, sizeof(*blk_key)); if (crypto_mode >= ARRAY_SIZE(blk_crypto_modes)) return -EINVAL; BUILD_BUG_ON(BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE < BLK_CRYPTO_MAX_KEY_SIZE); mode = &blk_crypto_modes[crypto_mode]; if (is_hw_wrapped) { if (raw_key_size < mode->keysize || raw_key_size > BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE) return -EINVAL; } else { if (raw_key_size != mode->keysize) return -EINVAL; } if (dun_bytes <= 0 || dun_bytes > BLK_CRYPTO_MAX_IV_SIZE) return -EINVAL; if (!is_power_of_2(data_unit_size)) return -EINVAL; blk_key->crypto_mode = crypto_mode; blk_key->data_unit_size = data_unit_size; blk_key->data_unit_size_bits = ilog2(data_unit_size); blk_key->size = raw_key_size; blk_key->is_hw_wrapped = is_hw_wrapped; memcpy(blk_key->raw, raw_key, raw_key_size); /* * The keyslot manager uses the SipHash of the key to implement O(1) key * lookups while avoiding leaking information about the keys. It's * precomputed here so that it only needs to be computed once per key. */ get_random_once(&hash_key, sizeof(hash_key)); hash = (u32)siphash(raw_key, raw_key_size, &hash_key); blk_crypto_key_set_hash_and_dun_bytes(blk_key, hash, dun_bytes); return 0; } EXPORT_SYMBOL_GPL(blk_crypto_init_key); /** * blk_crypto_start_using_mode() - Start using blk-crypto on a device * @crypto_mode: the crypto mode that will be used * @dun_bytes: number of bytes that will be used to specify the DUN * @data_unit_size: the data unit size that will be used * @is_hw_wrapped_key: whether the key will be hardware-wrapped * @q: the request queue for the device * * Upper layers must call this function to ensure that either the hardware * supports the needed crypto settings, or the crypto API fallback has * transforms for the needed mode allocated and ready to go. * * Return: 0 on success; -ENOPKG if the hardware doesn't support the crypto * settings and blk-crypto-fallback is either disabled or the needed * algorithm is disabled in the crypto API; or another -errno code. */ int blk_crypto_start_using_mode(enum blk_crypto_mode_num crypto_mode, unsigned int dun_bytes, unsigned int data_unit_size, bool is_hw_wrapped_key, struct request_queue *q) { if (keyslot_manager_crypto_mode_supported(q->ksm, crypto_mode, dun_bytes, data_unit_size, is_hw_wrapped_key)) return 0; if (is_hw_wrapped_key) { pr_warn_once("hardware doesn't support wrapped keys\n"); return -EOPNOTSUPP; } return blk_crypto_fallback_start_using_mode(crypto_mode); } EXPORT_SYMBOL_GPL(blk_crypto_start_using_mode); /** * blk_crypto_evict_key() - Evict a key from any inline encryption hardware * it may have been programmed into * @q: The request queue who's keyslot manager this key might have been * programmed into * @key: The key to evict * * Upper layers (filesystems) should call this function to ensure that a key * is evicted from hardware that it might have been programmed into. This * will call keyslot_manager_evict_key on the queue's keyslot manager, if one * exists, and supports the crypto algorithm with the specified data unit size. * Otherwise, it will evict the key from the blk-crypto-fallback's ksm. * * Return: 0 on success, -err on error. */ int blk_crypto_evict_key(struct request_queue *q, const struct blk_crypto_key *key) { if (q->ksm && keyslot_manager_crypto_mode_supported(q->ksm, key->crypto_mode, blk_crypto_key_dun_bytes(key), key->data_unit_size, key->is_hw_wrapped)) return keyslot_manager_evict_key(q->ksm, key); return blk_crypto_fallback_evict_key(key); } EXPORT_SYMBOL_GPL(blk_crypto_evict_key);