root/crypto/aead.c

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

DEFINITIONS

This source file includes following definitions.
  1. setkey_unaligned
  2. crypto_aead_setkey
  3. crypto_aead_setauthsize
  4. crypto_aead_encrypt
  5. crypto_aead_decrypt
  6. crypto_aead_exit_tfm
  7. crypto_aead_init_tfm
  8. crypto_aead_report
  9. crypto_aead_report
  10. crypto_aead_show
  11. crypto_aead_free_instance
  12. aead_geniv_setkey
  13. aead_geniv_setauthsize
  14. aead_geniv_alloc
  15. aead_geniv_free
  16. aead_init_geniv
  17. aead_exit_geniv
  18. crypto_grab_aead
  19. crypto_alloc_aead
  20. aead_prepare_alg
  21. crypto_register_aead
  22. crypto_unregister_aead
  23. crypto_register_aeads
  24. crypto_unregister_aeads
  25. aead_register_instance

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

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