1/* 2 * Shared async block cipher helpers 3 * 4 * Copyright (c) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi> 5 * 6 * Based on aesni-intel_glue.c by: 7 * Copyright (C) 2008, Intel Corp. 8 * Author: Huang Ying <ying.huang@intel.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 * USA 24 * 25 */ 26 27#include <linux/kernel.h> 28#include <linux/crypto.h> 29#include <linux/init.h> 30#include <linux/module.h> 31#include <linux/hardirq.h> 32#include <crypto/algapi.h> 33#include <crypto/cryptd.h> 34#include <crypto/ablk_helper.h> 35#include <asm/simd.h> 36 37int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, 38 unsigned int key_len) 39{ 40 struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm); 41 struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base; 42 int err; 43 44 crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); 45 crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm) 46 & CRYPTO_TFM_REQ_MASK); 47 err = crypto_ablkcipher_setkey(child, key, key_len); 48 crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child) 49 & CRYPTO_TFM_RES_MASK); 50 return err; 51} 52EXPORT_SYMBOL_GPL(ablk_set_key); 53 54int __ablk_encrypt(struct ablkcipher_request *req) 55{ 56 struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); 57 struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm); 58 struct blkcipher_desc desc; 59 60 desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); 61 desc.info = req->info; 62 desc.flags = 0; 63 64 return crypto_blkcipher_crt(desc.tfm)->encrypt( 65 &desc, req->dst, req->src, req->nbytes); 66} 67EXPORT_SYMBOL_GPL(__ablk_encrypt); 68 69int ablk_encrypt(struct ablkcipher_request *req) 70{ 71 struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); 72 struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm); 73 74 if (!may_use_simd()) { 75 struct ablkcipher_request *cryptd_req = 76 ablkcipher_request_ctx(req); 77 78 *cryptd_req = *req; 79 ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); 80 81 return crypto_ablkcipher_encrypt(cryptd_req); 82 } else { 83 return __ablk_encrypt(req); 84 } 85} 86EXPORT_SYMBOL_GPL(ablk_encrypt); 87 88int ablk_decrypt(struct ablkcipher_request *req) 89{ 90 struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); 91 struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm); 92 93 if (!may_use_simd()) { 94 struct ablkcipher_request *cryptd_req = 95 ablkcipher_request_ctx(req); 96 97 *cryptd_req = *req; 98 ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); 99 100 return crypto_ablkcipher_decrypt(cryptd_req); 101 } else { 102 struct blkcipher_desc desc; 103 104 desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); 105 desc.info = req->info; 106 desc.flags = 0; 107 108 return crypto_blkcipher_crt(desc.tfm)->decrypt( 109 &desc, req->dst, req->src, req->nbytes); 110 } 111} 112EXPORT_SYMBOL_GPL(ablk_decrypt); 113 114void ablk_exit(struct crypto_tfm *tfm) 115{ 116 struct async_helper_ctx *ctx = crypto_tfm_ctx(tfm); 117 118 cryptd_free_ablkcipher(ctx->cryptd_tfm); 119} 120EXPORT_SYMBOL_GPL(ablk_exit); 121 122int ablk_init_common(struct crypto_tfm *tfm, const char *drv_name) 123{ 124 struct async_helper_ctx *ctx = crypto_tfm_ctx(tfm); 125 struct cryptd_ablkcipher *cryptd_tfm; 126 127 cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, CRYPTO_ALG_INTERNAL, 128 CRYPTO_ALG_INTERNAL); 129 if (IS_ERR(cryptd_tfm)) 130 return PTR_ERR(cryptd_tfm); 131 132 ctx->cryptd_tfm = cryptd_tfm; 133 tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + 134 crypto_ablkcipher_reqsize(&cryptd_tfm->base); 135 136 return 0; 137} 138EXPORT_SYMBOL_GPL(ablk_init_common); 139 140int ablk_init(struct crypto_tfm *tfm) 141{ 142 char drv_name[CRYPTO_MAX_ALG_NAME]; 143 144 snprintf(drv_name, sizeof(drv_name), "__driver-%s", 145 crypto_tfm_alg_driver_name(tfm)); 146 147 return ablk_init_common(tfm, drv_name); 148} 149EXPORT_SYMBOL_GPL(ablk_init); 150 151MODULE_LICENSE("GPL"); 152