| /* SPDX-License-Identifier: GPL-2.0 */ |
| /* |
| * Copyright 2019 Google LLC |
| */ |
| #ifndef __LINUX_BIO_CRYPT_CTX_H |
| #define __LINUX_BIO_CRYPT_CTX_H |
| |
| enum blk_crypto_mode_num { |
| BLK_ENCRYPTION_MODE_INVALID = 0, |
| BLK_ENCRYPTION_MODE_AES_256_XTS = 1, |
| }; |
| |
| #ifdef CONFIG_BLOCK |
| #include <linux/blk_types.h> |
| |
| #ifdef CONFIG_BLK_INLINE_ENCRYPTION |
| struct bio_crypt_ctx { |
| int keyslot; |
| const u8 *raw_key; |
| enum blk_crypto_mode_num crypto_mode; |
| u64 data_unit_num; |
| unsigned int data_unit_size_bits; |
| |
| /* |
| * The keyslot manager where the key has been programmed |
| * with keyslot. |
| */ |
| struct keyslot_manager *processing_ksm; |
| |
| /* |
| * Copy of the bvec_iter when this bio was submitted. |
| * We only want to en/decrypt the part of the bio |
| * as described by the bvec_iter upon submission because |
| * bio might be split before being resubmitted |
| */ |
| struct bvec_iter crypt_iter; |
| u64 sw_data_unit_num; |
| }; |
| |
| extern int bio_crypt_clone(struct bio *dst, struct bio *src, |
| gfp_t gfp_mask); |
| |
| static inline bool bio_has_crypt_ctx(struct bio *bio) |
| { |
| return bio->bi_crypt_context; |
| } |
| |
| static inline void bio_crypt_advance(struct bio *bio, unsigned int bytes) |
| { |
| if (bio_has_crypt_ctx(bio)) { |
| bio->bi_crypt_context->data_unit_num += |
| bytes >> bio->bi_crypt_context->data_unit_size_bits; |
| } |
| } |
| |
| extern bool bio_crypt_swhandled(struct bio *bio); |
| |
| static inline bool bio_crypt_has_keyslot(struct bio *bio) |
| { |
| return bio->bi_crypt_context->keyslot >= 0; |
| } |
| |
| extern int bio_crypt_ctx_init(void); |
| |
| extern struct bio_crypt_ctx *bio_crypt_alloc_ctx(gfp_t gfp_mask); |
| |
| extern void bio_crypt_free_ctx(struct bio *bio); |
| |
| static inline int bio_crypt_set_ctx(struct bio *bio, |
| const u8 *raw_key, |
| enum blk_crypto_mode_num crypto_mode, |
| u64 dun, |
| unsigned int dun_bits, |
| gfp_t gfp_mask) |
| { |
| struct bio_crypt_ctx *crypt_ctx; |
| |
| crypt_ctx = bio_crypt_alloc_ctx(gfp_mask); |
| if (!crypt_ctx) |
| return -ENOMEM; |
| |
| crypt_ctx->raw_key = raw_key; |
| crypt_ctx->data_unit_num = dun; |
| crypt_ctx->data_unit_size_bits = dun_bits; |
| crypt_ctx->crypto_mode = crypto_mode; |
| crypt_ctx->processing_ksm = NULL; |
| crypt_ctx->keyslot = -1; |
| bio->bi_crypt_context = crypt_ctx; |
| |
| return 0; |
| } |
| |
| static inline void bio_set_data_unit_num(struct bio *bio, u64 dun) |
| { |
| bio->bi_crypt_context->data_unit_num = dun; |
| } |
| |
| static inline int bio_crypt_get_keyslot(struct bio *bio) |
| { |
| return bio->bi_crypt_context->keyslot; |
| } |
| |
| static inline void bio_crypt_set_keyslot(struct bio *bio, |
| unsigned int keyslot, |
| struct keyslot_manager *ksm) |
| { |
| bio->bi_crypt_context->keyslot = keyslot; |
| bio->bi_crypt_context->processing_ksm = ksm; |
| } |
| |
| extern void bio_crypt_ctx_release_keyslot(struct bio *bio); |
| |
| extern int bio_crypt_ctx_acquire_keyslot(struct bio *bio, |
| struct keyslot_manager *ksm); |
| |
| static inline const u8 *bio_crypt_raw_key(struct bio *bio) |
| { |
| return bio->bi_crypt_context->raw_key; |
| } |
| |
| static inline enum blk_crypto_mode_num bio_crypto_mode(struct bio *bio) |
| { |
| return bio->bi_crypt_context->crypto_mode; |
| } |
| |
| static inline u64 bio_crypt_data_unit_num(struct bio *bio) |
| { |
| return bio->bi_crypt_context->data_unit_num; |
| } |
| |
| static inline u64 bio_crypt_sw_data_unit_num(struct bio *bio) |
| { |
| return bio->bi_crypt_context->sw_data_unit_num; |
| } |
| |
| extern bool bio_crypt_should_process(struct bio *bio, struct request_queue *q); |
| |
| extern bool bio_crypt_ctx_compatible(struct bio *b_1, struct bio *b_2); |
| |
| extern bool bio_crypt_ctx_back_mergeable(struct bio *b_1, |
| unsigned int b1_sectors, |
| struct bio *b_2); |
| |
| #else /* CONFIG_BLK_INLINE_ENCRYPTION */ |
| struct keyslot_manager; |
| |
| static inline int bio_crypt_ctx_init(void) |
| { |
| return 0; |
| } |
| |
| static inline int bio_crypt_clone(struct bio *dst, struct bio *src, |
| gfp_t gfp_mask) |
| { |
| return 0; |
| } |
| |
| static inline void bio_crypt_advance(struct bio *bio, |
| unsigned int bytes) { } |
| |
| static inline bool bio_has_crypt_ctx(struct bio *bio) |
| { |
| return false; |
| } |
| |
| static inline void bio_crypt_free_ctx(struct bio *bio) { } |
| |
| static inline void bio_crypt_set_ctx(struct bio *bio, |
| u8 *raw_key, |
| enum blk_crypto_mode_num crypto_mode, |
| u64 dun, |
| unsigned int dun_bits, |
| gfp_t gfp_mask) { } |
| |
| static inline bool bio_crypt_swhandled(struct bio *bio) |
| { |
| return false; |
| } |
| |
| static inline void bio_set_data_unit_num(struct bio *bio, u64 dun) { } |
| |
| static inline bool bio_crypt_has_keyslot(struct bio *bio) |
| { |
| return false; |
| } |
| |
| static inline void bio_crypt_set_keyslot(struct bio *bio, |
| unsigned int keyslot, |
| struct keyslot_manager *ksm) { } |
| |
| static inline int bio_crypt_get_keyslot(struct bio *bio) |
| { |
| return -1; |
| } |
| |
| static inline u8 *bio_crypt_raw_key(struct bio *bio) |
| { |
| return NULL; |
| } |
| |
| static inline u64 bio_crypt_data_unit_num(struct bio *bio) |
| { |
| return 0; |
| } |
| |
| static inline bool bio_crypt_should_process(struct bio *bio, |
| struct request_queue *q) |
| { |
| return false; |
| } |
| |
| static inline bool bio_crypt_ctx_compatible(struct bio *b_1, struct bio *b_2) |
| { |
| return true; |
| } |
| |
| static inline bool bio_crypt_ctx_back_mergeable(struct bio *b_1, |
| unsigned int b1_sectors, |
| struct bio *b_2) |
| { |
| return true; |
| } |
| |
| #endif /* CONFIG_BLK_INLINE_ENCRYPTION */ |
| #endif /* CONFIG_BLOCK */ |
| #endif /* __LINUX_BIO_CRYPT_CTX_H */ |