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        if (IS_ERR(algt))
 285                return ERR_CAST(algt);
 286
 287        if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) &
 288            algt->mask)
 289                return ERR_PTR(-EINVAL);
 290
 291        name = crypto_attr_alg_name(tb[1]);
 292        if (IS_ERR(name))
 293                return ERR_CAST(name);
 294
 295        inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
 296        if (!inst)
 297                return ERR_PTR(-ENOMEM);
 298
 299        spawn = crypto_instance_ctx(inst);
 300
 301        /* Ignore async algorithms if necessary. */
 302        mask |= crypto_requires_sync(algt->type, algt->mask);
 303
 304        crypto_set_aead_spawn(spawn, inst);
 305        err = crypto_grab_nivaead(spawn, name, type, mask);
 306        if (err)
 307                goto err_free_inst;
 308
 309        alg = crypto_aead_spawn_alg(spawn);
 310
 311        err = -EINVAL;
 312        if (!alg->cra_aead.ivsize)
 313                goto err_drop_alg;
 314
 315        /*
 316         * This is only true if we're constructing an algorithm with its
 317         * default IV generator.  For the default generator we elide the
 318         * template name and double-check the IV generator.
 319         */
 320        if (algt->mask & CRYPTO_ALG_GENIV) {
 321                if (strcmp(tmpl->name, alg->cra_aead.geniv))
 322                        goto err_drop_alg;
 323
 324                memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
 325                memcpy(inst->alg.cra_driver_name, alg->cra_driver_name,
 326                       CRYPTO_MAX_ALG_NAME);
 327        } else {
 328                err = -ENAMETOOLONG;
 329                if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
 330                             "%s(%s)", tmpl->name, alg->cra_name) >=
 331                    CRYPTO_MAX_ALG_NAME)
 332                        goto err_drop_alg;
 333                if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
 334                             "%s(%s)", tmpl->name, alg->cra_driver_name) >=
 335                    CRYPTO_MAX_ALG_NAME)
 336                        goto err_drop_alg;
 337        }
 338
 339        inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV;
 340        inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
 341        inst->alg.cra_priority = alg->cra_priority;
 342        inst->alg.cra_blocksize = alg->cra_blocksize;
 343        inst->alg.cra_alignmask = alg->cra_alignmask;
 344        inst->alg.cra_type = &crypto_aead_type;
 345
 346        inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize;
 347        inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize;
 348        inst->alg.cra_aead.geniv = alg->cra_aead.geniv;
 349
 350        inst->alg.cra_aead.setkey = alg->cra_aead.setkey;
 351        inst->alg.cra_aead.setauthsize = alg->cra_aead.setauthsize;
 352        inst->alg.cra_aead.encrypt = alg->cra_aead.encrypt;
 353        inst->alg.cra_aead.decrypt = alg->cra_aead.decrypt;
 354
 355out:
 356        return inst;
 357
 358err_drop_alg:
 359        crypto_drop_aead(spawn);
 360err_free_inst:
 361        kfree(inst);
 362        inst = ERR_PTR(err);
 363        goto out;
 364}
 365EXPORT_SYMBOL_GPL(aead_geniv_alloc);
 366
 367void aead_geniv_free(struct crypto_instance *inst)
 368{
 369        crypto_drop_aead(crypto_instance_ctx(inst));
 370        kfree(inst);
 371}
 372EXPORT_SYMBOL_GPL(aead_geniv_free);
 373
 374int aead_geniv_init(struct crypto_tfm *tfm)
 375{
 376        struct crypto_instance *inst = (void *)tfm->__crt_alg;
 377        struct crypto_aead *aead;
 378
 379        aead = crypto_spawn_aead(crypto_instance_ctx(inst));
 380        if (IS_ERR(aead))
 381                return PTR_ERR(aead);
 382
 383        tfm->crt_aead.base = aead;
 384        tfm->crt_aead.reqsize += crypto_aead_reqsize(aead);
 385
 386        return 0;
 387}
 388EXPORT_SYMBOL_GPL(aead_geniv_init);
 389
 390void aead_geniv_exit(struct crypto_tfm *tfm)
 391{
 392        crypto_free_aead(tfm->crt_aead.base);
 393}
 394EXPORT_SYMBOL_GPL(aead_geniv_exit);
 395
 396static int crypto_nivaead_default(struct crypto_alg *alg, u32 type, u32 mask)
 397{
 398        struct rtattr *tb[3];
 399        struct {
 400                struct rtattr attr;
 401                struct crypto_attr_type data;
 402        } ptype;
 403        struct {
 404                struct rtattr attr;
 405                struct crypto_attr_alg data;
 406        } palg;
 407        struct crypto_template *tmpl;
 408        struct crypto_instance *inst;
 409        struct crypto_alg *larval;
 410        const char *geniv;
 411        int err;
 412
 413        larval = crypto_larval_lookup(alg->cra_driver_name,
 414                                      CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV,
 415                                      CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 416        err = PTR_ERR(larval);
 417        if (IS_ERR(larval))
 418                goto out;
 419
 420        err = -EAGAIN;
 421        if (!crypto_is_larval(larval))
 422                goto drop_larval;
 423
 424        ptype.attr.rta_len = sizeof(ptype);
 425        ptype.attr.rta_type = CRYPTOA_TYPE;
 426        ptype.data.type = type | CRYPTO_ALG_GENIV;
 427        /* GENIV tells the template that we're making a default geniv. */
 428        ptype.data.mask = mask | CRYPTO_ALG_GENIV;
 429        tb[0] = &ptype.attr;
 430
 431        palg.attr.rta_len = sizeof(palg);
 432        palg.attr.rta_type = CRYPTOA_ALG;
 433        /* Must use the exact name to locate ourselves. */
 434        memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME);
 435        tb[1] = &palg.attr;
 436
 437        tb[2] = NULL;
 438
 439        geniv = alg->cra_aead.geniv;
 440
 441        tmpl = crypto_lookup_template(geniv);
 442        err = -ENOENT;
 443        if (!tmpl)
 444                goto kill_larval;
 445
 446        inst = tmpl->alloc(tb);
 447        err = PTR_ERR(inst);
 448        if (IS_ERR(inst))
 449                goto put_tmpl;
 450
 451        if ((err = crypto_register_instance(tmpl, inst))) {
 452                tmpl->free(inst);
 453                goto put_tmpl;
 454        }
 455
 456        /* Redo the lookup to use the instance we just registered. */
 457        err = -EAGAIN;
 458
 459put_tmpl:
 460        crypto_tmpl_put(tmpl);
 461kill_larval:
 462        crypto_larval_kill(larval);
 463drop_larval:
 464        crypto_mod_put(larval);
 465out:
 466        crypto_mod_put(alg);
 467        return err;
 468}
 469
 470struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask)
 471{
 472        struct crypto_alg *alg;
 473
 474        alg = crypto_alg_mod_lookup(name, type, mask);
 475        if (IS_ERR(alg))
 476                return alg;
 477
 478        if (alg->cra_type == &crypto_aead_type)
 479                return alg;
 480
 481        if (!alg->cra_aead.ivsize)
 482                return alg;
 483
 484        crypto_mod_put(alg);
 485        alg = crypto_alg_mod_lookup(name, type | CRYPTO_ALG_TESTED,
 486                                    mask & ~CRYPTO_ALG_TESTED);
 487        if (IS_ERR(alg))
 488                return alg;
 489
 490        if (alg->cra_type == &crypto_aead_type) {
 491                if ((alg->cra_flags ^ type ^ ~mask) & CRYPTO_ALG_TESTED) {
 492                        crypto_mod_put(alg);
 493                        alg = ERR_PTR(-ENOENT);
 494                }
 495                return alg;
 496        }
 497
 498        BUG_ON(!alg->cra_aead.ivsize);
 499
 500        return ERR_PTR(crypto_nivaead_default(alg, type, mask));
 501}
 502EXPORT_SYMBOL_GPL(crypto_lookup_aead);
 503
 504int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
 505                     u32 type, u32 mask)
 506{
 507        struct crypto_alg *alg;
 508        int err;
 509
 510        type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 511        type |= CRYPTO_ALG_TYPE_AEAD;
 512        mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 513        mask |= CRYPTO_ALG_TYPE_MASK;
 514
 515        alg = crypto_lookup_aead(name, type, mask);
 516        if (IS_ERR(alg))
 517                return PTR_ERR(alg);
 518
 519        err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
 520        crypto_mod_put(alg);
 521        return err;
 522}
 523EXPORT_SYMBOL_GPL(crypto_grab_aead);
 524
 525struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask)
 526{
 527        struct crypto_tfm *tfm;
 528        int err;
 529
 530        type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 531        type |= CRYPTO_ALG_TYPE_AEAD;
 532        mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
 533        mask |= CRYPTO_ALG_TYPE_MASK;
 534
 535        for (;;) {
 536                struct crypto_alg *alg;
 537
 538                alg = crypto_lookup_aead(alg_name, type, mask);
 539                if (IS_ERR(alg)) {
 540                        err = PTR_ERR(alg);
 541                        goto err;
 542                }
 543
 544                tfm = __crypto_alloc_tfm(alg, type, mask);
 545                if (!IS_ERR(tfm))
 546                        return __crypto_aead_cast(tfm);
 547
 548                crypto_mod_put(alg);
 549                err = PTR_ERR(tfm);
 550
 551err:
 552                if (err != -EAGAIN)
 553                        break;
 554                if (signal_pending(current)) {
 555                        err = -EINTR;
 556                        break;
 557                }
 558        }
 559
 560        return ERR_PTR(err);
 561}
 562EXPORT_SYMBOL_GPL(crypto_alloc_aead);
 563
 564MODULE_LICENSE("GPL");
 565MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");
 566
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.