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