summaryrefslogtreecommitdiff
path: root/lib/crypto/x86/aes-aesni.S
blob: 6795e82c34c82e64192f2a6803635ddeca3cc00a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
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
257
258
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
355
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
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
/* SPDX-License-Identifier: GPL-2.0-or-later */
//
// AES block cipher using AES-NI instructions
//
// Copyright 2026 Google LLC
//
// The code in this file supports 32-bit and 64-bit CPUs (except for
// aes_ctr64_crypt_aesni() which supports 64-bit only), and it doesn't require
// AVX.  It does use up to SSE4.1, which all CPUs with AES-NI have.
#include <linux/linkage.h>

#ifdef __x86_64__
#define RODATA(label)	label(%rip)

#define ARG0		%rdi
#define ARG1		%rsi
#define ARG2		%rdx
#define ARG2_32		%edx
#define ARG3		%rcx
#define ARG4		%r8
#define TMP		%rax
#define TMP_32		%eax
#define TMP_16		%ax
#define TMP_8		%al

#else // __x86_64__

#define RODATA(label)	label

// Caller-save GPRs and the first 3 function arguments, assuming -mregparm=3
#define ARG0		%eax
#define ARG1		%edx
#define ARG2		%ecx
#define ARG2_32		%ecx

// *Callee*-save GPRs.
#define ARG3		%edi
#define ARG4		%esi
#define TMP		%ebx
#define TMP_32		%ebx
#define TMP_16		%bx
#define TMP_8		%bl
#endif // !__x86_64__

// Offsets in struct aes_key
#define OFFSETOF_NROUNDS	4
#define OFFSETOF_ROUNDKEYS	16
#define OFFSETOF_INVROUNDKEYS	256

.section .rodata
.p2align 4
.Lxts_gf_poly:
	// For XTS: a constant used when advancing the tweak by one block by
	// multiplying by the polynomial 'x' in GF(2^128).  The low 64 bits of
	// this value represent the polynomial x^7 + x^2 + x + 1; it is the
	// value that must be XOR'd into the low 64 bits of the tweak each time
	// a 1 is carried out of the high 64 bits.
	//
	// The high 64 bits of this value is just the internal carry bit that
	// exists when there's a carry out of the low 64 bits of the tweak.
	.quad	0x87, 1

#ifdef __x86_64__
.Lbswap_mask:
	// A mask for pshufb that byte-reflects the value.
	.byte	15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#endif

.Lexpandkey_mask:
	// A mask for pshufb that extracts the last dword, rotates it right by 8
	// bits, and copies the result to all four dwords.
	.byte	13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12

.Lrcon:
	// The AES round constants, used during key expansion
	.long	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36

.Lcts_permute_table:
	.byte	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
	.byte	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
	.byte	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
	.byte	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
	.byte	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
	.byte	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80

.text

// In 32-bit mode, push certain callee-saved GPRs and optionally load function
// arguments from the stack into them.  Do nothing in 64-bit mode.
//
// TMP is always made available as a temporary register.
//
// \uses_arg3 is 0 to not touch ARG3, 1 to make it available as a temporary
// register only, or 2 to actually load it as an argument from the stack.
// Likewise for \uses_arg4 and ARG4.  It's assumed the -mregparm=3 convention is
// being used and %esp hasn't been modified since function entry.
.macro _prologue	uses_arg3=0, uses_arg4=0
#ifdef __i386__
	.set	ARG3_OFFSET, 4	// Assuming -mregparm=3
	.set	ARG3_PUSHED, \uses_arg3
	.set	ARG4_PUSHED, \uses_arg4
.if \uses_arg3
	push	ARG3
	.set	ARG3_OFFSET, ARG3_OFFSET + 4
  .if \uses_arg3 == 2
	mov	ARG3_OFFSET(%esp), ARG3
  .endif
.endif
.if \uses_arg4
	push	ARG4
	.set	ARG3_OFFSET, ARG3_OFFSET + 4
  .if \uses_arg4 == 2
	mov	ARG3_OFFSET+4(%esp), ARG4
  .endif
.endif
	push	TMP
	.set	ARG3_OFFSET, ARG3_OFFSET + 4
#endif // __i386__
.endm

.macro _reload_arg3
#ifdef __i386__
	mov	ARG3_OFFSET(%esp), ARG3
#endif
.endm

// Undo any pushes that _prologue did, then return.
.macro _epilogue
#ifdef __i386__
	pop	TMP
.if ARG4_PUSHED
	pop	ARG4
.endif
.if ARG3_PUSHED
	pop	ARG3
.endif
#endif
	RET
.endm

.macro	_aesenc		enc, rndkey, data
.if \enc
	aesenc		\rndkey, \data
.else
	aesdec		\rndkey, \data
.endif
.endm

.macro	_aesenclast	enc, rndkeylast, data
.if \enc
	aesenclast	\rndkeylast, \data
.else
	aesdeclast	\rndkeylast, \data
.endif
.endm

// Transform four dwords [a0, a1, a2, a3] in \a into
// [a0, a0^a1, a0^a1^a2, a0^a1^a2^a3].  \tmp is a temporary xmm register.
//
// Note: this could be done in four instructions, shufps + pxor + shufps + pxor,
// if the temporary register were zero-initialized ahead of time.  We instead do
// it in an easier-to-understand way that doesn't require zero-initialization
// and avoids the unusual shufps instruction.  movdqa is usually "free" anyway.
.macro	_prefix_sum	a, tmp
	movdqa		\a, \tmp	// [a0, a1, a2, a3]
	pslldq		$4, \a		// [0, a0, a1, a2]
	pxor		\tmp, \a	// [a0, a0^a1, a1^a2, a2^a3]
	movdqa		\a, \tmp
	pslldq		$8, \a		// [0, 0, a0, a0^a1]
	pxor		\tmp, \a	// [a0, a0^a1, a0^a1^a2, a0^a1^a2^a3]
.endm

.macro	_gen_round_key	a, b
	// Compute four copies of rcon[i] ^ SubBytes(ror32(w, 8)), where w is
	// the last dword of the previous round key (given in \b).
	//
	// 'aesenclast src, dst' does dst = src XOR SubBytes(ShiftRows(dst)).
	// It is used here solely for the SubBytes and the XOR.  The ShiftRows
	// is a no-op because all four columns are the same here.
	//
	// Don't use the 'aeskeygenassist' instruction, since:
	//  - On most Intel CPUs it is microcoded, making it have a much higher
	//    latency and use more execution ports than 'aesenclast'.
	//  - It cannot be used in a loop, since it requires an immediate.
	//  - It doesn't do much more than 'aesenclast' in the first place.
	movdqa		\b, %xmm2
	pshufb		MASK, %xmm2
	aesenclast	RCON, %xmm2

	// XOR in the prefix sum of the four dwords of \a, which is the
	// previous round key (AES-128) or the first round key in the previous
	// pair of round keys (AES-256).  The result is the next round key.
	_prefix_sum	\a, tmp=%xmm3
	pxor		%xmm2, \a

	// Store the next round key to memory.  Also leave it in \a.
	movdqu		\a, (RNDKEYS)
.endm

.macro	_aes_expandkey_aesni	is_aes128
	// Arguments
	.set	RNDKEYS,	ARG0
	.set	INV_RNDKEYS,	ARG1
	.set	IN_KEY,		ARG2

	// Other local variables
	.set	RCON_PTR,	ARG3
	.set	COUNTER,	TMP_32
	.set	RCON,		%xmm6
	.set	MASK,		%xmm7

	_prologue	uses_arg3=1

.if \is_aes128
	// AES-128: the first round key is simply a copy of the raw key.
	movdqu		(IN_KEY), %xmm0
	movdqu		%xmm0, (RNDKEYS)
.else
	// AES-256: the first two round keys are simply a copy of the raw key.
	movdqu		(IN_KEY), %xmm0
	movdqu		%xmm0, (RNDKEYS)
	movdqu		16(IN_KEY), %xmm1
	movdqu		%xmm1, 16(RNDKEYS)
	add		$32, RNDKEYS
.endif

	// Generate the remaining round keys.
	movdqa		RODATA(.Lexpandkey_mask), MASK
.if \is_aes128
	lea		RODATA(.Lrcon), RCON_PTR
	mov		$10, COUNTER
.Lgen_next_aes128_round_key:
	add		$16, RNDKEYS
	movd		(RCON_PTR), RCON
	pshufd		$0x00, RCON, RCON
	add		$4, RCON_PTR
	_gen_round_key	%xmm0, %xmm0
	dec		COUNTER
	jnz		.Lgen_next_aes128_round_key
.else
	// AES-256: only the first 7 round constants are needed, so instead of
	// loading each one from memory, just start by loading [1, 1, 1, 1] and
	// then generate the rest by doubling.
	pshufd		$0x00, RODATA(.Lrcon), RCON
	pxor		%xmm5, %xmm5	// All-zeroes
	mov		$7, COUNTER
.Lgen_next_aes256_round_key_pair:
	// Generate the next AES-256 round key: either the first of a pair of
	// two, or the last one.
	_gen_round_key	%xmm0, %xmm1

	dec		COUNTER
	jz		.Lgen_aes256_round_keys_done

	// Generate the second AES-256 round key of the pair.  Compared to the
	// first, there's no rotation and no XOR of a round constant.
	pshufd		$0xff, %xmm0, %xmm2	// Get four copies of last dword
	aesenclast	%xmm5, %xmm2		// Just does SubBytes
	_prefix_sum	%xmm1, tmp=%xmm3
	pxor		%xmm2, %xmm1
	movdqu		%xmm1, 16(RNDKEYS)
	add		$32, RNDKEYS
	paddd		RCON, RCON		// RCON <<= 1
	jmp		.Lgen_next_aes256_round_key_pair
.Lgen_aes256_round_keys_done:
.endif

	// If INV_RNDKEYS is non-NULL, write the round keys for the Equivalent
	// Inverse Cipher to it.  To do that, reverse the standard round keys,
	// and apply aesimc (InvMixColumn) to each except the first and last.
	test		INV_RNDKEYS, INV_RNDKEYS
	jz		.Ldone\@
	movdqu		(RNDKEYS), %xmm0	// Last standard round key
	movdqu		%xmm0, (INV_RNDKEYS)	// => First inverse round key
.if \is_aes128
	mov		$9, COUNTER
.else
	mov		$13, COUNTER
.endif
.Lgen_next_inv_round_key\@:
	sub		$16, RNDKEYS
	add		$16, INV_RNDKEYS
	movdqu		(RNDKEYS), %xmm0
	aesimc		%xmm0, %xmm0
	movdqu		%xmm0, (INV_RNDKEYS)
	dec		COUNTER
	jnz		.Lgen_next_inv_round_key\@
	movdqu		-16(RNDKEYS), %xmm0	// First standard round key
	movdqu		%xmm0, 16(INV_RNDKEYS)	// => Last inverse round key

.Ldone\@:
	_epilogue
.endm

// void aes128_expandkey_aesni(u32 rndkeys[], u32 *inv_rndkeys,
//			       const u8 in_key[AES_KEYSIZE_128]);
SYM_FUNC_START(aes128_expandkey_aesni)
	_aes_expandkey_aesni	1
SYM_FUNC_END(aes128_expandkey_aesni)

// void aes256_expandkey_aesni(u32 rndkeys[], u32 *inv_rndkeys,
//			       const u8 in_key[AES_KEYSIZE_256]);
SYM_FUNC_START(aes256_expandkey_aesni)
	_aes_expandkey_aesni	0
SYM_FUNC_END(aes256_expandkey_aesni)

// AES-encrypt (\enc=1) or AES-decrypt (\enc=0) the AESDATA registers specified
// in \vecs using the aes_enckey or aes_key pointed to by KEY.  RNDKEY must be
// set to a temporary XMM register, NROUNDS to a temporary 32-bit GPR, and
// RNDKEY_PTR to a temporary full-size GPR.
.macro	_do_aes		enc, vecs:vararg
	movl		OFFSETOF_NROUNDS(KEY), NROUNDS
	dec		NROUNDS
.if \enc
	.set		rndkey0_offs, OFFSETOF_ROUNDKEYS
.else
	.set		rndkey0_offs, OFFSETOF_INVROUNDKEYS
.endif

	// Do the zero-th AES round.
	movdqu		rndkey0_offs(KEY), RNDKEY
.irp i, \vecs
	pxor		RNDKEY, AESDATA\i
.endr
	// Do the regular AES rounds.
	lea		rndkey0_offs+16(KEY), RNDKEY_PTR
.Lnext_round\@:
	movdqu		(RNDKEY_PTR), RNDKEY
	add		$16, RNDKEY_PTR
.irp i, \vecs
	_aesenc		\enc, RNDKEY, AESDATA\i
.endr
	dec		NROUNDS
	jnz		.Lnext_round\@
	// Do the last AES round.
	movdqu		(RNDKEY_PTR), RNDKEY
.irp i, \vecs
	_aesenclast	\enc, RNDKEY, AESDATA\i
.endr
.endm

.macro	_do_aes_ecb	enc, vecs:vararg
.irp i, \vecs
	movdqu		\i*16(SRC), AESDATA\i
.endr
	_do_aes		\enc, \vecs
.irp i, \vecs
	movdqu		AESDATA\i, \i*16(DST)
.endr
.endm

.macro	_aes_crypt_aesni	enc
	.set	DST,		ARG0
	.set	SRC,		ARG1
	.set	KEY,		ARG2
	.set	RNDKEY_PTR,	ARG3	// Temporary register for _do_aes
	.set	NROUNDS,	TMP_32	// Temporary register for _do_aes
	.set	AESDATA0,	%xmm0
	.set	RNDKEY,		%xmm1	// Temporary register for _do_aes

	_prologue	uses_arg3=1
	_do_aes_ecb	\enc, 0
	_epilogue
.endm

// void aes_encrypt_aesni(u8 dst[AES_BLOCK_SIZE], const u8 src[AES_BLOCK_SIZE],
//			  const struct aes_enckey *key);
SYM_FUNC_START(aes_encrypt_aesni)
	_aes_crypt_aesni	1
SYM_FUNC_END(aes_encrypt_aesni)

// void aes_decrypt_aesni(u8 dst[AES_BLOCK_SIZE], const u8 src[AES_BLOCK_SIZE],
//			  const struct aes_key *key);
SYM_FUNC_START(aes_decrypt_aesni)
	_aes_crypt_aesni	0
SYM_FUNC_END(aes_decrypt_aesni)

.macro	_ecb_crypt	enc
	// Arguments
	.set	DST,		ARG0
	.set	SRC,		ARG1
	.set	NBLOCKS,	ARG2
	.set	NBLOCKS32,	ARG2_32	// Used for improved code density
	.set	KEY,		ARG3

	// Other local variables
	.set	RNDKEY_PTR,	ARG4	// Temporary register for _do_aes
	.set	NROUNDS,	TMP_32	// Temporary register for _do_aes
	.set	AESDATA0,	%xmm0
	.set	AESDATA1,	%xmm1
	.set	AESDATA2,	%xmm2
	.set	AESDATA3,	%xmm3
	.set	RNDKEY,		%xmm4	// Temporary register for _do_aes
	_prologue	uses_arg3=2, uses_arg4=1

	sub		$4, NBLOCKS
	jl		.Lecb_loop4_done\@
.p2align 5
.Lecb_loop4\@:
	_do_aes_ecb	\enc, 0,1,2,3
	add		$64, SRC
	add		$64, DST
	sub		$4, NBLOCKS
	jge		.Lecb_loop4\@
.Lecb_loop4_done\@:
	add		$4, NBLOCKS32
	jz		.Lecb_done\@

.Lecb_loop1\@:
	_do_aes_ecb	\enc, 0
	add		$16, SRC
	add		$16, DST
	dec		NBLOCKS32
	jnz		.Lecb_loop1\@

.Lecb_done\@:
	_epilogue
.endm

// void aes_ecb_encrypt_aesni(u8 *dst, const u8 *src, long nblocks,
//			      const struct aes_enckey *key);
SYM_FUNC_START(aes_ecb_encrypt_aesni)
	_ecb_crypt	1
SYM_FUNC_END(aes_ecb_encrypt_aesni)

// void aes_ecb_decrypt_aesni(u8 *dst, const u8 *src, long nblocks,
//			      const struct aes_key *key);
SYM_FUNC_START(aes_ecb_decrypt_aesni)
	_ecb_crypt	0
SYM_FUNC_END(aes_ecb_decrypt_aesni)

// void aes_cbc_encrypt_aesni(u8 *dst, const u8 *src, long nblocks,
//			      u8 iv[AES_BLOCK_SIZE],
//			      const struct aes_enckey *key);
//
// This assumes nblocks > 0.
SYM_FUNC_START(aes_cbc_encrypt_aesni)
	// Arguments
	.set	DST,		ARG0
	.set	SRC,		ARG1
	.set	NBLOCKS,	ARG2
	.set	IV_PTR,		ARG3
	.set	KEY,		ARG4

	// Other local variables
#ifdef __x86_64__
	.set	RNDKEY_PTR,	%r9	// Temporary register for _do_aes
#else
	.set	RNDKEY_PTR,	IV_PTR	// IV_PTR is clobbered and reloaded later
#endif
	.set	NROUNDS,	TMP_32	// Temporary register for _do_aes
	.set	AESDATA0,	%xmm0
	.set	PTEXT,		%xmm1
	.set	RNDKEY,		%xmm2	// Temporary register for _do_aes
	_prologue	uses_arg3=2, uses_arg4=2

	movdqu		(IV_PTR), AESDATA0
.p2align 5
.Lcbc_enc_loop:
	movdqu		(SRC), PTEXT
	pxor		PTEXT, AESDATA0
	_do_aes		1, 0
	movdqu		AESDATA0, (DST)
	add		$16, SRC
	add		$16, DST
	dec		NBLOCKS
	jnz		.Lcbc_enc_loop

	// Store the next IV.  On 32-bit, reload IV_PTR from stack first.
	_reload_arg3
	movdqu		AESDATA0, (IV_PTR)
	_epilogue
SYM_FUNC_END(aes_cbc_encrypt_aesni)

// void aes_cbc_decrypt_aesni(u8 *dst, const u8 *src, long nblocks,
//			      u8 iv[AES_BLOCK_SIZE], const struct aes_key *key);
SYM_FUNC_START(aes_cbc_decrypt_aesni)
	// Arguments
	.set	DST,		ARG0
	.set	SRC,		ARG1
	.set	NBLOCKS,	ARG2
	.set	NBLOCKS32,	ARG2_32	// Used for improved code density
	.set	IV_PTR,		ARG3
	.set	KEY,		ARG4

	// Other local variables
#ifdef __x86_64__
	.set	RNDKEY_PTR,	%r9	// Temporary register for _do_aes
#else
	.set	RNDKEY_PTR,	IV_PTR	// IV_PTR is clobbered and reloaded later
#endif
	.set	NROUNDS,	TMP_32	// Temporary register for _do_aes
	.set	AESDATA0,	%xmm0
	.set	AESDATA1,	%xmm1
	.set	AESDATA2,	%xmm2
	.set	AESDATA3,	%xmm3
	.set	RNDKEY,		%xmm4	// Temporary register for _do_aes
	.set	IV,		%xmm5
	.set	CTEXT0,		%xmm6
	.set	CTEXT1,		%xmm7
#ifdef __x86_64__
	.set	CTEXT2,		%xmm8
	.set	CTEXT3,		%xmm9
#endif
	_prologue	uses_arg3=2, uses_arg4=2

	movdqu		(IV_PTR), IV

	sub		$4, NBLOCKS
	jl		.Lcbc_dec_loop4_done
.p2align 5
.Lcbc_dec_loop4:
	movdqu		0(SRC), AESDATA0
	movdqu		16(SRC), AESDATA1
	movdqu		32(SRC), AESDATA2
	movdqu		48(SRC), AESDATA3
	movdqa		AESDATA0, CTEXT0
	movdqa		AESDATA1, CTEXT1
#ifdef __x86_64__
	movdqa		AESDATA2, CTEXT2
	movdqa		AESDATA3, CTEXT3
#endif
	_do_aes		0, 0,1,2,3
	pxor		IV, AESDATA0
	pxor		CTEXT0, AESDATA1
	pxor		CTEXT1, AESDATA2
#ifdef __x86_64__
	pxor		CTEXT2, AESDATA3
	movdqa		CTEXT3, IV
#else
	movdqu		32(SRC), CTEXT0
	pxor		CTEXT0, AESDATA3
	movdqu		48(SRC), IV
#endif
	movdqu		AESDATA0, 0(DST)
	movdqu		AESDATA1, 16(DST)
	movdqu		AESDATA2, 32(DST)
	movdqu		AESDATA3, 48(DST)
	add		$64, SRC
	add		$64, DST
	sub		$4, NBLOCKS
	jge		.Lcbc_dec_loop4
.Lcbc_dec_loop4_done:
	add		$4, NBLOCKS32
	jz		.Lcbc_dec_done

.Lcbc_dec_loop1:
	movdqu		(SRC), AESDATA0
	movdqa		AESDATA0, CTEXT0
	_do_aes		0, 0
	pxor		IV, AESDATA0
	movdqa		CTEXT0, IV
	movdqu		AESDATA0, (DST)
	add		$16, SRC
	add		$16, DST
	dec		NBLOCKS32
	jnz		.Lcbc_dec_loop1

.Lcbc_dec_done:
	// Store the next IV.  On 32-bit, reload IV_PTR from stack first.
	_reload_arg3
	movdqu		IV, (IV_PTR)
	_epilogue
SYM_FUNC_END(aes_cbc_decrypt_aesni)

.macro	_aes_cbc_cts_crypt	enc
	.set	DST,		ARG0
	.set	SRC,		ARG1
	.set	PN_LEN,		ARG2
	.set	IV_PTR,		ARG3
	.set	KEY,		ARG4
	.set	RNDKEY_PTR,	IV_PTR	// Temporary register for _do_aes
	.set	NROUNDS,	TMP_32	// Temporary register for _do_aes
	.set	RSHIFT_MASK,	%xmm0 // range(16-PN_LEN,16) + [0x80, 0x80, ...]
				      // Must be %xmm0 for pblendvb to work.
	.set	LSHIFT_MASK,	%xmm1 // [0x80, 0x80, ...] + range(PN_LEN)
	.set	AESDATA0,	%xmm2
	.set	AESDATA1,	%xmm3
	.set	RNDKEY,		%xmm4	// Temporary register for _do_aes
	.set	IV,		%xmm5

	_prologue	uses_arg3=2, uses_arg4=2

	// Load LSHIFT_MASK and RSHIFT_MASK.
	lea		RODATA(.Lcts_permute_table), TMP
	movdqu		(TMP,PN_LEN), LSHIFT_MASK
	sub		PN_LEN, TMP
	movdqu		32(TMP), RSHIFT_MASK

	// Load the IV, freeing up IV_PTR to reuse for RNDKEY_PTR.
	movdqu		(IV_PTR), IV

	// Load the second-from-last source block (P[n-1] or C[n-1]) and
	// AES-en/decrypt it.  In the encryption case, XOR it with the IV first.
	movdqu		(SRC), AESDATA0
.if \enc
	pxor		IV, AESDATA0
.endif
	_do_aes		\enc, 0

	// Load the last source block (P[n] or C[n]), left-aligned.
	movdqu		(SRC,PN_LEN), AESDATA1

.if \enc
	// Right-align P[n], XOR it with the first AES output, and AES-encrypt
	// the result.  This gives C[n-1] in AESDATA1.
	pshufb		RSHIFT_MASK, AESDATA1
	pxor		AESDATA0, AESDATA1
	_do_aes		1, 1

	// Left-align the first AES output to get left-aligned C[n].
	pshufb		LSHIFT_MASK, AESDATA0
.else
	// Save a copy of the first AES output in %xmm6 for later.
	movdqa		AESDATA0, %xmm6

	// Left-align the first AES output and XOR it with the
	// already-left-aligned C[n].  This gives the left-aligned P[n].
	pshufb		LSHIFT_MASK, AESDATA0
	pxor		AESDATA1, AESDATA0

	// Right-align C[n], then use RSHIFT_MASK (in %xmm0 as pblendvb's
	// implicit operand) as a blend mask to select C[n] and the remaining
	// bytes from the first AES output, with the result in AESDATA1.
	pshufb		RSHIFT_MASK, AESDATA1
	pblendvb	%xmm6, AESDATA1

	// AES-decrypt the result and XOR with the IV to get P[n-1] in AESDATA1.
	_do_aes		0, 1
	pxor		IV, AESDATA1
.endif
	// Store the left-aligned C[n] or P[n], then C[n-1] or P[n-1].
	// Note that these stores may overlap.
	movdqu		AESDATA0, (DST,PN_LEN)
	movdqu		AESDATA1, (DST)
	_epilogue
.endm

// void aes_cbc_cts_encrypt_aesni(u8 *dst, const u8 *src, long pn_len,
//				  const u8 iv[AES_BLOCK_SIZE],
//				  const struct aes_enckey *key);
// void aes_cbc_cts_decrypt_aesni(u8 *dst, const u8 *src, long pn_len,
//				  const u8 iv[AES_BLOCK_SIZE],
//				  const struct aes_key *key);
//
// Use the CS3 variant of ciphertext stealing to encrypt or decrypt the last two
// blocks in a message.  The two blocks are located at src and consist of one
// full block of length 16 bytes and one possibly-partial block of length 1 <=
// pn_len <= 16 bytes.  The output is written to dst, which may equal src.
SYM_FUNC_START(aes_cbc_cts_encrypt_aesni)
	_aes_cbc_cts_crypt	1
SYM_FUNC_END(aes_cbc_cts_encrypt_aesni)
SYM_FUNC_START(aes_cbc_cts_decrypt_aesni)
	_aes_cbc_cts_crypt	0
SYM_FUNC_END(aes_cbc_cts_decrypt_aesni)

#ifdef __x86_64__
// void aes_ctr64_crypt_aesni(u8 *dst, const u8 *src, s64 len,
//			      const u64 le_ctr[2],
//			      const struct aes_enckey *key);
SYM_FUNC_START(aes_ctr64_crypt_aesni)
	// Arguments
	.set	DST,		ARG0
	.set	SRC,		ARG1
	.set	LEN,		ARG2
	.set	LEN32,		ARG2_32	// Used for improved code density
	.set	LE_CTR_PTR,	ARG3	// Used as temp reg after LE_CTR is loaded
	.set	KEY,		ARG4

	// Other local variables
	.set	AESDATA0,	%xmm0
	.set	AESDATA1,	%xmm1
	.set	AESDATA2,	%xmm2
	.set	AESDATA3,	%xmm3
	.set	LE_CTR,		%xmm4	// Current 128-bit little endian counter
	.set	LE_CTR_INC,	%xmm5	// Initialized to (u64[])[1, 0]
	.set	BSWAP_MASK,	%xmm6
	.set	RNDKEY,		%xmm7	// Temporary register for _do_aes
	.set	RNDKEY_PTR,	LE_CTR_PTR  // Temporary register for _do_aes
	.set	NROUNDS,	TMP_32	// Temporary register for _do_aes

	// Initialize LE_CTR, BSWAP_MASK, and LE_CTR_INC.
	movdqu		(LE_CTR_PTR), LE_CTR
	movdqa		RODATA(.Lbswap_mask), BSWAP_MASK
	mov		$1, TMP_32
	movd		TMP_32, LE_CTR_INC

	// Encrypt and XOR four blocks (64 bytes) at a time.
	sub		$64, LEN
	jl		.Lctr_loop4_done
.p2align 5
.Lctr_loop4:
.irp i, 0,1,2,3
	movdqa		LE_CTR, AESDATA\i
	pshufb		BSWAP_MASK, AESDATA\i	// => big endian counter
	paddq		LE_CTR_INC, LE_CTR
.endr
	_do_aes		1, 0,1,2,3
	// AESDATA[0-3] now contain four keystream blocks.
.irp i, 0,1,2,3
	movdqu		\i*16(SRC), RNDKEY	// Use RNDKEY as temp register.
	pxor		RNDKEY, AESDATA\i
	movdqu		AESDATA\i, \i*16(DST)
.endr
	add		$64, SRC
	add		$64, DST
	sub		$64, LEN
	jge		.Lctr_loop4
.Lctr_loop4_done:
	add		$64, LEN32
	jz		.Lctr_done

	// 1 <= LEN <= 63 bytes remain.  Prepare four more keystream blocks.
.irp i, 0,1,2,3
	movdqa		LE_CTR, AESDATA\i
	pshufb		BSWAP_MASK, AESDATA\i	// => big endian counter
  .if \i != 3
	paddq		LE_CTR_INC, LE_CTR
  .endif
.endr
	_do_aes		1, 0,1,2,3
	// AESDATA[0-3] now contain four keystream blocks.

	// XOR one block (16 bytes) at a time.
	sub		$16, LEN32
	jl		.Lctr_xor_partial
.Lctr_xor1:
	movdqu		(SRC), RNDKEY		// Use RNDKEY as temp register.
	pxor		RNDKEY, AESDATA0
	movdqu		AESDATA0, (DST)
	movdqa		AESDATA1, AESDATA0
	movdqa		AESDATA2, AESDATA1
	movdqa		AESDATA3, AESDATA2
	add		$16, SRC
	add		$16, DST
	sub		$16, LEN32
	jge		.Lctr_xor1

	// XOR the remaining LEN mod 16 bytes.
.Lctr_xor_partial:
	test		$8, LEN32
	jz		1f
	movq		AESDATA0, TMP
	xor		(SRC), TMP	// XOR 8 bytes.
	mov		TMP, (DST)
	add		$8, SRC
	add		$8, DST
	psrldq		$8, AESDATA0
1:
	test		$4, LEN32
	jz		2f
	movd		AESDATA0, TMP_32
	xor		(SRC), TMP_32	// XOR 4 bytes.
	mov		TMP_32, (DST)
	add		$4, SRC
	add		$4, DST
	psrldq		$4, AESDATA0
2:
	test		$2, LEN32
	jz		3f
	movd		AESDATA0, TMP_32
	xor		(SRC), TMP_16	// XOR 2 bytes.
	mov		TMP_16, (DST)
	add		$2, SRC
	add		$2, DST
	psrldq		$2, AESDATA0
3:
	test		$1, LEN32
	jz		.Lctr_done
	movd		AESDATA0, TMP_32
	xor		(SRC), TMP_8	// XOR 1 byte.
	mov		TMP_8, (DST)
.Lctr_done:
	RET
SYM_FUNC_END(aes_ctr64_crypt_aesni)
#endif // __x86_64__

// Given a 128-bit XTS tweak in the xmm register \tweak, compute the next tweak
// (by multiplying by the polynomial 'x') and write it back to \tweak.
.macro	_next_tweak	tweak, tmp
	pshufd		$0x13, \tweak, \tmp
	paddq		\tweak, \tweak
	psrad		$31, \tmp
	pand		GF_POLY, \tmp
	pxor		\tmp, \tweak
.endm

.macro	_aes_xts_crypt	enc
	// Arguments
	.set	DST,		ARG0
	.set	SRC,		ARG1
	.set	NBLOCKS,	ARG2
	.set	NBLOCKS32,	ARG2_32	// Used for improved code density
	.set	TWEAK_PTR,	ARG3
	.set	KEY,		ARG4

	// Other local variables
#ifdef __x86_64__
	.set	RNDKEY_PTR,	%r9	// Temporary register for _do_aes
#else
	.set	RNDKEY_PTR,	TWEAK_PTR // TWEAK_PTR is clobbered and reloaded later.
#endif
	.set	NROUNDS,	TMP_32	// Temporary register for _do_aes
	.set	AESDATA0,	%xmm0
	.set	AESDATA1,	%xmm1
	.set	AESDATA2,	%xmm2
	.set	AESDATA3,	%xmm3
	.set	GF_POLY,	%xmm4
	.set	RNDKEY,		%xmm5	// Temporary register for _do_aes
	.set	TWEAK,		%xmm6
	.set	SAVED_TWEAK0,	%xmm7
#ifdef __x86_64__
	.set	SAVED_TWEAK1,	%xmm8
	.set	SAVED_TWEAK2,	%xmm9
#endif

	_prologue	uses_arg3=2, uses_arg4=2
#ifdef __i386__
	// Reserve 16-byte aligned space to spill two tweaks.
	push		%ebp
	mov		%esp, %ebp
	and		$~15, %esp
	sub		$32, %esp
#endif

	movdqu		(TWEAK_PTR), TWEAK
	movdqa		RODATA(.Lxts_gf_poly), GF_POLY

	sub		$4, NBLOCKS
	jl		.Lxts_loop4_done\@
.p2align 5
.Lxts_loop4\@:
	// Load the next four source blocks into AESDATA[0-3] and XOR them with
	// their tweaks, advancing the tweak three times in order to do so.
	// Save the four tweaks for later; on 64-bit they all fit into
	// registers, while on 32-bit two tweaks are spilled to the stack.
.irp i, 0,1,2,3
	movdqu		\i*16(SRC), AESDATA\i
	pxor		TWEAK, AESDATA\i
  .if \i != 3
#ifdef __x86_64__
	movdqa		TWEAK, SAVED_TWEAK\i
#else
    .if \i == 0
	movdqa		TWEAK, SAVED_TWEAK0
    .else
	movdqa		TWEAK, (\i-1)*16(%esp)
    .endif
#endif
	_next_tweak	TWEAK, RNDKEY
  .endif
.endr

	// Encrypt or decrypt the blocks.
	_do_aes		\enc, 0,1,2,3

	// XOR the blocks with the saved tweaks.
	pxor		SAVED_TWEAK0, AESDATA0
#ifdef __x86_64__
	pxor		SAVED_TWEAK1, AESDATA1
	pxor		SAVED_TWEAK2, AESDATA2
#else
	pxor		(%esp), AESDATA1
	pxor		16(%esp), AESDATA2
#endif
	pxor		TWEAK, AESDATA3

	// Store the encrypted or decrypted blocks.
.irp i, 0,1,2,3
	movdqu		AESDATA\i, \i*16(DST)
.endr

	_next_tweak	TWEAK, RNDKEY
	add		$64, SRC
	add		$64, DST
	sub		$4, NBLOCKS
	jge		.Lxts_loop4\@
.Lxts_loop4_done\@:
	add		$4, NBLOCKS32
	jz		.Lxts_done\@

.Lxts_loop1\@:
	movdqu		(SRC), AESDATA0
	pxor		TWEAK, AESDATA0
	_do_aes		\enc, 0
	pxor		TWEAK, AESDATA0
	movdqu		AESDATA0, (DST)
	_next_tweak	TWEAK, RNDKEY
	add		$16, SRC
	add		$16, DST
	dec		NBLOCKS32
	jnz		.Lxts_loop1\@

.Lxts_done\@:
#ifdef __i386__
	// Zeroize the stack buffer that tweaks were spilled to.
	pxor		AESDATA0, AESDATA0
	movdqa		AESDATA0, (%esp)
	movdqa		AESDATA0, 16(%esp)
	mov		%ebp, %esp
	pop		%ebp
#endif
	// Store the next tweak.  On 32-bit, reload TWEAK_PTR from stack first.
	_reload_arg3
	movdqu		TWEAK, (TWEAK_PTR)
	_epilogue
.endm

// void aes_xts_encrypt_aesni(u8 *dst, const u8 *src, long nblocks,
//			      u8 tweak[AES_BLOCK_SIZE],
//			      const struct aes_key *key);
// void aes_xts_decrypt_aesni(u8 *dst, const u8 *src, long nblocks,
//			      u8 tweak[AES_BLOCK_SIZE],
//			      const struct aes_key *key);
//
// `tweak` must have already been encrypted by the tweak key; `key` is just the
// main key.  To allow incremental computation, `tweak` is updated to contain
// the next tweak.
SYM_FUNC_START(aes_xts_encrypt_aesni)
	_aes_xts_crypt	1
SYM_FUNC_END(aes_xts_encrypt_aesni)
SYM_FUNC_START(aes_xts_decrypt_aesni)
	_aes_xts_crypt	0
SYM_FUNC_END(aes_xts_decrypt_aesni)