From: Boojin Kim Date: Wed, 24 Jan 2018 08:00:12 +0000 (+0900) Subject: [COMMON] crypto: support diskcipher X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=2ad5939ed77e83c3315d6932dafa6eb6326c76ce;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [COMMON] crypto: support diskcipher Change-Id: I7b01a64020d6be4ec0c4344d71e6629db08fe2c6 Signed-off-by: Boojin Kim --- diff --git a/crypto/Kconfig b/crypto/Kconfig index d8b96515abe8..ad583228e0cd 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1627,6 +1627,13 @@ config CRYPTO_TWOFISH_AVX_X86_64 See also: +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 diff --git a/crypto/Makefile b/crypto/Makefile index d953cc1d57c4..62b9758d00bb 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -135,6 +135,7 @@ obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o 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 diff --git a/crypto/diskcipher.c b/crypto/diskcipher.c new file mode 100644 index 000000000000..78f1f0394d9f --- /dev/null +++ b/crypto/diskcipher.c @@ -0,0 +1,375 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + +#ifdef EANBLE_DISKCIPHER_DEBUG +#include +#include + +#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); +} diff --git a/crypto/testmgr.c b/crypto/testmgr.c index b5bb45a89ff8..68a1cfadd3fc 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -1682,6 +1683,150 @@ out: 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) { @@ -2526,6 +2671,17 @@ static const struct alg_test_desc alg_test_descs[] = { .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, @@ -3575,6 +3731,17 @@ static const struct alg_test_desc alg_test_descs[] = { .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, diff --git a/include/crypto/diskcipher.h b/include/crypto/diskcipher.h new file mode 100644 index 000000000000..2369b8b52030 --- /dev/null +++ b/include/crypto/diskcipher.h @@ -0,0 +1,222 @@ +/* + * 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 +#include + +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_ */ diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 29c4257f9c5b..dd76928b9ead 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -50,6 +50,7 @@ #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