summaryrefslogtreecommitdiffstats
path: root/arch/x86/crypto/aes-gcm-vaes-avx2.S
blob: 9cc387957fa93e2de6d90a139fb4f9777c081e58 (plain)
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
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
/* SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause */
//
// AES-GCM implementation for x86_64 CPUs that support the following CPU
// features: VAES && VPCLMULQDQ && AVX2
//
// Copyright 2025 Google LLC
//
// Author: Eric Biggers <ebiggers@google.com>
//
//------------------------------------------------------------------------------
//
// This file is dual-licensed, meaning that you can use it under your choice of
// either of the following two licenses:
//
// Licensed under the Apache License 2.0 (the "License").  You may obtain a copy
// of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// or
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// This is similar to aes-gcm-vaes-avx512.S, but it uses AVX2 instead of AVX512.
// This means it can only use 16 vector registers instead of 32, the maximum
// vector length is 32 bytes, and some instructions such as vpternlogd and
// masked loads/stores are unavailable.  However, it is able to run on CPUs that
// have VAES without AVX512, namely AMD Zen 3 (including "Milan" server CPUs),
// various Intel client CPUs such as Alder Lake, and Intel Sierra Forest.
//
// This implementation also uses Karatsuba multiplication instead of schoolbook
// multiplication for GHASH in its main loop.  This does not help much on Intel,
// but it improves performance by ~5% on AMD Zen 3.  Other factors weighing
// slightly in favor of Karatsuba multiplication in this implementation are the
// lower maximum vector length (which means there are fewer key powers, so we
// can cache the halves of each key power XOR'd together and still use less
// memory than the AVX512 implementation), and the unavailability of the
// vpternlogd instruction (which helped schoolbook a bit more than Karatsuba).

#include <linux/linkage.h>

.section .rodata
.p2align 4

	// The below three 16-byte values must be in the order that they are, as
	// they are really two 32-byte tables and a 16-byte value that overlap:
	//
	// - The first 32-byte table begins at .Lselect_high_bytes_table.
	//   For 0 <= len <= 16, the 16-byte value at
	//   '.Lselect_high_bytes_table + len' selects the high 'len' bytes of
	//   another 16-byte value when AND'ed with it.
	//
	// - The second 32-byte table begins at .Lrshift_and_bswap_table.
	//   For 0 <= len <= 16, the 16-byte value at
	//   '.Lrshift_and_bswap_table + len' is a vpshufb mask that does the
	//   following operation: right-shift by '16 - len' bytes (shifting in
	//   zeroes), then reflect all 16 bytes.
	//
	// - The 16-byte value at .Lbswap_mask is a vpshufb mask that reflects
	//   all 16 bytes.
.Lselect_high_bytes_table:
	.octa	0
.Lrshift_and_bswap_table:
	.octa	0xffffffffffffffffffffffffffffffff
.Lbswap_mask:
	.octa	0x000102030405060708090a0b0c0d0e0f

	// Sixteen 0x0f bytes.  By XOR'ing an entry of .Lrshift_and_bswap_table
	// with this, we get a mask that left-shifts by '16 - len' bytes.
.Lfifteens:
	.octa	0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f

	// This is the GHASH reducing polynomial without its constant term, i.e.
	// x^128 + x^7 + x^2 + x, represented using the backwards mapping
	// between bits and polynomial coefficients.
	//
	// Alternatively, it can be interpreted as the naturally-ordered
	// representation of the polynomial x^127 + x^126 + x^121 + 1, i.e. the
	// "reversed" GHASH reducing polynomial without its x^128 term.
.Lgfpoly:
	.octa	0xc2000000000000000000000000000001

	// Same as above, but with the (1 << 64) bit set.
.Lgfpoly_and_internal_carrybit:
	.octa	0xc2000000000000010000000000000001

	// Values needed to prepare the initial vector of counter blocks.
.Lctr_pattern:
	.octa	0
	.octa	1

	// The number of AES blocks per vector, as a 128-bit value.
.Linc_2blocks:
	.octa	2

// Offsets in struct aes_gcm_key_vaes_avx2
#define OFFSETOF_AESKEYLEN	0
#define OFFSETOF_AESROUNDKEYS	16
#define OFFSETOF_H_POWERS	288
#define NUM_H_POWERS		8
#define OFFSETOFEND_H_POWERS    (OFFSETOF_H_POWERS + (NUM_H_POWERS * 16))
#define OFFSETOF_H_POWERS_XORED	OFFSETOFEND_H_POWERS

.text

// Do one step of GHASH-multiplying the 128-bit lanes of \a by the 128-bit lanes
// of \b and storing the reduced products in \dst.  Uses schoolbook
// multiplication.
.macro	_ghash_mul_step	i, a, b, dst, gfpoly, t0, t1, t2
.if \i == 0
	vpclmulqdq	$0x00, \a, \b, \t0	  // LO = a_L * b_L
	vpclmulqdq	$0x01, \a, \b, \t1	  // MI_0 = a_L * b_H
.elseif \i == 1
	vpclmulqdq	$0x10, \a, \b, \t2	  // MI_1 = a_H * b_L
.elseif \i == 2
	vpxor		\t2, \t1, \t1		  // MI = MI_0 + MI_1
.elseif \i == 3
	vpclmulqdq	$0x01, \t0, \gfpoly, \t2  // LO_L*(x^63 + x^62 + x^57)
.elseif \i == 4
	vpshufd		$0x4e, \t0, \t0		  // Swap halves of LO
.elseif \i == 5
	vpxor		\t0, \t1, \t1		  // Fold LO into MI (part 1)
	vpxor		\t2, \t1, \t1		  // Fold LO into MI (part 2)
.elseif \i == 6
	vpclmulqdq	$0x11, \a, \b, \dst	  // HI = a_H * b_H
.elseif \i == 7
	vpclmulqdq	$0x01, \t1, \gfpoly, \t0  // MI_L*(x^63 + x^62 + x^57)
.elseif \i == 8
	vpshufd		$0x4e, \t1, \t1		  // Swap halves of MI
.elseif \i == 9
	vpxor		\t1, \dst, \dst		  // Fold MI into HI (part 1)
	vpxor		\t0, \dst, \dst		  // Fold MI into HI (part 2)
.endif
.endm

// GHASH-multiply the 128-bit lanes of \a by the 128-bit lanes of \b and store
// the reduced products in \dst.  See _ghash_mul_step for full explanation.
.macro	_ghash_mul	a, b, dst, gfpoly, t0, t1, t2
.irp i, 0,1,2,3,4,5,6,7,8,9
	_ghash_mul_step	\i, \a, \b, \dst, \gfpoly, \t0, \t1, \t2
.endr
.endm

// GHASH-multiply the 128-bit lanes of \a by the 128-bit lanes of \b and add the
// *unreduced* products to \lo, \mi, and \hi.
.macro	_ghash_mul_noreduce	a, b, lo, mi, hi, t0
	vpclmulqdq	$0x00, \a, \b, \t0	// a_L * b_L
	vpxor		\t0, \lo, \lo
	vpclmulqdq	$0x01, \a, \b, \t0	// a_L * b_H
	vpxor		\t0, \mi, \mi
	vpclmulqdq	$0x10, \a, \b, \t0	// a_H * b_L
	vpxor		\t0, \mi, \mi
	vpclmulqdq	$0x11, \a, \b, \t0	// a_H * b_H
	vpxor		\t0, \hi, \hi
.endm

// Reduce the unreduced products from \lo, \mi, and \hi and store the 128-bit
// reduced products in \hi.  See _ghash_mul_step for explanation of reduction.
.macro	_ghash_reduce	lo, mi, hi, gfpoly, t0
	vpclmulqdq	$0x01, \lo, \gfpoly, \t0
	vpshufd		$0x4e, \lo, \lo
	vpxor		\lo, \mi, \mi
	vpxor		\t0, \mi, \mi
	vpclmulqdq	$0x01, \mi, \gfpoly, \t0
	vpshufd		$0x4e, \mi, \mi
	vpxor		\mi, \hi, \hi
	vpxor		\t0, \hi, \hi
.endm

// This is a specialized version of _ghash_mul that computes \a * \a, i.e. it
// squares \a.  It skips computing MI = (a_L * a_H) + (a_H * a_L) = 0.
.macro	_ghash_square	a, dst, gfpoly, t0, t1
	vpclmulqdq	$0x00, \a, \a, \t0	  // LO = a_L * a_L
	vpclmulqdq	$0x11, \a, \a, \dst	  // HI = a_H * a_H
	vpclmulqdq	$0x01, \t0, \gfpoly, \t1  // LO_L*(x^63 + x^62 + x^57)
	vpshufd		$0x4e, \t0, \t0		  // Swap halves of LO
	vpxor		\t0, \t1, \t1		  // Fold LO into MI
	vpclmulqdq	$0x01, \t1, \gfpoly, \t0  // MI_L*(x^63 + x^62 + x^57)
	vpshufd		$0x4e, \t1, \t1		  // Swap halves of MI
	vpxor		\t1, \dst, \dst		  // Fold MI into HI (part 1)
	vpxor		\t0, \dst, \dst		  // Fold MI into HI (part 2)
.endm

// void aes_gcm_precompute_vaes_avx2(struct aes_gcm_key_vaes_avx2 *key);
//
// Given the expanded AES key |key->base.aes_key|, derive the GHASH subkey and
// initialize |key->h_powers| and |key->h_powers_xored|.
//
// We use h_powers[0..7] to store H^8 through H^1, and h_powers_xored[0..7] to
// store the 64-bit halves of the key powers XOR'd together (for Karatsuba
// multiplication) in the order 8,6,7,5,4,2,3,1.
SYM_FUNC_START(aes_gcm_precompute_vaes_avx2)

	// Function arguments
	.set	KEY,		%rdi

	// Additional local variables
	.set	POWERS_PTR,	%rsi
	.set	RNDKEYLAST_PTR,	%rdx
	.set	TMP0,		%ymm0
	.set	TMP0_XMM,	%xmm0
	.set	TMP1,		%ymm1
	.set	TMP1_XMM,	%xmm1
	.set	TMP2,		%ymm2
	.set	TMP2_XMM,	%xmm2
	.set	H_CUR,		%ymm3
	.set	H_CUR_XMM,	%xmm3
	.set	H_CUR2,		%ymm4
	.set	H_INC,		%ymm5
	.set	H_INC_XMM,	%xmm5
	.set	GFPOLY,		%ymm6
	.set	GFPOLY_XMM,	%xmm6

	// Encrypt an all-zeroes block to get the raw hash subkey.
	movl		OFFSETOF_AESKEYLEN(KEY), %eax
	lea		OFFSETOF_AESROUNDKEYS+6*16(KEY,%rax,4), RNDKEYLAST_PTR
	vmovdqu		OFFSETOF_AESROUNDKEYS(KEY), H_CUR_XMM
	lea		OFFSETOF_AESROUNDKEYS+16(KEY), %rax
1:
	vaesenc		(%rax), H_CUR_XMM, H_CUR_XMM
	add		$16, %rax
	cmp		%rax, RNDKEYLAST_PTR
	jne		1b
	vaesenclast	(RNDKEYLAST_PTR), H_CUR_XMM, H_CUR_XMM

	// Reflect the bytes of the raw hash subkey.
	vpshufb		.Lbswap_mask(%rip), H_CUR_XMM, H_CUR_XMM

	// Finish preprocessing the byte-reflected hash subkey by multiplying it
	// by x^-1 ("standard" interpretation of polynomial coefficients) or
	// equivalently x^1 (natural interpretation).  This gets the key into a
	// format that avoids having to bit-reflect the data blocks later.
	vpshufd		$0xd3, H_CUR_XMM, TMP0_XMM
	vpsrad		$31, TMP0_XMM, TMP0_XMM
	vpaddq		H_CUR_XMM, H_CUR_XMM, H_CUR_XMM
	vpand		.Lgfpoly_and_internal_carrybit(%rip), TMP0_XMM, TMP0_XMM
	vpxor		TMP0_XMM, H_CUR_XMM, H_CUR_XMM

	// Load the gfpoly constant.
	vbroadcasti128	.Lgfpoly(%rip), GFPOLY

	// Square H^1 to get H^2.
	_ghash_square	H_CUR_XMM, H_INC_XMM, GFPOLY_XMM, TMP0_XMM, TMP1_XMM

	// Create H_CUR = [H^2, H^1] and H_INC = [H^2, H^2].
	vinserti128	$1, H_CUR_XMM, H_INC, H_CUR
	vinserti128	$1, H_INC_XMM, H_INC, H_INC

	// Compute H_CUR2 = [H^4, H^3].
	_ghash_mul	H_INC, H_CUR, H_CUR2, GFPOLY, TMP0, TMP1, TMP2

	// Store [H^2, H^1] and [H^4, H^3].
	vmovdqu		H_CUR, OFFSETOF_H_POWERS+3*32(KEY)
	vmovdqu		H_CUR2, OFFSETOF_H_POWERS+2*32(KEY)

	// For Karatsuba multiplication: compute and store the two 64-bit halves
	// of each key power XOR'd together.  Order is 4,2,3,1.
	vpunpcklqdq	H_CUR, H_CUR2, TMP0
	vpunpckhqdq	H_CUR, H_CUR2, TMP1
	vpxor		TMP1, TMP0, TMP0
	vmovdqu		TMP0, OFFSETOF_H_POWERS_XORED+32(KEY)

	// Compute and store H_CUR = [H^6, H^5] and H_CUR2 = [H^8, H^7].
	_ghash_mul	H_INC, H_CUR2, H_CUR, GFPOLY, TMP0, TMP1, TMP2
	_ghash_mul	H_INC, H_CUR, H_CUR2, GFPOLY, TMP0, TMP1, TMP2
	vmovdqu		H_CUR, OFFSETOF_H_POWERS+1*32(KEY)
	vmovdqu		H_CUR2, OFFSETOF_H_POWERS+0*32(KEY)

	// Again, compute and store the two 64-bit halves of each key power
	// XOR'd together.  Order is 8,6,7,5.
	vpunpcklqdq	H_CUR, H_CUR2, TMP0
	vpunpckhqdq	H_CUR, H_CUR2, TMP1
	vpxor		TMP1, TMP0, TMP0
	vmovdqu		TMP0, OFFSETOF_H_POWERS_XORED(KEY)

	vzeroupper
	RET
SYM_FUNC_END(aes_gcm_precompute_vaes_avx2)

// Do one step of the GHASH update of four vectors of data blocks.
//   \i: the step to do, 0 through 9
//   \ghashdata_ptr: pointer to the data blocks (ciphertext or AAD)
//   KEY: pointer to struct aes_gcm_key_vaes_avx2
//   BSWAP_MASK: mask for reflecting the bytes of blocks
//   H_POW[2-1]_XORED: cached values from KEY->h_powers_xored
//   TMP[0-2]: temporary registers.  TMP[1-2] must be preserved across steps.
//   LO, MI: working state for this macro that must be preserved across steps
//   GHASH_ACC: the GHASH accumulator (input/output)
.macro	_ghash_step_4x	i, ghashdata_ptr
	.set		HI, GHASH_ACC # alias
	.set		HI_XMM, GHASH_ACC_XMM
.if \i == 0
	// First vector
	vmovdqu		0*32(\ghashdata_ptr), TMP1
	vpshufb		BSWAP_MASK, TMP1, TMP1
	vmovdqu		OFFSETOF_H_POWERS+0*32(KEY), TMP2
	vpxor		GHASH_ACC, TMP1, TMP1
	vpclmulqdq	$0x00, TMP2, TMP1, LO
	vpclmulqdq	$0x11, TMP2, TMP1, HI
	vpunpckhqdq	TMP1, TMP1, TMP0
	vpxor		TMP1, TMP0, TMP0
	vpclmulqdq	$0x00, H_POW2_XORED, TMP0, MI
.elseif \i == 1
.elseif \i == 2
	// Second vector
	vmovdqu		1*32(\ghashdata_ptr), TMP1
	vpshufb		BSWAP_MASK, TMP1, TMP1
	vmovdqu		OFFSETOF_H_POWERS+1*32(KEY), TMP2
	vpclmulqdq	$0x00, TMP2, TMP1, TMP0
	vpxor		TMP0, LO, LO
	vpclmulqdq	$0x11, TMP2, TMP1, TMP0
	vpxor		TMP0, HI, HI
	vpunpckhqdq	TMP1, TMP1, TMP0
	vpxor		TMP1, TMP0, TMP0
	vpclmulqdq	$0x10, H_POW2_XORED, TMP0, TMP0
	vpxor		TMP0, MI, MI
.elseif \i == 3
	// Third vector
	vmovdqu		2*32(\ghashdata_ptr), TMP1
	vpshufb		BSWAP_MASK, TMP1, TMP1
	vmovdqu		OFFSETOF_H_POWERS+2*32(KEY), TMP2
.elseif \i == 4
	vpclmulqdq	$0x00, TMP2, TMP1, TMP0
	vpxor		TMP0, LO, LO
	vpclmulqdq	$0x11, TMP2, TMP1, TMP0
	vpxor		TMP0, HI, HI
.elseif \i == 5
	vpunpckhqdq	TMP1, TMP1, TMP0
	vpxor		TMP1, TMP0, TMP0
	vpclmulqdq	$0x00, H_POW1_XORED, TMP0, TMP0
	vpxor		TMP0, MI, MI

	// Fourth vector
	vmovdqu		3*32(\ghashdata_ptr), TMP1
	vpshufb		BSWAP_MASK, TMP1, TMP1
.elseif \i == 6
	vmovdqu		OFFSETOF_H_POWERS+3*32(KEY), TMP2
	vpclmulqdq	$0x00, TMP2, TMP1, TMP0
	vpxor		TMP0, LO, LO
	vpclmulqdq	$0x11, TMP2, TMP1, TMP0
	vpxor		TMP0, HI, HI
	vpunpckhqdq	TMP1, TMP1, TMP0
	vpxor		TMP1, TMP0, TMP0
	vpclmulqdq	$0x10, H_POW1_XORED, TMP0, TMP0
	vpxor		TMP0, MI, MI
.elseif \i == 7
	// Finalize 'mi' following Karatsuba multiplication.
	vpxor		LO, MI, MI
	vpxor		HI, MI, MI

	// Fold lo into mi.
	vbroadcasti128	.Lgfpoly(%rip), TMP2
	vpclmulqdq	$0x01, LO, TMP2, TMP0
	vpshufd		$0x4e, LO, LO
	vpxor		LO, MI, MI
	vpxor		TMP0, MI, MI
.elseif \i == 8
	// Fold mi into hi.
	vpclmulqdq	$0x01, MI, TMP2, TMP0
	vpshufd		$0x4e, MI, MI
	vpxor		MI, HI, HI
	vpxor		TMP0, HI, HI
.elseif \i == 9
	vextracti128	$1, HI, TMP0_XMM
	vpxor		TMP0_XMM, HI_XMM, GHASH_ACC_XMM
.endif
.endm

// Update GHASH with four vectors of data blocks.  See _ghash_step_4x for full
// explanation.
.macro	_ghash_4x	ghashdata_ptr
.irp i, 0,1,2,3,4,5,6,7,8,9
	_ghash_step_4x	\i, \ghashdata_ptr
.endr
.endm

// Load 1 <= %ecx <= 16 bytes from the pointer \src into the xmm register \dst
// and zeroize any remaining bytes.  Clobbers %rax, %rcx, and \tmp{64,32}.
.macro	_load_partial_block	src, dst, tmp64, tmp32
	sub		$8, %ecx		// LEN - 8
	jle		.Lle8\@

	// Load 9 <= LEN <= 16 bytes.
	vmovq		(\src), \dst		// Load first 8 bytes
	mov		(\src, %rcx), %rax	// Load last 8 bytes
	neg		%ecx
	shl		$3, %ecx
	shr		%cl, %rax		// Discard overlapping bytes
	vpinsrq		$1, %rax, \dst, \dst
	jmp		.Ldone\@

.Lle8\@:
	add		$4, %ecx		// LEN - 4
	jl		.Llt4\@

	// Load 4 <= LEN <= 8 bytes.
	mov		(\src), %eax		// Load first 4 bytes
	mov		(\src, %rcx), \tmp32	// Load last 4 bytes
	jmp		.Lcombine\@

.Llt4\@:
	// Load 1 <= LEN <= 3 bytes.
	add		$2, %ecx		// LEN - 2
	movzbl		(\src), %eax		// Load first byte
	jl		.Lmovq\@
	movzwl		(\src, %rcx), \tmp32	// Load last 2 bytes
.Lcombine\@:
	shl		$3, %ecx
	shl		%cl, \tmp64
	or		\tmp64, %rax		// Combine the two parts
.Lmovq\@:
	vmovq		%rax, \dst
.Ldone\@:
.endm

// Store 1 <= %ecx <= 16 bytes from the xmm register \src to the pointer \dst.
// Clobbers %rax, %rcx, and \tmp{64,32}.
.macro	_store_partial_block	src, dst, tmp64, tmp32
	sub		$8, %ecx		// LEN - 8
	jl		.Llt8\@

	// Store 8 <= LEN <= 16 bytes.
	vpextrq		$1, \src, %rax
	mov		%ecx, \tmp32
	shl		$3, %ecx
	ror		%cl, %rax
	mov		%rax, (\dst, \tmp64)	// Store last LEN - 8 bytes
	vmovq		\src, (\dst)		// Store first 8 bytes
	jmp		.Ldone\@

.Llt8\@:
	add		$4, %ecx		// LEN - 4
	jl		.Llt4\@

	// Store 4 <= LEN <= 7 bytes.
	vpextrd		$1, \src, %eax
	mov		%ecx, \tmp32
	shl		$3, %ecx
	ror		%cl, %eax
	mov		%eax, (\dst, \tmp64)	// Store last LEN - 4 bytes
	vmovd		\src, (\dst)		// Store first 4 bytes
	jmp		.Ldone\@

.Llt4\@:
	// Store 1 <= LEN <= 3 bytes.
	vpextrb		$0, \src, 0(\dst)
	cmp		$-2, %ecx		// LEN - 4 == -2, i.e. LEN == 2?
	jl		.Ldone\@
	vpextrb		$1, \src, 1(\dst)
	je		.Ldone\@
	vpextrb		$2, \src, 2(\dst)
.Ldone\@:
.endm

// void aes_gcm_aad_update_vaes_avx2(const struct aes_gcm_key_vaes_avx2 *key,
//				     u8 ghash_acc[16],
//				     const u8 *aad, int aadlen);
//
// This function processes the AAD (Additional Authenticated Data) in GCM.
// Using the key |key|, it updates the GHASH accumulator |ghash_acc| with the
// data given by |aad| and |aadlen|.  On the first call, |ghash_acc| must be all
// zeroes.  |aadlen| must be a multiple of 16, except on the last call where it
// can be any length.  The caller must do any buffering needed to ensure this.
//
// This handles large amounts of AAD efficiently, while also keeping overhead
// low for small amounts which is the common case.  TLS and IPsec use less than
// one block of AAD, but (uncommonly) other use cases may use much more.
SYM_FUNC_START(aes_gcm_aad_update_vaes_avx2)

	// Function arguments
	.set	KEY,		%rdi
	.set	GHASH_ACC_PTR,	%rsi
	.set	AAD,		%rdx
	.set	AADLEN,		%ecx	// Must be %ecx for _load_partial_block
	.set	AADLEN64,	%rcx	// Zero-extend AADLEN before using!

	// Additional local variables.
	// %rax and %r8 are used as temporary registers.
	.set	TMP0,		%ymm0
	.set	TMP0_XMM,	%xmm0
	.set	TMP1,		%ymm1
	.set	TMP1_XMM,	%xmm1
	.set	TMP2,		%ymm2
	.set	TMP2_XMM,	%xmm2
	.set	LO,		%ymm3
	.set	LO_XMM,		%xmm3
	.set	MI,		%ymm4
	.set	MI_XMM,		%xmm4
	.set	GHASH_ACC,	%ymm5
	.set	GHASH_ACC_XMM,	%xmm5
	.set	BSWAP_MASK,	%ymm6
	.set	BSWAP_MASK_XMM,	%xmm6
	.set	GFPOLY,		%ymm7
	.set	GFPOLY_XMM,	%xmm7
	.set	H_POW2_XORED,	%ymm8
	.set	H_POW1_XORED,	%ymm9

	// Load the bswap_mask and gfpoly constants.  Since AADLEN is usually
	// small, usually only 128-bit vectors will be used.  So as an
	// optimization, don't broadcast these constants to both 128-bit lanes
	// quite yet.
	vmovdqu		.Lbswap_mask(%rip), BSWAP_MASK_XMM
	vmovdqu		.Lgfpoly(%rip), GFPOLY_XMM

	// Load the GHASH accumulator.
	vmovdqu		(GHASH_ACC_PTR), GHASH_ACC_XMM

	// Check for the common case of AADLEN <= 16, as well as AADLEN == 0.
	test		AADLEN, AADLEN
	jz		.Laad_done
	cmp		$16, AADLEN
	jle		.Laad_lastblock

	// AADLEN > 16, so we'll operate on full vectors.  Broadcast bswap_mask
	// and gfpoly to both 128-bit lanes.
	vinserti128	$1, BSWAP_MASK_XMM, BSWAP_MASK, BSWAP_MASK
	vinserti128	$1, GFPOLY_XMM, GFPOLY, GFPOLY

	// If AADLEN >= 128, update GHASH with 128 bytes of AAD at a time.
	add		$-128, AADLEN	// 128 is 4 bytes, -128 is 1 byte
	jl		.Laad_loop_4x_done
	vmovdqu		OFFSETOF_H_POWERS_XORED(KEY), H_POW2_XORED
	vmovdqu		OFFSETOF_H_POWERS_XORED+32(KEY), H_POW1_XORED
.Laad_loop_4x:
	_ghash_4x	AAD
	sub		$-128, AAD
	add		$-128, AADLEN
	jge		.Laad_loop_4x
.Laad_loop_4x_done:

	// If AADLEN >= 32, update GHASH with 32 bytes of AAD at a time.
	add		$96, AADLEN
	jl		.Laad_loop_1x_done
.Laad_loop_1x:
	vmovdqu		(AAD), TMP0
	vpshufb		BSWAP_MASK, TMP0, TMP0
	vpxor		TMP0, GHASH_ACC, GHASH_ACC
	vmovdqu		OFFSETOFEND_H_POWERS-32(KEY), TMP0
	_ghash_mul	TMP0, GHASH_ACC, GHASH_ACC, GFPOLY, TMP1, TMP2, LO
	vextracti128	$1, GHASH_ACC, TMP0_XMM
	vpxor		TMP0_XMM, GHASH_ACC_XMM, GHASH_ACC_XMM
	add		$32, AAD
	sub		$32, AADLEN
	jge		.Laad_loop_1x
.Laad_loop_1x_done:
	add		$32, AADLEN
	// Now 0 <= AADLEN < 32.

	jz		.Laad_done
	cmp		$16, AADLEN
	jle		.Laad_lastblock

	// Update GHASH with the remaining 17 <= AADLEN <= 31 bytes of AAD.
	mov		AADLEN, AADLEN	// Zero-extend AADLEN to AADLEN64.
	vmovdqu		(AAD), TMP0_XMM
	vmovdqu		-16(AAD, AADLEN64), TMP1_XMM
	vpshufb		BSWAP_MASK_XMM, TMP0_XMM, TMP0_XMM
	vpxor		TMP0_XMM, GHASH_ACC_XMM, GHASH_ACC_XMM
	lea		.Lrshift_and_bswap_table(%rip), %rax
	vpshufb		-16(%rax, AADLEN64), TMP1_XMM, TMP1_XMM
	vinserti128	$1, TMP1_XMM, GHASH_ACC, GHASH_ACC
	vmovdqu		OFFSETOFEND_H_POWERS-32(KEY), TMP0
	_ghash_mul	TMP0, GHASH_ACC, GHASH_ACC, GFPOLY, TMP1, TMP2, LO
	vextracti128	$1, GHASH_ACC, TMP0_XMM
	vpxor		TMP0_XMM, GHASH_ACC_XMM, GHASH_ACC_XMM
	jmp		.Laad_done

.Laad_lastblock:
	// Update GHASH with the remaining 1 <= AADLEN <= 16 bytes of AAD.
	_load_partial_block	AAD, TMP0_XMM, %r8, %r8d
	vpshufb		BSWAP_MASK_XMM, TMP0_XMM, TMP0_XMM
	vpxor		TMP0_XMM, GHASH_ACC_XMM, GHASH_ACC_XMM
	vmovdqu		OFFSETOFEND_H_POWERS-16(KEY), TMP0_XMM
	_ghash_mul	TMP0_XMM, GHASH_ACC_XMM, GHASH_ACC_XMM, GFPOLY_XMM, \
			TMP1_XMM, TMP2_XMM, LO_XMM

.Laad_done:
	// Store the updated GHASH accumulator back to memory.
	vmovdqu		GHASH_ACC_XMM, (GHASH_ACC_PTR)

	vzeroupper
	RET
SYM_FUNC_END(aes_gcm_aad_update_vaes_avx2)

// Do one non-last round of AES encryption on the blocks in the given AESDATA
// vectors using the round key that has been broadcast to all 128-bit lanes of
// \round_key.
.macro	_vaesenc	round_key, vecs:vararg
.irp i, \vecs
	vaesenc		\round_key, AESDATA\i, AESDATA\i
.endr
.endm

// Generate counter blocks in the given AESDATA vectors, then do the zero-th AES
// round on them.  Clobbers TMP0.
.macro	_ctr_begin	vecs:vararg
	vbroadcasti128	.Linc_2blocks(%rip), TMP0
.irp i, \vecs
	vpshufb		BSWAP_MASK, LE_CTR, AESDATA\i
	vpaddd		TMP0, LE_CTR, LE_CTR
.endr
.irp i, \vecs
	vpxor		RNDKEY0, AESDATA\i, AESDATA\i
.endr
.endm

// Generate and encrypt counter blocks in the given AESDATA vectors, excluding
// the last AES round.  Clobbers %rax and TMP0.
.macro	_aesenc_loop	vecs:vararg
	_ctr_begin	\vecs
	lea		OFFSETOF_AESROUNDKEYS+16(KEY), %rax
.Laesenc_loop\@:
	vbroadcasti128	(%rax), TMP0
	_vaesenc	TMP0, \vecs
	add		$16, %rax
	cmp		%rax, RNDKEYLAST_PTR
	jne		.Laesenc_loop\@
.endm

// Finalize the keystream blocks in the given AESDATA vectors by doing the last
// AES round, then XOR those keystream blocks with the corresponding data.
// Reduce latency by doing the XOR before the vaesenclast, utilizing the
// property vaesenclast(key, a) ^ b == vaesenclast(key ^ b, a).  Clobbers TMP0.
.macro	_aesenclast_and_xor	vecs:vararg
.irp i, \vecs
	vpxor		\i*32(SRC), RNDKEYLAST, TMP0
	vaesenclast	TMP0, AESDATA\i, AESDATA\i
.endr
.irp i, \vecs
	vmovdqu		AESDATA\i, \i*32(DST)
.endr
.endm

// void aes_gcm_{enc,dec}_update_vaes_avx2(const struct aes_gcm_key_vaes_avx2 *key,
//					   const u32 le_ctr[4], u8 ghash_acc[16],
//					   const u8 *src, u8 *dst, int datalen);
//
// This macro generates a GCM encryption or decryption update function with the
// above prototype (with \enc selecting which one).  The function computes the
// next portion of the CTR keystream, XOR's it with |datalen| bytes from |src|,
// and writes the resulting encrypted or decrypted data to |dst|.  It also
// updates the GHASH accumulator |ghash_acc| using the next |datalen| ciphertext
// bytes.
//
// |datalen| must be a multiple of 16, except on the last call where it can be
// any length.  The caller must do any buffering needed to ensure this.  Both
// in-place and out-of-place en/decryption are supported.
//
// |le_ctr| must give the current counter in little-endian format.  This
// function loads the counter from |le_ctr| and increments the loaded counter as
// needed, but it does *not* store the updated counter back to |le_ctr|.  The
// caller must update |le_ctr| if any more data segments follow.  Internally,
// only the low 32-bit word of the counter is incremented, following the GCM
// standard.
.macro	_aes_gcm_update	enc

	// Function arguments
	.set	KEY,		%rdi
	.set	LE_CTR_PTR,	%rsi
	.set	LE_CTR_PTR32,	%esi
	.set	GHASH_ACC_PTR,	%rdx
	.set	SRC,		%rcx	// Assumed to be %rcx.
					// See .Ltail_xor_and_ghash_1to16bytes
	.set	DST,		%r8
	.set	DATALEN,	%r9d
	.set	DATALEN64,	%r9	// Zero-extend DATALEN before using!

	// Additional local variables

	// %rax is used as a temporary register.  LE_CTR_PTR is also available
	// as a temporary register after the counter is loaded.

	// AES key length in bytes
	.set	AESKEYLEN,	%r10d
	.set	AESKEYLEN64,	%r10

	// Pointer to the last AES round key for the chosen AES variant
	.set	RNDKEYLAST_PTR,	%r11

	// BSWAP_MASK is the shuffle mask for byte-reflecting 128-bit values
	// using vpshufb, copied to all 128-bit lanes.
	.set	BSWAP_MASK,	%ymm0
	.set	BSWAP_MASK_XMM,	%xmm0

	// GHASH_ACC is the accumulator variable for GHASH.  When fully reduced,
	// only the lowest 128-bit lane can be nonzero.  When not fully reduced,
	// more than one lane may be used, and they need to be XOR'd together.
	.set	GHASH_ACC,	%ymm1
	.set	GHASH_ACC_XMM,	%xmm1

	// TMP[0-2] are temporary registers.
	.set	TMP0,		%ymm2
	.set	TMP0_XMM,	%xmm2
	.set	TMP1,		%ymm3
	.set	TMP1_XMM,	%xmm3
	.set	TMP2,		%ymm4
	.set	TMP2_XMM,	%xmm4

	// LO and MI are used to accumulate unreduced GHASH products.
	.set	LO,		%ymm5
	.set	LO_XMM,		%xmm5
	.set	MI,		%ymm6
	.set	MI_XMM,		%xmm6

	// H_POW[2-1]_XORED contain cached values from KEY->h_powers_xored.  The
	// descending numbering reflects the order of the key powers.
	.set	H_POW2_XORED,	%ymm7
	.set	H_POW2_XORED_XMM, %xmm7
	.set	H_POW1_XORED,	%ymm8

	// RNDKEY0 caches the zero-th round key, and RNDKEYLAST the last one.
	.set	RNDKEY0,	%ymm9
	.set	RNDKEYLAST,	%ymm10

	// LE_CTR contains the next set of little-endian counter blocks.
	.set	LE_CTR,		%ymm11

	// AESDATA[0-3] hold the counter blocks that are being encrypted by AES.
	.set	AESDATA0,	%ymm12
	.set	AESDATA0_XMM,	%xmm12
	.set	AESDATA1,	%ymm13
	.set	AESDATA1_XMM,	%xmm13
	.set	AESDATA2,	%ymm14
	.set	AESDATA3,	%ymm15

.if \enc
	.set	GHASHDATA_PTR,	DST
.else
	.set	GHASHDATA_PTR,	SRC
.endif

	vbroadcasti128	.Lbswap_mask(%rip), BSWAP_MASK

	// Load the GHASH accumulator and the starting counter.
	vmovdqu		(GHASH_ACC_PTR), GHASH_ACC_XMM
	vbroadcasti128	(LE_CTR_PTR), LE_CTR

	// Load the AES key length in bytes.
	movl		OFFSETOF_AESKEYLEN(KEY), AESKEYLEN

	// Make RNDKEYLAST_PTR point to the last AES round key.  This is the
	// round key with index 10, 12, or 14 for AES-128, AES-192, or AES-256
	// respectively.  Then load the zero-th and last round keys.
	lea		OFFSETOF_AESROUNDKEYS+6*16(KEY,AESKEYLEN64,4), RNDKEYLAST_PTR
	vbroadcasti128	OFFSETOF_AESROUNDKEYS(KEY), RNDKEY0
	vbroadcasti128	(RNDKEYLAST_PTR), RNDKEYLAST

	// Finish initializing LE_CTR by adding 1 to the second block.
	vpaddd		.Lctr_pattern(%rip), LE_CTR, LE_CTR

	// If there are at least 128 bytes of data, then continue into the loop
	// that processes 128 bytes of data at a time.  Otherwise skip it.
	add		$-128, DATALEN	// 128 is 4 bytes, -128 is 1 byte
	jl		.Lcrypt_loop_4x_done\@

	vmovdqu		OFFSETOF_H_POWERS_XORED(KEY), H_POW2_XORED
	vmovdqu		OFFSETOF_H_POWERS_XORED+32(KEY), H_POW1_XORED

	// Main loop: en/decrypt and hash 4 vectors (128 bytes) at a time.

.if \enc
	// Encrypt the first 4 vectors of plaintext blocks.
	_aesenc_loop	0,1,2,3
	_aesenclast_and_xor	0,1,2,3
	sub		$-128, SRC	// 128 is 4 bytes, -128 is 1 byte
	add		$-128, DATALEN
	jl		.Lghash_last_ciphertext_4x\@
.endif

.align 16
.Lcrypt_loop_4x\@:

	// Start the AES encryption of the counter blocks.
	_ctr_begin	0,1,2,3
	cmp		$24, AESKEYLEN
	jl		128f	// AES-128?
	je		192f	// AES-192?
	// AES-256
	vbroadcasti128	-13*16(RNDKEYLAST_PTR), TMP0
	_vaesenc	TMP0, 0,1,2,3
	vbroadcasti128	-12*16(RNDKEYLAST_PTR), TMP0
	_vaesenc	TMP0, 0,1,2,3
192:
	vbroadcasti128	-11*16(RNDKEYLAST_PTR), TMP0
	_vaesenc	TMP0, 0,1,2,3
	vbroadcasti128	-10*16(RNDKEYLAST_PTR), TMP0
	_vaesenc	TMP0, 0,1,2,3
128:

	// Finish the AES encryption of the counter blocks in AESDATA[0-3],
	// interleaved with the GHASH update of the ciphertext blocks.
.irp i, 9,8,7,6,5,4,3,2,1
	_ghash_step_4x  (9 - \i), GHASHDATA_PTR
	vbroadcasti128	-\i*16(RNDKEYLAST_PTR), TMP0
	_vaesenc	TMP0, 0,1,2,3
.endr
	_ghash_step_4x	9, GHASHDATA_PTR
.if \enc
	sub		$-128, DST	// 128 is 4 bytes, -128 is 1 byte
.endif
	_aesenclast_and_xor	0,1,2,3
	sub		$-128, SRC
.if !\enc
	sub		$-128, DST
.endif
	add		$-128, DATALEN
	jge		.Lcrypt_loop_4x\@

.if \enc
.Lghash_last_ciphertext_4x\@:
	// Update GHASH with the last set of ciphertext blocks.
	_ghash_4x	DST
	sub		$-128, DST
.endif

.Lcrypt_loop_4x_done\@:

	// Undo the extra subtraction by 128 and check whether data remains.
	sub		$-128, DATALEN	// 128 is 4 bytes, -128 is 1 byte
	jz		.Ldone\@

	// The data length isn't a multiple of 128 bytes.  Process the remaining
	// data of length 1 <= DATALEN < 128.
	//
	// Since there are enough key powers available for all remaining data,
	// there is no need to do a GHASH reduction after each iteration.
	// Instead, multiply each remaining block by its own key power, and only
	// do a GHASH reduction at the very end.

	// Make POWERS_PTR point to the key powers [H^N, H^(N-1), ...] where N
	// is the number of blocks that remain.
	.set		POWERS_PTR, LE_CTR_PTR	// LE_CTR_PTR is free to be reused.
	.set		POWERS_PTR32, LE_CTR_PTR32
	mov		DATALEN, %eax
	neg		%rax
	and		$~15, %rax  // -round_up(DATALEN, 16)
	lea		OFFSETOFEND_H_POWERS(KEY,%rax), POWERS_PTR

	// Start collecting the unreduced GHASH intermediate value LO, MI, HI.
	.set		HI, H_POW2_XORED	// H_POW2_XORED is free to be reused.
	.set		HI_XMM, H_POW2_XORED_XMM
	vpxor		LO_XMM, LO_XMM, LO_XMM
	vpxor		MI_XMM, MI_XMM, MI_XMM
	vpxor		HI_XMM, HI_XMM, HI_XMM

	// 1 <= DATALEN < 128.  Generate 2 or 4 more vectors of keystream blocks
	// excluding the last AES round, depending on the remaining DATALEN.
	cmp		$64, DATALEN
	jg		.Ltail_gen_4_keystream_vecs\@
	_aesenc_loop	0,1
	cmp		$32, DATALEN
	jge		.Ltail_xor_and_ghash_full_vec_loop\@
	jmp		.Ltail_xor_and_ghash_partial_vec\@
.Ltail_gen_4_keystream_vecs\@:
	_aesenc_loop	0,1,2,3

	// XOR the remaining data and accumulate the unreduced GHASH products
	// for DATALEN >= 32, starting with one full 32-byte vector at a time.
.Ltail_xor_and_ghash_full_vec_loop\@:
.if \enc
	_aesenclast_and_xor	0
	vpshufb		BSWAP_MASK, AESDATA0, AESDATA0
.else
	vmovdqu		(SRC), TMP1
	vpxor		TMP1, RNDKEYLAST, TMP0
	vaesenclast	TMP0, AESDATA0, AESDATA0
	vmovdqu		AESDATA0, (DST)
	vpshufb		BSWAP_MASK, TMP1, AESDATA0
.endif
	// The ciphertext blocks (i.e. GHASH input data) are now in AESDATA0.
	vpxor		GHASH_ACC, AESDATA0, AESDATA0
	vmovdqu		(POWERS_PTR), TMP2
	_ghash_mul_noreduce	TMP2, AESDATA0, LO, MI, HI, TMP0
	vmovdqa		AESDATA1, AESDATA0
	vmovdqa		AESDATA2, AESDATA1
	vmovdqa		AESDATA3, AESDATA2
	vpxor		GHASH_ACC_XMM, GHASH_ACC_XMM, GHASH_ACC_XMM
	add		$32, SRC
	add		$32, DST
	add		$32, POWERS_PTR
	sub		$32, DATALEN
	cmp		$32, DATALEN
	jge		.Ltail_xor_and_ghash_full_vec_loop\@
	test		DATALEN, DATALEN
	jz		.Ltail_ghash_reduce\@

.Ltail_xor_and_ghash_partial_vec\@:
	// XOR the remaining data and accumulate the unreduced GHASH products,
	// for 1 <= DATALEN < 32.
	vaesenclast	RNDKEYLAST, AESDATA0, AESDATA0
	cmp		$16, DATALEN
	jle		.Ltail_xor_and_ghash_1to16bytes\@

	// Handle 17 <= DATALEN < 32.

	// Load a vpshufb mask that will right-shift by '32 - DATALEN' bytes
	// (shifting in zeroes), then reflect all 16 bytes.
	lea		.Lrshift_and_bswap_table(%rip), %rax
	vmovdqu		-16(%rax, DATALEN64), TMP2_XMM

	// Move the second keystream block to its own register and left-align it
	vextracti128	$1, AESDATA0, AESDATA1_XMM
	vpxor		.Lfifteens(%rip), TMP2_XMM, TMP0_XMM
	vpshufb		TMP0_XMM, AESDATA1_XMM, AESDATA1_XMM

	// Using overlapping loads and stores, XOR the source data with the
	// keystream and write the destination data.  Then prepare the GHASH
	// input data: the full ciphertext block and the zero-padded partial
	// ciphertext block, both byte-reflected, in AESDATA0.
.if \enc
	vpxor		-16(SRC, DATALEN64), AESDATA1_XMM, AESDATA1_XMM
	vpxor		(SRC), AESDATA0_XMM, AESDATA0_XMM
	vmovdqu		AESDATA1_XMM, -16(DST, DATALEN64)
	vmovdqu		AESDATA0_XMM, (DST)
	vpshufb		TMP2_XMM, AESDATA1_XMM, AESDATA1_XMM
	vpshufb		BSWAP_MASK_XMM, AESDATA0_XMM, AESDATA0_XMM
.else
	vmovdqu		-16(SRC, DATALEN64), TMP1_XMM
	vmovdqu		(SRC), TMP0_XMM
	vpxor		TMP1_XMM, AESDATA1_XMM, AESDATA1_XMM
	vpxor		TMP0_XMM, AESDATA0_XMM, AESDATA0_XMM
	vmovdqu		AESDATA1_XMM, -16(DST, DATALEN64)
	vmovdqu		AESDATA0_XMM, (DST)
	vpshufb		TMP2_XMM, TMP1_XMM, AESDATA1_XMM
	vpshufb		BSWAP_MASK_XMM, TMP0_XMM, AESDATA0_XMM
.endif
	vpxor		GHASH_ACC_XMM, AESDATA0_XMM, AESDATA0_XMM
	vinserti128	$1, AESDATA1_XMM, AESDATA0, AESDATA0
	vmovdqu		(POWERS_PTR), TMP2
	jmp		.Ltail_ghash_last_vec\@

.Ltail_xor_and_ghash_1to16bytes\@:
	// Handle 1 <= DATALEN <= 16.  Carefully load and store the
	// possibly-partial block, which we mustn't access out of bounds.
	vmovdqu		(POWERS_PTR), TMP2_XMM
	mov		SRC, KEY	// Free up %rcx, assuming SRC == %rcx
	mov		DATALEN, %ecx
	_load_partial_block	KEY, TMP0_XMM, POWERS_PTR, POWERS_PTR32
	vpxor		TMP0_XMM, AESDATA0_XMM, AESDATA0_XMM
	mov		DATALEN, %ecx
	_store_partial_block	AESDATA0_XMM, DST, POWERS_PTR, POWERS_PTR32
.if \enc
	lea		.Lselect_high_bytes_table(%rip), %rax
	vpshufb		BSWAP_MASK_XMM, AESDATA0_XMM, AESDATA0_XMM
	vpand		(%rax, DATALEN64), AESDATA0_XMM, AESDATA0_XMM
.else
	vpshufb		BSWAP_MASK_XMM, TMP0_XMM, AESDATA0_XMM
.endif
	vpxor		GHASH_ACC_XMM, AESDATA0_XMM, AESDATA0_XMM

.Ltail_ghash_last_vec\@:
	// Accumulate the unreduced GHASH products for the last 1-2 blocks.  The
	// GHASH input data is in AESDATA0.  If only one block remains, then the
	// second block in AESDATA0 is zero and does not affect the result.
	_ghash_mul_noreduce	TMP2, AESDATA0, LO, MI, HI, TMP0

.Ltail_ghash_reduce\@:
	// Finally, do the GHASH reduction.
	vbroadcasti128	.Lgfpoly(%rip), TMP0
	_ghash_reduce	LO, MI, HI, TMP0, TMP1
	vextracti128	$1, HI, GHASH_ACC_XMM
	vpxor		HI_XMM, GHASH_ACC_XMM, GHASH_ACC_XMM

.Ldone\@:
	// Store the updated GHASH accumulator back to memory.
	vmovdqu		GHASH_ACC_XMM, (GHASH_ACC_PTR)

	vzeroupper
	RET
.endm

// void aes_gcm_enc_final_vaes_avx2(const struct aes_gcm_key_vaes_avx2 *key,
//				    const u32 le_ctr[4], u8 ghash_acc[16],
//				    u64 total_aadlen, u64 total_datalen);
// bool aes_gcm_dec_final_vaes_avx2(const struct aes_gcm_key_vaes_avx2 *key,
//				    const u32 le_ctr[4], const u8 ghash_acc[16],
//				    u64 total_aadlen, u64 total_datalen,
//				    const u8 tag[16], int taglen);
//
// This macro generates one of the above two functions (with \enc selecting
// which one).  Both functions finish computing the GCM authentication tag by
// updating GHASH with the lengths block and encrypting the GHASH accumulator.
// |total_aadlen| and |total_datalen| must be the total length of the additional
// authenticated data and the en/decrypted data in bytes, respectively.
//
// The encryption function then stores the full-length (16-byte) computed
// authentication tag to |ghash_acc|.  The decryption function instead loads the
// expected authentication tag (the one that was transmitted) from the 16-byte
// buffer |tag|, compares the first 4 <= |taglen| <= 16 bytes of it to the
// computed tag in constant time, and returns true if and only if they match.
.macro	_aes_gcm_final	enc

	// Function arguments
	.set	KEY,		%rdi
	.set	LE_CTR_PTR,	%rsi
	.set	GHASH_ACC_PTR,	%rdx
	.set	TOTAL_AADLEN,	%rcx
	.set	TOTAL_DATALEN,	%r8
	.set	TAG,		%r9
	.set	TAGLEN,		%r10d	// Originally at 8(%rsp)
	.set	TAGLEN64,	%r10

	// Additional local variables.
	// %rax and %xmm0-%xmm3 are used as temporary registers.
	.set	AESKEYLEN,	%r11d
	.set	AESKEYLEN64,	%r11
	.set	GFPOLY,		%xmm4
	.set	BSWAP_MASK,	%xmm5
	.set	LE_CTR,		%xmm6
	.set	GHASH_ACC,	%xmm7
	.set	H_POW1,		%xmm8

	// Load some constants.
	vmovdqa		.Lgfpoly(%rip), GFPOLY
	vmovdqa		.Lbswap_mask(%rip), BSWAP_MASK

	// Load the AES key length in bytes.
	movl		OFFSETOF_AESKEYLEN(KEY), AESKEYLEN

	// Set up a counter block with 1 in the low 32-bit word.  This is the
	// counter that produces the ciphertext needed to encrypt the auth tag.
	// GFPOLY has 1 in the low word, so grab the 1 from there using a blend.
	vpblendd	$0xe, (LE_CTR_PTR), GFPOLY, LE_CTR

	// Build the lengths block and XOR it with the GHASH accumulator.
	// Although the lengths block is defined as the AAD length followed by
	// the en/decrypted data length, both in big-endian byte order, a byte
	// reflection of the full block is needed because of the way we compute
	// GHASH (see _ghash_mul_step).  By using little-endian values in the
	// opposite order, we avoid having to reflect any bytes here.
	vmovq		TOTAL_DATALEN, %xmm0
	vpinsrq		$1, TOTAL_AADLEN, %xmm0, %xmm0
	vpsllq		$3, %xmm0, %xmm0	// Bytes to bits
	vpxor		(GHASH_ACC_PTR), %xmm0, GHASH_ACC

	// Load the first hash key power (H^1), which is stored last.
	vmovdqu		OFFSETOFEND_H_POWERS-16(KEY), H_POW1

	// Load TAGLEN if decrypting.
.if !\enc
	movl		8(%rsp), TAGLEN
.endif

	// Make %rax point to the last AES round key for the chosen AES variant.
	lea		OFFSETOF_AESROUNDKEYS+6*16(KEY,AESKEYLEN64,4), %rax

	// Start the AES encryption of the counter block by swapping the counter
	// block to big-endian and XOR-ing it with the zero-th AES round key.
	vpshufb		BSWAP_MASK, LE_CTR, %xmm0
	vpxor		OFFSETOF_AESROUNDKEYS(KEY), %xmm0, %xmm0

	// Complete the AES encryption and multiply GHASH_ACC by H^1.
	// Interleave the AES and GHASH instructions to improve performance.
	cmp		$24, AESKEYLEN
	jl		128f	// AES-128?
	je		192f	// AES-192?
	// AES-256
	vaesenc		-13*16(%rax), %xmm0, %xmm0
	vaesenc		-12*16(%rax), %xmm0, %xmm0
192:
	vaesenc		-11*16(%rax), %xmm0, %xmm0
	vaesenc		-10*16(%rax), %xmm0, %xmm0
128:
.irp i, 0,1,2,3,4,5,6,7,8
	_ghash_mul_step	\i, H_POW1, GHASH_ACC, GHASH_ACC, GFPOLY, \
			%xmm1, %xmm2, %xmm3
	vaesenc		(\i-9)*16(%rax), %xmm0, %xmm0
.endr
	_ghash_mul_step	9, H_POW1, GHASH_ACC, GHASH_ACC, GFPOLY, \
			%xmm1, %xmm2, %xmm3

	// Undo the byte reflection of the GHASH accumulator.
	vpshufb		BSWAP_MASK, GHASH_ACC, GHASH_ACC

	// Do the last AES round and XOR the resulting keystream block with the
	// GHASH accumulator to produce the full computed authentication tag.
	//
	// Reduce latency by taking advantage of the property vaesenclast(key,
	// a) ^ b == vaesenclast(key ^ b, a).  I.e., XOR GHASH_ACC into the last
	// round key, instead of XOR'ing the final AES output with GHASH_ACC.
	//
	// enc_final then returns the computed auth tag, while dec_final
	// compares it with the transmitted one and returns a bool.  To compare
	// the tags, dec_final XORs them together and uses vptest to check
	// whether the result is all-zeroes.  This should be constant-time.
	// dec_final applies the vaesenclast optimization to this additional
	// value XOR'd too.
.if \enc
	vpxor		(%rax), GHASH_ACC, %xmm1
	vaesenclast	%xmm1, %xmm0, GHASH_ACC
	vmovdqu		GHASH_ACC, (GHASH_ACC_PTR)
.else
	vpxor		(TAG), GHASH_ACC, GHASH_ACC
	vpxor		(%rax), GHASH_ACC, GHASH_ACC
	vaesenclast	GHASH_ACC, %xmm0, %xmm0
	lea		.Lselect_high_bytes_table(%rip), %rax
	vmovdqu		(%rax, TAGLEN64), %xmm1
	vpshufb		BSWAP_MASK, %xmm1, %xmm1 // select low bytes, not high
	xor		%eax, %eax
	vptest		%xmm1, %xmm0
	sete		%al
.endif
	// No need for vzeroupper here, since only used xmm registers were used.
	RET
.endm

SYM_FUNC_START(aes_gcm_enc_update_vaes_avx2)
	_aes_gcm_update	1
SYM_FUNC_END(aes_gcm_enc_update_vaes_avx2)
SYM_FUNC_START(aes_gcm_dec_update_vaes_avx2)
	_aes_gcm_update	0
SYM_FUNC_END(aes_gcm_dec_update_vaes_avx2)

SYM_FUNC_START(aes_gcm_enc_final_vaes_avx2)
	_aes_gcm_final	1
SYM_FUNC_END(aes_gcm_enc_final_vaes_avx2)
SYM_FUNC_START(aes_gcm_dec_final_vaes_avx2)
	_aes_gcm_final	0
SYM_FUNC_END(aes_gcm_dec_final_vaes_avx2)