Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/crypto/lrw.c
10814 views
1
/* LRW: as defined by Cyril Guyot in
2
* http://grouper.ieee.org/groups/1619/email/pdf00017.pdf
3
*
4
* Copyright (c) 2006 Rik Snel <[email protected]>
5
*
6
* Based om ecb.c
7
* Copyright (c) 2006 Herbert Xu <[email protected]>
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
/* This implementation is checked against the test vectors in the above
15
* document and by a test vector provided by Ken Buchanan at
16
* http://www.mail-archive.com/[email protected]/msg00173.html
17
*
18
* The test vectors are included in the testing module tcrypt.[ch] */
19
#include <crypto/algapi.h>
20
#include <linux/err.h>
21
#include <linux/init.h>
22
#include <linux/kernel.h>
23
#include <linux/module.h>
24
#include <linux/scatterlist.h>
25
#include <linux/slab.h>
26
27
#include <crypto/b128ops.h>
28
#include <crypto/gf128mul.h>
29
30
struct priv {
31
struct crypto_cipher *child;
32
/* optimizes multiplying a random (non incrementing, as at the
33
* start of a new sector) value with key2, we could also have
34
* used 4k optimization tables or no optimization at all. In the
35
* latter case we would have to store key2 here */
36
struct gf128mul_64k *table;
37
/* stores:
38
* key2*{ 0,0,...0,0,0,0,1 }, key2*{ 0,0,...0,0,0,1,1 },
39
* key2*{ 0,0,...0,0,1,1,1 }, key2*{ 0,0,...0,1,1,1,1 }
40
* key2*{ 0,0,...1,1,1,1,1 }, etc
41
* needed for optimized multiplication of incrementing values
42
* with key2 */
43
be128 mulinc[128];
44
};
45
46
static inline void setbit128_bbe(void *b, int bit)
47
{
48
__set_bit(bit ^ (0x80 -
49
#ifdef __BIG_ENDIAN
50
BITS_PER_LONG
51
#else
52
BITS_PER_BYTE
53
#endif
54
), b);
55
}
56
57
static int setkey(struct crypto_tfm *parent, const u8 *key,
58
unsigned int keylen)
59
{
60
struct priv *ctx = crypto_tfm_ctx(parent);
61
struct crypto_cipher *child = ctx->child;
62
int err, i;
63
be128 tmp = { 0 };
64
int bsize = crypto_cipher_blocksize(child);
65
66
crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
67
crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
68
CRYPTO_TFM_REQ_MASK);
69
if ((err = crypto_cipher_setkey(child, key, keylen - bsize)))
70
return err;
71
crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
72
CRYPTO_TFM_RES_MASK);
73
74
if (ctx->table)
75
gf128mul_free_64k(ctx->table);
76
77
/* initialize multiplication table for Key2 */
78
ctx->table = gf128mul_init_64k_bbe((be128 *)(key + keylen - bsize));
79
if (!ctx->table)
80
return -ENOMEM;
81
82
/* initialize optimization table */
83
for (i = 0; i < 128; i++) {
84
setbit128_bbe(&tmp, i);
85
ctx->mulinc[i] = tmp;
86
gf128mul_64k_bbe(&ctx->mulinc[i], ctx->table);
87
}
88
89
return 0;
90
}
91
92
struct sinfo {
93
be128 t;
94
struct crypto_tfm *tfm;
95
void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
96
};
97
98
static inline void inc(be128 *iv)
99
{
100
be64_add_cpu(&iv->b, 1);
101
if (!iv->b)
102
be64_add_cpu(&iv->a, 1);
103
}
104
105
static inline void lrw_round(struct sinfo *s, void *dst, const void *src)
106
{
107
be128_xor(dst, &s->t, src); /* PP <- T xor P */
108
s->fn(s->tfm, dst, dst); /* CC <- E(Key2,PP) */
109
be128_xor(dst, dst, &s->t); /* C <- T xor CC */
110
}
111
112
/* this returns the number of consequative 1 bits starting
113
* from the right, get_index128(00 00 00 00 00 00 ... 00 00 10 FB) = 2 */
114
static inline int get_index128(be128 *block)
115
{
116
int x;
117
__be32 *p = (__be32 *) block;
118
119
for (p += 3, x = 0; x < 128; p--, x += 32) {
120
u32 val = be32_to_cpup(p);
121
122
if (!~val)
123
continue;
124
125
return x + ffz(val);
126
}
127
128
return x;
129
}
130
131
static int crypt(struct blkcipher_desc *d,
132
struct blkcipher_walk *w, struct priv *ctx,
133
void (*fn)(struct crypto_tfm *, u8 *, const u8 *))
134
{
135
int err;
136
unsigned int avail;
137
const int bs = crypto_cipher_blocksize(ctx->child);
138
struct sinfo s = {
139
.tfm = crypto_cipher_tfm(ctx->child),
140
.fn = fn
141
};
142
be128 *iv;
143
u8 *wsrc;
144
u8 *wdst;
145
146
err = blkcipher_walk_virt(d, w);
147
if (!(avail = w->nbytes))
148
return err;
149
150
wsrc = w->src.virt.addr;
151
wdst = w->dst.virt.addr;
152
153
/* calculate first value of T */
154
iv = (be128 *)w->iv;
155
s.t = *iv;
156
157
/* T <- I*Key2 */
158
gf128mul_64k_bbe(&s.t, ctx->table);
159
160
goto first;
161
162
for (;;) {
163
do {
164
/* T <- I*Key2, using the optimization
165
* discussed in the specification */
166
be128_xor(&s.t, &s.t, &ctx->mulinc[get_index128(iv)]);
167
inc(iv);
168
169
first:
170
lrw_round(&s, wdst, wsrc);
171
172
wsrc += bs;
173
wdst += bs;
174
} while ((avail -= bs) >= bs);
175
176
err = blkcipher_walk_done(d, w, avail);
177
if (!(avail = w->nbytes))
178
break;
179
180
wsrc = w->src.virt.addr;
181
wdst = w->dst.virt.addr;
182
}
183
184
return err;
185
}
186
187
static int encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
188
struct scatterlist *src, unsigned int nbytes)
189
{
190
struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
191
struct blkcipher_walk w;
192
193
blkcipher_walk_init(&w, dst, src, nbytes);
194
return crypt(desc, &w, ctx,
195
crypto_cipher_alg(ctx->child)->cia_encrypt);
196
}
197
198
static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
199
struct scatterlist *src, unsigned int nbytes)
200
{
201
struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
202
struct blkcipher_walk w;
203
204
blkcipher_walk_init(&w, dst, src, nbytes);
205
return crypt(desc, &w, ctx,
206
crypto_cipher_alg(ctx->child)->cia_decrypt);
207
}
208
209
static int init_tfm(struct crypto_tfm *tfm)
210
{
211
struct crypto_cipher *cipher;
212
struct crypto_instance *inst = (void *)tfm->__crt_alg;
213
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
214
struct priv *ctx = crypto_tfm_ctx(tfm);
215
u32 *flags = &tfm->crt_flags;
216
217
cipher = crypto_spawn_cipher(spawn);
218
if (IS_ERR(cipher))
219
return PTR_ERR(cipher);
220
221
if (crypto_cipher_blocksize(cipher) != 16) {
222
*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
223
return -EINVAL;
224
}
225
226
ctx->child = cipher;
227
return 0;
228
}
229
230
static void exit_tfm(struct crypto_tfm *tfm)
231
{
232
struct priv *ctx = crypto_tfm_ctx(tfm);
233
if (ctx->table)
234
gf128mul_free_64k(ctx->table);
235
crypto_free_cipher(ctx->child);
236
}
237
238
static struct crypto_instance *alloc(struct rtattr **tb)
239
{
240
struct crypto_instance *inst;
241
struct crypto_alg *alg;
242
int err;
243
244
err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
245
if (err)
246
return ERR_PTR(err);
247
248
alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
249
CRYPTO_ALG_TYPE_MASK);
250
if (IS_ERR(alg))
251
return ERR_CAST(alg);
252
253
inst = crypto_alloc_instance("lrw", alg);
254
if (IS_ERR(inst))
255
goto out_put_alg;
256
257
inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
258
inst->alg.cra_priority = alg->cra_priority;
259
inst->alg.cra_blocksize = alg->cra_blocksize;
260
261
if (alg->cra_alignmask < 7) inst->alg.cra_alignmask = 7;
262
else inst->alg.cra_alignmask = alg->cra_alignmask;
263
inst->alg.cra_type = &crypto_blkcipher_type;
264
265
if (!(alg->cra_blocksize % 4))
266
inst->alg.cra_alignmask |= 3;
267
inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
268
inst->alg.cra_blkcipher.min_keysize =
269
alg->cra_cipher.cia_min_keysize + alg->cra_blocksize;
270
inst->alg.cra_blkcipher.max_keysize =
271
alg->cra_cipher.cia_max_keysize + alg->cra_blocksize;
272
273
inst->alg.cra_ctxsize = sizeof(struct priv);
274
275
inst->alg.cra_init = init_tfm;
276
inst->alg.cra_exit = exit_tfm;
277
278
inst->alg.cra_blkcipher.setkey = setkey;
279
inst->alg.cra_blkcipher.encrypt = encrypt;
280
inst->alg.cra_blkcipher.decrypt = decrypt;
281
282
out_put_alg:
283
crypto_mod_put(alg);
284
return inst;
285
}
286
287
static void free(struct crypto_instance *inst)
288
{
289
crypto_drop_spawn(crypto_instance_ctx(inst));
290
kfree(inst);
291
}
292
293
static struct crypto_template crypto_tmpl = {
294
.name = "lrw",
295
.alloc = alloc,
296
.free = free,
297
.module = THIS_MODULE,
298
};
299
300
static int __init crypto_module_init(void)
301
{
302
return crypto_register_template(&crypto_tmpl);
303
}
304
305
static void __exit crypto_module_exit(void)
306
{
307
crypto_unregister_template(&crypto_tmpl);
308
}
309
310
module_init(crypto_module_init);
311
module_exit(crypto_module_exit);
312
313
MODULE_LICENSE("GPL");
314
MODULE_DESCRIPTION("LRW block cipher mode");
315
316