Blame view

crypto/vmac.c 18.8 KB
f1939f7c5   Shane Wang   crypto: vmac - Ne...
1
  /*
bb2964810   Eric Biggers   crypto: vmac - se...
2
3
4
5
   * VMAC: Message Authentication Code using Universal Hashing
   *
   * Reference: https://tools.ietf.org/html/draft-krovetz-vmac-01
   *
f1939f7c5   Shane Wang   crypto: vmac - Ne...
6
   * Copyright (c) 2009, Intel Corporation.
bb2964810   Eric Biggers   crypto: vmac - se...
7
   * Copyright (c) 2018, Google Inc.
f1939f7c5   Shane Wang   crypto: vmac - Ne...
8
9
10
11
12
13
14
15
16
17
18
19
20
21
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms and conditions of the GNU General Public License,
   * version 2, as published by the Free Software Foundation.
   *
   * This program is distributed in the hope it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   * more details.
   *
   * You should have received a copy of the GNU General Public License along with
   * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
   * Place - Suite 330, Boston, MA 02111-1307 USA.
   */
bb2964810   Eric Biggers   crypto: vmac - se...
22
23
24
25
26
27
28
  /*
   * Derived from:
   *	VMAC and VHASH Implementation by Ted Krovetz (tdk@acm.org) and Wei Dai.
   *	This implementation is herby placed in the public domain.
   *	The authors offers no warranty. Use at your own risk.
   *	Last modified: 17 APR 08, 1700 PDT
   */
f1939f7c5   Shane Wang   crypto: vmac - Ne...
29

bb2964810   Eric Biggers   crypto: vmac - se...
30
  #include <asm/unaligned.h>
f1939f7c5   Shane Wang   crypto: vmac - Ne...
31
32
33
  #include <linux/init.h>
  #include <linux/types.h>
  #include <linux/crypto.h>
4bb33cc89   Paul Gortmaker   crypto: add modul...
34
  #include <linux/module.h>
f1939f7c5   Shane Wang   crypto: vmac - Ne...
35
36
37
  #include <linux/scatterlist.h>
  #include <asm/byteorder.h>
  #include <crypto/scatterwalk.h>
f1939f7c5   Shane Wang   crypto: vmac - Ne...
38
39
40
  #include <crypto/internal/hash.h>
  
  /*
bb2964810   Eric Biggers   crypto: vmac - se...
41
42
43
44
45
46
   * User definable settings.
   */
  #define VMAC_TAG_LEN	64
  #define VMAC_KEY_SIZE	128/* Must be 128, 192 or 256			*/
  #define VMAC_KEY_LEN	(VMAC_KEY_SIZE/8)
  #define VMAC_NHBYTES	128/* Must 2^i for any 3 < i < 13 Standard = 128*/
ed331adab   Eric Biggers   crypto: vmac - ad...
47
  #define VMAC_NONCEBYTES	16
bb2964810   Eric Biggers   crypto: vmac - se...
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  
  /* per-transform (per-key) context */
  struct vmac_tfm_ctx {
  	struct crypto_cipher *cipher;
  	u64 nhkey[(VMAC_NHBYTES/8)+2*(VMAC_TAG_LEN/64-1)];
  	u64 polykey[2*VMAC_TAG_LEN/64];
  	u64 l3key[2*VMAC_TAG_LEN/64];
  };
  
  /* per-request context */
  struct vmac_desc_ctx {
  	union {
  		u8 partial[VMAC_NHBYTES];	/* partial block */
  		__le64 partial_words[VMAC_NHBYTES / 8];
  	};
  	unsigned int partial_size;	/* size of the partial block */
  	bool first_block_processed;
  	u64 polytmp[2*VMAC_TAG_LEN/64];	/* running total of L2-hash */
ed331adab   Eric Biggers   crypto: vmac - ad...
66
67
68
69
70
  	union {
  		u8 bytes[VMAC_NONCEBYTES];
  		__be64 pads[VMAC_NONCEBYTES / 8];
  	} nonce;
  	unsigned int nonce_size; /* nonce bytes filled so far */
bb2964810   Eric Biggers   crypto: vmac - se...
71
72
73
  };
  
  /*
f1939f7c5   Shane Wang   crypto: vmac - Ne...
74
75
76
   * Constants and masks
   */
  #define UINT64_C(x) x##ULL
66ce0b0f2   Jussi Kivilinna   crypto: crypto_us...
77
78
79
80
81
  static const u64 p64   = UINT64_C(0xfffffffffffffeff);	/* 2^64 - 257 prime  */
  static const u64 m62   = UINT64_C(0x3fffffffffffffff);	/* 62-bit mask       */
  static const u64 m63   = UINT64_C(0x7fffffffffffffff);	/* 63-bit mask       */
  static const u64 m64   = UINT64_C(0xffffffffffffffff);	/* 64-bit mask       */
  static const u64 mpoly = UINT64_C(0x1fffffff1fffffff);	/* Poly key mask     */
f1939f7c5   Shane Wang   crypto: vmac - Ne...
82

304a204ec   Shane Wang   crypto: vmac - Fi...
83
  #define pe64_to_cpup le64_to_cpup		/* Prefer little endian */
f1939f7c5   Shane Wang   crypto: vmac - Ne...
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
  #ifdef __LITTLE_ENDIAN
  #define INDEX_HIGH 1
  #define INDEX_LOW 0
  #else
  #define INDEX_HIGH 0
  #define INDEX_LOW 1
  #endif
  
  /*
   * The following routines are used in this implementation. They are
   * written via macros to simulate zero-overhead call-by-reference.
   *
   * MUL64: 64x64->128-bit multiplication
   * PMUL64: assumes top bits cleared on inputs
   * ADD128: 128x128->128-bit addition
   */
  
  #define ADD128(rh, rl, ih, il)						\
  	do {								\
  		u64 _il = (il);						\
  		(rl) += (_il);						\
  		if ((rl) < (_il))					\
  			(rh)++;						\
  		(rh) += (ih);						\
  	} while (0)
  
  #define MUL32(i1, i2)	((u64)(u32)(i1)*(u32)(i2))
  
  #define PMUL64(rh, rl, i1, i2)	/* Assumes m doesn't overflow */	\
  	do {								\
  		u64 _i1 = (i1), _i2 = (i2);				\
  		u64 m = MUL32(_i1, _i2>>32) + MUL32(_i1>>32, _i2);	\
  		rh = MUL32(_i1>>32, _i2>>32);				\
  		rl = MUL32(_i1, _i2);					\
  		ADD128(rh, rl, (m >> 32), (m << 32));			\
  	} while (0)
  
  #define MUL64(rh, rl, i1, i2)						\
  	do {								\
  		u64 _i1 = (i1), _i2 = (i2);				\
  		u64 m1 = MUL32(_i1, _i2>>32);				\
  		u64 m2 = MUL32(_i1>>32, _i2);				\
  		rh = MUL32(_i1>>32, _i2>>32);				\
  		rl = MUL32(_i1, _i2);					\
  		ADD128(rh, rl, (m1 >> 32), (m1 << 32));			\
  		ADD128(rh, rl, (m2 >> 32), (m2 << 32));			\
  	} while (0)
  
  /*
   * For highest performance the L1 NH and L2 polynomial hashes should be
25985edce   Lucas De Marchi   Fix common misspe...
134
   * carefully implemented to take advantage of one's target architecture.
f1939f7c5   Shane Wang   crypto: vmac - Ne...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
   * Here these two hash functions are defined multiple time; once for
   * 64-bit architectures, once for 32-bit SSE2 architectures, and once
   * for the rest (32-bit) architectures.
   * For each, nh_16 *must* be defined (works on multiples of 16 bytes).
   * Optionally, nh_vmac_nhbytes can be defined (for multiples of
   * VMAC_NHBYTES), and nh_16_2 and nh_vmac_nhbytes_2 (versions that do two
   * NH computations at once).
   */
  
  #ifdef CONFIG_64BIT
  
  #define nh_16(mp, kp, nw, rh, rl)					\
  	do {								\
  		int i; u64 th, tl;					\
  		rh = rl = 0;						\
  		for (i = 0; i < nw; i += 2) {				\
304a204ec   Shane Wang   crypto: vmac - Fi...
151
152
  			MUL64(th, tl, pe64_to_cpup((mp)+i)+(kp)[i],	\
  				pe64_to_cpup((mp)+i+1)+(kp)[i+1]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
153
154
155
156
157
158
159
160
161
  			ADD128(rh, rl, th, tl);				\
  		}							\
  	} while (0)
  
  #define nh_16_2(mp, kp, nw, rh, rl, rh1, rl1)				\
  	do {								\
  		int i; u64 th, tl;					\
  		rh1 = rl1 = rh = rl = 0;				\
  		for (i = 0; i < nw; i += 2) {				\
304a204ec   Shane Wang   crypto: vmac - Fi...
162
163
  			MUL64(th, tl, pe64_to_cpup((mp)+i)+(kp)[i],	\
  				pe64_to_cpup((mp)+i+1)+(kp)[i+1]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
164
  			ADD128(rh, rl, th, tl);				\
304a204ec   Shane Wang   crypto: vmac - Fi...
165
166
  			MUL64(th, tl, pe64_to_cpup((mp)+i)+(kp)[i+2],	\
  				pe64_to_cpup((mp)+i+1)+(kp)[i+3]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
167
168
169
170
171
172
173
174
175
176
  			ADD128(rh1, rl1, th, tl);			\
  		}							\
  	} while (0)
  
  #if (VMAC_NHBYTES >= 64) /* These versions do 64-bytes of message at a time */
  #define nh_vmac_nhbytes(mp, kp, nw, rh, rl)				\
  	do {								\
  		int i; u64 th, tl;					\
  		rh = rl = 0;						\
  		for (i = 0; i < nw; i += 8) {				\
304a204ec   Shane Wang   crypto: vmac - Fi...
177
178
  			MUL64(th, tl, pe64_to_cpup((mp)+i)+(kp)[i],	\
  				pe64_to_cpup((mp)+i+1)+(kp)[i+1]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
179
  			ADD128(rh, rl, th, tl);				\
304a204ec   Shane Wang   crypto: vmac - Fi...
180
181
  			MUL64(th, tl, pe64_to_cpup((mp)+i+2)+(kp)[i+2],	\
  				pe64_to_cpup((mp)+i+3)+(kp)[i+3]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
182
  			ADD128(rh, rl, th, tl);				\
304a204ec   Shane Wang   crypto: vmac - Fi...
183
184
  			MUL64(th, tl, pe64_to_cpup((mp)+i+4)+(kp)[i+4],	\
  				pe64_to_cpup((mp)+i+5)+(kp)[i+5]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
185
  			ADD128(rh, rl, th, tl);				\
304a204ec   Shane Wang   crypto: vmac - Fi...
186
187
  			MUL64(th, tl, pe64_to_cpup((mp)+i+6)+(kp)[i+6],	\
  				pe64_to_cpup((mp)+i+7)+(kp)[i+7]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
188
189
190
191
192
193
194
195
196
  			ADD128(rh, rl, th, tl);				\
  		}							\
  	} while (0)
  
  #define nh_vmac_nhbytes_2(mp, kp, nw, rh, rl, rh1, rl1)			\
  	do {								\
  		int i; u64 th, tl;					\
  		rh1 = rl1 = rh = rl = 0;				\
  		for (i = 0; i < nw; i += 8) {				\
304a204ec   Shane Wang   crypto: vmac - Fi...
197
198
  			MUL64(th, tl, pe64_to_cpup((mp)+i)+(kp)[i],	\
  				pe64_to_cpup((mp)+i+1)+(kp)[i+1]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
199
  			ADD128(rh, rl, th, tl);				\
304a204ec   Shane Wang   crypto: vmac - Fi...
200
201
  			MUL64(th, tl, pe64_to_cpup((mp)+i)+(kp)[i+2],	\
  				pe64_to_cpup((mp)+i+1)+(kp)[i+3]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
202
  			ADD128(rh1, rl1, th, tl);			\
304a204ec   Shane Wang   crypto: vmac - Fi...
203
204
  			MUL64(th, tl, pe64_to_cpup((mp)+i+2)+(kp)[i+2],	\
  				pe64_to_cpup((mp)+i+3)+(kp)[i+3]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
205
  			ADD128(rh, rl, th, tl);				\
304a204ec   Shane Wang   crypto: vmac - Fi...
206
207
  			MUL64(th, tl, pe64_to_cpup((mp)+i+2)+(kp)[i+4],	\
  				pe64_to_cpup((mp)+i+3)+(kp)[i+5]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
208
  			ADD128(rh1, rl1, th, tl);			\
304a204ec   Shane Wang   crypto: vmac - Fi...
209
210
  			MUL64(th, tl, pe64_to_cpup((mp)+i+4)+(kp)[i+4],	\
  				pe64_to_cpup((mp)+i+5)+(kp)[i+5]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
211
  			ADD128(rh, rl, th, tl);				\
304a204ec   Shane Wang   crypto: vmac - Fi...
212
213
  			MUL64(th, tl, pe64_to_cpup((mp)+i+4)+(kp)[i+6],	\
  				pe64_to_cpup((mp)+i+5)+(kp)[i+7]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
214
  			ADD128(rh1, rl1, th, tl);			\
304a204ec   Shane Wang   crypto: vmac - Fi...
215
216
  			MUL64(th, tl, pe64_to_cpup((mp)+i+6)+(kp)[i+6],	\
  				pe64_to_cpup((mp)+i+7)+(kp)[i+7]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
217
  			ADD128(rh, rl, th, tl);				\
304a204ec   Shane Wang   crypto: vmac - Fi...
218
219
  			MUL64(th, tl, pe64_to_cpup((mp)+i+6)+(kp)[i+8],	\
  				pe64_to_cpup((mp)+i+7)+(kp)[i+9]);	\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
  			ADD128(rh1, rl1, th, tl);			\
  		}							\
  	} while (0)
  #endif
  
  #define poly_step(ah, al, kh, kl, mh, ml)				\
  	do {								\
  		u64 t1h, t1l, t2h, t2l, t3h, t3l, z = 0;		\
  		/* compute ab*cd, put bd into result registers */	\
  		PMUL64(t3h, t3l, al, kh);				\
  		PMUL64(t2h, t2l, ah, kl);				\
  		PMUL64(t1h, t1l, ah, 2*kh);				\
  		PMUL64(ah, al, al, kl);					\
  		/* add 2 * ac to result */				\
  		ADD128(ah, al, t1h, t1l);				\
  		/* add together ad + bc */				\
  		ADD128(t2h, t2l, t3h, t3l);				\
  		/* now (ah,al), (t2l,2*t2h) need summing */		\
  		/* first add the high registers, carrying into t2h */	\
  		ADD128(t2h, ah, z, t2l);				\
  		/* double t2h and add top bit of ah */			\
  		t2h = 2 * t2h + (ah >> 63);				\
  		ah &= m63;						\
  		/* now add the low registers */				\
  		ADD128(ah, al, mh, ml);					\
  		ADD128(ah, al, z, t2h);					\
  	} while (0)
  
  #else /* ! CONFIG_64BIT */
  
  #ifndef nh_16
  #define nh_16(mp, kp, nw, rh, rl)					\
  	do {								\
  		u64 t1, t2, m1, m2, t;					\
  		int i;							\
  		rh = rl = t = 0;					\
  		for (i = 0; i < nw; i += 2)  {				\
304a204ec   Shane Wang   crypto: vmac - Fi...
257
258
  			t1 = pe64_to_cpup(mp+i) + kp[i];		\
  			t2 = pe64_to_cpup(mp+i+1) + kp[i+1];		\
f1939f7c5   Shane Wang   crypto: vmac - Ne...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
  			m2 = MUL32(t1 >> 32, t2);			\
  			m1 = MUL32(t1, t2 >> 32);			\
  			ADD128(rh, rl, MUL32(t1 >> 32, t2 >> 32),	\
  				MUL32(t1, t2));				\
  			rh += (u64)(u32)(m1 >> 32)			\
  				+ (u32)(m2 >> 32);			\
  			t += (u64)(u32)m1 + (u32)m2;			\
  		}							\
  		ADD128(rh, rl, (t >> 32), (t << 32));			\
  	} while (0)
  #endif
  
  static void poly_step_func(u64 *ahi, u64 *alo,
  			const u64 *kh, const u64 *kl,
  			const u64 *mh, const u64 *ml)
  {
  #define a0 (*(((u32 *)alo)+INDEX_LOW))
  #define a1 (*(((u32 *)alo)+INDEX_HIGH))
  #define a2 (*(((u32 *)ahi)+INDEX_LOW))
  #define a3 (*(((u32 *)ahi)+INDEX_HIGH))
  #define k0 (*(((u32 *)kl)+INDEX_LOW))
  #define k1 (*(((u32 *)kl)+INDEX_HIGH))
  #define k2 (*(((u32 *)kh)+INDEX_LOW))
  #define k3 (*(((u32 *)kh)+INDEX_HIGH))
  
  	u64 p, q, t;
  	u32 t2;
  
  	p = MUL32(a3, k3);
  	p += p;
  	p += *(u64 *)mh;
  	p += MUL32(a0, k2);
  	p += MUL32(a1, k1);
  	p += MUL32(a2, k0);
  	t = (u32)(p);
  	p >>= 32;
  	p += MUL32(a0, k3);
  	p += MUL32(a1, k2);
  	p += MUL32(a2, k1);
  	p += MUL32(a3, k0);
  	t |= ((u64)((u32)p & 0x7fffffff)) << 32;
  	p >>= 31;
  	p += (u64)(((u32 *)ml)[INDEX_LOW]);
  	p += MUL32(a0, k0);
  	q =  MUL32(a1, k3);
  	q += MUL32(a2, k2);
  	q += MUL32(a3, k1);
  	q += q;
  	p += q;
  	t2 = (u32)(p);
  	p >>= 32;
  	p += (u64)(((u32 *)ml)[INDEX_HIGH]);
  	p += MUL32(a0, k1);
  	p += MUL32(a1, k0);
  	q =  MUL32(a2, k3);
  	q += MUL32(a3, k2);
  	q += q;
  	p += q;
  	*(u64 *)(alo) = (p << 32) | t2;
  	p >>= 32;
  	*(u64 *)(ahi) = p + t;
  
  #undef a0
  #undef a1
  #undef a2
  #undef a3
  #undef k0
  #undef k1
  #undef k2
  #undef k3
  }
  
  #define poly_step(ah, al, kh, kl, mh, ml)				\
  	poly_step_func(&(ah), &(al), &(kh), &(kl), &(mh), &(ml))
  
  #endif  /* end of specialized NH and poly definitions */
  
  /* At least nh_16 is defined. Defined others as needed here */
  #ifndef nh_16_2
  #define nh_16_2(mp, kp, nw, rh, rl, rh2, rl2)				\
  	do { 								\
  		nh_16(mp, kp, nw, rh, rl);				\
  		nh_16(mp, ((kp)+2), nw, rh2, rl2);			\
  	} while (0)
  #endif
  #ifndef nh_vmac_nhbytes
  #define nh_vmac_nhbytes(mp, kp, nw, rh, rl)				\
  	nh_16(mp, kp, nw, rh, rl)
  #endif
  #ifndef nh_vmac_nhbytes_2
  #define nh_vmac_nhbytes_2(mp, kp, nw, rh, rl, rh2, rl2)			\
  	do {								\
  		nh_vmac_nhbytes(mp, kp, nw, rh, rl);			\
  		nh_vmac_nhbytes(mp, ((kp)+2), nw, rh2, rl2);		\
  	} while (0)
  #endif
304a204ec   Shane Wang   crypto: vmac - Fi...
355
  static u64 l3hash(u64 p1, u64 p2, u64 k1, u64 k2, u64 len)
f1939f7c5   Shane Wang   crypto: vmac - Ne...
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
  {
  	u64 rh, rl, t, z = 0;
  
  	/* fully reduce (p1,p2)+(len,0) mod p127 */
  	t = p1 >> 63;
  	p1 &= m63;
  	ADD128(p1, p2, len, t);
  	/* At this point, (p1,p2) is at most 2^127+(len<<64) */
  	t = (p1 > m63) + ((p1 == m63) && (p2 == m64));
  	ADD128(p1, p2, z, t);
  	p1 &= m63;
  
  	/* compute (p1,p2)/(2^64-2^32) and (p1,p2)%(2^64-2^32) */
  	t = p1 + (p2 >> 32);
  	t += (t >> 32);
  	t += (u32)t > 0xfffffffeu;
  	p1 += (t >> 32);
  	p2 += (p1 << 32);
  
  	/* compute (p1+k1)%p64 and (p2+k2)%p64 */
  	p1 += k1;
  	p1 += (0 - (p1 < k1)) & 257;
  	p2 += k2;
  	p2 += (0 - (p2 < k2)) & 257;
  
  	/* compute (p1+k1)*(p2+k2)%p64 */
  	MUL64(rh, rl, p1, p2);
  	t = rh >> 56;
  	ADD128(t, rl, z, rh);
  	rh <<= 8;
  	ADD128(t, rl, z, rh);
  	t += t << 8;
  	rl += t;
  	rl += (0 - (rl < t)) & 257;
  	rl += (0 - (rl > p64-1)) & 257;
  	return rl;
  }
bb2964810   Eric Biggers   crypto: vmac - se...
393
394
395
396
  /* L1 and L2-hash one or more VMAC_NHBYTES-byte blocks */
  static void vhash_blocks(const struct vmac_tfm_ctx *tctx,
  			 struct vmac_desc_ctx *dctx,
  			 const __le64 *mptr, unsigned int blocks)
f1939f7c5   Shane Wang   crypto: vmac - Ne...
397
  {
bb2964810   Eric Biggers   crypto: vmac - se...
398
399
400
401
402
403
404
405
406
  	const u64 *kptr = tctx->nhkey;
  	const u64 pkh = tctx->polykey[0];
  	const u64 pkl = tctx->polykey[1];
  	u64 ch = dctx->polytmp[0];
  	u64 cl = dctx->polytmp[1];
  	u64 rh, rl;
  
  	if (!dctx->first_block_processed) {
  		dctx->first_block_processed = true;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
407
408
409
410
  		nh_vmac_nhbytes(mptr, kptr, VMAC_NHBYTES/8, rh, rl);
  		rh &= m62;
  		ADD128(ch, cl, rh, rl);
  		mptr += (VMAC_NHBYTES/sizeof(u64));
bb2964810   Eric Biggers   crypto: vmac - se...
411
  		blocks--;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
412
  	}
bb2964810   Eric Biggers   crypto: vmac - se...
413
  	while (blocks--) {
f1939f7c5   Shane Wang   crypto: vmac - Ne...
414
415
416
417
418
  		nh_vmac_nhbytes(mptr, kptr, VMAC_NHBYTES/8, rh, rl);
  		rh &= m62;
  		poly_step(ch, cl, pkh, pkl, rh, rl);
  		mptr += (VMAC_NHBYTES/sizeof(u64));
  	}
bb2964810   Eric Biggers   crypto: vmac - se...
419
420
  	dctx->polytmp[0] = ch;
  	dctx->polytmp[1] = cl;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
421
  }
bb2964810   Eric Biggers   crypto: vmac - se...
422
423
  static int vmac_setkey(struct crypto_shash *tfm,
  		       const u8 *key, unsigned int keylen)
f1939f7c5   Shane Wang   crypto: vmac - Ne...
424
  {
bb2964810   Eric Biggers   crypto: vmac - se...
425
426
427
428
429
  	struct vmac_tfm_ctx *tctx = crypto_shash_ctx(tfm);
  	__be64 out[2];
  	u8 in[16] = { 0 };
  	unsigned int i;
  	int err;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
430

674f368a9   Eric Biggers   crypto: remove CR...
431
  	if (keylen != VMAC_KEY_LEN)
bb2964810   Eric Biggers   crypto: vmac - se...
432
  		return -EINVAL;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
433

bb2964810   Eric Biggers   crypto: vmac - se...
434
  	err = crypto_cipher_setkey(tctx->cipher, key, keylen);
f1939f7c5   Shane Wang   crypto: vmac - Ne...
435
436
437
438
  	if (err)
  		return err;
  
  	/* Fill nh key */
bb2964810   Eric Biggers   crypto: vmac - se...
439
440
441
442
443
444
  	in[0] = 0x80;
  	for (i = 0; i < ARRAY_SIZE(tctx->nhkey); i += 2) {
  		crypto_cipher_encrypt_one(tctx->cipher, (u8 *)out, in);
  		tctx->nhkey[i] = be64_to_cpu(out[0]);
  		tctx->nhkey[i+1] = be64_to_cpu(out[1]);
  		in[15]++;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
445
446
447
  	}
  
  	/* Fill poly key */
bb2964810   Eric Biggers   crypto: vmac - se...
448
449
450
451
452
453
454
  	in[0] = 0xC0;
  	in[15] = 0;
  	for (i = 0; i < ARRAY_SIZE(tctx->polykey); i += 2) {
  		crypto_cipher_encrypt_one(tctx->cipher, (u8 *)out, in);
  		tctx->polykey[i] = be64_to_cpu(out[0]) & mpoly;
  		tctx->polykey[i+1] = be64_to_cpu(out[1]) & mpoly;
  		in[15]++;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
455
456
457
  	}
  
  	/* Fill ip key */
bb2964810   Eric Biggers   crypto: vmac - se...
458
459
460
  	in[0] = 0xE0;
  	in[15] = 0;
  	for (i = 0; i < ARRAY_SIZE(tctx->l3key); i += 2) {
f1939f7c5   Shane Wang   crypto: vmac - Ne...
461
  		do {
bb2964810   Eric Biggers   crypto: vmac - se...
462
463
464
465
466
  			crypto_cipher_encrypt_one(tctx->cipher, (u8 *)out, in);
  			tctx->l3key[i] = be64_to_cpu(out[0]);
  			tctx->l3key[i+1] = be64_to_cpu(out[1]);
  			in[15]++;
  		} while (tctx->l3key[i] >= p64 || tctx->l3key[i+1] >= p64);
f1939f7c5   Shane Wang   crypto: vmac - Ne...
467
  	}
bb2964810   Eric Biggers   crypto: vmac - se...
468
  	return 0;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
469
  }
bb2964810   Eric Biggers   crypto: vmac - se...
470
  static int vmac_init(struct shash_desc *desc)
f1939f7c5   Shane Wang   crypto: vmac - Ne...
471
  {
bb2964810   Eric Biggers   crypto: vmac - se...
472
473
  	const struct vmac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
  	struct vmac_desc_ctx *dctx = shash_desc_ctx(desc);
f1939f7c5   Shane Wang   crypto: vmac - Ne...
474

bb2964810   Eric Biggers   crypto: vmac - se...
475
476
477
  	dctx->partial_size = 0;
  	dctx->first_block_processed = false;
  	memcpy(dctx->polytmp, tctx->polykey, sizeof(dctx->polytmp));
ed331adab   Eric Biggers   crypto: vmac - ad...
478
479
480
  	dctx->nonce_size = 0;
  	return 0;
  }
bb2964810   Eric Biggers   crypto: vmac - se...
481
  static int vmac_update(struct shash_desc *desc, const u8 *p, unsigned int len)
f1939f7c5   Shane Wang   crypto: vmac - Ne...
482
  {
bb2964810   Eric Biggers   crypto: vmac - se...
483
484
485
  	const struct vmac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
  	struct vmac_desc_ctx *dctx = shash_desc_ctx(desc);
  	unsigned int n;
ed331adab   Eric Biggers   crypto: vmac - ad...
486
487
488
489
490
491
492
493
  	/* Nonce is passed as first VMAC_NONCEBYTES bytes of data */
  	if (dctx->nonce_size < VMAC_NONCEBYTES) {
  		n = min(len, VMAC_NONCEBYTES - dctx->nonce_size);
  		memcpy(&dctx->nonce.bytes[dctx->nonce_size], p, n);
  		dctx->nonce_size += n;
  		p += n;
  		len -= n;
  	}
bb2964810   Eric Biggers   crypto: vmac - se...
494
495
496
497
498
499
500
501
502
503
504
  	if (dctx->partial_size) {
  		n = min(len, VMAC_NHBYTES - dctx->partial_size);
  		memcpy(&dctx->partial[dctx->partial_size], p, n);
  		dctx->partial_size += n;
  		p += n;
  		len -= n;
  		if (dctx->partial_size == VMAC_NHBYTES) {
  			vhash_blocks(tctx, dctx, dctx->partial_words, 1);
  			dctx->partial_size = 0;
  		}
  	}
ba1ee0709   Salman Qazi   crypto: vmac - Ma...
505

bb2964810   Eric Biggers   crypto: vmac - se...
506
507
508
509
510
511
  	if (len >= VMAC_NHBYTES) {
  		n = round_down(len, VMAC_NHBYTES);
  		/* TODO: 'p' may be misaligned here */
  		vhash_blocks(tctx, dctx, (const __le64 *)p, n / VMAC_NHBYTES);
  		p += n;
  		len -= n;
ba1ee0709   Salman Qazi   crypto: vmac - Ma...
512
  	}
bb2964810   Eric Biggers   crypto: vmac - se...
513
514
515
516
  	if (len) {
  		memcpy(dctx->partial, p, len);
  		dctx->partial_size = len;
  	}
f1939f7c5   Shane Wang   crypto: vmac - Ne...
517
518
519
  
  	return 0;
  }
bb2964810   Eric Biggers   crypto: vmac - se...
520
521
  static u64 vhash_final(const struct vmac_tfm_ctx *tctx,
  		       struct vmac_desc_ctx *dctx)
f1939f7c5   Shane Wang   crypto: vmac - Ne...
522
  {
bb2964810   Eric Biggers   crypto: vmac - se...
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
  	unsigned int partial = dctx->partial_size;
  	u64 ch = dctx->polytmp[0];
  	u64 cl = dctx->polytmp[1];
  
  	/* L1 and L2-hash the final block if needed */
  	if (partial) {
  		/* Zero-pad to next 128-bit boundary */
  		unsigned int n = round_up(partial, 16);
  		u64 rh, rl;
  
  		memset(&dctx->partial[partial], 0, n - partial);
  		nh_16(dctx->partial_words, tctx->nhkey, n / 8, rh, rl);
  		rh &= m62;
  		if (dctx->first_block_processed)
  			poly_step(ch, cl, tctx->polykey[0], tctx->polykey[1],
  				  rh, rl);
  		else
  			ADD128(ch, cl, rh, rl);
ba1ee0709   Salman Qazi   crypto: vmac - Ma...
541
  	}
bb2964810   Eric Biggers   crypto: vmac - se...
542
543
544
545
  
  	/* L3-hash the 128-bit output of L2-hash */
  	return l3hash(ch, cl, tctx->l3key[0], tctx->l3key[1], partial * 8);
  }
0917b8731   Eric Biggers   crypto: vmac - re...
546
  static int vmac_final(struct shash_desc *desc, u8 *out)
bb2964810   Eric Biggers   crypto: vmac - se...
547
548
549
  {
  	const struct vmac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
  	struct vmac_desc_ctx *dctx = shash_desc_ctx(desc);
bb2964810   Eric Biggers   crypto: vmac - se...
550
551
  	int index;
  	u64 hash, pad;
ed331adab   Eric Biggers   crypto: vmac - ad...
552
553
554
555
556
557
558
559
560
561
562
  	if (dctx->nonce_size != VMAC_NONCEBYTES)
  		return -EINVAL;
  
  	/*
  	 * The VMAC specification requires a nonce at least 1 bit shorter than
  	 * the block cipher's block length, so we actually only accept a 127-bit
  	 * nonce.  We define the unused bit to be the first one and require that
  	 * it be 0, so the needed prepending of a 0 bit is implicit.
  	 */
  	if (dctx->nonce.bytes[0] & 0x80)
  		return -EINVAL;
bb2964810   Eric Biggers   crypto: vmac - se...
563
564
565
566
  	/* Finish calculating the VHASH of the message */
  	hash = vhash_final(tctx, dctx);
  
  	/* Generate pseudorandom pad by encrypting the nonce */
ed331adab   Eric Biggers   crypto: vmac - ad...
567
568
569
570
571
572
  	BUILD_BUG_ON(VMAC_NONCEBYTES != 2 * (VMAC_TAG_LEN / 8));
  	index = dctx->nonce.bytes[VMAC_NONCEBYTES - 1] & 1;
  	dctx->nonce.bytes[VMAC_NONCEBYTES - 1] &= ~1;
  	crypto_cipher_encrypt_one(tctx->cipher, dctx->nonce.bytes,
  				  dctx->nonce.bytes);
  	pad = be64_to_cpu(dctx->nonce.pads[index]);
bb2964810   Eric Biggers   crypto: vmac - se...
573
574
  
  	/* The VMAC is the sum of VHASH and the pseudorandom pad */
0917b8731   Eric Biggers   crypto: vmac - re...
575
  	put_unaligned_be64(hash + pad, out);
f1939f7c5   Shane Wang   crypto: vmac - Ne...
576
577
578
579
580
  	return 0;
  }
  
  static int vmac_init_tfm(struct crypto_tfm *tfm)
  {
bb2964810   Eric Biggers   crypto: vmac - se...
581
  	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
d5ed3b65f   Eric Biggers   crypto: cipher - ...
582
  	struct crypto_cipher_spawn *spawn = crypto_instance_ctx(inst);
bb2964810   Eric Biggers   crypto: vmac - se...
583
584
  	struct vmac_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
  	struct crypto_cipher *cipher;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
585
586
587
588
  
  	cipher = crypto_spawn_cipher(spawn);
  	if (IS_ERR(cipher))
  		return PTR_ERR(cipher);
bb2964810   Eric Biggers   crypto: vmac - se...
589
  	tctx->cipher = cipher;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
590
591
592
593
594
  	return 0;
  }
  
  static void vmac_exit_tfm(struct crypto_tfm *tfm)
  {
bb2964810   Eric Biggers   crypto: vmac - se...
595
596
597
  	struct vmac_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
  
  	crypto_free_cipher(tctx->cipher);
f1939f7c5   Shane Wang   crypto: vmac - Ne...
598
  }
0917b8731   Eric Biggers   crypto: vmac - re...
599
  static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb)
f1939f7c5   Shane Wang   crypto: vmac - Ne...
600
601
  {
  	struct shash_instance *inst;
3b4e73d8c   Eric Biggers   crypto: vmac - us...
602
  	struct crypto_cipher_spawn *spawn;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
603
  	struct crypto_alg *alg;
7bcb2c99f   Eric Biggers   crypto: algapi - ...
604
  	u32 mask;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
605
  	int err;
7bcb2c99f   Eric Biggers   crypto: algapi - ...
606
  	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH, &mask);
f1939f7c5   Shane Wang   crypto: vmac - Ne...
607
608
  	if (err)
  		return err;
3b4e73d8c   Eric Biggers   crypto: vmac - us...
609
610
611
612
613
614
  	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  	if (!inst)
  		return -ENOMEM;
  	spawn = shash_instance_ctx(inst);
  
  	err = crypto_grab_cipher(spawn, shash_crypto_instance(inst),
7bcb2c99f   Eric Biggers   crypto: algapi - ...
615
  				 crypto_attr_alg_name(tb[1]), 0, mask);
3b4e73d8c   Eric Biggers   crypto: vmac - us...
616
617
618
  	if (err)
  		goto err_free_inst;
  	alg = crypto_spawn_cipher_alg(spawn);
f1939f7c5   Shane Wang   crypto: vmac - Ne...
619

73bf20ef3   Eric Biggers   crypto: vmac - re...
620
  	err = -EINVAL;
ed331adab   Eric Biggers   crypto: vmac - ad...
621
  	if (alg->cra_blocksize != VMAC_NONCEBYTES)
3b4e73d8c   Eric Biggers   crypto: vmac - us...
622
  		goto err_free_inst;
73bf20ef3   Eric Biggers   crypto: vmac - re...
623

3b4e73d8c   Eric Biggers   crypto: vmac - us...
624
  	err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg);
f1939f7c5   Shane Wang   crypto: vmac - Ne...
625
  	if (err)
3b4e73d8c   Eric Biggers   crypto: vmac - us...
626
  		goto err_free_inst;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
627
628
629
630
  
  	inst->alg.base.cra_priority = alg->cra_priority;
  	inst->alg.base.cra_blocksize = alg->cra_blocksize;
  	inst->alg.base.cra_alignmask = alg->cra_alignmask;
bb2964810   Eric Biggers   crypto: vmac - se...
631
  	inst->alg.base.cra_ctxsize = sizeof(struct vmac_tfm_ctx);
f1939f7c5   Shane Wang   crypto: vmac - Ne...
632
633
  	inst->alg.base.cra_init = vmac_init_tfm;
  	inst->alg.base.cra_exit = vmac_exit_tfm;
bb2964810   Eric Biggers   crypto: vmac - se...
634
635
  	inst->alg.descsize = sizeof(struct vmac_desc_ctx);
  	inst->alg.digestsize = VMAC_TAG_LEN / 8;
0917b8731   Eric Biggers   crypto: vmac - re...
636
  	inst->alg.init = vmac_init;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
637
  	inst->alg.update = vmac_update;
0917b8731   Eric Biggers   crypto: vmac - re...
638
  	inst->alg.final = vmac_final;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
639
  	inst->alg.setkey = vmac_setkey;
a39c66cc2   Eric Biggers   crypto: shash - c...
640
  	inst->free = shash_free_singlespawn_instance;
f1939f7c5   Shane Wang   crypto: vmac - Ne...
641
642
  	err = shash_register_instance(tmpl, inst);
  	if (err) {
3b4e73d8c   Eric Biggers   crypto: vmac - us...
643
  err_free_inst:
a39c66cc2   Eric Biggers   crypto: shash - c...
644
  		shash_free_singlespawn_instance(inst);
f1939f7c5   Shane Wang   crypto: vmac - Ne...
645
  	}
f1939f7c5   Shane Wang   crypto: vmac - Ne...
646
647
  	return err;
  }
ed331adab   Eric Biggers   crypto: vmac - ad...
648
649
  static struct crypto_template vmac64_tmpl = {
  	.name = "vmac64",
0917b8731   Eric Biggers   crypto: vmac - re...
650
  	.create = vmac_create,
ed331adab   Eric Biggers   crypto: vmac - ad...
651
652
  	.module = THIS_MODULE,
  };
f1939f7c5   Shane Wang   crypto: vmac - Ne...
653
654
  static int __init vmac_module_init(void)
  {
0917b8731   Eric Biggers   crypto: vmac - re...
655
  	return crypto_register_template(&vmac64_tmpl);
f1939f7c5   Shane Wang   crypto: vmac - Ne...
656
657
658
659
  }
  
  static void __exit vmac_module_exit(void)
  {
ed331adab   Eric Biggers   crypto: vmac - ad...
660
  	crypto_unregister_template(&vmac64_tmpl);
f1939f7c5   Shane Wang   crypto: vmac - Ne...
661
  }
c4741b230   Eric Biggers   crypto: run initc...
662
  subsys_initcall(vmac_module_init);
f1939f7c5   Shane Wang   crypto: vmac - Ne...
663
664
665
666
  module_exit(vmac_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("VMAC hash algorithm");
ed331adab   Eric Biggers   crypto: vmac - ad...
667
  MODULE_ALIAS_CRYPTO("vmac64");