10a270321SHerbert Xu /* 20a270321SHerbert Xu * seqiv: Sequence Number IV Generator 30a270321SHerbert Xu * 40a270321SHerbert Xu * This generator generates an IV based on a sequence number by xoring it 50a270321SHerbert Xu * with a salt. This algorithm is mainly useful for CTR and similar modes. 60a270321SHerbert Xu * 70a270321SHerbert Xu * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au> 80a270321SHerbert Xu * 90a270321SHerbert Xu * This program is free software; you can redistribute it and/or modify it 100a270321SHerbert Xu * under the terms of the GNU General Public License as published by the Free 110a270321SHerbert Xu * Software Foundation; either version 2 of the License, or (at your option) 120a270321SHerbert Xu * any later version. 130a270321SHerbert Xu * 140a270321SHerbert Xu */ 150a270321SHerbert Xu 16661cfd0eSHerbert Xu #include <crypto/internal/geniv.h> 170a270321SHerbert Xu #include <crypto/internal/skcipher.h> 18a0f000ecSHerbert Xu #include <crypto/rng.h> 19856e3f40SHerbert Xu #include <crypto/scatterwalk.h> 200a270321SHerbert Xu #include <linux/err.h> 210a270321SHerbert Xu #include <linux/init.h> 220a270321SHerbert Xu #include <linux/kernel.h> 230a270321SHerbert Xu #include <linux/module.h> 245a0e3ad6STejun Heo #include <linux/slab.h> 250a270321SHerbert Xu #include <linux/spinlock.h> 260a270321SHerbert Xu #include <linux/string.h> 270a270321SHerbert Xu 280a270321SHerbert Xu struct seqiv_ctx { 290a270321SHerbert Xu spinlock_t lock; 300a270321SHerbert Xu u8 salt[] __attribute__ ((aligned(__alignof__(u32)))); 310a270321SHerbert Xu }; 320a270321SHerbert Xu 330677157bSHerbert Xu static void seqiv_free(struct crypto_instance *inst); 340677157bSHerbert Xu 350a270321SHerbert Xu static void seqiv_complete2(struct skcipher_givcrypt_request *req, int err) 360a270321SHerbert Xu { 370a270321SHerbert Xu struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req); 380a270321SHerbert Xu struct crypto_ablkcipher *geniv; 390a270321SHerbert Xu 400a270321SHerbert Xu if (err == -EINPROGRESS) 410a270321SHerbert Xu return; 420a270321SHerbert Xu 430a270321SHerbert Xu if (err) 440a270321SHerbert Xu goto out; 450a270321SHerbert Xu 460a270321SHerbert Xu geniv = skcipher_givcrypt_reqtfm(req); 470a270321SHerbert Xu memcpy(req->creq.info, subreq->info, crypto_ablkcipher_ivsize(geniv)); 480a270321SHerbert Xu 490a270321SHerbert Xu out: 500a270321SHerbert Xu kfree(subreq->info); 510a270321SHerbert Xu } 520a270321SHerbert Xu 530a270321SHerbert Xu static void seqiv_complete(struct crypto_async_request *base, int err) 540a270321SHerbert Xu { 550a270321SHerbert Xu struct skcipher_givcrypt_request *req = base->data; 560a270321SHerbert Xu 570a270321SHerbert Xu seqiv_complete2(req, err); 580a270321SHerbert Xu skcipher_givcrypt_complete(req, err); 590a270321SHerbert Xu } 600a270321SHerbert Xu 61856e3f40SHerbert Xu static void seqiv_aead_encrypt_complete2(struct aead_request *req, int err) 62856e3f40SHerbert Xu { 63856e3f40SHerbert Xu struct aead_request *subreq = aead_request_ctx(req); 64856e3f40SHerbert Xu struct crypto_aead *geniv; 65856e3f40SHerbert Xu 66856e3f40SHerbert Xu if (err == -EINPROGRESS) 67856e3f40SHerbert Xu return; 68856e3f40SHerbert Xu 69856e3f40SHerbert Xu if (err) 70856e3f40SHerbert Xu goto out; 71856e3f40SHerbert Xu 72856e3f40SHerbert Xu geniv = crypto_aead_reqtfm(req); 73856e3f40SHerbert Xu memcpy(req->iv, subreq->iv, crypto_aead_ivsize(geniv)); 74856e3f40SHerbert Xu 75856e3f40SHerbert Xu out: 76856e3f40SHerbert Xu kzfree(subreq->iv); 77856e3f40SHerbert Xu } 78856e3f40SHerbert Xu 79856e3f40SHerbert Xu static void seqiv_aead_encrypt_complete(struct crypto_async_request *base, 80856e3f40SHerbert Xu int err) 81856e3f40SHerbert Xu { 82856e3f40SHerbert Xu struct aead_request *req = base->data; 83856e3f40SHerbert Xu 84856e3f40SHerbert Xu seqiv_aead_encrypt_complete2(req, err); 85856e3f40SHerbert Xu aead_request_complete(req, err); 86856e3f40SHerbert Xu } 87856e3f40SHerbert Xu 8814df4d80SHerbert Xu static void seqiv_geniv(struct seqiv_ctx *ctx, u8 *info, u64 seq, 8914df4d80SHerbert Xu unsigned int ivsize) 9014df4d80SHerbert Xu { 9114df4d80SHerbert Xu unsigned int len = ivsize; 9214df4d80SHerbert Xu 9314df4d80SHerbert Xu if (ivsize > sizeof(u64)) { 9414df4d80SHerbert Xu memset(info, 0, ivsize - sizeof(u64)); 9514df4d80SHerbert Xu len = sizeof(u64); 9614df4d80SHerbert Xu } 9714df4d80SHerbert Xu seq = cpu_to_be64(seq); 9814df4d80SHerbert Xu memcpy(info + ivsize - len, &seq, len); 9914df4d80SHerbert Xu crypto_xor(info, ctx->salt, ivsize); 10014df4d80SHerbert Xu } 10114df4d80SHerbert Xu 1020a270321SHerbert Xu static int seqiv_givencrypt(struct skcipher_givcrypt_request *req) 1030a270321SHerbert Xu { 1040a270321SHerbert Xu struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); 1050a270321SHerbert Xu struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); 1060a270321SHerbert Xu struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req); 1073e3dc25fSMark Rustad crypto_completion_t compl; 1080a270321SHerbert Xu void *data; 1090a270321SHerbert Xu u8 *info; 1100a270321SHerbert Xu unsigned int ivsize; 1110a270321SHerbert Xu int err; 1120a270321SHerbert Xu 1130a270321SHerbert Xu ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv)); 1140a270321SHerbert Xu 1153e3dc25fSMark Rustad compl = req->creq.base.complete; 1160a270321SHerbert Xu data = req->creq.base.data; 1170a270321SHerbert Xu info = req->creq.info; 1180a270321SHerbert Xu 1190a270321SHerbert Xu ivsize = crypto_ablkcipher_ivsize(geniv); 1200a270321SHerbert Xu 1210a270321SHerbert Xu if (unlikely(!IS_ALIGNED((unsigned long)info, 1220a270321SHerbert Xu crypto_ablkcipher_alignmask(geniv) + 1))) { 1230a270321SHerbert Xu info = kmalloc(ivsize, req->creq.base.flags & 1240a270321SHerbert Xu CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL: 1250a270321SHerbert Xu GFP_ATOMIC); 1260a270321SHerbert Xu if (!info) 1270a270321SHerbert Xu return -ENOMEM; 1280a270321SHerbert Xu 1293e3dc25fSMark Rustad compl = seqiv_complete; 1300a270321SHerbert Xu data = req; 1310a270321SHerbert Xu } 1320a270321SHerbert Xu 1333e3dc25fSMark Rustad ablkcipher_request_set_callback(subreq, req->creq.base.flags, compl, 1340a270321SHerbert Xu data); 1350a270321SHerbert Xu ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst, 1360a270321SHerbert Xu req->creq.nbytes, info); 1370a270321SHerbert Xu 13814df4d80SHerbert Xu seqiv_geniv(ctx, info, req->seq, ivsize); 1390a270321SHerbert Xu memcpy(req->giv, info, ivsize); 1400a270321SHerbert Xu 1410a270321SHerbert Xu err = crypto_ablkcipher_encrypt(subreq); 1420a270321SHerbert Xu if (unlikely(info != req->creq.info)) 1430a270321SHerbert Xu seqiv_complete2(req, err); 1440a270321SHerbert Xu return err; 1450a270321SHerbert Xu } 1460a270321SHerbert Xu 147856e3f40SHerbert Xu static int seqiv_aead_encrypt(struct aead_request *req) 148856e3f40SHerbert Xu { 149856e3f40SHerbert Xu struct crypto_aead *geniv = crypto_aead_reqtfm(req); 150659e7f52SHerbert Xu struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv); 151856e3f40SHerbert Xu struct aead_request *subreq = aead_request_ctx(req); 152856e3f40SHerbert Xu crypto_completion_t compl; 153856e3f40SHerbert Xu void *data; 154856e3f40SHerbert Xu u8 *info; 155dd04446eSHerbert Xu unsigned int ivsize = 8; 156856e3f40SHerbert Xu int err; 157856e3f40SHerbert Xu 158dd04446eSHerbert Xu if (req->cryptlen < ivsize) 159dd04446eSHerbert Xu return -EINVAL; 160dd04446eSHerbert Xu 161659e7f52SHerbert Xu aead_request_set_tfm(subreq, ctx->child); 162856e3f40SHerbert Xu 163856e3f40SHerbert Xu compl = req->base.complete; 164856e3f40SHerbert Xu data = req->base.data; 165856e3f40SHerbert Xu info = req->iv; 166856e3f40SHerbert Xu 167856e3f40SHerbert Xu if (req->src != req->dst) { 168856e3f40SHerbert Xu struct blkcipher_desc desc = { 169856e3f40SHerbert Xu .tfm = ctx->null, 170856e3f40SHerbert Xu }; 171856e3f40SHerbert Xu 172d0ad1b24SHerbert Xu err = crypto_blkcipher_encrypt(&desc, req->dst, req->src, 173d0ad1b24SHerbert Xu req->assoclen + req->cryptlen); 174856e3f40SHerbert Xu if (err) 175856e3f40SHerbert Xu return err; 176856e3f40SHerbert Xu } 177856e3f40SHerbert Xu 178856e3f40SHerbert Xu if (unlikely(!IS_ALIGNED((unsigned long)info, 179856e3f40SHerbert Xu crypto_aead_alignmask(geniv) + 1))) { 180856e3f40SHerbert Xu info = kmalloc(ivsize, req->base.flags & 181856e3f40SHerbert Xu CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL: 182856e3f40SHerbert Xu GFP_ATOMIC); 183856e3f40SHerbert Xu if (!info) 184856e3f40SHerbert Xu return -ENOMEM; 185856e3f40SHerbert Xu 186856e3f40SHerbert Xu memcpy(info, req->iv, ivsize); 187856e3f40SHerbert Xu compl = seqiv_aead_encrypt_complete; 188856e3f40SHerbert Xu data = req; 189856e3f40SHerbert Xu } 190856e3f40SHerbert Xu 191856e3f40SHerbert Xu aead_request_set_callback(subreq, req->base.flags, compl, data); 192856e3f40SHerbert Xu aead_request_set_crypt(subreq, req->dst, req->dst, 193856e3f40SHerbert Xu req->cryptlen - ivsize, info); 194374d4ad1SHerbert Xu aead_request_set_ad(subreq, req->assoclen + ivsize); 195856e3f40SHerbert Xu 196856e3f40SHerbert Xu crypto_xor(info, ctx->salt, ivsize); 197856e3f40SHerbert Xu scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1); 198856e3f40SHerbert Xu 199856e3f40SHerbert Xu err = crypto_aead_encrypt(subreq); 200856e3f40SHerbert Xu if (unlikely(info != req->iv)) 201856e3f40SHerbert Xu seqiv_aead_encrypt_complete2(req, err); 202856e3f40SHerbert Xu return err; 203856e3f40SHerbert Xu } 204856e3f40SHerbert Xu 205856e3f40SHerbert Xu static int seqiv_aead_decrypt(struct aead_request *req) 206856e3f40SHerbert Xu { 207856e3f40SHerbert Xu struct crypto_aead *geniv = crypto_aead_reqtfm(req); 208659e7f52SHerbert Xu struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv); 209856e3f40SHerbert Xu struct aead_request *subreq = aead_request_ctx(req); 210856e3f40SHerbert Xu crypto_completion_t compl; 211856e3f40SHerbert Xu void *data; 212dd04446eSHerbert Xu unsigned int ivsize = 8; 213dd04446eSHerbert Xu 214dd04446eSHerbert Xu if (req->cryptlen < ivsize + crypto_aead_authsize(geniv)) 215dd04446eSHerbert Xu return -EINVAL; 216856e3f40SHerbert Xu 217659e7f52SHerbert Xu aead_request_set_tfm(subreq, ctx->child); 218856e3f40SHerbert Xu 219856e3f40SHerbert Xu compl = req->base.complete; 220856e3f40SHerbert Xu data = req->base.data; 221856e3f40SHerbert Xu 222856e3f40SHerbert Xu aead_request_set_callback(subreq, req->base.flags, compl, data); 223856e3f40SHerbert Xu aead_request_set_crypt(subreq, req->src, req->dst, 224856e3f40SHerbert Xu req->cryptlen - ivsize, req->iv); 225374d4ad1SHerbert Xu aead_request_set_ad(subreq, req->assoclen + ivsize); 226856e3f40SHerbert Xu 227856e3f40SHerbert Xu scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0); 228856e3f40SHerbert Xu 229856e3f40SHerbert Xu return crypto_aead_decrypt(subreq); 230856e3f40SHerbert Xu } 231856e3f40SHerbert Xu 2320a270321SHerbert Xu static int seqiv_init(struct crypto_tfm *tfm) 2330a270321SHerbert Xu { 2340a270321SHerbert Xu struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm); 2350a270321SHerbert Xu struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); 236eeee12aaSHerbert Xu int err; 2370a270321SHerbert Xu 2380a270321SHerbert Xu spin_lock_init(&ctx->lock); 2390a270321SHerbert Xu 2400a270321SHerbert Xu tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request); 2410a270321SHerbert Xu 242eeee12aaSHerbert Xu err = 0; 243eeee12aaSHerbert Xu if (!crypto_get_default_rng()) { 244eeee12aaSHerbert Xu crypto_ablkcipher_crt(geniv)->givencrypt = seqiv_givencrypt; 245eeee12aaSHerbert Xu err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt, 246eeee12aaSHerbert Xu crypto_ablkcipher_ivsize(geniv)); 247eeee12aaSHerbert Xu crypto_put_default_rng(); 248eeee12aaSHerbert Xu } 249eeee12aaSHerbert Xu 250eeee12aaSHerbert Xu return err ?: skcipher_geniv_init(tfm); 2510a270321SHerbert Xu } 2520a270321SHerbert Xu 2530677157bSHerbert Xu static int seqiv_ablkcipher_create(struct crypto_template *tmpl, 2540677157bSHerbert Xu struct rtattr **tb) 2550a270321SHerbert Xu { 2560a270321SHerbert Xu struct crypto_instance *inst; 2570677157bSHerbert Xu int err; 2580a270321SHerbert Xu 2590677157bSHerbert Xu inst = skcipher_geniv_alloc(tmpl, tb, 0, 0); 26014df4d80SHerbert Xu 2610a270321SHerbert Xu if (IS_ERR(inst)) 2620677157bSHerbert Xu return PTR_ERR(inst); 2630a270321SHerbert Xu 2640677157bSHerbert Xu err = -EINVAL; 2650677157bSHerbert Xu if (inst->alg.cra_ablkcipher.ivsize < sizeof(u64)) 2660677157bSHerbert Xu goto free_inst; 267c0ecf891SHerbert Xu 2680a270321SHerbert Xu inst->alg.cra_init = seqiv_init; 2690a270321SHerbert Xu inst->alg.cra_exit = skcipher_geniv_exit; 2700a270321SHerbert Xu 2710a270321SHerbert Xu inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize; 272856e3f40SHerbert Xu inst->alg.cra_ctxsize += sizeof(struct seqiv_ctx); 2730a270321SHerbert Xu 2740677157bSHerbert Xu inst->alg.cra_alignmask |= __alignof__(u32) - 1; 2750677157bSHerbert Xu 2760677157bSHerbert Xu err = crypto_register_instance(tmpl, inst); 2770677157bSHerbert Xu if (err) 2780677157bSHerbert Xu goto free_inst; 2790677157bSHerbert Xu 2800a270321SHerbert Xu out: 2810677157bSHerbert Xu return err; 2820677157bSHerbert Xu 2830677157bSHerbert Xu free_inst: 2840677157bSHerbert Xu skcipher_geniv_free(inst); 2850677157bSHerbert Xu goto out; 2860a270321SHerbert Xu } 2870a270321SHerbert Xu 2880677157bSHerbert Xu static int seqiv_aead_create(struct crypto_template *tmpl, struct rtattr **tb) 28914df4d80SHerbert Xu { 290856e3f40SHerbert Xu struct aead_instance *inst; 291856e3f40SHerbert Xu struct crypto_aead_spawn *spawn; 292856e3f40SHerbert Xu struct aead_alg *alg; 2930677157bSHerbert Xu int err; 29414df4d80SHerbert Xu 2950677157bSHerbert Xu inst = aead_geniv_alloc(tmpl, tb, 0, 0); 29614df4d80SHerbert Xu 29714df4d80SHerbert Xu if (IS_ERR(inst)) 2980677157bSHerbert Xu return PTR_ERR(inst); 2990677157bSHerbert Xu 3000677157bSHerbert Xu inst->alg.base.cra_alignmask |= __alignof__(u32) - 1; 30114df4d80SHerbert Xu 302661cfd0eSHerbert Xu spawn = aead_instance_ctx(inst); 303661cfd0eSHerbert Xu alg = crypto_spawn_aead_alg(spawn); 304661cfd0eSHerbert Xu 3050677157bSHerbert Xu err = -EINVAL; 306dd04446eSHerbert Xu if (inst->alg.ivsize != sizeof(u64)) 3070677157bSHerbert Xu goto free_inst; 308c0ecf891SHerbert Xu 309b7dcfab4SHerbert Xu inst->alg.encrypt = seqiv_aead_encrypt; 310856e3f40SHerbert Xu inst->alg.decrypt = seqiv_aead_decrypt; 31114df4d80SHerbert Xu 312659e7f52SHerbert Xu inst->alg.init = aead_init_geniv; 313659e7f52SHerbert Xu inst->alg.exit = aead_exit_geniv; 314856e3f40SHerbert Xu 315659e7f52SHerbert Xu inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx); 3165964f26cSHerbert Xu inst->alg.base.cra_ctxsize += inst->alg.ivsize; 317856e3f40SHerbert Xu 3180677157bSHerbert Xu err = aead_register_instance(tmpl, inst); 3190677157bSHerbert Xu if (err) 3200677157bSHerbert Xu goto free_inst; 3210677157bSHerbert Xu 32214df4d80SHerbert Xu out: 3230677157bSHerbert Xu return err; 3240677157bSHerbert Xu 3250677157bSHerbert Xu free_inst: 3260677157bSHerbert Xu aead_geniv_free(inst); 3270677157bSHerbert Xu goto out; 32814df4d80SHerbert Xu } 32914df4d80SHerbert Xu 3300677157bSHerbert Xu static int seqiv_create(struct crypto_template *tmpl, struct rtattr **tb) 33114df4d80SHerbert Xu { 33214df4d80SHerbert Xu struct crypto_attr_type *algt; 33314df4d80SHerbert Xu int err; 33414df4d80SHerbert Xu 33514df4d80SHerbert Xu algt = crypto_get_attr_type(tb); 33614df4d80SHerbert Xu if (IS_ERR(algt)) 3370677157bSHerbert Xu return PTR_ERR(algt); 33814df4d80SHerbert Xu 33914df4d80SHerbert Xu if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK) 3400677157bSHerbert Xu err = seqiv_ablkcipher_create(tmpl, tb); 34114df4d80SHerbert Xu else 3420677157bSHerbert Xu err = seqiv_aead_create(tmpl, tb); 34314df4d80SHerbert Xu 3440677157bSHerbert Xu return err; 34514df4d80SHerbert Xu } 34614df4d80SHerbert Xu 34714df4d80SHerbert Xu static void seqiv_free(struct crypto_instance *inst) 34814df4d80SHerbert Xu { 34914df4d80SHerbert Xu if ((inst->alg.cra_flags ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK) 35014df4d80SHerbert Xu skcipher_geniv_free(inst); 35114df4d80SHerbert Xu else 352856e3f40SHerbert Xu aead_geniv_free(aead_instance(inst)); 35314df4d80SHerbert Xu } 35414df4d80SHerbert Xu 3550a270321SHerbert Xu static struct crypto_template seqiv_tmpl = { 3560a270321SHerbert Xu .name = "seqiv", 3570677157bSHerbert Xu .create = seqiv_create, 35814df4d80SHerbert Xu .free = seqiv_free, 3590a270321SHerbert Xu .module = THIS_MODULE, 3600a270321SHerbert Xu }; 3610a270321SHerbert Xu 3620a270321SHerbert Xu static int __init seqiv_module_init(void) 3630a270321SHerbert Xu { 3648a2cd1c4SHerbert Xu return crypto_register_template(&seqiv_tmpl); 3650a270321SHerbert Xu } 3660a270321SHerbert Xu 3670a270321SHerbert Xu static void __exit seqiv_module_exit(void) 3680a270321SHerbert Xu { 3690a270321SHerbert Xu crypto_unregister_template(&seqiv_tmpl); 3700a270321SHerbert Xu } 3710a270321SHerbert Xu 3720a270321SHerbert Xu module_init(seqiv_module_init); 3730a270321SHerbert Xu module_exit(seqiv_module_exit); 3740a270321SHerbert Xu 3750a270321SHerbert Xu MODULE_LICENSE("GPL"); 3760a270321SHerbert Xu MODULE_DESCRIPTION("Sequence Number IV Generator"); 3774943ba16SKees Cook MODULE_ALIAS_CRYPTO("seqiv"); 378