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