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 19 static 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 27 static 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 35 struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl, 36 struct rtattr **tb, u32 type, u32 mask) 37 { 38 const char *name; 39 struct crypto_aead_spawn *spawn; 40 struct crypto_attr_type *algt; 41 struct aead_instance *inst; 42 struct aead_alg *alg; 43 unsigned int ivsize; 44 unsigned int maxauthsize; 45 int err; 46 47 algt = crypto_get_attr_type(tb); 48 if (IS_ERR(algt)) 49 return ERR_CAST(algt); 50 51 if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) 52 return ERR_PTR(-EINVAL); 53 54 name = crypto_attr_alg_name(tb[1]); 55 if (IS_ERR(name)) 56 return ERR_CAST(name); 57 58 inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); 59 if (!inst) 60 return ERR_PTR(-ENOMEM); 61 62 spawn = aead_instance_ctx(inst); 63 64 /* Ignore async algorithms if necessary. */ 65 mask |= crypto_requires_sync(algt->type, algt->mask); 66 67 crypto_set_aead_spawn(spawn, aead_crypto_instance(inst)); 68 err = crypto_grab_aead(spawn, name, type, mask); 69 if (err) 70 goto err_free_inst; 71 72 alg = crypto_spawn_aead_alg(spawn); 73 74 ivsize = crypto_aead_alg_ivsize(alg); 75 maxauthsize = crypto_aead_alg_maxauthsize(alg); 76 77 err = -EINVAL; 78 if (ivsize < sizeof(u64)) 79 goto err_drop_alg; 80 81 err = -ENAMETOOLONG; 82 if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, 83 "%s(%s)", tmpl->name, alg->base.cra_name) >= 84 CRYPTO_MAX_ALG_NAME) 85 goto err_drop_alg; 86 if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, 87 "%s(%s)", tmpl->name, alg->base.cra_driver_name) >= 88 CRYPTO_MAX_ALG_NAME) 89 goto err_drop_alg; 90 91 inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC; 92 inst->alg.base.cra_priority = alg->base.cra_priority; 93 inst->alg.base.cra_blocksize = alg->base.cra_blocksize; 94 inst->alg.base.cra_alignmask = alg->base.cra_alignmask; 95 inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx); 96 97 inst->alg.setkey = aead_geniv_setkey; 98 inst->alg.setauthsize = aead_geniv_setauthsize; 99 100 inst->alg.ivsize = ivsize; 101 inst->alg.maxauthsize = maxauthsize; 102 103 out: 104 return inst; 105 106 err_drop_alg: 107 crypto_drop_aead(spawn); 108 err_free_inst: 109 kfree(inst); 110 inst = ERR_PTR(err); 111 goto out; 112 } 113 EXPORT_SYMBOL_GPL(aead_geniv_alloc); 114 115 void aead_geniv_free(struct aead_instance *inst) 116 { 117 crypto_drop_aead(aead_instance_ctx(inst)); 118 kfree(inst); 119 } 120 EXPORT_SYMBOL_GPL(aead_geniv_free); 121 122 int aead_init_geniv(struct crypto_aead *aead) 123 { 124 struct aead_geniv_ctx *ctx = crypto_aead_ctx(aead); 125 struct aead_instance *inst = aead_alg_instance(aead); 126 struct crypto_aead *child; 127 int err; 128 129 spin_lock_init(&ctx->lock); 130 131 err = crypto_get_default_rng(); 132 if (err) 133 goto out; 134 135 err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt, 136 crypto_aead_ivsize(aead)); 137 crypto_put_default_rng(); 138 if (err) 139 goto out; 140 141 ctx->sknull = crypto_get_default_null_skcipher(); 142 err = PTR_ERR(ctx->sknull); 143 if (IS_ERR(ctx->sknull)) 144 goto out; 145 146 child = crypto_spawn_aead(aead_instance_ctx(inst)); 147 err = PTR_ERR(child); 148 if (IS_ERR(child)) 149 goto drop_null; 150 151 ctx->child = child; 152 crypto_aead_set_reqsize(aead, crypto_aead_reqsize(child) + 153 sizeof(struct aead_request)); 154 155 err = 0; 156 157 out: 158 return err; 159 160 drop_null: 161 crypto_put_default_null_skcipher(); 162 goto out; 163 } 164 EXPORT_SYMBOL_GPL(aead_init_geniv); 165 166 void aead_exit_geniv(struct crypto_aead *tfm) 167 { 168 struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm); 169 170 crypto_free_aead(ctx->child); 171 crypto_put_default_null_skcipher(); 172 } 173 EXPORT_SYMBOL_GPL(aead_exit_geniv); 174 175 MODULE_LICENSE("GPL"); 176 MODULE_DESCRIPTION("Shared IV generator code"); 177