1a10f554fSHerbert Xu /* 2a10f554fSHerbert Xu * echainiv: Encrypted Chain IV Generator 3a10f554fSHerbert Xu * 4a10f554fSHerbert Xu * This generator generates an IV based on a sequence number by xoring it 5a10f554fSHerbert Xu * with a salt and then encrypting it with the same key as used to encrypt 6a10f554fSHerbert Xu * the plain text. This algorithm requires that the block size be equal 7a10f554fSHerbert Xu * to the IV size. It is mainly useful for CBC. 8a10f554fSHerbert Xu * 9a10f554fSHerbert Xu * This generator can only be used by algorithms where authentication 10a10f554fSHerbert Xu * is performed after encryption (i.e., authenc). 11a10f554fSHerbert Xu * 12a10f554fSHerbert Xu * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au> 13a10f554fSHerbert Xu * 14a10f554fSHerbert Xu * This program is free software; you can redistribute it and/or modify it 15a10f554fSHerbert Xu * under the terms of the GNU General Public License as published by the Free 16a10f554fSHerbert Xu * Software Foundation; either version 2 of the License, or (at your option) 17a10f554fSHerbert Xu * any later version. 18a10f554fSHerbert Xu * 19a10f554fSHerbert Xu */ 20a10f554fSHerbert Xu 21d97de47cSHerbert Xu #include <crypto/internal/geniv.h> 22a10f554fSHerbert Xu #include <crypto/scatterwalk.h> 23a10f554fSHerbert Xu #include <linux/err.h> 24a10f554fSHerbert Xu #include <linux/init.h> 25a10f554fSHerbert Xu #include <linux/kernel.h> 26a10f554fSHerbert Xu #include <linux/mm.h> 27a10f554fSHerbert Xu #include <linux/module.h> 28a10f554fSHerbert Xu #include <linux/percpu.h> 29a10f554fSHerbert Xu #include <linux/spinlock.h> 30a10f554fSHerbert Xu #include <linux/string.h> 31a10f554fSHerbert Xu 32a10f554fSHerbert Xu #define MAX_IV_SIZE 16 33a10f554fSHerbert Xu 34a10f554fSHerbert Xu static DEFINE_PER_CPU(u32 [MAX_IV_SIZE / sizeof(u32)], echainiv_iv); 35a10f554fSHerbert Xu 36a10f554fSHerbert Xu /* We don't care if we get preempted and read/write IVs from the next CPU. */ 37622ff875SWu Fengguang static void echainiv_read_iv(u8 *dst, unsigned size) 38a10f554fSHerbert Xu { 39a10f554fSHerbert Xu u32 *a = (u32 *)dst; 40a10f554fSHerbert Xu u32 __percpu *b = echainiv_iv; 41a10f554fSHerbert Xu 42a10f554fSHerbert Xu for (; size >= 4; size -= 4) { 43a10f554fSHerbert Xu *a++ = this_cpu_read(*b); 44a10f554fSHerbert Xu b++; 45a10f554fSHerbert Xu } 46a10f554fSHerbert Xu } 47a10f554fSHerbert Xu 48622ff875SWu Fengguang static void echainiv_write_iv(const u8 *src, unsigned size) 49a10f554fSHerbert Xu { 50a10f554fSHerbert Xu const u32 *a = (const u32 *)src; 51a10f554fSHerbert Xu u32 __percpu *b = echainiv_iv; 52a10f554fSHerbert Xu 53a10f554fSHerbert Xu for (; size >= 4; size -= 4) { 54a10f554fSHerbert Xu this_cpu_write(*b, *a); 55a10f554fSHerbert Xu a++; 56a10f554fSHerbert Xu b++; 57a10f554fSHerbert Xu } 58a10f554fSHerbert Xu } 59a10f554fSHerbert Xu 60a10f554fSHerbert Xu static void echainiv_encrypt_complete2(struct aead_request *req, int err) 61a10f554fSHerbert Xu { 62a10f554fSHerbert Xu struct aead_request *subreq = aead_request_ctx(req); 63a10f554fSHerbert Xu struct crypto_aead *geniv; 64a10f554fSHerbert Xu unsigned int ivsize; 65a10f554fSHerbert Xu 66a10f554fSHerbert Xu if (err == -EINPROGRESS) 67a10f554fSHerbert Xu return; 68a10f554fSHerbert Xu 69a10f554fSHerbert Xu if (err) 70a10f554fSHerbert Xu goto out; 71a10f554fSHerbert Xu 72a10f554fSHerbert Xu geniv = crypto_aead_reqtfm(req); 73a10f554fSHerbert Xu ivsize = crypto_aead_ivsize(geniv); 74a10f554fSHerbert Xu 75a10f554fSHerbert Xu echainiv_write_iv(subreq->iv, ivsize); 76a10f554fSHerbert Xu 77a10f554fSHerbert Xu if (req->iv != subreq->iv) 78a10f554fSHerbert Xu memcpy(req->iv, subreq->iv, ivsize); 79a10f554fSHerbert Xu 80a10f554fSHerbert Xu out: 81a10f554fSHerbert Xu if (req->iv != subreq->iv) 82a10f554fSHerbert Xu kzfree(subreq->iv); 83a10f554fSHerbert Xu } 84a10f554fSHerbert Xu 85a10f554fSHerbert Xu static void echainiv_encrypt_complete(struct crypto_async_request *base, 86a10f554fSHerbert Xu int err) 87a10f554fSHerbert Xu { 88a10f554fSHerbert Xu struct aead_request *req = base->data; 89a10f554fSHerbert Xu 90a10f554fSHerbert Xu echainiv_encrypt_complete2(req, err); 91a10f554fSHerbert Xu aead_request_complete(req, err); 92a10f554fSHerbert Xu } 93a10f554fSHerbert Xu 94a10f554fSHerbert Xu static int echainiv_encrypt(struct aead_request *req) 95a10f554fSHerbert Xu { 96a10f554fSHerbert Xu struct crypto_aead *geniv = crypto_aead_reqtfm(req); 97376e0d69SHerbert Xu struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv); 98a10f554fSHerbert Xu struct aead_request *subreq = aead_request_ctx(req); 99a10f554fSHerbert Xu crypto_completion_t compl; 100a10f554fSHerbert Xu void *data; 101a10f554fSHerbert Xu u8 *info; 102823655c9SHerbert Xu unsigned int ivsize = crypto_aead_ivsize(geniv); 103a10f554fSHerbert Xu int err; 104a10f554fSHerbert Xu 105823655c9SHerbert Xu if (req->cryptlen < ivsize) 106823655c9SHerbert Xu return -EINVAL; 107823655c9SHerbert Xu 108376e0d69SHerbert Xu aead_request_set_tfm(subreq, ctx->child); 109a10f554fSHerbert Xu 110a10f554fSHerbert Xu compl = echainiv_encrypt_complete; 111a10f554fSHerbert Xu data = req; 112a10f554fSHerbert Xu info = req->iv; 113a10f554fSHerbert Xu 114a10f554fSHerbert Xu if (req->src != req->dst) { 115a10f554fSHerbert Xu struct blkcipher_desc desc = { 116a10f554fSHerbert Xu .tfm = ctx->null, 117a10f554fSHerbert Xu }; 118a10f554fSHerbert Xu 119a10f554fSHerbert Xu err = crypto_blkcipher_encrypt( 120838c9d56SHerbert Xu &desc, req->dst, req->src, 121838c9d56SHerbert Xu req->assoclen + req->cryptlen); 122a10f554fSHerbert Xu if (err) 123a10f554fSHerbert Xu return err; 124a10f554fSHerbert Xu } 125a10f554fSHerbert Xu 126a10f554fSHerbert Xu if (unlikely(!IS_ALIGNED((unsigned long)info, 127a10f554fSHerbert Xu crypto_aead_alignmask(geniv) + 1))) { 128a10f554fSHerbert Xu info = kmalloc(ivsize, req->base.flags & 129a10f554fSHerbert Xu CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL: 130a10f554fSHerbert Xu GFP_ATOMIC); 131a10f554fSHerbert Xu if (!info) 132a10f554fSHerbert Xu return -ENOMEM; 133a10f554fSHerbert Xu 134a10f554fSHerbert Xu memcpy(info, req->iv, ivsize); 135a10f554fSHerbert Xu } 136a10f554fSHerbert Xu 137a10f554fSHerbert Xu aead_request_set_callback(subreq, req->base.flags, compl, data); 138a10f554fSHerbert Xu aead_request_set_crypt(subreq, req->dst, req->dst, 1395499b1a7SHerbert Xu req->cryptlen, info); 1405499b1a7SHerbert Xu aead_request_set_ad(subreq, req->assoclen); 141a10f554fSHerbert Xu 142a10f554fSHerbert Xu crypto_xor(info, ctx->salt, ivsize); 143a10f554fSHerbert Xu scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1); 144a10f554fSHerbert Xu echainiv_read_iv(info, ivsize); 145a10f554fSHerbert Xu 146a10f554fSHerbert Xu err = crypto_aead_encrypt(subreq); 147a10f554fSHerbert Xu echainiv_encrypt_complete2(req, err); 148a10f554fSHerbert Xu return err; 149a10f554fSHerbert Xu } 150a10f554fSHerbert Xu 151a10f554fSHerbert Xu static int echainiv_decrypt(struct aead_request *req) 152a10f554fSHerbert Xu { 153a10f554fSHerbert Xu struct crypto_aead *geniv = crypto_aead_reqtfm(req); 154376e0d69SHerbert Xu struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv); 155a10f554fSHerbert Xu struct aead_request *subreq = aead_request_ctx(req); 156a10f554fSHerbert Xu crypto_completion_t compl; 157a10f554fSHerbert Xu void *data; 158823655c9SHerbert Xu unsigned int ivsize = crypto_aead_ivsize(geniv); 159823655c9SHerbert Xu 1605499b1a7SHerbert Xu if (req->cryptlen < ivsize) 161823655c9SHerbert Xu return -EINVAL; 162a10f554fSHerbert Xu 163376e0d69SHerbert Xu aead_request_set_tfm(subreq, ctx->child); 164a10f554fSHerbert Xu 165a10f554fSHerbert Xu compl = req->base.complete; 166a10f554fSHerbert Xu data = req->base.data; 167a10f554fSHerbert Xu 168a10f554fSHerbert Xu aead_request_set_callback(subreq, req->base.flags, compl, data); 169a10f554fSHerbert Xu aead_request_set_crypt(subreq, req->src, req->dst, 170a10f554fSHerbert Xu req->cryptlen - ivsize, req->iv); 171374d4ad1SHerbert Xu aead_request_set_ad(subreq, req->assoclen + ivsize); 172a10f554fSHerbert Xu 173a10f554fSHerbert Xu scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0); 174a10f554fSHerbert Xu 175a10f554fSHerbert Xu return crypto_aead_decrypt(subreq); 176a10f554fSHerbert Xu } 177a10f554fSHerbert Xu 1781e419c79SHerbert Xu static int echainiv_aead_create(struct crypto_template *tmpl, 1791e419c79SHerbert Xu struct rtattr **tb) 180a10f554fSHerbert Xu { 181a10f554fSHerbert Xu struct aead_instance *inst; 182a10f554fSHerbert Xu struct crypto_aead_spawn *spawn; 183a10f554fSHerbert Xu struct aead_alg *alg; 1841e419c79SHerbert Xu int err; 185a10f554fSHerbert Xu 1861e419c79SHerbert Xu inst = aead_geniv_alloc(tmpl, tb, 0, 0); 187a10f554fSHerbert Xu 188a10f554fSHerbert Xu if (IS_ERR(inst)) 1891e419c79SHerbert Xu return PTR_ERR(inst); 190a10f554fSHerbert Xu 191a10f554fSHerbert Xu spawn = aead_instance_ctx(inst); 192a10f554fSHerbert Xu alg = crypto_spawn_aead_alg(spawn); 193a10f554fSHerbert Xu 194d97de47cSHerbert Xu err = -EINVAL; 195d97de47cSHerbert Xu if (inst->alg.ivsize & (sizeof(u32) - 1) || 196d97de47cSHerbert Xu inst->alg.ivsize > MAX_IV_SIZE) 197d97de47cSHerbert Xu goto free_inst; 198d97de47cSHerbert Xu 199f261c5fbSHerbert Xu inst->alg.encrypt = echainiv_encrypt; 200a10f554fSHerbert Xu inst->alg.decrypt = echainiv_decrypt; 201a10f554fSHerbert Xu 202376e0d69SHerbert Xu inst->alg.init = aead_init_geniv; 203376e0d69SHerbert Xu inst->alg.exit = aead_exit_geniv; 204a10f554fSHerbert Xu 205a10f554fSHerbert Xu inst->alg.base.cra_alignmask |= __alignof__(u32) - 1; 206376e0d69SHerbert Xu inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx); 2079d03aee1SHerbert Xu inst->alg.base.cra_ctxsize += inst->alg.ivsize; 208a10f554fSHerbert Xu 2095499b1a7SHerbert Xu inst->free = aead_geniv_free; 2105499b1a7SHerbert Xu 2111e419c79SHerbert Xu err = aead_register_instance(tmpl, inst); 2121e419c79SHerbert Xu if (err) 2131e419c79SHerbert Xu goto free_inst; 2141e419c79SHerbert Xu 215a10f554fSHerbert Xu out: 2161e419c79SHerbert Xu return err; 2171e419c79SHerbert Xu 2181e419c79SHerbert Xu free_inst: 2191e419c79SHerbert Xu aead_geniv_free(inst); 2201e419c79SHerbert Xu goto out; 221a10f554fSHerbert Xu } 222a10f554fSHerbert Xu 223a10f554fSHerbert Xu static void echainiv_free(struct crypto_instance *inst) 224a10f554fSHerbert Xu { 225a10f554fSHerbert Xu aead_geniv_free(aead_instance(inst)); 226a10f554fSHerbert Xu } 227a10f554fSHerbert Xu 228a10f554fSHerbert Xu static struct crypto_template echainiv_tmpl = { 229a10f554fSHerbert Xu .name = "echainiv", 2309fcc704dSHerbert Xu .create = echainiv_aead_create, 231a10f554fSHerbert Xu .free = echainiv_free, 232a10f554fSHerbert Xu .module = THIS_MODULE, 233a10f554fSHerbert Xu }; 234a10f554fSHerbert Xu 235a10f554fSHerbert Xu static int __init echainiv_module_init(void) 236a10f554fSHerbert Xu { 237a10f554fSHerbert Xu return crypto_register_template(&echainiv_tmpl); 238a10f554fSHerbert Xu } 239a10f554fSHerbert Xu 240a10f554fSHerbert Xu static void __exit echainiv_module_exit(void) 241a10f554fSHerbert Xu { 242a10f554fSHerbert Xu crypto_unregister_template(&echainiv_tmpl); 243a10f554fSHerbert Xu } 244a10f554fSHerbert Xu 245a10f554fSHerbert Xu module_init(echainiv_module_init); 246a10f554fSHerbert Xu module_exit(echainiv_module_exit); 247a10f554fSHerbert Xu 248a10f554fSHerbert Xu MODULE_LICENSE("GPL"); 249a10f554fSHerbert Xu MODULE_DESCRIPTION("Encrypted Chain IV Generator"); 250a10f554fSHerbert Xu MODULE_ALIAS_CRYPTO("echainiv"); 251