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