247 lines
7.4 KiB
C
Executable File
247 lines
7.4 KiB
C
Executable File
/* 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_ */
|