linux/crypto/geniv.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * geniv: Shared IV generator code
   4 *
   5 * This file provides common code to IV generators such as seqiv.
   6 *
   7 * Copyright (c) 2007-2019 Herbert Xu <herbert@gondor.apana.org.au>
   8 */
   9
  10#include <crypto/internal/geniv.h>
  11#include <crypto/internal/rng.h>
  12#include <crypto/null.h>
  13#include <linux/err.h>
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16#include <linux/rtnetlink.h>
  17#include <linux/slab.h>
  18
  19static int aead_geniv_setkey(struct crypto_aead *tfm,
  20                             const u8 *key, unsigned int keylen)
  21{
  22        struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm);
  23
  24        return crypto_aead_setkey(ctx->child, key, keylen);
  25}
  26
  27static int aead_geniv_setauthsize(struct crypto_aead *tfm,
  28                                  unsigned int authsize)
  29{
  30        struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm);
  31
  32        return crypto_aead_setauthsize(ctx->child, authsize);
  33}
  34
  35static void aead_geniv_free(struct aead_instance *inst)
  36{
  37        crypto_drop_aead(aead_instance_ctx(inst));
  38        kfree(inst);
  39}
  40
  41struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl,
  42                                       struct rtattr **tb)
  43{
  44        struct crypto_aead_spawn *spawn;
  45        struct aead_instance *inst;
  46        struct aead_alg *alg;
  47        unsigned int ivsize;
  48        unsigned int maxauthsize;
  49        u32 mask;
  50        int err;
  51
  52        err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);
  53        if (err)
  54                return ERR_PTR(err);
  55
  56        inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  57        if (!inst)
  58                return ERR_PTR(-ENOMEM);
  59
  60        spawn = aead_instance_ctx(inst);
  61
  62        err = crypto_grab_aead(spawn, aead_crypto_instance(inst),
  63                               crypto_attr_alg_name(tb[1]), 0, mask);
  64        if (err)
  65                goto err_free_inst;
  66
  67        alg = crypto_spawn_aead_alg(spawn);
  68
  69        ivsize = crypto_aead_alg_ivsize(alg);
  70        maxauthsize = crypto_aead_alg_maxauthsize(alg);
  71
  72        err = -EINVAL;
  73        if (ivsize < sizeof(u64))
  74                goto err_free_inst;
  75
  76        err = -ENAMETOOLONG;
  77        if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
  78                     "%s(%s)", tmpl->name, alg->base.cra_name) >=
  79            CRYPTO_MAX_ALG_NAME)
  80                goto err_free_inst;
  81        if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
  82                     "%s(%s)", tmpl->name, alg->base.cra_driver_name) >=
  83            CRYPTO_MAX_ALG_NAME)
  84                goto err_free_inst;
  85
  86        inst->alg.base.cra_priority = alg->base.cra_priority;
  87        inst->alg.base.cra_blocksize = alg->base.cra_blocksize;
  88        inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
  89        inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx);
  90
  91        inst->alg.setkey = aead_geniv_setkey;
  92        inst->alg.setauthsize = aead_geniv_setauthsize;
  93
  94        inst->alg.ivsize = ivsize;
  95        inst->alg.maxauthsize = maxauthsize;
  96
  97        inst->free = aead_geniv_free;
  98
  99out:
 100        return inst;
 101
 102err_free_inst:
 103        aead_geniv_free(inst);
 104        inst = ERR_PTR(err);
 105        goto out;
 106}
 107EXPORT_SYMBOL_GPL(aead_geniv_alloc);
 108
 109int aead_init_geniv(struct crypto_aead *aead)
 110{
 111        struct aead_geniv_ctx *ctx = crypto_aead_ctx(aead);
 112        struct aead_instance *inst = aead_alg_instance(aead);
 113        struct crypto_aead *child;
 114        int err;
 115
 116        spin_lock_init(&ctx->lock);
 117
 118        err = crypto_get_default_rng();
 119        if (err)
 120                goto out;
 121
 122        err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
 123                                   crypto_aead_ivsize(aead));
 124        crypto_put_default_rng();
 125        if (err)
 126                goto out;
 127
 128        ctx->sknull = crypto_get_default_null_skcipher();
 129        err = PTR_ERR(ctx->sknull);
 130        if (IS_ERR(ctx->sknull))
 131                goto out;
 132
 133        child = crypto_spawn_aead(aead_instance_ctx(inst));
 134        err = PTR_ERR(child);
 135        if (IS_ERR(child))
 136                goto drop_null;
 137
 138        ctx->child = child;
 139        crypto_aead_set_reqsize(aead, crypto_aead_reqsize(child) +
 140                                      sizeof(struct aead_request));
 141
 142        err = 0;
 143
 144out:
 145        return err;
 146
 147drop_null:
 148        crypto_put_default_null_skcipher();
 149        goto out;
 150}
 151EXPORT_SYMBOL_GPL(aead_init_geniv);
 152
 153void aead_exit_geniv(struct crypto_aead *tfm)
 154{
 155        struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm);
 156
 157        crypto_free_aead(ctx->child);
 158        crypto_put_default_null_skcipher();
 159}
 160EXPORT_SYMBOL_GPL(aead_exit_geniv);
 161
 162MODULE_LICENSE("GPL");
 163MODULE_DESCRIPTION("Shared IV generator code");
 164