linux/crypto/aead.c
<<
>>
Prefs
   1/*
   2 * AEAD: Authenticated Encryption with Associated Data
   3 *
   4 * This file provides API support for AEAD algorithms.
   5 *
   6 * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
   7 *
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms of the GNU General Public License as published by the Free
  10 * Software Foundation; either version 2 of the License, or (at your option)
  11 * any later version.
  12 *
  13 */
  14
  15#include <crypto/internal/aead.h>
  16#include <linux/err.h>
  17#include <linux/init.h>
  18#include <linux/kernel.h>
  19#include <linux/module.h>
  20#include <linux/rtnetlink.h>
  21#include <linux/sched.h>
  22#include <linux/slab.h>
  23#include <linux/seq_file.h>
  24#include <linux/cryptouser.h>
  25#include <net/netlink.h>
  26
  27#include "internal.h"
  28
  29static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key,
  30                            unsigned int keylen)
  31{
  32        struct aead_alg *aead = crypto_aead_alg(tfm);
  33        unsigned long alignmask = crypto_aead_alignmask(tfm);
  34        int ret;
  35        u8 *buffer, *alignbuffer;
  36        unsigned long absize;
  37
  38        absize = keylen + alignmask;
  39        buffer = kmalloc(absize, GFP_ATOMIC);
  40        if (!buffer)
  41                return -ENOMEM;
  42
  43        alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
  44        memcpy(alignbuffer, key, keylen);
  45        ret = aead->setkey(tfm, alignbuffer, keylen);
  46        memset(alignbuffer, 0, keylen);
  47        kfree(buffer);
  48        return ret;
  49}
  50
  51static int setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
  52{
  53        struct aead_alg *aead = crypto_aead_alg(tfm);
  54        unsigned long alignmask = crypto_aead_alignmask(tfm);
  55
  56        if ((unsigned long)key & alignmask)
  57                return setkey_unaligned(tfm, key, keylen);
  58
  59        return aead->setkey(tfm, key, keylen);
  60}
  61
  62int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
  63{
  64        struct aead_tfm *crt = crypto_aead_crt(tfm);
  65        int err;
  66
  67        if (authsize > crypto_aead_alg(tfm)->maxauthsize)
  68                return -EINVAL;
  69
  70        if (crypto_aead_alg(tfm)->setauthsize) {
  71                err = crypto_aead_alg(tfm)->setauthsize(crt->base, authsize);
  72                if (err)
  73                        return err;
  74        }
  75
  76        crypto_aead_crt(crt->base)->authsize = authsize;
  77        crt->authsize = authsize;
  78        return 0;
  79}
  80EXPORT_SYMBOL_GPL(crypto_aead_setauthsize);
  81
  82static unsigned int crypto_aead_ctxsize(struct crypto_alg *alg, u32 type,
  83                                        u32 mask)
  84{
  85        return alg->cra_ctxsize;
  86}
  87
  88static int no_givcrypt(struct aead_givcrypt_request *req)
  89{
  90        return -ENOSYS;
  91}
  92
  93static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
  94{
  95        struct aead_alg *alg = &tfm->__crt_alg->cra_aead;
  96        struct aead_tfm *crt = &tfm->crt_aead;
  97
  98        if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
  99                return -EINVAL;
 100
 101        crt->setkey = tfm->__crt_alg->cra_flags & CRYPTO_ALG_GENIV ?
 102                      alg->setkey : setkey;
 103        crt->encrypt = alg->encrypt;
 104        crt->decrypt = alg->decrypt;
 105        crt->givencrypt = alg->givencrypt ?: no_givcrypt;
 106        crt->givdecrypt = alg->givdecrypt ?: no_givcrypt;
 107        crt->base = __crypto_aead_cast(tfm);
 108        crt->ivsize = alg->ivsize;
 109        crt->authsize = alg->maxauthsize;
 110
 111        return 0;
 112}
 113
 114#ifdef CONFIG_NET
 115static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
 116{
 117        struct crypto_report_aead raead;
 118        struct aead_alg *aead = &alg->cra_aead;
 119
 120        snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "aead");
 121        snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s",
 122                 aead->geniv ?: "<built-in>");
 123
 124        raead.blocksize = alg->cra_blocksize;
 125        raead.maxauthsize = aead->maxauthsize;
 126        raead.ivsize = aead->ivsize;
 127
 128        if (nla_put(skb, CRYPTOCFGA_REPORT_AEAD,
 129                    sizeof(struct crypto_report_aead), &raead))
 130                goto nla_put_failure;
 131        return 0;
 132
 133nla_put_failure:
 134        return -EMSGSIZE;
 135}
 136#else
 137static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
 138{
 139        return -ENOSYS;
 140}
 141#endif
 142
 143static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
 144        __attribute__ ((unused));
 145static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
 146{
 147        struct aead_alg *aead = &alg->cra_aead;
 148
 149        seq_printf(m, "type         : aead\n");
 150        seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
 151                                             "yes" : "no");
 152        seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
 153        seq_printf(m, "ivsize       : %u\n", aead->ivsize);
 154        seq_printf(m, "maxauthsize  : %u\n", aead->maxauthsize);
 155        seq_printf(m, "geniv        : %s\n", aead->geniv ?: "<built-in>");
 156}
 157
 158const struct crypto_type crypto_aead_type = {
 159        .ctxsize = crypto_aead_ctxsize,
 160        .init = crypto_init_aead_ops,
 161#ifdef CONFIG_PROC_FS
 162        .show = crypto_aead_show,
 163#endif
 164        .report = crypto_aead_report,
 165};
 166EXPORT_SYMBOL_GPL(crypto_aead_type);
 167
 168static int aead_null_givencrypt(struct aead_givcrypt_request *req)
 169{
 170        return crypto_aead_encrypt(&req->areq);
 171}
 172
 173static int aead_null_givdecrypt(struct aead_givcrypt_request *req)
 174{
 175        return crypto_aead_decrypt(&req->areq);
 176}
 177
 178static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 179{
 180        struct aead_alg *alg = &tfm->__crt_alg->cra_aead;
 181        struct aead_tfm *crt = &tfm->crt_aead;
 182
 183        if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
 184                return -EINVAL;
 185
 186        crt->setkey = setkey;
 187        crt->encrypt = alg->encrypt;
 188        crt->decrypt = alg->decrypt;
 189        if (!alg->ivsize) {
 190                crt->givencrypt = aead_null_givencrypt;
 191                crt->givdecrypt = aead_null_givdecrypt;
 192        }
 193        crt->base = __crypto_aead_cast(tfm);
 194        crt->ivsize = alg->ivsize;
 195        crt->authsize = alg->maxauthsize;
 196
 197        return 0;
 198}
 199
 200#ifdef CONFIG_NET
 201static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
 202{
 203        struct crypto_report_aead raead;
 204        struct aead_alg *aead = &alg->cra_aead;
 205
 206        snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "nivaead");
 207        snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", aead->geniv);
 208
 209        raead.blocksize = alg->cra_blocksize;
 210        raead.maxauthsize = aead->maxauthsize;
 211        raead.ivsize = aead->ivsize;
 212
 213        if (nla_put(skb, CRYPTOCFGA_REPORT_AEAD,
 214                    sizeof(struct crypto_report_aead), &raead))
 215                goto nla_put_failure;
 216        return 0;
 217
 218nla_put_failure:
 219        return -EMSGSIZE;
 220}
 221#else
 222static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
 223{
 224        return -ENOSYS;
 225}
 226#endif
 227
 228
 229static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
 230        __attribute__ ((unused));
 231static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
 232{
 233        struct aead_alg *aead = &alg->cra_aead;
 234
 235        seq_printf(m, "type         : nivaead\n");
 236        seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
 237                                             "yes" : "no");
 238        seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
 239        seq_printf(m, "ivsize       : %u\n", aead->ivsize);
 240        seq_printf(m, "maxauthsize  : %u\n", aead->maxauthsize);
 241        seq_printf(m, "geniv        : %s\n", aead->geniv);
 242}
 243
 244const struct crypto_type crypto_nivaead_type = {
 245        .ctxsize = crypto_aead_ctxsize,
 246        .init = crypto_init_nivaead_ops,
 247#ifdef CONFIG_PROC_FS
 248        .show = crypto_nivaead_show,
 249#endif
 250        .report = crypto_nivaead_report,
 251};
 252EXPORT_SYMBOL_GPL(crypto_nivaead_type);
 253
 254static int crypto_grab_nivaead(struct crypto_aead_spawn *spawn,
 255                               const char *name, u32 type, u32 mask)
 256{
 257        struct crypto_alg *alg;
 258        int err;
 259
 260        type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 261        type |= CRYPTO_ALG_TYPE_AEAD;
 262        mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV;
 263
 264        alg = crypto_alg_mod_lookup(name, type, mask);
 265        if (IS_ERR(alg))
 266                return PTR_ERR(alg);
 267
 268        err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
 269        crypto_mod_put(alg);
 270        return err;
 271}
 272
 273struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl,
 274                                         struct rtattr **tb, u32 type,
 275                                         u32 mask)
 276{
 277        const char *name;
 278        struct crypto_aead_spawn *spawn;
 279        struct crypto_attr_type *algt;
 280        struct crypto_instance *inst;
 281        struct crypto_alg *alg;
 282        int err;
 283
 284        algt = crypto_get_attr_type(tb);
 285        err = PTR_ERR(algt);
 286        if (IS_ERR(algt))
 287                return ERR_PTR(err);
 288
 289        if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) &
 290            algt->mask)
 291                return ERR_PTR(-EINVAL);
 292
 293        name = crypto_attr_alg_name(tb[1]);
 294        err = PTR_ERR(name);
 295        if (IS_ERR(name))
 296                return ERR_PTR(err);
 297
 298        inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
 299        if (!inst)
 300                return ERR_PTR(-ENOMEM);
 301
 302        spawn = crypto_instance_ctx(inst);
 303
 304        /* Ignore async algorithms if necessary. */
 305        mask |= crypto_requires_sync(algt->type, algt->mask);
 306
 307        crypto_set_aead_spawn(spawn, inst);
 308        err = crypto_grab_nivaead(spawn, name, type, mask);
 309        if (err)
 310                goto err_free_inst;
 311
 312        alg = crypto_aead_spawn_alg(spawn);
 313
 314        err = -EINVAL;
 315        if (!alg->cra_aead.ivsize)
 316                goto err_drop_alg;
 317
 318        /*
 319         * This is only true if we're constructing an algorithm with its
 320         * default IV generator.  For the default generator we elide the
 321         * template name and double-check the IV generator.
 322         */
 323        if (algt->mask & CRYPTO_ALG_GENIV) {
 324                if (strcmp(tmpl->name, alg->cra_aead.geniv))
 325                        goto err_drop_alg;
 326
 327                memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
 328                memcpy(inst->alg.cra_driver_name, alg->cra_driver_name,
 329                       CRYPTO_MAX_ALG_NAME);
 330        } else {
 331                err = -ENAMETOOLONG;
 332                if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
 333                             "%s(%s)", tmpl->name, alg->cra_name) >=
 334                    CRYPTO_MAX_ALG_NAME)
 335                        goto err_drop_alg;
 336                if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
 337                             "%s(%s)", tmpl->name, alg->cra_driver_name) >=
 338                    CRYPTO_MAX_ALG_NAME)
 339                        goto err_drop_alg;
 340        }
 341
 342        inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV;
 343        inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
 344        inst->alg.cra_priority = alg->cra_priority;
 345        inst->alg.cra_blocksize = alg->cra_blocksize;
 346        inst->alg.cra_alignmask = alg->cra_alignmask;
 347        inst->alg.cra_type = &crypto_aead_type;
 348
 349        inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize;
 350        inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize;
 351        inst->alg.cra_aead.geniv = alg->cra_aead.geniv;
 352
 353        inst->alg.cra_aead.setkey = alg->cra_aead.setkey;
 354        inst->alg.cra_aead.setauthsize = alg->cra_aead.setauthsize;
 355        inst->alg.cra_aead.encrypt = alg->cra_aead.encrypt;
 356        inst->alg.cra_aead.decrypt = alg->cra_aead.decrypt;
 357
 358out:
 359        return inst;
 360
 361err_drop_alg:
 362        crypto_drop_aead(spawn);
 363err_free_inst:
 364        kfree(inst);
 365        inst = ERR_PTR(err);
 366        goto out;
 367}
 368EXPORT_SYMBOL_GPL(aead_geniv_alloc);
 369
 370void aead_geniv_free(struct crypto_instance *inst)
 371{
 372        crypto_drop_aead(crypto_instance_ctx(inst));
 373        kfree(inst);
 374}
 375EXPORT_SYMBOL_GPL(aead_geniv_free);
 376
 377int aead_geniv_init(struct crypto_tfm *tfm)
 378{
 379        struct crypto_instance *inst = (void *)tfm->__crt_alg;
 380        struct crypto_aead *aead;
 381
 382        aead = crypto_spawn_aead(crypto_instance_ctx(inst));
 383        if (IS_ERR(aead))
 384                return PTR_ERR(aead);
 385
 386        tfm->crt_aead.base = aead;
 387        tfm->crt_aead.reqsize += crypto_aead_reqsize(aead);
 388
 389        return 0;
 390}
 391EXPORT_SYMBOL_GPL(aead_geniv_init);
 392
 393void aead_geniv_exit(struct crypto_tfm *tfm)
 394{
 395        crypto_free_aead(tfm->crt_aead.base);
 396}
 397EXPORT_SYMBOL_GPL(aead_geniv_exit);
 398
 399static int crypto_nivaead_default(struct crypto_alg *alg, u32 type, u32 mask)
 400{
 401        struct rtattr *tb[3];
 402        struct {
 403                struct rtattr attr;
 404                struct crypto_attr_type data;
 405        } ptype;
 406        struct {
 407                struct rtattr attr;
 408                struct crypto_attr_alg data;
 409        } palg;
 410        struct crypto_template *tmpl;
 411        struct crypto_instance *inst;
 412        struct crypto_alg *larval;
 413        const char *geniv;
 414        int err;
 415
 416        larval = crypto_larval_lookup(alg->cra_driver_name,
 417                                      CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV,
 418                                      CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 419        err = PTR_ERR(larval);
 420        if (IS_ERR(larval))
 421                goto out;
 422
 423        err = -EAGAIN;
 424        if (!crypto_is_larval(larval))
 425                goto drop_larval;
 426
 427        ptype.attr.rta_len = sizeof(ptype);
 428        ptype.attr.rta_type = CRYPTOA_TYPE;
 429        ptype.data.type = type | CRYPTO_ALG_GENIV;
 430        /* GENIV tells the template that we're making a default geniv. */
 431        ptype.data.mask = mask | CRYPTO_ALG_GENIV;
 432        tb[0] = &ptype.attr;
 433
 434        palg.attr.rta_len = sizeof(palg);
 435        palg.attr.rta_type = CRYPTOA_ALG;
 436        /* Must use the exact name to locate ourselves. */
 437        memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME);
 438        tb[1] = &palg.attr;
 439
 440        tb[2] = NULL;
 441
 442        geniv = alg->cra_aead.geniv;
 443
 444        tmpl = crypto_lookup_template(geniv);
 445        err = -ENOENT;
 446        if (!tmpl)
 447                goto kill_larval;
 448
 449        inst = tmpl->alloc(tb);
 450        err = PTR_ERR(inst);
 451        if (IS_ERR(inst))
 452                goto put_tmpl;
 453
 454        if ((err = crypto_register_instance(tmpl, inst))) {
 455                tmpl->free(inst);
 456                goto put_tmpl;
 457        }
 458
 459        /* Redo the lookup to use the instance we just registered. */
 460        err = -EAGAIN;
 461
 462put_tmpl:
 463        crypto_tmpl_put(tmpl);
 464kill_larval:
 465        crypto_larval_kill(larval);
 466drop_larval:
 467        crypto_mod_put(larval);
 468out:
 469        crypto_mod_put(alg);
 470        return err;
 471}
 472
 473struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask)
 474{
 475        struct crypto_alg *alg;
 476
 477        alg = crypto_alg_mod_lookup(name, type, mask);
 478        if (IS_ERR(alg))
 479                return alg;
 480
 481        if (alg->cra_type == &crypto_aead_type)
 482                return alg;
 483
 484        if (!alg->cra_aead.ivsize)
 485                return alg;
 486
 487        crypto_mod_put(alg);
 488        alg = crypto_alg_mod_lookup(name, type | CRYPTO_ALG_TESTED,
 489                                    mask & ~CRYPTO_ALG_TESTED);
 490        if (IS_ERR(alg))
 491                return alg;
 492
 493        if (alg->cra_type == &crypto_aead_type) {
 494                if ((alg->cra_flags ^ type ^ ~mask) & CRYPTO_ALG_TESTED) {
 495                        crypto_mod_put(alg);
 496                        alg = ERR_PTR(-ENOENT);
 497                }
 498                return alg;
 499        }
 500
 501        BUG_ON(!alg->cra_aead.ivsize);
 502
 503        return ERR_PTR(crypto_nivaead_default(alg, type, mask));
 504}
 505EXPORT_SYMBOL_GPL(crypto_lookup_aead);
 506
 507int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
 508                     u32 type, u32 mask)
 509{
 510        struct crypto_alg *alg;
 511        int err;
 512
 513        type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 514        type |= CRYPTO_ALG_TYPE_AEAD;
 515        mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 516        mask |= CRYPTO_ALG_TYPE_MASK;
 517
 518        alg = crypto_lookup_aead(name, type, mask);
 519        if (IS_ERR(alg))
 520                return PTR_ERR(alg);
 521
 522        err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
 523        crypto_mod_put(alg);
 524        return err;
 525}
 526EXPORT_SYMBOL_GPL(crypto_grab_aead);
 527
 528struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask)
 529{
 530        struct crypto_tfm *tfm;
 531        int err;
 532
 533        type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 534        type |= CRYPTO_ALG_TYPE_AEAD;
 535        mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 536        mask |= CRYPTO_ALG_TYPE_MASK;
 537
 538        for (;;) {
 539                struct crypto_alg *alg;
 540
 541                alg = crypto_lookup_aead(alg_name, type, mask);
 542                if (IS_ERR(alg)) {
 543                        err = PTR_ERR(alg);
 544                        goto err;
 545                }
 546
 547                tfm = __crypto_alloc_tfm(alg, type, mask);
 548                if (!IS_ERR(tfm))
 549                        return __crypto_aead_cast(tfm);
 550
 551                crypto_mod_put(alg);
 552                err = PTR_ERR(tfm);
 553
 554err:
 555                if (err != -EAGAIN)
 556                        break;
 557                if (signal_pending(current)) {
 558                        err = -EINTR;
 559                        break;
 560                }
 561        }
 562
 563        return ERR_PTR(err);
 564}
 565EXPORT_SYMBOL_GPL(crypto_alloc_aead);
 566
 567MODULE_LICENSE("GPL");
 568MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");
 569
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.