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