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)
|