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