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 err = crypto_stdrng_get_bytes(ctx->salt, crypto_aead_ivsize(aead)); 116 if (err) 117 goto out; 118 119 child = crypto_spawn_aead(aead_instance_ctx(inst)); 120 err = PTR_ERR(child); 121 if (IS_ERR(child)) 122 goto out; 123 124 ctx->child = child; 125 crypto_aead_set_reqsize(aead, crypto_aead_reqsize(child) + 126 sizeof(struct aead_request)); 127 128 err = 0; 129 130 out: 131 return err; 132 } 133 EXPORT_SYMBOL_GPL(aead_init_geniv); 134 135 void aead_exit_geniv(struct crypto_aead *tfm) 136 { 137 struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm); 138 139 crypto_free_aead(ctx->child); 140 } 141 EXPORT_SYMBOL_GPL(aead_exit_geniv); 142 143 MODULE_LICENSE("GPL"); 144 MODULE_DESCRIPTION("Shared IV generator code"); 145