Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[CRYPTO] seqiv: Add Sequence Number IV Generator

This generator generates an IV based on a sequence number by xoring it
with a salt. This algorithm is mainly useful for CTR and similar modes.

This patch also sets it as the default IV generator for ctr.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

+198
+9
crypto/Kconfig
··· 32 32 tristate 33 33 select CRYPTO_ALGAPI 34 34 35 + config CRYPTO_SEQIV 36 + tristate "Sequence Number IV Generator" 37 + select CRYPTO_BLKCIPHER 38 + help 39 + This IV generator generates an IV based on a sequence number by 40 + xoring it with a salt. This algorithm is mainly useful for CTR 41 + and similar modes. 42 + 35 43 config CRYPTO_HASH 36 44 tristate 37 45 select CRYPTO_ALGAPI ··· 205 197 config CRYPTO_CTR 206 198 tristate "CTR support" 207 199 select CRYPTO_BLKCIPHER 200 + select CRYPTO_SEQIV 208 201 select CRYPTO_MANAGER 209 202 help 210 203 CTR: Counter mode
+1
crypto/Makefile
··· 15 15 obj-$(CONFIG_CRYPTO_BLKCIPHER) += crypto_blkcipher.o 16 16 obj-$(CONFIG_CRYPTO_BLKCIPHER) += chainiv.o 17 17 obj-$(CONFIG_CRYPTO_BLKCIPHER) += eseqiv.o 18 + obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o 18 19 19 20 crypto_hash-objs := hash.o 20 21 obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
+2
crypto/ctr.c
··· 361 361 inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize 362 362 + CTR_RFC3686_NONCE_SIZE; 363 363 364 + inst->alg.cra_blkcipher.geniv = "seqiv"; 365 + 364 366 inst->alg.cra_ctxsize = sizeof(struct crypto_rfc3686_ctx); 365 367 366 368 inst->alg.cra_init = crypto_rfc3686_init_tfm;
+186
crypto/seqiv.c
··· 1 + /* 2 + * seqiv: Sequence Number IV Generator 3 + * 4 + * This generator generates an IV based on a sequence number by xoring it 5 + * with a salt. This algorithm is mainly useful for CTR and similar modes. 6 + * 7 + * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au> 8 + * 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms of the GNU General Public License as published by the Free 11 + * Software Foundation; either version 2 of the License, or (at your option) 12 + * any later version. 13 + * 14 + */ 15 + 16 + #include <crypto/internal/skcipher.h> 17 + #include <linux/err.h> 18 + #include <linux/init.h> 19 + #include <linux/kernel.h> 20 + #include <linux/module.h> 21 + #include <linux/random.h> 22 + #include <linux/spinlock.h> 23 + #include <linux/string.h> 24 + 25 + struct seqiv_ctx { 26 + spinlock_t lock; 27 + u8 salt[] __attribute__ ((aligned(__alignof__(u32)))); 28 + }; 29 + 30 + static void seqiv_complete2(struct skcipher_givcrypt_request *req, int err) 31 + { 32 + struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req); 33 + struct crypto_ablkcipher *geniv; 34 + 35 + if (err == -EINPROGRESS) 36 + return; 37 + 38 + if (err) 39 + goto out; 40 + 41 + geniv = skcipher_givcrypt_reqtfm(req); 42 + memcpy(req->creq.info, subreq->info, crypto_ablkcipher_ivsize(geniv)); 43 + 44 + out: 45 + kfree(subreq->info); 46 + } 47 + 48 + static void seqiv_complete(struct crypto_async_request *base, int err) 49 + { 50 + struct skcipher_givcrypt_request *req = base->data; 51 + 52 + seqiv_complete2(req, err); 53 + skcipher_givcrypt_complete(req, err); 54 + } 55 + 56 + static int seqiv_givencrypt(struct skcipher_givcrypt_request *req) 57 + { 58 + struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); 59 + struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); 60 + struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req); 61 + crypto_completion_t complete; 62 + void *data; 63 + u8 *info; 64 + __be64 seq; 65 + unsigned int ivsize; 66 + unsigned int len; 67 + int err; 68 + 69 + ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv)); 70 + 71 + complete = req->creq.base.complete; 72 + data = req->creq.base.data; 73 + info = req->creq.info; 74 + 75 + ivsize = crypto_ablkcipher_ivsize(geniv); 76 + 77 + if (unlikely(!IS_ALIGNED((unsigned long)info, 78 + crypto_ablkcipher_alignmask(geniv) + 1))) { 79 + info = kmalloc(ivsize, req->creq.base.flags & 80 + CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL: 81 + GFP_ATOMIC); 82 + if (!info) 83 + return -ENOMEM; 84 + 85 + complete = seqiv_complete; 86 + data = req; 87 + } 88 + 89 + ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete, 90 + data); 91 + ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst, 92 + req->creq.nbytes, info); 93 + 94 + len = ivsize; 95 + if (ivsize > sizeof(u64)) { 96 + memset(info, 0, ivsize - sizeof(u64)); 97 + len = sizeof(u64); 98 + } 99 + seq = cpu_to_be64(req->seq); 100 + memcpy(info + ivsize - len, &seq, len); 101 + crypto_xor(info, ctx->salt, ivsize); 102 + 103 + memcpy(req->giv, info, ivsize); 104 + 105 + err = crypto_ablkcipher_encrypt(subreq); 106 + if (unlikely(info != req->creq.info)) 107 + seqiv_complete2(req, err); 108 + return err; 109 + } 110 + 111 + static int seqiv_givencrypt_first(struct skcipher_givcrypt_request *req) 112 + { 113 + struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); 114 + struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); 115 + 116 + spin_lock_bh(&ctx->lock); 117 + if (crypto_ablkcipher_crt(geniv)->givencrypt != seqiv_givencrypt_first) 118 + goto unlock; 119 + 120 + crypto_ablkcipher_crt(geniv)->givencrypt = seqiv_givencrypt; 121 + get_random_bytes(ctx->salt, crypto_ablkcipher_ivsize(geniv)); 122 + 123 + unlock: 124 + spin_unlock_bh(&ctx->lock); 125 + 126 + return seqiv_givencrypt(req); 127 + } 128 + 129 + static int seqiv_init(struct crypto_tfm *tfm) 130 + { 131 + struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm); 132 + struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); 133 + 134 + spin_lock_init(&ctx->lock); 135 + 136 + tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request); 137 + 138 + return skcipher_geniv_init(tfm); 139 + } 140 + 141 + static struct crypto_template seqiv_tmpl; 142 + 143 + static struct crypto_instance *seqiv_alloc(struct rtattr **tb) 144 + { 145 + struct crypto_instance *inst; 146 + 147 + inst = skcipher_geniv_alloc(&seqiv_tmpl, tb, 0, 0); 148 + if (IS_ERR(inst)) 149 + goto out; 150 + 151 + inst->alg.cra_ablkcipher.givencrypt = seqiv_givencrypt_first; 152 + 153 + inst->alg.cra_init = seqiv_init; 154 + inst->alg.cra_exit = skcipher_geniv_exit; 155 + 156 + inst->alg.cra_alignmask |= __alignof__(u32) - 1; 157 + 158 + inst->alg.cra_ctxsize = sizeof(struct seqiv_ctx); 159 + inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize; 160 + 161 + out: 162 + return inst; 163 + } 164 + 165 + static struct crypto_template seqiv_tmpl = { 166 + .name = "seqiv", 167 + .alloc = seqiv_alloc, 168 + .free = skcipher_geniv_free, 169 + .module = THIS_MODULE, 170 + }; 171 + 172 + static int __init seqiv_module_init(void) 173 + { 174 + return crypto_register_template(&seqiv_tmpl); 175 + } 176 + 177 + static void __exit seqiv_module_exit(void) 178 + { 179 + crypto_unregister_template(&seqiv_tmpl); 180 + } 181 + 182 + module_init(seqiv_module_init); 183 + module_exit(seqiv_module_exit); 184 + 185 + MODULE_LICENSE("GPL"); 186 + MODULE_DESCRIPTION("Sequence Number IV Generator");