15068c7a8SSteffen Klassert /* 25068c7a8SSteffen Klassert * pcrypt - Parallel crypto wrapper. 35068c7a8SSteffen Klassert * 45068c7a8SSteffen Klassert * Copyright (C) 2009 secunet Security Networks AG 55068c7a8SSteffen Klassert * Copyright (C) 2009 Steffen Klassert <steffen.klassert@secunet.com> 65068c7a8SSteffen Klassert * 75068c7a8SSteffen Klassert * This program is free software; you can redistribute it and/or modify it 85068c7a8SSteffen Klassert * under the terms and conditions of the GNU General Public License, 95068c7a8SSteffen Klassert * version 2, as published by the Free Software Foundation. 105068c7a8SSteffen Klassert * 115068c7a8SSteffen Klassert * This program is distributed in the hope it will be useful, but WITHOUT 125068c7a8SSteffen Klassert * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 135068c7a8SSteffen Klassert * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 145068c7a8SSteffen Klassert * more details. 155068c7a8SSteffen Klassert * 165068c7a8SSteffen Klassert * You should have received a copy of the GNU General Public License along with 175068c7a8SSteffen Klassert * this program; if not, write to the Free Software Foundation, Inc., 185068c7a8SSteffen Klassert * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 195068c7a8SSteffen Klassert */ 205068c7a8SSteffen Klassert 215068c7a8SSteffen Klassert #include <crypto/algapi.h> 225068c7a8SSteffen Klassert #include <crypto/internal/aead.h> 235068c7a8SSteffen Klassert #include <linux/err.h> 245068c7a8SSteffen Klassert #include <linux/init.h> 255068c7a8SSteffen Klassert #include <linux/module.h> 265068c7a8SSteffen Klassert #include <linux/slab.h> 275068c7a8SSteffen Klassert #include <crypto/pcrypt.h> 285068c7a8SSteffen Klassert 295068c7a8SSteffen Klassert static struct padata_instance *pcrypt_enc_padata; 305068c7a8SSteffen Klassert static struct padata_instance *pcrypt_dec_padata; 315068c7a8SSteffen Klassert static struct workqueue_struct *encwq; 325068c7a8SSteffen Klassert static struct workqueue_struct *decwq; 335068c7a8SSteffen Klassert 345068c7a8SSteffen Klassert struct pcrypt_instance_ctx { 355068c7a8SSteffen Klassert struct crypto_spawn spawn; 365068c7a8SSteffen Klassert unsigned int tfm_count; 375068c7a8SSteffen Klassert }; 385068c7a8SSteffen Klassert 395068c7a8SSteffen Klassert struct pcrypt_aead_ctx { 405068c7a8SSteffen Klassert struct crypto_aead *child; 415068c7a8SSteffen Klassert unsigned int cb_cpu; 425068c7a8SSteffen Klassert }; 435068c7a8SSteffen Klassert 445068c7a8SSteffen Klassert static int pcrypt_do_parallel(struct padata_priv *padata, unsigned int *cb_cpu, 455068c7a8SSteffen Klassert struct padata_instance *pinst) 465068c7a8SSteffen Klassert { 475068c7a8SSteffen Klassert unsigned int cpu_index, cpu, i; 485068c7a8SSteffen Klassert 495068c7a8SSteffen Klassert cpu = *cb_cpu; 505068c7a8SSteffen Klassert 515068c7a8SSteffen Klassert if (cpumask_test_cpu(cpu, cpu_active_mask)) 525068c7a8SSteffen Klassert goto out; 535068c7a8SSteffen Klassert 545068c7a8SSteffen Klassert cpu_index = cpu % cpumask_weight(cpu_active_mask); 555068c7a8SSteffen Klassert 565068c7a8SSteffen Klassert cpu = cpumask_first(cpu_active_mask); 575068c7a8SSteffen Klassert for (i = 0; i < cpu_index; i++) 585068c7a8SSteffen Klassert cpu = cpumask_next(cpu, cpu_active_mask); 595068c7a8SSteffen Klassert 605068c7a8SSteffen Klassert *cb_cpu = cpu; 615068c7a8SSteffen Klassert 625068c7a8SSteffen Klassert out: 635068c7a8SSteffen Klassert return padata_do_parallel(pinst, padata, cpu); 645068c7a8SSteffen Klassert } 655068c7a8SSteffen Klassert 665068c7a8SSteffen Klassert static int pcrypt_aead_setkey(struct crypto_aead *parent, 675068c7a8SSteffen Klassert const u8 *key, unsigned int keylen) 685068c7a8SSteffen Klassert { 695068c7a8SSteffen Klassert struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(parent); 705068c7a8SSteffen Klassert 715068c7a8SSteffen Klassert return crypto_aead_setkey(ctx->child, key, keylen); 725068c7a8SSteffen Klassert } 735068c7a8SSteffen Klassert 745068c7a8SSteffen Klassert static int pcrypt_aead_setauthsize(struct crypto_aead *parent, 755068c7a8SSteffen Klassert unsigned int authsize) 765068c7a8SSteffen Klassert { 775068c7a8SSteffen Klassert struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(parent); 785068c7a8SSteffen Klassert 795068c7a8SSteffen Klassert return crypto_aead_setauthsize(ctx->child, authsize); 805068c7a8SSteffen Klassert } 815068c7a8SSteffen Klassert 825068c7a8SSteffen Klassert static void pcrypt_aead_serial(struct padata_priv *padata) 835068c7a8SSteffen Klassert { 845068c7a8SSteffen Klassert struct pcrypt_request *preq = pcrypt_padata_request(padata); 855068c7a8SSteffen Klassert struct aead_request *req = pcrypt_request_ctx(preq); 865068c7a8SSteffen Klassert 875068c7a8SSteffen Klassert aead_request_complete(req->base.data, padata->info); 885068c7a8SSteffen Klassert } 895068c7a8SSteffen Klassert 905068c7a8SSteffen Klassert static void pcrypt_aead_giv_serial(struct padata_priv *padata) 915068c7a8SSteffen Klassert { 925068c7a8SSteffen Klassert struct pcrypt_request *preq = pcrypt_padata_request(padata); 935068c7a8SSteffen Klassert struct aead_givcrypt_request *req = pcrypt_request_ctx(preq); 945068c7a8SSteffen Klassert 955068c7a8SSteffen Klassert aead_request_complete(req->areq.base.data, padata->info); 965068c7a8SSteffen Klassert } 975068c7a8SSteffen Klassert 985068c7a8SSteffen Klassert static void pcrypt_aead_done(struct crypto_async_request *areq, int err) 995068c7a8SSteffen Klassert { 1005068c7a8SSteffen Klassert struct aead_request *req = areq->data; 1015068c7a8SSteffen Klassert struct pcrypt_request *preq = aead_request_ctx(req); 1025068c7a8SSteffen Klassert struct padata_priv *padata = pcrypt_request_padata(preq); 1035068c7a8SSteffen Klassert 1045068c7a8SSteffen Klassert padata->info = err; 1055068c7a8SSteffen Klassert req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; 1065068c7a8SSteffen Klassert 1075068c7a8SSteffen Klassert padata_do_serial(padata); 1085068c7a8SSteffen Klassert } 1095068c7a8SSteffen Klassert 1105068c7a8SSteffen Klassert static void pcrypt_aead_enc(struct padata_priv *padata) 1115068c7a8SSteffen Klassert { 1125068c7a8SSteffen Klassert struct pcrypt_request *preq = pcrypt_padata_request(padata); 1135068c7a8SSteffen Klassert struct aead_request *req = pcrypt_request_ctx(preq); 1145068c7a8SSteffen Klassert 1155068c7a8SSteffen Klassert padata->info = crypto_aead_encrypt(req); 1165068c7a8SSteffen Klassert 1175068c7a8SSteffen Klassert if (padata->info) 1185068c7a8SSteffen Klassert return; 1195068c7a8SSteffen Klassert 1205068c7a8SSteffen Klassert padata_do_serial(padata); 1215068c7a8SSteffen Klassert } 1225068c7a8SSteffen Klassert 1235068c7a8SSteffen Klassert static int pcrypt_aead_encrypt(struct aead_request *req) 1245068c7a8SSteffen Klassert { 1255068c7a8SSteffen Klassert int err; 1265068c7a8SSteffen Klassert struct pcrypt_request *preq = aead_request_ctx(req); 1275068c7a8SSteffen Klassert struct aead_request *creq = pcrypt_request_ctx(preq); 1285068c7a8SSteffen Klassert struct padata_priv *padata = pcrypt_request_padata(preq); 1295068c7a8SSteffen Klassert struct crypto_aead *aead = crypto_aead_reqtfm(req); 1305068c7a8SSteffen Klassert struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(aead); 1315068c7a8SSteffen Klassert u32 flags = aead_request_flags(req); 1325068c7a8SSteffen Klassert 1335068c7a8SSteffen Klassert memset(padata, 0, sizeof(struct padata_priv)); 1345068c7a8SSteffen Klassert 1355068c7a8SSteffen Klassert padata->parallel = pcrypt_aead_enc; 1365068c7a8SSteffen Klassert padata->serial = pcrypt_aead_serial; 1375068c7a8SSteffen Klassert 1385068c7a8SSteffen Klassert aead_request_set_tfm(creq, ctx->child); 1395068c7a8SSteffen Klassert aead_request_set_callback(creq, flags & ~CRYPTO_TFM_REQ_MAY_SLEEP, 1405068c7a8SSteffen Klassert pcrypt_aead_done, req); 1415068c7a8SSteffen Klassert aead_request_set_crypt(creq, req->src, req->dst, 1425068c7a8SSteffen Klassert req->cryptlen, req->iv); 1435068c7a8SSteffen Klassert aead_request_set_assoc(creq, req->assoc, req->assoclen); 1445068c7a8SSteffen Klassert 1455068c7a8SSteffen Klassert err = pcrypt_do_parallel(padata, &ctx->cb_cpu, pcrypt_enc_padata); 1465068c7a8SSteffen Klassert if (err) 1475068c7a8SSteffen Klassert return err; 1485068c7a8SSteffen Klassert else 1495068c7a8SSteffen Klassert err = crypto_aead_encrypt(creq); 1505068c7a8SSteffen Klassert 1515068c7a8SSteffen Klassert return err; 1525068c7a8SSteffen Klassert } 1535068c7a8SSteffen Klassert 1545068c7a8SSteffen Klassert static void pcrypt_aead_dec(struct padata_priv *padata) 1555068c7a8SSteffen Klassert { 1565068c7a8SSteffen Klassert struct pcrypt_request *preq = pcrypt_padata_request(padata); 1575068c7a8SSteffen Klassert struct aead_request *req = pcrypt_request_ctx(preq); 1585068c7a8SSteffen Klassert 1595068c7a8SSteffen Klassert padata->info = crypto_aead_decrypt(req); 1605068c7a8SSteffen Klassert 1615068c7a8SSteffen Klassert if (padata->info) 1625068c7a8SSteffen Klassert return; 1635068c7a8SSteffen Klassert 1645068c7a8SSteffen Klassert padata_do_serial(padata); 1655068c7a8SSteffen Klassert } 1665068c7a8SSteffen Klassert 1675068c7a8SSteffen Klassert static int pcrypt_aead_decrypt(struct aead_request *req) 1685068c7a8SSteffen Klassert { 1695068c7a8SSteffen Klassert int err; 1705068c7a8SSteffen Klassert struct pcrypt_request *preq = aead_request_ctx(req); 1715068c7a8SSteffen Klassert struct aead_request *creq = pcrypt_request_ctx(preq); 1725068c7a8SSteffen Klassert struct padata_priv *padata = pcrypt_request_padata(preq); 1735068c7a8SSteffen Klassert struct crypto_aead *aead = crypto_aead_reqtfm(req); 1745068c7a8SSteffen Klassert struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(aead); 1755068c7a8SSteffen Klassert u32 flags = aead_request_flags(req); 1765068c7a8SSteffen Klassert 1775068c7a8SSteffen Klassert memset(padata, 0, sizeof(struct padata_priv)); 1785068c7a8SSteffen Klassert 1795068c7a8SSteffen Klassert padata->parallel = pcrypt_aead_dec; 1805068c7a8SSteffen Klassert padata->serial = pcrypt_aead_serial; 1815068c7a8SSteffen Klassert 1825068c7a8SSteffen Klassert aead_request_set_tfm(creq, ctx->child); 1835068c7a8SSteffen Klassert aead_request_set_callback(creq, flags & ~CRYPTO_TFM_REQ_MAY_SLEEP, 1845068c7a8SSteffen Klassert pcrypt_aead_done, req); 1855068c7a8SSteffen Klassert aead_request_set_crypt(creq, req->src, req->dst, 1865068c7a8SSteffen Klassert req->cryptlen, req->iv); 1875068c7a8SSteffen Klassert aead_request_set_assoc(creq, req->assoc, req->assoclen); 1885068c7a8SSteffen Klassert 1895068c7a8SSteffen Klassert err = pcrypt_do_parallel(padata, &ctx->cb_cpu, pcrypt_dec_padata); 1905068c7a8SSteffen Klassert if (err) 1915068c7a8SSteffen Klassert return err; 1925068c7a8SSteffen Klassert else 1935068c7a8SSteffen Klassert err = crypto_aead_decrypt(creq); 1945068c7a8SSteffen Klassert 1955068c7a8SSteffen Klassert return err; 1965068c7a8SSteffen Klassert } 1975068c7a8SSteffen Klassert 1985068c7a8SSteffen Klassert static void pcrypt_aead_givenc(struct padata_priv *padata) 1995068c7a8SSteffen Klassert { 2005068c7a8SSteffen Klassert struct pcrypt_request *preq = pcrypt_padata_request(padata); 2015068c7a8SSteffen Klassert struct aead_givcrypt_request *req = pcrypt_request_ctx(preq); 2025068c7a8SSteffen Klassert 2035068c7a8SSteffen Klassert padata->info = crypto_aead_givencrypt(req); 2045068c7a8SSteffen Klassert 2055068c7a8SSteffen Klassert if (padata->info) 2065068c7a8SSteffen Klassert return; 2075068c7a8SSteffen Klassert 2085068c7a8SSteffen Klassert padata_do_serial(padata); 2095068c7a8SSteffen Klassert } 2105068c7a8SSteffen Klassert 2115068c7a8SSteffen Klassert static int pcrypt_aead_givencrypt(struct aead_givcrypt_request *req) 2125068c7a8SSteffen Klassert { 2135068c7a8SSteffen Klassert int err; 2145068c7a8SSteffen Klassert struct aead_request *areq = &req->areq; 2155068c7a8SSteffen Klassert struct pcrypt_request *preq = aead_request_ctx(areq); 2165068c7a8SSteffen Klassert struct aead_givcrypt_request *creq = pcrypt_request_ctx(preq); 2175068c7a8SSteffen Klassert struct padata_priv *padata = pcrypt_request_padata(preq); 2185068c7a8SSteffen Klassert struct crypto_aead *aead = aead_givcrypt_reqtfm(req); 2195068c7a8SSteffen Klassert struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(aead); 2205068c7a8SSteffen Klassert u32 flags = aead_request_flags(areq); 2215068c7a8SSteffen Klassert 2225068c7a8SSteffen Klassert memset(padata, 0, sizeof(struct padata_priv)); 2235068c7a8SSteffen Klassert 2245068c7a8SSteffen Klassert padata->parallel = pcrypt_aead_givenc; 2255068c7a8SSteffen Klassert padata->serial = pcrypt_aead_giv_serial; 2265068c7a8SSteffen Klassert 2275068c7a8SSteffen Klassert aead_givcrypt_set_tfm(creq, ctx->child); 2285068c7a8SSteffen Klassert aead_givcrypt_set_callback(creq, flags & ~CRYPTO_TFM_REQ_MAY_SLEEP, 2295068c7a8SSteffen Klassert pcrypt_aead_done, areq); 2305068c7a8SSteffen Klassert aead_givcrypt_set_crypt(creq, areq->src, areq->dst, 2315068c7a8SSteffen Klassert areq->cryptlen, areq->iv); 2325068c7a8SSteffen Klassert aead_givcrypt_set_assoc(creq, areq->assoc, areq->assoclen); 2335068c7a8SSteffen Klassert aead_givcrypt_set_giv(creq, req->giv, req->seq); 2345068c7a8SSteffen Klassert 2355068c7a8SSteffen Klassert err = pcrypt_do_parallel(padata, &ctx->cb_cpu, pcrypt_enc_padata); 2365068c7a8SSteffen Klassert if (err) 2375068c7a8SSteffen Klassert return err; 2385068c7a8SSteffen Klassert else 2395068c7a8SSteffen Klassert err = crypto_aead_givencrypt(creq); 2405068c7a8SSteffen Klassert 2415068c7a8SSteffen Klassert return err; 2425068c7a8SSteffen Klassert } 2435068c7a8SSteffen Klassert 2445068c7a8SSteffen Klassert static int pcrypt_aead_init_tfm(struct crypto_tfm *tfm) 2455068c7a8SSteffen Klassert { 2465068c7a8SSteffen Klassert int cpu, cpu_index; 2475068c7a8SSteffen Klassert struct crypto_instance *inst = crypto_tfm_alg_instance(tfm); 2485068c7a8SSteffen Klassert struct pcrypt_instance_ctx *ictx = crypto_instance_ctx(inst); 2495068c7a8SSteffen Klassert struct pcrypt_aead_ctx *ctx = crypto_tfm_ctx(tfm); 2505068c7a8SSteffen Klassert struct crypto_aead *cipher; 2515068c7a8SSteffen Klassert 2525068c7a8SSteffen Klassert ictx->tfm_count++; 2535068c7a8SSteffen Klassert 2545068c7a8SSteffen Klassert cpu_index = ictx->tfm_count % cpumask_weight(cpu_active_mask); 2555068c7a8SSteffen Klassert 2565068c7a8SSteffen Klassert ctx->cb_cpu = cpumask_first(cpu_active_mask); 2575068c7a8SSteffen Klassert for (cpu = 0; cpu < cpu_index; cpu++) 2585068c7a8SSteffen Klassert ctx->cb_cpu = cpumask_next(ctx->cb_cpu, cpu_active_mask); 2595068c7a8SSteffen Klassert 2605068c7a8SSteffen Klassert cipher = crypto_spawn_aead(crypto_instance_ctx(inst)); 2615068c7a8SSteffen Klassert 2625068c7a8SSteffen Klassert if (IS_ERR(cipher)) 2635068c7a8SSteffen Klassert return PTR_ERR(cipher); 2645068c7a8SSteffen Klassert 2655068c7a8SSteffen Klassert ctx->child = cipher; 2665068c7a8SSteffen Klassert tfm->crt_aead.reqsize = sizeof(struct pcrypt_request) 2675068c7a8SSteffen Klassert + sizeof(struct aead_givcrypt_request) 2685068c7a8SSteffen Klassert + crypto_aead_reqsize(cipher); 2695068c7a8SSteffen Klassert 2705068c7a8SSteffen Klassert return 0; 2715068c7a8SSteffen Klassert } 2725068c7a8SSteffen Klassert 2735068c7a8SSteffen Klassert static void pcrypt_aead_exit_tfm(struct crypto_tfm *tfm) 2745068c7a8SSteffen Klassert { 2755068c7a8SSteffen Klassert struct pcrypt_aead_ctx *ctx = crypto_tfm_ctx(tfm); 2765068c7a8SSteffen Klassert 2775068c7a8SSteffen Klassert crypto_free_aead(ctx->child); 2785068c7a8SSteffen Klassert } 2795068c7a8SSteffen Klassert 2805068c7a8SSteffen Klassert static struct crypto_instance *pcrypt_alloc_instance(struct crypto_alg *alg) 2815068c7a8SSteffen Klassert { 2825068c7a8SSteffen Klassert struct crypto_instance *inst; 2835068c7a8SSteffen Klassert struct pcrypt_instance_ctx *ctx; 2845068c7a8SSteffen Klassert int err; 2855068c7a8SSteffen Klassert 2865068c7a8SSteffen Klassert inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); 2875068c7a8SSteffen Klassert if (!inst) { 2885068c7a8SSteffen Klassert inst = ERR_PTR(-ENOMEM); 2895068c7a8SSteffen Klassert goto out; 2905068c7a8SSteffen Klassert } 2915068c7a8SSteffen Klassert 2925068c7a8SSteffen Klassert err = -ENAMETOOLONG; 2935068c7a8SSteffen Klassert if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, 2945068c7a8SSteffen Klassert "pcrypt(%s)", alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) 2955068c7a8SSteffen Klassert goto out_free_inst; 2965068c7a8SSteffen Klassert 2975068c7a8SSteffen Klassert memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); 2985068c7a8SSteffen Klassert 2995068c7a8SSteffen Klassert ctx = crypto_instance_ctx(inst); 3005068c7a8SSteffen Klassert err = crypto_init_spawn(&ctx->spawn, alg, inst, 3015068c7a8SSteffen Klassert CRYPTO_ALG_TYPE_MASK); 3025068c7a8SSteffen Klassert if (err) 3035068c7a8SSteffen Klassert goto out_free_inst; 3045068c7a8SSteffen Klassert 3055068c7a8SSteffen Klassert inst->alg.cra_priority = alg->cra_priority + 100; 3065068c7a8SSteffen Klassert inst->alg.cra_blocksize = alg->cra_blocksize; 3075068c7a8SSteffen Klassert inst->alg.cra_alignmask = alg->cra_alignmask; 3085068c7a8SSteffen Klassert 3095068c7a8SSteffen Klassert out: 3105068c7a8SSteffen Klassert return inst; 3115068c7a8SSteffen Klassert 3125068c7a8SSteffen Klassert out_free_inst: 3135068c7a8SSteffen Klassert kfree(inst); 3145068c7a8SSteffen Klassert inst = ERR_PTR(err); 3155068c7a8SSteffen Klassert goto out; 3165068c7a8SSteffen Klassert } 3175068c7a8SSteffen Klassert 3185068c7a8SSteffen Klassert static struct crypto_instance *pcrypt_alloc_aead(struct rtattr **tb) 3195068c7a8SSteffen Klassert { 3205068c7a8SSteffen Klassert struct crypto_instance *inst; 3215068c7a8SSteffen Klassert struct crypto_alg *alg; 3225068c7a8SSteffen Klassert struct crypto_attr_type *algt; 3235068c7a8SSteffen Klassert 3245068c7a8SSteffen Klassert algt = crypto_get_attr_type(tb); 3255068c7a8SSteffen Klassert 3265068c7a8SSteffen Klassert alg = crypto_get_attr_alg(tb, algt->type, 3275068c7a8SSteffen Klassert (algt->mask & CRYPTO_ALG_TYPE_MASK)); 3285068c7a8SSteffen Klassert if (IS_ERR(alg)) 3295068c7a8SSteffen Klassert return ERR_CAST(alg); 3305068c7a8SSteffen Klassert 3315068c7a8SSteffen Klassert inst = pcrypt_alloc_instance(alg); 3325068c7a8SSteffen Klassert if (IS_ERR(inst)) 3335068c7a8SSteffen Klassert goto out_put_alg; 3345068c7a8SSteffen Klassert 3355068c7a8SSteffen Klassert inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC; 3365068c7a8SSteffen Klassert inst->alg.cra_type = &crypto_aead_type; 3375068c7a8SSteffen Klassert 3385068c7a8SSteffen Klassert inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize; 3395068c7a8SSteffen Klassert inst->alg.cra_aead.geniv = alg->cra_aead.geniv; 3405068c7a8SSteffen Klassert inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize; 3415068c7a8SSteffen Klassert 3425068c7a8SSteffen Klassert inst->alg.cra_ctxsize = sizeof(struct pcrypt_aead_ctx); 3435068c7a8SSteffen Klassert 3445068c7a8SSteffen Klassert inst->alg.cra_init = pcrypt_aead_init_tfm; 3455068c7a8SSteffen Klassert inst->alg.cra_exit = pcrypt_aead_exit_tfm; 3465068c7a8SSteffen Klassert 3475068c7a8SSteffen Klassert inst->alg.cra_aead.setkey = pcrypt_aead_setkey; 3485068c7a8SSteffen Klassert inst->alg.cra_aead.setauthsize = pcrypt_aead_setauthsize; 3495068c7a8SSteffen Klassert inst->alg.cra_aead.encrypt = pcrypt_aead_encrypt; 3505068c7a8SSteffen Klassert inst->alg.cra_aead.decrypt = pcrypt_aead_decrypt; 3515068c7a8SSteffen Klassert inst->alg.cra_aead.givencrypt = pcrypt_aead_givencrypt; 3525068c7a8SSteffen Klassert 3535068c7a8SSteffen Klassert out_put_alg: 3545068c7a8SSteffen Klassert crypto_mod_put(alg); 3555068c7a8SSteffen Klassert return inst; 3565068c7a8SSteffen Klassert } 3575068c7a8SSteffen Klassert 3585068c7a8SSteffen Klassert static struct crypto_instance *pcrypt_alloc(struct rtattr **tb) 3595068c7a8SSteffen Klassert { 3605068c7a8SSteffen Klassert struct crypto_attr_type *algt; 3615068c7a8SSteffen Klassert 3625068c7a8SSteffen Klassert algt = crypto_get_attr_type(tb); 3635068c7a8SSteffen Klassert if (IS_ERR(algt)) 3645068c7a8SSteffen Klassert return ERR_CAST(algt); 3655068c7a8SSteffen Klassert 3665068c7a8SSteffen Klassert switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) { 3675068c7a8SSteffen Klassert case CRYPTO_ALG_TYPE_AEAD: 3685068c7a8SSteffen Klassert return pcrypt_alloc_aead(tb); 3695068c7a8SSteffen Klassert } 3705068c7a8SSteffen Klassert 3715068c7a8SSteffen Klassert return ERR_PTR(-EINVAL); 3725068c7a8SSteffen Klassert } 3735068c7a8SSteffen Klassert 3745068c7a8SSteffen Klassert static void pcrypt_free(struct crypto_instance *inst) 3755068c7a8SSteffen Klassert { 3765068c7a8SSteffen Klassert struct pcrypt_instance_ctx *ctx = crypto_instance_ctx(inst); 3775068c7a8SSteffen Klassert 3785068c7a8SSteffen Klassert crypto_drop_spawn(&ctx->spawn); 3795068c7a8SSteffen Klassert kfree(inst); 3805068c7a8SSteffen Klassert } 3815068c7a8SSteffen Klassert 3825068c7a8SSteffen Klassert static struct crypto_template pcrypt_tmpl = { 3835068c7a8SSteffen Klassert .name = "pcrypt", 3845068c7a8SSteffen Klassert .alloc = pcrypt_alloc, 3855068c7a8SSteffen Klassert .free = pcrypt_free, 3865068c7a8SSteffen Klassert .module = THIS_MODULE, 3875068c7a8SSteffen Klassert }; 3885068c7a8SSteffen Klassert 3895068c7a8SSteffen Klassert static int __init pcrypt_init(void) 3905068c7a8SSteffen Klassert { 3915068c7a8SSteffen Klassert encwq = create_workqueue("pencrypt"); 3925068c7a8SSteffen Klassert if (!encwq) 3935068c7a8SSteffen Klassert goto err; 3945068c7a8SSteffen Klassert 3955068c7a8SSteffen Klassert decwq = create_workqueue("pdecrypt"); 3965068c7a8SSteffen Klassert if (!decwq) 3975068c7a8SSteffen Klassert goto err_destroy_encwq; 3985068c7a8SSteffen Klassert 3995068c7a8SSteffen Klassert 4005068c7a8SSteffen Klassert pcrypt_enc_padata = padata_alloc(cpu_possible_mask, encwq); 4015068c7a8SSteffen Klassert if (!pcrypt_enc_padata) 4025068c7a8SSteffen Klassert goto err_destroy_decwq; 4035068c7a8SSteffen Klassert 4045068c7a8SSteffen Klassert pcrypt_dec_padata = padata_alloc(cpu_possible_mask, decwq); 4055068c7a8SSteffen Klassert if (!pcrypt_dec_padata) 4065068c7a8SSteffen Klassert goto err_free_padata; 4075068c7a8SSteffen Klassert 4085068c7a8SSteffen Klassert padata_start(pcrypt_enc_padata); 4095068c7a8SSteffen Klassert padata_start(pcrypt_dec_padata); 4105068c7a8SSteffen Klassert 4115068c7a8SSteffen Klassert return crypto_register_template(&pcrypt_tmpl); 4125068c7a8SSteffen Klassert 4135068c7a8SSteffen Klassert err_free_padata: 4145068c7a8SSteffen Klassert padata_free(pcrypt_enc_padata); 4155068c7a8SSteffen Klassert 4165068c7a8SSteffen Klassert err_destroy_decwq: 4175068c7a8SSteffen Klassert destroy_workqueue(decwq); 4185068c7a8SSteffen Klassert 4195068c7a8SSteffen Klassert err_destroy_encwq: 4205068c7a8SSteffen Klassert destroy_workqueue(encwq); 4215068c7a8SSteffen Klassert 4225068c7a8SSteffen Klassert err: 4235068c7a8SSteffen Klassert return -ENOMEM; 4245068c7a8SSteffen Klassert } 4255068c7a8SSteffen Klassert 4265068c7a8SSteffen Klassert static void __exit pcrypt_exit(void) 4275068c7a8SSteffen Klassert { 4285068c7a8SSteffen Klassert padata_stop(pcrypt_enc_padata); 4295068c7a8SSteffen Klassert padata_stop(pcrypt_dec_padata); 4305068c7a8SSteffen Klassert 4315068c7a8SSteffen Klassert destroy_workqueue(encwq); 4325068c7a8SSteffen Klassert destroy_workqueue(decwq); 4335068c7a8SSteffen Klassert 4345068c7a8SSteffen Klassert padata_free(pcrypt_enc_padata); 4355068c7a8SSteffen Klassert padata_free(pcrypt_dec_padata); 4365068c7a8SSteffen Klassert 4375068c7a8SSteffen Klassert crypto_unregister_template(&pcrypt_tmpl); 4385068c7a8SSteffen Klassert } 4395068c7a8SSteffen Klassert 4405068c7a8SSteffen Klassert module_init(pcrypt_init); 4415068c7a8SSteffen Klassert module_exit(pcrypt_exit); 4425068c7a8SSteffen Klassert 4435068c7a8SSteffen Klassert MODULE_LICENSE("GPL"); 4445068c7a8SSteffen Klassert MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>"); 4455068c7a8SSteffen Klassert MODULE_DESCRIPTION("Parallel crypto wrapper"); 446