Permalink
Please
sign in to comment.
Browse files
crypto: create generic version of ablk_helper
Create a generic version of ablk_helper so it can be reused by other architectures. Acked-by: Jussi Kivilinna <jussi.kivilinna@iki.fi> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Git-commit: a62b01cd6cc1feb5e80d64d6937c291473ed82cb Signed-off-by: Joonwoo Park <joonwoop@codeaurora.org>
- Loading branch information...
Showing
with
200 additions
and 0 deletions.
- +4 −0 crypto/Kconfig
- +1 −0 crypto/Makefile
- +150 −0 crypto/ablk_helper.c
- +14 −0 include/asm-generic/simd.h
- +31 −0 include/crypto/ablk_helper.h
| @@ -0,0 +1,150 @@ | |||
| /* | |||
| * Shared async block cipher helpers | |||
| * | |||
| * Copyright (c) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | |||
| * | |||
| * Based on aesni-intel_glue.c by: | |||
| * Copyright (C) 2008, Intel Corp. | |||
| * Author: Huang Ying <ying.huang@intel.com> | |||
| * | |||
| * 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. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU General Public License | |||
| * along with this program; if not, write to the Free Software | |||
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | |||
| * USA | |||
| * | |||
| */ | |||
|
|
|||
| #include <linux/kernel.h> | |||
| #include <linux/crypto.h> | |||
| #include <linux/init.h> | |||
| #include <linux/module.h> | |||
| #include <linux/hardirq.h> | |||
| #include <crypto/algapi.h> | |||
| #include <crypto/cryptd.h> | |||
| #include <crypto/ablk_helper.h> | |||
| #include <asm/simd.h> | |||
|
|
|||
| int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, | |||
| unsigned int key_len) | |||
| { | |||
| struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm); | |||
| struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base; | |||
| int err; | |||
|
|
|||
| crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); | |||
| crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm) | |||
| & CRYPTO_TFM_REQ_MASK); | |||
| err = crypto_ablkcipher_setkey(child, key, key_len); | |||
| crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child) | |||
| & CRYPTO_TFM_RES_MASK); | |||
| return err; | |||
| } | |||
| EXPORT_SYMBOL_GPL(ablk_set_key); | |||
|
|
|||
| int __ablk_encrypt(struct ablkcipher_request *req) | |||
| { | |||
| struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); | |||
| struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm); | |||
| struct blkcipher_desc desc; | |||
|
|
|||
| desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); | |||
| desc.info = req->info; | |||
| desc.flags = 0; | |||
|
|
|||
| return crypto_blkcipher_crt(desc.tfm)->encrypt( | |||
| &desc, req->dst, req->src, req->nbytes); | |||
| } | |||
| EXPORT_SYMBOL_GPL(__ablk_encrypt); | |||
|
|
|||
| int ablk_encrypt(struct ablkcipher_request *req) | |||
| { | |||
| struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); | |||
| struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm); | |||
|
|
|||
| if (!may_use_simd()) { | |||
| struct ablkcipher_request *cryptd_req = | |||
| ablkcipher_request_ctx(req); | |||
|
|
|||
| memcpy(cryptd_req, req, sizeof(*req)); | |||
| ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); | |||
|
|
|||
| return crypto_ablkcipher_encrypt(cryptd_req); | |||
| } else { | |||
| return __ablk_encrypt(req); | |||
| } | |||
| } | |||
| EXPORT_SYMBOL_GPL(ablk_encrypt); | |||
|
|
|||
| int ablk_decrypt(struct ablkcipher_request *req) | |||
| { | |||
| struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); | |||
| struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm); | |||
|
|
|||
| if (!may_use_simd()) { | |||
| struct ablkcipher_request *cryptd_req = | |||
| ablkcipher_request_ctx(req); | |||
|
|
|||
| memcpy(cryptd_req, req, sizeof(*req)); | |||
| ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); | |||
|
|
|||
| return crypto_ablkcipher_decrypt(cryptd_req); | |||
| } else { | |||
| struct blkcipher_desc desc; | |||
|
|
|||
| desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); | |||
| desc.info = req->info; | |||
| desc.flags = 0; | |||
|
|
|||
| return crypto_blkcipher_crt(desc.tfm)->decrypt( | |||
| &desc, req->dst, req->src, req->nbytes); | |||
| } | |||
| } | |||
| EXPORT_SYMBOL_GPL(ablk_decrypt); | |||
|
|
|||
| void ablk_exit(struct crypto_tfm *tfm) | |||
| { | |||
| struct async_helper_ctx *ctx = crypto_tfm_ctx(tfm); | |||
|
|
|||
| cryptd_free_ablkcipher(ctx->cryptd_tfm); | |||
| } | |||
| EXPORT_SYMBOL_GPL(ablk_exit); | |||
|
|
|||
| int ablk_init_common(struct crypto_tfm *tfm, const char *drv_name) | |||
| { | |||
| struct async_helper_ctx *ctx = crypto_tfm_ctx(tfm); | |||
| struct cryptd_ablkcipher *cryptd_tfm; | |||
|
|
|||
| cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0); | |||
| if (IS_ERR(cryptd_tfm)) | |||
| return PTR_ERR(cryptd_tfm); | |||
|
|
|||
| ctx->cryptd_tfm = cryptd_tfm; | |||
| tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + | |||
| crypto_ablkcipher_reqsize(&cryptd_tfm->base); | |||
|
|
|||
| return 0; | |||
| } | |||
| EXPORT_SYMBOL_GPL(ablk_init_common); | |||
|
|
|||
| int ablk_init(struct crypto_tfm *tfm) | |||
| { | |||
| char drv_name[CRYPTO_MAX_ALG_NAME]; | |||
|
|
|||
| snprintf(drv_name, sizeof(drv_name), "__driver-%s", | |||
| crypto_tfm_alg_driver_name(tfm)); | |||
|
|
|||
| return ablk_init_common(tfm, drv_name); | |||
| } | |||
| EXPORT_SYMBOL_GPL(ablk_init); | |||
|
|
|||
| MODULE_LICENSE("GPL"); | |||
| @@ -0,0 +1,14 @@ | |||
|
|
|||
| #include <linux/hardirq.h> | |||
|
|
|||
| /* | |||
| * may_use_simd - whether it is allowable at this time to issue SIMD | |||
| * instructions or access the SIMD register file | |||
| * | |||
| * As architectures typically don't preserve the SIMD register file when | |||
| * taking an interrupt, !in_interrupt() should be a reasonable default. | |||
| */ | |||
| static __must_check inline bool may_use_simd(void) | |||
| { | |||
| return !in_interrupt(); | |||
| } | |||
| @@ -0,0 +1,31 @@ | |||
| /* | |||
| * Shared async block cipher helpers | |||
| */ | |||
|
|
|||
| #ifndef _CRYPTO_ABLK_HELPER_H | |||
| #define _CRYPTO_ABLK_HELPER_H | |||
|
|
|||
| #include <linux/crypto.h> | |||
| #include <linux/kernel.h> | |||
| #include <crypto/cryptd.h> | |||
|
|
|||
| struct async_helper_ctx { | |||
| struct cryptd_ablkcipher *cryptd_tfm; | |||
| }; | |||
|
|
|||
| extern int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, | |||
| unsigned int key_len); | |||
|
|
|||
| extern int __ablk_encrypt(struct ablkcipher_request *req); | |||
|
|
|||
| extern int ablk_encrypt(struct ablkcipher_request *req); | |||
|
|
|||
| extern int ablk_decrypt(struct ablkcipher_request *req); | |||
|
|
|||
| extern void ablk_exit(struct crypto_tfm *tfm); | |||
|
|
|||
| extern int ablk_init_common(struct crypto_tfm *tfm, const char *drv_name); | |||
|
|
|||
| extern int ablk_init(struct crypto_tfm *tfm); | |||
|
|
|||
| #endif /* _CRYPTO_ABLK_HELPER_H */ | |||
0 comments on commit
adcea6f