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