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