root/crypto/pcrypt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pcrypt_tfm_ictx
  2. pcrypt_aead_setkey
  3. pcrypt_aead_setauthsize
  4. pcrypt_aead_serial
  5. pcrypt_aead_done
  6. pcrypt_aead_enc
  7. pcrypt_aead_encrypt
  8. pcrypt_aead_dec
  9. pcrypt_aead_decrypt
  10. pcrypt_aead_init_tfm
  11. pcrypt_aead_exit_tfm
  12. pcrypt_free
  13. pcrypt_init_instance
  14. pcrypt_create_aead
  15. pcrypt_create
  16. pcrypt_sysfs_add
  17. pcrypt_init_padata
  18. pcrypt_fini_padata
  19. pcrypt_init
  20. pcrypt_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * pcrypt - Parallel crypto wrapper.
   4  *
   5  * Copyright (C) 2009 secunet Security Networks AG
   6  * Copyright (C) 2009 Steffen Klassert <steffen.klassert@secunet.com>
   7  */
   8 
   9 #include <crypto/algapi.h>
  10 #include <crypto/internal/aead.h>
  11 #include <linux/atomic.h>
  12 #include <linux/err.h>
  13 #include <linux/init.h>
  14 #include <linux/module.h>
  15 #include <linux/slab.h>
  16 #include <linux/notifier.h>
  17 #include <linux/kobject.h>
  18 #include <linux/cpu.h>
  19 #include <crypto/pcrypt.h>
  20 
  21 static struct padata_instance *pencrypt;
  22 static struct padata_instance *pdecrypt;
  23 static struct kset           *pcrypt_kset;
  24 
  25 struct pcrypt_instance_ctx {
  26         struct crypto_aead_spawn spawn;
  27         struct padata_shell *psenc;
  28         struct padata_shell *psdec;
  29         atomic_t tfm_count;
  30 };
  31 
  32 struct pcrypt_aead_ctx {
  33         struct crypto_aead *child;
  34         unsigned int cb_cpu;
  35 };
  36 
  37 static inline struct pcrypt_instance_ctx *pcrypt_tfm_ictx(
  38         struct crypto_aead *tfm)
  39 {
  40         return aead_instance_ctx(aead_alg_instance(tfm));
  41 }
  42 
  43 static int pcrypt_aead_setkey(struct crypto_aead *parent,
  44                               const u8 *key, unsigned int keylen)
  45 {
  46         struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(parent);
  47 
  48         return crypto_aead_setkey(ctx->child, key, keylen);
  49 }
  50 
  51 static int pcrypt_aead_setauthsize(struct crypto_aead *parent,
  52                                    unsigned int authsize)
  53 {
  54         struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(parent);
  55 
  56         return crypto_aead_setauthsize(ctx->child, authsize);
  57 }
  58 
  59 static void pcrypt_aead_serial(struct padata_priv *padata)
  60 {
  61         struct pcrypt_request *preq = pcrypt_padata_request(padata);
  62         struct aead_request *req = pcrypt_request_ctx(preq);
  63 
  64         aead_request_complete(req->base.data, padata->info);
  65 }
  66 
  67 static void pcrypt_aead_done(struct crypto_async_request *areq, int err)
  68 {
  69         struct aead_request *req = areq->data;
  70         struct pcrypt_request *preq = aead_request_ctx(req);
  71         struct padata_priv *padata = pcrypt_request_padata(preq);
  72 
  73         padata->info = err;
  74 
  75         padata_do_serial(padata);
  76 }
  77 
  78 static void pcrypt_aead_enc(struct padata_priv *padata)
  79 {
  80         struct pcrypt_request *preq = pcrypt_padata_request(padata);
  81         struct aead_request *req = pcrypt_request_ctx(preq);
  82 
  83         padata->info = crypto_aead_encrypt(req);
  84 
  85         if (padata->info == -EINPROGRESS)
  86                 return;
  87 
  88         padata_do_serial(padata);
  89 }
  90 
  91 static int pcrypt_aead_encrypt(struct aead_request *req)
  92 {
  93         int err;
  94         struct pcrypt_request *preq = aead_request_ctx(req);
  95         struct aead_request *creq = pcrypt_request_ctx(preq);
  96         struct padata_priv *padata = pcrypt_request_padata(preq);
  97         struct crypto_aead *aead = crypto_aead_reqtfm(req);
  98         struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(aead);
  99         u32 flags = aead_request_flags(req);
 100         struct pcrypt_instance_ctx *ictx;
 101 
 102         ictx = pcrypt_tfm_ictx(aead);
 103 
 104         memset(padata, 0, sizeof(struct padata_priv));
 105 
 106         padata->parallel = pcrypt_aead_enc;
 107         padata->serial = pcrypt_aead_serial;
 108 
 109         aead_request_set_tfm(creq, ctx->child);
 110         aead_request_set_callback(creq, flags & ~CRYPTO_TFM_REQ_MAY_SLEEP,
 111                                   pcrypt_aead_done, req);
 112         aead_request_set_crypt(creq, req->src, req->dst,
 113                                req->cryptlen, req->iv);
 114         aead_request_set_ad(creq, req->assoclen);
 115 
 116         err = padata_do_parallel(ictx->psenc, padata, &ctx->cb_cpu);
 117         if (!err)
 118                 return -EINPROGRESS;
 119 
 120         return err;
 121 }
 122 
 123 static void pcrypt_aead_dec(struct padata_priv *padata)
 124 {
 125         struct pcrypt_request *preq = pcrypt_padata_request(padata);
 126         struct aead_request *req = pcrypt_request_ctx(preq);
 127 
 128         padata->info = crypto_aead_decrypt(req);
 129 
 130         if (padata->info == -EINPROGRESS)
 131                 return;
 132 
 133         padata_do_serial(padata);
 134 }
 135 
 136 static int pcrypt_aead_decrypt(struct aead_request *req)
 137 {
 138         int err;
 139         struct pcrypt_request *preq = aead_request_ctx(req);
 140         struct aead_request *creq = pcrypt_request_ctx(preq);
 141         struct padata_priv *padata = pcrypt_request_padata(preq);
 142         struct crypto_aead *aead = crypto_aead_reqtfm(req);
 143         struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(aead);
 144         u32 flags = aead_request_flags(req);
 145         struct pcrypt_instance_ctx *ictx;
 146 
 147         ictx = pcrypt_tfm_ictx(aead);
 148 
 149         memset(padata, 0, sizeof(struct padata_priv));
 150 
 151         padata->parallel = pcrypt_aead_dec;
 152         padata->serial = pcrypt_aead_serial;
 153 
 154         aead_request_set_tfm(creq, ctx->child);
 155         aead_request_set_callback(creq, flags & ~CRYPTO_TFM_REQ_MAY_SLEEP,
 156                                   pcrypt_aead_done, req);
 157         aead_request_set_crypt(creq, req->src, req->dst,
 158                                req->cryptlen, req->iv);
 159         aead_request_set_ad(creq, req->assoclen);
 160 
 161         err = padata_do_parallel(ictx->psdec, padata, &ctx->cb_cpu);
 162         if (!err)
 163                 return -EINPROGRESS;
 164 
 165         return err;
 166 }
 167 
 168 static int pcrypt_aead_init_tfm(struct crypto_aead *tfm)
 169 {
 170         int cpu, cpu_index;
 171         struct aead_instance *inst = aead_alg_instance(tfm);
 172         struct pcrypt_instance_ctx *ictx = aead_instance_ctx(inst);
 173         struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(tfm);
 174         struct crypto_aead *cipher;
 175 
 176         cpu_index = (unsigned int)atomic_inc_return(&ictx->tfm_count) %
 177                     cpumask_weight(cpu_online_mask);
 178 
 179         ctx->cb_cpu = cpumask_first(cpu_online_mask);
 180         for (cpu = 0; cpu < cpu_index; cpu++)
 181                 ctx->cb_cpu = cpumask_next(ctx->cb_cpu, cpu_online_mask);
 182 
 183         cipher = crypto_spawn_aead(&ictx->spawn);
 184 
 185         if (IS_ERR(cipher))
 186                 return PTR_ERR(cipher);
 187 
 188         ctx->child = cipher;
 189         crypto_aead_set_reqsize(tfm, sizeof(struct pcrypt_request) +
 190                                      sizeof(struct aead_request) +
 191                                      crypto_aead_reqsize(cipher));
 192 
 193         return 0;
 194 }
 195 
 196 static void pcrypt_aead_exit_tfm(struct crypto_aead *tfm)
 197 {
 198         struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(tfm);
 199 
 200         crypto_free_aead(ctx->child);
 201 }
 202 
 203 static void pcrypt_free(struct aead_instance *inst)
 204 {
 205         struct pcrypt_instance_ctx *ctx = aead_instance_ctx(inst);
 206 
 207         crypto_drop_aead(&ctx->spawn);
 208         padata_free_shell(ctx->psdec);
 209         padata_free_shell(ctx->psenc);
 210         kfree(inst);
 211 }
 212 
 213 static int pcrypt_init_instance(struct crypto_instance *inst,
 214                                 struct crypto_alg *alg)
 215 {
 216         if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
 217                      "pcrypt(%s)", alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
 218                 return -ENAMETOOLONG;
 219 
 220         memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
 221 
 222         inst->alg.cra_priority = alg->cra_priority + 100;
 223         inst->alg.cra_blocksize = alg->cra_blocksize;
 224         inst->alg.cra_alignmask = alg->cra_alignmask;
 225 
 226         return 0;
 227 }
 228 
 229 static int pcrypt_create_aead(struct crypto_template *tmpl, struct rtattr **tb,
 230                               u32 type, u32 mask)
 231 {
 232         struct pcrypt_instance_ctx *ctx;
 233         struct crypto_attr_type *algt;
 234         struct aead_instance *inst;
 235         struct aead_alg *alg;
 236         const char *name;
 237         int err;
 238 
 239         algt = crypto_get_attr_type(tb);
 240         if (IS_ERR(algt))
 241                 return PTR_ERR(algt);
 242 
 243         name = crypto_attr_alg_name(tb[1]);
 244         if (IS_ERR(name))
 245                 return PTR_ERR(name);
 246 
 247         inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
 248         if (!inst)
 249                 return -ENOMEM;
 250 
 251         err = -ENOMEM;
 252 
 253         ctx = aead_instance_ctx(inst);
 254         ctx->psenc = padata_alloc_shell(pencrypt);
 255         if (!ctx->psenc)
 256                 goto out_free_inst;
 257 
 258         ctx->psdec = padata_alloc_shell(pdecrypt);
 259         if (!ctx->psdec)
 260                 goto out_free_psenc;
 261 
 262         crypto_set_aead_spawn(&ctx->spawn, aead_crypto_instance(inst));
 263 
 264         err = crypto_grab_aead(&ctx->spawn, name, 0, 0);
 265         if (err)
 266                 goto out_free_psdec;
 267 
 268         alg = crypto_spawn_aead_alg(&ctx->spawn);
 269         err = pcrypt_init_instance(aead_crypto_instance(inst), &alg->base);
 270         if (err)
 271                 goto out_drop_aead;
 272 
 273         inst->alg.base.cra_flags = CRYPTO_ALG_ASYNC;
 274 
 275         inst->alg.ivsize = crypto_aead_alg_ivsize(alg);
 276         inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg);
 277 
 278         inst->alg.base.cra_ctxsize = sizeof(struct pcrypt_aead_ctx);
 279 
 280         inst->alg.init = pcrypt_aead_init_tfm;
 281         inst->alg.exit = pcrypt_aead_exit_tfm;
 282 
 283         inst->alg.setkey = pcrypt_aead_setkey;
 284         inst->alg.setauthsize = pcrypt_aead_setauthsize;
 285         inst->alg.encrypt = pcrypt_aead_encrypt;
 286         inst->alg.decrypt = pcrypt_aead_decrypt;
 287 
 288         inst->free = pcrypt_free;
 289 
 290         err = aead_register_instance(tmpl, inst);
 291         if (err)
 292                 goto out_drop_aead;
 293 
 294 out:
 295         return err;
 296 
 297 out_drop_aead:
 298         crypto_drop_aead(&ctx->spawn);
 299 out_free_psdec:
 300         padata_free_shell(ctx->psdec);
 301 out_free_psenc:
 302         padata_free_shell(ctx->psenc);
 303 out_free_inst:
 304         kfree(inst);
 305         goto out;
 306 }
 307 
 308 static int pcrypt_create(struct crypto_template *tmpl, struct rtattr **tb)
 309 {
 310         struct crypto_attr_type *algt;
 311 
 312         algt = crypto_get_attr_type(tb);
 313         if (IS_ERR(algt))
 314                 return PTR_ERR(algt);
 315 
 316         switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) {
 317         case CRYPTO_ALG_TYPE_AEAD:
 318                 return pcrypt_create_aead(tmpl, tb, algt->type, algt->mask);
 319         }
 320 
 321         return -EINVAL;
 322 }
 323 
 324 static int pcrypt_sysfs_add(struct padata_instance *pinst, const char *name)
 325 {
 326         int ret;
 327 
 328         pinst->kobj.kset = pcrypt_kset;
 329         ret = kobject_add(&pinst->kobj, NULL, "%s", name);
 330         if (!ret)
 331                 kobject_uevent(&pinst->kobj, KOBJ_ADD);
 332 
 333         return ret;
 334 }
 335 
 336 static int pcrypt_init_padata(struct padata_instance **pinst, const char *name)
 337 {
 338         int ret = -ENOMEM;
 339 
 340         *pinst = padata_alloc_possible(name);
 341         if (!*pinst)
 342                 return ret;
 343 
 344         ret = pcrypt_sysfs_add(*pinst, name);
 345         if (ret)
 346                 padata_free(*pinst);
 347 
 348         return ret;
 349 }
 350 
 351 static void pcrypt_fini_padata(struct padata_instance *pinst)
 352 {
 353         padata_stop(pinst);
 354         padata_free(pinst);
 355 }
 356 
 357 static struct crypto_template pcrypt_tmpl = {
 358         .name = "pcrypt",
 359         .create = pcrypt_create,
 360         .module = THIS_MODULE,
 361 };
 362 
 363 static int __init pcrypt_init(void)
 364 {
 365         int err = -ENOMEM;
 366 
 367         pcrypt_kset = kset_create_and_add("pcrypt", NULL, kernel_kobj);
 368         if (!pcrypt_kset)
 369                 goto err;
 370 
 371         err = pcrypt_init_padata(&pencrypt, "pencrypt");
 372         if (err)
 373                 goto err_unreg_kset;
 374 
 375         err = pcrypt_init_padata(&pdecrypt, "pdecrypt");
 376         if (err)
 377                 goto err_deinit_pencrypt;
 378 
 379         padata_start(pencrypt);
 380         padata_start(pdecrypt);
 381 
 382         return crypto_register_template(&pcrypt_tmpl);
 383 
 384 err_deinit_pencrypt:
 385         pcrypt_fini_padata(pencrypt);
 386 err_unreg_kset:
 387         kset_unregister(pcrypt_kset);
 388 err:
 389         return err;
 390 }
 391 
 392 static void __exit pcrypt_exit(void)
 393 {
 394         crypto_unregister_template(&pcrypt_tmpl);
 395 
 396         pcrypt_fini_padata(pencrypt);
 397         pcrypt_fini_padata(pdecrypt);
 398 
 399         kset_unregister(pcrypt_kset);
 400 }
 401 
 402 subsys_initcall(pcrypt_init);
 403 module_exit(pcrypt_exit);
 404 
 405 MODULE_LICENSE("GPL");
 406 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
 407 MODULE_DESCRIPTION("Parallel crypto wrapper");
 408 MODULE_ALIAS_CRYPTO("pcrypt");

/* [<][>][^][v][top][bottom][index][help] */