See also:
<http://www.schneier.com/twofish.html>
+config CRYPTO_DISKCIPHER
+ bool "Diskcipher support"
+ default n
+ help
+ Diskcipher support the crypt operation of the block host device
+ that has inline crypto engine.
+
comment "Compression"
config CRYPTO_DEFLATE
obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
obj-$(CONFIG_CRYPTO_USER_API_RNG) += algif_rng.o
obj-$(CONFIG_CRYPTO_USER_API_AEAD) += algif_aead.o
+obj-$(CONFIG_CRYPTO_DISKCIPHER) += diskcipher.o
ecdh_generic-y := ecc.o
ecdh_generic-y += ecdh.o
--- /dev/null
+/*
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/blkdev.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/diskcipher.h>
+
+#include "internal.h"
+
+#ifdef EANBLE_DISKCIPHER_DEBUG
+#include <crypto/fmp.h>
+#include <linux/mm_types.h>
+
+#define DUMP_MAX 20
+
+enum diskcipher_api {
+ DISKC_API_ALLOC, DISKC_API_FREE, DISKC_API_SET,
+ DISKC_API_GET, DISKC_API_CRYPT, DISKC_API_CLEAR, DISKC_API_MAX,
+};
+
+struct dump_err {
+ struct page *page;
+ struct bio bio;
+ struct fmp_crypto_info ci;
+ enum diskcipher_api api;
+};
+
+struct diskc_debug_info {
+ struct dump_err dump[DUMP_MAX];
+ int err;
+ u32 cnt[DISKC_API_MAX][2];
+};
+
+static struct diskc_debug_info diskc_dbg;
+
+static void print_err(void)
+{
+ int i, j;
+ struct bio_vec *bv; /* bio page list */
+ struct bio *bio;
+ struct fmp_crypto_info *ci;
+ struct diskc_debug_info *dbg = &diskc_dbg;
+
+ for (j = 0; j < dbg->err; j++) {
+ bio = &dbg->dump[j].bio;
+ ci = &dbg->dump[j].ci;
+
+ if (bio) {
+ pr_info
+ ("%s(%d/%d): bio:%p ci:%p page:%p flag:%x, opf:%x, crypt:%p\n",
+ __func__, j, dbg->err, bio, ci, &dbg->dump[j].page,
+ bio->bi_flags, bio->bi_opf, bio->bi_aux_private);
+ print_hex_dump(KERN_CONT, "bio:", DUMP_PREFIX_OFFSET,
+ 16, 1, bio, sizeof(struct bio), false);
+ for (i = 0; i < bio->bi_max_vecs; i++) {
+ bv = &bio->bi_io_vec[i];
+ pr_info("bv[%d] page:%p len:%d offset:%d\n",
+ i, bv->bv_page, bv->bv_len, bv->bv_offset);
+ }
+ }
+
+ if (ci) {
+ pr_info("[ci] key_size:%d algo_mode:%d\n",
+ ci->key_size, ci->algo_mode);
+ print_hex_dump(KERN_CONT, "key:", DUMP_PREFIX_OFFSET,
+ 16, 1, ci->key, sizeof(ci->key), false);
+ }
+ }
+}
+
+static void dump_err(struct crypto_diskcipher *ci, enum diskcipher_api api,
+ struct bio *bio, struct page *page)
+{
+ struct diskc_debug_info *dbg = &diskc_dbg;
+
+ if ((dbg->err < DUMP_MAX) && ci) {
+ struct crypto_tfm *tfm = crypto_diskcipher_tfm(ci);
+
+ dbg->dump[dbg->err].api = api;
+ memcpy(&dbg->dump[dbg->err].ci, crypto_tfm_ctx(tfm),
+ sizeof(struct fmp_crypto_info));
+
+ if (page)
+ dbg->dump[dbg->err].page = page;
+ if (bio)
+ memcpy(&dbg->dump[dbg->err].bio, bio,
+ sizeof(struct bio));
+ }
+ dbg->err++;
+}
+
+static inline void disckipher_log(enum diskcipher_api api, int ret,
+ struct crypto_diskcipher *ci)
+{
+ struct diskc_debug_info *dbg = &diskc_dbg;
+
+ dbg->cnt[api][0]++;
+ if (ret) {
+ dbg->cnt[api][1]++;
+ if (ci)
+ dump_err(ci, api, NULL, NULL);
+ }
+}
+
+static void disckipher_log_show(struct seq_file *m)
+{
+ int i;
+ char name[DISKC_API_MAX][8]
+ = {"alloc", "free", "set", "get", "crypt", "clear"};
+ struct diskc_debug_info *dbg = &diskc_dbg;
+
+ for (i = 0; i < DISKC_API_MAX; i++)
+ seq_printf(m, "%s\t: %6u(err:%u)\n",
+ name[i], dbg->cnt[i][0], dbg->cnt[i][1]);
+
+ if (dbg->err)
+ print_err();
+}
+
+/* check diskcipher for FBE */
+void crypto_diskcipher_check(struct bio *bio, struct page *page)
+{
+#ifdef FBE_DEBUG
+ int ret = 0;
+ struct crypto_diskcipher *ci = NULL;
+
+ if (page && !PageAnon(page) && bio)
+ if (page->mapping)
+ if (page->mapping->host)
+ if (page->mapping->host->i_crypt_info) {
+ ci = page->mapping->host->i_crypt_info->ci_dtfm;
+ if (ci && (bio->bi_aux_private != ci)
+ && (!(bio->bi_flags & REQ_OP_DISCARD))) {
+ dump_err(ci, DISKC_API_GET, bio, page);
+ ret = 1;
+ }
+ }
+ disckipher_log(DISKC_API_GET, ret, ci);
+#endif
+}
+#else
+enum diskcipher_api {
+ DISKC_API_ALLOC, DISKC_API_FREE, DISKC_API_SET,
+ DISKC_API_GET, DISKC_API_CRYPT, DISKC_API_CLEAR, DISKC_API_MAX,
+};
+
+#define disckipher_log_show(a) do { } while (0)
+#define disckipher_log(a, b, c) do { } while (0)
+#endif
+
+#define DISKC_NAME "-disk"
+#define DISKC_NAME_SIZE (5)
+
+struct crypto_diskcipher *crypto_diskcipher_get(struct bio *bio)
+{
+ if (!bio || !virt_addr_valid(bio)) {
+ pr_err("%s: Invalid bio:%p\n", __func__, bio);
+ return NULL;
+ }
+ if (bio->bi_opf & REQ_CRYPT)
+ return bio->bi_aux_private;
+ else
+ return NULL;
+}
+
+void crypto_diskcipher_set(struct bio *bio,
+ struct crypto_diskcipher *diskcipher)
+{
+ if (bio && diskcipher) {
+ bio->bi_opf |= (REQ_CRYPT | REQ_AUX_PRIV);
+ bio->bi_aux_private = diskcipher;
+ }
+ disckipher_log(DISKC_API_SET, 0, NULL);
+}
+
+int crypto_diskcipher_setkey(struct crypto_diskcipher *tfm, const char *in_key,
+ unsigned int key_len, bool persistent)
+{
+ struct crypto_tfm *base = crypto_diskcipher_tfm(tfm);
+ struct diskcipher_alg *cra = crypto_diskcipher_alg(base->__crt_alg);
+
+ if (!cra) {
+ pr_err("%s: doesn't exist cra", __func__);
+ return -EINVAL;
+ }
+ return cra->setkey(base, in_key, key_len, persistent);
+}
+
+int crypto_diskcipher_clearkey(struct crypto_diskcipher *tfm)
+{
+ struct crypto_tfm *base = crypto_diskcipher_tfm(tfm);
+ struct diskcipher_alg *cra = crypto_diskcipher_alg(base->__crt_alg);
+
+ if (!cra) {
+ pr_err("%s: doesn't exist cra", __func__);
+ return -EINVAL;
+ }
+ return cra->clearkey(base);
+}
+
+int crypto_diskcipher_set_crypt(struct crypto_diskcipher *tfm, void *req)
+{
+ int ret = 0;
+ struct crypto_tfm *base = crypto_diskcipher_tfm(tfm);
+ struct diskcipher_alg *cra = crypto_diskcipher_alg(base->__crt_alg);
+
+ if (!cra) {
+ pr_err("%s: doesn't exist cra", __func__);
+ ret = EINVAL;
+ goto out;
+ }
+
+ ret = cra->crypt(base, req);
+out:
+ if (ret)
+ pr_err("%s fails ret:%d, cra:%p\n", __func__, ret, cra);
+ pr_debug("%s done\n", __func__);
+ disckipher_log(DISKC_API_CRYPT, ret, tfm);
+ return ret;
+}
+
+int crypto_diskcipher_clear_crypt(struct crypto_diskcipher *tfm, void *req)
+{
+ int ret = 0;
+ struct crypto_tfm *base = crypto_diskcipher_tfm(tfm);
+ struct diskcipher_alg *cra = crypto_diskcipher_alg(base->__crt_alg);
+
+ if (!cra) {
+ pr_err("%s: doesn't exist cra", __func__);
+ ret = EINVAL;
+ goto out;
+ }
+
+ ret = cra->clear(base, req);
+ if (ret)
+ pr_err("%s fails", __func__);
+
+out:
+ pr_debug("%s done\n", __func__);
+ disckipher_log(DISKC_API_CLEAR, ret, tfm);
+ return ret;
+}
+
+#ifndef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
+int diskcipher_do_crypt(struct crypto_diskcipher *tfm,
+ struct diskcipher_test_request *req)
+{
+ int ret;
+ struct crypto_tfm *base = crypto_diskcipher_tfm(tfm);
+ struct diskcipher_alg *cra = crypto_diskcipher_alg(base->__crt_alg);
+
+ if (!cra) {
+ pr_err("%s: doesn't exist cra", __func__);
+ ret = EINVAL;
+ goto out;
+ }
+
+ if (cra->do_crypt)
+ ret = cra->do_crypt(base, req);
+ else
+ ret = -EINVAL;
+ if (ret)
+ pr_err("%s fails ret:%d", __func__, ret);
+
+out:
+ pr_debug("%s done\n", __func__);
+ return ret;
+}
+#endif
+
+static int crypto_diskcipher_init_tfm(struct crypto_tfm *tfm)
+{
+ return 0;
+}
+
+unsigned int crypto_diskcipher_extsize(struct crypto_alg *alg)
+{
+ return alg->cra_ctxsize +
+ (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1));
+}
+
+static void crypto_diskcipher_show(struct seq_file *m, struct crypto_alg *alg)
+{
+ seq_printf(m, "type : diskcipher\n");
+ disckipher_log_show(m);
+}
+
+static const struct crypto_type crypto_diskcipher_type = {
+ .extsize = crypto_diskcipher_extsize,
+ .init_tfm = crypto_diskcipher_init_tfm,
+#ifdef CONFIG_PROC_FS
+ .show = crypto_diskcipher_show,
+#endif
+ .maskclear = ~CRYPTO_ALG_TYPE_MASK,
+ .maskset = CRYPTO_ALG_TYPE_MASK,
+ .type = CRYPTO_ALG_TYPE_DISKCIPHER,
+ .tfmsize = offsetof(struct crypto_diskcipher, base),
+};
+
+struct crypto_diskcipher *crypto_alloc_diskcipher(const char *alg_name,
+ u32 type, u32 mask, bool force)
+{
+ disckipher_log(DISKC_API_ALLOC, 0, NULL);
+ if (force) {
+ if (strlen(alg_name) + DISKC_NAME_SIZE < CRYPTO_MAX_ALG_NAME) {
+ char diskc_name[CRYPTO_MAX_ALG_NAME];
+
+ strcpy(diskc_name, alg_name);
+ strcat(diskc_name, DISKC_NAME);
+ return crypto_alloc_tfm(diskc_name,
+ &crypto_diskcipher_type, type, mask);
+ }
+ } else {
+ return crypto_alloc_tfm(alg_name, &crypto_diskcipher_type, type, mask);
+ }
+
+ return NULL;
+}
+
+void crypto_free_diskcipher(struct crypto_diskcipher *tfm)
+{
+ disckipher_log(DISKC_API_FREE, 0, NULL);
+ crypto_destroy_tfm(tfm, crypto_diskcipher_tfm(tfm));
+}
+
+int crypto_register_diskcipher(struct diskcipher_alg *alg)
+{
+ struct crypto_alg *base = &alg->base;
+
+ base->cra_type = &crypto_diskcipher_type;
+ base->cra_flags = CRYPTO_ALG_TYPE_DISKCIPHER;
+ return crypto_register_alg(base);
+}
+
+void crypto_unregister_diskcipher(struct diskcipher_alg *alg)
+{
+ crypto_unregister_alg(&alg->base);
+}
+
+int crypto_register_diskciphers(struct diskcipher_alg *algs, int count)
+{
+ int i, ret;
+
+ for (i = 0; i < count; i++) {
+ ret = crypto_register_diskcipher(algs + i);
+ if (ret)
+ goto err;
+ }
+ return 0;
+
+err:
+ for (--i; i >= 0; --i)
+ crypto_unregister_diskcipher(algs + i);
+ return ret;
+}
+
+void crypto_unregister_diskciphers(struct diskcipher_alg *algs, int count)
+{
+ int i;
+
+ for (i = count - 1; i >= 0; --i)
+ crypto_unregister_diskcipher(algs + i);
+}
#include <crypto/rng.h>
#include <crypto/drbg.h>
#include <crypto/akcipher.h>
+#include <crypto/diskcipher.h>
#include <crypto/kpp.h>
#include <crypto/acompress.h>
return err;
}
+#ifdef CONFIG_CRYPTO_DISKCIPHER
+static int __test_diskcipher(struct crypto_diskcipher *tfm, int enc,
+ const struct cipher_testvec *template, unsigned int tcount,
+ const int align_offset)
+{
+ const char *algo =
+ crypto_tfm_alg_driver_name(crypto_diskcipher_tfm(tfm));
+ unsigned int i, j;
+ char *q;
+ struct scatterlist sg[8];
+ struct scatterlist sgout[8];
+ const char *e = (enc == ENCRYPT) ? "encryption" : "decryption";
+ struct tcrypt_result result;
+ void *data;
+ char iv[MAX_IVLEN];
+ char *xbuf[XBUFSIZE];
+ char *xoutbuf[XBUFSIZE];
+ int ret = -ENOMEM;
+ unsigned int ivsize = crypto_diskcipher_ivsize(tfm);
+ struct diskcipher_test_request req;
+
+ if (testmgr_alloc_buf(xbuf))
+ goto out_nobuf;
+
+ if (testmgr_alloc_buf(xoutbuf))
+ goto out_nooutbuf;
+
+ init_completion(&result.completion);
+
+ j = 0;
+ for (i = 0; i < tcount; i++) {
+ if (template[i].np && !template[i].also_non_np)
+ continue;
+
+ if (template[i].fips_skip)
+ continue;
+
+ if (template[i].iv)
+ memcpy(iv, template[i].iv, ivsize);
+ else
+ memset(iv, 0, MAX_IVLEN);
+
+ j++;
+ ret = -EINVAL;
+ if (WARN_ON(align_offset + template[i].ilen > PAGE_SIZE))
+ goto out;
+
+ ret = crypto_diskcipher_setkey(tfm, template[i].key,
+ template[i].klen, 0);
+ if (ret == -ENOKEY) {
+ pr_err("alg: diskcipher: no support %d keylen for %s. skip it\n",
+ template[i].klen, algo);
+ continue;
+ } else if (ret) {
+ pr_err("alg: diskcipher: setkey failed on test %d for %s\n",
+ j, algo);
+ goto out;
+ }
+
+ data = xbuf[0];
+ data += align_offset;
+ memcpy(data, template[i].input, template[i].ilen);
+ sg_init_one(&sg[0], data, template[i].ilen);
+
+ data = xoutbuf[0];
+ data += align_offset;
+ sg_init_one(&sgout[0], data, template[i].ilen);
+
+ diskcipher_request_set_crypt(&req, sg, sgout,
+ template[i].ilen, iv, enc ? 1 : 0);
+ ret = diskcipher_do_crypt(tfm, &req);
+ if (ret) {
+ pr_err("alg: diskcipher: %s failed on test %d for %s: ret=%d\n",
+ e, j, algo, -ret);
+ goto out;
+ }
+
+ q = data;
+ if (memcmp(q, template[i].result, template[i].rlen)) {
+ pr_err("alg: diskcipher: Test %d failed (invalid result) on %s for %s\n",
+ j, e, algo);
+ hexdump(q, template[i].rlen);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+ ret = 0;
+
+out:
+ testmgr_free_buf(xoutbuf);
+out_nooutbuf:
+ testmgr_free_buf(xbuf);
+out_nobuf:
+ return ret;
+}
+
+static int test_diskcipher(struct crypto_diskcipher *tfm, int enc,
+ const struct cipher_testvec *template,
+ unsigned int tcount)
+{
+ int ret;
+
+ ret = __test_diskcipher(tfm, enc, template, tcount, 0);
+ if (ret)
+ return ret;
+
+ /* test unaligned buffers, check with one byte offset */
+ ret = __test_diskcipher(tfm, enc, template, tcount, 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int alg_test_diskcipher(const struct alg_test_desc *desc,
+ const char *driver, u32 type, u32 mask)
+{
+ struct crypto_diskcipher *tfm;
+ int err = 0;
+
+ tfm = crypto_alloc_diskcipher(driver, type | CRYPTO_ALG_INTERNAL, mask, 0);
+ if (!tfm || IS_ERR(tfm)) {
+ pr_err("alg: diskcipher: Failed to load transform for %s: %ld\n",
+ driver, PTR_ERR(tfm));
+ return PTR_ERR(tfm);
+ }
+
+ if (desc->suite.cipher.enc.vecs) {
+ err = test_diskcipher(tfm, ENCRYPT, desc->suite.cipher.enc.vecs,
+ desc->suite.cipher.enc.count);
+ if (err)
+ goto out;
+ }
+
+ if (desc->suite.cipher.dec.vecs)
+ err = test_diskcipher(tfm, DECRYPT, desc->suite.cipher.dec.vecs,
+ desc->suite.cipher.dec.count);
+
+out:
+ crypto_free_diskcipher(tfm);
+ return err;
+}
+#endif
+
static int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
u32 type, u32 mask)
{
.dec = __VECS(aes_cbc_dec_tv_template)
}
}
+#ifdef CONFIG_CRYPTO_DISKCIPHER
+ }, {
+ .alg = "cbc(aes)-disk",
+ .test = alg_test_diskcipher,
+ .suite = {
+ .cipher = {
+ .enc = __VECS(aes_cbc_enc_tv_template),
+ .dec = __VECS(aes_cbc_dec_tv_template)
+ }
+ }
+#endif
}, {
.alg = "cbc(anubis)",
.test = alg_test_skcipher,
.dec = __VECS(aes_xts_dec_tv_template)
}
}
+#ifdef CONFIG_CRYPTO_DISKCIPHER
+ }, {
+ .alg = "xts(aes)-disk",
+ .test = alg_test_diskcipher,
+ .suite = {
+ .cipher = {
+ .enc = __VECS(aes_xts_enc_tv_template),
+ .dec = __VECS(aes_xts_dec_tv_template)
+ }
+ }
+#endif
}, {
.alg = "xts(camellia)",
.test = alg_test_skcipher,
--- /dev/null
+/*
+ * 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;
+ 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.
+ */
+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
+ 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);
+
+/**
+ * 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);
+
+/**
+ * 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
+#define EANBLE_DISKCIPHER_DEBUG
+#ifdef EANBLE_DISKCIPHER_DEBUG
+void crypto_diskcipher_check(struct bio *bio, struct page *page);
+#endif
+#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) ((void)0)
+#define crypto_diskcipher_clearkey(a) ((void)0)
+#define crypto_diskcipher_setkey(a, b, c, d) (-1)
+#endif
+#endif /* _DISKCIPHER_H_ */
#define CRYPTO_ALG_TYPE_ABLKCIPHER 0x00000005
#define CRYPTO_ALG_TYPE_SKCIPHER 0x00000005
#define CRYPTO_ALG_TYPE_GIVCIPHER 0x00000006
+#define CRYPTO_ALG_TYPE_DISKCIPHER 0x00000007
#define CRYPTO_ALG_TYPE_KPP 0x00000008
#define CRYPTO_ALG_TYPE_ACOMPRESS 0x0000000a
#define CRYPTO_ALG_TYPE_SCOMPRESS 0x0000000b