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        strncpy(raead.type, "aead", sizeof(raead.type));
 121        strncpy(raead.geniv, aead->geniv ?: "<built-in>", sizeof(raead.geniv));
 122
 123        raead.blocksize = alg->cra_blocksize;
 124        raead.maxauthsize = aead->maxauthsize;
 125        raead.ivsize = aead->ivsize;
 126
 127        if (nla_put(skb, CRYPTOCFGA_REPORT_AEAD,
 128                    sizeof(struct crypto_report_aead), &raead))
 129                goto nla_put_failure;
 130        return 0;
 131
 132nla_put_failure:
 133        return -EMSGSIZE;
 134}
 135#else
 136static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
 137{
 138        return -ENOSYS;
 139}
 140#endif
 141
 142static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
 143        __attribute__ ((unused));
 144static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
 145{
 146        struct aead_alg *aead = &alg->cra_aead;
 147
 148        seq_printf(m, "type         : aead\n");
 149        seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
 150                                             "yes" : "no");
 151        seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
 152        seq_printf(m, "ivsize       : %u\n", aead->ivsize);
 153        seq_printf(m, "maxauthsize  : %u\n", aead->maxauthsize);
 154        seq_printf(m, "geniv        : %s\n", aead->geniv ?: "<built-in>");
 155}
 156
 157const struct crypto_type crypto_aead_type = {
 158        .ctxsize = crypto_aead_ctxsize,
 159        .init = crypto_init_aead_ops,
 160#ifdef CONFIG_PROC_FS
 161        .show = crypto_aead_show,
 162#endif
 163        .report = crypto_aead_report,
 164};
 165EXPORT_SYMBOL_GPL(crypto_aead_type);
 166
 167static int aead_null_givencrypt(struct aead_givcrypt_request *req)
 168{
 169        return crypto_aead_encrypt(&req->areq);
 170}
 171
 172static int aead_null_givdecrypt(struct aead_givcrypt_request *req)
 173{
 174        return crypto_aead_decrypt(&req->areq);
 175}
 176
 177static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 178{
 179        struct aead_alg *alg = &tfm->__crt_alg->cra_aead;
 180        struct aead_tfm *crt = &tfm->crt_aead;
 181
 182        if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
 183                return -EINVAL;
 184
 185        crt->setkey = setkey;
 186        crt->encrypt = alg->encrypt;
 187        crt->decrypt = alg->decrypt;
 188        if (!alg->ivsize) {
 189                crt->givencrypt = aead_null_givencrypt;
 190                crt->givdecrypt = aead_null_givdecrypt;
 191        }
 192        crt->base = __crypto_aead_cast(tfm);
 193        crt->ivsize = alg->ivsize;
 194        crt->authsize = alg->maxauthsize;
 195
 196        return 0;
 197}
 198
 199#ifdef CONFIG_NET
 200static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
 201{
 202        struct crypto_report_aead raead;
 203        struct aead_alg *aead = &alg->cra_aead;
 204
 205        strncpy(raead.type, "nivaead", sizeof(raead.type));
 206        strncpy(raead.geniv, aead->geniv, sizeof(raead.geniv));
 207
 208        raead.blocksize = alg->cra_blocksize;
 209        raead.maxauthsize = aead->maxauthsize;
 210        raead.ivsize = aead->ivsize;
 211
 212        if (nla_put(skb, CRYPTOCFGA_REPORT_AEAD,
 213                    sizeof(struct crypto_report_aead), &raead))
 214                goto nla_put_failure;
 215        return 0;
 216
 217nla_put_failure:
 218        return -EMSGSIZE;
 219}
 220#else
 221static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
 222{
 223        return -ENOSYS;
 224}
 225#endif
 226
 227
 228static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
 229        __attribute__ ((unused));
 230static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
 231{
 232        struct aead_alg *aead = &alg->cra_aead;
 233
 234        seq_printf(m, "type         : nivaead\n");
 235        seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
 236                                             "yes" : "no");
 237        seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
 238        seq_printf(m, "ivsize       : %u\n", aead->ivsize);
 239        seq_printf(m, "maxauthsize  : %u\n", aead->maxauthsize);
 240        seq_printf(m, "geniv        : %s\n", aead->geniv);
 241}
 242
 243const struct crypto_type crypto_nivaead_type = {
 244        .ctxsize = crypto_aead_ctxsize,
 245        .init = crypto_init_nivaead_ops,
 246#ifdef CONFIG_PROC_FS
 247        .show = crypto_nivaead_show,
 248#endif
 249        .report = crypto_nivaead_report,
 250};
 251EXPORT_SYMBOL_GPL(crypto_nivaead_type);
 252
 253static int crypto_grab_nivaead(struct crypto_aead_spawn *spawn,
 254                               const char *name, u32 type, u32 mask)
 255{
 256        struct crypto_alg *alg;
 257        int err;
 258
 259        type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 260        type |= CRYPTO_ALG_TYPE_AEAD;
 261        mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV;
 262
 263        alg = crypto_alg_mod_lookup(name, type, mask);
 264        if (IS_ERR(alg))
 265                return PTR_ERR(alg);
 266
 267        err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
 268        crypto_mod_put(alg);
 269        return err;
 270}
 271
 272struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl,
 273                                         struct rtattr **tb, u32 type,
 274                                         u32 mask)
 275{
 276        const char *name;
 277        struct crypto_aead_spawn *spawn;
 278        struct crypto_attr_type *algt;
 279        struct crypto_instance *inst;
 280        struct crypto_alg *alg;
 281        int err;
 282
 283        algt = crypto_get_attr_type(tb);
 284        err = PTR_ERR(algt);
 285        if (IS_ERR(algt))
 286                return ERR_PTR(err);
 287
 288        if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) &
 289            algt->mask)
 290                return ERR_PTR(-EINVAL);
 291
 292        name = crypto_attr_alg_name(tb[1]);
 293        err = PTR_ERR(name);
 294        if (IS_ERR(name))
 295                return ERR_PTR(err);
 296
 297        inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
 298        if (!inst)
 299                return ERR_PTR(-ENOMEM);
 300
 301        spawn = crypto_instance_ctx(inst);
 302
 303        /* Ignore async algorithms if necessary. */
 304        mask |= crypto_requires_sync(algt->type, algt->mask);
 305
 306        crypto_set_aead_spawn(spawn, inst);
 307        err = crypto_grab_nivaead(spawn, name, type, mask);
 308        if (err)
 309                goto err_free_inst;
 310
 311        alg = crypto_aead_spawn_alg(spawn);
 312
 313        err = -EINVAL;
 314        if (!alg->cra_aead.ivsize)
 315                goto err_drop_alg;
 316
 317        /*
 318         * This is only true if we're constructing an algorithm with its
 319         * default IV generator.  For the default generator we elide the
 320         * template name and double-check the IV generator.
 321         */
 322        if (algt->mask & CRYPTO_ALG_GENIV) {
 323                if (strcmp(tmpl->name, alg->cra_aead.geniv))
 324                        goto err_drop_alg;
 325
 326                memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
 327                memcpy(inst->alg.cra_driver_name, alg->cra_driver_name,
 328                       CRYPTO_MAX_ALG_NAME);
 329        } else {
 330                err = -ENAMETOOLONG;
 331                if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
 332                             "%s(%s)", tmpl->name, alg->cra_name) >=
 333                    CRYPTO_MAX_ALG_NAME)
 334                        goto err_drop_alg;
 335                if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
 336                             "%s(%s)", tmpl->name, alg->cra_driver_name) >=
 337                    CRYPTO_MAX_ALG_NAME)
 338                        goto err_drop_alg;
 339        }
 340
 341        inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV;
 342        inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
 343        inst->alg.cra_priority = alg->cra_priority;
 344        inst->alg.cra_blocksize = alg->cra_blocksize;
 345        inst->alg.cra_alignmask = alg->cra_alignmask;
 346        inst->alg.cra_type = &crypto_aead_type;
 347
 348        inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize;
 349        inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize;
 350        inst->alg.cra_aead.geniv = alg->cra_aead.geniv;
 351
 352        inst->alg.cra_aead.setkey = alg->cra_aead.setkey;
 353        inst->alg.cra_aead.setauthsize = alg->cra_aead.setauthsize;
 354        inst->alg.cra_aead.encrypt = alg->cra_aead.encrypt;
 355        inst->alg.cra_aead.decrypt = alg->cra_aead.decrypt;
 356
 357out:
 358        return inst;
 359
 360err_drop_alg:
 361        crypto_drop_aead(spawn);
 362err_free_inst:
 363        kfree(inst);
 364        inst = ERR_PTR(err);
 365        goto out;
 366}
 367EXPORT_SYMBOL_GPL(aead_geniv_alloc);
 368
 369void aead_geniv_free(struct crypto_instance *inst)
 370{
 371        crypto_drop_aead(crypto_instance_ctx(inst));
 372        kfree(inst);
 373}
 374EXPORT_SYMBOL_GPL(aead_geniv_free);
 375
 376int aead_geniv_init(struct crypto_tfm *tfm)
 377{
 378        struct crypto_instance *inst = (void *)tfm->__crt_alg;
 379        struct crypto_aead *aead;
 380
 381        aead = crypto_spawn_aead(crypto_instance_ctx(inst));
 382        if (IS_ERR(aead))
 383                return PTR_ERR(aead);
 384
 385        tfm->crt_aead.base = aead;
 386        tfm->crt_aead.reqsize += crypto_aead_reqsize(aead);
 387
 388        return 0;
 389}
 390EXPORT_SYMBOL_GPL(aead_geniv_init);
 391
 392void aead_geniv_exit(struct crypto_tfm *tfm)
 393{
 394        crypto_free_aead(tfm->crt_aead.base);
 395}
 396EXPORT_SYMBOL_GPL(aead_geniv_exit);
 397
 398static int crypto_nivaead_default(struct crypto_alg *alg, u32 type, u32 mask)
 399{
 400        struct rtattr *tb[3];
 401        struct {
 402                struct rtattr attr;
 403                struct crypto_attr_type data;
 404        } ptype;
 405        struct {
 406                struct rtattr attr;
 407                struct crypto_attr_alg data;
 408        } palg;
 409        struct crypto_template *tmpl;
 410        struct crypto_instance *inst;
 411        struct crypto_alg *larval;
 412        const char *geniv;
 413        int err;
 414
 415        larval = crypto_larval_lookup(alg->cra_driver_name,
 416                                      CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV,
 417                                      CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 418        err = PTR_ERR(larval);
 419        if (IS_ERR(larval))
 420                goto out;
 421
 422        err = -EAGAIN;
 423        if (!crypto_is_larval(larval))
 424                goto drop_larval;
 425
 426        ptype.attr.rta_len = sizeof(ptype);
 427        ptype.attr.rta_type = CRYPTOA_TYPE;
 428        ptype.data.type = type | CRYPTO_ALG_GENIV;
 429        /* GENIV tells the template that we're making a default geniv. */
 430        ptype.data.mask = mask | CRYPTO_ALG_GENIV;
 431        tb[0] = &ptype.attr;
 432
 433        palg.attr.rta_len = sizeof(palg);
 434        palg.attr.rta_type = CRYPTOA_ALG;
 435        /* Must use the exact name to locate ourselves. */
 436        memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME);
 437        tb[1] = &palg.attr;
 438
 439        tb[2] = NULL;
 440
 441        geniv = alg->cra_aead.geniv;
 442
 443        tmpl = crypto_lookup_template(geniv);
 444        err = -ENOENT;
 445        if (!tmpl)
 446                goto kill_larval;
 447
 448        inst = tmpl->alloc(tb);
 449        err = PTR_ERR(inst);
 450        if (IS_ERR(inst))
 451                goto put_tmpl;
 452
 453        if ((err = crypto_register_instance(tmpl, inst))) {
 454                tmpl->free(inst);
 455                goto put_tmpl;
 456        }
 457
 458        /* Redo the lookup to use the instance we just registered. */
 459        err = -EAGAIN;
 460
 461put_tmpl:
 462        crypto_tmpl_put(tmpl);
 463kill_larval:
 464        crypto_larval_kill(larval);
 465drop_larval:
 466        crypto_mod_put(larval);
 467out:
 468        crypto_mod_put(alg);
 469        return err;
 470}
 471
 472struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask)
 473{
 474        struct crypto_alg *alg;
 475
 476        alg = crypto_alg_mod_lookup(name, type, mask);
 477        if (IS_ERR(alg))
 478                return alg;
 479
 480        if (alg->cra_type == &crypto_aead_type)
 481                return alg;
 482
 483        if (!alg->cra_aead.ivsize)
 484                return alg;
 485
 486        crypto_mod_put(alg);
 487        alg = crypto_alg_mod_lookup(name, type | CRYPTO_ALG_TESTED,
 488                                    mask & ~CRYPTO_ALG_TESTED);
 489        if (IS_ERR(alg))
 490                return alg;
 491
 492        if (alg->cra_type == &crypto_aead_type) {
 493                if ((alg->cra_flags ^ type ^ ~mask) & CRYPTO_ALG_TESTED) {
 494                        crypto_mod_put(alg);
 495                        alg = ERR_PTR(-ENOENT);
 496                }
 497                return alg;
 498        }
 499
 500        BUG_ON(!alg->cra_aead.ivsize);
 501
 502        return ERR_PTR(crypto_nivaead_default(alg, type, mask));
 503}
 504EXPORT_SYMBOL_GPL(crypto_lookup_aead);
 505
 506int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
 507                     u32 type, u32 mask)
 508{
 509        struct crypto_alg *alg;
 510        int err;
 511
 512        type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 513        type |= CRYPTO_ALG_TYPE_AEAD;
 514        mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 515        mask |= CRYPTO_ALG_TYPE_MASK;
 516
 517        alg = crypto_lookup_aead(name, type, mask);
 518        if (IS_ERR(alg))
 519                return PTR_ERR(alg);
 520
 521        err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
 522        crypto_mod_put(alg);
 523        return err;
 524}
 525EXPORT_SYMBOL_GPL(crypto_grab_aead);
 526
 527struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask)
 528{
 529        struct crypto_tfm *tfm;
 530        int err;
 531
 532        type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 533        type |= CRYPTO_ALG_TYPE_AEAD;
 534        mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 535        mask |= CRYPTO_ALG_TYPE_MASK;
 536
 537        for (;;) {
 538                struct crypto_alg *alg;
 539
 540                alg = crypto_lookup_aead(alg_name, type, mask);
 541                if (IS_ERR(alg)) {
 542                        err = PTR_ERR(alg);
 543                        goto err;
 544                }
 545
 546                tfm = __crypto_alloc_tfm(alg, type, mask);
 547                if (!IS_ERR(tfm))
 548                        return __crypto_aead_cast(tfm);
 549
 550                crypto_mod_put(alg);
 551                err = PTR_ERR(tfm);
 552
 553err:
 554                if (err != -EAGAIN)
 555                        break;
 556                if (signal_pending(current)) {
 557                        err = -EINTR;
 558                        break;
 559                }
 560        }
 561
 562        return ERR_PTR(err);
 563}
 564EXPORT_SYMBOL_GPL(crypto_alloc_aead);
 565
 566MODULE_LICENSE("GPL");
 567MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");
 568
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.