Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/crypto/ctr.c
10814 views
1
/*
2
* CTR: Counter mode
3
*
4
* (C) Copyright IBM Corp. 2007 - Joy Latten <[email protected]>
5
*
6
* This program is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License as published by the Free
8
* Software Foundation; either version 2 of the License, or (at your option)
9
* any later version.
10
*
11
*/
12
13
#include <crypto/algapi.h>
14
#include <crypto/ctr.h>
15
#include <linux/err.h>
16
#include <linux/init.h>
17
#include <linux/kernel.h>
18
#include <linux/module.h>
19
#include <linux/random.h>
20
#include <linux/scatterlist.h>
21
#include <linux/slab.h>
22
23
struct crypto_ctr_ctx {
24
struct crypto_cipher *child;
25
};
26
27
struct crypto_rfc3686_ctx {
28
struct crypto_blkcipher *child;
29
u8 nonce[CTR_RFC3686_NONCE_SIZE];
30
};
31
32
static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key,
33
unsigned int keylen)
34
{
35
struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(parent);
36
struct crypto_cipher *child = ctx->child;
37
int err;
38
39
crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
40
crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
41
CRYPTO_TFM_REQ_MASK);
42
err = crypto_cipher_setkey(child, key, keylen);
43
crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
44
CRYPTO_TFM_RES_MASK);
45
46
return err;
47
}
48
49
static void crypto_ctr_crypt_final(struct blkcipher_walk *walk,
50
struct crypto_cipher *tfm)
51
{
52
unsigned int bsize = crypto_cipher_blocksize(tfm);
53
unsigned long alignmask = crypto_cipher_alignmask(tfm);
54
u8 *ctrblk = walk->iv;
55
u8 tmp[bsize + alignmask];
56
u8 *keystream = PTR_ALIGN(tmp + 0, alignmask + 1);
57
u8 *src = walk->src.virt.addr;
58
u8 *dst = walk->dst.virt.addr;
59
unsigned int nbytes = walk->nbytes;
60
61
crypto_cipher_encrypt_one(tfm, keystream, ctrblk);
62
crypto_xor(keystream, src, nbytes);
63
memcpy(dst, keystream, nbytes);
64
65
crypto_inc(ctrblk, bsize);
66
}
67
68
static int crypto_ctr_crypt_segment(struct blkcipher_walk *walk,
69
struct crypto_cipher *tfm)
70
{
71
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
72
crypto_cipher_alg(tfm)->cia_encrypt;
73
unsigned int bsize = crypto_cipher_blocksize(tfm);
74
u8 *ctrblk = walk->iv;
75
u8 *src = walk->src.virt.addr;
76
u8 *dst = walk->dst.virt.addr;
77
unsigned int nbytes = walk->nbytes;
78
79
do {
80
/* create keystream */
81
fn(crypto_cipher_tfm(tfm), dst, ctrblk);
82
crypto_xor(dst, src, bsize);
83
84
/* increment counter in counterblock */
85
crypto_inc(ctrblk, bsize);
86
87
src += bsize;
88
dst += bsize;
89
} while ((nbytes -= bsize) >= bsize);
90
91
return nbytes;
92
}
93
94
static int crypto_ctr_crypt_inplace(struct blkcipher_walk *walk,
95
struct crypto_cipher *tfm)
96
{
97
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
98
crypto_cipher_alg(tfm)->cia_encrypt;
99
unsigned int bsize = crypto_cipher_blocksize(tfm);
100
unsigned long alignmask = crypto_cipher_alignmask(tfm);
101
unsigned int nbytes = walk->nbytes;
102
u8 *ctrblk = walk->iv;
103
u8 *src = walk->src.virt.addr;
104
u8 tmp[bsize + alignmask];
105
u8 *keystream = PTR_ALIGN(tmp + 0, alignmask + 1);
106
107
do {
108
/* create keystream */
109
fn(crypto_cipher_tfm(tfm), keystream, ctrblk);
110
crypto_xor(src, keystream, bsize);
111
112
/* increment counter in counterblock */
113
crypto_inc(ctrblk, bsize);
114
115
src += bsize;
116
} while ((nbytes -= bsize) >= bsize);
117
118
return nbytes;
119
}
120
121
static int crypto_ctr_crypt(struct blkcipher_desc *desc,
122
struct scatterlist *dst, struct scatterlist *src,
123
unsigned int nbytes)
124
{
125
struct blkcipher_walk walk;
126
struct crypto_blkcipher *tfm = desc->tfm;
127
struct crypto_ctr_ctx *ctx = crypto_blkcipher_ctx(tfm);
128
struct crypto_cipher *child = ctx->child;
129
unsigned int bsize = crypto_cipher_blocksize(child);
130
int err;
131
132
blkcipher_walk_init(&walk, dst, src, nbytes);
133
err = blkcipher_walk_virt_block(desc, &walk, bsize);
134
135
while (walk.nbytes >= bsize) {
136
if (walk.src.virt.addr == walk.dst.virt.addr)
137
nbytes = crypto_ctr_crypt_inplace(&walk, child);
138
else
139
nbytes = crypto_ctr_crypt_segment(&walk, child);
140
141
err = blkcipher_walk_done(desc, &walk, nbytes);
142
}
143
144
if (walk.nbytes) {
145
crypto_ctr_crypt_final(&walk, child);
146
err = blkcipher_walk_done(desc, &walk, 0);
147
}
148
149
return err;
150
}
151
152
static int crypto_ctr_init_tfm(struct crypto_tfm *tfm)
153
{
154
struct crypto_instance *inst = (void *)tfm->__crt_alg;
155
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
156
struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm);
157
struct crypto_cipher *cipher;
158
159
cipher = crypto_spawn_cipher(spawn);
160
if (IS_ERR(cipher))
161
return PTR_ERR(cipher);
162
163
ctx->child = cipher;
164
165
return 0;
166
}
167
168
static void crypto_ctr_exit_tfm(struct crypto_tfm *tfm)
169
{
170
struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm);
171
172
crypto_free_cipher(ctx->child);
173
}
174
175
static struct crypto_instance *crypto_ctr_alloc(struct rtattr **tb)
176
{
177
struct crypto_instance *inst;
178
struct crypto_alg *alg;
179
int err;
180
181
err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
182
if (err)
183
return ERR_PTR(err);
184
185
alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER,
186
CRYPTO_ALG_TYPE_MASK);
187
if (IS_ERR(alg))
188
return ERR_CAST(alg);
189
190
/* Block size must be >= 4 bytes. */
191
err = -EINVAL;
192
if (alg->cra_blocksize < 4)
193
goto out_put_alg;
194
195
/* If this is false we'd fail the alignment of crypto_inc. */
196
if (alg->cra_blocksize % 4)
197
goto out_put_alg;
198
199
inst = crypto_alloc_instance("ctr", alg);
200
if (IS_ERR(inst))
201
goto out;
202
203
inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
204
inst->alg.cra_priority = alg->cra_priority;
205
inst->alg.cra_blocksize = 1;
206
inst->alg.cra_alignmask = alg->cra_alignmask | (__alignof__(u32) - 1);
207
inst->alg.cra_type = &crypto_blkcipher_type;
208
209
inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
210
inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
211
inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
212
213
inst->alg.cra_ctxsize = sizeof(struct crypto_ctr_ctx);
214
215
inst->alg.cra_init = crypto_ctr_init_tfm;
216
inst->alg.cra_exit = crypto_ctr_exit_tfm;
217
218
inst->alg.cra_blkcipher.setkey = crypto_ctr_setkey;
219
inst->alg.cra_blkcipher.encrypt = crypto_ctr_crypt;
220
inst->alg.cra_blkcipher.decrypt = crypto_ctr_crypt;
221
222
inst->alg.cra_blkcipher.geniv = "chainiv";
223
224
out:
225
crypto_mod_put(alg);
226
return inst;
227
228
out_put_alg:
229
inst = ERR_PTR(err);
230
goto out;
231
}
232
233
static void crypto_ctr_free(struct crypto_instance *inst)
234
{
235
crypto_drop_spawn(crypto_instance_ctx(inst));
236
kfree(inst);
237
}
238
239
static struct crypto_template crypto_ctr_tmpl = {
240
.name = "ctr",
241
.alloc = crypto_ctr_alloc,
242
.free = crypto_ctr_free,
243
.module = THIS_MODULE,
244
};
245
246
static int crypto_rfc3686_setkey(struct crypto_tfm *parent, const u8 *key,
247
unsigned int keylen)
248
{
249
struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(parent);
250
struct crypto_blkcipher *child = ctx->child;
251
int err;
252
253
/* the nonce is stored in bytes at end of key */
254
if (keylen < CTR_RFC3686_NONCE_SIZE)
255
return -EINVAL;
256
257
memcpy(ctx->nonce, key + (keylen - CTR_RFC3686_NONCE_SIZE),
258
CTR_RFC3686_NONCE_SIZE);
259
260
keylen -= CTR_RFC3686_NONCE_SIZE;
261
262
crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
263
crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
264
CRYPTO_TFM_REQ_MASK);
265
err = crypto_blkcipher_setkey(child, key, keylen);
266
crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
267
CRYPTO_TFM_RES_MASK);
268
269
return err;
270
}
271
272
static int crypto_rfc3686_crypt(struct blkcipher_desc *desc,
273
struct scatterlist *dst,
274
struct scatterlist *src, unsigned int nbytes)
275
{
276
struct crypto_blkcipher *tfm = desc->tfm;
277
struct crypto_rfc3686_ctx *ctx = crypto_blkcipher_ctx(tfm);
278
struct crypto_blkcipher *child = ctx->child;
279
unsigned long alignmask = crypto_blkcipher_alignmask(tfm);
280
u8 ivblk[CTR_RFC3686_BLOCK_SIZE + alignmask];
281
u8 *iv = PTR_ALIGN(ivblk + 0, alignmask + 1);
282
u8 *info = desc->info;
283
int err;
284
285
/* set up counter block */
286
memcpy(iv, ctx->nonce, CTR_RFC3686_NONCE_SIZE);
287
memcpy(iv + CTR_RFC3686_NONCE_SIZE, info, CTR_RFC3686_IV_SIZE);
288
289
/* initialize counter portion of counter block */
290
*(__be32 *)(iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) =
291
cpu_to_be32(1);
292
293
desc->tfm = child;
294
desc->info = iv;
295
err = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
296
desc->tfm = tfm;
297
desc->info = info;
298
299
return err;
300
}
301
302
static int crypto_rfc3686_init_tfm(struct crypto_tfm *tfm)
303
{
304
struct crypto_instance *inst = (void *)tfm->__crt_alg;
305
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
306
struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
307
struct crypto_blkcipher *cipher;
308
309
cipher = crypto_spawn_blkcipher(spawn);
310
if (IS_ERR(cipher))
311
return PTR_ERR(cipher);
312
313
ctx->child = cipher;
314
315
return 0;
316
}
317
318
static void crypto_rfc3686_exit_tfm(struct crypto_tfm *tfm)
319
{
320
struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
321
322
crypto_free_blkcipher(ctx->child);
323
}
324
325
static struct crypto_instance *crypto_rfc3686_alloc(struct rtattr **tb)
326
{
327
struct crypto_instance *inst;
328
struct crypto_alg *alg;
329
int err;
330
331
err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
332
if (err)
333
return ERR_PTR(err);
334
335
alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER,
336
CRYPTO_ALG_TYPE_MASK);
337
err = PTR_ERR(alg);
338
if (IS_ERR(alg))
339
return ERR_PTR(err);
340
341
/* We only support 16-byte blocks. */
342
err = -EINVAL;
343
if (alg->cra_blkcipher.ivsize != CTR_RFC3686_BLOCK_SIZE)
344
goto out_put_alg;
345
346
/* Not a stream cipher? */
347
if (alg->cra_blocksize != 1)
348
goto out_put_alg;
349
350
inst = crypto_alloc_instance("rfc3686", alg);
351
if (IS_ERR(inst))
352
goto out;
353
354
inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
355
inst->alg.cra_priority = alg->cra_priority;
356
inst->alg.cra_blocksize = 1;
357
inst->alg.cra_alignmask = alg->cra_alignmask;
358
inst->alg.cra_type = &crypto_blkcipher_type;
359
360
inst->alg.cra_blkcipher.ivsize = CTR_RFC3686_IV_SIZE;
361
inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize
362
+ CTR_RFC3686_NONCE_SIZE;
363
inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize
364
+ CTR_RFC3686_NONCE_SIZE;
365
366
inst->alg.cra_blkcipher.geniv = "seqiv";
367
368
inst->alg.cra_ctxsize = sizeof(struct crypto_rfc3686_ctx);
369
370
inst->alg.cra_init = crypto_rfc3686_init_tfm;
371
inst->alg.cra_exit = crypto_rfc3686_exit_tfm;
372
373
inst->alg.cra_blkcipher.setkey = crypto_rfc3686_setkey;
374
inst->alg.cra_blkcipher.encrypt = crypto_rfc3686_crypt;
375
inst->alg.cra_blkcipher.decrypt = crypto_rfc3686_crypt;
376
377
out:
378
crypto_mod_put(alg);
379
return inst;
380
381
out_put_alg:
382
inst = ERR_PTR(err);
383
goto out;
384
}
385
386
static struct crypto_template crypto_rfc3686_tmpl = {
387
.name = "rfc3686",
388
.alloc = crypto_rfc3686_alloc,
389
.free = crypto_ctr_free,
390
.module = THIS_MODULE,
391
};
392
393
static int __init crypto_ctr_module_init(void)
394
{
395
int err;
396
397
err = crypto_register_template(&crypto_ctr_tmpl);
398
if (err)
399
goto out;
400
401
err = crypto_register_template(&crypto_rfc3686_tmpl);
402
if (err)
403
goto out_drop_ctr;
404
405
out:
406
return err;
407
408
out_drop_ctr:
409
crypto_unregister_template(&crypto_ctr_tmpl);
410
goto out;
411
}
412
413
static void __exit crypto_ctr_module_exit(void)
414
{
415
crypto_unregister_template(&crypto_rfc3686_tmpl);
416
crypto_unregister_template(&crypto_ctr_tmpl);
417
}
418
419
module_init(crypto_ctr_module_init);
420
module_exit(crypto_ctr_module_exit);
421
422
MODULE_LICENSE("GPL");
423
MODULE_DESCRIPTION("CTR Counter block mode");
424
MODULE_ALIAS("rfc3686");
425
426