linux/crypto/aead.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * AEAD: Authenticated Encryption with Associated Data
   4 *
   5 * This file provides API support for AEAD algorithms.
   6 *
   7 * Copyright (c) 2007-2015 Herbert Xu <herbert@gondor.apana.org.au>
   8 */
   9
  10#include <crypto/internal/geniv.h>
  11#include <crypto/internal/rng.h>
  12#include <crypto/null.h>
  13#include <crypto/scatterwalk.h>
  14#include <linux/err.h>
  15#include <linux/init.h>
  16#include <linux/kernel.h>
  17#include <linux/module.h>
  18#include <linux/rtnetlink.h>
  19#include <linux/slab.h>
  20#include <linux/seq_file.h>
  21#include <linux/cryptouser.h>
  22#include <linux/compiler.h>
  23#include <net/netlink.h>
  24
  25#include "internal.h"
  26
  27static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key,
  28                            unsigned int keylen)
  29{
  30        unsigned long alignmask = crypto_aead_alignmask(tfm);
  31        int ret;
  32        u8 *buffer, *alignbuffer;
  33        unsigned long absize;
  34
  35        absize = keylen + alignmask;
  36        buffer = kmalloc(absize, GFP_ATOMIC);
  37        if (!buffer)
  38                return -ENOMEM;
  39
  40        alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
  41        memcpy(alignbuffer, key, keylen);
  42        ret = crypto_aead_alg(tfm)->setkey(tfm, alignbuffer, keylen);
  43        memset(alignbuffer, 0, keylen);
  44        kfree(buffer);
  45        return ret;
  46}
  47
  48int crypto_aead_setkey(struct crypto_aead *tfm,
  49                       const u8 *key, unsigned int keylen)
  50{
  51        unsigned long alignmask = crypto_aead_alignmask(tfm);
  52        int err;
  53
  54        if ((unsigned long)key & alignmask)
  55                err = setkey_unaligned(tfm, key, keylen);
  56        else
  57                err = crypto_aead_alg(tfm)->setkey(tfm, key, keylen);
  58
  59        if (unlikely(err)) {
  60                crypto_aead_set_flags(tfm, CRYPTO_TFM_NEED_KEY);
  61                return err;
  62        }
  63
  64        crypto_aead_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
  65        return 0;
  66}
  67EXPORT_SYMBOL_GPL(crypto_aead_setkey);
  68
  69int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
  70{
  71        int err;
  72
  73        if (authsize > crypto_aead_maxauthsize(tfm))
  74                return -EINVAL;
  75
  76        if (crypto_aead_alg(tfm)->setauthsize) {
  77                err = crypto_aead_alg(tfm)->setauthsize(tfm, authsize);
  78                if (err)
  79                        return err;
  80        }
  81
  82        tfm->authsize = authsize;
  83        return 0;
  84}
  85EXPORT_SYMBOL_GPL(crypto_aead_setauthsize);
  86
  87int crypto_aead_encrypt(struct aead_request *req)
  88{
  89        struct crypto_aead *aead = crypto_aead_reqtfm(req);
  90        struct crypto_alg *alg = aead->base.__crt_alg;
  91        unsigned int cryptlen = req->cryptlen;
  92        int ret;
  93
  94        crypto_stats_get(alg);
  95        if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
  96                ret = -ENOKEY;
  97        else
  98                ret = crypto_aead_alg(aead)->encrypt(req);
  99        crypto_stats_aead_encrypt(cryptlen, alg, ret);
 100        return ret;
 101}
 102EXPORT_SYMBOL_GPL(crypto_aead_encrypt);
 103
 104int crypto_aead_decrypt(struct aead_request *req)
 105{
 106        struct crypto_aead *aead = crypto_aead_reqtfm(req);
 107        struct crypto_alg *alg = aead->base.__crt_alg;
 108        unsigned int cryptlen = req->cryptlen;
 109        int ret;
 110
 111        crypto_stats_get(alg);
 112        if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
 113                ret = -ENOKEY;
 114        else if (req->cryptlen < crypto_aead_authsize(aead))
 115                ret = -EINVAL;
 116        else
 117                ret = crypto_aead_alg(aead)->decrypt(req);
 118        crypto_stats_aead_decrypt(cryptlen, alg, ret);
 119        return ret;
 120}
 121EXPORT_SYMBOL_GPL(crypto_aead_decrypt);
 122
 123static void crypto_aead_exit_tfm(struct crypto_tfm *tfm)
 124{
 125        struct crypto_aead *aead = __crypto_aead_cast(tfm);
 126        struct aead_alg *alg = crypto_aead_alg(aead);
 127
 128        alg->exit(aead);
 129}
 130
 131static int crypto_aead_init_tfm(struct crypto_tfm *tfm)
 132{
 133        struct crypto_aead *aead = __crypto_aead_cast(tfm);
 134        struct aead_alg *alg = crypto_aead_alg(aead);
 135
 136        crypto_aead_set_flags(aead, CRYPTO_TFM_NEED_KEY);
 137
 138        aead->authsize = alg->maxauthsize;
 139
 140        if (alg->exit)
 141                aead->base.exit = crypto_aead_exit_tfm;
 142
 143        if (alg->init)
 144                return alg->init(aead);
 145
 146        return 0;
 147}
 148
 149#ifdef CONFIG_NET
 150static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
 151{
 152        struct crypto_report_aead raead;
 153        struct aead_alg *aead = container_of(alg, struct aead_alg, base);
 154
 155        memset(&raead, 0, sizeof(raead));
 156
 157        strscpy(raead.type, "aead", sizeof(raead.type));
 158        strscpy(raead.geniv, "<none>", sizeof(raead.geniv));
 159
 160        raead.blocksize = alg->cra_blocksize;
 161        raead.maxauthsize = aead->maxauthsize;
 162        raead.ivsize = aead->ivsize;
 163
 164        return nla_put(skb, CRYPTOCFGA_REPORT_AEAD, sizeof(raead), &raead);
 165}
 166#else
 167static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
 168{
 169        return -ENOSYS;
 170}
 171#endif
 172
 173static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
 174        __maybe_unused;
 175static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
 176{
 177        struct aead_alg *aead = container_of(alg, struct aead_alg, base);
 178
 179        seq_printf(m, "type         : aead\n");
 180        seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
 181                                             "yes" : "no");
 182        seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
 183        seq_printf(m, "ivsize       : %u\n", aead->ivsize);
 184        seq_printf(m, "maxauthsize  : %u\n", aead->maxauthsize);
 185        seq_printf(m, "geniv        : <none>\n");
 186}
 187
 188static void crypto_aead_free_instance(struct crypto_instance *inst)
 189{
 190        struct aead_instance *aead = aead_instance(inst);
 191
 192        if (!aead->free) {
 193                inst->tmpl->free(inst);
 194                return;
 195        }
 196
 197        aead->free(aead);
 198}
 199
 200static const struct crypto_type crypto_aead_type = {
 201        .extsize = crypto_alg_extsize,
 202        .init_tfm = crypto_aead_init_tfm,
 203        .free = crypto_aead_free_instance,
 204#ifdef CONFIG_PROC_FS
 205        .show = crypto_aead_show,
 206#endif
 207        .report = crypto_aead_report,
 208        .maskclear = ~CRYPTO_ALG_TYPE_MASK,
 209        .maskset = CRYPTO_ALG_TYPE_MASK,
 210        .type = CRYPTO_ALG_TYPE_AEAD,
 211        .tfmsize = offsetof(struct crypto_aead, base),
 212};
 213
 214static int aead_geniv_setkey(struct crypto_aead *tfm,
 215                             const u8 *key, unsigned int keylen)
 216{
 217        struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm);
 218
 219        return crypto_aead_setkey(ctx->child, key, keylen);
 220}
 221
 222static int aead_geniv_setauthsize(struct crypto_aead *tfm,
 223                                  unsigned int authsize)
 224{
 225        struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm);
 226
 227        return crypto_aead_setauthsize(ctx->child, authsize);
 228}
 229
 230struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl,
 231                                       struct rtattr **tb, u32 type, u32 mask)
 232{
 233        const char *name;
 234        struct crypto_aead_spawn *spawn;
 235        struct crypto_attr_type *algt;
 236        struct aead_instance *inst;
 237        struct aead_alg *alg;
 238        unsigned int ivsize;
 239        unsigned int maxauthsize;
 240        int err;
 241
 242        algt = crypto_get_attr_type(tb);
 243        if (IS_ERR(algt))
 244                return ERR_CAST(algt);
 245
 246        if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
 247                return ERR_PTR(-EINVAL);
 248
 249        name = crypto_attr_alg_name(tb[1]);
 250        if (IS_ERR(name))
 251                return ERR_CAST(name);
 252
 253        inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
 254        if (!inst)
 255                return ERR_PTR(-ENOMEM);
 256
 257        spawn = aead_instance_ctx(inst);
 258
 259        /* Ignore async algorithms if necessary. */
 260        mask |= crypto_requires_sync(algt->type, algt->mask);
 261
 262        crypto_set_aead_spawn(spawn, aead_crypto_instance(inst));
 263        err = crypto_grab_aead(spawn, name, type, mask);
 264        if (err)
 265                goto err_free_inst;
 266
 267        alg = crypto_spawn_aead_alg(spawn);
 268
 269        ivsize = crypto_aead_alg_ivsize(alg);
 270        maxauthsize = crypto_aead_alg_maxauthsize(alg);
 271
 272        err = -EINVAL;
 273        if (ivsize < sizeof(u64))
 274                goto err_drop_alg;
 275
 276        err = -ENAMETOOLONG;
 277        if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
 278                     "%s(%s)", tmpl->name, alg->base.cra_name) >=
 279            CRYPTO_MAX_ALG_NAME)
 280                goto err_drop_alg;
 281        if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
 282                     "%s(%s)", tmpl->name, alg->base.cra_driver_name) >=
 283            CRYPTO_MAX_ALG_NAME)
 284                goto err_drop_alg;
 285
 286        inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
 287        inst->alg.base.cra_priority = alg->base.cra_priority;
 288        inst->alg.base.cra_blocksize = alg->base.cra_blocksize;
 289        inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
 290        inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx);
 291
 292        inst->alg.setkey = aead_geniv_setkey;
 293        inst->alg.setauthsize = aead_geniv_setauthsize;
 294
 295        inst->alg.ivsize = ivsize;
 296        inst->alg.maxauthsize = maxauthsize;
 297
 298out:
 299        return inst;
 300
 301err_drop_alg:
 302        crypto_drop_aead(spawn);
 303err_free_inst:
 304        kfree(inst);
 305        inst = ERR_PTR(err);
 306        goto out;
 307}
 308EXPORT_SYMBOL_GPL(aead_geniv_alloc);
 309
 310void aead_geniv_free(struct aead_instance *inst)
 311{
 312        crypto_drop_aead(aead_instance_ctx(inst));
 313        kfree(inst);
 314}
 315EXPORT_SYMBOL_GPL(aead_geniv_free);
 316
 317int aead_init_geniv(struct crypto_aead *aead)
 318{
 319        struct aead_geniv_ctx *ctx = crypto_aead_ctx(aead);
 320        struct aead_instance *inst = aead_alg_instance(aead);
 321        struct crypto_aead *child;
 322        int err;
 323
 324        spin_lock_init(&ctx->lock);
 325
 326        err = crypto_get_default_rng();
 327        if (err)
 328                goto out;
 329
 330        err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
 331                                   crypto_aead_ivsize(aead));
 332        crypto_put_default_rng();
 333        if (err)
 334                goto out;
 335
 336        ctx->sknull = crypto_get_default_null_skcipher();
 337        err = PTR_ERR(ctx->sknull);
 338        if (IS_ERR(ctx->sknull))
 339                goto out;
 340
 341        child = crypto_spawn_aead(aead_instance_ctx(inst));
 342        err = PTR_ERR(child);
 343        if (IS_ERR(child))
 344                goto drop_null;
 345
 346        ctx->child = child;
 347        crypto_aead_set_reqsize(aead, crypto_aead_reqsize(child) +
 348                                      sizeof(struct aead_request));
 349
 350        err = 0;
 351
 352out:
 353        return err;
 354
 355drop_null:
 356        crypto_put_default_null_skcipher();
 357        goto out;
 358}
 359EXPORT_SYMBOL_GPL(aead_init_geniv);
 360
 361void aead_exit_geniv(struct crypto_aead *tfm)
 362{
 363        struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm);
 364
 365        crypto_free_aead(ctx->child);
 366        crypto_put_default_null_skcipher();
 367}
 368EXPORT_SYMBOL_GPL(aead_exit_geniv);
 369
 370int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
 371                     u32 type, u32 mask)
 372{
 373        spawn->base.frontend = &crypto_aead_type;
 374        return crypto_grab_spawn(&spawn->base, name, type, mask);
 375}
 376EXPORT_SYMBOL_GPL(crypto_grab_aead);
 377
 378struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask)
 379{
 380        return crypto_alloc_tfm(alg_name, &crypto_aead_type, type, mask);
 381}
 382EXPORT_SYMBOL_GPL(crypto_alloc_aead);
 383
 384static int aead_prepare_alg(struct aead_alg *alg)
 385{
 386        struct crypto_alg *base = &alg->base;
 387
 388        if (max3(alg->maxauthsize, alg->ivsize, alg->chunksize) >
 389            PAGE_SIZE / 8)
 390                return -EINVAL;
 391
 392        if (!alg->chunksize)
 393                alg->chunksize = base->cra_blocksize;
 394
 395        base->cra_type = &crypto_aead_type;
 396        base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
 397        base->cra_flags |= CRYPTO_ALG_TYPE_AEAD;
 398
 399        return 0;
 400}
 401
 402int crypto_register_aead(struct aead_alg *alg)
 403{
 404        struct crypto_alg *base = &alg->base;
 405        int err;
 406
 407        err = aead_prepare_alg(alg);
 408        if (err)
 409                return err;
 410
 411        return crypto_register_alg(base);
 412}
 413EXPORT_SYMBOL_GPL(crypto_register_aead);
 414
 415void crypto_unregister_aead(struct aead_alg *alg)
 416{
 417        crypto_unregister_alg(&alg->base);
 418}
 419EXPORT_SYMBOL_GPL(crypto_unregister_aead);
 420
 421int crypto_register_aeads(struct aead_alg *algs, int count)
 422{
 423        int i, ret;
 424
 425        for (i = 0; i < count; i++) {
 426                ret = crypto_register_aead(&algs[i]);
 427                if (ret)
 428                        goto err;
 429        }
 430
 431        return 0;
 432
 433err:
 434        for (--i; i >= 0; --i)
 435                crypto_unregister_aead(&algs[i]);
 436
 437        return ret;
 438}
 439EXPORT_SYMBOL_GPL(crypto_register_aeads);
 440
 441void crypto_unregister_aeads(struct aead_alg *algs, int count)
 442{
 443        int i;
 444
 445        for (i = count - 1; i >= 0; --i)
 446                crypto_unregister_aead(&algs[i]);
 447}
 448EXPORT_SYMBOL_GPL(crypto_unregister_aeads);
 449
 450int aead_register_instance(struct crypto_template *tmpl,
 451                           struct aead_instance *inst)
 452{
 453        int err;
 454
 455        err = aead_prepare_alg(&inst->alg);
 456        if (err)
 457                return err;
 458
 459        return crypto_register_instance(tmpl, aead_crypto_instance(inst));
 460}
 461EXPORT_SYMBOL_GPL(aead_register_instance);
 462
 463MODULE_LICENSE("GPL");
 464MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");
 465