120cc01baSHerbert Xu // SPDX-License-Identifier: GPL-2.0-or-later 220cc01baSHerbert Xu /* 320cc01baSHerbert Xu * geniv: Shared IV generator code 420cc01baSHerbert Xu * 520cc01baSHerbert Xu * This file provides common code to IV generators such as seqiv. 620cc01baSHerbert Xu * 720cc01baSHerbert Xu * Copyright (c) 2007-2019 Herbert Xu <herbert@gondor.apana.org.au> 820cc01baSHerbert Xu */ 920cc01baSHerbert Xu 1020cc01baSHerbert Xu #include <crypto/internal/geniv.h> 1120cc01baSHerbert Xu #include <crypto/internal/rng.h> 1220cc01baSHerbert Xu #include <crypto/null.h> 1320cc01baSHerbert Xu #include <linux/err.h> 1420cc01baSHerbert Xu #include <linux/kernel.h> 1520cc01baSHerbert Xu #include <linux/module.h> 1620cc01baSHerbert Xu #include <linux/rtnetlink.h> 1720cc01baSHerbert Xu #include <linux/slab.h> 1820cc01baSHerbert Xu 1920cc01baSHerbert Xu static int aead_geniv_setkey(struct crypto_aead *tfm, 2020cc01baSHerbert Xu const u8 *key, unsigned int keylen) 2120cc01baSHerbert Xu { 2220cc01baSHerbert Xu struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm); 2320cc01baSHerbert Xu 2420cc01baSHerbert Xu return crypto_aead_setkey(ctx->child, key, keylen); 2520cc01baSHerbert Xu } 2620cc01baSHerbert Xu 2720cc01baSHerbert Xu static int aead_geniv_setauthsize(struct crypto_aead *tfm, 2820cc01baSHerbert Xu unsigned int authsize) 2920cc01baSHerbert Xu { 3020cc01baSHerbert Xu struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm); 3120cc01baSHerbert Xu 3220cc01baSHerbert Xu return crypto_aead_setauthsize(ctx->child, authsize); 3320cc01baSHerbert Xu } 3420cc01baSHerbert Xu 350f8f6d86SEric Biggers static void aead_geniv_free(struct aead_instance *inst) 360f8f6d86SEric Biggers { 370f8f6d86SEric Biggers crypto_drop_aead(aead_instance_ctx(inst)); 380f8f6d86SEric Biggers kfree(inst); 390f8f6d86SEric Biggers } 400f8f6d86SEric Biggers 4120cc01baSHerbert Xu struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl, 42e72b48c5SEric Biggers struct rtattr **tb) 4320cc01baSHerbert Xu { 4420cc01baSHerbert Xu struct crypto_aead_spawn *spawn; 4520cc01baSHerbert Xu struct aead_instance *inst; 4620cc01baSHerbert Xu struct aead_alg *alg; 4720cc01baSHerbert Xu unsigned int ivsize; 4820cc01baSHerbert Xu unsigned int maxauthsize; 49e72b48c5SEric Biggers u32 mask; 5020cc01baSHerbert Xu int err; 5120cc01baSHerbert Xu 52*7bcb2c99SEric Biggers err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask); 53*7bcb2c99SEric Biggers if (err) 54*7bcb2c99SEric Biggers return ERR_PTR(err); 5520cc01baSHerbert Xu 5620cc01baSHerbert Xu inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); 5720cc01baSHerbert Xu if (!inst) 5820cc01baSHerbert Xu return ERR_PTR(-ENOMEM); 5920cc01baSHerbert Xu 6020cc01baSHerbert Xu spawn = aead_instance_ctx(inst); 6120cc01baSHerbert Xu 62cd900f0cSEric Biggers err = crypto_grab_aead(spawn, aead_crypto_instance(inst), 63e72b48c5SEric Biggers crypto_attr_alg_name(tb[1]), 0, mask); 6420cc01baSHerbert Xu if (err) 6520cc01baSHerbert Xu goto err_free_inst; 6620cc01baSHerbert Xu 6720cc01baSHerbert Xu alg = crypto_spawn_aead_alg(spawn); 6820cc01baSHerbert Xu 6920cc01baSHerbert Xu ivsize = crypto_aead_alg_ivsize(alg); 7020cc01baSHerbert Xu maxauthsize = crypto_aead_alg_maxauthsize(alg); 7120cc01baSHerbert Xu 7220cc01baSHerbert Xu err = -EINVAL; 7320cc01baSHerbert Xu if (ivsize < sizeof(u64)) 74376ffe1aSEric Biggers goto err_free_inst; 7520cc01baSHerbert Xu 7620cc01baSHerbert Xu err = -ENAMETOOLONG; 7720cc01baSHerbert Xu if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, 7820cc01baSHerbert Xu "%s(%s)", tmpl->name, alg->base.cra_name) >= 7920cc01baSHerbert Xu CRYPTO_MAX_ALG_NAME) 80376ffe1aSEric Biggers goto err_free_inst; 8120cc01baSHerbert Xu if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, 8220cc01baSHerbert Xu "%s(%s)", tmpl->name, alg->base.cra_driver_name) >= 8320cc01baSHerbert Xu CRYPTO_MAX_ALG_NAME) 84376ffe1aSEric Biggers goto err_free_inst; 8520cc01baSHerbert Xu 8620cc01baSHerbert Xu inst->alg.base.cra_priority = alg->base.cra_priority; 8720cc01baSHerbert Xu inst->alg.base.cra_blocksize = alg->base.cra_blocksize; 8820cc01baSHerbert Xu inst->alg.base.cra_alignmask = alg->base.cra_alignmask; 8920cc01baSHerbert Xu inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx); 9020cc01baSHerbert Xu 9120cc01baSHerbert Xu inst->alg.setkey = aead_geniv_setkey; 9220cc01baSHerbert Xu inst->alg.setauthsize = aead_geniv_setauthsize; 9320cc01baSHerbert Xu 9420cc01baSHerbert Xu inst->alg.ivsize = ivsize; 9520cc01baSHerbert Xu inst->alg.maxauthsize = maxauthsize; 9620cc01baSHerbert Xu 970f8f6d86SEric Biggers inst->free = aead_geniv_free; 980f8f6d86SEric Biggers 9920cc01baSHerbert Xu out: 10020cc01baSHerbert Xu return inst; 10120cc01baSHerbert Xu 10220cc01baSHerbert Xu err_free_inst: 103376ffe1aSEric Biggers aead_geniv_free(inst); 10420cc01baSHerbert Xu inst = ERR_PTR(err); 10520cc01baSHerbert Xu goto out; 10620cc01baSHerbert Xu } 10720cc01baSHerbert Xu EXPORT_SYMBOL_GPL(aead_geniv_alloc); 10820cc01baSHerbert Xu 10920cc01baSHerbert Xu int aead_init_geniv(struct crypto_aead *aead) 11020cc01baSHerbert Xu { 11120cc01baSHerbert Xu struct aead_geniv_ctx *ctx = crypto_aead_ctx(aead); 11220cc01baSHerbert Xu struct aead_instance *inst = aead_alg_instance(aead); 11320cc01baSHerbert Xu struct crypto_aead *child; 11420cc01baSHerbert Xu int err; 11520cc01baSHerbert Xu 11620cc01baSHerbert Xu spin_lock_init(&ctx->lock); 11720cc01baSHerbert Xu 11820cc01baSHerbert Xu err = crypto_get_default_rng(); 11920cc01baSHerbert Xu if (err) 12020cc01baSHerbert Xu goto out; 12120cc01baSHerbert Xu 12220cc01baSHerbert Xu err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt, 12320cc01baSHerbert Xu crypto_aead_ivsize(aead)); 12420cc01baSHerbert Xu crypto_put_default_rng(); 12520cc01baSHerbert Xu if (err) 12620cc01baSHerbert Xu goto out; 12720cc01baSHerbert Xu 12820cc01baSHerbert Xu ctx->sknull = crypto_get_default_null_skcipher(); 12920cc01baSHerbert Xu err = PTR_ERR(ctx->sknull); 13020cc01baSHerbert Xu if (IS_ERR(ctx->sknull)) 13120cc01baSHerbert Xu goto out; 13220cc01baSHerbert Xu 13320cc01baSHerbert Xu child = crypto_spawn_aead(aead_instance_ctx(inst)); 13420cc01baSHerbert Xu err = PTR_ERR(child); 13520cc01baSHerbert Xu if (IS_ERR(child)) 13620cc01baSHerbert Xu goto drop_null; 13720cc01baSHerbert Xu 13820cc01baSHerbert Xu ctx->child = child; 13920cc01baSHerbert Xu crypto_aead_set_reqsize(aead, crypto_aead_reqsize(child) + 14020cc01baSHerbert Xu sizeof(struct aead_request)); 14120cc01baSHerbert Xu 14220cc01baSHerbert Xu err = 0; 14320cc01baSHerbert Xu 14420cc01baSHerbert Xu out: 14520cc01baSHerbert Xu return err; 14620cc01baSHerbert Xu 14720cc01baSHerbert Xu drop_null: 14820cc01baSHerbert Xu crypto_put_default_null_skcipher(); 14920cc01baSHerbert Xu goto out; 15020cc01baSHerbert Xu } 15120cc01baSHerbert Xu EXPORT_SYMBOL_GPL(aead_init_geniv); 15220cc01baSHerbert Xu 15320cc01baSHerbert Xu void aead_exit_geniv(struct crypto_aead *tfm) 15420cc01baSHerbert Xu { 15520cc01baSHerbert Xu struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm); 15620cc01baSHerbert Xu 15720cc01baSHerbert Xu crypto_free_aead(ctx->child); 15820cc01baSHerbert Xu crypto_put_default_null_skcipher(); 15920cc01baSHerbert Xu } 16020cc01baSHerbert Xu EXPORT_SYMBOL_GPL(aead_exit_geniv); 16120cc01baSHerbert Xu 16220cc01baSHerbert Xu MODULE_LICENSE("GPL"); 16320cc01baSHerbert Xu MODULE_DESCRIPTION("Shared IV generator code"); 164