dbb1d7d66febc54639dbaa3af0f570b5426505aa
[openssl.git] / crypto / aes / asm / bsaes-x86_64.pl
1 #!/usr/bin/env perl
2
3 ###################################################################
4 ### AES-128 [originally in CTR mode]                            ###
5 ### bitsliced implementation for Intel Core 2 processors        ###
6 ### requires support of SSE extensions up to SSSE3              ###
7 ### Author: Emilia Käsper and Peter Schwabe                    ###
8 ### Date: 2009-03-19                                            ###
9 ### Public domain                                               ###
10 ###                                                             ###
11 ### See http://homes.esat.kuleuven.be/~ekasper/#software for    ###
12 ### further information.                                        ###
13 ###################################################################
14 #
15 # September 2011.
16 #
17 # Started as transliteration to "perlasm" the original code has
18 # undergone following changes:
19 #
20 # - code was made position-independent;
21 # - rounds were folded into a loop resulting in >5x size reduction
22 #   from 12.5KB to 2.2KB;
23 # - above was possibile thanks to mixcolumns() modification that
24 #   allowed to feed its output back to aesenc[last], this was
25 #   achieved at cost of two additional inter-registers moves;
26 # - some instruction reordering and interleaving;
27 # - this module doesn't implement key setup subroutine, instead it
28 #   relies on conversion of "conventional" key schedule as returned
29 #   by AES_set_encrypt_key (see discussion below);
30 # - first and last round keys are treated differently, which allowed
31 #   to skip one shiftrows(), reduce bit-sliced key schedule and
32 #   speed-up conversion by 22%;
33 # - support for 192- and 256-bit keys was added;
34 #
35 # Resulting performance in CPU cycles spent to encrypt one byte out
36 # of 4096-byte buffer with 128-bit key is:
37 #
38 #               Emilia's        this(*)         difference
39 #
40 # Core 2        9.30            8.69            +7%
41 # Nehalem(**)   7.63            6.98            +9%
42 # Atom          17.1            17.4            -2%(***)
43 #
44 # (*)   Comparison is not completely fair, because "this" is ECB,
45 #       i.e. no extra processing such as counter values calculation
46 #       and xor-ing input as in Emilia's CTR implementation is
47 #       performed. However, the CTR calculations stand for not more
48 #       than 1% of total time, so comparison is *rather* fair.
49 #
50 # (**)  Results were collected on Westmere, which is considered to
51 #       be equivalent to Nehalem for this code.
52 #
53 # (***) Slowdown on Atom is rather strange per se, because original
54 #       implementation has a number of 9+-bytes instructions, which
55 #       are bad for Atom front-end, and which I eliminated completely.
56 #       In attempt to address deterioration sbox() was tested in FP
57 #       SIMD "domain" (movaps instead of movdqa, xorps instead of
58 #       pxor, etc.). While it resulted in nominal 4% improvement on
59 #       Atom, it hurted Westmere by more than 2x factor.
60 #
61 # As for key schedule conversion subroutine. Interface to OpenSSL
62 # relies on per-invocation on-the-fly conversion. This naturally
63 # has impact on performance, especially for short inputs. Conversion
64 # time in CPU cycles and its ratio to CPU cycles spent in 8x block
65 # function is:
66 #
67 #               conversion      conversion/8x block
68 # Core 2        410             0.37
69 # Nehalem       310             0.35
70 # Atom          570             0.26
71 #
72 # The ratio values mean that 128-byte blocks will be processed
73 # 21-27% slower, 256-byte blocks - 12-16%, 384-byte blocks - 8-11%,
74 # etc. Then keep in mind that input sizes not divisible by 128 are
75 # *effectively* slower, especially shortest ones, e.g. consecutive
76 # 144-byte blocks are processed 44% slower than one would expect,
77 # 272 - 29%, 400 - 22%, etc. Yet, despite all these "shortcomings"
78 # it's still faster than ["hyper-threading-safe" code path in]
79 # aes-x86_64.pl on all lengths above 64 bytes...
80 #
81 # October 2011.
82 #
83 # Add decryption procedure.
84 #
85 #                                               <appro@openssl.org>
86
87 $flavour = shift;
88 $output  = shift;
89 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
90
91 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
92
93 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
94 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
95 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
96 die "can't locate x86_64-xlate.pl";
97
98 open STDOUT,"| $^X $xlate $flavour $output";
99
100 my ($inp,$out,$len,$key,$ivp)=("%rdi","%rsi","%rdx","%rcx");
101 my @XMM=map("%xmm$_",(15,0..14));       # best on Atom, +10% over (0..15)
102
103 {
104 my ($key,$rounds,$const)=("%rax","%r10d","%r11");
105
106 sub Sbox {
107 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
108 # output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb
109 my @b=@_[0..7];
110 my @t=@_[8..11];
111 my @s=@_[12..15];
112         &InBasisChange  (@b);
113         &Inv_GF256      (@b[6,5,0,3,7,1,4,2],@t,@s);
114         &OutBasisChange (@b[7,1,4,2,6,5,0,3]);
115 }
116
117 sub InBasisChange {
118 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
119 # output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb 
120 my @b=@_[0..7];
121 $code.=<<___;
122         pxor    @b[6], @b[5]
123         pxor    @b[1], @b[2]
124         pxor    @b[0], @b[3]
125         pxor    @b[2], @b[6]
126         pxor    @b[0], @b[5]
127
128         pxor    @b[3], @b[6]
129         pxor    @b[7], @b[3]
130         pxor    @b[5], @b[7]
131         pxor    @b[4], @b[3]
132         pxor    @b[5], @b[4]
133         pxor    @b[1], @b[3]
134
135         pxor    @b[7], @b[2]
136         pxor    @b[5], @b[1]
137 ___
138 }
139
140 sub OutBasisChange {
141 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
142 # output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb
143 my @b=@_[0..7];
144 $code.=<<___;
145         pxor    @b[6], @b[0]
146         pxor    @b[4], @b[1]
147         pxor    @b[0], @b[2]
148         pxor    @b[6], @b[4]
149         pxor    @b[1], @b[6]
150
151         pxor    @b[5], @b[1]
152         pxor    @b[3], @b[5]
153         pxor    @b[7], @b[3]
154         pxor    @b[5], @b[7]
155         pxor    @b[5], @b[2]
156
157         pxor    @b[7], @b[4]
158 ___
159 }
160
161 sub InvSbox {
162 # input in lsb  > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
163 # output in lsb > [b0, b1, b6, b4, b2, b7, b3, b5] < msb
164 my @b=@_[0..7];
165 my @t=@_[8..11];
166 my @s=@_[12..15];
167         &InvInBasisChange       (@b);
168         &Inv_GF256              (@b[5,1,2,6,3,7,0,4],@t,@s);
169         &InvOutBasisChange      (@b[3,7,0,4,5,1,2,6]);
170 }
171
172 sub InvInBasisChange {          # OutBasisChange in reverse
173 my @b=@_[5,1,2,6,3,7,0,4];
174 $code.=<<___
175         pxor    @b[7], @b[4]
176
177         pxor    @b[5], @b[7]
178         pxor    @b[5], @b[2]
179         pxor    @b[7], @b[3]
180         pxor    @b[3], @b[5]
181         pxor    @b[5], @b[1]
182
183         pxor    @b[1], @b[6]
184         pxor    @b[0], @b[2]
185         pxor    @b[6], @b[4]
186         pxor    @b[6], @b[0]
187         pxor    @b[4], @b[1]
188 ___
189 }
190
191 sub InvOutBasisChange {         # InBasisChange in reverse
192 my @b=@_[2,5,7,3,6,1,0,4];
193 $code.=<<___;
194         pxor    @b[5], @b[1]
195         pxor    @b[7], @b[2]
196
197         pxor    @b[1], @b[3]
198         pxor    @b[5], @b[4]
199         pxor    @b[5], @b[7]
200         pxor    @b[4], @b[3]
201          pxor   @b[0], @b[5]
202         pxor    @b[7], @b[3]
203          pxor   @b[2], @b[6]
204          pxor   @b[1], @b[2]
205         pxor    @b[3], @b[6]
206
207         pxor    @b[0], @b[3]
208         pxor    @b[6], @b[5]
209 ___
210 }
211
212 sub Mul_GF4 {
213 #;*************************************************************
214 #;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) *
215 #;*************************************************************
216 my ($x0,$x1,$y0,$y1,$t0)=@_;
217 $code.=<<___;
218         movdqa  $y0, $t0
219         pxor    $y1, $t0
220         pand    $x0, $t0
221         pxor    $x1, $x0
222         pand    $y0, $x1
223         pand    $y1, $x0
224         pxor    $x1, $x0
225         pxor    $t0, $x1
226 ___
227 }
228
229 sub Mul_GF4_N {                         # not used, see next subroutine
230 # multiply and scale by N
231 my ($x0,$x1,$y0,$y1,$t0)=@_;
232 $code.=<<___;
233         movdqa  $y0, $t0
234         pxor    $y1, $t0
235         pand    $x0, $t0
236         pxor    $x1, $x0
237         pand    $y0, $x1
238         pand    $y1, $x0
239         pxor    $x0, $x1
240         pxor    $t0, $x0
241 ___
242 }
243
244 sub Mul_GF4_N_GF4 {
245 # interleaved Mul_GF4_N and Mul_GF4
246 my ($x0,$x1,$y0,$y1,$t0,
247     $x2,$x3,$y2,$y3,$t1)=@_;
248 $code.=<<___;
249         movdqa  $y0, $t0
250          movdqa $y2, $t1
251         pxor    $y1, $t0
252          pxor   $y3, $t1
253         pand    $x0, $t0
254          pand   $x2, $t1
255         pxor    $x1, $x0
256          pxor   $x3, $x2
257         pand    $y0, $x1
258          pand   $y2, $x3
259         pand    $y1, $x0
260          pand   $y3, $x2
261         pxor    $x0, $x1
262          pxor   $x3, $x2
263         pxor    $t0, $x0
264          pxor   $t1, $x3
265 ___
266 }
267 sub Mul_GF16_2 {
268 my @x=@_[0..7];
269 my @y=@_[8..11];
270 my @t=@_[12..15];
271 $code.=<<___;
272         movdqa  @x[0], @t[0]
273         movdqa  @x[1], @t[1]
274 ___
275         &Mul_GF4        (@x[0], @x[1], @y[0], @y[1], @t[2]);
276 $code.=<<___;
277         pxor    @x[2], @t[0]
278         pxor    @x[3], @t[1]
279         pxor    @y[2], @y[0]
280         pxor    @y[3], @y[1]
281 ___
282         Mul_GF4_N_GF4   (@t[0], @t[1], @y[0], @y[1], @t[3],
283                          @x[2], @x[3], @y[2], @y[3], @t[2]);
284 $code.=<<___;
285         pxor    @t[0], @x[0]
286         pxor    @t[0], @x[2]
287         pxor    @t[1], @x[1]
288         pxor    @t[1], @x[3]
289
290         movdqa  @x[4], @t[0]
291         movdqa  @x[5], @t[1]
292         pxor    @x[6], @t[0]
293         pxor    @x[7], @t[1]
294 ___
295         &Mul_GF4_N_GF4  (@t[0], @t[1], @y[0], @y[1], @t[3],
296                          @x[6], @x[7], @y[2], @y[3], @t[2]);
297 $code.=<<___;
298         pxor    @y[2], @y[0]
299         pxor    @y[3], @y[1]
300 ___
301         &Mul_GF4        (@x[4], @x[5], @y[0], @y[1], @t[3]);
302 $code.=<<___;
303         pxor    @t[0], @x[4]
304         pxor    @t[0], @x[6]
305         pxor    @t[1], @x[5]
306         pxor    @t[1], @x[7]
307 ___
308 }
309 sub Inv_GF256 {
310 #;********************************************************************
311 #;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144)       *
312 #;********************************************************************
313 my @x=@_[0..7];
314 my @t=@_[8..11];
315 my @s=@_[12..15];
316 # direct optimizations from hardware
317 $code.=<<___;
318         movdqa  @x[4], @t[3]
319         movdqa  @x[5], @t[2]
320         movdqa  @x[1], @t[1]
321         movdqa  @x[7], @s[1]
322         movdqa  @x[0], @s[0]
323
324         pxor    @x[6], @t[3]
325         pxor    @x[7], @t[2]
326         pxor    @x[3], @t[1]
327          movdqa @t[3], @s[2]
328         pxor    @x[6], @s[1]
329          movdqa @t[2], @t[0]
330         pxor    @x[2], @s[0]
331          movdqa @t[3], @s[3]
332
333         por     @t[1], @t[2]
334         por     @s[0], @t[3]
335         pxor    @t[0], @s[3]
336         pand    @s[0], @s[2]
337         pxor    @t[1], @s[0]
338         pand    @t[1], @t[0]
339         pand    @s[0], @s[3]
340         movdqa  @x[3], @s[0]
341         pxor    @x[2], @s[0]
342         pand    @s[0], @s[1]
343         pxor    @s[1], @t[3]
344         pxor    @s[1], @t[2]
345         movdqa  @x[4], @s[1]
346         movdqa  @x[1], @s[0]
347         pxor    @x[5], @s[1]
348         pxor    @x[0], @s[0]
349         movdqa  @s[1], @t[1]
350         pand    @s[0], @s[1]
351         por     @s[0], @t[1]
352         pxor    @s[1], @t[0]
353         pxor    @s[3], @t[3]
354         pxor    @s[2], @t[2]
355         pxor    @s[3], @t[1]
356         movdqa  @x[7], @s[0]
357         pxor    @s[2], @t[0]
358         movdqa  @x[6], @s[1]
359         pxor    @s[2], @t[1]
360         movdqa  @x[5], @s[2]
361         pand    @x[3], @s[0]
362         movdqa  @x[4], @s[3]
363         pand    @x[2], @s[1]
364         pand    @x[1], @s[2]
365         por     @x[0], @s[3]
366         pxor    @s[0], @t[3]
367         pxor    @s[1], @t[2]
368         pxor    @s[2], @t[1]
369         pxor    @s[3], @t[0] 
370
371         #Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
372
373         # new smaller inversion
374
375         movdqa  @t[3], @s[0]
376         pand    @t[1], @t[3]
377         pxor    @t[2], @s[0]
378
379         movdqa  @t[0], @s[2]
380         movdqa  @s[0], @s[3]
381         pxor    @t[3], @s[2]
382         pand    @s[2], @s[3]
383
384         movdqa  @t[1], @s[1]
385         pxor    @t[2], @s[3]
386         pxor    @t[0], @s[1]
387
388         pxor    @t[2], @t[3]
389
390         pand    @t[3], @s[1]
391
392         movdqa  @s[2], @t[2]
393         pxor    @t[0], @s[1]
394
395         pxor    @s[1], @t[2]
396         pxor    @s[1], @t[1]
397
398         pand    @t[0], @t[2]
399
400         pxor    @t[2], @s[2]
401         pxor    @t[2], @t[1]
402
403         pand    @s[3], @s[2]
404
405         pxor    @s[0], @s[2]
406 ___
407 # output in s3, s2, s1, t1
408
409 # Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3
410
411 # Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3
412         &Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]);
413
414 ### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb
415 }
416
417 # AES linear components
418
419 sub ShiftRows {
420 my @x=@_[0..7];
421 my $mask=pop;
422 $code.=<<___;
423         pxor    0x00($key),@x[0]
424         pxor    0x10($key),@x[1]
425         pshufb  $mask,@x[0]
426         pxor    0x20($key),@x[2]
427         pshufb  $mask,@x[1]
428         pxor    0x30($key),@x[3]
429         pshufb  $mask,@x[2]
430         pxor    0x40($key),@x[4]
431         pshufb  $mask,@x[3]
432         pxor    0x50($key),@x[5]
433         pshufb  $mask,@x[4]
434         pxor    0x60($key),@x[6]
435         pshufb  $mask,@x[5]
436         pxor    0x70($key),@x[7]
437         pshufb  $mask,@x[6]
438         lea     0x80($key),$key
439         pshufb  $mask,@x[7]
440 ___
441 }
442
443 sub MixColumns {
444 # modified to emit output in order suitable for feeding back to aesenc[last]
445 my @x=@_[0..7];
446 my @t=@_[8..15];
447 $code.=<<___;
448         pshufd  \$0x93, @x[0], @t[0]    # x0 <<< 32
449         pshufd  \$0x93, @x[1], @t[1]
450          pxor   @t[0], @x[0]            # x0 ^ (x0 <<< 32)
451         pshufd  \$0x93, @x[2], @t[2]
452          pxor   @t[1], @x[1]
453         pshufd  \$0x93, @x[3], @t[3]
454          pxor   @t[2], @x[2]
455         pshufd  \$0x93, @x[4], @t[4]
456          pxor   @t[3], @x[3]
457         pshufd  \$0x93, @x[5], @t[5]
458          pxor   @t[4], @x[4]
459         pshufd  \$0x93, @x[6], @t[6]
460          pxor   @t[5], @x[5]
461         pshufd  \$0x93, @x[7], @t[7]
462          pxor   @t[6], @x[6]
463          pxor   @t[7], @x[7]
464
465         pxor    @x[0], @t[1]
466         pxor    @x[7], @t[0]
467         pxor    @x[7], @t[1]
468          pshufd \$0x4E, @x[0], @x[0]    # (x0 ^ (x0 <<< 32)) <<< 64)
469         pxor    @x[1], @t[2]
470          pshufd \$0x4E, @x[1], @x[1]
471         pxor    @x[4], @t[5]
472          pxor   @t[0], @x[0]
473         pxor    @x[5], @t[6]
474          pxor   @t[1], @x[1]
475         pxor    @x[3], @t[4]
476          pshufd \$0x4E, @x[4], @t[0]
477         pxor    @x[6], @t[7]
478          pshufd \$0x4E, @x[5], @t[1]
479         pxor    @x[2], @t[3]
480          pshufd \$0x4E, @x[3], @x[4]
481         pxor    @x[7], @t[3]
482          pshufd \$0x4E, @x[7], @x[5]
483         pxor    @x[7], @t[4]
484          pshufd \$0x4E, @x[6], @x[3]
485         pxor    @t[4], @t[0]
486          pshufd \$0x4E, @x[2], @x[6]
487         pxor    @t[5], @t[1]
488
489         pxor    @t[3], @x[4]
490         pxor    @t[7], @x[5]
491         pxor    @t[6], @x[3]
492          movdqa @t[0], @x[2]
493         pxor    @t[2], @x[6]
494          movdqa @t[1], @x[7]
495 ___
496 }
497
498 sub InvMixColumns {
499 my @x=@_[0..7];
500 my @t=@_[8..15];
501
502 $code.=<<___;
503         pshufd  \$0x93, @x[0], @t[0]
504         pshufd  \$0x93, @x[1], @t[1]
505         movdqa  @x[2], @t[2]
506         pshufd  \$0x93, @x[3], @t[3]
507         movdqa  @x[4], @t[4]
508         movdqa  @x[5], @t[5]
509         pshufd  \$0x93, @x[6], @t[6]
510         pshufd  \$0x93, @x[7], @t[7]
511
512         # multiplication by 0x0e
513         pxor    @x[5], @x[7]            # 7 5
514         pxor    @x[5], @x[2]            # 2 5
515         pxor    @x[0], @x[5]            # 5 0           [1]
516         pxor    @x[1], @x[0]            # 0 1
517         pxor    @x[2], @x[1]            # 1 25
518         pxor    @x[6], @x[0]            # 01 6          [2]
519         pxor    @x[3], @x[1]            # 125 3         [4]
520         pxor    @x[0], @x[2]            # 25 016        [3]
521         pxor    @x[7], @x[3]            # 3 75
522         pxor    @x[6], @x[7]            # 75 6          [0]
523         pxor    @x[4], @x[6]            # 6 4
524         pxor    @x[3], @x[4]            # 4 375         [6]
525         pxor    @x[7], @x[3]            # 375 756=36
526         pxor    @t[5], @x[6]            # 64 5          [7]
527         pshufd  \$0x93, @t[5], @t[5]
528         pxor    @t[2], @x[3]            # 36 2
529         pshufd  \$0x93, @t[2], @t[2]
530         pxor    @t[4], @x[3]            # 362 4         [5]
531         pshufd  \$0x93, @t[4], @t[4]
532 ___
533                                         my @y = @x[7,5,0,2,1,3,4,6];
534 $code.=<<___;
535         # multiplication by 0x0b
536         pxor    @y[0], @y[1]
537         pxor    @t[0], @y[0]
538         pxor    @t[5], @y[0]
539         pxor    @t[7], @y[0]            # 0^=057
540         pxor    @y[0], @y[1]            # 1^=057
541         pxor    @t[1], @y[1]
542         pxor    @t[6], @y[1]            # 1^=057 16
543
544         pxor    @t[6], @t[7]            # clobber t[7]
545
546         pxor    @t[1], @y[2]
547         pxor    @t[2], @y[2]
548         pxor    @t[7], @y[2]            # 2^=12 67
549
550         pxor    @t[0], @y[3]
551         pxor    @t[2], @y[3]
552         pxor    @t[3], @y[3]
553         pxor    @t[5], @y[3]            # 3^=0235
554
555         pxor    @t[7], @y[7]
556         pxor    @t[4], @y[7]            # 7^=4 67
557
558         pxor    @t[5], @t[7]            # clobber t[7] even more
559
560         pxor    @t[3], @y[6]
561         pxor    @t[7], @y[6]            # 6^=3 567
562
563         pxor    @t[7], @y[5]            # 5^=567
564         pxor    @t[7], @y[4]            # 4^=567
565
566         pxor    @t[5], @t[7]
567         pxor    @t[6], @t[7]            # restore t[7]
568
569         pxor    @t[2], @y[5]
570         pxor    @t[4], @y[5]            # 5^=24 567
571
572         pxor    @t[1], @y[4]
573         pxor    @t[3], @y[4]
574         pxor    @t[4], @y[4]            # 4^=134 567
575
576         pshufd  \$0x93, @t[0], @t[0]
577         pshufd  \$0x93, @t[1], @t[1]
578         pshufd  \$0x93, @t[2], @t[2]
579         pshufd  \$0x93, @t[3], @t[3]
580         pshufd  \$0x93, @t[4], @t[4]
581         pshufd  \$0x93, @t[5], @t[5]
582         pshufd  \$0x93, @t[6], @t[6]
583         pshufd  \$0x93, @t[7], @t[7]
584
585         # multiplication by 0x0d
586         pxor    @t[0], @y[0]
587         pxor    @t[5], @y[0]
588         pxor    @t[6], @y[0]            # 0^=056
589
590         pxor    @y[1], @y[3]
591         pxor    @t[1], @y[1]
592         pxor    @t[5], @y[1]
593         pxor    @t[7], @y[1]            # 1^=157
594         pxor    @y[1], @y[3]            # 3^=157
595
596         pxor    @t[0], @y[2]
597         pxor    @t[2], @y[2]
598         pxor    @t[6], @y[2]            # 2^=026
599
600         pxor    @t[3], @t[6]            # clobber t[6]
601
602         pxor    @t[0], @y[3]
603         pxor    @t[6], @y[3]            # 3^=0 36 157
604
605         pxor    @y[7], @y[4]
606         pxor    @t[4], @y[7]
607         pxor    @t[5], @y[7]
608         pxor    @t[7], @y[7]            # 7^=457
609         pxor    @y[7], @y[4]            # 4^=457
610         pxor    @t[1], @y[4]
611         pxor    @t[2], @y[4]            # 4^=12 457
612
613         pxor    @t[2], @y[5]
614         pxor    @t[5], @y[5]
615         pxor    @t[6], @y[5]            # 5^=25 36
616
617         pxor    @t[6], @y[6]
618         pxor    @t[4], @y[6]
619         pxor    @t[7], @y[6]            # 6^=47 36
620         pxor    @t[3], @t[6]            # restore t[6]
621
622         pshufd  \$0x93, @t[0], @t[0]
623         pshufd  \$0x93, @t[1], @t[1]
624         pshufd  \$0x93, @t[2], @t[2]
625         pshufd  \$0x93, @t[3], @t[3]
626         pshufd  \$0x93, @t[4], @t[4]
627         pshufd  \$0x93, @t[5], @t[5]
628         pshufd  \$0x93, @t[6], @t[6]
629         pshufd  \$0x93, @t[7], @t[7]
630
631         # multiplication by 0x09
632         pxor    @y[1], @y[4]
633         pxor    @t[1], @y[1]
634         pxor    @t[5], @y[1]
635         pxor    @t[6], @y[1]            # 1^=156
636         pxor    @y[1], @y[4]            # 4^=156
637         pxor    @t[4], @y[4]            # 4^=4 156
638
639         pxor    @t[7], @t[6]            # clobber t[6]
640         pxor    @t[5], @t[0]            # clobber t[0]
641
642         pxor    @t[0], @y[0]            # 0^=05
643         pxor    @t[0], @y[3]
644         pxor    @t[3], @y[3]
645         pxor    @t[7], @y[3]            # 3^=05 37
646
647         pxor    @t[2], @y[2]
648         pxor    @t[6], @y[2]            # 2^=2 67
649
650         pxor    @t[2], @y[5]
651         pxor    @t[5], @y[5]
652         pxor    @t[6], @y[5]            # 5^=25 67
653
654         pxor    @t[3], @y[6]
655         pxor    @t[6], @y[6]            # 6^=3 67
656
657         pxor    @t[4], @y[7]
658         pxor    @t[7], @y[7]            # 7^=47
659
660         movdqa  @y[0], @t[0]
661         movdqa  @y[1], @t[1]
662         movdqa  @y[2], @t[2]
663         movdqa  @y[3], @t[3]
664         movdqa  @y[4], @t[4]
665         movdqa  @y[5], @t[5]
666         movdqa  @y[6], @t[6]
667         movdqa  @y[7], @t[7]
668
669         movdqa  @t[0],@XMM[0]
670         movdqa  @t[1],@XMM[1]
671         movdqa  @t[2],@XMM[2]
672         movdqa  @t[3],@XMM[3]
673         movdqa  @t[4],@XMM[4]
674         movdqa  @t[5],@XMM[5]
675         movdqa  @t[6],@XMM[6]
676         movdqa  @t[7],@XMM[7]
677 ___
678 }
679
680 sub aesenc {                            # not used
681 my @b=@_[0..7];
682 my @t=@_[8..15];
683 $code.=<<___;
684         movdqa  0x30($const),@t[0]      # .LSR
685 ___
686         &ShiftRows      (@b,@t[0]);
687         &Sbox           (@b,@t);
688         &MixColumns     (@b[0,1,4,6,3,7,2,5],@t);
689 }
690
691 sub aesenclast {                        # not used
692 my @b=@_[0..7];
693 my @t=@_[8..15];
694 $code.=<<___;
695         movdqa  0x40($const),@t[0]      # .LSRM0
696 ___
697         &ShiftRows      (@b,@t[0]);
698         &Sbox           (@b,@t);
699 $code.=<<___
700         pxor    0x00($key),@b[0]
701         pxor    0x10($key),@b[1]
702         pxor    0x20($key),@b[4]
703         pxor    0x30($key),@b[6]
704         pxor    0x40($key),@b[3]
705         pxor    0x50($key),@b[7]
706         pxor    0x60($key),@b[2]
707         pxor    0x70($key),@b[5]
708 ___
709 }
710
711 sub swapmove {
712 my ($a,$b,$n,$mask,$t)=@_;
713 $code.=<<___;
714         movdqa  $b,$t
715         psrlq   \$$n,$b
716         pxor    $a,$b
717         pand    $mask,$b
718         pxor    $b,$a
719         psllq   \$$n,$b
720         pxor    $t,$b
721 ___
722 }
723 sub swapmove2x {
724 my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_;
725 $code.=<<___;
726         movdqa  $b0,$t0
727         psrlq   \$$n,$b0
728          movdqa $b1,$t1
729          psrlq  \$$n,$b1
730         pxor    $a0,$b0
731          pxor   $a1,$b1
732         pand    $mask,$b0
733          pand   $mask,$b1
734         pxor    $b0,$a0
735         psllq   \$$n,$b0
736          pxor   $b1,$a1
737          psllq  \$$n,$b1
738         pxor    $t0,$b0
739          pxor   $t1,$b1
740 ___
741 }
742
743 sub bitslice {
744 my @x=reverse(@_[0..7]);
745 my ($t0,$t1,$t2,$t3)=@_[8..11];
746 $code.=<<___;
747         movdqa  0x00($const),$t0        # .LBS0
748         movdqa  0x10($const),$t1        # .LBS1
749 ___
750         &swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3);
751         &swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
752 $code.=<<___;
753         movdqa  0x20($const),$t0        # .LBS2
754 ___
755         &swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3);
756         &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
757
758         &swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3);
759         &swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3);
760 }
761
762 $code.=<<___;
763 .text
764
765 .extern AES_encrypt
766 .extern AES_decrypt
767
768 .type   _bsaes_encrypt8,\@abi-omnipotent
769 .align  64
770 _bsaes_encrypt8:
771         lea     .LBS0(%rip), $const     # constants table
772
773         movdqa  ($key), @XMM[9]         # round 0 key
774         lea     0x10($key), $key
775         movdqa  0x60($const), @XMM[8]   # .LM0SR
776         pxor    @XMM[9], @XMM[0]        # xor with round0 key
777         pxor    @XMM[9], @XMM[1]
778          pshufb @XMM[8], @XMM[0]
779         pxor    @XMM[9], @XMM[2]
780          pshufb @XMM[8], @XMM[1]
781         pxor    @XMM[9], @XMM[3]
782          pshufb @XMM[8], @XMM[2]
783         pxor    @XMM[9], @XMM[4]
784          pshufb @XMM[8], @XMM[3]
785         pxor    @XMM[9], @XMM[5]
786          pshufb @XMM[8], @XMM[4]
787         pxor    @XMM[9], @XMM[6]
788          pshufb @XMM[8], @XMM[5]
789         pxor    @XMM[9], @XMM[7]
790          pshufb @XMM[8], @XMM[6]
791          pshufb @XMM[8], @XMM[7]
792 _bsaes_encrypt8_bitslice:
793 ___
794         &bitslice       (@XMM[0..7, 8..11]);
795 $code.=<<___;
796         dec     $rounds
797         jmp     .Lenc_sbox
798 .align  16
799 .Lenc_loop:
800 ___
801         &ShiftRows      (@XMM[0..7, 8]);
802 $code.=".Lenc_sbox:\n";
803         &Sbox           (@XMM[0..7, 8..15]);
804 $code.=<<___;
805         dec     $rounds
806         jl      .Lenc_done
807 ___
808         &MixColumns     (@XMM[0,1,4,6,3,7,2,5, 8..15]);
809 $code.=<<___;
810         movdqa  0x30($const), @XMM[8]   # .LSR
811         jnz     .Lenc_loop
812         movdqa  0x40($const), @XMM[8]   # .LSRM0
813         jmp     .Lenc_loop
814 .align  16
815 .Lenc_done:
816 ___
817         # output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb
818         &bitslice       (@XMM[0,1,4,6,3,7,2,5, 8..11]);
819 $code.=<<___;
820         movdqa  ($key), @XMM[8]         # last round key
821         pxor    @XMM[8], @XMM[4]
822         pxor    @XMM[8], @XMM[6]
823         pxor    @XMM[8], @XMM[3]
824         pxor    @XMM[8], @XMM[7]
825         pxor    @XMM[8], @XMM[2]
826         pxor    @XMM[8], @XMM[5]
827         pxor    @XMM[8], @XMM[0]
828         pxor    @XMM[8], @XMM[1]
829         ret
830 .size   _bsaes_encrypt8,.-_bsaes_encrypt8
831
832 .type   _bsaes_decrypt8,\@abi-omnipotent
833 .align  64
834 _bsaes_decrypt8:
835         lea     .LBS0(%rip), $const     # constants table
836
837         movdqa  ($key), @XMM[9]         # round 0 key
838         lea     0x10($key), $key
839         movdqa  -0x30($const), @XMM[8]  # .LM0ISR
840         pxor    @XMM[9], @XMM[0]        # xor with round0 key
841         pxor    @XMM[9], @XMM[1]
842          pshufb @XMM[8], @XMM[0]
843         pxor    @XMM[9], @XMM[2]
844          pshufb @XMM[8], @XMM[1]
845         pxor    @XMM[9], @XMM[3]
846          pshufb @XMM[8], @XMM[2]
847         pxor    @XMM[9], @XMM[4]
848          pshufb @XMM[8], @XMM[3]
849         pxor    @XMM[9], @XMM[5]
850          pshufb @XMM[8], @XMM[4]
851         pxor    @XMM[9], @XMM[6]
852          pshufb @XMM[8], @XMM[5]
853         pxor    @XMM[9], @XMM[7]
854          pshufb @XMM[8], @XMM[6]
855          pshufb @XMM[8], @XMM[7]
856 ___
857         &bitslice       (@XMM[0..7, 8..11]);
858 $code.=<<___;
859         dec     $rounds
860         jmp     .Ldec_sbox
861 .align  16
862 .Ldec_loop:
863 ___
864         &ShiftRows      (@XMM[0..7, 8]);
865 $code.=".Ldec_sbox:\n";
866         &InvSbox        (@XMM[0..7, 8..15]);
867 $code.=<<___;
868         dec     $rounds
869         jl      .Ldec_done
870 ___
871         &InvMixColumns  (@XMM[0,1,6,4,2,7,3,5, 8..15]);
872 $code.=<<___;
873         movdqa  -0x10($const), @XMM[8]  # .LISR
874         jnz     .Ldec_loop
875         movdqa  -0x20($const), @XMM[8]  # .LISRM0
876         jmp     .Ldec_loop
877 .align  16
878 .Ldec_done:
879 ___
880         &bitslice       (@XMM[0,1,6,4,2,7,3,5, 8..11]);
881 $code.=<<___;
882         movdqa  ($key), @XMM[8]         # last round key
883         pxor    @XMM[8], @XMM[6]
884         pxor    @XMM[8], @XMM[4]
885         pxor    @XMM[8], @XMM[2]
886         pxor    @XMM[8], @XMM[7]
887         pxor    @XMM[8], @XMM[3]
888         pxor    @XMM[8], @XMM[5]
889         pxor    @XMM[8], @XMM[0]
890         pxor    @XMM[8], @XMM[1]
891         ret
892 .size   _bsaes_decrypt8,.-_bsaes_decrypt8
893 ___
894 }
895 {
896 my ($out,$inp,$rounds,$const)=("%rax","%rcx","%r10d","%r11");
897
898 sub bitslice_key {
899 my @x=reverse(@_[0..7]);
900 my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12];
901
902         &swapmove       (@x[0,1],1,$bs0,$t2,$t3);
903 $code.=<<___;
904         #&swapmove(@x[2,3],1,$t0,$t2,$t3);
905         movdqa  @x[0], @x[2]
906         movdqa  @x[1], @x[3]
907 ___
908         #&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
909
910         &swapmove2x     (@x[0,2,1,3],2,$bs1,$t2,$t3);
911 $code.=<<___;
912         #&swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
913         movdqa  @x[0], @x[4]
914         movdqa  @x[2], @x[6]
915         movdqa  @x[1], @x[5]
916         movdqa  @x[3], @x[7]
917 ___
918         &swapmove2x     (@x[0,4,1,5],4,$bs2,$t2,$t3);
919         &swapmove2x     (@x[2,6,3,7],4,$bs2,$t2,$t3);
920 }
921
922 $code.=<<___;
923 .type   _bsaes_key_convert,\@abi-omnipotent
924 .align  16
925 _bsaes_key_convert:
926         lea     .LBS1(%rip), $const
927         movdqu  ($inp), %xmm7           # load round 0 key
928         movdqa  -0x10($const), %xmm8    # .LBS0
929         movdqa  0x00($const), %xmm9     # .LBS1
930         movdqa  0x10($const), %xmm10    # .LBS2
931         movdqa  0x40($const), %xmm13    # .LM0
932         movdqa  0x60($const), %xmm14    # .LNOT
933
934         movdqu  0x10($inp), %xmm6       # load round 1 key
935         lea     0x10($inp), $inp
936         movdqa  %xmm7, ($out)           # save round 0 key
937         lea     0x10($out), $out
938         dec     $rounds
939         jmp     .Lkey_loop
940 .align  16
941 .Lkey_loop:
942         pshufb  %xmm13, %xmm6           # .LM0
943         movdqa  %xmm6, %xmm7
944 ___
945         &bitslice_key   (map("%xmm$_",(0..7, 8..12)));
946 $code.=<<___;
947         pxor    %xmm14, %xmm5           # "pnot"
948         pxor    %xmm14, %xmm6
949         pxor    %xmm14, %xmm0
950         pxor    %xmm14, %xmm1
951         lea     0x10($inp), $inp
952         movdqa  %xmm0, 0x00($out)       # write bit-sliced round key
953         movdqa  %xmm1, 0x10($out)
954         movdqa  %xmm2, 0x20($out)
955         movdqa  %xmm3, 0x30($out)
956         movdqa  %xmm4, 0x40($out)
957         movdqa  %xmm5, 0x50($out)
958         movdqa  %xmm6, 0x60($out)
959         movdqa  %xmm7, 0x70($out)
960         lea     0x80($out),$out
961         movdqu  ($inp), %xmm6           # load next round key
962         dec     $rounds
963         jnz     .Lkey_loop
964
965         movdqa  0x70($const), %xmm7     # .L63
966         #movdqa %xmm6, ($out)           # don't save last round key
967         ret
968 .size   _bsaes_key_convert,.-_bsaes_key_convert
969 ___
970 }
971
972 if (1 && !$win64) {     # following four functions are unsupported interface
973                         # used for benchmarking...
974 $code.=<<___;
975 .globl  bsaes_enc_key_convert
976 .type   bsaes_enc_key_convert,\@function,2
977 .align  16
978 bsaes_enc_key_convert:
979         mov     240($inp),%r10d         # pass rounds
980         mov     $inp,%rcx               # pass key
981         mov     $out,%rax               # pass key schedule
982         call    _bsaes_key_convert
983         pxor    %xmm6,%xmm7             # fix up last round key
984         movdqa  %xmm7,(%rax)            # save last round key
985         ret
986 .size   bsaes_enc_key_convert,.-bsaes_enc_key_convert
987
988 .globl  bsaes_encrypt_128
989 .type   bsaes_encrypt_128,\@function,4
990 .align  16
991 bsaes_encrypt_128:
992 .Lenc128_loop:
993         movdqu  0x00($inp), @XMM[0]     # load input
994         movdqu  0x10($inp), @XMM[1]
995         movdqu  0x20($inp), @XMM[2]
996         movdqu  0x30($inp), @XMM[3]
997         movdqu  0x40($inp), @XMM[4]
998         movdqu  0x50($inp), @XMM[5]
999         movdqu  0x60($inp), @XMM[6]
1000         movdqu  0x70($inp), @XMM[7]
1001         mov     $key, %rax              # pass the $key
1002         lea     0x80($inp), $inp
1003         mov     \$10,%r10d
1004
1005         call    _bsaes_encrypt8
1006
1007         movdqu  @XMM[0], 0x00($out)     # write output
1008         movdqu  @XMM[1], 0x10($out)
1009         movdqu  @XMM[4], 0x20($out)
1010         movdqu  @XMM[6], 0x30($out)
1011         movdqu  @XMM[3], 0x40($out)
1012         movdqu  @XMM[7], 0x50($out)
1013         movdqu  @XMM[2], 0x60($out)
1014         movdqu  @XMM[5], 0x70($out)
1015         lea     0x80($out), $out
1016         sub     \$0x80,$len
1017         ja      .Lenc128_loop
1018         ret
1019 .size   bsaes_encrypt_128,.-bsaes_encrypt_128
1020
1021 .globl  bsaes_dec_key_convert
1022 .type   bsaes_dec_key_convert,\@function,2
1023 .align  16
1024 bsaes_dec_key_convert:
1025         mov     240($inp),%r10d         # pass rounds
1026         mov     $inp,%rcx               # pass key
1027         mov     $out,%rax               # pass key schedule
1028         call    _bsaes_key_convert
1029         pxor    ($out),%xmm7            # fix up round 0 key
1030         movdqa  %xmm6,(%rax)            # save last round key
1031         movdqa  %xmm7,($out)
1032         ret
1033 .size   bsaes_dec_key_convert,.-bsaes_dec_key_convert
1034
1035 .globl  bsaes_decrypt_128
1036 .type   bsaes_decrypt_128,\@function,4
1037 .align  16
1038 bsaes_decrypt_128:
1039 .Ldec128_loop:
1040         movdqu  0x00($inp), @XMM[0]     # load input
1041         movdqu  0x10($inp), @XMM[1]
1042         movdqu  0x20($inp), @XMM[2]
1043         movdqu  0x30($inp), @XMM[3]
1044         movdqu  0x40($inp), @XMM[4]
1045         movdqu  0x50($inp), @XMM[5]
1046         movdqu  0x60($inp), @XMM[6]
1047         movdqu  0x70($inp), @XMM[7]
1048         mov     $key, %rax              # pass the $key
1049         lea     0x80($inp), $inp
1050         mov     \$10,%r10d
1051
1052         call    _bsaes_decrypt8
1053
1054         movdqu  @XMM[0], 0x00($out)     # write output
1055         movdqu  @XMM[1], 0x10($out)
1056         movdqu  @XMM[6], 0x20($out)
1057         movdqu  @XMM[4], 0x30($out)
1058         movdqu  @XMM[2], 0x40($out)
1059         movdqu  @XMM[7], 0x50($out)
1060         movdqu  @XMM[3], 0x60($out)
1061         movdqu  @XMM[5], 0x70($out)
1062         lea     0x80($out), $out
1063         sub     \$0x80,$len
1064         ja      .Ldec128_loop
1065         ret
1066 .size   bsaes_decrypt_128,.-bsaes_decrypt_128
1067 ___
1068 }
1069 {
1070 ######################################################################
1071 #
1072 # OpenSSL interface
1073 #
1074 my ($arg1,$arg2,$arg3,$arg4,$arg5) = $win64     ? ("%rcx","%rdx","%r8","%r9","%r10")
1075                                                 : ("%rdi","%rsi","%rdx","%rcx","%r8");
1076 my ($inp,$out,$len,$key)=("%r12","%r13","%r14","%r15");
1077
1078 $code.=<<___;
1079 .globl  bsaes_ecb_encrypt_blocks
1080 .type   bsaes_ecb_encrypt_blocks,\@abi-omnipotent
1081 .align  16
1082 bsaes_ecb_encrypt_blocks:
1083         push    %rbp
1084         push    %rbx
1085         push    %r12
1086         push    %r13
1087         push    %r14
1088         push    %r15
1089         lea     -0x48(%rsp),%rsp
1090 ___
1091 $code.=<<___ if ($win64);
1092         lea     -0xa0(%rsp), %rsp
1093         movaps  %xmm6, 0x40(%rsp)
1094         movaps  %xmm7, 0x50(%rsp)
1095         movaps  %xmm8, 0x60(%rsp)
1096         movaps  %xmm9, 0x70(%rsp)
1097         movaps  %xmm10, 0x80(%rsp)
1098         movaps  %xmm11, 0x90(%rsp)
1099         movaps  %xmm12, 0xa0(%rsp)
1100         movaps  %xmm13, 0xb0(%rsp)
1101         movaps  %xmm14, 0xc0(%rsp)
1102         movaps  %xmm15, 0xd0(%rsp)
1103 .Lecb_enc_body:
1104 ___
1105 $code.=<<___;
1106         mov     %rsp,%rbp               # backup %rsp
1107         mov     240($arg4),%eax         # rounds
1108         mov     $arg1,$inp              # backup arguments
1109         mov     $arg2,$out
1110         mov     $arg3,$len
1111         mov     $arg4,$key
1112         cmp     \$8,$arg3
1113         jb      .Lecb_enc_short
1114
1115         mov     %eax,%ebx               # backup rounds
1116         shl     \$7,%rax                # 128 bytes per inner round key
1117         sub     \$`128-32`,%rax         # size of bit-sliced key schedule
1118         sub     %rax,%rsp
1119         mov     %rsp,%rax               # pass key schedule
1120         mov     $key,%rcx               # pass key
1121         mov     %ebx,%r10d              # pass rounds
1122         call    _bsaes_key_convert
1123         pxor    %xmm6,%xmm7             # fix up last round key
1124         movdqa  %xmm7,(%rax)            # save last round key
1125
1126         sub     \$8,$len
1127 .Lecb_enc_loop:
1128         movdqu  0x00($inp), @XMM[0]     # load input
1129         movdqu  0x10($inp), @XMM[1]
1130         movdqu  0x20($inp), @XMM[2]
1131         movdqu  0x30($inp), @XMM[3]
1132         movdqu  0x40($inp), @XMM[4]
1133         movdqu  0x50($inp), @XMM[5]
1134         mov     %rsp, %rax              # pass key schedule
1135         movdqu  0x60($inp), @XMM[6]
1136         mov     %ebx,%r10d              # pass rounds
1137         movdqu  0x70($inp), @XMM[7]
1138         lea     0x80($inp), $inp
1139
1140         call    _bsaes_encrypt8
1141
1142         movdqu  @XMM[0], 0x00($out)     # write output
1143         movdqu  @XMM[1], 0x10($out)
1144         movdqu  @XMM[4], 0x20($out)
1145         movdqu  @XMM[6], 0x30($out)
1146         movdqu  @XMM[3], 0x40($out)
1147         movdqu  @XMM[7], 0x50($out)
1148         movdqu  @XMM[2], 0x60($out)
1149         movdqu  @XMM[5], 0x70($out)
1150         lea     0x80($out), $out
1151         sub     \$8,$len
1152         jnc     .Lecb_enc_loop
1153
1154         add     \$8,$len
1155         jz      .Lecb_enc_done
1156
1157         movdqu  0x00($inp), @XMM[0]     # load input
1158         mov     %rsp, %rax              # pass key schedule
1159         mov     %ebx,%r10d              # pass rounds
1160         cmp     \$2,$len
1161         jb      .Lecb_enc_one
1162         movdqu  0x10($inp), @XMM[1]
1163         je      .Lecb_enc_two
1164         movdqu  0x20($inp), @XMM[2]
1165         cmp     \$4,$len
1166         jb      .Lecb_enc_three
1167         movdqu  0x30($inp), @XMM[3]
1168         je      .Lecb_enc_four
1169         movdqu  0x40($inp), @XMM[4]
1170         cmp     \$6,$len
1171         jb      .Lecb_enc_five
1172         movdqu  0x50($inp), @XMM[5]
1173         je      .Lecb_enc_six
1174         movdqu  0x60($inp), @XMM[6]
1175         call    _bsaes_encrypt8
1176         movdqu  @XMM[0], 0x00($out)     # write output
1177         movdqu  @XMM[1], 0x10($out)
1178         movdqu  @XMM[4], 0x20($out)
1179         movdqu  @XMM[6], 0x30($out)
1180         movdqu  @XMM[3], 0x40($out)
1181         movdqu  @XMM[7], 0x50($out)
1182         movdqu  @XMM[2], 0x60($out)
1183         jmp     .Lecb_enc_done
1184 .align  16
1185 .Lecb_enc_six:
1186         call    _bsaes_encrypt8
1187         movdqu  @XMM[0], 0x00($out)     # write output
1188         movdqu  @XMM[1], 0x10($out)
1189         movdqu  @XMM[4], 0x20($out)
1190         movdqu  @XMM[6], 0x30($out)
1191         movdqu  @XMM[3], 0x40($out)
1192         movdqu  @XMM[7], 0x50($out)
1193         jmp     .Lecb_enc_done
1194 .align  16
1195 .Lecb_enc_five:
1196         call    _bsaes_encrypt8
1197         movdqu  @XMM[0], 0x00($out)     # write output
1198         movdqu  @XMM[1], 0x10($out)
1199         movdqu  @XMM[4], 0x20($out)
1200         movdqu  @XMM[6], 0x30($out)
1201         movdqu  @XMM[3], 0x40($out)
1202         jmp     .Lecb_enc_done
1203 .align  16
1204 .Lecb_enc_four:
1205         call    _bsaes_encrypt8
1206         movdqu  @XMM[0], 0x00($out)     # write output
1207         movdqu  @XMM[1], 0x10($out)
1208         movdqu  @XMM[4], 0x20($out)
1209         movdqu  @XMM[6], 0x30($out)
1210         jmp     .Lecb_enc_done
1211 .align  16
1212 .Lecb_enc_three:
1213         call    _bsaes_encrypt8
1214         movdqu  @XMM[0], 0x00($out)     # write output
1215         movdqu  @XMM[1], 0x10($out)
1216         movdqu  @XMM[4], 0x20($out)
1217         jmp     .Lecb_enc_done
1218 .align  16
1219 .Lecb_enc_two:
1220         call    _bsaes_encrypt8
1221         movdqu  @XMM[0], 0x00($out)     # write output
1222         movdqu  @XMM[1], 0x10($out)
1223         jmp     .Lecb_enc_done
1224 .align  16
1225 .Lecb_enc_one:
1226         call    _bsaes_encrypt8
1227         movdqu  @XMM[0], 0x00($out)     # write output
1228         jmp     .Lecb_enc_done
1229 .align  16
1230 .Lecb_enc_short:
1231         lea     ($inp), $arg1
1232         lea     ($out), $arg2
1233         lea     ($key), $arg3
1234         call    AES_encrypt
1235         lea     16($inp), $inp
1236         lea     16($out), $out
1237         dec     $len
1238         jnz     .Lecb_enc_short
1239
1240 .Lecb_enc_done:
1241         lea     (%rsp),%rax
1242         pxor    %xmm0, %xmm0
1243 .Lecb_enc_bzero:                        # wipe key schedule [if any]
1244         movdqa  %xmm0, 0x00(%rax)
1245         movdqa  %xmm0, 0x10(%rax)
1246         lea     0x20(%rax), %rax
1247         cmp     %rax, %rbp
1248         jb      .Lecb_enc_bzero
1249
1250         lea     (%rbp),%rsp             # restore %rsp
1251 ___
1252 $code.=<<___ if ($win64);
1253         movaps  0x40(%rbp), %xmm6
1254         movaps  0x50(%rbp), %xmm7
1255         movaps  0x60(%rbp), %xmm8
1256         movaps  0x70(%rbp), %xmm9
1257         movaps  0x80(%rbp), %xmm10
1258         movaps  0x90(%rbp), %xmm11
1259         movaps  0xa0(%rbp), %xmm12
1260         movaps  0xb0(%rbp), %xmm13
1261         movaps  0xc0(%rbp), %xmm14
1262         movaps  0xd0(%rbp), %xmm15
1263         lea     0xa0(%rbp), %rsp
1264 ___
1265 $code.=<<___;
1266         mov     0x48(%rsp), %r15
1267         mov     0x50(%rsp), %r14
1268         mov     0x58(%rsp), %r13
1269         mov     0x60(%rsp), %r12
1270         mov     0x68(%rsp), %rbx
1271         mov     0x70(%rsp), %rbp
1272         lea     0x78(%rsp), %rsp
1273 .Lecb_enc_epilogue:
1274         ret
1275 .size   bsaes_ecb_encrypt_blocks,.-bsaes_ecb_encrypt_blocks
1276
1277 .globl  bsaes_ctr32_encrypt_blocks
1278 .type   bsaes_ctr32_encrypt_blocks,\@abi-omnipotent
1279 .align  16
1280 bsaes_ctr32_encrypt_blocks:
1281         push    %rbp
1282         push    %rbx
1283         push    %r12
1284         push    %r13
1285         push    %r14
1286         push    %r15
1287         lea     -0x48(%rsp), %rsp
1288 ___
1289 $code.=<<___ if ($win64);
1290         mov     0xa0(%rsp),$arg5        # pull ivp
1291         lea     -0xa0(%rsp), %rsp
1292         movaps  %xmm6, 0x40(%rsp)
1293         movaps  %xmm7, 0x50(%rsp)
1294         movaps  %xmm8, 0x60(%rsp)
1295         movaps  %xmm9, 0x70(%rsp)
1296         movaps  %xmm10, 0x80(%rsp)
1297         movaps  %xmm11, 0x90(%rsp)
1298         movaps  %xmm12, 0xa0(%rsp)
1299         movaps  %xmm13, 0xb0(%rsp)
1300         movaps  %xmm14, 0xc0(%rsp)
1301         movaps  %xmm15, 0xd0(%rsp)
1302 .Lctr_enc_body:
1303 ___
1304 $code.=<<___;
1305         mov     %rsp, %rbp              # backup %rsp
1306         movdqu  ($arg5), %xmm0          # load counter
1307         mov     240($arg4), %eax        # rounds
1308         mov     $arg1, $inp             # backup arguments
1309         mov     $arg2, $out
1310         mov     $arg3, $len
1311         mov     $arg4, $key
1312         movdqa  %xmm0, 0x20(%rbp)       # copy counter
1313         cmp     \$8, $arg3
1314         jb      .Lctr_enc_short
1315
1316         mov     %eax, %ebx              # rounds
1317         shl     \$7, %rax               # 128 bytes per inner round key
1318         sub     \$`128-32`, %rax        # size of bit-sliced key schedule
1319         sub     %rax, %rsp
1320
1321         mov     %rsp, %rax              # pass key schedule
1322         mov     $key, %rcx              # pass key
1323         mov     %ebx, %r10d             # pass rounds
1324         call    _bsaes_key_convert
1325         pxor    %xmm6,%xmm7             # fix up last round key
1326         movdqa  %xmm7,(%rax)            # save last round key
1327
1328         movdqa  (%rsp), @XMM[9]         # load round0 key
1329         lea     .LADD1(%rip), %r11
1330         movdqa  0x20(%rbp), @XMM[0]     # counter copy
1331         movdqa  -0x20(%r11), @XMM[8]    # .LSWPUP
1332         pshufb  @XMM[8], @XMM[9]        # byte swap upper part
1333         pshufb  @XMM[8], @XMM[0]
1334         movdqa  @XMM[9], (%rsp)         # save adjusted round0 key
1335         jmp     .Lctr_enc_loop
1336 .align  16
1337 .Lctr_enc_loop:
1338         movdqa  @XMM[0], 0x20(%rbp)     # save counter
1339         movdqa  @XMM[0], @XMM[1]        # prepare 8 counter values
1340         movdqa  @XMM[0], @XMM[2]
1341         paddd   0x00(%r11), @XMM[1]     # .LADD1
1342         movdqa  @XMM[0], @XMM[3]
1343         paddd   0x10(%r11), @XMM[2]     # .LADD2
1344         movdqa  @XMM[0], @XMM[4]
1345         paddd   0x20(%r11), @XMM[3]     # .LADD3
1346         movdqa  @XMM[0], @XMM[5]
1347         paddd   0x30(%r11), @XMM[4]     # .LADD4
1348         movdqa  @XMM[0], @XMM[6]
1349         paddd   0x40(%r11), @XMM[5]     # .LADD5
1350         movdqa  @XMM[0], @XMM[7]
1351         paddd   0x50(%r11), @XMM[6]     # .LADD6
1352         paddd   0x60(%r11), @XMM[7]     # .LADD7
1353
1354         # Borrow prologue from _bsaes_encrypt8 to use the opportunity
1355         # to flip byte order in 32-bit counter
1356         movdqa  (%rsp), @XMM[9]         # round 0 key
1357         lea     0x10(%rsp), %rax        # pass key schedule
1358         movdqa  -0x10(%r11), @XMM[8]    # .LSWPUPM0SR
1359         pxor    @XMM[9], @XMM[0]        # xor with round0 key
1360         pxor    @XMM[9], @XMM[1]
1361          pshufb @XMM[8], @XMM[0]
1362         pxor    @XMM[9], @XMM[2]
1363          pshufb @XMM[8], @XMM[1]
1364         pxor    @XMM[9], @XMM[3]
1365          pshufb @XMM[8], @XMM[2]
1366         pxor    @XMM[9], @XMM[4]
1367          pshufb @XMM[8], @XMM[3]
1368         pxor    @XMM[9], @XMM[5]
1369          pshufb @XMM[8], @XMM[4]
1370         pxor    @XMM[9], @XMM[6]
1371          pshufb @XMM[8], @XMM[5]
1372         pxor    @XMM[9], @XMM[7]
1373          pshufb @XMM[8], @XMM[6]
1374         lea     .LBS0(%rip), %r11       # constants table
1375          pshufb @XMM[8], @XMM[7]
1376         mov     %ebx,%r10d              # pass rounds
1377
1378         call    _bsaes_encrypt8_bitslice
1379
1380         sub     \$8,$len
1381         jc      .Lctr_enc_loop_done
1382
1383         movdqu  0x00($inp), @XMM[8]     # load input
1384         movdqu  0x10($inp), @XMM[9]
1385         movdqu  0x20($inp), @XMM[10]
1386         movdqu  0x30($inp), @XMM[11]
1387         movdqu  0x40($inp), @XMM[12]
1388         movdqu  0x50($inp), @XMM[13]
1389         movdqu  0x60($inp), @XMM[14]
1390         movdqu  0x70($inp), @XMM[15]
1391         lea     0x80($inp),$inp
1392         pxor    @XMM[0], @XMM[8]
1393         movdqa  0x20(%rbp), @XMM[0]     # load counter
1394         pxor    @XMM[9], @XMM[1]
1395         movdqu  @XMM[8], 0x00($out)     # write output
1396         pxor    @XMM[10], @XMM[4]
1397         movdqu  @XMM[1], 0x10($out)
1398         pxor    @XMM[11], @XMM[6]
1399         movdqu  @XMM[4], 0x20($out)
1400         pxor    @XMM[12], @XMM[3]
1401         movdqu  @XMM[6], 0x30($out)
1402         pxor    @XMM[13], @XMM[7]
1403         movdqu  @XMM[3], 0x40($out)
1404         pxor    @XMM[14], @XMM[2]
1405         movdqu  @XMM[7], 0x50($out)
1406         pxor    @XMM[15], @XMM[5]
1407         movdqu  @XMM[2], 0x60($out)
1408         lea     .LADD1(%rip), %r11
1409         movdqu  @XMM[5], 0x70($out)
1410         lea     0x80($out), $out
1411         paddd   0x70(%r11), @XMM[0]     # .LADD8
1412         jnz     .Lctr_enc_loop
1413
1414         jmp     .Lctr_enc_done
1415 .align  16
1416 .Lctr_enc_loop_done:
1417         movdqu  0x00($inp), @XMM[8]     # load input
1418         pxor    @XMM[8], @XMM[0]
1419         movdqu  @XMM[0], 0x00($out)     # write output
1420         cmp     \$2,$len
1421         jb      .Lctr_enc_done
1422         movdqu  0x10($inp), @XMM[9]
1423         pxor    @XMM[9], @XMM[1]
1424         movdqu  @XMM[1], 0x10($out)
1425         je      .Lctr_enc_done
1426         movdqu  0x20($inp), @XMM[10]
1427         pxor    @XMM[10], @XMM[4]
1428         movdqu  @XMM[4], 0x20($out)
1429         cmp     \$4,$len
1430         jb      .Lctr_enc_done
1431         movdqu  0x30($inp), @XMM[11]
1432         pxor    @XMM[11], @XMM[6]
1433         movdqu  @XMM[6], 0x30($out)
1434         je      .Lctr_enc_done
1435         movdqu  0x40($inp), @XMM[12]
1436         pxor    @XMM[12], @XMM[3]
1437         movdqu  @XMM[3], 0x40($out)
1438         cmp     \$6,$len
1439         jb      .Lctr_enc_done
1440         movdqu  0x50($inp), @XMM[13]
1441         pxor    @XMM[13], @XMM[7]
1442         movdqu  @XMM[7], 0x50($out)
1443         je      .Lctr_enc_done
1444         movdqu  0x60($inp), @XMM[14]
1445         pxor    @XMM[14], @XMM[2]
1446         movdqu  @XMM[2], 0x60($out)
1447         jmp     .Lctr_enc_done
1448
1449 .align  16
1450 .Lctr_enc_short:
1451         lea     0x20(%rbp), $arg1
1452         lea     0x30(%rbp), $arg2
1453         lea     ($key), $arg3
1454         call    AES_encrypt
1455         movdqu  ($inp), @XMM[1]
1456         lea     16($inp), $inp
1457         mov     0x2c(%rbp), %eax        # load 32-bit counter
1458         bswap   %eax
1459         pxor    0x30(%rbp), @XMM[1]
1460         inc     %eax                    # increment
1461         movdqu  @XMM[1], ($out)
1462         bswap   %eax
1463         lea     16($out), $out
1464         mov     %eax, 0x2c(%rsp)        # save 32-bit counter
1465         dec     $len
1466         jnz     .Lctr_enc_short
1467
1468 .Lctr_enc_done:
1469         lea     (%rsp), %rax
1470         pxor    %xmm0, %xmm0
1471 .Lctr_enc_bzero:                        # wipe key schedule [if any]
1472         movdqa  %xmm0, 0x00(%rax)
1473         movdqa  %xmm0, 0x10(%rax)
1474         lea     0x20(%rax), %rax
1475         cmp     %rax, %rbp
1476         ja      .Lctr_enc_bzero
1477
1478         lea     (%rbp),%rsp             # restore %rsp
1479 ___
1480 $code.=<<___ if ($win64);
1481         movaps  0x40(%rbp), %xmm6
1482         movaps  0x50(%rbp), %xmm7
1483         movaps  0x60(%rbp), %xmm8
1484         movaps  0x70(%rbp), %xmm9
1485         movaps  0x80(%rbp), %xmm10
1486         movaps  0x90(%rbp), %xmm11
1487         movaps  0xa0(%rbp), %xmm12
1488         movaps  0xb0(%rbp), %xmm13
1489         movaps  0xc0(%rbp), %xmm14
1490         movaps  0xd0(%rbp), %xmm15
1491         lea     0xa0(%rbp), %rsp
1492 ___
1493 $code.=<<___;
1494         mov     0x48(%rsp), %r15
1495         mov     0x50(%rsp), %r14
1496         mov     0x58(%rsp), %r13
1497         mov     0x60(%rsp), %r12
1498         mov     0x68(%rsp), %rbx
1499         mov     0x70(%rsp), %rbp
1500         lea     0x78(%rsp), %rsp
1501 .Lctr_enc_epilogue:
1502         ret
1503 .size   bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
1504 ___
1505 }
1506 $code.=<<___;
1507 .align  64
1508 .LM0ISR:        # InvShiftRows constants
1509         .quad   0x0a0e0206070b0f03, 0x0004080c0d010509
1510 .LISRM0:
1511         .quad   0x01040b0e0205080f, 0x0306090c00070a0d
1512 .LISR:
1513         .quad   0x0504070602010003, 0x0f0e0d0c080b0a09
1514 .LBS0:          # bit-slice constants
1515         .quad   0x5555555555555555, 0x5555555555555555
1516 .LBS1:
1517         .quad   0x3333333333333333, 0x3333333333333333
1518 .LBS2:
1519         .quad   0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f
1520 .LSR:           # shiftrows constants
1521         .quad   0x0504070600030201, 0x0f0e0d0c0a09080b
1522 .LSRM0:
1523         .quad   0x0304090e00050a0f, 0x01060b0c0207080d
1524 .LM0:
1525         .quad   0x02060a0e03070b0f, 0x0004080c0105090d
1526 .LM0SR:
1527         .quad   0x0a0e02060f03070b, 0x0004080c05090d01
1528 .LNOT:          # magic constants
1529         .quad   0xffffffffffffffff, 0xffffffffffffffff
1530 .L63:
1531         .quad   0x6363636363636363, 0x6363636363636363
1532 .LSWPUP:        # byte-swap upper dword
1533         .quad   0x0706050403020100, 0x0c0d0e0f0b0a0908
1534 .LSWPUPM0SR:
1535         .quad   0x0a0d02060c03070b, 0x0004080f05090e01
1536 .LADD1:         # counter increment constants
1537         .quad   0x0000000000000000, 0x0000000100000000
1538 .LADD2:
1539         .quad   0x0000000000000000, 0x0000000200000000
1540 .LADD3:
1541         .quad   0x0000000000000000, 0x0000000300000000
1542 .LADD4:
1543         .quad   0x0000000000000000, 0x0000000400000000
1544 .LADD5:
1545         .quad   0x0000000000000000, 0x0000000500000000
1546 .LADD6:
1547         .quad   0x0000000000000000, 0x0000000600000000
1548 .LADD7:
1549         .quad   0x0000000000000000, 0x0000000700000000
1550 .LADD8:
1551         .quad   0x0000000000000000, 0x0000000800000000
1552 .asciz  "Bit-sliced AES for x86_64/SSSE3, Emilia Käsper and Peter Schwabe"
1553 .align  64
1554 ___
1555
1556 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
1557
1558 print $code;
1559
1560 close STDOUT;