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