| /* SPDX-License-Identifier: GPL-2.0-or-later */ |
| /* |
| * Copyright (C) 2017 Samsung Electronics Co., Ltd. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| */ |
| |
| #ifndef _DISKCIPHER_H_ |
| #define _DISKCIPHER_H_ |
| |
| #include <linux/crypto.h> |
| #include <linux/blk_types.h> |
| |
| struct diskcipher_alg; |
| |
| enum iv_mode { |
| IV_MODE_LBA, /* dm-dcrypt/ext4 uses it for more blk merge */ |
| IV_MODE_DUN, /* f2fs should use it for garbeage colloection */ |
| }; |
| |
| struct crypto_diskcipher { |
| u32 algo; |
| unsigned int ivsize; |
| struct inode *inode; |
| /* for crypto_free_req_diskcipher */ |
| atomic_t status; |
| struct crypto_tfm base; |
| enum iv_mode ivmode; |
| }; |
| |
| struct diskcipher_test_request { |
| unsigned int cryptlen; |
| const u8 *iv; |
| struct scatterlist *src; |
| struct scatterlist *dst; |
| bool enc; |
| }; |
| |
| /** |
| * struct diskcipher_alg - disk cipher definition |
| * for inline crypto engine on disk host device |
| * |
| * @setkey |
| * @clearkey |
| * @crypt |
| * @clear |
| * @do_crypt |
| * @base: Common crypto API algorithm data structure. |
| * |
| * Diskcipher supports APIs to set crypto information for dm-crypt and fscrypt |
| * And pass the crypto information to disk host device via bio. |
| * Crypt operation executes on inline crypto on disk host device. |
| */ |
| struct diskcipher_alg { |
| int (*init)(struct crypto_diskcipher *tfm); |
| int (*exit)(struct crypto_diskcipher *tfm); |
| int (*setkey)(struct crypto_diskcipher *tfm, const char *key, |
| u32 keylen, bool persistent); |
| int (*clearkey)(struct crypto_diskcipher *tfm); |
| int (*crypt)(struct crypto_diskcipher *tfm, void *req); |
| int (*clear)(struct crypto_diskcipher *tfm, void *req); |
| int (*do_crypt)(struct crypto_diskcipher *tfm, |
| struct diskcipher_test_request *req); |
| struct device *dev; |
| struct crypto_alg base; |
| }; |
| |
| static inline unsigned int crypto_diskcipher_ivsize( |
| struct crypto_diskcipher *tfm) |
| { |
| return tfm->ivsize; |
| } |
| |
| static inline struct crypto_tfm *crypto_diskcipher_tfm( |
| struct crypto_diskcipher *tfm) |
| { |
| return &tfm->base; |
| } |
| |
| static inline struct diskcipher_alg *__crypto_diskcipher_alg( |
| struct crypto_alg *alg) |
| { |
| return container_of(alg, struct diskcipher_alg, base); |
| } |
| static inline struct diskcipher_alg *crypto_diskcipher_alg( |
| struct crypto_diskcipher *tfm) |
| { |
| return __crypto_diskcipher_alg(crypto_diskcipher_tfm(tfm)->__crt_alg); |
| } |
| |
| static inline struct crypto_diskcipher *__crypto_diskcipher_cast( |
| struct crypto_tfm *tfm) |
| { |
| return container_of(tfm, struct crypto_diskcipher, base); |
| } |
| |
| int crypto_register_diskcipher(struct diskcipher_alg *alg); |
| void crypto_unregister_diskcipher(struct diskcipher_alg *alg); |
| int crypto_register_diskciphers(struct diskcipher_alg *algs, int count); |
| void crypto_unregister_diskciphers(struct diskcipher_alg *algs, int count); |
| |
| #if defined(CONFIG_CRYPTO_DISKCIPHER) |
| /** |
| * crypto_alloc_diskcipher() - allocate disk cipher running on disk device |
| * @alg_name: is the cra_name / name or cra_driver_name / driver name of the |
| * skcipher cipher |
| * @type: specifies the type of the cipher |
| * @mask: specifies the mask for the cipher |
| * @force: add diskcipher postfix '-disk' on algo_name |
| * |
| * Allocate a cipher handle for an diskcipher. The returned struct |
| * crypto_diskcipher is the cipher handle that is required for any subsequent |
| * API invocation for that diskcipher. |
| * |
| * Return: allocated cipher handle in case of success; IS_ERR() is true in case |
| * of an error, PTR_ERR() returns the error code. |
| */ |
| struct crypto_diskcipher *crypto_alloc_diskcipher(const char *alg_name, |
| u32 type, u32 mask, bool force); |
| |
| /** |
| * crypto_free_diskcipher() - zeroize and free cipher handle |
| * @tfm: cipher handle to be freed |
| */ |
| void crypto_free_diskcipher(struct crypto_diskcipher *tfm); |
| |
| /** |
| * crypto_diskcipher_get() - get diskcipher from bio |
| * @bio: bio structure |
| */ |
| struct crypto_diskcipher *crypto_diskcipher_get(struct bio *bio); |
| |
| /** |
| * crypto_diskcipher_set() - set diskcipher to bio |
| * @bio: bio structure to contain diskcipher |
| * @tfm: cipher handle |
| * |
| * This functions set thm to bio->bi_aux_private to pass it to host driver. |
| * |
| */ |
| void crypto_diskcipher_set(struct bio *bio, struct crypto_diskcipher *tfm, |
| u64 dun); |
| |
| /** |
| * crypto_diskcipher_setkey() - set key for cipher |
| * @tfm: cipher handle |
| * @key: buffer holding the key |
| * @keylen: length of the key in bytes |
| * @persistent: option of key storage option |
| * |
| * The caller provided key is set for the skcipher referenced by the cipher |
| * handle. |
| * |
| * Return: 0 if the setting of the key was successful; < 0 if an error occurred |
| */ |
| int crypto_diskcipher_setkey(struct crypto_diskcipher *tfm, const char *key, |
| u32 keylen, bool persistent, |
| const struct inode *inode); |
| |
| /** |
| * crypto_diskcipher_clearkey() - clear key |
| * @tfm: cipher handle |
| */ |
| int crypto_diskcipher_clearkey(struct crypto_diskcipher *tfm); |
| |
| /** |
| * crypto_diskcipher_set_crypt() - set crypto info for inline crypto engine |
| * @tfm: cipher handle |
| * @req: request handle. it's specific structure for inline crypt hardware |
| * |
| * Return: 0 if the setting of the key was successful; < 0 if an error occurred |
| */ |
| int crypto_diskcipher_set_crypt(struct crypto_diskcipher *tfm, void *req); |
| |
| /** |
| * crypto_diskcipher_clear_crypt() - clear crypto info on inline crypt hardware |
| * @tfm: cipher handle |
| * @req: request handle. it's specific structure for inline crypt hardware |
| * |
| * Return: 0 if the setting of the key was successful; < 0 if an error occurred |
| */ |
| int crypto_diskcipher_clear_crypt(struct crypto_diskcipher *tfm, void *req); |
| |
| /** |
| * diskcipher_do_crypt() - execute crypto for test |
| * @tfm: cipher handle |
| * @req: diskcipher_test_request handle |
| * |
| * The caller uses this function to request crypto |
| * Diskcipher_algo allocates the block area for test and then request block I/O |
| * |
| */ |
| int diskcipher_do_crypt(struct crypto_diskcipher *tfm, |
| struct diskcipher_test_request *req); |
| |
| /** |
| * diskcipher_request_set_crypt() - fill diskcipher_test_requeust |
| * @req: request handle |
| * @src: source scatter / gather list |
| * @dst: destination scatter / gather list |
| * @cryptlen: number of bytes to process from @src |
| * @iv: IV for the cipher operation which must comply with the IV size defined |
| * by crypto_skcipher_ivsize |
| * @enc: encrypt(1) / decrypt(0) |
| * |
| * This function allows setting of the source data and destination data |
| * scatter / gather lists. |
| * |
| * For encryption, the source is treated as the plaintext and the |
| * destination is the ciphertext. For a decryption operation, the use is |
| * reversed - the source is the ciphertext and the destination is the plaintext. |
| */ |
| static inline void diskcipher_request_set_crypt( |
| struct diskcipher_test_request *req, |
| struct scatterlist *src, struct scatterlist *dst, |
| unsigned int cryptlen, void *iv, bool enc) |
| { |
| req->src = src; |
| req->dst = dst; |
| req->cryptlen = cryptlen; |
| req->iv = iv; |
| req->enc = enc; |
| } |
| |
| /** |
| * crypto_diskcipher_blk_mergeble() - check the crypt option of bios and decide |
| * whether to merge or not |
| * @bio1: a bio to be mergeable |
| * @bio2: a bio to be mergeable |
| */ |
| bool crypto_diskcipher_blk_mergeble(struct bio *bio1, struct bio *bio2); |
| |
| #else |
| |
| #define crypto_alloc_diskcipher(a, b, c, d) ((void *)NULL) |
| #define crypto_free_diskcipher(a) ((void)0) |
| #define crypto_diskcipher_get(a) ((void *)NULL) |
| #define crypto_diskcipher_set(a, b, d) ((void)0) |
| #define crypto_diskcipher_clearkey(a) ((void)0) |
| #define crypto_diskcipher_setkey(a, b, c, d, e) (-EINVAL) |
| #define crypto_diskcipher_blk_mergeble(a, b) (0) |
| #endif |
| #endif /* _DISKCIPHER_H_ */ |