blob: 656e004124779013adc7c16e2cedf8c88d929398 [file] [log] [blame]
/*
* 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;
struct crypto_diskcipher {
u32 algo;
unsigned int ivsize;
#ifdef USE_FREE_REQ
/* for crypto_free_req_diskcipher */
unsigned long req_jiffies;
struct list_head node;
#endif
atomic_t status;
struct crypto_tfm base;
};
struct diskcipher_test_request {
unsigned int cryptlen;
const u8 *iv;
struct scatterlist *src;
struct scatterlist *dst;
bool enc;
};
/**
* struct diskcipher_alg - symmetric key 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.
*/
#ifdef USE_FREE_REQ
struct diskcipher_freectrl {
spinlock_t freelist_lock;
struct list_head freelist;
struct delayed_work freewq;
atomic_t freewq_active;
u32 max_io_ms;
};
#endif
struct diskcipher_alg {
int (*setkey)(struct crypto_tfm *tfm, const char *key, u32 keylen,
bool persistent);
int (*clearkey)(struct crypto_tfm *tfm);
int (*crypt)(struct crypto_tfm *tfm, void *req);
int (*clear)(struct crypto_tfm *tfm, void *req);
#ifndef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
int (*do_crypt)(struct crypto_tfm *tfm,
struct diskcipher_test_request *req);
#endif
#ifdef USE_FREE_REQ
struct diskcipher_freectrl freectrl;
#endif
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 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 symmetric 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);
void crypto_free_req_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);
/**
* 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);
#ifndef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
/**
* 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;
}
#endif
enum diskcipher_dbg {
DISKC_API_ALLOC, DISKC_API_FREE, DISKC_API_FREEREQ, DISKC_API_SETKEY,
DISKC_API_SET, DISKC_API_GET, DISKC_API_CRYPT, DISKC_API_CLEAR,
DISKC_API_MAX, FS_PAGEIO, FS_READP, FS_DIO, FS_BLOCK_WRITE,
FS_ZEROPAGE, BLK_BH, DMCRYPT, DISKC_MERGE, DISKC_MERGE_ERR_INODE, DISKC_MERGE_ERR_DISKC,
FS_DEC_WARN, FS_ENC_WARN, DISKC_MERGE_DIO, DISKC_FREE_REQ_WARN,
DISKC_FREE_WQ_WARN, DISKC_CRYPT_WARN,
DM_CRYPT_NONENCRYPT, DM_CRYPT_CTR, DM_CRYPT_DTR, DM_CRYPT_OVER,
F2FS_gc, F2FS_gc_data_page, F2FS_gc_data_page_key, F2FS_gc_data_page_key_FC,
F2FS_gc_data_page_FC, F2FS_gc_data_block, F2FS_gc_data_block_key,
F2FS_gc_data_block_err1, F2FS_gc_data_block_err2, F2FS_gc_data_block_err3, F2FS_gc_skip,
DISKC_ERR, DISKC_NO_KEY_ERR, DISKC_NO_SYNC_ERR, DISKC_NO_CRYPT_ERR, DISKC_NO_DISKC_ERR,
DISKC_USER_MAX
};
#ifdef CONFIG_CRYPTO_DISKCIPHER_DEBUG
void crypto_diskcipher_debug(enum diskcipher_dbg dbg, int idx);
#else
#define crypto_diskcipher_debug(a, b) ((void)0)
#endif
#else
#define crypto_alloc_diskcipher(a, b, c, d) ((void *)-EINVAL)
#define crypto_free_diskcipher(a) ((void)0)
#define crypto_free_req_diskcipher(a) ((void)0)
#define crypto_diskcipher_get(a) ((void *)NULL)
#define crypto_diskcipher_set(a, b, c, d) ((void)0)
#define crypto_diskcipher_clearkey(a) ((void)0)
#define crypto_diskcipher_setkey(a, b, c, d) (-1)
#define crypto_diskcipher_debug(a, b) ((void)0)
#endif
#endif /* _DISKCIPHER_H_ */