bsaes-x86_64.pl: add CBC decrypt and engage it in e_aes.c.
[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. Performance in CPU cycles spent to decrypt
84 # one byte out of 4096-byte buffer with 128-bit key is:
85 #
86 # Core 2        11.0
87 # Nehalem       9.16
88 #
89 #                                               <appro@openssl.org>
90
91 $flavour = shift;
92 $output  = shift;
93 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
94
95 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
96
97 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
98 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
99 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
100 die "can't locate x86_64-xlate.pl";
101
102 open STDOUT,"| $^X $xlate $flavour $output";
103
104 my ($inp,$out,$len,$key,$ivp)=("%rdi","%rsi","%rdx","%rcx");
105 my @XMM=map("%xmm$_",(15,0..14));       # best on Atom, +10% over (0..15)
106
107 {
108 my ($key,$rounds,$const)=("%rax","%r10d","%r11");
109
110 sub Sbox {
111 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
112 # output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb
113 my @b=@_[0..7];
114 my @t=@_[8..11];
115 my @s=@_[12..15];
116         &InBasisChange  (@b);
117         &Inv_GF256      (@b[6,5,0,3,7,1,4,2],@t,@s);
118         &OutBasisChange (@b[7,1,4,2,6,5,0,3]);
119 }
120
121 sub InBasisChange {
122 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
123 # output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb 
124 my @b=@_[0..7];
125 $code.=<<___;
126         pxor    @b[6], @b[5]
127         pxor    @b[1], @b[2]
128         pxor    @b[0], @b[3]
129         pxor    @b[2], @b[6]
130         pxor    @b[0], @b[5]
131
132         pxor    @b[3], @b[6]
133         pxor    @b[7], @b[3]
134         pxor    @b[5], @b[7]
135         pxor    @b[4], @b[3]
136         pxor    @b[5], @b[4]
137         pxor    @b[1], @b[3]
138
139         pxor    @b[7], @b[2]
140         pxor    @b[5], @b[1]
141 ___
142 }
143
144 sub OutBasisChange {
145 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
146 # output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb
147 my @b=@_[0..7];
148 $code.=<<___;
149         pxor    @b[6], @b[0]
150         pxor    @b[4], @b[1]
151         pxor    @b[0], @b[2]
152         pxor    @b[6], @b[4]
153         pxor    @b[1], @b[6]
154
155         pxor    @b[5], @b[1]
156         pxor    @b[3], @b[5]
157         pxor    @b[7], @b[3]
158         pxor    @b[5], @b[7]
159         pxor    @b[5], @b[2]
160
161         pxor    @b[7], @b[4]
162 ___
163 }
164
165 sub InvSbox {
166 # input in lsb  > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
167 # output in lsb > [b0, b1, b6, b4, b2, b7, b3, b5] < msb
168 my @b=@_[0..7];
169 my @t=@_[8..11];
170 my @s=@_[12..15];
171         &InvInBasisChange       (@b);
172         &Inv_GF256              (@b[5,1,2,6,3,7,0,4],@t,@s);
173         &InvOutBasisChange      (@b[3,7,0,4,5,1,2,6]);
174 }
175
176 sub InvInBasisChange {          # OutBasisChange in reverse
177 my @b=@_[5,1,2,6,3,7,0,4];
178 $code.=<<___
179         pxor    @b[7], @b[4]
180
181         pxor    @b[5], @b[7]
182         pxor    @b[5], @b[2]
183         pxor    @b[7], @b[3]
184         pxor    @b[3], @b[5]
185         pxor    @b[5], @b[1]
186
187         pxor    @b[1], @b[6]
188         pxor    @b[0], @b[2]
189         pxor    @b[6], @b[4]
190         pxor    @b[6], @b[0]
191         pxor    @b[4], @b[1]
192 ___
193 }
194
195 sub InvOutBasisChange {         # InBasisChange in reverse
196 my @b=@_[2,5,7,3,6,1,0,4];
197 $code.=<<___;
198         pxor    @b[5], @b[1]
199         pxor    @b[7], @b[2]
200
201         pxor    @b[1], @b[3]
202         pxor    @b[5], @b[4]
203         pxor    @b[5], @b[7]
204         pxor    @b[4], @b[3]
205          pxor   @b[0], @b[5]
206         pxor    @b[7], @b[3]
207          pxor   @b[2], @b[6]
208          pxor   @b[1], @b[2]
209         pxor    @b[3], @b[6]
210
211         pxor    @b[0], @b[3]
212         pxor    @b[6], @b[5]
213 ___
214 }
215
216 sub Mul_GF4 {
217 #;*************************************************************
218 #;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) *
219 #;*************************************************************
220 my ($x0,$x1,$y0,$y1,$t0)=@_;
221 $code.=<<___;
222         movdqa  $y0, $t0
223         pxor    $y1, $t0
224         pand    $x0, $t0
225         pxor    $x1, $x0
226         pand    $y0, $x1
227         pand    $y1, $x0
228         pxor    $x1, $x0
229         pxor    $t0, $x1
230 ___
231 }
232
233 sub Mul_GF4_N {                         # not used, see next subroutine
234 # multiply and scale by N
235 my ($x0,$x1,$y0,$y1,$t0)=@_;
236 $code.=<<___;
237         movdqa  $y0, $t0
238         pxor    $y1, $t0
239         pand    $x0, $t0
240         pxor    $x1, $x0
241         pand    $y0, $x1
242         pand    $y1, $x0
243         pxor    $x0, $x1
244         pxor    $t0, $x0
245 ___
246 }
247
248 sub Mul_GF4_N_GF4 {
249 # interleaved Mul_GF4_N and Mul_GF4
250 my ($x0,$x1,$y0,$y1,$t0,
251     $x2,$x3,$y2,$y3,$t1)=@_;
252 $code.=<<___;
253         movdqa  $y0, $t0
254          movdqa $y2, $t1
255         pxor    $y1, $t0
256          pxor   $y3, $t1
257         pand    $x0, $t0
258          pand   $x2, $t1
259         pxor    $x1, $x0
260          pxor   $x3, $x2
261         pand    $y0, $x1
262          pand   $y2, $x3
263         pand    $y1, $x0
264          pand   $y3, $x2
265         pxor    $x0, $x1
266          pxor   $x3, $x2
267         pxor    $t0, $x0
268          pxor   $t1, $x3
269 ___
270 }
271 sub Mul_GF16_2 {
272 my @x=@_[0..7];
273 my @y=@_[8..11];
274 my @t=@_[12..15];
275 $code.=<<___;
276         movdqa  @x[0], @t[0]
277         movdqa  @x[1], @t[1]
278 ___
279         &Mul_GF4        (@x[0], @x[1], @y[0], @y[1], @t[2]);
280 $code.=<<___;
281         pxor    @x[2], @t[0]
282         pxor    @x[3], @t[1]
283         pxor    @y[2], @y[0]
284         pxor    @y[3], @y[1]
285 ___
286         Mul_GF4_N_GF4   (@t[0], @t[1], @y[0], @y[1], @t[3],
287                          @x[2], @x[3], @y[2], @y[3], @t[2]);
288 $code.=<<___;
289         pxor    @t[0], @x[0]
290         pxor    @t[0], @x[2]
291         pxor    @t[1], @x[1]
292         pxor    @t[1], @x[3]
293
294         movdqa  @x[4], @t[0]
295         movdqa  @x[5], @t[1]
296         pxor    @x[6], @t[0]
297         pxor    @x[7], @t[1]
298 ___
299         &Mul_GF4_N_GF4  (@t[0], @t[1], @y[0], @y[1], @t[3],
300                          @x[6], @x[7], @y[2], @y[3], @t[2]);
301 $code.=<<___;
302         pxor    @y[2], @y[0]
303         pxor    @y[3], @y[1]
304 ___
305         &Mul_GF4        (@x[4], @x[5], @y[0], @y[1], @t[3]);
306 $code.=<<___;
307         pxor    @t[0], @x[4]
308         pxor    @t[0], @x[6]
309         pxor    @t[1], @x[5]
310         pxor    @t[1], @x[7]
311 ___
312 }
313 sub Inv_GF256 {
314 #;********************************************************************
315 #;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144)       *
316 #;********************************************************************
317 my @x=@_[0..7];
318 my @t=@_[8..11];
319 my @s=@_[12..15];
320 # direct optimizations from hardware
321 $code.=<<___;
322         movdqa  @x[4], @t[3]
323         movdqa  @x[5], @t[2]
324         movdqa  @x[1], @t[1]
325         movdqa  @x[7], @s[1]
326         movdqa  @x[0], @s[0]
327
328         pxor    @x[6], @t[3]
329         pxor    @x[7], @t[2]
330         pxor    @x[3], @t[1]
331          movdqa @t[3], @s[2]
332         pxor    @x[6], @s[1]
333          movdqa @t[2], @t[0]
334         pxor    @x[2], @s[0]
335          movdqa @t[3], @s[3]
336
337         por     @t[1], @t[2]
338         por     @s[0], @t[3]
339         pxor    @t[0], @s[3]
340         pand    @s[0], @s[2]
341         pxor    @t[1], @s[0]
342         pand    @t[1], @t[0]
343         pand    @s[0], @s[3]
344         movdqa  @x[3], @s[0]
345         pxor    @x[2], @s[0]
346         pand    @s[0], @s[1]
347         pxor    @s[1], @t[3]
348         pxor    @s[1], @t[2]
349         movdqa  @x[4], @s[1]
350         movdqa  @x[1], @s[0]
351         pxor    @x[5], @s[1]
352         pxor    @x[0], @s[0]
353         movdqa  @s[1], @t[1]
354         pand    @s[0], @s[1]
355         por     @s[0], @t[1]
356         pxor    @s[1], @t[0]
357         pxor    @s[3], @t[3]
358         pxor    @s[2], @t[2]
359         pxor    @s[3], @t[1]
360         movdqa  @x[7], @s[0]
361         pxor    @s[2], @t[0]
362         movdqa  @x[6], @s[1]
363         pxor    @s[2], @t[1]
364         movdqa  @x[5], @s[2]
365         pand    @x[3], @s[0]
366         movdqa  @x[4], @s[3]
367         pand    @x[2], @s[1]
368         pand    @x[1], @s[2]
369         por     @x[0], @s[3]
370         pxor    @s[0], @t[3]
371         pxor    @s[1], @t[2]
372         pxor    @s[2], @t[1]
373         pxor    @s[3], @t[0] 
374
375         #Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
376
377         # new smaller inversion
378
379         movdqa  @t[3], @s[0]
380         pand    @t[1], @t[3]
381         pxor    @t[2], @s[0]
382
383         movdqa  @t[0], @s[2]
384         movdqa  @s[0], @s[3]
385         pxor    @t[3], @s[2]
386         pand    @s[2], @s[3]
387
388         movdqa  @t[1], @s[1]
389         pxor    @t[2], @s[3]
390         pxor    @t[0], @s[1]
391
392         pxor    @t[2], @t[3]
393
394         pand    @t[3], @s[1]
395
396         movdqa  @s[2], @t[2]
397         pxor    @t[0], @s[1]
398
399         pxor    @s[1], @t[2]
400         pxor    @s[1], @t[1]
401
402         pand    @t[0], @t[2]
403
404         pxor    @t[2], @s[2]
405         pxor    @t[2], @t[1]
406
407         pand    @s[3], @s[2]
408
409         pxor    @s[0], @s[2]
410 ___
411 # output in s3, s2, s1, t1
412
413 # Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3
414
415 # Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3
416         &Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]);
417
418 ### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb
419 }
420
421 # AES linear components
422
423 sub ShiftRows {
424 my @x=@_[0..7];
425 my $mask=pop;
426 $code.=<<___;
427         pxor    0x00($key),@x[0]
428         pxor    0x10($key),@x[1]
429         pshufb  $mask,@x[0]
430         pxor    0x20($key),@x[2]
431         pshufb  $mask,@x[1]
432         pxor    0x30($key),@x[3]
433         pshufb  $mask,@x[2]
434         pxor    0x40($key),@x[4]
435         pshufb  $mask,@x[3]
436         pxor    0x50($key),@x[5]
437         pshufb  $mask,@x[4]
438         pxor    0x60($key),@x[6]
439         pshufb  $mask,@x[5]
440         pxor    0x70($key),@x[7]
441         pshufb  $mask,@x[6]
442         lea     0x80($key),$key
443         pshufb  $mask,@x[7]
444 ___
445 }
446
447 sub MixColumns {
448 # modified to emit output in order suitable for feeding back to aesenc[last]
449 my @x=@_[0..7];
450 my @t=@_[8..15];
451 $code.=<<___;
452         pshufd  \$0x93, @x[0], @t[0]    # x0 <<< 32
453         pshufd  \$0x93, @x[1], @t[1]
454          pxor   @t[0], @x[0]            # x0 ^ (x0 <<< 32)
455         pshufd  \$0x93, @x[2], @t[2]
456          pxor   @t[1], @x[1]
457         pshufd  \$0x93, @x[3], @t[3]
458          pxor   @t[2], @x[2]
459         pshufd  \$0x93, @x[4], @t[4]
460          pxor   @t[3], @x[3]
461         pshufd  \$0x93, @x[5], @t[5]
462          pxor   @t[4], @x[4]
463         pshufd  \$0x93, @x[6], @t[6]
464          pxor   @t[5], @x[5]
465         pshufd  \$0x93, @x[7], @t[7]
466          pxor   @t[6], @x[6]
467          pxor   @t[7], @x[7]
468
469         pxor    @x[0], @t[1]
470         pxor    @x[7], @t[0]
471         pxor    @x[7], @t[1]
472          pshufd \$0x4E, @x[0], @x[0]    # (x0 ^ (x0 <<< 32)) <<< 64)
473         pxor    @x[1], @t[2]
474          pshufd \$0x4E, @x[1], @x[1]
475         pxor    @x[4], @t[5]
476          pxor   @t[0], @x[0]
477         pxor    @x[5], @t[6]
478          pxor   @t[1], @x[1]
479         pxor    @x[3], @t[4]
480          pshufd \$0x4E, @x[4], @t[0]
481         pxor    @x[6], @t[7]
482          pshufd \$0x4E, @x[5], @t[1]
483         pxor    @x[2], @t[3]
484          pshufd \$0x4E, @x[3], @x[4]
485         pxor    @x[7], @t[3]
486          pshufd \$0x4E, @x[7], @x[5]
487         pxor    @x[7], @t[4]
488          pshufd \$0x4E, @x[6], @x[3]
489         pxor    @t[4], @t[0]
490          pshufd \$0x4E, @x[2], @x[6]
491         pxor    @t[5], @t[1]
492
493         pxor    @t[3], @x[4]
494         pxor    @t[7], @x[5]
495         pxor    @t[6], @x[3]
496          movdqa @t[0], @x[2]
497         pxor    @t[2], @x[6]
498          movdqa @t[1], @x[7]
499 ___
500 }
501
502 sub InvMixColumns {
503 my @x=@_[0..7];
504 my @t=@_[8..15];
505
506 $code.=<<___;
507         # multiplication by 0x0e
508         pshufd  \$0x93, @x[7], @t[7]
509         movdqa  @x[2], @t[2]
510         pxor    @x[5], @x[7]            # 7 5
511         pxor    @x[5], @x[2]            # 2 5
512         pshufd  \$0x93, @x[0], @t[0]
513         movdqa  @x[5], @t[5]
514         pxor    @x[0], @x[5]            # 5 0           [1]
515         pxor    @x[1], @x[0]            # 0 1
516         pshufd  \$0x93, @x[1], @t[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         pshufd  \$0x93, @x[3], @t[3]
521         pxor    @x[0], @x[2]            # 25 016        [3]
522         pxor    @x[7], @x[3]            # 3 75
523         pxor    @x[6], @x[7]            # 75 6          [0]
524         pshufd  \$0x93, @x[6], @t[6]
525         movdqa  @x[4], @t[4]
526         pxor    @x[4], @x[6]            # 6 4
527         pxor    @x[3], @x[4]            # 4 375         [6]
528         pxor    @x[7], @x[3]            # 375 756=36
529         pxor    @t[5], @x[6]            # 64 5          [7]
530         pxor    @t[2], @x[3]            # 36 2
531         pxor    @t[4], @x[3]            # 362 4         [5]
532         pshufd  \$0x93, @t[5], @t[5]
533 ___
534                                         my @y = @x[7,5,0,2,1,3,4,6];
535 $code.=<<___;
536         # multiplication by 0x0b
537         pxor    @y[0], @y[1]
538         pxor    @t[0], @y[0]
539         pxor    @t[1], @y[1]
540         pshufd  \$0x93, @t[2], @t[2]
541         pxor    @t[5], @y[0]
542         pxor    @t[6], @y[1]
543         pxor    @t[7], @y[0]
544         pshufd  \$0x93, @t[4], @t[4]
545         pxor    @t[6], @t[7]            # clobber t[7]
546         pxor    @y[0], @y[1]
547
548         pxor    @t[0], @y[3]
549         pshufd  \$0x93, @t[0], @t[0]
550         pxor    @t[1], @y[2]
551         pxor    @t[1], @y[4]
552         pxor    @t[2], @y[2]
553         pshufd  \$0x93, @t[1], @t[1]
554         pxor    @t[2], @y[3]
555         pxor    @t[2], @y[5]
556         pxor    @t[7], @y[2]
557         pshufd  \$0x93, @t[2], @t[2]
558         pxor    @t[3], @y[3]
559         pxor    @t[3], @y[6]
560         pxor    @t[3], @y[4]
561         pshufd  \$0x93, @t[3], @t[3]
562         pxor    @t[4], @y[7]
563         pxor    @t[4], @y[5]
564         pxor    @t[7], @y[7]
565         pxor    @t[5], @y[3]
566         pxor    @t[4], @y[4]
567         pxor    @t[5], @t[7]            # clobber t[7] even more
568
569         pxor    @t[7], @y[5]
570         pshufd  \$0x93, @t[4], @t[4]
571         pxor    @t[7], @y[6]
572         pxor    @t[7], @y[4]
573
574         pxor    @t[5], @t[7]
575         pshufd  \$0x93, @t[5], @t[5]
576         pxor    @t[6], @t[7]            # restore t[7]
577
578         # multiplication by 0x0d
579         pxor    @y[7], @y[4]
580         pxor    @t[4], @y[7]
581         pshufd  \$0x93, @t[6], @t[6]
582         pxor    @t[0], @y[2]
583         pxor    @t[5], @y[7]
584         pxor    @t[2], @y[2]
585         pshufd  \$0x93, @t[7], @t[7]
586
587         pxor    @y[1], @y[3]
588         pxor    @t[1], @y[1]
589         pxor    @t[0], @y[0]
590         pxor    @t[0], @y[3]
591         pxor    @t[5], @y[1]
592         pxor    @t[5], @y[0]
593         pxor    @t[7], @y[1]
594         pshufd  \$0x93, @t[0], @t[0]
595         pxor    @t[6], @y[0]
596         pxor    @y[1], @y[3]
597         pxor    @t[1], @y[4]
598         pshufd  \$0x93, @t[1], @t[1]
599
600         pxor    @t[7], @y[7]
601         pxor    @t[2], @y[4]
602         pxor    @t[2], @y[5]
603         pshufd  \$0x93, @t[2], @t[2]
604         pxor    @t[6], @y[2]
605         pxor    @t[3], @t[6]            # clobber t[6]
606         pxor    @y[7], @y[4]
607         pxor    @t[6], @y[3]
608
609         pxor    @t[6], @y[6]
610         pxor    @t[5], @y[5]
611         pxor    @t[4], @y[6]
612         pshufd  \$0x93, @t[4], @t[4]
613         pxor    @t[6], @y[5]
614         pxor    @t[7], @y[6]
615         pxor    @t[3], @t[6]            # restore t[6]
616
617         pshufd  \$0x93, @t[5], @t[5]
618         pshufd  \$0x93, @t[6], @t[6]
619         pshufd  \$0x93, @t[7], @t[7]
620         pshufd  \$0x93, @t[3], @t[3]
621
622         # multiplication by 0x09
623         pxor    @y[1], @y[4]
624         pxor    @y[1], @t[1]            # t[1]=y[1]
625         pxor    @t[5], @t[0]            # clobber t[0]
626         pxor    @t[5], @t[1]
627         pxor    @t[0], @y[3]
628         pxor    @y[0], @t[0]            # t[0]=y[0]
629         pxor    @t[6], @t[1]
630         pxor    @t[7], @t[6]            # clobber t[6]
631         pxor    @t[1], @y[4]
632         pxor    @t[4], @y[7]
633         pxor    @y[4], @t[4]            # t[4]=y[4]
634         pxor    @t[3], @y[6]
635         pxor    @y[3], @t[3]            # t[3]=y[3]
636         pxor    @t[2], @y[5]
637         pxor    @y[2], @t[2]            # t[2]=y[2]
638         pxor    @t[7], @t[3]
639         pxor    @y[5], @t[5]            # t[5]=y[5]
640         pxor    @t[6], @t[2]
641         pxor    @t[6], @t[5]
642         pxor    @y[6], @t[6]            # t[6]=y[6]
643         pxor    @y[7], @t[7]            # t[7]=y[7]
644
645         movdqa  @t[0],@XMM[0]
646         movdqa  @t[1],@XMM[1]
647         movdqa  @t[2],@XMM[2]
648         movdqa  @t[3],@XMM[3]
649         movdqa  @t[4],@XMM[4]
650         movdqa  @t[5],@XMM[5]
651         movdqa  @t[6],@XMM[6]
652         movdqa  @t[7],@XMM[7]
653 ___
654 }
655
656 sub aesenc {                            # not used
657 my @b=@_[0..7];
658 my @t=@_[8..15];
659 $code.=<<___;
660         movdqa  0x30($const),@t[0]      # .LSR
661 ___
662         &ShiftRows      (@b,@t[0]);
663         &Sbox           (@b,@t);
664         &MixColumns     (@b[0,1,4,6,3,7,2,5],@t);
665 }
666
667 sub aesenclast {                        # not used
668 my @b=@_[0..7];
669 my @t=@_[8..15];
670 $code.=<<___;
671         movdqa  0x40($const),@t[0]      # .LSRM0
672 ___
673         &ShiftRows      (@b,@t[0]);
674         &Sbox           (@b,@t);
675 $code.=<<___
676         pxor    0x00($key),@b[0]
677         pxor    0x10($key),@b[1]
678         pxor    0x20($key),@b[4]
679         pxor    0x30($key),@b[6]
680         pxor    0x40($key),@b[3]
681         pxor    0x50($key),@b[7]
682         pxor    0x60($key),@b[2]
683         pxor    0x70($key),@b[5]
684 ___
685 }
686
687 sub swapmove {
688 my ($a,$b,$n,$mask,$t)=@_;
689 $code.=<<___;
690         movdqa  $b,$t
691         psrlq   \$$n,$b
692         pxor    $a,$b
693         pand    $mask,$b
694         pxor    $b,$a
695         psllq   \$$n,$b
696         pxor    $t,$b
697 ___
698 }
699 sub swapmove2x {
700 my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_;
701 $code.=<<___;
702         movdqa  $b0,$t0
703         psrlq   \$$n,$b0
704          movdqa $b1,$t1
705          psrlq  \$$n,$b1
706         pxor    $a0,$b0
707          pxor   $a1,$b1
708         pand    $mask,$b0
709          pand   $mask,$b1
710         pxor    $b0,$a0
711         psllq   \$$n,$b0
712          pxor   $b1,$a1
713          psllq  \$$n,$b1
714         pxor    $t0,$b0
715          pxor   $t1,$b1
716 ___
717 }
718
719 sub bitslice {
720 my @x=reverse(@_[0..7]);
721 my ($t0,$t1,$t2,$t3)=@_[8..11];
722 $code.=<<___;
723         movdqa  0x00($const),$t0        # .LBS0
724         movdqa  0x10($const),$t1        # .LBS1
725 ___
726         &swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3);
727         &swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
728 $code.=<<___;
729         movdqa  0x20($const),$t0        # .LBS2
730 ___
731         &swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3);
732         &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
733
734         &swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3);
735         &swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3);
736 }
737
738 $code.=<<___;
739 .text
740
741 .extern AES_encrypt
742 .extern AES_decrypt
743
744 .type   _bsaes_encrypt8,\@abi-omnipotent
745 .align  64
746 _bsaes_encrypt8:
747         lea     .LBS0(%rip), $const     # constants table
748
749         movdqa  ($key), @XMM[9]         # round 0 key
750         lea     0x10($key), $key
751         movdqa  0x60($const), @XMM[8]   # .LM0SR
752         pxor    @XMM[9], @XMM[0]        # xor with round0 key
753         pxor    @XMM[9], @XMM[1]
754          pshufb @XMM[8], @XMM[0]
755         pxor    @XMM[9], @XMM[2]
756          pshufb @XMM[8], @XMM[1]
757         pxor    @XMM[9], @XMM[3]
758          pshufb @XMM[8], @XMM[2]
759         pxor    @XMM[9], @XMM[4]
760          pshufb @XMM[8], @XMM[3]
761         pxor    @XMM[9], @XMM[5]
762          pshufb @XMM[8], @XMM[4]
763         pxor    @XMM[9], @XMM[6]
764          pshufb @XMM[8], @XMM[5]
765         pxor    @XMM[9], @XMM[7]
766          pshufb @XMM[8], @XMM[6]
767          pshufb @XMM[8], @XMM[7]
768 _bsaes_encrypt8_bitslice:
769 ___
770         &bitslice       (@XMM[0..7, 8..11]);
771 $code.=<<___;
772         dec     $rounds
773         jmp     .Lenc_sbox
774 .align  16
775 .Lenc_loop:
776 ___
777         &ShiftRows      (@XMM[0..7, 8]);
778 $code.=".Lenc_sbox:\n";
779         &Sbox           (@XMM[0..7, 8..15]);
780 $code.=<<___;
781         dec     $rounds
782         jl      .Lenc_done
783 ___
784         &MixColumns     (@XMM[0,1,4,6,3,7,2,5, 8..15]);
785 $code.=<<___;
786         movdqa  0x30($const), @XMM[8]   # .LSR
787         jnz     .Lenc_loop
788         movdqa  0x40($const), @XMM[8]   # .LSRM0
789         jmp     .Lenc_loop
790 .align  16
791 .Lenc_done:
792 ___
793         # output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb
794         &bitslice       (@XMM[0,1,4,6,3,7,2,5, 8..11]);
795 $code.=<<___;
796         movdqa  ($key), @XMM[8]         # last round key
797         pxor    @XMM[8], @XMM[4]
798         pxor    @XMM[8], @XMM[6]
799         pxor    @XMM[8], @XMM[3]
800         pxor    @XMM[8], @XMM[7]
801         pxor    @XMM[8], @XMM[2]
802         pxor    @XMM[8], @XMM[5]
803         pxor    @XMM[8], @XMM[0]
804         pxor    @XMM[8], @XMM[1]
805         ret
806 .size   _bsaes_encrypt8,.-_bsaes_encrypt8
807
808 .type   _bsaes_decrypt8,\@abi-omnipotent
809 .align  64
810 _bsaes_decrypt8:
811         lea     .LBS0(%rip), $const     # constants table
812
813         movdqa  ($key), @XMM[9]         # round 0 key
814         lea     0x10($key), $key
815         movdqa  -0x30($const), @XMM[8]  # .LM0ISR
816         pxor    @XMM[9], @XMM[0]        # xor with round0 key
817         pxor    @XMM[9], @XMM[1]
818          pshufb @XMM[8], @XMM[0]
819         pxor    @XMM[9], @XMM[2]
820          pshufb @XMM[8], @XMM[1]
821         pxor    @XMM[9], @XMM[3]
822          pshufb @XMM[8], @XMM[2]
823         pxor    @XMM[9], @XMM[4]
824          pshufb @XMM[8], @XMM[3]
825         pxor    @XMM[9], @XMM[5]
826          pshufb @XMM[8], @XMM[4]
827         pxor    @XMM[9], @XMM[6]
828          pshufb @XMM[8], @XMM[5]
829         pxor    @XMM[9], @XMM[7]
830          pshufb @XMM[8], @XMM[6]
831          pshufb @XMM[8], @XMM[7]
832 ___
833         &bitslice       (@XMM[0..7, 8..11]);
834 $code.=<<___;
835         dec     $rounds
836         jmp     .Ldec_sbox
837 .align  16
838 .Ldec_loop:
839 ___
840         &ShiftRows      (@XMM[0..7, 8]);
841 $code.=".Ldec_sbox:\n";
842         &InvSbox        (@XMM[0..7, 8..15]);
843 $code.=<<___;
844         dec     $rounds
845         jl      .Ldec_done
846 ___
847         &InvMixColumns  (@XMM[0,1,6,4,2,7,3,5, 8..15]);
848 $code.=<<___;
849         movdqa  -0x10($const), @XMM[8]  # .LISR
850         jnz     .Ldec_loop
851         movdqa  -0x20($const), @XMM[8]  # .LISRM0
852         jmp     .Ldec_loop
853 .align  16
854 .Ldec_done:
855 ___
856         &bitslice       (@XMM[0,1,6,4,2,7,3,5, 8..11]);
857 $code.=<<___;
858         movdqa  ($key), @XMM[8]         # last round key
859         pxor    @XMM[8], @XMM[6]
860         pxor    @XMM[8], @XMM[4]
861         pxor    @XMM[8], @XMM[2]
862         pxor    @XMM[8], @XMM[7]
863         pxor    @XMM[8], @XMM[3]
864         pxor    @XMM[8], @XMM[5]
865         pxor    @XMM[8], @XMM[0]
866         pxor    @XMM[8], @XMM[1]
867         ret
868 .size   _bsaes_decrypt8,.-_bsaes_decrypt8
869 ___
870 }
871 {
872 my ($out,$inp,$rounds,$const)=("%rax","%rcx","%r10d","%r11");
873
874 sub bitslice_key {
875 my @x=reverse(@_[0..7]);
876 my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12];
877
878         &swapmove       (@x[0,1],1,$bs0,$t2,$t3);
879 $code.=<<___;
880         #&swapmove(@x[2,3],1,$t0,$t2,$t3);
881         movdqa  @x[0], @x[2]
882         movdqa  @x[1], @x[3]
883 ___
884         #&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
885
886         &swapmove2x     (@x[0,2,1,3],2,$bs1,$t2,$t3);
887 $code.=<<___;
888         #&swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
889         movdqa  @x[0], @x[4]
890         movdqa  @x[2], @x[6]
891         movdqa  @x[1], @x[5]
892         movdqa  @x[3], @x[7]
893 ___
894         &swapmove2x     (@x[0,4,1,5],4,$bs2,$t2,$t3);
895         &swapmove2x     (@x[2,6,3,7],4,$bs2,$t2,$t3);
896 }
897
898 $code.=<<___;
899 .type   _bsaes_key_convert,\@abi-omnipotent
900 .align  16
901 _bsaes_key_convert:
902         lea     .LBS1(%rip), $const
903         movdqu  ($inp), %xmm7           # load round 0 key
904         movdqa  -0x10($const), %xmm8    # .LBS0
905         movdqa  0x00($const), %xmm9     # .LBS1
906         movdqa  0x10($const), %xmm10    # .LBS2
907         movdqa  0x40($const), %xmm13    # .LM0
908         movdqa  0x60($const), %xmm14    # .LNOT
909
910         movdqu  0x10($inp), %xmm6       # load round 1 key
911         lea     0x10($inp), $inp
912         movdqa  %xmm7, ($out)           # save round 0 key
913         lea     0x10($out), $out
914         dec     $rounds
915         jmp     .Lkey_loop
916 .align  16
917 .Lkey_loop:
918         pshufb  %xmm13, %xmm6           # .LM0
919         movdqa  %xmm6, %xmm7
920 ___
921         &bitslice_key   (map("%xmm$_",(0..7, 8..12)));
922 $code.=<<___;
923         pxor    %xmm14, %xmm5           # "pnot"
924         pxor    %xmm14, %xmm6
925         pxor    %xmm14, %xmm0
926         pxor    %xmm14, %xmm1
927         lea     0x10($inp), $inp
928         movdqa  %xmm0, 0x00($out)       # write bit-sliced round key
929         movdqa  %xmm1, 0x10($out)
930         movdqa  %xmm2, 0x20($out)
931         movdqa  %xmm3, 0x30($out)
932         movdqa  %xmm4, 0x40($out)
933         movdqa  %xmm5, 0x50($out)
934         movdqa  %xmm6, 0x60($out)
935         movdqa  %xmm7, 0x70($out)
936         lea     0x80($out),$out
937         movdqu  ($inp), %xmm6           # load next round key
938         dec     $rounds
939         jnz     .Lkey_loop
940
941         movdqa  0x70($const), %xmm7     # .L63
942         #movdqa %xmm6, ($out)           # don't save last round key
943         ret
944 .size   _bsaes_key_convert,.-_bsaes_key_convert
945 ___
946 }
947
948 if (1 && !$win64) {     # following four functions are unsupported interface
949                         # used for benchmarking...
950 $code.=<<___;
951 .globl  bsaes_enc_key_convert
952 .type   bsaes_enc_key_convert,\@function,2
953 .align  16
954 bsaes_enc_key_convert:
955         mov     240($inp),%r10d         # pass rounds
956         mov     $inp,%rcx               # pass key
957         mov     $out,%rax               # pass key schedule
958         call    _bsaes_key_convert
959         pxor    %xmm6,%xmm7             # fix up last round key
960         movdqa  %xmm7,(%rax)            # save last round key
961         ret
962 .size   bsaes_enc_key_convert,.-bsaes_enc_key_convert
963
964 .globl  bsaes_encrypt_128
965 .type   bsaes_encrypt_128,\@function,4
966 .align  16
967 bsaes_encrypt_128:
968 .Lenc128_loop:
969         movdqu  0x00($inp), @XMM[0]     # load input
970         movdqu  0x10($inp), @XMM[1]
971         movdqu  0x20($inp), @XMM[2]
972         movdqu  0x30($inp), @XMM[3]
973         movdqu  0x40($inp), @XMM[4]
974         movdqu  0x50($inp), @XMM[5]
975         movdqu  0x60($inp), @XMM[6]
976         movdqu  0x70($inp), @XMM[7]
977         mov     $key, %rax              # pass the $key
978         lea     0x80($inp), $inp
979         mov     \$10,%r10d
980
981         call    _bsaes_encrypt8
982
983         movdqu  @XMM[0], 0x00($out)     # write output
984         movdqu  @XMM[1], 0x10($out)
985         movdqu  @XMM[4], 0x20($out)
986         movdqu  @XMM[6], 0x30($out)
987         movdqu  @XMM[3], 0x40($out)
988         movdqu  @XMM[7], 0x50($out)
989         movdqu  @XMM[2], 0x60($out)
990         movdqu  @XMM[5], 0x70($out)
991         lea     0x80($out), $out
992         sub     \$0x80,$len
993         ja      .Lenc128_loop
994         ret
995 .size   bsaes_encrypt_128,.-bsaes_encrypt_128
996
997 .globl  bsaes_dec_key_convert
998 .type   bsaes_dec_key_convert,\@function,2
999 .align  16
1000 bsaes_dec_key_convert:
1001         mov     240($inp),%r10d         # pass rounds
1002         mov     $inp,%rcx               # pass key
1003         mov     $out,%rax               # pass key schedule
1004         call    _bsaes_key_convert
1005         pxor    ($out),%xmm7            # fix up round 0 key
1006         movdqa  %xmm6,(%rax)            # save last round key
1007         movdqa  %xmm7,($out)
1008         ret
1009 .size   bsaes_dec_key_convert,.-bsaes_dec_key_convert
1010
1011 .globl  bsaes_decrypt_128
1012 .type   bsaes_decrypt_128,\@function,4
1013 .align  16
1014 bsaes_decrypt_128:
1015 .Ldec128_loop:
1016         movdqu  0x00($inp), @XMM[0]     # load input
1017         movdqu  0x10($inp), @XMM[1]
1018         movdqu  0x20($inp), @XMM[2]
1019         movdqu  0x30($inp), @XMM[3]
1020         movdqu  0x40($inp), @XMM[4]
1021         movdqu  0x50($inp), @XMM[5]
1022         movdqu  0x60($inp), @XMM[6]
1023         movdqu  0x70($inp), @XMM[7]
1024         mov     $key, %rax              # pass the $key
1025         lea     0x80($inp), $inp
1026         mov     \$10,%r10d
1027
1028         call    _bsaes_decrypt8
1029
1030         movdqu  @XMM[0], 0x00($out)     # write output
1031         movdqu  @XMM[1], 0x10($out)
1032         movdqu  @XMM[6], 0x20($out)
1033         movdqu  @XMM[4], 0x30($out)
1034         movdqu  @XMM[2], 0x40($out)
1035         movdqu  @XMM[7], 0x50($out)
1036         movdqu  @XMM[3], 0x60($out)
1037         movdqu  @XMM[5], 0x70($out)
1038         lea     0x80($out), $out
1039         sub     \$0x80,$len
1040         ja      .Ldec128_loop
1041         ret
1042 .size   bsaes_decrypt_128,.-bsaes_decrypt_128
1043 ___
1044 }
1045 {
1046 ######################################################################
1047 #
1048 # OpenSSL interface
1049 #
1050 my ($arg1,$arg2,$arg3,$arg4,$arg5,$arg6)=$win64 ? ("%rcx","%rdx","%r8","%r9","%r10","%r11d")
1051                                                 : ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d");
1052 my ($inp,$out,$len,$key)=("%r12","%r13","%r14","%r15");
1053
1054 if (0) {        # suppress unreferenced ECB subroutines, spare some space...
1055 $code.=<<___;
1056 .globl  bsaes_ecb_encrypt_blocks
1057 .type   bsaes_ecb_encrypt_blocks,\@abi-omnipotent
1058 .align  16
1059 bsaes_ecb_encrypt_blocks:
1060         push    %rbp
1061         push    %rbx
1062         push    %r12
1063         push    %r13
1064         push    %r14
1065         push    %r15
1066         lea     -0x48(%rsp),%rsp
1067 ___
1068 $code.=<<___ if ($win64);
1069         lea     -0xa0(%rsp), %rsp
1070         movaps  %xmm6, 0x40(%rsp)
1071         movaps  %xmm7, 0x50(%rsp)
1072         movaps  %xmm8, 0x60(%rsp)
1073         movaps  %xmm9, 0x70(%rsp)
1074         movaps  %xmm10, 0x80(%rsp)
1075         movaps  %xmm11, 0x90(%rsp)
1076         movaps  %xmm12, 0xa0(%rsp)
1077         movaps  %xmm13, 0xb0(%rsp)
1078         movaps  %xmm14, 0xc0(%rsp)
1079         movaps  %xmm15, 0xd0(%rsp)
1080 .Lecb_enc_body:
1081 ___
1082 $code.=<<___;
1083         mov     %rsp,%rbp               # backup %rsp
1084         mov     240($arg4),%eax         # rounds
1085         mov     $arg1,$inp              # backup arguments
1086         mov     $arg2,$out
1087         mov     $arg3,$len
1088         mov     $arg4,$key
1089         cmp     \$8,$arg3
1090         jb      .Lecb_enc_short
1091
1092         mov     %eax,%ebx               # backup rounds
1093         shl     \$7,%rax                # 128 bytes per inner round key
1094         sub     \$`128-32`,%rax         # size of bit-sliced key schedule
1095         sub     %rax,%rsp
1096         mov     %rsp,%rax               # pass key schedule
1097         mov     $key,%rcx               # pass key
1098         mov     %ebx,%r10d              # pass rounds
1099         call    _bsaes_key_convert
1100         pxor    %xmm6,%xmm7             # fix up last round key
1101         movdqa  %xmm7,(%rax)            # save last round key
1102
1103         sub     \$8,$len
1104 .Lecb_enc_loop:
1105         movdqu  0x00($inp), @XMM[0]     # load input
1106         movdqu  0x10($inp), @XMM[1]
1107         movdqu  0x20($inp), @XMM[2]
1108         movdqu  0x30($inp), @XMM[3]
1109         movdqu  0x40($inp), @XMM[4]
1110         movdqu  0x50($inp), @XMM[5]
1111         mov     %rsp, %rax              # pass key schedule
1112         movdqu  0x60($inp), @XMM[6]
1113         mov     %ebx,%r10d              # pass rounds
1114         movdqu  0x70($inp), @XMM[7]
1115         lea     0x80($inp), $inp
1116
1117         call    _bsaes_encrypt8
1118
1119         movdqu  @XMM[0], 0x00($out)     # write output
1120         movdqu  @XMM[1], 0x10($out)
1121         movdqu  @XMM[4], 0x20($out)
1122         movdqu  @XMM[6], 0x30($out)
1123         movdqu  @XMM[3], 0x40($out)
1124         movdqu  @XMM[7], 0x50($out)
1125         movdqu  @XMM[2], 0x60($out)
1126         movdqu  @XMM[5], 0x70($out)
1127         lea     0x80($out), $out
1128         sub     \$8,$len
1129         jnc     .Lecb_enc_loop
1130
1131         add     \$8,$len
1132         jz      .Lecb_enc_done
1133
1134         movdqu  0x00($inp), @XMM[0]     # load input
1135         mov     %rsp, %rax              # pass key schedule
1136         mov     %ebx,%r10d              # pass rounds
1137         cmp     \$2,$len
1138         jb      .Lecb_enc_one
1139         movdqu  0x10($inp), @XMM[1]
1140         je      .Lecb_enc_two
1141         movdqu  0x20($inp), @XMM[2]
1142         cmp     \$4,$len
1143         jb      .Lecb_enc_three
1144         movdqu  0x30($inp), @XMM[3]
1145         je      .Lecb_enc_four
1146         movdqu  0x40($inp), @XMM[4]
1147         cmp     \$6,$len
1148         jb      .Lecb_enc_five
1149         movdqu  0x50($inp), @XMM[5]
1150         je      .Lecb_enc_six
1151         movdqu  0x60($inp), @XMM[6]
1152         call    _bsaes_encrypt8
1153         movdqu  @XMM[0], 0x00($out)     # write output
1154         movdqu  @XMM[1], 0x10($out)
1155         movdqu  @XMM[4], 0x20($out)
1156         movdqu  @XMM[6], 0x30($out)
1157         movdqu  @XMM[3], 0x40($out)
1158         movdqu  @XMM[7], 0x50($out)
1159         movdqu  @XMM[2], 0x60($out)
1160         jmp     .Lecb_enc_done
1161 .align  16
1162 .Lecb_enc_six:
1163         call    _bsaes_encrypt8
1164         movdqu  @XMM[0], 0x00($out)     # write output
1165         movdqu  @XMM[1], 0x10($out)
1166         movdqu  @XMM[4], 0x20($out)
1167         movdqu  @XMM[6], 0x30($out)
1168         movdqu  @XMM[3], 0x40($out)
1169         movdqu  @XMM[7], 0x50($out)
1170         jmp     .Lecb_enc_done
1171 .align  16
1172 .Lecb_enc_five:
1173         call    _bsaes_encrypt8
1174         movdqu  @XMM[0], 0x00($out)     # write output
1175         movdqu  @XMM[1], 0x10($out)
1176         movdqu  @XMM[4], 0x20($out)
1177         movdqu  @XMM[6], 0x30($out)
1178         movdqu  @XMM[3], 0x40($out)
1179         jmp     .Lecb_enc_done
1180 .align  16
1181 .Lecb_enc_four:
1182         call    _bsaes_encrypt8
1183         movdqu  @XMM[0], 0x00($out)     # write output
1184         movdqu  @XMM[1], 0x10($out)
1185         movdqu  @XMM[4], 0x20($out)
1186         movdqu  @XMM[6], 0x30($out)
1187         jmp     .Lecb_enc_done
1188 .align  16
1189 .Lecb_enc_three:
1190         call    _bsaes_encrypt8
1191         movdqu  @XMM[0], 0x00($out)     # write output
1192         movdqu  @XMM[1], 0x10($out)
1193         movdqu  @XMM[4], 0x20($out)
1194         jmp     .Lecb_enc_done
1195 .align  16
1196 .Lecb_enc_two:
1197         call    _bsaes_encrypt8
1198         movdqu  @XMM[0], 0x00($out)     # write output
1199         movdqu  @XMM[1], 0x10($out)
1200         jmp     .Lecb_enc_done
1201 .align  16
1202 .Lecb_enc_one:
1203         call    _bsaes_encrypt8
1204         movdqu  @XMM[0], 0x00($out)     # write output
1205         jmp     .Lecb_enc_done
1206 .align  16
1207 .Lecb_enc_short:
1208         lea     ($inp), $arg1
1209         lea     ($out), $arg2
1210         lea     ($key), $arg3
1211         call    AES_encrypt
1212         lea     16($inp), $inp
1213         lea     16($out), $out
1214         dec     $len
1215         jnz     .Lecb_enc_short
1216
1217 .Lecb_enc_done:
1218         lea     (%rsp),%rax
1219         pxor    %xmm0, %xmm0
1220 .Lecb_enc_bzero:                        # wipe key schedule [if any]
1221         movdqa  %xmm0, 0x00(%rax)
1222         movdqa  %xmm0, 0x10(%rax)
1223         lea     0x20(%rax), %rax
1224         cmp     %rax, %rbp
1225         jb      .Lecb_enc_bzero
1226
1227         lea     (%rbp),%rsp             # restore %rsp
1228 ___
1229 $code.=<<___ if ($win64);
1230         movaps  0x40(%rbp), %xmm6
1231         movaps  0x50(%rbp), %xmm7
1232         movaps  0x60(%rbp), %xmm8
1233         movaps  0x70(%rbp), %xmm9
1234         movaps  0x80(%rbp), %xmm10
1235         movaps  0x90(%rbp), %xmm11
1236         movaps  0xa0(%rbp), %xmm12
1237         movaps  0xb0(%rbp), %xmm13
1238         movaps  0xc0(%rbp), %xmm14
1239         movaps  0xd0(%rbp), %xmm15
1240         lea     0xa0(%rbp), %rsp
1241 ___
1242 $code.=<<___;
1243         mov     0x48(%rsp), %r15
1244         mov     0x50(%rsp), %r14
1245         mov     0x58(%rsp), %r13
1246         mov     0x60(%rsp), %r12
1247         mov     0x68(%rsp), %rbx
1248         mov     0x70(%rsp), %rbp
1249         lea     0x78(%rsp), %rsp
1250 .Lecb_enc_epilogue:
1251         ret
1252 .size   bsaes_ecb_encrypt_blocks,.-bsaes_ecb_encrypt_blocks
1253
1254 .globl  bsaes_ecb_decrypt_blocks
1255 .type   bsaes_ecb_decrypt_blocks,\@abi-omnipotent
1256 .align  16
1257 bsaes_ecb_decrypt_blocks:
1258         push    %rbp
1259         push    %rbx
1260         push    %r12
1261         push    %r13
1262         push    %r14
1263         push    %r15
1264         lea     -0x48(%rsp),%rsp
1265 ___
1266 $code.=<<___ if ($win64);
1267         lea     -0xa0(%rsp), %rsp
1268         movaps  %xmm6, 0x40(%rsp)
1269         movaps  %xmm7, 0x50(%rsp)
1270         movaps  %xmm8, 0x60(%rsp)
1271         movaps  %xmm9, 0x70(%rsp)
1272         movaps  %xmm10, 0x80(%rsp)
1273         movaps  %xmm11, 0x90(%rsp)
1274         movaps  %xmm12, 0xa0(%rsp)
1275         movaps  %xmm13, 0xb0(%rsp)
1276         movaps  %xmm14, 0xc0(%rsp)
1277         movaps  %xmm15, 0xd0(%rsp)
1278 .Lecb_dec_body:
1279 ___
1280 $code.=<<___;
1281         mov     %rsp,%rbp               # backup %rsp
1282         mov     240($arg4),%eax         # rounds
1283         mov     $arg1,$inp              # backup arguments
1284         mov     $arg2,$out
1285         mov     $arg3,$len
1286         mov     $arg4,$key
1287         cmp     \$8,$arg3
1288         jb      .Lecb_dec_short
1289
1290         mov     %eax,%ebx               # backup rounds
1291         shl     \$7,%rax                # 128 bytes per inner round key
1292         sub     \$`128-32`,%rax         # size of bit-sliced key schedule
1293         sub     %rax,%rsp
1294         mov     %rsp,%rax               # pass key schedule
1295         mov     $key,%rcx               # pass key
1296         mov     %ebx,%r10d              # pass rounds
1297         call    _bsaes_key_convert
1298         pxor    (%rsp),%xmm7            # fix up 0 round key
1299         movdqa  %xmm6,(%rax)            # save last round key
1300         movdqa  %xmm7,(%rsp)
1301
1302         sub     \$8,$len
1303 .Lecb_dec_loop:
1304         movdqu  0x00($inp), @XMM[0]     # load input
1305         movdqu  0x10($inp), @XMM[1]
1306         movdqu  0x20($inp), @XMM[2]
1307         movdqu  0x30($inp), @XMM[3]
1308         movdqu  0x40($inp), @XMM[4]
1309         movdqu  0x50($inp), @XMM[5]
1310         mov     %rsp, %rax              # pass key schedule
1311         movdqu  0x60($inp), @XMM[6]
1312         mov     %ebx,%r10d              # pass rounds
1313         movdqu  0x70($inp), @XMM[7]
1314         lea     0x80($inp), $inp
1315
1316         call    _bsaes_decrypt8
1317
1318         movdqu  @XMM[0], 0x00($out)     # write output
1319         movdqu  @XMM[1], 0x10($out)
1320         movdqu  @XMM[6], 0x20($out)
1321         movdqu  @XMM[4], 0x30($out)
1322         movdqu  @XMM[2], 0x40($out)
1323         movdqu  @XMM[7], 0x50($out)
1324         movdqu  @XMM[3], 0x60($out)
1325         movdqu  @XMM[5], 0x70($out)
1326         lea     0x80($out), $out
1327         sub     \$8,$len
1328         jnc     .Lecb_dec_loop
1329
1330         add     \$8,$len
1331         jz      .Lecb_dec_done
1332
1333         movdqu  0x00($inp), @XMM[0]     # load input
1334         mov     %rsp, %rax              # pass key schedule
1335         mov     %ebx,%r10d              # pass rounds
1336         cmp     \$2,$len
1337         jb      .Lecb_dec_one
1338         movdqu  0x10($inp), @XMM[1]
1339         je      .Lecb_dec_two
1340         movdqu  0x20($inp), @XMM[2]
1341         cmp     \$4,$len
1342         jb      .Lecb_dec_three
1343         movdqu  0x30($inp), @XMM[3]
1344         je      .Lecb_dec_four
1345         movdqu  0x40($inp), @XMM[4]
1346         cmp     \$6,$len
1347         jb      .Lecb_dec_five
1348         movdqu  0x50($inp), @XMM[5]
1349         je      .Lecb_dec_six
1350         movdqu  0x60($inp), @XMM[6]
1351         call    _bsaes_decrypt8
1352         movdqu  @XMM[0], 0x00($out)     # write output
1353         movdqu  @XMM[1], 0x10($out)
1354         movdqu  @XMM[6], 0x20($out)
1355         movdqu  @XMM[4], 0x30($out)
1356         movdqu  @XMM[2], 0x40($out)
1357         movdqu  @XMM[7], 0x50($out)
1358         movdqu  @XMM[3], 0x60($out)
1359         jmp     .Lecb_dec_done
1360 .align  16
1361 .Lecb_dec_six:
1362         call    _bsaes_decrypt8
1363         movdqu  @XMM[0], 0x00($out)     # write output
1364         movdqu  @XMM[1], 0x10($out)
1365         movdqu  @XMM[6], 0x20($out)
1366         movdqu  @XMM[4], 0x30($out)
1367         movdqu  @XMM[2], 0x40($out)
1368         movdqu  @XMM[7], 0x50($out)
1369         jmp     .Lecb_dec_done
1370 .align  16
1371 .Lecb_dec_five:
1372         call    _bsaes_decrypt8
1373         movdqu  @XMM[0], 0x00($out)     # write output
1374         movdqu  @XMM[1], 0x10($out)
1375         movdqu  @XMM[6], 0x20($out)
1376         movdqu  @XMM[4], 0x30($out)
1377         movdqu  @XMM[2], 0x40($out)
1378         jmp     .Lecb_dec_done
1379 .align  16
1380 .Lecb_dec_four:
1381         call    _bsaes_decrypt8
1382         movdqu  @XMM[0], 0x00($out)     # write output
1383         movdqu  @XMM[1], 0x10($out)
1384         movdqu  @XMM[6], 0x20($out)
1385         movdqu  @XMM[4], 0x30($out)
1386         jmp     .Lecb_dec_done
1387 .align  16
1388 .Lecb_dec_three:
1389         call    _bsaes_decrypt8
1390         movdqu  @XMM[0], 0x00($out)     # write output
1391         movdqu  @XMM[1], 0x10($out)
1392         movdqu  @XMM[6], 0x20($out)
1393         jmp     .Lecb_dec_done
1394 .align  16
1395 .Lecb_dec_two:
1396         call    _bsaes_decrypt8
1397         movdqu  @XMM[0], 0x00($out)     # write output
1398         movdqu  @XMM[1], 0x10($out)
1399         jmp     .Lecb_dec_done
1400 .align  16
1401 .Lecb_dec_one:
1402         call    _bsaes_decrypt8
1403         movdqu  @XMM[0], 0x00($out)     # write output
1404         jmp     .Lecb_dec_done
1405 .align  16
1406 .Lecb_dec_short:
1407         lea     ($inp), $arg1
1408         lea     ($out), $arg2
1409         lea     ($key), $arg3
1410         call    AES_decrypt
1411         lea     16($inp), $inp
1412         lea     16($out), $out
1413         dec     $len
1414         jnz     .Lecb_dec_short
1415
1416 .Lecb_dec_done:
1417         lea     (%rsp),%rax
1418         pxor    %xmm0, %xmm0
1419 .Lecb_dec_bzero:                        # wipe key schedule [if any]
1420         movdqa  %xmm0, 0x00(%rax)
1421         movdqa  %xmm0, 0x10(%rax)
1422         lea     0x20(%rax), %rax
1423         cmp     %rax, %rbp
1424         jb      .Lecb_dec_bzero
1425
1426         lea     (%rbp),%rsp             # restore %rsp
1427 ___
1428 $code.=<<___ if ($win64);
1429         movaps  0x40(%rbp), %xmm6
1430         movaps  0x50(%rbp), %xmm7
1431         movaps  0x60(%rbp), %xmm8
1432         movaps  0x70(%rbp), %xmm9
1433         movaps  0x80(%rbp), %xmm10
1434         movaps  0x90(%rbp), %xmm11
1435         movaps  0xa0(%rbp), %xmm12
1436         movaps  0xb0(%rbp), %xmm13
1437         movaps  0xc0(%rbp), %xmm14
1438         movaps  0xd0(%rbp), %xmm15
1439         lea     0xa0(%rbp), %rsp
1440 ___
1441 $code.=<<___;
1442         mov     0x48(%rsp), %r15
1443         mov     0x50(%rsp), %r14
1444         mov     0x58(%rsp), %r13
1445         mov     0x60(%rsp), %r12
1446         mov     0x68(%rsp), %rbx
1447         mov     0x70(%rsp), %rbp
1448         lea     0x78(%rsp), %rsp
1449 .Lecb_dec_epilogue:
1450         ret
1451 .size   bsaes_ecb_decrypt_blocks,.-bsaes_ecb_decrypt_blocks
1452 ___
1453 }
1454 $code.=<<___;
1455 .extern AES_cbc_encrypt
1456 .globl  bsaes_cbc_encrypt
1457 .type   bsaes_cbc_encrypt,\@abi-omnipotent
1458 .align  16
1459 bsaes_cbc_encrypt:
1460 ___
1461 $code.=<<___ if ($win64);
1462         mov     48(%rsp),$arg6          # pull direction flag
1463 ___
1464 $code.=<<___;
1465         cmp     \$0,$arg6
1466         jne     AES_cbc_encrypt
1467         cmp     \$128,$arg3
1468         jb      AES_cbc_encrypt
1469
1470         push    %rbp
1471         push    %rbx
1472         push    %r12
1473         push    %r13
1474         push    %r14
1475         push    %r15
1476         lea     -0x48(%rsp), %rsp
1477 ___
1478 $code.=<<___ if ($win64);
1479         mov     0xa0(%rsp),$arg5        # pull ivp
1480         lea     -0xa0(%rsp), %rsp
1481         movaps  %xmm6, 0x40(%rsp)
1482         movaps  %xmm7, 0x50(%rsp)
1483         movaps  %xmm8, 0x60(%rsp)
1484         movaps  %xmm9, 0x70(%rsp)
1485         movaps  %xmm10, 0x80(%rsp)
1486         movaps  %xmm11, 0x90(%rsp)
1487         movaps  %xmm12, 0xa0(%rsp)
1488         movaps  %xmm13, 0xb0(%rsp)
1489         movaps  %xmm14, 0xc0(%rsp)
1490         movaps  %xmm15, 0xd0(%rsp)
1491 .Lcbc_dec_body:
1492 ___
1493 $code.=<<___;
1494         mov     %rsp, %rbp              # backup %rsp
1495         mov     240($arg4), %eax        # rounds
1496         mov     $arg1, $inp             # backup arguments
1497         mov     $arg2, $out
1498         mov     $arg3, $len
1499         mov     $arg4, $key
1500         mov     $arg5, %rdx
1501         shr     \$4, $len               # bytes to blocks
1502
1503         mov     %eax, %ebx              # rounds
1504         shl     \$7, %rax               # 128 bytes per inner round key
1505         sub     \$`128-32`, %rax        # size of bit-sliced key schedule
1506         sub     %rax, %rsp
1507
1508         mov     %rsp, %rax              # pass key schedule
1509         mov     $key, %rcx              # pass key
1510         mov     %ebx, %r10d             # pass rounds
1511         call    _bsaes_key_convert
1512         pxor    (%rsp),%xmm7            # fix up 0 round key
1513         movdqa  %xmm6,(%rax)            # save last round key
1514         movdqa  %xmm7,(%rsp)
1515
1516         movdqu  (%rdx), @XMM[15]        # load IV
1517         sub     \$8,$len
1518 .Lcbc_dec_loop:
1519         movdqu  0x00($inp), @XMM[0]     # load input
1520         movdqu  0x10($inp), @XMM[1]
1521         movdqu  0x20($inp), @XMM[2]
1522         movdqu  0x30($inp), @XMM[3]
1523         movdqu  0x40($inp), @XMM[4]
1524         movdqu  0x50($inp), @XMM[5]
1525         mov     %rsp, %rax              # pass key schedule
1526         movdqu  0x60($inp), @XMM[6]
1527         mov     %ebx,%r10d              # pass rounds
1528         movdqu  0x70($inp), @XMM[7]
1529         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1530
1531         call    _bsaes_decrypt8
1532
1533         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1534         movdqu  0x00($inp), @XMM[8]     # re-load input
1535         movdqu  0x10($inp), @XMM[9]
1536         pxor    @XMM[8], @XMM[1]
1537         movdqu  0x20($inp), @XMM[10]
1538         pxor    @XMM[9], @XMM[6]
1539         movdqu  0x30($inp), @XMM[11]
1540         pxor    @XMM[10], @XMM[4]
1541         movdqu  0x40($inp), @XMM[12]
1542         pxor    @XMM[11], @XMM[2]
1543         movdqu  0x50($inp), @XMM[13]
1544         pxor    @XMM[12], @XMM[7]
1545         movdqu  0x60($inp), @XMM[14]
1546         pxor    @XMM[13], @XMM[3]
1547         movdqu  0x70($inp), @XMM[15]    # IV
1548         pxor    @XMM[14], @XMM[5]
1549         movdqu  @XMM[0], 0x00($out)     # write output
1550         lea     0x80($inp), $inp
1551         movdqu  @XMM[1], 0x10($out)
1552         movdqu  @XMM[6], 0x20($out)
1553         movdqu  @XMM[4], 0x30($out)
1554         movdqu  @XMM[2], 0x40($out)
1555         movdqu  @XMM[7], 0x50($out)
1556         movdqu  @XMM[3], 0x60($out)
1557         movdqu  @XMM[5], 0x70($out)
1558         lea     0x80($out), $out
1559         sub     \$8,$len
1560         jnc     .Lcbc_dec_loop
1561
1562         add     \$8,$len
1563         jz      .Lcbc_dec_done
1564
1565         movdqu  0x00($inp), @XMM[0]     # load input
1566         mov     %rsp, %rax              # pass key schedule
1567         mov     %ebx, %r10d             # pass rounds
1568         cmp     \$2,$len
1569         jb      .Lcbc_dec_one
1570         movdqu  0x10($inp), @XMM[1]
1571         je      .Lcbc_dec_two
1572         movdqu  0x20($inp), @XMM[2]
1573         cmp     \$4,$len
1574         jb      .Lcbc_dec_three
1575         movdqu  0x30($inp), @XMM[3]
1576         je      .Lcbc_dec_four
1577         movdqu  0x40($inp), @XMM[4]
1578         cmp     \$6,$len
1579         jb      .Lcbc_dec_five
1580         movdqu  0x50($inp), @XMM[5]
1581         je      .Lcbc_dec_six
1582         movdqu  0x60($inp), @XMM[6]
1583         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1584         call    _bsaes_decrypt8
1585         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1586         movdqu  0x00($inp), @XMM[8]     # re-load input
1587         movdqu  0x10($inp), @XMM[9]
1588         pxor    @XMM[8], @XMM[1]
1589         movdqu  0x20($inp), @XMM[10]
1590         pxor    @XMM[9], @XMM[6]
1591         movdqu  0x30($inp), @XMM[11]
1592         pxor    @XMM[10], @XMM[4]
1593         movdqu  0x40($inp), @XMM[12]
1594         pxor    @XMM[11], @XMM[2]
1595         movdqu  0x50($inp), @XMM[13]
1596         pxor    @XMM[12], @XMM[7]
1597         movdqu  0x60($inp), @XMM[15]    # IV
1598         pxor    @XMM[13], @XMM[3]
1599         movdqu  @XMM[0], 0x00($out)     # write output
1600         movdqu  @XMM[1], 0x10($out)
1601         movdqu  @XMM[6], 0x20($out)
1602         movdqu  @XMM[4], 0x30($out)
1603         movdqu  @XMM[2], 0x40($out)
1604         movdqu  @XMM[7], 0x50($out)
1605         movdqu  @XMM[3], 0x60($out)
1606         jmp     .Lcbc_dec_done
1607 .align  16
1608 .Lcbc_dec_six:
1609         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1610         call    _bsaes_decrypt8
1611         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1612         movdqu  0x00($inp), @XMM[8]     # re-load input
1613         movdqu  0x10($inp), @XMM[9]
1614         pxor    @XMM[8], @XMM[1]
1615         movdqu  0x20($inp), @XMM[10]
1616         pxor    @XMM[9], @XMM[6]
1617         movdqu  0x30($inp), @XMM[11]
1618         pxor    @XMM[10], @XMM[4]
1619         movdqu  0x40($inp), @XMM[12]
1620         pxor    @XMM[11], @XMM[2]
1621         movdqu  0x50($inp), @XMM[15]    # IV
1622         pxor    @XMM[12], @XMM[7]
1623         movdqu  @XMM[0], 0x00($out)     # write output
1624         movdqu  @XMM[1], 0x10($out)
1625         movdqu  @XMM[6], 0x20($out)
1626         movdqu  @XMM[4], 0x30($out)
1627         movdqu  @XMM[2], 0x40($out)
1628         movdqu  @XMM[7], 0x50($out)
1629         jmp     .Lcbc_dec_done
1630 .align  16
1631 .Lcbc_dec_five:
1632         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1633         call    _bsaes_decrypt8
1634         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1635         movdqu  0x00($inp), @XMM[8]     # re-load input
1636         movdqu  0x10($inp), @XMM[9]
1637         pxor    @XMM[8], @XMM[1]
1638         movdqu  0x20($inp), @XMM[10]
1639         pxor    @XMM[9], @XMM[6]
1640         movdqu  0x30($inp), @XMM[11]
1641         pxor    @XMM[10], @XMM[4]
1642         movdqu  0x40($inp), @XMM[15]    # IV
1643         pxor    @XMM[11], @XMM[2]
1644         movdqu  @XMM[0], 0x00($out)     # write output
1645         movdqu  @XMM[1], 0x10($out)
1646         movdqu  @XMM[6], 0x20($out)
1647         movdqu  @XMM[4], 0x30($out)
1648         movdqu  @XMM[2], 0x40($out)
1649         jmp     .Lcbc_dec_done
1650 .align  16
1651 .Lcbc_dec_four:
1652         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1653         call    _bsaes_decrypt8
1654         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1655         movdqu  0x00($inp), @XMM[8]     # re-load input
1656         movdqu  0x10($inp), @XMM[9]
1657         pxor    @XMM[8], @XMM[1]
1658         movdqu  0x20($inp), @XMM[10]
1659         pxor    @XMM[9], @XMM[6]
1660         movdqu  0x30($inp), @XMM[15]    # IV
1661         pxor    @XMM[10], @XMM[4]
1662         movdqu  @XMM[0], 0x00($out)     # write output
1663         movdqu  @XMM[1], 0x10($out)
1664         movdqu  @XMM[6], 0x20($out)
1665         movdqu  @XMM[4], 0x30($out)
1666         jmp     .Lcbc_dec_done
1667 .align  16
1668 .Lcbc_dec_three:
1669         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1670         call    _bsaes_decrypt8
1671         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1672         movdqu  0x00($inp), @XMM[8]     # re-load input
1673         movdqu  0x10($inp), @XMM[9]
1674         pxor    @XMM[8], @XMM[1]
1675         movdqu  0x20($inp), @XMM[15]    # IV
1676         pxor    @XMM[9], @XMM[6]
1677         movdqu  @XMM[0], 0x00($out)     # write output
1678         movdqu  @XMM[1], 0x10($out)
1679         movdqu  @XMM[6], 0x20($out)
1680         jmp     .Lcbc_dec_done
1681 .align  16
1682 .Lcbc_dec_two:
1683         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1684         call    _bsaes_decrypt8
1685         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1686         movdqu  0x00($inp), @XMM[8]     # re-load input
1687         movdqu  0x10($inp), @XMM[15]    # IV
1688         pxor    @XMM[8], @XMM[1]
1689         movdqu  @XMM[0], 0x00($out)     # write output
1690         movdqu  @XMM[1], 0x10($out)
1691         jmp     .Lcbc_dec_done
1692 .align  16
1693 .Lcbc_dec_one:
1694         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1695         call    _bsaes_decrypt8
1696         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1697         movdqu  0x00($inp), @XMM[15]    # IV
1698         movdqu  @XMM[0], 0x00($out)     # write output
1699
1700 .Lcbc_dec_done:
1701         movdqu  @XMM[15], (%rdx)        # return IV
1702         lea     (%rsp), %rax
1703         pxor    %xmm0, %xmm0
1704 .Lcbc_dec_bzero:                        # wipe key schedule [if any]
1705         movdqa  %xmm0, 0x00(%rax)
1706         movdqa  %xmm0, 0x10(%rax)
1707         lea     0x20(%rax), %rax
1708         cmp     %rax, %rbp
1709         ja      .Lcbc_dec_bzero
1710
1711         lea     (%rbp),%rsp             # restore %rsp
1712 ___
1713 $code.=<<___ if ($win64);
1714         movaps  0x40(%rbp), %xmm6
1715         movaps  0x50(%rbp), %xmm7
1716         movaps  0x60(%rbp), %xmm8
1717         movaps  0x70(%rbp), %xmm9
1718         movaps  0x80(%rbp), %xmm10
1719         movaps  0x90(%rbp), %xmm11
1720         movaps  0xa0(%rbp), %xmm12
1721         movaps  0xb0(%rbp), %xmm13
1722         movaps  0xc0(%rbp), %xmm14
1723         movaps  0xd0(%rbp), %xmm15
1724         lea     0xa0(%rbp), %rsp
1725 ___
1726 $code.=<<___;
1727         mov     0x48(%rsp), %r15
1728         mov     0x50(%rsp), %r14
1729         mov     0x58(%rsp), %r13
1730         mov     0x60(%rsp), %r12
1731         mov     0x68(%rsp), %rbx
1732         mov     0x70(%rsp), %rbp
1733         lea     0x78(%rsp), %rsp
1734 .Lcbc_dec_epilogue:
1735         ret
1736 .size   bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
1737
1738 .globl  bsaes_ctr32_encrypt_blocks
1739 .type   bsaes_ctr32_encrypt_blocks,\@abi-omnipotent
1740 .align  16
1741 bsaes_ctr32_encrypt_blocks:
1742         push    %rbp
1743         push    %rbx
1744         push    %r12
1745         push    %r13
1746         push    %r14
1747         push    %r15
1748         lea     -0x48(%rsp), %rsp
1749 ___
1750 $code.=<<___ if ($win64);
1751         mov     0xa0(%rsp),$arg5        # pull ivp
1752         lea     -0xa0(%rsp), %rsp
1753         movaps  %xmm6, 0x40(%rsp)
1754         movaps  %xmm7, 0x50(%rsp)
1755         movaps  %xmm8, 0x60(%rsp)
1756         movaps  %xmm9, 0x70(%rsp)
1757         movaps  %xmm10, 0x80(%rsp)
1758         movaps  %xmm11, 0x90(%rsp)
1759         movaps  %xmm12, 0xa0(%rsp)
1760         movaps  %xmm13, 0xb0(%rsp)
1761         movaps  %xmm14, 0xc0(%rsp)
1762         movaps  %xmm15, 0xd0(%rsp)
1763 .Lctr_enc_body:
1764 ___
1765 $code.=<<___;
1766         mov     %rsp, %rbp              # backup %rsp
1767         movdqu  ($arg5), %xmm0          # load counter
1768         mov     240($arg4), %eax        # rounds
1769         mov     $arg1, $inp             # backup arguments
1770         mov     $arg2, $out
1771         mov     $arg3, $len
1772         mov     $arg4, $key
1773         movdqa  %xmm0, 0x20(%rbp)       # copy counter
1774         cmp     \$8, $arg3
1775         jb      .Lctr_enc_short
1776
1777         mov     %eax, %ebx              # rounds
1778         shl     \$7, %rax               # 128 bytes per inner round key
1779         sub     \$`128-32`, %rax        # size of bit-sliced key schedule
1780         sub     %rax, %rsp
1781
1782         mov     %rsp, %rax              # pass key schedule
1783         mov     $key, %rcx              # pass key
1784         mov     %ebx, %r10d             # pass rounds
1785         call    _bsaes_key_convert
1786         pxor    %xmm6,%xmm7             # fix up last round key
1787         movdqa  %xmm7,(%rax)            # save last round key
1788
1789         movdqa  (%rsp), @XMM[9]         # load round0 key
1790         lea     .LADD1(%rip), %r11
1791         movdqa  0x20(%rbp), @XMM[0]     # counter copy
1792         movdqa  -0x20(%r11), @XMM[8]    # .LSWPUP
1793         pshufb  @XMM[8], @XMM[9]        # byte swap upper part
1794         pshufb  @XMM[8], @XMM[0]
1795         movdqa  @XMM[9], (%rsp)         # save adjusted round0 key
1796         jmp     .Lctr_enc_loop
1797 .align  16
1798 .Lctr_enc_loop:
1799         movdqa  @XMM[0], 0x20(%rbp)     # save counter
1800         movdqa  @XMM[0], @XMM[1]        # prepare 8 counter values
1801         movdqa  @XMM[0], @XMM[2]
1802         paddd   0x00(%r11), @XMM[1]     # .LADD1
1803         movdqa  @XMM[0], @XMM[3]
1804         paddd   0x10(%r11), @XMM[2]     # .LADD2
1805         movdqa  @XMM[0], @XMM[4]
1806         paddd   0x20(%r11), @XMM[3]     # .LADD3
1807         movdqa  @XMM[0], @XMM[5]
1808         paddd   0x30(%r11), @XMM[4]     # .LADD4
1809         movdqa  @XMM[0], @XMM[6]
1810         paddd   0x40(%r11), @XMM[5]     # .LADD5
1811         movdqa  @XMM[0], @XMM[7]
1812         paddd   0x50(%r11), @XMM[6]     # .LADD6
1813         paddd   0x60(%r11), @XMM[7]     # .LADD7
1814
1815         # Borrow prologue from _bsaes_encrypt8 to use the opportunity
1816         # to flip byte order in 32-bit counter
1817         movdqa  (%rsp), @XMM[9]         # round 0 key
1818         lea     0x10(%rsp), %rax        # pass key schedule
1819         movdqa  -0x10(%r11), @XMM[8]    # .LSWPUPM0SR
1820         pxor    @XMM[9], @XMM[0]        # xor with round0 key
1821         pxor    @XMM[9], @XMM[1]
1822          pshufb @XMM[8], @XMM[0]
1823         pxor    @XMM[9], @XMM[2]
1824          pshufb @XMM[8], @XMM[1]
1825         pxor    @XMM[9], @XMM[3]
1826          pshufb @XMM[8], @XMM[2]
1827         pxor    @XMM[9], @XMM[4]
1828          pshufb @XMM[8], @XMM[3]
1829         pxor    @XMM[9], @XMM[5]
1830          pshufb @XMM[8], @XMM[4]
1831         pxor    @XMM[9], @XMM[6]
1832          pshufb @XMM[8], @XMM[5]
1833         pxor    @XMM[9], @XMM[7]
1834          pshufb @XMM[8], @XMM[6]
1835         lea     .LBS0(%rip), %r11       # constants table
1836          pshufb @XMM[8], @XMM[7]
1837         mov     %ebx,%r10d              # pass rounds
1838
1839         call    _bsaes_encrypt8_bitslice
1840
1841         sub     \$8,$len
1842         jc      .Lctr_enc_loop_done
1843
1844         movdqu  0x00($inp), @XMM[8]     # load input
1845         movdqu  0x10($inp), @XMM[9]
1846         movdqu  0x20($inp), @XMM[10]
1847         movdqu  0x30($inp), @XMM[11]
1848         movdqu  0x40($inp), @XMM[12]
1849         movdqu  0x50($inp), @XMM[13]
1850         movdqu  0x60($inp), @XMM[14]
1851         movdqu  0x70($inp), @XMM[15]
1852         lea     0x80($inp),$inp
1853         pxor    @XMM[0], @XMM[8]
1854         movdqa  0x20(%rbp), @XMM[0]     # load counter
1855         pxor    @XMM[9], @XMM[1]
1856         movdqu  @XMM[8], 0x00($out)     # write output
1857         pxor    @XMM[10], @XMM[4]
1858         movdqu  @XMM[1], 0x10($out)
1859         pxor    @XMM[11], @XMM[6]
1860         movdqu  @XMM[4], 0x20($out)
1861         pxor    @XMM[12], @XMM[3]
1862         movdqu  @XMM[6], 0x30($out)
1863         pxor    @XMM[13], @XMM[7]
1864         movdqu  @XMM[3], 0x40($out)
1865         pxor    @XMM[14], @XMM[2]
1866         movdqu  @XMM[7], 0x50($out)
1867         pxor    @XMM[15], @XMM[5]
1868         movdqu  @XMM[2], 0x60($out)
1869         lea     .LADD1(%rip), %r11
1870         movdqu  @XMM[5], 0x70($out)
1871         lea     0x80($out), $out
1872         paddd   0x70(%r11), @XMM[0]     # .LADD8
1873         jnz     .Lctr_enc_loop
1874
1875         jmp     .Lctr_enc_done
1876 .align  16
1877 .Lctr_enc_loop_done:
1878         movdqu  0x00($inp), @XMM[8]     # load input
1879         pxor    @XMM[8], @XMM[0]
1880         movdqu  @XMM[0], 0x00($out)     # write output
1881         cmp     \$2,$len
1882         jb      .Lctr_enc_done
1883         movdqu  0x10($inp), @XMM[9]
1884         pxor    @XMM[9], @XMM[1]
1885         movdqu  @XMM[1], 0x10($out)
1886         je      .Lctr_enc_done
1887         movdqu  0x20($inp), @XMM[10]
1888         pxor    @XMM[10], @XMM[4]
1889         movdqu  @XMM[4], 0x20($out)
1890         cmp     \$4,$len
1891         jb      .Lctr_enc_done
1892         movdqu  0x30($inp), @XMM[11]
1893         pxor    @XMM[11], @XMM[6]
1894         movdqu  @XMM[6], 0x30($out)
1895         je      .Lctr_enc_done
1896         movdqu  0x40($inp), @XMM[12]
1897         pxor    @XMM[12], @XMM[3]
1898         movdqu  @XMM[3], 0x40($out)
1899         cmp     \$6,$len
1900         jb      .Lctr_enc_done
1901         movdqu  0x50($inp), @XMM[13]
1902         pxor    @XMM[13], @XMM[7]
1903         movdqu  @XMM[7], 0x50($out)
1904         je      .Lctr_enc_done
1905         movdqu  0x60($inp), @XMM[14]
1906         pxor    @XMM[14], @XMM[2]
1907         movdqu  @XMM[2], 0x60($out)
1908         jmp     .Lctr_enc_done
1909
1910 .align  16
1911 .Lctr_enc_short:
1912         lea     0x20(%rbp), $arg1
1913         lea     0x30(%rbp), $arg2
1914         lea     ($key), $arg3
1915         call    AES_encrypt
1916         movdqu  ($inp), @XMM[1]
1917         lea     16($inp), $inp
1918         mov     0x2c(%rbp), %eax        # load 32-bit counter
1919         bswap   %eax
1920         pxor    0x30(%rbp), @XMM[1]
1921         inc     %eax                    # increment
1922         movdqu  @XMM[1], ($out)
1923         bswap   %eax
1924         lea     16($out), $out
1925         mov     %eax, 0x2c(%rsp)        # save 32-bit counter
1926         dec     $len
1927         jnz     .Lctr_enc_short
1928
1929 .Lctr_enc_done:
1930         lea     (%rsp), %rax
1931         pxor    %xmm0, %xmm0
1932 .Lctr_enc_bzero:                        # wipe key schedule [if any]
1933         movdqa  %xmm0, 0x00(%rax)
1934         movdqa  %xmm0, 0x10(%rax)
1935         lea     0x20(%rax), %rax
1936         cmp     %rax, %rbp
1937         ja      .Lctr_enc_bzero
1938
1939         lea     (%rbp),%rsp             # restore %rsp
1940 ___
1941 $code.=<<___ if ($win64);
1942         movaps  0x40(%rbp), %xmm6
1943         movaps  0x50(%rbp), %xmm7
1944         movaps  0x60(%rbp), %xmm8
1945         movaps  0x70(%rbp), %xmm9
1946         movaps  0x80(%rbp), %xmm10
1947         movaps  0x90(%rbp), %xmm11
1948         movaps  0xa0(%rbp), %xmm12
1949         movaps  0xb0(%rbp), %xmm13
1950         movaps  0xc0(%rbp), %xmm14
1951         movaps  0xd0(%rbp), %xmm15
1952         lea     0xa0(%rbp), %rsp
1953 ___
1954 $code.=<<___;
1955         mov     0x48(%rsp), %r15
1956         mov     0x50(%rsp), %r14
1957         mov     0x58(%rsp), %r13
1958         mov     0x60(%rsp), %r12
1959         mov     0x68(%rsp), %rbx
1960         mov     0x70(%rsp), %rbp
1961         lea     0x78(%rsp), %rsp
1962 .Lctr_enc_epilogue:
1963         ret
1964 .size   bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
1965 ___
1966 }
1967 $code.=<<___;
1968 .type   _bsaes_const,\@object
1969 .align  64
1970 _bsaes_const:
1971 .LM0ISR:        # InvShiftRows constants
1972         .quad   0x0a0e0206070b0f03, 0x0004080c0d010509
1973 .LISRM0:
1974         .quad   0x01040b0e0205080f, 0x0306090c00070a0d
1975 .LISR:
1976         .quad   0x0504070602010003, 0x0f0e0d0c080b0a09
1977 .LBS0:          # bit-slice constants
1978         .quad   0x5555555555555555, 0x5555555555555555
1979 .LBS1:
1980         .quad   0x3333333333333333, 0x3333333333333333
1981 .LBS2:
1982         .quad   0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f
1983 .LSR:           # shiftrows constants
1984         .quad   0x0504070600030201, 0x0f0e0d0c0a09080b
1985 .LSRM0:
1986         .quad   0x0304090e00050a0f, 0x01060b0c0207080d
1987 .LM0:
1988         .quad   0x02060a0e03070b0f, 0x0004080c0105090d
1989 .LM0SR:
1990         .quad   0x0a0e02060f03070b, 0x0004080c05090d01
1991 .LNOT:          # magic constants
1992         .quad   0xffffffffffffffff, 0xffffffffffffffff
1993 .L63:
1994         .quad   0x6363636363636363, 0x6363636363636363
1995 .LSWPUP:        # byte-swap upper dword
1996         .quad   0x0706050403020100, 0x0c0d0e0f0b0a0908
1997 .LSWPUPM0SR:
1998         .quad   0x0a0d02060c03070b, 0x0004080f05090e01
1999 .LADD1:         # counter increment constants
2000         .quad   0x0000000000000000, 0x0000000100000000
2001 .LADD2:
2002         .quad   0x0000000000000000, 0x0000000200000000
2003 .LADD3:
2004         .quad   0x0000000000000000, 0x0000000300000000
2005 .LADD4:
2006         .quad   0x0000000000000000, 0x0000000400000000
2007 .LADD5:
2008         .quad   0x0000000000000000, 0x0000000500000000
2009 .LADD6:
2010         .quad   0x0000000000000000, 0x0000000600000000
2011 .LADD7:
2012         .quad   0x0000000000000000, 0x0000000700000000
2013 .LADD8:
2014         .quad   0x0000000000000000, 0x0000000800000000
2015 .asciz  "Bit-sliced AES for x86_64/SSSE3, Emilia Käsper, Peter Schwabe, Andy Polyakov"
2016 .align  64
2017 .size   _bsaes_const,.-_bsaes_const
2018 ___
2019
2020 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
2021
2022 print $code;
2023
2024 close STDOUT;