004bf026147eb6e59a2bc4d68939930ee9aaf674
[openssl.git] / crypto / aes / asm / aesni-x86_64.pl
1 #! /usr/bin/env perl
2 # Copyright 2009-2016 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the OpenSSL license (the "License").  You may not use
5 # this file except in compliance with the License.  You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
8
9 #
10 # ====================================================================
11 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
12 # project. The module is, however, dual licensed under OpenSSL and
13 # CRYPTOGAMS licenses depending on where you obtain it. For further
14 # details see http://www.openssl.org/~appro/cryptogams/.
15 # ====================================================================
16 #
17 # This module implements support for Intel AES-NI extension. In
18 # OpenSSL context it's used with Intel engine, but can also be used as
19 # drop-in replacement for crypto/aes/asm/aes-x86_64.pl [see below for
20 # details].
21 #
22 # Performance.
23 #
24 # Given aes(enc|dec) instructions' latency asymptotic performance for
25 # non-parallelizable modes such as CBC encrypt is 3.75 cycles per byte
26 # processed with 128-bit key. And given their throughput asymptotic
27 # performance for parallelizable modes is 1.25 cycles per byte. Being
28 # asymptotic limit it's not something you commonly achieve in reality,
29 # but how close does one get? Below are results collected for
30 # different modes and block sized. Pairs of numbers are for en-/
31 # decryption.
32 #
33 #       16-byte     64-byte     256-byte    1-KB        8-KB
34 # ECB   4.25/4.25   1.38/1.38   1.28/1.28   1.26/1.26   1.26/1.26
35 # CTR   5.42/5.42   1.92/1.92   1.44/1.44   1.28/1.28   1.26/1.26
36 # CBC   4.38/4.43   4.15/1.43   4.07/1.32   4.07/1.29   4.06/1.28
37 # CCM   5.66/9.42   4.42/5.41   4.16/4.40   4.09/4.15   4.06/4.07
38 # OFB   5.42/5.42   4.64/4.64   4.44/4.44   4.39/4.39   4.38/4.38
39 # CFB   5.73/5.85   5.56/5.62   5.48/5.56   5.47/5.55   5.47/5.55
40 #
41 # ECB, CTR, CBC and CCM results are free from EVP overhead. This means
42 # that otherwise used 'openssl speed -evp aes-128-??? -engine aesni
43 # [-decrypt]' will exhibit 10-15% worse results for smaller blocks.
44 # The results were collected with specially crafted speed.c benchmark
45 # in order to compare them with results reported in "Intel Advanced
46 # Encryption Standard (AES) New Instruction Set" White Paper Revision
47 # 3.0 dated May 2010. All above results are consistently better. This
48 # module also provides better performance for block sizes smaller than
49 # 128 bytes in points *not* represented in the above table.
50 #
51 # Looking at the results for 8-KB buffer.
52 #
53 # CFB and OFB results are far from the limit, because implementation
54 # uses "generic" CRYPTO_[c|o]fb128_encrypt interfaces relying on
55 # single-block aesni_encrypt, which is not the most optimal way to go.
56 # CBC encrypt result is unexpectedly high and there is no documented
57 # explanation for it. Seemingly there is a small penalty for feeding
58 # the result back to AES unit the way it's done in CBC mode. There is
59 # nothing one can do and the result appears optimal. CCM result is
60 # identical to CBC, because CBC-MAC is essentially CBC encrypt without
61 # saving output. CCM CTR "stays invisible," because it's neatly
62 # interleaved wih CBC-MAC. This provides ~30% improvement over
63 # "straghtforward" CCM implementation with CTR and CBC-MAC performed
64 # disjointly. Parallelizable modes practically achieve the theoretical
65 # limit.
66 #
67 # Looking at how results vary with buffer size.
68 #
69 # Curves are practically saturated at 1-KB buffer size. In most cases
70 # "256-byte" performance is >95%, and "64-byte" is ~90% of "8-KB" one.
71 # CTR curve doesn't follow this pattern and is "slowest" changing one
72 # with "256-byte" result being 87% of "8-KB." This is because overhead
73 # in CTR mode is most computationally intensive. Small-block CCM
74 # decrypt is slower than encrypt, because first CTR and last CBC-MAC
75 # iterations can't be interleaved.
76 #
77 # Results for 192- and 256-bit keys.
78 #
79 # EVP-free results were observed to scale perfectly with number of
80 # rounds for larger block sizes, i.e. 192-bit result being 10/12 times
81 # lower and 256-bit one - 10/14. Well, in CBC encrypt case differences
82 # are a tad smaller, because the above mentioned penalty biases all
83 # results by same constant value. In similar way function call
84 # overhead affects small-block performance, as well as OFB and CFB
85 # results. Differences are not large, most common coefficients are
86 # 10/11.7 and 10/13.4 (as opposite to 10/12.0 and 10/14.0), but one
87 # observe even 10/11.2 and 10/12.4 (CTR, OFB, CFB)...
88
89 # January 2011
90 #
91 # While Westmere processor features 6 cycles latency for aes[enc|dec]
92 # instructions, which can be scheduled every second cycle, Sandy
93 # Bridge spends 8 cycles per instruction, but it can schedule them
94 # every cycle. This means that code targeting Westmere would perform
95 # suboptimally on Sandy Bridge. Therefore this update.
96 #
97 # In addition, non-parallelizable CBC encrypt (as well as CCM) is
98 # optimized. Relative improvement might appear modest, 8% on Westmere,
99 # but in absolute terms it's 3.77 cycles per byte encrypted with
100 # 128-bit key on Westmere, and 5.07 - on Sandy Bridge. These numbers
101 # should be compared to asymptotic limits of 3.75 for Westmere and
102 # 5.00 for Sandy Bridge. Actually, the fact that they get this close
103 # to asymptotic limits is quite amazing. Indeed, the limit is
104 # calculated as latency times number of rounds, 10 for 128-bit key,
105 # and divided by 16, the number of bytes in block, or in other words
106 # it accounts *solely* for aesenc instructions. But there are extra
107 # instructions, and numbers so close to the asymptotic limits mean
108 # that it's as if it takes as little as *one* additional cycle to
109 # execute all of them. How is it possible? It is possible thanks to
110 # out-of-order execution logic, which manages to overlap post-
111 # processing of previous block, things like saving the output, with
112 # actual encryption of current block, as well as pre-processing of
113 # current block, things like fetching input and xor-ing it with
114 # 0-round element of the key schedule, with actual encryption of
115 # previous block. Keep this in mind...
116 #
117 # For parallelizable modes, such as ECB, CBC decrypt, CTR, higher
118 # performance is achieved by interleaving instructions working on
119 # independent blocks. In which case asymptotic limit for such modes
120 # can be obtained by dividing above mentioned numbers by AES
121 # instructions' interleave factor. Westmere can execute at most 3
122 # instructions at a time, meaning that optimal interleave factor is 3,
123 # and that's where the "magic" number of 1.25 come from. "Optimal
124 # interleave factor" means that increase of interleave factor does
125 # not improve performance. The formula has proven to reflect reality
126 # pretty well on Westmere... Sandy Bridge on the other hand can
127 # execute up to 8 AES instructions at a time, so how does varying
128 # interleave factor affect the performance? Here is table for ECB
129 # (numbers are cycles per byte processed with 128-bit key):
130 #
131 # instruction interleave factor         3x      6x      8x
132 # theoretical asymptotic limit          1.67    0.83    0.625
133 # measured performance for 8KB block    1.05    0.86    0.84
134 #
135 # "as if" interleave factor             4.7x    5.8x    6.0x
136 #
137 # Further data for other parallelizable modes:
138 #
139 # CBC decrypt                           1.16    0.93    0.74
140 # CTR                                   1.14    0.91    0.74
141 #
142 # Well, given 3x column it's probably inappropriate to call the limit
143 # asymptotic, if it can be surpassed, isn't it? What happens there?
144 # Rewind to CBC paragraph for the answer. Yes, out-of-order execution
145 # magic is responsible for this. Processor overlaps not only the
146 # additional instructions with AES ones, but even AES instuctions
147 # processing adjacent triplets of independent blocks. In the 6x case
148 # additional instructions  still claim disproportionally small amount
149 # of additional cycles, but in 8x case number of instructions must be
150 # a tad too high for out-of-order logic to cope with, and AES unit
151 # remains underutilized... As you can see 8x interleave is hardly
152 # justifiable, so there no need to feel bad that 32-bit aesni-x86.pl
153 # utilizies 6x interleave because of limited register bank capacity.
154 #
155 # Higher interleave factors do have negative impact on Westmere
156 # performance. While for ECB mode it's negligible ~1.5%, other
157 # parallelizables perform ~5% worse, which is outweighed by ~25%
158 # improvement on Sandy Bridge. To balance regression on Westmere
159 # CTR mode was implemented with 6x aesenc interleave factor.
160
161 # April 2011
162 #
163 # Add aesni_xts_[en|de]crypt. Westmere spends 1.25 cycles processing
164 # one byte out of 8KB with 128-bit key, Sandy Bridge - 0.90. Just like
165 # in CTR mode AES instruction interleave factor was chosen to be 6x.
166
167 # November 2015
168 #
169 # Add aesni_ocb_[en|de]crypt. AES instruction interleave factor was
170 # chosen to be 6x.
171
172 ######################################################################
173 # Current large-block performance in cycles per byte processed with
174 # 128-bit key (less is better).
175 #
176 #               CBC en-/decrypt CTR     XTS     ECB     OCB
177 # Westmere      3.77/1.25       1.25    1.25    1.26
178 # * Bridge      5.07/0.74       0.75    0.90    0.85    0.98
179 # Haswell       4.44/0.63       0.63    0.73    0.63    0.70
180 # Skylake       2.62/0.63       0.63    0.63    0.63
181 # Silvermont    5.75/3.54       3.56    4.12    3.87(*) 4.11
182 # Goldmont      3.82/1.26       1.26    1.29    1.29    1.50
183 # Bulldozer     5.77/0.70       0.72    0.90    0.70    0.95
184 # Ryzen         2.71/0.35       0.35    0.44    ?       ?
185 #
186 # (*)   Atom Silvermont ECB result is suboptimal because of penalties
187 #       incurred by operations on %xmm8-15. As ECB is not considered
188 #       critical, nothing was done to mitigate the problem.
189
190 $PREFIX="aesni";        # if $PREFIX is set to "AES", the script
191                         # generates drop-in replacement for
192                         # crypto/aes/asm/aes-x86_64.pl:-)
193
194 $flavour = shift;
195 $output  = shift;
196 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
197
198 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
199
200 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
201 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
202 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
203 die "can't locate x86_64-xlate.pl";
204
205 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
206 *STDOUT=*OUT;
207
208 $movkey = $PREFIX eq "aesni" ? "movups" : "movups";
209 @_4args=$win64? ("%rcx","%rdx","%r8", "%r9") :  # Win64 order
210                 ("%rdi","%rsi","%rdx","%rcx");  # Unix order
211
212 $code=".text\n";
213 $code.=".extern OPENSSL_ia32cap_P\n";
214
215 $rounds="%eax"; # input to and changed by aesni_[en|de]cryptN !!!
216 # this is natural Unix argument order for public $PREFIX_[ecb|cbc]_encrypt ...
217 $inp="%rdi";
218 $out="%rsi";
219 $len="%rdx";
220 $key="%rcx";    # input to and changed by aesni_[en|de]cryptN !!!
221 $ivp="%r8";     # cbc, ctr, ...
222
223 $rnds_="%r10d"; # backup copy for $rounds
224 $key_="%r11";   # backup copy for $key
225
226 # %xmm register layout
227 $rndkey0="%xmm0";       $rndkey1="%xmm1";
228 $inout0="%xmm2";        $inout1="%xmm3";
229 $inout2="%xmm4";        $inout3="%xmm5";
230 $inout4="%xmm6";        $inout5="%xmm7";
231 $inout6="%xmm8";        $inout7="%xmm9";
232
233 $in2="%xmm6";           $in1="%xmm7";   # used in CBC decrypt, CTR, ...
234 $in0="%xmm8";           $iv="%xmm9";
235 \f
236 # Inline version of internal aesni_[en|de]crypt1.
237 #
238 # Why folded loop? Because aes[enc|dec] is slow enough to accommodate
239 # cycles which take care of loop variables...
240 { my $sn;
241 sub aesni_generate1 {
242 my ($p,$key,$rounds,$inout,$ivec)=@_;   $inout=$inout0 if (!defined($inout));
243 ++$sn;
244 $code.=<<___;
245         $movkey ($key),$rndkey0
246         $movkey 16($key),$rndkey1
247 ___
248 $code.=<<___ if (defined($ivec));
249         xorps   $rndkey0,$ivec
250         lea     32($key),$key
251         xorps   $ivec,$inout
252 ___
253 $code.=<<___ if (!defined($ivec));
254         lea     32($key),$key
255         xorps   $rndkey0,$inout
256 ___
257 $code.=<<___;
258 .Loop_${p}1_$sn:
259         aes${p} $rndkey1,$inout
260         dec     $rounds
261         $movkey ($key),$rndkey1
262         lea     16($key),$key
263         jnz     .Loop_${p}1_$sn # loop body is 16 bytes
264         aes${p}last     $rndkey1,$inout
265 ___
266 }}
267 # void $PREFIX_[en|de]crypt (const void *inp,void *out,const AES_KEY *key);
268 #
269 { my ($inp,$out,$key) = @_4args;
270
271 $code.=<<___;
272 .globl  ${PREFIX}_encrypt
273 .type   ${PREFIX}_encrypt,\@abi-omnipotent
274 .align  16
275 ${PREFIX}_encrypt:
276         movups  ($inp),$inout0          # load input
277         mov     240($key),$rounds       # key->rounds
278 ___
279         &aesni_generate1("enc",$key,$rounds);
280 $code.=<<___;
281          pxor   $rndkey0,$rndkey0       # clear register bank
282          pxor   $rndkey1,$rndkey1
283         movups  $inout0,($out)          # output
284          pxor   $inout0,$inout0
285         ret
286 .size   ${PREFIX}_encrypt,.-${PREFIX}_encrypt
287
288 .globl  ${PREFIX}_decrypt
289 .type   ${PREFIX}_decrypt,\@abi-omnipotent
290 .align  16
291 ${PREFIX}_decrypt:
292         movups  ($inp),$inout0          # load input
293         mov     240($key),$rounds       # key->rounds
294 ___
295         &aesni_generate1("dec",$key,$rounds);
296 $code.=<<___;
297          pxor   $rndkey0,$rndkey0       # clear register bank
298          pxor   $rndkey1,$rndkey1
299         movups  $inout0,($out)          # output
300          pxor   $inout0,$inout0
301         ret
302 .size   ${PREFIX}_decrypt, .-${PREFIX}_decrypt
303 ___
304 }
305 \f
306 # _aesni_[en|de]cryptN are private interfaces, N denotes interleave
307 # factor. Why 3x subroutine were originally used in loops? Even though
308 # aes[enc|dec] latency was originally 6, it could be scheduled only
309 # every *2nd* cycle. Thus 3x interleave was the one providing optimal
310 # utilization, i.e. when subroutine's throughput is virtually same as
311 # of non-interleaved subroutine [for number of input blocks up to 3].
312 # This is why it originally made no sense to implement 2x subroutine.
313 # But times change and it became appropriate to spend extra 192 bytes
314 # on 2x subroutine on Atom Silvermont account. For processors that
315 # can schedule aes[enc|dec] every cycle optimal interleave factor
316 # equals to corresponding instructions latency. 8x is optimal for
317 # * Bridge and "super-optimal" for other Intel CPUs...
318
319 sub aesni_generate2 {
320 my $dir=shift;
321 # As already mentioned it takes in $key and $rounds, which are *not*
322 # preserved. $inout[0-1] is cipher/clear text...
323 $code.=<<___;
324 .type   _aesni_${dir}rypt2,\@abi-omnipotent
325 .align  16
326 _aesni_${dir}rypt2:
327         $movkey ($key),$rndkey0
328         shl     \$4,$rounds
329         $movkey 16($key),$rndkey1
330         xorps   $rndkey0,$inout0
331         xorps   $rndkey0,$inout1
332         $movkey 32($key),$rndkey0
333         lea     32($key,$rounds),$key
334         neg     %rax                            # $rounds
335         add     \$16,%rax
336
337 .L${dir}_loop2:
338         aes${dir}       $rndkey1,$inout0
339         aes${dir}       $rndkey1,$inout1
340         $movkey         ($key,%rax),$rndkey1
341         add             \$32,%rax
342         aes${dir}       $rndkey0,$inout0
343         aes${dir}       $rndkey0,$inout1
344         $movkey         -16($key,%rax),$rndkey0
345         jnz             .L${dir}_loop2
346
347         aes${dir}       $rndkey1,$inout0
348         aes${dir}       $rndkey1,$inout1
349         aes${dir}last   $rndkey0,$inout0
350         aes${dir}last   $rndkey0,$inout1
351         ret
352 .size   _aesni_${dir}rypt2,.-_aesni_${dir}rypt2
353 ___
354 }
355 sub aesni_generate3 {
356 my $dir=shift;
357 # As already mentioned it takes in $key and $rounds, which are *not*
358 # preserved. $inout[0-2] is cipher/clear text...
359 $code.=<<___;
360 .type   _aesni_${dir}rypt3,\@abi-omnipotent
361 .align  16
362 _aesni_${dir}rypt3:
363         $movkey ($key),$rndkey0
364         shl     \$4,$rounds
365         $movkey 16($key),$rndkey1
366         xorps   $rndkey0,$inout0
367         xorps   $rndkey0,$inout1
368         xorps   $rndkey0,$inout2
369         $movkey 32($key),$rndkey0
370         lea     32($key,$rounds),$key
371         neg     %rax                            # $rounds
372         add     \$16,%rax
373
374 .L${dir}_loop3:
375         aes${dir}       $rndkey1,$inout0
376         aes${dir}       $rndkey1,$inout1
377         aes${dir}       $rndkey1,$inout2
378         $movkey         ($key,%rax),$rndkey1
379         add             \$32,%rax
380         aes${dir}       $rndkey0,$inout0
381         aes${dir}       $rndkey0,$inout1
382         aes${dir}       $rndkey0,$inout2
383         $movkey         -16($key,%rax),$rndkey0
384         jnz             .L${dir}_loop3
385
386         aes${dir}       $rndkey1,$inout0
387         aes${dir}       $rndkey1,$inout1
388         aes${dir}       $rndkey1,$inout2
389         aes${dir}last   $rndkey0,$inout0
390         aes${dir}last   $rndkey0,$inout1
391         aes${dir}last   $rndkey0,$inout2
392         ret
393 .size   _aesni_${dir}rypt3,.-_aesni_${dir}rypt3
394 ___
395 }
396 # 4x interleave is implemented to improve small block performance,
397 # most notably [and naturally] 4 block by ~30%. One can argue that one
398 # should have implemented 5x as well, but improvement would be <20%,
399 # so it's not worth it...
400 sub aesni_generate4 {
401 my $dir=shift;
402 # As already mentioned it takes in $key and $rounds, which are *not*
403 # preserved. $inout[0-3] is cipher/clear text...
404 $code.=<<___;
405 .type   _aesni_${dir}rypt4,\@abi-omnipotent
406 .align  16
407 _aesni_${dir}rypt4:
408         $movkey ($key),$rndkey0
409         shl     \$4,$rounds
410         $movkey 16($key),$rndkey1
411         xorps   $rndkey0,$inout0
412         xorps   $rndkey0,$inout1
413         xorps   $rndkey0,$inout2
414         xorps   $rndkey0,$inout3
415         $movkey 32($key),$rndkey0
416         lea     32($key,$rounds),$key
417         neg     %rax                            # $rounds
418         .byte   0x0f,0x1f,0x00
419         add     \$16,%rax
420
421 .L${dir}_loop4:
422         aes${dir}       $rndkey1,$inout0
423         aes${dir}       $rndkey1,$inout1
424         aes${dir}       $rndkey1,$inout2
425         aes${dir}       $rndkey1,$inout3
426         $movkey         ($key,%rax),$rndkey1
427         add             \$32,%rax
428         aes${dir}       $rndkey0,$inout0
429         aes${dir}       $rndkey0,$inout1
430         aes${dir}       $rndkey0,$inout2
431         aes${dir}       $rndkey0,$inout3
432         $movkey         -16($key,%rax),$rndkey0
433         jnz             .L${dir}_loop4
434
435         aes${dir}       $rndkey1,$inout0
436         aes${dir}       $rndkey1,$inout1
437         aes${dir}       $rndkey1,$inout2
438         aes${dir}       $rndkey1,$inout3
439         aes${dir}last   $rndkey0,$inout0
440         aes${dir}last   $rndkey0,$inout1
441         aes${dir}last   $rndkey0,$inout2
442         aes${dir}last   $rndkey0,$inout3
443         ret
444 .size   _aesni_${dir}rypt4,.-_aesni_${dir}rypt4
445 ___
446 }
447 sub aesni_generate6 {
448 my $dir=shift;
449 # As already mentioned it takes in $key and $rounds, which are *not*
450 # preserved. $inout[0-5] is cipher/clear text...
451 $code.=<<___;
452 .type   _aesni_${dir}rypt6,\@abi-omnipotent
453 .align  16
454 _aesni_${dir}rypt6:
455         $movkey         ($key),$rndkey0
456         shl             \$4,$rounds
457         $movkey         16($key),$rndkey1
458         xorps           $rndkey0,$inout0
459         pxor            $rndkey0,$inout1
460         pxor            $rndkey0,$inout2
461         aes${dir}       $rndkey1,$inout0
462         lea             32($key,$rounds),$key
463         neg             %rax                    # $rounds
464         aes${dir}       $rndkey1,$inout1
465         pxor            $rndkey0,$inout3
466         pxor            $rndkey0,$inout4
467         aes${dir}       $rndkey1,$inout2
468         pxor            $rndkey0,$inout5
469         $movkey         ($key,%rax),$rndkey0
470         add             \$16,%rax
471         jmp             .L${dir}_loop6_enter
472 .align  16
473 .L${dir}_loop6:
474         aes${dir}       $rndkey1,$inout0
475         aes${dir}       $rndkey1,$inout1
476         aes${dir}       $rndkey1,$inout2
477 .L${dir}_loop6_enter:
478         aes${dir}       $rndkey1,$inout3
479         aes${dir}       $rndkey1,$inout4
480         aes${dir}       $rndkey1,$inout5
481         $movkey         ($key,%rax),$rndkey1
482         add             \$32,%rax
483         aes${dir}       $rndkey0,$inout0
484         aes${dir}       $rndkey0,$inout1
485         aes${dir}       $rndkey0,$inout2
486         aes${dir}       $rndkey0,$inout3
487         aes${dir}       $rndkey0,$inout4
488         aes${dir}       $rndkey0,$inout5
489         $movkey         -16($key,%rax),$rndkey0
490         jnz             .L${dir}_loop6
491
492         aes${dir}       $rndkey1,$inout0
493         aes${dir}       $rndkey1,$inout1
494         aes${dir}       $rndkey1,$inout2
495         aes${dir}       $rndkey1,$inout3
496         aes${dir}       $rndkey1,$inout4
497         aes${dir}       $rndkey1,$inout5
498         aes${dir}last   $rndkey0,$inout0
499         aes${dir}last   $rndkey0,$inout1
500         aes${dir}last   $rndkey0,$inout2
501         aes${dir}last   $rndkey0,$inout3
502         aes${dir}last   $rndkey0,$inout4
503         aes${dir}last   $rndkey0,$inout5
504         ret
505 .size   _aesni_${dir}rypt6,.-_aesni_${dir}rypt6
506 ___
507 }
508 sub aesni_generate8 {
509 my $dir=shift;
510 # As already mentioned it takes in $key and $rounds, which are *not*
511 # preserved. $inout[0-7] is cipher/clear text...
512 $code.=<<___;
513 .type   _aesni_${dir}rypt8,\@abi-omnipotent
514 .align  16
515 _aesni_${dir}rypt8:
516         $movkey         ($key),$rndkey0
517         shl             \$4,$rounds
518         $movkey         16($key),$rndkey1
519         xorps           $rndkey0,$inout0
520         xorps           $rndkey0,$inout1
521         pxor            $rndkey0,$inout2
522         pxor            $rndkey0,$inout3
523         pxor            $rndkey0,$inout4
524         lea             32($key,$rounds),$key
525         neg             %rax                    # $rounds
526         aes${dir}       $rndkey1,$inout0
527         pxor            $rndkey0,$inout5
528         pxor            $rndkey0,$inout6
529         aes${dir}       $rndkey1,$inout1
530         pxor            $rndkey0,$inout7
531         $movkey         ($key,%rax),$rndkey0
532         add             \$16,%rax
533         jmp             .L${dir}_loop8_inner
534 .align  16
535 .L${dir}_loop8:
536         aes${dir}       $rndkey1,$inout0
537         aes${dir}       $rndkey1,$inout1
538 .L${dir}_loop8_inner:
539         aes${dir}       $rndkey1,$inout2
540         aes${dir}       $rndkey1,$inout3
541         aes${dir}       $rndkey1,$inout4
542         aes${dir}       $rndkey1,$inout5
543         aes${dir}       $rndkey1,$inout6
544         aes${dir}       $rndkey1,$inout7
545 .L${dir}_loop8_enter:
546         $movkey         ($key,%rax),$rndkey1
547         add             \$32,%rax
548         aes${dir}       $rndkey0,$inout0
549         aes${dir}       $rndkey0,$inout1
550         aes${dir}       $rndkey0,$inout2
551         aes${dir}       $rndkey0,$inout3
552         aes${dir}       $rndkey0,$inout4
553         aes${dir}       $rndkey0,$inout5
554         aes${dir}       $rndkey0,$inout6
555         aes${dir}       $rndkey0,$inout7
556         $movkey         -16($key,%rax),$rndkey0
557         jnz             .L${dir}_loop8
558
559         aes${dir}       $rndkey1,$inout0
560         aes${dir}       $rndkey1,$inout1
561         aes${dir}       $rndkey1,$inout2
562         aes${dir}       $rndkey1,$inout3
563         aes${dir}       $rndkey1,$inout4
564         aes${dir}       $rndkey1,$inout5
565         aes${dir}       $rndkey1,$inout6
566         aes${dir}       $rndkey1,$inout7
567         aes${dir}last   $rndkey0,$inout0
568         aes${dir}last   $rndkey0,$inout1
569         aes${dir}last   $rndkey0,$inout2
570         aes${dir}last   $rndkey0,$inout3
571         aes${dir}last   $rndkey0,$inout4
572         aes${dir}last   $rndkey0,$inout5
573         aes${dir}last   $rndkey0,$inout6
574         aes${dir}last   $rndkey0,$inout7
575         ret
576 .size   _aesni_${dir}rypt8,.-_aesni_${dir}rypt8
577 ___
578 }
579 &aesni_generate2("enc") if ($PREFIX eq "aesni");
580 &aesni_generate2("dec");
581 &aesni_generate3("enc") if ($PREFIX eq "aesni");
582 &aesni_generate3("dec");
583 &aesni_generate4("enc") if ($PREFIX eq "aesni");
584 &aesni_generate4("dec");
585 &aesni_generate6("enc") if ($PREFIX eq "aesni");
586 &aesni_generate6("dec");
587 &aesni_generate8("enc") if ($PREFIX eq "aesni");
588 &aesni_generate8("dec");
589 \f
590 if ($PREFIX eq "aesni") {
591 ########################################################################
592 # void aesni_ecb_encrypt (const void *in, void *out,
593 #                         size_t length, const AES_KEY *key,
594 #                         int enc);
595 $code.=<<___;
596 .globl  aesni_ecb_encrypt
597 .type   aesni_ecb_encrypt,\@function,5
598 .align  16
599 aesni_ecb_encrypt:
600 ___
601 $code.=<<___ if ($win64);
602         lea     -0x58(%rsp),%rsp
603         movaps  %xmm6,(%rsp)            # offload $inout4..7
604         movaps  %xmm7,0x10(%rsp)
605         movaps  %xmm8,0x20(%rsp)
606         movaps  %xmm9,0x30(%rsp)
607 .Lecb_enc_body:
608 ___
609 $code.=<<___;
610         and     \$-16,$len              # if ($len<16)
611         jz      .Lecb_ret               # return
612
613         mov     240($key),$rounds       # key->rounds
614         $movkey ($key),$rndkey0
615         mov     $key,$key_              # backup $key
616         mov     $rounds,$rnds_          # backup $rounds
617         test    %r8d,%r8d               # 5th argument
618         jz      .Lecb_decrypt
619 #--------------------------- ECB ENCRYPT ------------------------------#
620         cmp     \$0x80,$len             # if ($len<8*16)
621         jb      .Lecb_enc_tail          # short input
622
623         movdqu  ($inp),$inout0          # load 8 input blocks
624         movdqu  0x10($inp),$inout1
625         movdqu  0x20($inp),$inout2
626         movdqu  0x30($inp),$inout3
627         movdqu  0x40($inp),$inout4
628         movdqu  0x50($inp),$inout5
629         movdqu  0x60($inp),$inout6
630         movdqu  0x70($inp),$inout7
631         lea     0x80($inp),$inp         # $inp+=8*16
632         sub     \$0x80,$len             # $len-=8*16 (can be zero)
633         jmp     .Lecb_enc_loop8_enter
634 .align 16
635 .Lecb_enc_loop8:
636         movups  $inout0,($out)          # store 8 output blocks
637         mov     $key_,$key              # restore $key
638         movdqu  ($inp),$inout0          # load 8 input blocks
639         mov     $rnds_,$rounds          # restore $rounds
640         movups  $inout1,0x10($out)
641         movdqu  0x10($inp),$inout1
642         movups  $inout2,0x20($out)
643         movdqu  0x20($inp),$inout2
644         movups  $inout3,0x30($out)
645         movdqu  0x30($inp),$inout3
646         movups  $inout4,0x40($out)
647         movdqu  0x40($inp),$inout4
648         movups  $inout5,0x50($out)
649         movdqu  0x50($inp),$inout5
650         movups  $inout6,0x60($out)
651         movdqu  0x60($inp),$inout6
652         movups  $inout7,0x70($out)
653         lea     0x80($out),$out         # $out+=8*16
654         movdqu  0x70($inp),$inout7
655         lea     0x80($inp),$inp         # $inp+=8*16
656 .Lecb_enc_loop8_enter:
657
658         call    _aesni_encrypt8
659
660         sub     \$0x80,$len
661         jnc     .Lecb_enc_loop8         # loop if $len-=8*16 didn't borrow
662
663         movups  $inout0,($out)          # store 8 output blocks
664         mov     $key_,$key              # restore $key
665         movups  $inout1,0x10($out)
666         mov     $rnds_,$rounds          # restore $rounds
667         movups  $inout2,0x20($out)
668         movups  $inout3,0x30($out)
669         movups  $inout4,0x40($out)
670         movups  $inout5,0x50($out)
671         movups  $inout6,0x60($out)
672         movups  $inout7,0x70($out)
673         lea     0x80($out),$out         # $out+=8*16
674         add     \$0x80,$len             # restore real remaining $len
675         jz      .Lecb_ret               # done if ($len==0)
676
677 .Lecb_enc_tail:                         # $len is less than 8*16
678         movups  ($inp),$inout0
679         cmp     \$0x20,$len
680         jb      .Lecb_enc_one
681         movups  0x10($inp),$inout1
682         je      .Lecb_enc_two
683         movups  0x20($inp),$inout2
684         cmp     \$0x40,$len
685         jb      .Lecb_enc_three
686         movups  0x30($inp),$inout3
687         je      .Lecb_enc_four
688         movups  0x40($inp),$inout4
689         cmp     \$0x60,$len
690         jb      .Lecb_enc_five
691         movups  0x50($inp),$inout5
692         je      .Lecb_enc_six
693         movdqu  0x60($inp),$inout6
694         xorps   $inout7,$inout7
695         call    _aesni_encrypt8
696         movups  $inout0,($out)          # store 7 output blocks
697         movups  $inout1,0x10($out)
698         movups  $inout2,0x20($out)
699         movups  $inout3,0x30($out)
700         movups  $inout4,0x40($out)
701         movups  $inout5,0x50($out)
702         movups  $inout6,0x60($out)
703         jmp     .Lecb_ret
704 .align  16
705 .Lecb_enc_one:
706 ___
707         &aesni_generate1("enc",$key,$rounds);
708 $code.=<<___;
709         movups  $inout0,($out)          # store one output block
710         jmp     .Lecb_ret
711 .align  16
712 .Lecb_enc_two:
713         call    _aesni_encrypt2
714         movups  $inout0,($out)          # store 2 output blocks
715         movups  $inout1,0x10($out)
716         jmp     .Lecb_ret
717 .align  16
718 .Lecb_enc_three:
719         call    _aesni_encrypt3
720         movups  $inout0,($out)          # store 3 output blocks
721         movups  $inout1,0x10($out)
722         movups  $inout2,0x20($out)
723         jmp     .Lecb_ret
724 .align  16
725 .Lecb_enc_four:
726         call    _aesni_encrypt4
727         movups  $inout0,($out)          # store 4 output blocks
728         movups  $inout1,0x10($out)
729         movups  $inout2,0x20($out)
730         movups  $inout3,0x30($out)
731         jmp     .Lecb_ret
732 .align  16
733 .Lecb_enc_five:
734         xorps   $inout5,$inout5
735         call    _aesni_encrypt6
736         movups  $inout0,($out)          # store 5 output blocks
737         movups  $inout1,0x10($out)
738         movups  $inout2,0x20($out)
739         movups  $inout3,0x30($out)
740         movups  $inout4,0x40($out)
741         jmp     .Lecb_ret
742 .align  16
743 .Lecb_enc_six:
744         call    _aesni_encrypt6
745         movups  $inout0,($out)          # store 6 output blocks
746         movups  $inout1,0x10($out)
747         movups  $inout2,0x20($out)
748         movups  $inout3,0x30($out)
749         movups  $inout4,0x40($out)
750         movups  $inout5,0x50($out)
751         jmp     .Lecb_ret
752 \f#--------------------------- ECB DECRYPT ------------------------------#
753 .align  16
754 .Lecb_decrypt:
755         cmp     \$0x80,$len             # if ($len<8*16)
756         jb      .Lecb_dec_tail          # short input
757
758         movdqu  ($inp),$inout0          # load 8 input blocks
759         movdqu  0x10($inp),$inout1
760         movdqu  0x20($inp),$inout2
761         movdqu  0x30($inp),$inout3
762         movdqu  0x40($inp),$inout4
763         movdqu  0x50($inp),$inout5
764         movdqu  0x60($inp),$inout6
765         movdqu  0x70($inp),$inout7
766         lea     0x80($inp),$inp         # $inp+=8*16
767         sub     \$0x80,$len             # $len-=8*16 (can be zero)
768         jmp     .Lecb_dec_loop8_enter
769 .align 16
770 .Lecb_dec_loop8:
771         movups  $inout0,($out)          # store 8 output blocks
772         mov     $key_,$key              # restore $key
773         movdqu  ($inp),$inout0          # load 8 input blocks
774         mov     $rnds_,$rounds          # restore $rounds
775         movups  $inout1,0x10($out)
776         movdqu  0x10($inp),$inout1
777         movups  $inout2,0x20($out)
778         movdqu  0x20($inp),$inout2
779         movups  $inout3,0x30($out)
780         movdqu  0x30($inp),$inout3
781         movups  $inout4,0x40($out)
782         movdqu  0x40($inp),$inout4
783         movups  $inout5,0x50($out)
784         movdqu  0x50($inp),$inout5
785         movups  $inout6,0x60($out)
786         movdqu  0x60($inp),$inout6
787         movups  $inout7,0x70($out)
788         lea     0x80($out),$out         # $out+=8*16
789         movdqu  0x70($inp),$inout7
790         lea     0x80($inp),$inp         # $inp+=8*16
791 .Lecb_dec_loop8_enter:
792
793         call    _aesni_decrypt8
794
795         $movkey ($key_),$rndkey0
796         sub     \$0x80,$len
797         jnc     .Lecb_dec_loop8         # loop if $len-=8*16 didn't borrow
798
799         movups  $inout0,($out)          # store 8 output blocks
800          pxor   $inout0,$inout0         # clear register bank
801         mov     $key_,$key              # restore $key
802         movups  $inout1,0x10($out)
803          pxor   $inout1,$inout1
804         mov     $rnds_,$rounds          # restore $rounds
805         movups  $inout2,0x20($out)
806          pxor   $inout2,$inout2
807         movups  $inout3,0x30($out)
808          pxor   $inout3,$inout3
809         movups  $inout4,0x40($out)
810          pxor   $inout4,$inout4
811         movups  $inout5,0x50($out)
812          pxor   $inout5,$inout5
813         movups  $inout6,0x60($out)
814          pxor   $inout6,$inout6
815         movups  $inout7,0x70($out)
816          pxor   $inout7,$inout7
817         lea     0x80($out),$out         # $out+=8*16
818         add     \$0x80,$len             # restore real remaining $len
819         jz      .Lecb_ret               # done if ($len==0)
820
821 .Lecb_dec_tail:
822         movups  ($inp),$inout0
823         cmp     \$0x20,$len
824         jb      .Lecb_dec_one
825         movups  0x10($inp),$inout1
826         je      .Lecb_dec_two
827         movups  0x20($inp),$inout2
828         cmp     \$0x40,$len
829         jb      .Lecb_dec_three
830         movups  0x30($inp),$inout3
831         je      .Lecb_dec_four
832         movups  0x40($inp),$inout4
833         cmp     \$0x60,$len
834         jb      .Lecb_dec_five
835         movups  0x50($inp),$inout5
836         je      .Lecb_dec_six
837         movups  0x60($inp),$inout6
838         $movkey ($key),$rndkey0
839         xorps   $inout7,$inout7
840         call    _aesni_decrypt8
841         movups  $inout0,($out)          # store 7 output blocks
842          pxor   $inout0,$inout0         # clear register bank
843         movups  $inout1,0x10($out)
844          pxor   $inout1,$inout1
845         movups  $inout2,0x20($out)
846          pxor   $inout2,$inout2
847         movups  $inout3,0x30($out)
848          pxor   $inout3,$inout3
849         movups  $inout4,0x40($out)
850          pxor   $inout4,$inout4
851         movups  $inout5,0x50($out)
852          pxor   $inout5,$inout5
853         movups  $inout6,0x60($out)
854          pxor   $inout6,$inout6
855          pxor   $inout7,$inout7
856         jmp     .Lecb_ret
857 .align  16
858 .Lecb_dec_one:
859 ___
860         &aesni_generate1("dec",$key,$rounds);
861 $code.=<<___;
862         movups  $inout0,($out)          # store one output block
863          pxor   $inout0,$inout0         # clear register bank
864         jmp     .Lecb_ret
865 .align  16
866 .Lecb_dec_two:
867         call    _aesni_decrypt2
868         movups  $inout0,($out)          # store 2 output blocks
869          pxor   $inout0,$inout0         # clear register bank
870         movups  $inout1,0x10($out)
871          pxor   $inout1,$inout1
872         jmp     .Lecb_ret
873 .align  16
874 .Lecb_dec_three:
875         call    _aesni_decrypt3
876         movups  $inout0,($out)          # store 3 output blocks
877          pxor   $inout0,$inout0         # clear register bank
878         movups  $inout1,0x10($out)
879          pxor   $inout1,$inout1
880         movups  $inout2,0x20($out)
881          pxor   $inout2,$inout2
882         jmp     .Lecb_ret
883 .align  16
884 .Lecb_dec_four:
885         call    _aesni_decrypt4
886         movups  $inout0,($out)          # store 4 output blocks
887          pxor   $inout0,$inout0         # clear register bank
888         movups  $inout1,0x10($out)
889          pxor   $inout1,$inout1
890         movups  $inout2,0x20($out)
891          pxor   $inout2,$inout2
892         movups  $inout3,0x30($out)
893          pxor   $inout3,$inout3
894         jmp     .Lecb_ret
895 .align  16
896 .Lecb_dec_five:
897         xorps   $inout5,$inout5
898         call    _aesni_decrypt6
899         movups  $inout0,($out)          # store 5 output blocks
900          pxor   $inout0,$inout0         # clear register bank
901         movups  $inout1,0x10($out)
902          pxor   $inout1,$inout1
903         movups  $inout2,0x20($out)
904          pxor   $inout2,$inout2
905         movups  $inout3,0x30($out)
906          pxor   $inout3,$inout3
907         movups  $inout4,0x40($out)
908          pxor   $inout4,$inout4
909          pxor   $inout5,$inout5
910         jmp     .Lecb_ret
911 .align  16
912 .Lecb_dec_six:
913         call    _aesni_decrypt6
914         movups  $inout0,($out)          # store 6 output blocks
915          pxor   $inout0,$inout0         # clear register bank
916         movups  $inout1,0x10($out)
917          pxor   $inout1,$inout1
918         movups  $inout2,0x20($out)
919          pxor   $inout2,$inout2
920         movups  $inout3,0x30($out)
921          pxor   $inout3,$inout3
922         movups  $inout4,0x40($out)
923          pxor   $inout4,$inout4
924         movups  $inout5,0x50($out)
925          pxor   $inout5,$inout5
926
927 .Lecb_ret:
928         xorps   $rndkey0,$rndkey0       # %xmm0
929         pxor    $rndkey1,$rndkey1
930 ___
931 $code.=<<___ if ($win64);
932         movaps  (%rsp),%xmm6
933         movaps  %xmm0,(%rsp)            # clear stack
934         movaps  0x10(%rsp),%xmm7
935         movaps  %xmm0,0x10(%rsp)
936         movaps  0x20(%rsp),%xmm8
937         movaps  %xmm0,0x20(%rsp)
938         movaps  0x30(%rsp),%xmm9
939         movaps  %xmm0,0x30(%rsp)
940         lea     0x58(%rsp),%rsp
941 .Lecb_enc_ret:
942 ___
943 $code.=<<___;
944         ret
945 .size   aesni_ecb_encrypt,.-aesni_ecb_encrypt
946 ___
947 \f
948 {
949 ######################################################################
950 # void aesni_ccm64_[en|de]crypt_blocks (const void *in, void *out,
951 #                         size_t blocks, const AES_KEY *key,
952 #                         const char *ivec,char *cmac);
953 #
954 # Handles only complete blocks, operates on 64-bit counter and
955 # does not update *ivec! Nor does it finalize CMAC value
956 # (see engine/eng_aesni.c for details)
957 #
958 {
959 my $cmac="%r9"; # 6th argument
960
961 my $increment="%xmm9";
962 my $iv="%xmm6";
963 my $bswap_mask="%xmm7";
964
965 $code.=<<___;
966 .globl  aesni_ccm64_encrypt_blocks
967 .type   aesni_ccm64_encrypt_blocks,\@function,6
968 .align  16
969 aesni_ccm64_encrypt_blocks:
970 ___
971 $code.=<<___ if ($win64);
972         lea     -0x58(%rsp),%rsp
973         movaps  %xmm6,(%rsp)            # $iv
974         movaps  %xmm7,0x10(%rsp)        # $bswap_mask
975         movaps  %xmm8,0x20(%rsp)        # $in0
976         movaps  %xmm9,0x30(%rsp)        # $increment
977 .Lccm64_enc_body:
978 ___
979 $code.=<<___;
980         mov     240($key),$rounds               # key->rounds
981         movdqu  ($ivp),$iv
982         movdqa  .Lincrement64(%rip),$increment
983         movdqa  .Lbswap_mask(%rip),$bswap_mask
984
985         shl     \$4,$rounds
986         mov     \$16,$rnds_
987         lea     0($key),$key_
988         movdqu  ($cmac),$inout1
989         movdqa  $iv,$inout0
990         lea     32($key,$rounds),$key           # end of key schedule
991         pshufb  $bswap_mask,$iv
992         sub     %rax,%r10                       # twisted $rounds
993         jmp     .Lccm64_enc_outer
994 .align  16
995 .Lccm64_enc_outer:
996         $movkey ($key_),$rndkey0
997         mov     %r10,%rax
998         movups  ($inp),$in0                     # load inp
999
1000         xorps   $rndkey0,$inout0                # counter
1001         $movkey 16($key_),$rndkey1
1002         xorps   $in0,$rndkey0
1003         xorps   $rndkey0,$inout1                # cmac^=inp
1004         $movkey 32($key_),$rndkey0
1005
1006 .Lccm64_enc2_loop:
1007         aesenc  $rndkey1,$inout0
1008         aesenc  $rndkey1,$inout1
1009         $movkey ($key,%rax),$rndkey1
1010         add     \$32,%rax
1011         aesenc  $rndkey0,$inout0
1012         aesenc  $rndkey0,$inout1
1013         $movkey -16($key,%rax),$rndkey0
1014         jnz     .Lccm64_enc2_loop
1015         aesenc  $rndkey1,$inout0
1016         aesenc  $rndkey1,$inout1
1017         paddq   $increment,$iv
1018         dec     $len                            # $len-- ($len is in blocks)
1019         aesenclast      $rndkey0,$inout0
1020         aesenclast      $rndkey0,$inout1
1021
1022         lea     16($inp),$inp
1023         xorps   $inout0,$in0                    # inp ^= E(iv)
1024         movdqa  $iv,$inout0
1025         movups  $in0,($out)                     # save output
1026         pshufb  $bswap_mask,$inout0
1027         lea     16($out),$out                   # $out+=16
1028         jnz     .Lccm64_enc_outer               # loop if ($len!=0)
1029
1030          pxor   $rndkey0,$rndkey0               # clear register bank
1031          pxor   $rndkey1,$rndkey1
1032          pxor   $inout0,$inout0
1033         movups  $inout1,($cmac)                 # store resulting mac
1034          pxor   $inout1,$inout1
1035          pxor   $in0,$in0
1036          pxor   $iv,$iv
1037 ___
1038 $code.=<<___ if ($win64);
1039         movaps  (%rsp),%xmm6
1040         movaps  %xmm0,(%rsp)                    # clear stack
1041         movaps  0x10(%rsp),%xmm7
1042         movaps  %xmm0,0x10(%rsp)
1043         movaps  0x20(%rsp),%xmm8
1044         movaps  %xmm0,0x20(%rsp)
1045         movaps  0x30(%rsp),%xmm9
1046         movaps  %xmm0,0x30(%rsp)
1047         lea     0x58(%rsp),%rsp
1048 .Lccm64_enc_ret:
1049 ___
1050 $code.=<<___;
1051         ret
1052 .size   aesni_ccm64_encrypt_blocks,.-aesni_ccm64_encrypt_blocks
1053 ___
1054 ######################################################################
1055 $code.=<<___;
1056 .globl  aesni_ccm64_decrypt_blocks
1057 .type   aesni_ccm64_decrypt_blocks,\@function,6
1058 .align  16
1059 aesni_ccm64_decrypt_blocks:
1060 ___
1061 $code.=<<___ if ($win64);
1062         lea     -0x58(%rsp),%rsp
1063         movaps  %xmm6,(%rsp)            # $iv
1064         movaps  %xmm7,0x10(%rsp)        # $bswap_mask
1065         movaps  %xmm8,0x20(%rsp)        # $in8
1066         movaps  %xmm9,0x30(%rsp)        # $increment
1067 .Lccm64_dec_body:
1068 ___
1069 $code.=<<___;
1070         mov     240($key),$rounds               # key->rounds
1071         movups  ($ivp),$iv
1072         movdqu  ($cmac),$inout1
1073         movdqa  .Lincrement64(%rip),$increment
1074         movdqa  .Lbswap_mask(%rip),$bswap_mask
1075
1076         movaps  $iv,$inout0
1077         mov     $rounds,$rnds_
1078         mov     $key,$key_
1079         pshufb  $bswap_mask,$iv
1080 ___
1081         &aesni_generate1("enc",$key,$rounds);
1082 $code.=<<___;
1083         shl     \$4,$rnds_
1084         mov     \$16,$rounds
1085         movups  ($inp),$in0                     # load inp
1086         paddq   $increment,$iv
1087         lea     16($inp),$inp                   # $inp+=16
1088         sub     %r10,%rax                       # twisted $rounds
1089         lea     32($key_,$rnds_),$key           # end of key schedule
1090         mov     %rax,%r10
1091         jmp     .Lccm64_dec_outer
1092 .align  16
1093 .Lccm64_dec_outer:
1094         xorps   $inout0,$in0                    # inp ^= E(iv)
1095         movdqa  $iv,$inout0
1096         movups  $in0,($out)                     # save output
1097         lea     16($out),$out                   # $out+=16
1098         pshufb  $bswap_mask,$inout0
1099
1100         sub     \$1,$len                        # $len-- ($len is in blocks)
1101         jz      .Lccm64_dec_break               # if ($len==0) break
1102
1103         $movkey ($key_),$rndkey0
1104         mov     %r10,%rax
1105         $movkey 16($key_),$rndkey1
1106         xorps   $rndkey0,$in0
1107         xorps   $rndkey0,$inout0
1108         xorps   $in0,$inout1                    # cmac^=out
1109         $movkey 32($key_),$rndkey0
1110         jmp     .Lccm64_dec2_loop
1111 .align  16
1112 .Lccm64_dec2_loop:
1113         aesenc  $rndkey1,$inout0
1114         aesenc  $rndkey1,$inout1
1115         $movkey ($key,%rax),$rndkey1
1116         add     \$32,%rax
1117         aesenc  $rndkey0,$inout0
1118         aesenc  $rndkey0,$inout1
1119         $movkey -16($key,%rax),$rndkey0
1120         jnz     .Lccm64_dec2_loop
1121         movups  ($inp),$in0                     # load input
1122         paddq   $increment,$iv
1123         aesenc  $rndkey1,$inout0
1124         aesenc  $rndkey1,$inout1
1125         aesenclast      $rndkey0,$inout0
1126         aesenclast      $rndkey0,$inout1
1127         lea     16($inp),$inp                   # $inp+=16
1128         jmp     .Lccm64_dec_outer
1129
1130 .align  16
1131 .Lccm64_dec_break:
1132         #xorps  $in0,$inout1                    # cmac^=out
1133         mov     240($key_),$rounds
1134 ___
1135         &aesni_generate1("enc",$key_,$rounds,$inout1,$in0);
1136 $code.=<<___;
1137          pxor   $rndkey0,$rndkey0               # clear register bank
1138          pxor   $rndkey1,$rndkey1
1139          pxor   $inout0,$inout0
1140         movups  $inout1,($cmac)                 # store resulting mac
1141          pxor   $inout1,$inout1
1142          pxor   $in0,$in0
1143          pxor   $iv,$iv
1144 ___
1145 $code.=<<___ if ($win64);
1146         movaps  (%rsp),%xmm6
1147         movaps  %xmm0,(%rsp)                    # clear stack
1148         movaps  0x10(%rsp),%xmm7
1149         movaps  %xmm0,0x10(%rsp)
1150         movaps  0x20(%rsp),%xmm8
1151         movaps  %xmm0,0x20(%rsp)
1152         movaps  0x30(%rsp),%xmm9
1153         movaps  %xmm0,0x30(%rsp)
1154         lea     0x58(%rsp),%rsp
1155 .Lccm64_dec_ret:
1156 ___
1157 $code.=<<___;
1158         ret
1159 .size   aesni_ccm64_decrypt_blocks,.-aesni_ccm64_decrypt_blocks
1160 ___
1161 }\f
1162 ######################################################################
1163 # void aesni_ctr32_encrypt_blocks (const void *in, void *out,
1164 #                         size_t blocks, const AES_KEY *key,
1165 #                         const char *ivec);
1166 #
1167 # Handles only complete blocks, operates on 32-bit counter and
1168 # does not update *ivec! (see crypto/modes/ctr128.c for details)
1169 #
1170 # Overhaul based on suggestions from Shay Gueron and Vlad Krasnov,
1171 # http://rt.openssl.org/Ticket/Display.html?id=3021&user=guest&pass=guest.
1172 # Keywords are full unroll and modulo-schedule counter calculations
1173 # with zero-round key xor.
1174 {
1175 my ($in0,$in1,$in2,$in3,$in4,$in5)=map("%xmm$_",(10..15));
1176 my ($key0,$ctr)=("%ebp","${ivp}d");
1177 my $frame_size = 0x80 + ($win64?160:0);
1178
1179 $code.=<<___;
1180 .globl  aesni_ctr32_encrypt_blocks
1181 .type   aesni_ctr32_encrypt_blocks,\@function,5
1182 .align  16
1183 aesni_ctr32_encrypt_blocks:
1184 .cfi_startproc
1185         cmp     \$1,$len
1186         jne     .Lctr32_bulk
1187
1188         # handle single block without allocating stack frame,
1189         # useful when handling edges
1190         movups  ($ivp),$inout0
1191         movups  ($inp),$inout1
1192         mov     240($key),%edx                  # key->rounds
1193 ___
1194         &aesni_generate1("enc",$key,"%edx");
1195 $code.=<<___;
1196          pxor   $rndkey0,$rndkey0               # clear register bank
1197          pxor   $rndkey1,$rndkey1
1198         xorps   $inout1,$inout0
1199          pxor   $inout1,$inout1
1200         movups  $inout0,($out)
1201          xorps  $inout0,$inout0
1202         jmp     .Lctr32_epilogue
1203
1204 .align  16
1205 .Lctr32_bulk:
1206         lea     (%rsp),$key_                    # use $key_ as frame pointer
1207 .cfi_def_cfa_register   $key_
1208         push    %rbp
1209 .cfi_push       %rbp
1210         sub     \$$frame_size,%rsp
1211         and     \$-16,%rsp      # Linux kernel stack can be incorrectly seeded
1212 ___
1213 $code.=<<___ if ($win64);
1214         movaps  %xmm6,-0xa8($key_)              # offload everything
1215         movaps  %xmm7,-0x98($key_)
1216         movaps  %xmm8,-0x88($key_)
1217         movaps  %xmm9,-0x78($key_)
1218         movaps  %xmm10,-0x68($key_)
1219         movaps  %xmm11,-0x58($key_)
1220         movaps  %xmm12,-0x48($key_)
1221         movaps  %xmm13,-0x38($key_)
1222         movaps  %xmm14,-0x28($key_)
1223         movaps  %xmm15,-0x18($key_)
1224 .Lctr32_body:
1225 ___
1226 $code.=<<___;
1227
1228         # 8 16-byte words on top of stack are counter values
1229         # xor-ed with zero-round key
1230
1231         movdqu  ($ivp),$inout0
1232         movdqu  ($key),$rndkey0
1233         mov     12($ivp),$ctr                   # counter LSB
1234         pxor    $rndkey0,$inout0
1235         mov     12($key),$key0                  # 0-round key LSB
1236         movdqa  $inout0,0x00(%rsp)              # populate counter block
1237         bswap   $ctr
1238         movdqa  $inout0,$inout1
1239         movdqa  $inout0,$inout2
1240         movdqa  $inout0,$inout3
1241         movdqa  $inout0,0x40(%rsp)
1242         movdqa  $inout0,0x50(%rsp)
1243         movdqa  $inout0,0x60(%rsp)
1244         mov     %rdx,%r10                       # about to borrow %rdx
1245         movdqa  $inout0,0x70(%rsp)
1246
1247         lea     1($ctr),%rax
1248          lea    2($ctr),%rdx
1249         bswap   %eax
1250          bswap  %edx
1251         xor     $key0,%eax
1252          xor    $key0,%edx
1253         pinsrd  \$3,%eax,$inout1
1254         lea     3($ctr),%rax
1255         movdqa  $inout1,0x10(%rsp)
1256          pinsrd \$3,%edx,$inout2
1257         bswap   %eax
1258          mov    %r10,%rdx                       # restore %rdx
1259          lea    4($ctr),%r10
1260          movdqa $inout2,0x20(%rsp)
1261         xor     $key0,%eax
1262          bswap  %r10d
1263         pinsrd  \$3,%eax,$inout3
1264          xor    $key0,%r10d
1265         movdqa  $inout3,0x30(%rsp)
1266         lea     5($ctr),%r9
1267          mov    %r10d,0x40+12(%rsp)
1268         bswap   %r9d
1269          lea    6($ctr),%r10
1270         mov     240($key),$rounds               # key->rounds
1271         xor     $key0,%r9d
1272          bswap  %r10d
1273         mov     %r9d,0x50+12(%rsp)
1274          xor    $key0,%r10d
1275         lea     7($ctr),%r9
1276          mov    %r10d,0x60+12(%rsp)
1277         bswap   %r9d
1278          mov    OPENSSL_ia32cap_P+4(%rip),%r10d
1279         xor     $key0,%r9d
1280          and    \$`1<<26|1<<22`,%r10d           # isolate XSAVE+MOVBE
1281         mov     %r9d,0x70+12(%rsp)
1282
1283         $movkey 0x10($key),$rndkey1
1284
1285         movdqa  0x40(%rsp),$inout4
1286         movdqa  0x50(%rsp),$inout5
1287
1288         cmp     \$8,$len                # $len is in blocks
1289         jb      .Lctr32_tail            # short input if ($len<8)
1290
1291         sub     \$6,$len                # $len is biased by -6
1292         cmp     \$`1<<22`,%r10d         # check for MOVBE without XSAVE
1293         je      .Lctr32_6x              # [which denotes Atom Silvermont]
1294
1295         lea     0x80($key),$key         # size optimization
1296         sub     \$2,$len                # $len is biased by -8
1297         jmp     .Lctr32_loop8
1298
1299 .align  16
1300 .Lctr32_6x:
1301         shl     \$4,$rounds
1302         mov     \$48,$rnds_
1303         bswap   $key0
1304         lea     32($key,$rounds),$key   # end of key schedule
1305         sub     %rax,%r10               # twisted $rounds
1306         jmp     .Lctr32_loop6
1307
1308 .align  16
1309 .Lctr32_loop6:
1310          add    \$6,$ctr                # next counter value
1311         $movkey -48($key,$rnds_),$rndkey0
1312         aesenc  $rndkey1,$inout0
1313          mov    $ctr,%eax
1314          xor    $key0,%eax
1315         aesenc  $rndkey1,$inout1
1316          movbe  %eax,`0x00+12`(%rsp)    # store next counter value
1317          lea    1($ctr),%eax
1318         aesenc  $rndkey1,$inout2
1319          xor    $key0,%eax
1320          movbe  %eax,`0x10+12`(%rsp)
1321         aesenc  $rndkey1,$inout3
1322          lea    2($ctr),%eax
1323          xor    $key0,%eax
1324         aesenc  $rndkey1,$inout4
1325          movbe  %eax,`0x20+12`(%rsp)
1326          lea    3($ctr),%eax
1327         aesenc  $rndkey1,$inout5
1328         $movkey -32($key,$rnds_),$rndkey1
1329          xor    $key0,%eax
1330
1331         aesenc  $rndkey0,$inout0
1332          movbe  %eax,`0x30+12`(%rsp)
1333          lea    4($ctr),%eax
1334         aesenc  $rndkey0,$inout1
1335          xor    $key0,%eax
1336          movbe  %eax,`0x40+12`(%rsp)
1337         aesenc  $rndkey0,$inout2
1338          lea    5($ctr),%eax
1339          xor    $key0,%eax
1340         aesenc  $rndkey0,$inout3
1341          movbe  %eax,`0x50+12`(%rsp)
1342          mov    %r10,%rax               # mov   $rnds_,$rounds
1343         aesenc  $rndkey0,$inout4
1344         aesenc  $rndkey0,$inout5
1345         $movkey -16($key,$rnds_),$rndkey0
1346
1347         call    .Lenc_loop6
1348
1349         movdqu  ($inp),$inout6          # load 6 input blocks
1350         movdqu  0x10($inp),$inout7
1351         movdqu  0x20($inp),$in0
1352         movdqu  0x30($inp),$in1
1353         movdqu  0x40($inp),$in2
1354         movdqu  0x50($inp),$in3
1355         lea     0x60($inp),$inp         # $inp+=6*16
1356         $movkey -64($key,$rnds_),$rndkey1
1357         pxor    $inout0,$inout6         # inp^=E(ctr)
1358         movaps  0x00(%rsp),$inout0      # load next counter [xor-ed with 0 round]
1359         pxor    $inout1,$inout7
1360         movaps  0x10(%rsp),$inout1
1361         pxor    $inout2,$in0
1362         movaps  0x20(%rsp),$inout2
1363         pxor    $inout3,$in1
1364         movaps  0x30(%rsp),$inout3
1365         pxor    $inout4,$in2
1366         movaps  0x40(%rsp),$inout4
1367         pxor    $inout5,$in3
1368         movaps  0x50(%rsp),$inout5
1369         movdqu  $inout6,($out)          # store 6 output blocks
1370         movdqu  $inout7,0x10($out)
1371         movdqu  $in0,0x20($out)
1372         movdqu  $in1,0x30($out)
1373         movdqu  $in2,0x40($out)
1374         movdqu  $in3,0x50($out)
1375         lea     0x60($out),$out         # $out+=6*16
1376
1377         sub     \$6,$len
1378         jnc     .Lctr32_loop6           # loop if $len-=6 didn't borrow
1379
1380         add     \$6,$len                # restore real remaining $len
1381         jz      .Lctr32_done            # done if ($len==0)
1382
1383         lea     -48($rnds_),$rounds
1384         lea     -80($key,$rnds_),$key   # restore $key
1385         neg     $rounds
1386         shr     \$4,$rounds             # restore $rounds
1387         jmp     .Lctr32_tail
1388
1389 .align  32
1390 .Lctr32_loop8:
1391          add            \$8,$ctr                # next counter value
1392         movdqa          0x60(%rsp),$inout6
1393         aesenc          $rndkey1,$inout0
1394          mov            $ctr,%r9d
1395         movdqa          0x70(%rsp),$inout7
1396         aesenc          $rndkey1,$inout1
1397          bswap          %r9d
1398         $movkey         0x20-0x80($key),$rndkey0
1399         aesenc          $rndkey1,$inout2
1400          xor            $key0,%r9d
1401          nop
1402         aesenc          $rndkey1,$inout3
1403          mov            %r9d,0x00+12(%rsp)      # store next counter value
1404          lea            1($ctr),%r9
1405         aesenc          $rndkey1,$inout4
1406         aesenc          $rndkey1,$inout5
1407         aesenc          $rndkey1,$inout6
1408         aesenc          $rndkey1,$inout7
1409         $movkey         0x30-0x80($key),$rndkey1
1410 ___
1411 for($i=2;$i<8;$i++) {
1412 my $rndkeyx = ($i&1)?$rndkey1:$rndkey0;
1413 $code.=<<___;
1414          bswap          %r9d
1415         aesenc          $rndkeyx,$inout0
1416         aesenc          $rndkeyx,$inout1
1417          xor            $key0,%r9d
1418          .byte          0x66,0x90
1419         aesenc          $rndkeyx,$inout2
1420         aesenc          $rndkeyx,$inout3
1421          mov            %r9d,`0x10*($i-1)`+12(%rsp)
1422          lea            $i($ctr),%r9
1423         aesenc          $rndkeyx,$inout4
1424         aesenc          $rndkeyx,$inout5
1425         aesenc          $rndkeyx,$inout6
1426         aesenc          $rndkeyx,$inout7
1427         $movkey         `0x20+0x10*$i`-0x80($key),$rndkeyx
1428 ___
1429 }
1430 $code.=<<___;
1431          bswap          %r9d
1432         aesenc          $rndkey0,$inout0
1433         aesenc          $rndkey0,$inout1
1434         aesenc          $rndkey0,$inout2
1435          xor            $key0,%r9d
1436          movdqu         0x00($inp),$in0         # start loading input
1437         aesenc          $rndkey0,$inout3
1438          mov            %r9d,0x70+12(%rsp)
1439          cmp            \$11,$rounds
1440         aesenc          $rndkey0,$inout4
1441         aesenc          $rndkey0,$inout5
1442         aesenc          $rndkey0,$inout6
1443         aesenc          $rndkey0,$inout7
1444         $movkey         0xa0-0x80($key),$rndkey0
1445
1446         jb              .Lctr32_enc_done
1447
1448         aesenc          $rndkey1,$inout0
1449         aesenc          $rndkey1,$inout1
1450         aesenc          $rndkey1,$inout2
1451         aesenc          $rndkey1,$inout3
1452         aesenc          $rndkey1,$inout4
1453         aesenc          $rndkey1,$inout5
1454         aesenc          $rndkey1,$inout6
1455         aesenc          $rndkey1,$inout7
1456         $movkey         0xb0-0x80($key),$rndkey1
1457
1458         aesenc          $rndkey0,$inout0
1459         aesenc          $rndkey0,$inout1
1460         aesenc          $rndkey0,$inout2
1461         aesenc          $rndkey0,$inout3
1462         aesenc          $rndkey0,$inout4
1463         aesenc          $rndkey0,$inout5
1464         aesenc          $rndkey0,$inout6
1465         aesenc          $rndkey0,$inout7
1466         $movkey         0xc0-0x80($key),$rndkey0
1467         je              .Lctr32_enc_done
1468
1469         aesenc          $rndkey1,$inout0
1470         aesenc          $rndkey1,$inout1
1471         aesenc          $rndkey1,$inout2
1472         aesenc          $rndkey1,$inout3
1473         aesenc          $rndkey1,$inout4
1474         aesenc          $rndkey1,$inout5
1475         aesenc          $rndkey1,$inout6
1476         aesenc          $rndkey1,$inout7
1477         $movkey         0xd0-0x80($key),$rndkey1
1478
1479         aesenc          $rndkey0,$inout0
1480         aesenc          $rndkey0,$inout1
1481         aesenc          $rndkey0,$inout2
1482         aesenc          $rndkey0,$inout3
1483         aesenc          $rndkey0,$inout4
1484         aesenc          $rndkey0,$inout5
1485         aesenc          $rndkey0,$inout6
1486         aesenc          $rndkey0,$inout7
1487         $movkey         0xe0-0x80($key),$rndkey0
1488         jmp             .Lctr32_enc_done
1489
1490 .align  16
1491 .Lctr32_enc_done:
1492         movdqu          0x10($inp),$in1
1493         pxor            $rndkey0,$in0           # input^=round[last]
1494         movdqu          0x20($inp),$in2
1495         pxor            $rndkey0,$in1
1496         movdqu          0x30($inp),$in3
1497         pxor            $rndkey0,$in2
1498         movdqu          0x40($inp),$in4
1499         pxor            $rndkey0,$in3
1500         movdqu          0x50($inp),$in5
1501         pxor            $rndkey0,$in4
1502         pxor            $rndkey0,$in5
1503         aesenc          $rndkey1,$inout0
1504         aesenc          $rndkey1,$inout1
1505         aesenc          $rndkey1,$inout2
1506         aesenc          $rndkey1,$inout3
1507         aesenc          $rndkey1,$inout4
1508         aesenc          $rndkey1,$inout5
1509         aesenc          $rndkey1,$inout6
1510         aesenc          $rndkey1,$inout7
1511         movdqu          0x60($inp),$rndkey1     # borrow $rndkey1 for inp[6]
1512         lea             0x80($inp),$inp         # $inp+=8*16
1513
1514         aesenclast      $in0,$inout0            # $inN is inp[N]^round[last]
1515         pxor            $rndkey0,$rndkey1       # borrowed $rndkey
1516         movdqu          0x70-0x80($inp),$in0
1517         aesenclast      $in1,$inout1
1518         pxor            $rndkey0,$in0
1519         movdqa          0x00(%rsp),$in1         # load next counter block
1520         aesenclast      $in2,$inout2
1521         aesenclast      $in3,$inout3
1522         movdqa          0x10(%rsp),$in2
1523         movdqa          0x20(%rsp),$in3
1524         aesenclast      $in4,$inout4
1525         aesenclast      $in5,$inout5
1526         movdqa          0x30(%rsp),$in4
1527         movdqa          0x40(%rsp),$in5
1528         aesenclast      $rndkey1,$inout6
1529         movdqa          0x50(%rsp),$rndkey0
1530         $movkey         0x10-0x80($key),$rndkey1#real 1st-round key
1531         aesenclast      $in0,$inout7
1532
1533         movups          $inout0,($out)          # store 8 output blocks
1534         movdqa          $in1,$inout0
1535         movups          $inout1,0x10($out)
1536         movdqa          $in2,$inout1
1537         movups          $inout2,0x20($out)
1538         movdqa          $in3,$inout2
1539         movups          $inout3,0x30($out)
1540         movdqa          $in4,$inout3
1541         movups          $inout4,0x40($out)
1542         movdqa          $in5,$inout4
1543         movups          $inout5,0x50($out)
1544         movdqa          $rndkey0,$inout5
1545         movups          $inout6,0x60($out)
1546         movups          $inout7,0x70($out)
1547         lea             0x80($out),$out         # $out+=8*16
1548
1549         sub     \$8,$len
1550         jnc     .Lctr32_loop8                   # loop if $len-=8 didn't borrow
1551
1552         add     \$8,$len                        # restore real remainig $len
1553         jz      .Lctr32_done                    # done if ($len==0)
1554         lea     -0x80($key),$key
1555
1556 .Lctr32_tail:
1557         # note that at this point $inout0..5 are populated with
1558         # counter values xor-ed with 0-round key
1559         lea     16($key),$key
1560         cmp     \$4,$len
1561         jb      .Lctr32_loop3
1562         je      .Lctr32_loop4
1563
1564         # if ($len>4) compute 7 E(counter)
1565         shl             \$4,$rounds
1566         movdqa          0x60(%rsp),$inout6
1567         pxor            $inout7,$inout7
1568
1569         $movkey         16($key),$rndkey0
1570         aesenc          $rndkey1,$inout0
1571         aesenc          $rndkey1,$inout1
1572         lea             32-16($key,$rounds),$key# prepare for .Lenc_loop8_enter
1573         neg             %rax
1574         aesenc          $rndkey1,$inout2
1575         add             \$16,%rax               # prepare for .Lenc_loop8_enter
1576          movups         ($inp),$in0
1577         aesenc          $rndkey1,$inout3
1578         aesenc          $rndkey1,$inout4
1579          movups         0x10($inp),$in1         # pre-load input
1580          movups         0x20($inp),$in2
1581         aesenc          $rndkey1,$inout5
1582         aesenc          $rndkey1,$inout6
1583
1584         call            .Lenc_loop8_enter
1585
1586         movdqu  0x30($inp),$in3
1587         pxor    $in0,$inout0
1588         movdqu  0x40($inp),$in0
1589         pxor    $in1,$inout1
1590         movdqu  $inout0,($out)                  # store output
1591         pxor    $in2,$inout2
1592         movdqu  $inout1,0x10($out)
1593         pxor    $in3,$inout3
1594         movdqu  $inout2,0x20($out)
1595         pxor    $in0,$inout4
1596         movdqu  $inout3,0x30($out)
1597         movdqu  $inout4,0x40($out)
1598         cmp     \$6,$len
1599         jb      .Lctr32_done                    # $len was 5, stop store
1600
1601         movups  0x50($inp),$in1
1602         xorps   $in1,$inout5
1603         movups  $inout5,0x50($out)
1604         je      .Lctr32_done                    # $len was 6, stop store
1605
1606         movups  0x60($inp),$in2
1607         xorps   $in2,$inout6
1608         movups  $inout6,0x60($out)
1609         jmp     .Lctr32_done                    # $len was 7, stop store
1610
1611 .align  32
1612 .Lctr32_loop4:
1613         aesenc          $rndkey1,$inout0
1614         lea             16($key),$key
1615         dec             $rounds
1616         aesenc          $rndkey1,$inout1
1617         aesenc          $rndkey1,$inout2
1618         aesenc          $rndkey1,$inout3
1619         $movkey         ($key),$rndkey1
1620         jnz             .Lctr32_loop4
1621         aesenclast      $rndkey1,$inout0
1622         aesenclast      $rndkey1,$inout1
1623          movups         ($inp),$in0             # load input
1624          movups         0x10($inp),$in1
1625         aesenclast      $rndkey1,$inout2
1626         aesenclast      $rndkey1,$inout3
1627          movups         0x20($inp),$in2
1628          movups         0x30($inp),$in3
1629
1630         xorps   $in0,$inout0
1631         movups  $inout0,($out)                  # store output
1632         xorps   $in1,$inout1
1633         movups  $inout1,0x10($out)
1634         pxor    $in2,$inout2
1635         movdqu  $inout2,0x20($out)
1636         pxor    $in3,$inout3
1637         movdqu  $inout3,0x30($out)
1638         jmp     .Lctr32_done                    # $len was 4, stop store
1639
1640 .align  32
1641 .Lctr32_loop3:
1642         aesenc          $rndkey1,$inout0
1643         lea             16($key),$key
1644         dec             $rounds
1645         aesenc          $rndkey1,$inout1
1646         aesenc          $rndkey1,$inout2
1647         $movkey         ($key),$rndkey1
1648         jnz             .Lctr32_loop3
1649         aesenclast      $rndkey1,$inout0
1650         aesenclast      $rndkey1,$inout1
1651         aesenclast      $rndkey1,$inout2
1652
1653         movups  ($inp),$in0                     # load input
1654         xorps   $in0,$inout0
1655         movups  $inout0,($out)                  # store output
1656         cmp     \$2,$len
1657         jb      .Lctr32_done                    # $len was 1, stop store
1658
1659         movups  0x10($inp),$in1
1660         xorps   $in1,$inout1
1661         movups  $inout1,0x10($out)
1662         je      .Lctr32_done                    # $len was 2, stop store
1663
1664         movups  0x20($inp),$in2
1665         xorps   $in2,$inout2
1666         movups  $inout2,0x20($out)              # $len was 3, stop store
1667
1668 .Lctr32_done:
1669         xorps   %xmm0,%xmm0                     # clear regiser bank
1670         xor     $key0,$key0
1671         pxor    %xmm1,%xmm1
1672         pxor    %xmm2,%xmm2
1673         pxor    %xmm3,%xmm3
1674         pxor    %xmm4,%xmm4
1675         pxor    %xmm5,%xmm5
1676 ___
1677 $code.=<<___ if (!$win64);
1678         pxor    %xmm6,%xmm6
1679         pxor    %xmm7,%xmm7
1680         movaps  %xmm0,0x00(%rsp)                # clear stack
1681         pxor    %xmm8,%xmm8
1682         movaps  %xmm0,0x10(%rsp)
1683         pxor    %xmm9,%xmm9
1684         movaps  %xmm0,0x20(%rsp)
1685         pxor    %xmm10,%xmm10
1686         movaps  %xmm0,0x30(%rsp)
1687         pxor    %xmm11,%xmm11
1688         movaps  %xmm0,0x40(%rsp)
1689         pxor    %xmm12,%xmm12
1690         movaps  %xmm0,0x50(%rsp)
1691         pxor    %xmm13,%xmm13
1692         movaps  %xmm0,0x60(%rsp)
1693         pxor    %xmm14,%xmm14
1694         movaps  %xmm0,0x70(%rsp)
1695         pxor    %xmm15,%xmm15
1696 ___
1697 $code.=<<___ if ($win64);
1698         movaps  -0xa8($key_),%xmm6
1699         movaps  %xmm0,-0xa8($key_)              # clear stack
1700         movaps  -0x98($key_),%xmm7
1701         movaps  %xmm0,-0x98($key_)
1702         movaps  -0x88($key_),%xmm8
1703         movaps  %xmm0,-0x88($key_)
1704         movaps  -0x78($key_),%xmm9
1705         movaps  %xmm0,-0x78($key_)
1706         movaps  -0x68($key_),%xmm10
1707         movaps  %xmm0,-0x68($key_)
1708         movaps  -0x58($key_),%xmm11
1709         movaps  %xmm0,-0x58($key_)
1710         movaps  -0x48($key_),%xmm12
1711         movaps  %xmm0,-0x48($key_)
1712         movaps  -0x38($key_),%xmm13
1713         movaps  %xmm0,-0x38($key_)
1714         movaps  -0x28($key_),%xmm14
1715         movaps  %xmm0,-0x28($key_)
1716         movaps  -0x18($key_),%xmm15
1717         movaps  %xmm0,-0x18($key_)
1718         movaps  %xmm0,0x00(%rsp)
1719         movaps  %xmm0,0x10(%rsp)
1720         movaps  %xmm0,0x20(%rsp)
1721         movaps  %xmm0,0x30(%rsp)
1722         movaps  %xmm0,0x40(%rsp)
1723         movaps  %xmm0,0x50(%rsp)
1724         movaps  %xmm0,0x60(%rsp)
1725         movaps  %xmm0,0x70(%rsp)
1726 ___
1727 $code.=<<___;
1728         mov     -8($key_),%rbp
1729 .cfi_restore    %rbp
1730         lea     ($key_),%rsp
1731 .cfi_def_cfa_register   %rsp
1732 .Lctr32_epilogue:
1733         ret
1734 .cfi_endproc
1735 .size   aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks
1736 ___
1737 }
1738 \f
1739 ######################################################################
1740 # void aesni_xts_[en|de]crypt(const char *inp,char *out,size_t len,
1741 #       const AES_KEY *key1, const AES_KEY *key2
1742 #       const unsigned char iv[16]);
1743 #
1744 {
1745 my @tweak=map("%xmm$_",(10..15));
1746 my ($twmask,$twres,$twtmp)=("%xmm8","%xmm9",@tweak[4]);
1747 my ($key2,$ivp,$len_)=("%r8","%r9","%r9");
1748 my $frame_size = 0x70 + ($win64?160:0);
1749 my $key_ = "%rbp";      # override so that we can use %r11 as FP
1750
1751 $code.=<<___;
1752 .globl  aesni_xts_encrypt
1753 .type   aesni_xts_encrypt,\@function,6
1754 .align  16
1755 aesni_xts_encrypt:
1756 .cfi_startproc
1757         lea     (%rsp),%r11                     # frame pointer
1758 .cfi_def_cfa_register   %r11
1759         push    %rbp
1760 .cfi_push       %rbp
1761         sub     \$$frame_size,%rsp
1762         and     \$-16,%rsp      # Linux kernel stack can be incorrectly seeded
1763 ___
1764 $code.=<<___ if ($win64);
1765         movaps  %xmm6,-0xa8(%r11)               # offload everything
1766         movaps  %xmm7,-0x98(%r11)
1767         movaps  %xmm8,-0x88(%r11)
1768         movaps  %xmm9,-0x78(%r11)
1769         movaps  %xmm10,-0x68(%r11)
1770         movaps  %xmm11,-0x58(%r11)
1771         movaps  %xmm12,-0x48(%r11)
1772         movaps  %xmm13,-0x38(%r11)
1773         movaps  %xmm14,-0x28(%r11)
1774         movaps  %xmm15,-0x18(%r11)
1775 .Lxts_enc_body:
1776 ___
1777 $code.=<<___;
1778         movups  ($ivp),$inout0                  # load clear-text tweak
1779         mov     240(%r8),$rounds                # key2->rounds
1780         mov     240($key),$rnds_                # key1->rounds
1781 ___
1782         # generate the tweak
1783         &aesni_generate1("enc",$key2,$rounds,$inout0);
1784 $code.=<<___;
1785         $movkey ($key),$rndkey0                 # zero round key
1786         mov     $key,$key_                      # backup $key
1787         mov     $rnds_,$rounds                  # backup $rounds
1788         shl     \$4,$rnds_
1789         mov     $len,$len_                      # backup $len
1790         and     \$-16,$len
1791
1792         $movkey 16($key,$rnds_),$rndkey1        # last round key
1793
1794         movdqa  .Lxts_magic(%rip),$twmask
1795         movdqa  $inout0,@tweak[5]
1796         pshufd  \$0x5f,$inout0,$twres
1797         pxor    $rndkey0,$rndkey1
1798 ___
1799     # alternative tweak calculation algorithm is based on suggestions
1800     # by Shay Gueron. psrad doesn't conflict with AES-NI instructions
1801     # and should help in the future...
1802     for ($i=0;$i<4;$i++) {
1803     $code.=<<___;
1804         movdqa  $twres,$twtmp
1805         paddd   $twres,$twres
1806         movdqa  @tweak[5],@tweak[$i]
1807         psrad   \$31,$twtmp                     # broadcast upper bits
1808         paddq   @tweak[5],@tweak[5]
1809         pand    $twmask,$twtmp
1810         pxor    $rndkey0,@tweak[$i]
1811         pxor    $twtmp,@tweak[5]
1812 ___
1813     }
1814 $code.=<<___;
1815         movdqa  @tweak[5],@tweak[4]
1816         psrad   \$31,$twres
1817         paddq   @tweak[5],@tweak[5]
1818         pand    $twmask,$twres
1819         pxor    $rndkey0,@tweak[4]
1820         pxor    $twres,@tweak[5]
1821         movaps  $rndkey1,0x60(%rsp)             # save round[0]^round[last]
1822
1823         sub     \$16*6,$len
1824         jc      .Lxts_enc_short                 # if $len-=6*16 borrowed
1825
1826         mov     \$16+96,$rounds
1827         lea     32($key_,$rnds_),$key           # end of key schedule
1828         sub     %r10,%rax                       # twisted $rounds
1829         $movkey 16($key_),$rndkey1
1830         mov     %rax,%r10                       # backup twisted $rounds
1831         lea     .Lxts_magic(%rip),%r8
1832         jmp     .Lxts_enc_grandloop
1833
1834 .align  32
1835 .Lxts_enc_grandloop:
1836         movdqu  `16*0`($inp),$inout0            # load input
1837         movdqa  $rndkey0,$twmask
1838         movdqu  `16*1`($inp),$inout1
1839         pxor    @tweak[0],$inout0               # input^=tweak^round[0]
1840         movdqu  `16*2`($inp),$inout2
1841         pxor    @tweak[1],$inout1
1842          aesenc         $rndkey1,$inout0
1843         movdqu  `16*3`($inp),$inout3
1844         pxor    @tweak[2],$inout2
1845          aesenc         $rndkey1,$inout1
1846         movdqu  `16*4`($inp),$inout4
1847         pxor    @tweak[3],$inout3
1848          aesenc         $rndkey1,$inout2
1849         movdqu  `16*5`($inp),$inout5
1850         pxor    @tweak[5],$twmask               # round[0]^=tweak[5]
1851          movdqa 0x60(%rsp),$twres               # load round[0]^round[last]
1852         pxor    @tweak[4],$inout4
1853          aesenc         $rndkey1,$inout3
1854         $movkey 32($key_),$rndkey0
1855         lea     `16*6`($inp),$inp
1856         pxor    $twmask,$inout5
1857
1858          pxor   $twres,@tweak[0]                # calclulate tweaks^round[last]
1859         aesenc          $rndkey1,$inout4
1860          pxor   $twres,@tweak[1]
1861          movdqa @tweak[0],`16*0`(%rsp)          # put aside tweaks^round[last]
1862         aesenc          $rndkey1,$inout5
1863         $movkey         48($key_),$rndkey1
1864          pxor   $twres,@tweak[2]
1865
1866         aesenc          $rndkey0,$inout0
1867          pxor   $twres,@tweak[3]
1868          movdqa @tweak[1],`16*1`(%rsp)
1869         aesenc          $rndkey0,$inout1
1870          pxor   $twres,@tweak[4]
1871          movdqa @tweak[2],`16*2`(%rsp)
1872         aesenc          $rndkey0,$inout2
1873         aesenc          $rndkey0,$inout3
1874          pxor   $twres,$twmask
1875          movdqa @tweak[4],`16*4`(%rsp)
1876         aesenc          $rndkey0,$inout4
1877         aesenc          $rndkey0,$inout5
1878         $movkey         64($key_),$rndkey0
1879          movdqa $twmask,`16*5`(%rsp)
1880         pshufd  \$0x5f,@tweak[5],$twres
1881         jmp     .Lxts_enc_loop6
1882 .align  32
1883 .Lxts_enc_loop6:
1884         aesenc          $rndkey1,$inout0
1885         aesenc          $rndkey1,$inout1
1886         aesenc          $rndkey1,$inout2
1887         aesenc          $rndkey1,$inout3
1888         aesenc          $rndkey1,$inout4
1889         aesenc          $rndkey1,$inout5
1890         $movkey         -64($key,%rax),$rndkey1
1891         add             \$32,%rax
1892
1893         aesenc          $rndkey0,$inout0
1894         aesenc          $rndkey0,$inout1
1895         aesenc          $rndkey0,$inout2
1896         aesenc          $rndkey0,$inout3
1897         aesenc          $rndkey0,$inout4
1898         aesenc          $rndkey0,$inout5
1899         $movkey         -80($key,%rax),$rndkey0
1900         jnz             .Lxts_enc_loop6
1901
1902         movdqa  (%r8),$twmask                   # start calculating next tweak
1903         movdqa  $twres,$twtmp
1904         paddd   $twres,$twres
1905          aesenc         $rndkey1,$inout0
1906         paddq   @tweak[5],@tweak[5]
1907         psrad   \$31,$twtmp
1908          aesenc         $rndkey1,$inout1
1909         pand    $twmask,$twtmp
1910         $movkey ($key_),@tweak[0]               # load round[0]
1911          aesenc         $rndkey1,$inout2
1912          aesenc         $rndkey1,$inout3
1913          aesenc         $rndkey1,$inout4
1914         pxor    $twtmp,@tweak[5]
1915         movaps  @tweak[0],@tweak[1]             # copy round[0]
1916          aesenc         $rndkey1,$inout5
1917          $movkey        -64($key),$rndkey1
1918
1919         movdqa  $twres,$twtmp
1920          aesenc         $rndkey0,$inout0
1921         paddd   $twres,$twres
1922         pxor    @tweak[5],@tweak[0]
1923          aesenc         $rndkey0,$inout1
1924         psrad   \$31,$twtmp
1925         paddq   @tweak[5],@tweak[5]
1926          aesenc         $rndkey0,$inout2
1927          aesenc         $rndkey0,$inout3
1928         pand    $twmask,$twtmp
1929         movaps  @tweak[1],@tweak[2]
1930          aesenc         $rndkey0,$inout4
1931         pxor    $twtmp,@tweak[5]
1932         movdqa  $twres,$twtmp
1933          aesenc         $rndkey0,$inout5
1934          $movkey        -48($key),$rndkey0
1935
1936         paddd   $twres,$twres
1937          aesenc         $rndkey1,$inout0
1938         pxor    @tweak[5],@tweak[1]
1939         psrad   \$31,$twtmp
1940          aesenc         $rndkey1,$inout1
1941         paddq   @tweak[5],@tweak[5]
1942         pand    $twmask,$twtmp
1943          aesenc         $rndkey1,$inout2
1944          aesenc         $rndkey1,$inout3
1945          movdqa @tweak[3],`16*3`(%rsp)
1946         pxor    $twtmp,@tweak[5]
1947          aesenc         $rndkey1,$inout4
1948         movaps  @tweak[2],@tweak[3]
1949         movdqa  $twres,$twtmp
1950          aesenc         $rndkey1,$inout5
1951          $movkey        -32($key),$rndkey1
1952
1953         paddd   $twres,$twres
1954          aesenc         $rndkey0,$inout0
1955         pxor    @tweak[5],@tweak[2]
1956         psrad   \$31,$twtmp
1957          aesenc         $rndkey0,$inout1
1958         paddq   @tweak[5],@tweak[5]
1959         pand    $twmask,$twtmp
1960          aesenc         $rndkey0,$inout2
1961          aesenc         $rndkey0,$inout3
1962          aesenc         $rndkey0,$inout4
1963         pxor    $twtmp,@tweak[5]
1964         movaps  @tweak[3],@tweak[4]
1965          aesenc         $rndkey0,$inout5
1966
1967         movdqa  $twres,$rndkey0
1968         paddd   $twres,$twres
1969          aesenc         $rndkey1,$inout0
1970         pxor    @tweak[5],@tweak[3]
1971         psrad   \$31,$rndkey0
1972          aesenc         $rndkey1,$inout1
1973         paddq   @tweak[5],@tweak[5]
1974         pand    $twmask,$rndkey0
1975          aesenc         $rndkey1,$inout2
1976          aesenc         $rndkey1,$inout3
1977         pxor    $rndkey0,@tweak[5]
1978         $movkey         ($key_),$rndkey0
1979          aesenc         $rndkey1,$inout4
1980          aesenc         $rndkey1,$inout5
1981         $movkey         16($key_),$rndkey1
1982
1983         pxor    @tweak[5],@tweak[4]
1984          aesenclast     `16*0`(%rsp),$inout0
1985         psrad   \$31,$twres
1986         paddq   @tweak[5],@tweak[5]
1987          aesenclast     `16*1`(%rsp),$inout1
1988          aesenclast     `16*2`(%rsp),$inout2
1989         pand    $twmask,$twres
1990         mov     %r10,%rax                       # restore $rounds
1991          aesenclast     `16*3`(%rsp),$inout3
1992          aesenclast     `16*4`(%rsp),$inout4
1993          aesenclast     `16*5`(%rsp),$inout5
1994         pxor    $twres,@tweak[5]
1995
1996         lea     `16*6`($out),$out               # $out+=6*16
1997         movups  $inout0,`-16*6`($out)           # store 6 output blocks
1998         movups  $inout1,`-16*5`($out)
1999         movups  $inout2,`-16*4`($out)
2000         movups  $inout3,`-16*3`($out)
2001         movups  $inout4,`-16*2`($out)
2002         movups  $inout5,`-16*1`($out)
2003         sub     \$16*6,$len
2004         jnc     .Lxts_enc_grandloop             # loop if $len-=6*16 didn't borrow
2005
2006         mov     \$16+96,$rounds
2007         sub     $rnds_,$rounds
2008         mov     $key_,$key                      # restore $key
2009         shr     \$4,$rounds                     # restore original value
2010
2011 .Lxts_enc_short:
2012         # at the point @tweak[0..5] are populated with tweak values
2013         mov     $rounds,$rnds_                  # backup $rounds
2014         pxor    $rndkey0,@tweak[0]
2015         add     \$16*6,$len                     # restore real remaining $len
2016         jz      .Lxts_enc_done                  # done if ($len==0)
2017
2018         pxor    $rndkey0,@tweak[1]
2019         cmp     \$0x20,$len
2020         jb      .Lxts_enc_one                   # $len is 1*16
2021         pxor    $rndkey0,@tweak[2]
2022         je      .Lxts_enc_two                   # $len is 2*16
2023
2024         pxor    $rndkey0,@tweak[3]
2025         cmp     \$0x40,$len
2026         jb      .Lxts_enc_three                 # $len is 3*16
2027         pxor    $rndkey0,@tweak[4]
2028         je      .Lxts_enc_four                  # $len is 4*16
2029
2030         movdqu  ($inp),$inout0                  # $len is 5*16
2031         movdqu  16*1($inp),$inout1
2032         movdqu  16*2($inp),$inout2
2033         pxor    @tweak[0],$inout0
2034         movdqu  16*3($inp),$inout3
2035         pxor    @tweak[1],$inout1
2036         movdqu  16*4($inp),$inout4
2037         lea     16*5($inp),$inp                 # $inp+=5*16
2038         pxor    @tweak[2],$inout2
2039         pxor    @tweak[3],$inout3
2040         pxor    @tweak[4],$inout4
2041         pxor    $inout5,$inout5
2042
2043         call    _aesni_encrypt6
2044
2045         xorps   @tweak[0],$inout0
2046         movdqa  @tweak[5],@tweak[0]
2047         xorps   @tweak[1],$inout1
2048         xorps   @tweak[2],$inout2
2049         movdqu  $inout0,($out)                  # store 5 output blocks
2050         xorps   @tweak[3],$inout3
2051         movdqu  $inout1,16*1($out)
2052         xorps   @tweak[4],$inout4
2053         movdqu  $inout2,16*2($out)
2054         movdqu  $inout3,16*3($out)
2055         movdqu  $inout4,16*4($out)
2056         lea     16*5($out),$out                 # $out+=5*16
2057         jmp     .Lxts_enc_done
2058
2059 .align  16
2060 .Lxts_enc_one:
2061         movups  ($inp),$inout0
2062         lea     16*1($inp),$inp                 # inp+=1*16
2063         xorps   @tweak[0],$inout0
2064 ___
2065         &aesni_generate1("enc",$key,$rounds);
2066 $code.=<<___;
2067         xorps   @tweak[0],$inout0
2068         movdqa  @tweak[1],@tweak[0]
2069         movups  $inout0,($out)                  # store one output block
2070         lea     16*1($out),$out                 # $out+=1*16
2071         jmp     .Lxts_enc_done
2072
2073 .align  16
2074 .Lxts_enc_two:
2075         movups  ($inp),$inout0
2076         movups  16($inp),$inout1
2077         lea     32($inp),$inp                   # $inp+=2*16
2078         xorps   @tweak[0],$inout0
2079         xorps   @tweak[1],$inout1
2080
2081         call    _aesni_encrypt2
2082
2083         xorps   @tweak[0],$inout0
2084         movdqa  @tweak[2],@tweak[0]
2085         xorps   @tweak[1],$inout1
2086         movups  $inout0,($out)                  # store 2 output blocks
2087         movups  $inout1,16*1($out)
2088         lea     16*2($out),$out                 # $out+=2*16
2089         jmp     .Lxts_enc_done
2090
2091 .align  16
2092 .Lxts_enc_three:
2093         movups  ($inp),$inout0
2094         movups  16*1($inp),$inout1
2095         movups  16*2($inp),$inout2
2096         lea     16*3($inp),$inp                 # $inp+=3*16
2097         xorps   @tweak[0],$inout0
2098         xorps   @tweak[1],$inout1
2099         xorps   @tweak[2],$inout2
2100
2101         call    _aesni_encrypt3
2102
2103         xorps   @tweak[0],$inout0
2104         movdqa  @tweak[3],@tweak[0]
2105         xorps   @tweak[1],$inout1
2106         xorps   @tweak[2],$inout2
2107         movups  $inout0,($out)                  # store 3 output blocks
2108         movups  $inout1,16*1($out)
2109         movups  $inout2,16*2($out)
2110         lea     16*3($out),$out                 # $out+=3*16
2111         jmp     .Lxts_enc_done
2112
2113 .align  16
2114 .Lxts_enc_four:
2115         movups  ($inp),$inout0
2116         movups  16*1($inp),$inout1
2117         movups  16*2($inp),$inout2
2118         xorps   @tweak[0],$inout0
2119         movups  16*3($inp),$inout3
2120         lea     16*4($inp),$inp                 # $inp+=4*16
2121         xorps   @tweak[1],$inout1
2122         xorps   @tweak[2],$inout2
2123         xorps   @tweak[3],$inout3
2124
2125         call    _aesni_encrypt4
2126
2127         pxor    @tweak[0],$inout0
2128         movdqa  @tweak[4],@tweak[0]
2129         pxor    @tweak[1],$inout1
2130         pxor    @tweak[2],$inout2
2131         movdqu  $inout0,($out)                  # store 4 output blocks
2132         pxor    @tweak[3],$inout3
2133         movdqu  $inout1,16*1($out)
2134         movdqu  $inout2,16*2($out)
2135         movdqu  $inout3,16*3($out)
2136         lea     16*4($out),$out                 # $out+=4*16
2137         jmp     .Lxts_enc_done
2138
2139 .align  16
2140 .Lxts_enc_done:
2141         and     \$15,$len_                      # see if $len%16 is 0
2142         jz      .Lxts_enc_ret
2143         mov     $len_,$len
2144
2145 .Lxts_enc_steal:
2146         movzb   ($inp),%eax                     # borrow $rounds ...
2147         movzb   -16($out),%ecx                  # ... and $key
2148         lea     1($inp),$inp
2149         mov     %al,-16($out)
2150         mov     %cl,0($out)
2151         lea     1($out),$out
2152         sub     \$1,$len
2153         jnz     .Lxts_enc_steal
2154
2155         sub     $len_,$out                      # rewind $out
2156         mov     $key_,$key                      # restore $key
2157         mov     $rnds_,$rounds                  # restore $rounds
2158
2159         movups  -16($out),$inout0
2160         xorps   @tweak[0],$inout0
2161 ___
2162         &aesni_generate1("enc",$key,$rounds);
2163 $code.=<<___;
2164         xorps   @tweak[0],$inout0
2165         movups  $inout0,-16($out)
2166
2167 .Lxts_enc_ret:
2168         xorps   %xmm0,%xmm0                     # clear register bank
2169         pxor    %xmm1,%xmm1
2170         pxor    %xmm2,%xmm2
2171         pxor    %xmm3,%xmm3
2172         pxor    %xmm4,%xmm4
2173         pxor    %xmm5,%xmm5
2174 ___
2175 $code.=<<___ if (!$win64);
2176         pxor    %xmm6,%xmm6
2177         pxor    %xmm7,%xmm7
2178         movaps  %xmm0,0x00(%rsp)                # clear stack
2179         pxor    %xmm8,%xmm8
2180         movaps  %xmm0,0x10(%rsp)
2181         pxor    %xmm9,%xmm9
2182         movaps  %xmm0,0x20(%rsp)
2183         pxor    %xmm10,%xmm10
2184         movaps  %xmm0,0x30(%rsp)
2185         pxor    %xmm11,%xmm11
2186         movaps  %xmm0,0x40(%rsp)
2187         pxor    %xmm12,%xmm12
2188         movaps  %xmm0,0x50(%rsp)
2189         pxor    %xmm13,%xmm13
2190         movaps  %xmm0,0x60(%rsp)
2191         pxor    %xmm14,%xmm14
2192         pxor    %xmm15,%xmm15
2193 ___
2194 $code.=<<___ if ($win64);
2195         movaps  -0xa8(%r11),%xmm6
2196         movaps  %xmm0,-0xa8(%r11)               # clear stack
2197         movaps  -0x98(%r11),%xmm7
2198         movaps  %xmm0,-0x98(%r11)
2199         movaps  -0x88(%r11),%xmm8
2200         movaps  %xmm0,-0x88(%r11)
2201         movaps  -0x78(%r11),%xmm9
2202         movaps  %xmm0,-0x78(%r11)
2203         movaps  -0x68(%r11),%xmm10
2204         movaps  %xmm0,-0x68(%r11)
2205         movaps  -0x58(%r11),%xmm11
2206         movaps  %xmm0,-0x58(%r11)
2207         movaps  -0x48(%r11),%xmm12
2208         movaps  %xmm0,-0x48(%r11)
2209         movaps  -0x38(%r11),%xmm13
2210         movaps  %xmm0,-0x38(%r11)
2211         movaps  -0x28(%r11),%xmm14
2212         movaps  %xmm0,-0x28(%r11)
2213         movaps  -0x18(%r11),%xmm15
2214         movaps  %xmm0,-0x18(%r11)
2215         movaps  %xmm0,0x00(%rsp)
2216         movaps  %xmm0,0x10(%rsp)
2217         movaps  %xmm0,0x20(%rsp)
2218         movaps  %xmm0,0x30(%rsp)
2219         movaps  %xmm0,0x40(%rsp)
2220         movaps  %xmm0,0x50(%rsp)
2221         movaps  %xmm0,0x60(%rsp)
2222 ___
2223 $code.=<<___;
2224         mov     -8(%r11),%rbp
2225 .cfi_restore    %rbp
2226         lea     (%r11),%rsp
2227 .cfi_def_cfa_register   %rsp
2228 .Lxts_enc_epilogue:
2229         ret
2230 .cfi_endproc
2231 .size   aesni_xts_encrypt,.-aesni_xts_encrypt
2232 ___
2233
2234 $code.=<<___;
2235 .globl  aesni_xts_decrypt
2236 .type   aesni_xts_decrypt,\@function,6
2237 .align  16
2238 aesni_xts_decrypt:
2239 .cfi_startproc
2240         lea     (%rsp),%r11                     # frame pointer
2241 .cfi_def_cfa_register   %r11
2242         push    %rbp
2243 .cfi_push       %rbp
2244         sub     \$$frame_size,%rsp
2245         and     \$-16,%rsp      # Linux kernel stack can be incorrectly seeded
2246 ___
2247 $code.=<<___ if ($win64);
2248         movaps  %xmm6,-0xa8(%r11)               # offload everything
2249         movaps  %xmm7,-0x98(%r11)
2250         movaps  %xmm8,-0x88(%r11)
2251         movaps  %xmm9,-0x78(%r11)
2252         movaps  %xmm10,-0x68(%r11)
2253         movaps  %xmm11,-0x58(%r11)
2254         movaps  %xmm12,-0x48(%r11)
2255         movaps  %xmm13,-0x38(%r11)
2256         movaps  %xmm14,-0x28(%r11)
2257         movaps  %xmm15,-0x18(%r11)
2258 .Lxts_dec_body:
2259 ___
2260 $code.=<<___;
2261         movups  ($ivp),$inout0                  # load clear-text tweak
2262         mov     240($key2),$rounds              # key2->rounds
2263         mov     240($key),$rnds_                # key1->rounds
2264 ___
2265         # generate the tweak
2266         &aesni_generate1("enc",$key2,$rounds,$inout0);
2267 $code.=<<___;
2268         xor     %eax,%eax                       # if ($len%16) len-=16;
2269         test    \$15,$len
2270         setnz   %al
2271         shl     \$4,%rax
2272         sub     %rax,$len
2273
2274         $movkey ($key),$rndkey0                 # zero round key
2275         mov     $key,$key_                      # backup $key
2276         mov     $rnds_,$rounds                  # backup $rounds
2277         shl     \$4,$rnds_
2278         mov     $len,$len_                      # backup $len
2279         and     \$-16,$len
2280
2281         $movkey 16($key,$rnds_),$rndkey1        # last round key
2282
2283         movdqa  .Lxts_magic(%rip),$twmask
2284         movdqa  $inout0,@tweak[5]
2285         pshufd  \$0x5f,$inout0,$twres
2286         pxor    $rndkey0,$rndkey1
2287 ___
2288     for ($i=0;$i<4;$i++) {
2289     $code.=<<___;
2290         movdqa  $twres,$twtmp
2291         paddd   $twres,$twres
2292         movdqa  @tweak[5],@tweak[$i]
2293         psrad   \$31,$twtmp                     # broadcast upper bits
2294         paddq   @tweak[5],@tweak[5]
2295         pand    $twmask,$twtmp
2296         pxor    $rndkey0,@tweak[$i]
2297         pxor    $twtmp,@tweak[5]
2298 ___
2299     }
2300 $code.=<<___;
2301         movdqa  @tweak[5],@tweak[4]
2302         psrad   \$31,$twres
2303         paddq   @tweak[5],@tweak[5]
2304         pand    $twmask,$twres
2305         pxor    $rndkey0,@tweak[4]
2306         pxor    $twres,@tweak[5]
2307         movaps  $rndkey1,0x60(%rsp)             # save round[0]^round[last]
2308
2309         sub     \$16*6,$len
2310         jc      .Lxts_dec_short                 # if $len-=6*16 borrowed
2311
2312         mov     \$16+96,$rounds
2313         lea     32($key_,$rnds_),$key           # end of key schedule
2314         sub     %r10,%rax                       # twisted $rounds
2315         $movkey 16($key_),$rndkey1
2316         mov     %rax,%r10                       # backup twisted $rounds
2317         lea     .Lxts_magic(%rip),%r8
2318         jmp     .Lxts_dec_grandloop
2319
2320 .align  32
2321 .Lxts_dec_grandloop:
2322         movdqu  `16*0`($inp),$inout0            # load input
2323         movdqa  $rndkey0,$twmask
2324         movdqu  `16*1`($inp),$inout1
2325         pxor    @tweak[0],$inout0               # intput^=tweak^round[0]
2326         movdqu  `16*2`($inp),$inout2
2327         pxor    @tweak[1],$inout1
2328          aesdec         $rndkey1,$inout0
2329         movdqu  `16*3`($inp),$inout3
2330         pxor    @tweak[2],$inout2
2331          aesdec         $rndkey1,$inout1
2332         movdqu  `16*4`($inp),$inout4
2333         pxor    @tweak[3],$inout3
2334          aesdec         $rndkey1,$inout2
2335         movdqu  `16*5`($inp),$inout5
2336         pxor    @tweak[5],$twmask               # round[0]^=tweak[5]
2337          movdqa 0x60(%rsp),$twres               # load round[0]^round[last]
2338         pxor    @tweak[4],$inout4
2339          aesdec         $rndkey1,$inout3
2340         $movkey 32($key_),$rndkey0
2341         lea     `16*6`($inp),$inp
2342         pxor    $twmask,$inout5
2343
2344          pxor   $twres,@tweak[0]                # calclulate tweaks^round[last]
2345         aesdec          $rndkey1,$inout4
2346          pxor   $twres,@tweak[1]
2347          movdqa @tweak[0],`16*0`(%rsp)          # put aside tweaks^last round key
2348         aesdec          $rndkey1,$inout5
2349         $movkey         48($key_),$rndkey1
2350          pxor   $twres,@tweak[2]
2351
2352         aesdec          $rndkey0,$inout0
2353          pxor   $twres,@tweak[3]
2354          movdqa @tweak[1],`16*1`(%rsp)
2355         aesdec          $rndkey0,$inout1
2356          pxor   $twres,@tweak[4]
2357          movdqa @tweak[2],`16*2`(%rsp)
2358         aesdec          $rndkey0,$inout2
2359         aesdec          $rndkey0,$inout3
2360          pxor   $twres,$twmask
2361          movdqa @tweak[4],`16*4`(%rsp)
2362         aesdec          $rndkey0,$inout4
2363         aesdec          $rndkey0,$inout5
2364         $movkey         64($key_),$rndkey0
2365          movdqa $twmask,`16*5`(%rsp)
2366         pshufd  \$0x5f,@tweak[5],$twres
2367         jmp     .Lxts_dec_loop6
2368 .align  32
2369 .Lxts_dec_loop6:
2370         aesdec          $rndkey1,$inout0
2371         aesdec          $rndkey1,$inout1
2372         aesdec          $rndkey1,$inout2
2373         aesdec          $rndkey1,$inout3
2374         aesdec          $rndkey1,$inout4
2375         aesdec          $rndkey1,$inout5
2376         $movkey         -64($key,%rax),$rndkey1
2377         add             \$32,%rax
2378
2379         aesdec          $rndkey0,$inout0
2380         aesdec          $rndkey0,$inout1
2381         aesdec          $rndkey0,$inout2
2382         aesdec          $rndkey0,$inout3
2383         aesdec          $rndkey0,$inout4
2384         aesdec          $rndkey0,$inout5
2385         $movkey         -80($key,%rax),$rndkey0
2386         jnz             .Lxts_dec_loop6
2387
2388         movdqa  (%r8),$twmask                   # start calculating next tweak
2389         movdqa  $twres,$twtmp
2390         paddd   $twres,$twres
2391          aesdec         $rndkey1,$inout0
2392         paddq   @tweak[5],@tweak[5]
2393         psrad   \$31,$twtmp
2394          aesdec         $rndkey1,$inout1
2395         pand    $twmask,$twtmp
2396         $movkey ($key_),@tweak[0]               # load round[0]
2397          aesdec         $rndkey1,$inout2
2398          aesdec         $rndkey1,$inout3
2399          aesdec         $rndkey1,$inout4
2400         pxor    $twtmp,@tweak[5]
2401         movaps  @tweak[0],@tweak[1]             # copy round[0]
2402          aesdec         $rndkey1,$inout5
2403          $movkey        -64($key),$rndkey1
2404
2405         movdqa  $twres,$twtmp
2406          aesdec         $rndkey0,$inout0
2407         paddd   $twres,$twres
2408         pxor    @tweak[5],@tweak[0]
2409          aesdec         $rndkey0,$inout1
2410         psrad   \$31,$twtmp
2411         paddq   @tweak[5],@tweak[5]
2412          aesdec         $rndkey0,$inout2
2413          aesdec         $rndkey0,$inout3
2414         pand    $twmask,$twtmp
2415         movaps  @tweak[1],@tweak[2]
2416          aesdec         $rndkey0,$inout4
2417         pxor    $twtmp,@tweak[5]
2418         movdqa  $twres,$twtmp
2419          aesdec         $rndkey0,$inout5
2420          $movkey        -48($key),$rndkey0
2421
2422         paddd   $twres,$twres
2423          aesdec         $rndkey1,$inout0
2424         pxor    @tweak[5],@tweak[1]
2425         psrad   \$31,$twtmp
2426          aesdec         $rndkey1,$inout1
2427         paddq   @tweak[5],@tweak[5]
2428         pand    $twmask,$twtmp
2429          aesdec         $rndkey1,$inout2
2430          aesdec         $rndkey1,$inout3
2431          movdqa @tweak[3],`16*3`(%rsp)
2432         pxor    $twtmp,@tweak[5]
2433          aesdec         $rndkey1,$inout4
2434         movaps  @tweak[2],@tweak[3]
2435         movdqa  $twres,$twtmp
2436          aesdec         $rndkey1,$inout5
2437          $movkey        -32($key),$rndkey1
2438
2439         paddd   $twres,$twres
2440          aesdec         $rndkey0,$inout0
2441         pxor    @tweak[5],@tweak[2]
2442         psrad   \$31,$twtmp
2443          aesdec         $rndkey0,$inout1
2444         paddq   @tweak[5],@tweak[5]
2445         pand    $twmask,$twtmp
2446          aesdec         $rndkey0,$inout2
2447          aesdec         $rndkey0,$inout3
2448          aesdec         $rndkey0,$inout4
2449         pxor    $twtmp,@tweak[5]
2450         movaps  @tweak[3],@tweak[4]
2451          aesdec         $rndkey0,$inout5
2452
2453         movdqa  $twres,$rndkey0
2454         paddd   $twres,$twres
2455          aesdec         $rndkey1,$inout0
2456         pxor    @tweak[5],@tweak[3]
2457         psrad   \$31,$rndkey0
2458          aesdec         $rndkey1,$inout1
2459         paddq   @tweak[5],@tweak[5]
2460         pand    $twmask,$rndkey0
2461          aesdec         $rndkey1,$inout2
2462          aesdec         $rndkey1,$inout3
2463         pxor    $rndkey0,@tweak[5]
2464         $movkey         ($key_),$rndkey0
2465          aesdec         $rndkey1,$inout4
2466          aesdec         $rndkey1,$inout5
2467         $movkey         16($key_),$rndkey1
2468
2469         pxor    @tweak[5],@tweak[4]
2470          aesdeclast     `16*0`(%rsp),$inout0
2471         psrad   \$31,$twres
2472         paddq   @tweak[5],@tweak[5]
2473          aesdeclast     `16*1`(%rsp),$inout1
2474          aesdeclast     `16*2`(%rsp),$inout2
2475         pand    $twmask,$twres
2476         mov     %r10,%rax                       # restore $rounds
2477          aesdeclast     `16*3`(%rsp),$inout3
2478          aesdeclast     `16*4`(%rsp),$inout4
2479          aesdeclast     `16*5`(%rsp),$inout5
2480         pxor    $twres,@tweak[5]
2481
2482         lea     `16*6`($out),$out               # $out+=6*16
2483         movups  $inout0,`-16*6`($out)           # store 6 output blocks
2484         movups  $inout1,`-16*5`($out)
2485         movups  $inout2,`-16*4`($out)
2486         movups  $inout3,`-16*3`($out)
2487         movups  $inout4,`-16*2`($out)
2488         movups  $inout5,`-16*1`($out)
2489         sub     \$16*6,$len
2490         jnc     .Lxts_dec_grandloop             # loop if $len-=6*16 didn't borrow
2491
2492         mov     \$16+96,$rounds
2493         sub     $rnds_,$rounds
2494         mov     $key_,$key                      # restore $key
2495         shr     \$4,$rounds                     # restore original value
2496
2497 .Lxts_dec_short:
2498         # at the point @tweak[0..5] are populated with tweak values
2499         mov     $rounds,$rnds_                  # backup $rounds
2500         pxor    $rndkey0,@tweak[0]
2501         pxor    $rndkey0,@tweak[1]
2502         add     \$16*6,$len                     # restore real remaining $len
2503         jz      .Lxts_dec_done                  # done if ($len==0)
2504
2505         pxor    $rndkey0,@tweak[2]
2506         cmp     \$0x20,$len
2507         jb      .Lxts_dec_one                   # $len is 1*16
2508         pxor    $rndkey0,@tweak[3]
2509         je      .Lxts_dec_two                   # $len is 2*16
2510
2511         pxor    $rndkey0,@tweak[4]
2512         cmp     \$0x40,$len
2513         jb      .Lxts_dec_three                 # $len is 3*16
2514         je      .Lxts_dec_four                  # $len is 4*16
2515
2516         movdqu  ($inp),$inout0                  # $len is 5*16
2517         movdqu  16*1($inp),$inout1
2518         movdqu  16*2($inp),$inout2
2519         pxor    @tweak[0],$inout0
2520         movdqu  16*3($inp),$inout3
2521         pxor    @tweak[1],$inout1
2522         movdqu  16*4($inp),$inout4
2523         lea     16*5($inp),$inp                 # $inp+=5*16
2524         pxor    @tweak[2],$inout2
2525         pxor    @tweak[3],$inout3
2526         pxor    @tweak[4],$inout4
2527
2528         call    _aesni_decrypt6
2529
2530         xorps   @tweak[0],$inout0
2531         xorps   @tweak[1],$inout1
2532         xorps   @tweak[2],$inout2
2533         movdqu  $inout0,($out)                  # store 5 output blocks
2534         xorps   @tweak[3],$inout3
2535         movdqu  $inout1,16*1($out)
2536         xorps   @tweak[4],$inout4
2537         movdqu  $inout2,16*2($out)
2538          pxor           $twtmp,$twtmp
2539         movdqu  $inout3,16*3($out)
2540          pcmpgtd        @tweak[5],$twtmp
2541         movdqu  $inout4,16*4($out)
2542         lea     16*5($out),$out                 # $out+=5*16
2543          pshufd         \$0x13,$twtmp,@tweak[1] # $twres
2544         and     \$15,$len_
2545         jz      .Lxts_dec_ret
2546
2547         movdqa  @tweak[5],@tweak[0]
2548         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
2549         pand    $twmask,@tweak[1]               # isolate carry and residue
2550         pxor    @tweak[5],@tweak[1]
2551         jmp     .Lxts_dec_done2
2552
2553 .align  16
2554 .Lxts_dec_one:
2555         movups  ($inp),$inout0
2556         lea     16*1($inp),$inp                 # $inp+=1*16
2557         xorps   @tweak[0],$inout0
2558 ___
2559         &aesni_generate1("dec",$key,$rounds);
2560 $code.=<<___;
2561         xorps   @tweak[0],$inout0
2562         movdqa  @tweak[1],@tweak[0]
2563         movups  $inout0,($out)                  # store one output block
2564         movdqa  @tweak[2],@tweak[1]
2565         lea     16*1($out),$out                 # $out+=1*16
2566         jmp     .Lxts_dec_done
2567
2568 .align  16
2569 .Lxts_dec_two:
2570         movups  ($inp),$inout0
2571         movups  16($inp),$inout1
2572         lea     32($inp),$inp                   # $inp+=2*16
2573         xorps   @tweak[0],$inout0
2574         xorps   @tweak[1],$inout1
2575
2576         call    _aesni_decrypt2
2577
2578         xorps   @tweak[0],$inout0
2579         movdqa  @tweak[2],@tweak[0]
2580         xorps   @tweak[1],$inout1
2581         movdqa  @tweak[3],@tweak[1]
2582         movups  $inout0,($out)                  # store 2 output blocks
2583         movups  $inout1,16*1($out)
2584         lea     16*2($out),$out                 # $out+=2*16
2585         jmp     .Lxts_dec_done
2586
2587 .align  16
2588 .Lxts_dec_three:
2589         movups  ($inp),$inout0
2590         movups  16*1($inp),$inout1
2591         movups  16*2($inp),$inout2
2592         lea     16*3($inp),$inp                 # $inp+=3*16
2593         xorps   @tweak[0],$inout0
2594         xorps   @tweak[1],$inout1
2595         xorps   @tweak[2],$inout2
2596
2597         call    _aesni_decrypt3
2598
2599         xorps   @tweak[0],$inout0
2600         movdqa  @tweak[3],@tweak[0]
2601         xorps   @tweak[1],$inout1
2602         movdqa  @tweak[4],@tweak[1]
2603         xorps   @tweak[2],$inout2
2604         movups  $inout0,($out)                  # store 3 output blocks
2605         movups  $inout1,16*1($out)
2606         movups  $inout2,16*2($out)
2607         lea     16*3($out),$out                 # $out+=3*16
2608         jmp     .Lxts_dec_done
2609
2610 .align  16
2611 .Lxts_dec_four:
2612         movups  ($inp),$inout0
2613         movups  16*1($inp),$inout1
2614         movups  16*2($inp),$inout2
2615         xorps   @tweak[0],$inout0
2616         movups  16*3($inp),$inout3
2617         lea     16*4($inp),$inp                 # $inp+=4*16
2618         xorps   @tweak[1],$inout1
2619         xorps   @tweak[2],$inout2
2620         xorps   @tweak[3],$inout3
2621
2622         call    _aesni_decrypt4
2623
2624         pxor    @tweak[0],$inout0
2625         movdqa  @tweak[4],@tweak[0]
2626         pxor    @tweak[1],$inout1
2627         movdqa  @tweak[5],@tweak[1]
2628         pxor    @tweak[2],$inout2
2629         movdqu  $inout0,($out)                  # store 4 output blocks
2630         pxor    @tweak[3],$inout3
2631         movdqu  $inout1,16*1($out)
2632         movdqu  $inout2,16*2($out)
2633         movdqu  $inout3,16*3($out)
2634         lea     16*4($out),$out                 # $out+=4*16
2635         jmp     .Lxts_dec_done
2636
2637 .align  16
2638 .Lxts_dec_done:
2639         and     \$15,$len_                      # see if $len%16 is 0
2640         jz      .Lxts_dec_ret
2641 .Lxts_dec_done2:
2642         mov     $len_,$len
2643         mov     $key_,$key                      # restore $key
2644         mov     $rnds_,$rounds                  # restore $rounds
2645
2646         movups  ($inp),$inout0
2647         xorps   @tweak[1],$inout0
2648 ___
2649         &aesni_generate1("dec",$key,$rounds);
2650 $code.=<<___;
2651         xorps   @tweak[1],$inout0
2652         movups  $inout0,($out)
2653
2654 .Lxts_dec_steal:
2655         movzb   16($inp),%eax                   # borrow $rounds ...
2656         movzb   ($out),%ecx                     # ... and $key
2657         lea     1($inp),$inp
2658         mov     %al,($out)
2659         mov     %cl,16($out)
2660         lea     1($out),$out
2661         sub     \$1,$len
2662         jnz     .Lxts_dec_steal
2663
2664         sub     $len_,$out                      # rewind $out
2665         mov     $key_,$key                      # restore $key
2666         mov     $rnds_,$rounds                  # restore $rounds
2667
2668         movups  ($out),$inout0
2669         xorps   @tweak[0],$inout0
2670 ___
2671         &aesni_generate1("dec",$key,$rounds);
2672 $code.=<<___;
2673         xorps   @tweak[0],$inout0
2674         movups  $inout0,($out)
2675
2676 .Lxts_dec_ret:
2677         xorps   %xmm0,%xmm0                     # clear register bank
2678         pxor    %xmm1,%xmm1
2679         pxor    %xmm2,%xmm2
2680         pxor    %xmm3,%xmm3
2681         pxor    %xmm4,%xmm4
2682         pxor    %xmm5,%xmm5
2683 ___
2684 $code.=<<___ if (!$win64);
2685         pxor    %xmm6,%xmm6
2686         pxor    %xmm7,%xmm7
2687         movaps  %xmm0,0x00(%rsp)                # clear stack
2688         pxor    %xmm8,%xmm8
2689         movaps  %xmm0,0x10(%rsp)
2690         pxor    %xmm9,%xmm9
2691         movaps  %xmm0,0x20(%rsp)
2692         pxor    %xmm10,%xmm10
2693         movaps  %xmm0,0x30(%rsp)
2694         pxor    %xmm11,%xmm11
2695         movaps  %xmm0,0x40(%rsp)
2696         pxor    %xmm12,%xmm12
2697         movaps  %xmm0,0x50(%rsp)
2698         pxor    %xmm13,%xmm13
2699         movaps  %xmm0,0x60(%rsp)
2700         pxor    %xmm14,%xmm14
2701         pxor    %xmm15,%xmm15
2702 ___
2703 $code.=<<___ if ($win64);
2704         movaps  -0xa8(%r11),%xmm6
2705         movaps  %xmm0,-0xa8(%r11)               # clear stack
2706         movaps  -0x98(%r11),%xmm7
2707         movaps  %xmm0,-0x98(%r11)
2708         movaps  -0x88(%r11),%xmm8
2709         movaps  %xmm0,-0x88(%r11)
2710         movaps  -0x78(%r11),%xmm9
2711         movaps  %xmm0,-0x78(%r11)
2712         movaps  -0x68(%r11),%xmm10
2713         movaps  %xmm0,-0x68(%r11)
2714         movaps  -0x58(%r11),%xmm11
2715         movaps  %xmm0,-0x58(%r11)
2716         movaps  -0x48(%r11),%xmm12
2717         movaps  %xmm0,-0x48(%r11)
2718         movaps  -0x38(%r11),%xmm13
2719         movaps  %xmm0,-0x38(%r11)
2720         movaps  -0x28(%r11),%xmm14
2721         movaps  %xmm0,-0x28(%r11)
2722         movaps  -0x18(%r11),%xmm15
2723         movaps  %xmm0,-0x18(%r11)
2724         movaps  %xmm0,0x00(%rsp)
2725         movaps  %xmm0,0x10(%rsp)
2726         movaps  %xmm0,0x20(%rsp)
2727         movaps  %xmm0,0x30(%rsp)
2728         movaps  %xmm0,0x40(%rsp)
2729         movaps  %xmm0,0x50(%rsp)
2730         movaps  %xmm0,0x60(%rsp)
2731 ___
2732 $code.=<<___;
2733         mov     -8(%r11),%rbp
2734 .cfi_restore    %rbp
2735         lea     (%r11),%rsp
2736 .cfi_def_cfa_register   %rsp
2737 .Lxts_dec_epilogue:
2738         ret
2739 .cfi_endproc
2740 .size   aesni_xts_decrypt,.-aesni_xts_decrypt
2741 ___
2742 }
2743 \f
2744 ######################################################################
2745 # void aesni_ocb_[en|de]crypt(const char *inp, char *out, size_t blocks,
2746 #       const AES_KEY *key, unsigned int start_block_num,
2747 #       unsigned char offset_i[16], const unsigned char L_[][16],
2748 #       unsigned char checksum[16]);
2749 #
2750 {
2751 my @offset=map("%xmm$_",(10..15));
2752 my ($checksum,$rndkey0l)=("%xmm8","%xmm9");
2753 my ($block_num,$offset_p)=("%r8","%r9");                # 5th and 6th arguments
2754 my ($L_p,$checksum_p) = ("%rbx","%rbp");
2755 my ($i1,$i3,$i5) = ("%r12","%r13","%r14");
2756 my $seventh_arg = $win64 ? 56 : 8;
2757 my $blocks = $len;
2758
2759 $code.=<<___;
2760 .globl  aesni_ocb_encrypt
2761 .type   aesni_ocb_encrypt,\@function,6
2762 .align  32
2763 aesni_ocb_encrypt:
2764 .cfi_startproc
2765         lea     (%rsp),%rax
2766         push    %rbx
2767 .cfi_push       %rbx
2768         push    %rbp
2769 .cfi_push       %rbp
2770         push    %r12
2771 .cfi_push       %r12
2772         push    %r13
2773 .cfi_push       %r13
2774         push    %r14
2775 .cfi_push       %r14
2776 ___
2777 $code.=<<___ if ($win64);
2778         lea     -0xa0(%rsp),%rsp
2779         movaps  %xmm6,0x00(%rsp)                # offload everything
2780         movaps  %xmm7,0x10(%rsp)
2781         movaps  %xmm8,0x20(%rsp)
2782         movaps  %xmm9,0x30(%rsp)
2783         movaps  %xmm10,0x40(%rsp)
2784         movaps  %xmm11,0x50(%rsp)
2785         movaps  %xmm12,0x60(%rsp)
2786         movaps  %xmm13,0x70(%rsp)
2787         movaps  %xmm14,0x80(%rsp)
2788         movaps  %xmm15,0x90(%rsp)
2789 .Locb_enc_body:
2790 ___
2791 $code.=<<___;
2792         mov     $seventh_arg(%rax),$L_p         # 7th argument
2793         mov     $seventh_arg+8(%rax),$checksum_p# 8th argument
2794
2795         mov     240($key),$rnds_
2796         mov     $key,$key_
2797         shl     \$4,$rnds_
2798         $movkey ($key),$rndkey0l                # round[0]
2799         $movkey 16($key,$rnds_),$rndkey1        # round[last]
2800
2801         movdqu  ($offset_p),@offset[5]          # load last offset_i
2802         pxor    $rndkey1,$rndkey0l              # round[0] ^ round[last]
2803         pxor    $rndkey1,@offset[5]             # offset_i ^ round[last]
2804
2805         mov     \$16+32,$rounds
2806         lea     32($key_,$rnds_),$key
2807         $movkey 16($key_),$rndkey1              # round[1]
2808         sub     %r10,%rax                       # twisted $rounds
2809         mov     %rax,%r10                       # backup twisted $rounds
2810
2811         movdqu  ($L_p),@offset[0]               # L_0 for all odd-numbered blocks
2812         movdqu  ($checksum_p),$checksum         # load checksum
2813
2814         test    \$1,$block_num                  # is first block number odd?
2815         jnz     .Locb_enc_odd
2816
2817         bsf     $block_num,$i1
2818         add     \$1,$block_num
2819         shl     \$4,$i1
2820         movdqu  ($L_p,$i1),$inout5              # borrow
2821         movdqu  ($inp),$inout0
2822         lea     16($inp),$inp
2823
2824         call    __ocb_encrypt1
2825
2826         movdqa  $inout5,@offset[5]
2827         movups  $inout0,($out)
2828         lea     16($out),$out
2829         sub     \$1,$blocks
2830         jz      .Locb_enc_done
2831
2832 .Locb_enc_odd:
2833         lea     1($block_num),$i1               # even-numbered blocks
2834         lea     3($block_num),$i3
2835         lea     5($block_num),$i5
2836         lea     6($block_num),$block_num
2837         bsf     $i1,$i1                         # ntz(block)
2838         bsf     $i3,$i3
2839         bsf     $i5,$i5
2840         shl     \$4,$i1                         # ntz(block) -> table offset
2841         shl     \$4,$i3
2842         shl     \$4,$i5
2843
2844         sub     \$6,$blocks
2845         jc      .Locb_enc_short
2846         jmp     .Locb_enc_grandloop
2847
2848 .align  32
2849 .Locb_enc_grandloop:
2850         movdqu  `16*0`($inp),$inout0            # load input
2851         movdqu  `16*1`($inp),$inout1
2852         movdqu  `16*2`($inp),$inout2
2853         movdqu  `16*3`($inp),$inout3
2854         movdqu  `16*4`($inp),$inout4
2855         movdqu  `16*5`($inp),$inout5
2856         lea     `16*6`($inp),$inp
2857
2858         call    __ocb_encrypt6
2859
2860         movups  $inout0,`16*0`($out)            # store output
2861         movups  $inout1,`16*1`($out)
2862         movups  $inout2,`16*2`($out)
2863         movups  $inout3,`16*3`($out)
2864         movups  $inout4,`16*4`($out)
2865         movups  $inout5,`16*5`($out)
2866         lea     `16*6`($out),$out
2867         sub     \$6,$blocks
2868         jnc     .Locb_enc_grandloop
2869
2870 .Locb_enc_short:
2871         add     \$6,$blocks
2872         jz      .Locb_enc_done
2873
2874         movdqu  `16*0`($inp),$inout0
2875         cmp     \$2,$blocks
2876         jb      .Locb_enc_one
2877         movdqu  `16*1`($inp),$inout1
2878         je      .Locb_enc_two
2879
2880         movdqu  `16*2`($inp),$inout2
2881         cmp     \$4,$blocks
2882         jb      .Locb_enc_three
2883         movdqu  `16*3`($inp),$inout3
2884         je      .Locb_enc_four
2885
2886         movdqu  `16*4`($inp),$inout4
2887         pxor    $inout5,$inout5
2888
2889         call    __ocb_encrypt6
2890
2891         movdqa  @offset[4],@offset[5]
2892         movups  $inout0,`16*0`($out)
2893         movups  $inout1,`16*1`($out)
2894         movups  $inout2,`16*2`($out)
2895         movups  $inout3,`16*3`($out)
2896         movups  $inout4,`16*4`($out)
2897
2898         jmp     .Locb_enc_done
2899
2900 .align  16
2901 .Locb_enc_one:
2902         movdqa  @offset[0],$inout5              # borrow
2903
2904         call    __ocb_encrypt1
2905
2906         movdqa  $inout5,@offset[5]
2907         movups  $inout0,`16*0`($out)
2908         jmp     .Locb_enc_done
2909
2910 .align  16
2911 .Locb_enc_two:
2912         pxor    $inout2,$inout2
2913         pxor    $inout3,$inout3
2914
2915         call    __ocb_encrypt4
2916
2917         movdqa  @offset[1],@offset[5]
2918         movups  $inout0,`16*0`($out)
2919         movups  $inout1,`16*1`($out)
2920
2921         jmp     .Locb_enc_done
2922
2923 .align  16
2924 .Locb_enc_three:
2925         pxor    $inout3,$inout3
2926
2927         call    __ocb_encrypt4
2928
2929         movdqa  @offset[2],@offset[5]
2930         movups  $inout0,`16*0`($out)
2931         movups  $inout1,`16*1`($out)
2932         movups  $inout2,`16*2`($out)
2933
2934         jmp     .Locb_enc_done
2935
2936 .align  16
2937 .Locb_enc_four:
2938         call    __ocb_encrypt4
2939
2940         movdqa  @offset[3],@offset[5]
2941         movups  $inout0,`16*0`($out)
2942         movups  $inout1,`16*1`($out)
2943         movups  $inout2,`16*2`($out)
2944         movups  $inout3,`16*3`($out)
2945
2946 .Locb_enc_done:
2947         pxor    $rndkey0,@offset[5]             # "remove" round[last]
2948         movdqu  $checksum,($checksum_p)         # store checksum
2949         movdqu  @offset[5],($offset_p)          # store last offset_i
2950
2951         xorps   %xmm0,%xmm0                     # clear register bank
2952         pxor    %xmm1,%xmm1
2953         pxor    %xmm2,%xmm2
2954         pxor    %xmm3,%xmm3
2955         pxor    %xmm4,%xmm4
2956         pxor    %xmm5,%xmm5
2957 ___
2958 $code.=<<___ if (!$win64);
2959         pxor    %xmm6,%xmm6
2960         pxor    %xmm7,%xmm7
2961         pxor    %xmm8,%xmm8
2962         pxor    %xmm9,%xmm9
2963         pxor    %xmm10,%xmm10
2964         pxor    %xmm11,%xmm11
2965         pxor    %xmm12,%xmm12
2966         pxor    %xmm13,%xmm13
2967         pxor    %xmm14,%xmm14
2968         pxor    %xmm15,%xmm15
2969         lea     0x28(%rsp),%rax
2970 .cfi_def_cfa    %rax,8
2971 ___
2972 $code.=<<___ if ($win64);
2973         movaps  0x00(%rsp),%xmm6
2974         movaps  %xmm0,0x00(%rsp)                # clear stack
2975         movaps  0x10(%rsp),%xmm7
2976         movaps  %xmm0,0x10(%rsp)
2977         movaps  0x20(%rsp),%xmm8
2978         movaps  %xmm0,0x20(%rsp)
2979         movaps  0x30(%rsp),%xmm9
2980         movaps  %xmm0,0x30(%rsp)
2981         movaps  0x40(%rsp),%xmm10
2982         movaps  %xmm0,0x40(%rsp)
2983         movaps  0x50(%rsp),%xmm11
2984         movaps  %xmm0,0x50(%rsp)
2985         movaps  0x60(%rsp),%xmm12
2986         movaps  %xmm0,0x60(%rsp)
2987         movaps  0x70(%rsp),%xmm13
2988         movaps  %xmm0,0x70(%rsp)
2989         movaps  0x80(%rsp),%xmm14
2990         movaps  %xmm0,0x80(%rsp)
2991         movaps  0x90(%rsp),%xmm15
2992         movaps  %xmm0,0x90(%rsp)
2993         lea     0xa0+0x28(%rsp),%rax
2994 .Locb_enc_pop:
2995 ___
2996 $code.=<<___;
2997         mov     -40(%rax),%r14
2998 .cfi_restore    %r14
2999         mov     -32(%rax),%r13
3000 .cfi_restore    %r13
3001         mov     -24(%rax),%r12
3002 .cfi_restore    %r12
3003         mov     -16(%rax),%rbp
3004 .cfi_restore    %rbp
3005         mov     -8(%rax),%rbx
3006 .cfi_restore    %rbx
3007         lea     (%rax),%rsp
3008 .cfi_def_cfa_register   %rsp
3009 .Locb_enc_epilogue:
3010         ret
3011 .cfi_endproc
3012 .size   aesni_ocb_encrypt,.-aesni_ocb_encrypt
3013
3014 .type   __ocb_encrypt6,\@abi-omnipotent
3015 .align  32
3016 __ocb_encrypt6:
3017          pxor           $rndkey0l,@offset[5]    # offset_i ^ round[0]
3018          movdqu         ($L_p,$i1),@offset[1]
3019          movdqa         @offset[0],@offset[2]
3020          movdqu         ($L_p,$i3),@offset[3]
3021          movdqa         @offset[0],@offset[4]
3022          pxor           @offset[5],@offset[0]
3023          movdqu         ($L_p,$i5),@offset[5]
3024          pxor           @offset[0],@offset[1]
3025         pxor            $inout0,$checksum       # accumulate checksum
3026         pxor            @offset[0],$inout0      # input ^ round[0] ^ offset_i
3027          pxor           @offset[1],@offset[2]
3028         pxor            $inout1,$checksum
3029         pxor            @offset[1],$inout1
3030          pxor           @offset[2],@offset[3]
3031         pxor            $inout2,$checksum
3032         pxor            @offset[2],$inout2
3033          pxor           @offset[3],@offset[4]
3034         pxor            $inout3,$checksum
3035         pxor            @offset[3],$inout3
3036          pxor           @offset[4],@offset[5]
3037         pxor            $inout4,$checksum
3038         pxor            @offset[4],$inout4
3039         pxor            $inout5,$checksum
3040         pxor            @offset[5],$inout5
3041         $movkey         32($key_),$rndkey0
3042
3043         lea             1($block_num),$i1       # even-numbered blocks
3044         lea             3($block_num),$i3
3045         lea             5($block_num),$i5
3046         add             \$6,$block_num
3047          pxor           $rndkey0l,@offset[0]    # offset_i ^ round[last]
3048         bsf             $i1,$i1                 # ntz(block)
3049         bsf             $i3,$i3
3050         bsf             $i5,$i5
3051
3052         aesenc          $rndkey1,$inout0
3053         aesenc          $rndkey1,$inout1
3054         aesenc          $rndkey1,$inout2
3055         aesenc          $rndkey1,$inout3
3056          pxor           $rndkey0l,@offset[1]
3057          pxor           $rndkey0l,@offset[2]
3058         aesenc          $rndkey1,$inout4
3059          pxor           $rndkey0l,@offset[3]
3060          pxor           $rndkey0l,@offset[4]
3061         aesenc          $rndkey1,$inout5
3062         $movkey         48($key_),$rndkey1
3063          pxor           $rndkey0l,@offset[5]
3064
3065         aesenc          $rndkey0,$inout0
3066         aesenc          $rndkey0,$inout1
3067         aesenc          $rndkey0,$inout2
3068         aesenc          $rndkey0,$inout3
3069         aesenc          $rndkey0,$inout4
3070         aesenc          $rndkey0,$inout5
3071         $movkey         64($key_),$rndkey0
3072         shl             \$4,$i1                 # ntz(block) -> table offset
3073         shl             \$4,$i3
3074         jmp             .Locb_enc_loop6
3075
3076 .align  32
3077 .Locb_enc_loop6:
3078         aesenc          $rndkey1,$inout0
3079         aesenc          $rndkey1,$inout1
3080         aesenc          $rndkey1,$inout2
3081         aesenc          $rndkey1,$inout3
3082         aesenc          $rndkey1,$inout4
3083         aesenc          $rndkey1,$inout5
3084         $movkey         ($key,%rax),$rndkey1
3085         add             \$32,%rax
3086
3087         aesenc          $rndkey0,$inout0
3088         aesenc          $rndkey0,$inout1
3089         aesenc          $rndkey0,$inout2
3090         aesenc          $rndkey0,$inout3
3091         aesenc          $rndkey0,$inout4
3092         aesenc          $rndkey0,$inout5
3093         $movkey         -16($key,%rax),$rndkey0
3094         jnz             .Locb_enc_loop6
3095
3096         aesenc          $rndkey1,$inout0
3097         aesenc          $rndkey1,$inout1
3098         aesenc          $rndkey1,$inout2
3099         aesenc          $rndkey1,$inout3
3100         aesenc          $rndkey1,$inout4
3101         aesenc          $rndkey1,$inout5
3102         $movkey         16($key_),$rndkey1
3103         shl             \$4,$i5
3104
3105         aesenclast      @offset[0],$inout0
3106         movdqu          ($L_p),@offset[0]       # L_0 for all odd-numbered blocks
3107         mov             %r10,%rax               # restore twisted rounds
3108         aesenclast      @offset[1],$inout1
3109         aesenclast      @offset[2],$inout2
3110         aesenclast      @offset[3],$inout3
3111         aesenclast      @offset[4],$inout4
3112         aesenclast      @offset[5],$inout5
3113         ret
3114 .size   __ocb_encrypt6,.-__ocb_encrypt6
3115
3116 .type   __ocb_encrypt4,\@abi-omnipotent
3117 .align  32
3118 __ocb_encrypt4:
3119          pxor           $rndkey0l,@offset[5]    # offset_i ^ round[0]
3120          movdqu         ($L_p,$i1),@offset[1]
3121          movdqa         @offset[0],@offset[2]
3122          movdqu         ($L_p,$i3),@offset[3]
3123          pxor           @offset[5],@offset[0]
3124          pxor           @offset[0],@offset[1]
3125         pxor            $inout0,$checksum       # accumulate checksum
3126         pxor            @offset[0],$inout0      # input ^ round[0] ^ offset_i
3127          pxor           @offset[1],@offset[2]
3128         pxor            $inout1,$checksum
3129         pxor            @offset[1],$inout1
3130          pxor           @offset[2],@offset[3]
3131         pxor            $inout2,$checksum
3132         pxor            @offset[2],$inout2
3133         pxor            $inout3,$checksum
3134         pxor            @offset[3],$inout3
3135         $movkey         32($key_),$rndkey0
3136
3137          pxor           $rndkey0l,@offset[0]    # offset_i ^ round[last]
3138          pxor           $rndkey0l,@offset[1]
3139          pxor           $rndkey0l,@offset[2]
3140          pxor           $rndkey0l,@offset[3]
3141
3142         aesenc          $rndkey1,$inout0
3143         aesenc          $rndkey1,$inout1
3144         aesenc          $rndkey1,$inout2
3145         aesenc          $rndkey1,$inout3
3146         $movkey         48($key_),$rndkey1
3147
3148         aesenc          $rndkey0,$inout0
3149         aesenc          $rndkey0,$inout1
3150         aesenc          $rndkey0,$inout2
3151         aesenc          $rndkey0,$inout3
3152         $movkey         64($key_),$rndkey0
3153         jmp             .Locb_enc_loop4
3154
3155 .align  32
3156 .Locb_enc_loop4:
3157         aesenc          $rndkey1,$inout0
3158         aesenc          $rndkey1,$inout1
3159         aesenc          $rndkey1,$inout2
3160         aesenc          $rndkey1,$inout3
3161         $movkey         ($key,%rax),$rndkey1
3162         add             \$32,%rax
3163
3164         aesenc          $rndkey0,$inout0
3165         aesenc          $rndkey0,$inout1
3166         aesenc          $rndkey0,$inout2
3167         aesenc          $rndkey0,$inout3
3168         $movkey         -16($key,%rax),$rndkey0
3169         jnz             .Locb_enc_loop4
3170
3171         aesenc          $rndkey1,$inout0
3172         aesenc          $rndkey1,$inout1
3173         aesenc          $rndkey1,$inout2
3174         aesenc          $rndkey1,$inout3
3175         $movkey         16($key_),$rndkey1
3176         mov             %r10,%rax               # restore twisted rounds
3177
3178         aesenclast      @offset[0],$inout0
3179         aesenclast      @offset[1],$inout1
3180         aesenclast      @offset[2],$inout2
3181         aesenclast      @offset[3],$inout3
3182         ret
3183 .size   __ocb_encrypt4,.-__ocb_encrypt4
3184
3185 .type   __ocb_encrypt1,\@abi-omnipotent
3186 .align  32
3187 __ocb_encrypt1:
3188          pxor           @offset[5],$inout5      # offset_i
3189          pxor           $rndkey0l,$inout5       # offset_i ^ round[0]
3190         pxor            $inout0,$checksum       # accumulate checksum
3191         pxor            $inout5,$inout0         # input ^ round[0] ^ offset_i
3192         $movkey         32($key_),$rndkey0
3193
3194         aesenc          $rndkey1,$inout0
3195         $movkey         48($key_),$rndkey1
3196         pxor            $rndkey0l,$inout5       # offset_i ^ round[last]
3197
3198         aesenc          $rndkey0,$inout0
3199         $movkey         64($key_),$rndkey0
3200         jmp             .Locb_enc_loop1
3201
3202 .align  32
3203 .Locb_enc_loop1:
3204         aesenc          $rndkey1,$inout0
3205         $movkey         ($key,%rax),$rndkey1
3206         add             \$32,%rax
3207
3208         aesenc          $rndkey0,$inout0
3209         $movkey         -16($key,%rax),$rndkey0
3210         jnz             .Locb_enc_loop1
3211
3212         aesenc          $rndkey1,$inout0
3213         $movkey         16($key_),$rndkey1      # redundant in tail
3214         mov             %r10,%rax               # restore twisted rounds
3215
3216         aesenclast      $inout5,$inout0
3217         ret
3218 .size   __ocb_encrypt1,.-__ocb_encrypt1
3219
3220 .globl  aesni_ocb_decrypt
3221 .type   aesni_ocb_decrypt,\@function,6
3222 .align  32
3223 aesni_ocb_decrypt:
3224 .cfi_startproc
3225         lea     (%rsp),%rax
3226         push    %rbx
3227 .cfi_push       %rbx
3228         push    %rbp
3229 .cfi_push       %rbp
3230         push    %r12
3231 .cfi_push       %r12
3232         push    %r13
3233 .cfi_push       %r13
3234         push    %r14
3235 .cfi_push       %r14
3236 ___
3237 $code.=<<___ if ($win64);
3238         lea     -0xa0(%rsp),%rsp
3239         movaps  %xmm6,0x00(%rsp)                # offload everything
3240         movaps  %xmm7,0x10(%rsp)
3241         movaps  %xmm8,0x20(%rsp)
3242         movaps  %xmm9,0x30(%rsp)
3243         movaps  %xmm10,0x40(%rsp)
3244         movaps  %xmm11,0x50(%rsp)
3245         movaps  %xmm12,0x60(%rsp)
3246         movaps  %xmm13,0x70(%rsp)
3247         movaps  %xmm14,0x80(%rsp)
3248         movaps  %xmm15,0x90(%rsp)
3249 .Locb_dec_body:
3250 ___
3251 $code.=<<___;
3252         mov     $seventh_arg(%rax),$L_p         # 7th argument
3253         mov     $seventh_arg+8(%rax),$checksum_p# 8th argument
3254
3255         mov     240($key),$rnds_
3256         mov     $key,$key_
3257         shl     \$4,$rnds_
3258         $movkey ($key),$rndkey0l                # round[0]
3259         $movkey 16($key,$rnds_),$rndkey1        # round[last]
3260
3261         movdqu  ($offset_p),@offset[5]          # load last offset_i
3262         pxor    $rndkey1,$rndkey0l              # round[0] ^ round[last]
3263         pxor    $rndkey1,@offset[5]             # offset_i ^ round[last]
3264
3265         mov     \$16+32,$rounds
3266         lea     32($key_,$rnds_),$key
3267         $movkey 16($key_),$rndkey1              # round[1]
3268         sub     %r10,%rax                       # twisted $rounds
3269         mov     %rax,%r10                       # backup twisted $rounds
3270
3271         movdqu  ($L_p),@offset[0]               # L_0 for all odd-numbered blocks
3272         movdqu  ($checksum_p),$checksum         # load checksum
3273
3274         test    \$1,$block_num                  # is first block number odd?
3275         jnz     .Locb_dec_odd
3276
3277         bsf     $block_num,$i1
3278         add     \$1,$block_num
3279         shl     \$4,$i1
3280         movdqu  ($L_p,$i1),$inout5              # borrow
3281         movdqu  ($inp),$inout0
3282         lea     16($inp),$inp
3283
3284         call    __ocb_decrypt1
3285
3286         movdqa  $inout5,@offset[5]
3287         movups  $inout0,($out)
3288         xorps   $inout0,$checksum               # accumulate checksum
3289         lea     16($out),$out
3290         sub     \$1,$blocks
3291         jz      .Locb_dec_done
3292
3293 .Locb_dec_odd:
3294         lea     1($block_num),$i1               # even-numbered blocks
3295         lea     3($block_num),$i3
3296         lea     5($block_num),$i5
3297         lea     6($block_num),$block_num
3298         bsf     $i1,$i1                         # ntz(block)
3299         bsf     $i3,$i3
3300         bsf     $i5,$i5
3301         shl     \$4,$i1                         # ntz(block) -> table offset
3302         shl     \$4,$i3
3303         shl     \$4,$i5
3304
3305         sub     \$6,$blocks
3306         jc      .Locb_dec_short
3307         jmp     .Locb_dec_grandloop
3308
3309 .align  32
3310 .Locb_dec_grandloop:
3311         movdqu  `16*0`($inp),$inout0            # load input
3312         movdqu  `16*1`($inp),$inout1
3313         movdqu  `16*2`($inp),$inout2
3314         movdqu  `16*3`($inp),$inout3
3315         movdqu  `16*4`($inp),$inout4
3316         movdqu  `16*5`($inp),$inout5
3317         lea     `16*6`($inp),$inp
3318
3319         call    __ocb_decrypt6
3320
3321         movups  $inout0,`16*0`($out)            # store output
3322         pxor    $inout0,$checksum               # accumulate checksum
3323         movups  $inout1,`16*1`($out)
3324         pxor    $inout1,$checksum
3325         movups  $inout2,`16*2`($out)
3326         pxor    $inout2,$checksum
3327         movups  $inout3,`16*3`($out)
3328         pxor    $inout3,$checksum
3329         movups  $inout4,`16*4`($out)
3330         pxor    $inout4,$checksum
3331         movups  $inout5,`16*5`($out)
3332         pxor    $inout5,$checksum
3333         lea     `16*6`($out),$out
3334         sub     \$6,$blocks
3335         jnc     .Locb_dec_grandloop
3336
3337 .Locb_dec_short:
3338         add     \$6,$blocks
3339         jz      .Locb_dec_done
3340
3341         movdqu  `16*0`($inp),$inout0
3342         cmp     \$2,$blocks
3343         jb      .Locb_dec_one
3344         movdqu  `16*1`($inp),$inout1
3345         je      .Locb_dec_two
3346
3347         movdqu  `16*2`($inp),$inout2
3348         cmp     \$4,$blocks
3349         jb      .Locb_dec_three
3350         movdqu  `16*3`($inp),$inout3
3351         je      .Locb_dec_four
3352
3353         movdqu  `16*4`($inp),$inout4
3354         pxor    $inout5,$inout5
3355
3356         call    __ocb_decrypt6
3357
3358         movdqa  @offset[4],@offset[5]
3359         movups  $inout0,`16*0`($out)            # store output
3360         pxor    $inout0,$checksum               # accumulate checksum
3361         movups  $inout1,`16*1`($out)
3362         pxor    $inout1,$checksum
3363         movups  $inout2,`16*2`($out)
3364         pxor    $inout2,$checksum
3365         movups  $inout3,`16*3`($out)
3366         pxor    $inout3,$checksum
3367         movups  $inout4,`16*4`($out)
3368         pxor    $inout4,$checksum
3369
3370         jmp     .Locb_dec_done
3371
3372 .align  16
3373 .Locb_dec_one:
3374         movdqa  @offset[0],$inout5              # borrow
3375
3376         call    __ocb_decrypt1
3377
3378         movdqa  $inout5,@offset[5]
3379         movups  $inout0,`16*0`($out)            # store output
3380         xorps   $inout0,$checksum               # accumulate checksum
3381         jmp     .Locb_dec_done
3382
3383 .align  16
3384 .Locb_dec_two:
3385         pxor    $inout2,$inout2
3386         pxor    $inout3,$inout3
3387
3388         call    __ocb_decrypt4
3389
3390         movdqa  @offset[1],@offset[5]
3391         movups  $inout0,`16*0`($out)            # store output
3392         xorps   $inout0,$checksum               # accumulate checksum
3393         movups  $inout1,`16*1`($out)
3394         xorps   $inout1,$checksum
3395
3396         jmp     .Locb_dec_done
3397
3398 .align  16
3399 .Locb_dec_three:
3400         pxor    $inout3,$inout3
3401
3402         call    __ocb_decrypt4
3403
3404         movdqa  @offset[2],@offset[5]
3405         movups  $inout0,`16*0`($out)            # store output
3406         xorps   $inout0,$checksum               # accumulate checksum
3407         movups  $inout1,`16*1`($out)
3408         xorps   $inout1,$checksum
3409         movups  $inout2,`16*2`($out)
3410         xorps   $inout2,$checksum
3411
3412         jmp     .Locb_dec_done
3413
3414 .align  16
3415 .Locb_dec_four:
3416         call    __ocb_decrypt4
3417
3418         movdqa  @offset[3],@offset[5]
3419         movups  $inout0,`16*0`($out)            # store output
3420         pxor    $inout0,$checksum               # accumulate checksum
3421         movups  $inout1,`16*1`($out)
3422         pxor    $inout1,$checksum
3423         movups  $inout2,`16*2`($out)
3424         pxor    $inout2,$checksum
3425         movups  $inout3,`16*3`($out)
3426         pxor    $inout3,$checksum
3427
3428 .Locb_dec_done:
3429         pxor    $rndkey0,@offset[5]             # "remove" round[last]
3430         movdqu  $checksum,($checksum_p)         # store checksum
3431         movdqu  @offset[5],($offset_p)          # store last offset_i
3432
3433         xorps   %xmm0,%xmm0                     # clear register bank
3434         pxor    %xmm1,%xmm1
3435         pxor    %xmm2,%xmm2
3436         pxor    %xmm3,%xmm3
3437         pxor    %xmm4,%xmm4
3438         pxor    %xmm5,%xmm5
3439 ___
3440 $code.=<<___ if (!$win64);
3441         pxor    %xmm6,%xmm6
3442         pxor    %xmm7,%xmm7
3443         pxor    %xmm8,%xmm8
3444         pxor    %xmm9,%xmm9
3445         pxor    %xmm10,%xmm10
3446         pxor    %xmm11,%xmm11
3447         pxor    %xmm12,%xmm12
3448         pxor    %xmm13,%xmm13
3449         pxor    %xmm14,%xmm14
3450         pxor    %xmm15,%xmm15
3451         lea     0x28(%rsp),%rax
3452 .cfi_def_cfa    %rax,8
3453 ___
3454 $code.=<<___ if ($win64);
3455         movaps  0x00(%rsp),%xmm6
3456         movaps  %xmm0,0x00(%rsp)                # clear stack
3457         movaps  0x10(%rsp),%xmm7
3458         movaps  %xmm0,0x10(%rsp)
3459         movaps  0x20(%rsp),%xmm8
3460         movaps  %xmm0,0x20(%rsp)
3461         movaps  0x30(%rsp),%xmm9
3462         movaps  %xmm0,0x30(%rsp)
3463         movaps  0x40(%rsp),%xmm10
3464         movaps  %xmm0,0x40(%rsp)
3465         movaps  0x50(%rsp),%xmm11
3466         movaps  %xmm0,0x50(%rsp)
3467         movaps  0x60(%rsp),%xmm12
3468         movaps  %xmm0,0x60(%rsp)
3469         movaps  0x70(%rsp),%xmm13
3470         movaps  %xmm0,0x70(%rsp)
3471         movaps  0x80(%rsp),%xmm14
3472         movaps  %xmm0,0x80(%rsp)
3473         movaps  0x90(%rsp),%xmm15
3474         movaps  %xmm0,0x90(%rsp)
3475         lea     0xa0+0x28(%rsp),%rax
3476 .Locb_dec_pop:
3477 ___
3478 $code.=<<___;
3479         mov     -40(%rax),%r14
3480 .cfi_restore    %r14
3481         mov     -32(%rax),%r13
3482 .cfi_restore    %r13
3483         mov     -24(%rax),%r12
3484 .cfi_restore    %r12
3485         mov     -16(%rax),%rbp
3486 .cfi_restore    %rbp
3487         mov     -8(%rax),%rbx
3488 .cfi_restore    %rbx
3489         lea     (%rax),%rsp
3490 .cfi_def_cfa_register   %rsp
3491 .Locb_dec_epilogue:
3492         ret
3493 .cfi_endproc
3494 .size   aesni_ocb_decrypt,.-aesni_ocb_decrypt
3495
3496 .type   __ocb_decrypt6,\@abi-omnipotent
3497 .align  32
3498 __ocb_decrypt6:
3499          pxor           $rndkey0l,@offset[5]    # offset_i ^ round[0]
3500          movdqu         ($L_p,$i1),@offset[1]
3501          movdqa         @offset[0],@offset[2]
3502          movdqu         ($L_p,$i3),@offset[3]
3503          movdqa         @offset[0],@offset[4]
3504          pxor           @offset[5],@offset[0]
3505          movdqu         ($L_p,$i5),@offset[5]
3506          pxor           @offset[0],@offset[1]
3507         pxor            @offset[0],$inout0      # input ^ round[0] ^ offset_i
3508          pxor           @offset[1],@offset[2]
3509         pxor            @offset[1],$inout1
3510          pxor           @offset[2],@offset[3]
3511         pxor            @offset[2],$inout2
3512          pxor           @offset[3],@offset[4]
3513         pxor            @offset[3],$inout3
3514          pxor           @offset[4],@offset[5]
3515         pxor            @offset[4],$inout4
3516         pxor            @offset[5],$inout5
3517         $movkey         32($key_),$rndkey0
3518
3519         lea             1($block_num),$i1       # even-numbered blocks
3520         lea             3($block_num),$i3
3521         lea             5($block_num),$i5
3522         add             \$6,$block_num
3523          pxor           $rndkey0l,@offset[0]    # offset_i ^ round[last]
3524         bsf             $i1,$i1                 # ntz(block)
3525         bsf             $i3,$i3
3526         bsf             $i5,$i5
3527
3528         aesdec          $rndkey1,$inout0
3529         aesdec          $rndkey1,$inout1
3530         aesdec          $rndkey1,$inout2
3531         aesdec          $rndkey1,$inout3
3532          pxor           $rndkey0l,@offset[1]
3533          pxor           $rndkey0l,@offset[2]
3534         aesdec          $rndkey1,$inout4
3535          pxor           $rndkey0l,@offset[3]
3536          pxor           $rndkey0l,@offset[4]
3537         aesdec          $rndkey1,$inout5
3538         $movkey         48($key_),$rndkey1
3539          pxor           $rndkey0l,@offset[5]
3540
3541         aesdec          $rndkey0,$inout0
3542         aesdec          $rndkey0,$inout1
3543         aesdec          $rndkey0,$inout2
3544         aesdec          $rndkey0,$inout3
3545         aesdec          $rndkey0,$inout4
3546         aesdec          $rndkey0,$inout5
3547         $movkey         64($key_),$rndkey0
3548         shl             \$4,$i1                 # ntz(block) -> table offset
3549         shl             \$4,$i3
3550         jmp             .Locb_dec_loop6
3551
3552 .align  32
3553 .Locb_dec_loop6:
3554         aesdec          $rndkey1,$inout0
3555         aesdec          $rndkey1,$inout1
3556         aesdec          $rndkey1,$inout2
3557         aesdec          $rndkey1,$inout3
3558         aesdec          $rndkey1,$inout4
3559         aesdec          $rndkey1,$inout5
3560         $movkey         ($key,%rax),$rndkey1
3561         add             \$32,%rax
3562
3563         aesdec          $rndkey0,$inout0
3564         aesdec          $rndkey0,$inout1
3565         aesdec          $rndkey0,$inout2
3566         aesdec          $rndkey0,$inout3
3567         aesdec          $rndkey0,$inout4
3568         aesdec          $rndkey0,$inout5
3569         $movkey         -16($key,%rax),$rndkey0
3570         jnz             .Locb_dec_loop6
3571
3572         aesdec          $rndkey1,$inout0
3573         aesdec          $rndkey1,$inout1
3574         aesdec          $rndkey1,$inout2
3575         aesdec          $rndkey1,$inout3
3576         aesdec          $rndkey1,$inout4
3577         aesdec          $rndkey1,$inout5
3578         $movkey         16($key_),$rndkey1
3579         shl             \$4,$i5
3580
3581         aesdeclast      @offset[0],$inout0
3582         movdqu          ($L_p),@offset[0]       # L_0 for all odd-numbered blocks
3583         mov             %r10,%rax               # restore twisted rounds
3584         aesdeclast      @offset[1],$inout1
3585         aesdeclast      @offset[2],$inout2
3586         aesdeclast      @offset[3],$inout3
3587         aesdeclast      @offset[4],$inout4
3588         aesdeclast      @offset[5],$inout5
3589         ret
3590 .size   __ocb_decrypt6,.-__ocb_decrypt6
3591
3592 .type   __ocb_decrypt4,\@abi-omnipotent
3593 .align  32
3594 __ocb_decrypt4:
3595          pxor           $rndkey0l,@offset[5]    # offset_i ^ round[0]
3596          movdqu         ($L_p,$i1),@offset[1]
3597          movdqa         @offset[0],@offset[2]
3598          movdqu         ($L_p,$i3),@offset[3]
3599          pxor           @offset[5],@offset[0]
3600          pxor           @offset[0],@offset[1]
3601         pxor            @offset[0],$inout0      # input ^ round[0] ^ offset_i
3602          pxor           @offset[1],@offset[2]
3603         pxor            @offset[1],$inout1
3604          pxor           @offset[2],@offset[3]
3605         pxor            @offset[2],$inout2
3606         pxor            @offset[3],$inout3
3607         $movkey         32($key_),$rndkey0
3608
3609          pxor           $rndkey0l,@offset[0]    # offset_i ^ round[last]
3610          pxor           $rndkey0l,@offset[1]
3611          pxor           $rndkey0l,@offset[2]
3612          pxor           $rndkey0l,@offset[3]
3613
3614         aesdec          $rndkey1,$inout0
3615         aesdec          $rndkey1,$inout1
3616         aesdec          $rndkey1,$inout2
3617         aesdec          $rndkey1,$inout3
3618         $movkey         48($key_),$rndkey1
3619
3620         aesdec          $rndkey0,$inout0
3621         aesdec          $rndkey0,$inout1
3622         aesdec          $rndkey0,$inout2
3623         aesdec          $rndkey0,$inout3
3624         $movkey         64($key_),$rndkey0
3625         jmp             .Locb_dec_loop4
3626
3627 .align  32
3628 .Locb_dec_loop4:
3629         aesdec          $rndkey1,$inout0
3630         aesdec          $rndkey1,$inout1
3631         aesdec          $rndkey1,$inout2
3632         aesdec          $rndkey1,$inout3
3633         $movkey         ($key,%rax),$rndkey1
3634         add             \$32,%rax
3635
3636         aesdec          $rndkey0,$inout0
3637         aesdec          $rndkey0,$inout1
3638         aesdec          $rndkey0,$inout2
3639         aesdec          $rndkey0,$inout3
3640         $movkey         -16($key,%rax),$rndkey0
3641         jnz             .Locb_dec_loop4
3642
3643         aesdec          $rndkey1,$inout0
3644         aesdec          $rndkey1,$inout1
3645         aesdec          $rndkey1,$inout2
3646         aesdec          $rndkey1,$inout3
3647         $movkey         16($key_),$rndkey1
3648         mov             %r10,%rax               # restore twisted rounds
3649
3650         aesdeclast      @offset[0],$inout0
3651         aesdeclast      @offset[1],$inout1
3652         aesdeclast      @offset[2],$inout2
3653         aesdeclast      @offset[3],$inout3
3654         ret
3655 .size   __ocb_decrypt4,.-__ocb_decrypt4
3656
3657 .type   __ocb_decrypt1,\@abi-omnipotent
3658 .align  32
3659 __ocb_decrypt1:
3660          pxor           @offset[5],$inout5      # offset_i
3661          pxor           $rndkey0l,$inout5       # offset_i ^ round[0]
3662         pxor            $inout5,$inout0         # input ^ round[0] ^ offset_i
3663         $movkey         32($key_),$rndkey0
3664
3665         aesdec          $rndkey1,$inout0
3666         $movkey         48($key_),$rndkey1
3667         pxor            $rndkey0l,$inout5       # offset_i ^ round[last]
3668
3669         aesdec          $rndkey0,$inout0
3670         $movkey         64($key_),$rndkey0
3671         jmp             .Locb_dec_loop1
3672
3673 .align  32
3674 .Locb_dec_loop1:
3675         aesdec          $rndkey1,$inout0
3676         $movkey         ($key,%rax),$rndkey1
3677         add             \$32,%rax
3678
3679         aesdec          $rndkey0,$inout0
3680         $movkey         -16($key,%rax),$rndkey0
3681         jnz             .Locb_dec_loop1
3682
3683         aesdec          $rndkey1,$inout0
3684         $movkey         16($key_),$rndkey1      # redundant in tail
3685         mov             %r10,%rax               # restore twisted rounds
3686
3687         aesdeclast      $inout5,$inout0
3688         ret
3689 .size   __ocb_decrypt1,.-__ocb_decrypt1
3690 ___
3691 } }}
3692 \f
3693 ########################################################################
3694 # void $PREFIX_cbc_encrypt (const void *inp, void *out,
3695 #                           size_t length, const AES_KEY *key,
3696 #                           unsigned char *ivp,const int enc);
3697 {
3698 my $frame_size = 0x10 + ($win64?0xa0:0);        # used in decrypt
3699 my ($iv,$in0,$in1,$in2,$in3,$in4)=map("%xmm$_",(10..15));
3700
3701 $code.=<<___;
3702 .globl  ${PREFIX}_cbc_encrypt
3703 .type   ${PREFIX}_cbc_encrypt,\@function,6
3704 .align  16
3705 ${PREFIX}_cbc_encrypt:
3706 .cfi_startproc
3707         test    $len,$len               # check length
3708         jz      .Lcbc_ret
3709
3710         mov     240($key),$rnds_        # key->rounds
3711         mov     $key,$key_              # backup $key
3712         test    %r9d,%r9d               # 6th argument
3713         jz      .Lcbc_decrypt
3714 #--------------------------- CBC ENCRYPT ------------------------------#
3715         movups  ($ivp),$inout0          # load iv as initial state
3716         mov     $rnds_,$rounds
3717         cmp     \$16,$len
3718         jb      .Lcbc_enc_tail
3719         sub     \$16,$len
3720         jmp     .Lcbc_enc_loop
3721 .align  16
3722 .Lcbc_enc_loop:
3723         movups  ($inp),$inout1          # load input
3724         lea     16($inp),$inp
3725         #xorps  $inout1,$inout0
3726 ___
3727         &aesni_generate1("enc",$key,$rounds,$inout0,$inout1);
3728 $code.=<<___;
3729         mov     $rnds_,$rounds          # restore $rounds
3730         mov     $key_,$key              # restore $key
3731         movups  $inout0,0($out)         # store output
3732         lea     16($out),$out
3733         sub     \$16,$len
3734         jnc     .Lcbc_enc_loop
3735         add     \$16,$len
3736         jnz     .Lcbc_enc_tail
3737          pxor   $rndkey0,$rndkey0       # clear register bank
3738          pxor   $rndkey1,$rndkey1
3739         movups  $inout0,($ivp)
3740          pxor   $inout0,$inout0
3741          pxor   $inout1,$inout1
3742         jmp     .Lcbc_ret
3743
3744 .Lcbc_enc_tail:
3745         mov     $len,%rcx       # zaps $key
3746         xchg    $inp,$out       # $inp is %rsi and $out is %rdi now
3747         .long   0x9066A4F3      # rep movsb
3748         mov     \$16,%ecx       # zero tail
3749         sub     $len,%rcx
3750         xor     %eax,%eax
3751         .long   0x9066AAF3      # rep stosb
3752         lea     -16(%rdi),%rdi  # rewind $out by 1 block
3753         mov     $rnds_,$rounds  # restore $rounds
3754         mov     %rdi,%rsi       # $inp and $out are the same
3755         mov     $key_,$key      # restore $key
3756         xor     $len,$len       # len=16
3757         jmp     .Lcbc_enc_loop  # one more spin
3758 \f#--------------------------- CBC DECRYPT ------------------------------#
3759 .align  16
3760 .Lcbc_decrypt:
3761         cmp     \$16,$len
3762         jne     .Lcbc_decrypt_bulk
3763
3764         # handle single block without allocating stack frame,
3765         # useful in ciphertext stealing mode
3766         movdqu  ($inp),$inout0          # load input
3767         movdqu  ($ivp),$inout1          # load iv
3768         movdqa  $inout0,$inout2         # future iv
3769 ___
3770         &aesni_generate1("dec",$key,$rnds_);
3771 $code.=<<___;
3772          pxor   $rndkey0,$rndkey0       # clear register bank
3773          pxor   $rndkey1,$rndkey1
3774         movdqu  $inout2,($ivp)          # store iv
3775         xorps   $inout1,$inout0         # ^=iv
3776          pxor   $inout1,$inout1
3777         movups  $inout0,($out)          # store output
3778          pxor   $inout0,$inout0
3779         jmp     .Lcbc_ret
3780 .align  16
3781 .Lcbc_decrypt_bulk:
3782         lea     (%rsp),%r11             # frame pointer
3783 .cfi_def_cfa_register   %r11
3784         push    %rbp
3785 .cfi_push       %rbp
3786         sub     \$$frame_size,%rsp
3787         and     \$-16,%rsp      # Linux kernel stack can be incorrectly seeded
3788 ___
3789 $code.=<<___ if ($win64);
3790         movaps  %xmm6,0x10(%rsp)
3791         movaps  %xmm7,0x20(%rsp)
3792         movaps  %xmm8,0x30(%rsp)
3793         movaps  %xmm9,0x40(%rsp)
3794         movaps  %xmm10,0x50(%rsp)
3795         movaps  %xmm11,0x60(%rsp)
3796         movaps  %xmm12,0x70(%rsp)
3797         movaps  %xmm13,0x80(%rsp)
3798         movaps  %xmm14,0x90(%rsp)
3799         movaps  %xmm15,0xa0(%rsp)
3800 .Lcbc_decrypt_body:
3801 ___
3802
3803 my $inp_=$key_="%rbp";                  # reassign $key_
3804
3805 $code.=<<___;
3806         mov     $key,$key_              # [re-]backup $key [after reassignment]
3807         movups  ($ivp),$iv
3808         mov     $rnds_,$rounds
3809         cmp     \$0x50,$len
3810         jbe     .Lcbc_dec_tail
3811
3812         $movkey ($key),$rndkey0
3813         movdqu  0x00($inp),$inout0      # load input
3814         movdqu  0x10($inp),$inout1
3815         movdqa  $inout0,$in0
3816         movdqu  0x20($inp),$inout2
3817         movdqa  $inout1,$in1
3818         movdqu  0x30($inp),$inout3
3819         movdqa  $inout2,$in2
3820         movdqu  0x40($inp),$inout4
3821         movdqa  $inout3,$in3
3822         movdqu  0x50($inp),$inout5
3823         movdqa  $inout4,$in4
3824         mov     OPENSSL_ia32cap_P+4(%rip),%r9d
3825         cmp     \$0x70,$len
3826         jbe     .Lcbc_dec_six_or_seven
3827
3828         and     \$`1<<26|1<<22`,%r9d    # isolate XSAVE+MOVBE
3829         sub     \$0x50,$len             # $len is biased by -5*16
3830         cmp     \$`1<<22`,%r9d          # check for MOVBE without XSAVE
3831         je      .Lcbc_dec_loop6_enter   # [which denotes Atom Silvermont]
3832         sub     \$0x20,$len             # $len is biased by -7*16
3833         lea     0x70($key),$key         # size optimization
3834         jmp     .Lcbc_dec_loop8_enter
3835 .align  16
3836 .Lcbc_dec_loop8:
3837         movups  $inout7,($out)
3838         lea     0x10($out),$out
3839 .Lcbc_dec_loop8_enter:
3840         movdqu          0x60($inp),$inout6
3841         pxor            $rndkey0,$inout0
3842         movdqu          0x70($inp),$inout7
3843         pxor            $rndkey0,$inout1
3844         $movkey         0x10-0x70($key),$rndkey1
3845         pxor            $rndkey0,$inout2
3846         mov             \$-1,$inp_
3847         cmp             \$0x70,$len     # is there at least 0x60 bytes ahead?
3848         pxor            $rndkey0,$inout3
3849         pxor            $rndkey0,$inout4
3850         pxor            $rndkey0,$inout5
3851         pxor            $rndkey0,$inout6
3852
3853         aesdec          $rndkey1,$inout0
3854         pxor            $rndkey0,$inout7
3855         $movkey         0x20-0x70($key),$rndkey0
3856         aesdec          $rndkey1,$inout1
3857         aesdec          $rndkey1,$inout2
3858         aesdec          $rndkey1,$inout3
3859         aesdec          $rndkey1,$inout4
3860         aesdec          $rndkey1,$inout5
3861         aesdec          $rndkey1,$inout6
3862         adc             \$0,$inp_
3863         and             \$128,$inp_
3864         aesdec          $rndkey1,$inout7
3865         add             $inp,$inp_
3866         $movkey         0x30-0x70($key),$rndkey1
3867 ___
3868 for($i=1;$i<12;$i++) {
3869 my $rndkeyx = ($i&1)?$rndkey0:$rndkey1;
3870 $code.=<<___    if ($i==7);
3871         cmp             \$11,$rounds
3872 ___
3873 $code.=<<___;
3874         aesdec          $rndkeyx,$inout0
3875         aesdec          $rndkeyx,$inout1
3876         aesdec          $rndkeyx,$inout2
3877         aesdec          $rndkeyx,$inout3
3878         aesdec          $rndkeyx,$inout4
3879         aesdec          $rndkeyx,$inout5
3880         aesdec          $rndkeyx,$inout6
3881         aesdec          $rndkeyx,$inout7
3882         $movkey         `0x30+0x10*$i`-0x70($key),$rndkeyx
3883 ___
3884 $code.=<<___    if ($i<6 || (!($i&1) && $i>7));
3885         nop
3886 ___
3887 $code.=<<___    if ($i==7);
3888         jb              .Lcbc_dec_done
3889 ___
3890 $code.=<<___    if ($i==9);
3891         je              .Lcbc_dec_done
3892 ___
3893 $code.=<<___    if ($i==11);
3894         jmp             .Lcbc_dec_done
3895 ___
3896 }
3897 $code.=<<___;
3898 .align  16
3899 .Lcbc_dec_done:
3900         aesdec          $rndkey1,$inout0
3901         aesdec          $rndkey1,$inout1
3902         pxor            $rndkey0,$iv
3903         pxor            $rndkey0,$in0
3904         aesdec          $rndkey1,$inout2
3905         aesdec          $rndkey1,$inout3
3906         pxor            $rndkey0,$in1
3907         pxor            $rndkey0,$in2
3908         aesdec          $rndkey1,$inout4
3909         aesdec          $rndkey1,$inout5
3910         pxor            $rndkey0,$in3
3911         pxor            $rndkey0,$in4
3912         aesdec          $rndkey1,$inout6
3913         aesdec          $rndkey1,$inout7
3914         movdqu          0x50($inp),$rndkey1
3915
3916         aesdeclast      $iv,$inout0
3917         movdqu          0x60($inp),$iv          # borrow $iv
3918         pxor            $rndkey0,$rndkey1
3919         aesdeclast      $in0,$inout1
3920         pxor            $rndkey0,$iv
3921         movdqu          0x70($inp),$rndkey0     # next IV
3922         aesdeclast      $in1,$inout2
3923         lea             0x80($inp),$inp
3924         movdqu          0x00($inp_),$in0
3925         aesdeclast      $in2,$inout3
3926         aesdeclast      $in3,$inout4
3927         movdqu          0x10($inp_),$in1
3928         movdqu          0x20($inp_),$in2
3929         aesdeclast      $in4,$inout5
3930         aesdeclast      $rndkey1,$inout6
3931         movdqu          0x30($inp_),$in3
3932         movdqu          0x40($inp_),$in4
3933         aesdeclast      $iv,$inout7
3934         movdqa          $rndkey0,$iv            # return $iv
3935         movdqu          0x50($inp_),$rndkey1
3936         $movkey         -0x70($key),$rndkey0
3937
3938         movups          $inout0,($out)          # store output
3939         movdqa          $in0,$inout0
3940         movups          $inout1,0x10($out)
3941         movdqa          $in1,$inout1
3942         movups          $inout2,0x20($out)
3943         movdqa          $in2,$inout2
3944         movups          $inout3,0x30($out)
3945         movdqa          $in3,$inout3
3946         movups          $inout4,0x40($out)
3947         movdqa          $in4,$inout4
3948         movups          $inout5,0x50($out)
3949         movdqa          $rndkey1,$inout5
3950         movups          $inout6,0x60($out)
3951         lea             0x70($out),$out
3952
3953         sub     \$0x80,$len
3954         ja      .Lcbc_dec_loop8
3955
3956         movaps  $inout7,$inout0
3957         lea     -0x70($key),$key
3958         add     \$0x70,$len
3959         jle     .Lcbc_dec_clear_tail_collected
3960         movups  $inout7,($out)
3961         lea     0x10($out),$out
3962         cmp     \$0x50,$len
3963         jbe     .Lcbc_dec_tail
3964
3965         movaps  $in0,$inout0
3966 .Lcbc_dec_six_or_seven:
3967         cmp     \$0x60,$len
3968         ja      .Lcbc_dec_seven
3969
3970         movaps  $inout5,$inout6
3971         call    _aesni_decrypt6
3972         pxor    $iv,$inout0             # ^= IV
3973         movaps  $inout6,$iv
3974         pxor    $in0,$inout1
3975         movdqu  $inout0,($out)
3976         pxor    $in1,$inout2
3977         movdqu  $inout1,0x10($out)
3978          pxor   $inout1,$inout1         # clear register bank
3979         pxor    $in2,$inout3
3980         movdqu  $inout2,0x20($out)
3981          pxor   $inout2,$inout2
3982         pxor    $in3,$inout4
3983         movdqu  $inout3,0x30($out)
3984          pxor   $inout3,$inout3
3985         pxor    $in4,$inout5
3986         movdqu  $inout4,0x40($out)
3987          pxor   $inout4,$inout4
3988         lea     0x50($out),$out
3989         movdqa  $inout5,$inout0
3990          pxor   $inout5,$inout5
3991         jmp     .Lcbc_dec_tail_collected
3992
3993 .align  16
3994 .Lcbc_dec_seven:
3995         movups  0x60($inp),$inout6
3996         xorps   $inout7,$inout7
3997         call    _aesni_decrypt8
3998         movups  0x50($inp),$inout7
3999         pxor    $iv,$inout0             # ^= IV
4000         movups  0x60($inp),$iv
4001         pxor    $in0,$inout1
4002         movdqu  $inout0,($out)
4003         pxor    $in1,$inout2
4004         movdqu  $inout1,0x10($out)
4005          pxor   $inout1,$inout1         # clear register bank
4006         pxor    $in2,$inout3
4007         movdqu  $inout2,0x20($out)
4008          pxor   $inout2,$inout2
4009         pxor    $in3,$inout4
4010         movdqu  $inout3,0x30($out)
4011          pxor   $inout3,$inout3
4012         pxor    $in4,$inout5
4013         movdqu  $inout4,0x40($out)
4014          pxor   $inout4,$inout4
4015         pxor    $inout7,$inout6
4016         movdqu  $inout5,0x50($out)
4017          pxor   $inout5,$inout5
4018         lea     0x60($out),$out
4019         movdqa  $inout6,$inout0
4020          pxor   $inout6,$inout6
4021          pxor   $inout7,$inout7
4022         jmp     .Lcbc_dec_tail_collected
4023
4024 .align  16
4025 .Lcbc_dec_loop6:
4026         movups  $inout5,($out)
4027         lea     0x10($out),$out
4028         movdqu  0x00($inp),$inout0      # load input
4029         movdqu  0x10($inp),$inout1
4030         movdqa  $inout0,$in0
4031         movdqu  0x20($inp),$inout2
4032         movdqa  $inout1,$in1
4033         movdqu  0x30($inp),$inout3
4034         movdqa  $inout2,$in2
4035         movdqu  0x40($inp),$inout4
4036         movdqa  $inout3,$in3
4037         movdqu  0x50($inp),$inout5
4038         movdqa  $inout4,$in4
4039 .Lcbc_dec_loop6_enter:
4040         lea     0x60($inp),$inp
4041         movdqa  $inout5,$inout6
4042
4043         call    _aesni_decrypt6
4044
4045         pxor    $iv,$inout0             # ^= IV
4046         movdqa  $inout6,$iv
4047         pxor    $in0,$inout1
4048         movdqu  $inout0,($out)
4049         pxor    $in1,$inout2
4050         movdqu  $inout1,0x10($out)
4051         pxor    $in2,$inout3
4052         movdqu  $inout2,0x20($out)
4053         pxor    $in3,$inout4
4054         mov     $key_,$key
4055         movdqu  $inout3,0x30($out)
4056         pxor    $in4,$inout5
4057         mov     $rnds_,$rounds
4058         movdqu  $inout4,0x40($out)
4059         lea     0x50($out),$out
4060         sub     \$0x60,$len
4061         ja      .Lcbc_dec_loop6
4062
4063         movdqa  $inout5,$inout0
4064         add     \$0x50,$len
4065         jle     .Lcbc_dec_clear_tail_collected
4066         movups  $inout5,($out)
4067         lea     0x10($out),$out
4068
4069 .Lcbc_dec_tail:
4070         movups  ($inp),$inout0
4071         sub     \$0x10,$len
4072         jbe     .Lcbc_dec_one           # $len is 1*16 or less
4073
4074         movups  0x10($inp),$inout1
4075         movaps  $inout0,$in0
4076         sub     \$0x10,$len
4077         jbe     .Lcbc_dec_two           # $len is 2*16 or less
4078
4079         movups  0x20($inp),$inout2
4080         movaps  $inout1,$in1
4081         sub     \$0x10,$len
4082         jbe     .Lcbc_dec_three         # $len is 3*16 or less
4083
4084         movups  0x30($inp),$inout3
4085         movaps  $inout2,$in2
4086         sub     \$0x10,$len
4087         jbe     .Lcbc_dec_four          # $len is 4*16 or less
4088
4089         movups  0x40($inp),$inout4      # $len is 5*16 or less
4090         movaps  $inout3,$in3
4091         movaps  $inout4,$in4
4092         xorps   $inout5,$inout5
4093         call    _aesni_decrypt6
4094         pxor    $iv,$inout0
4095         movaps  $in4,$iv
4096         pxor    $in0,$inout1
4097         movdqu  $inout0,($out)
4098         pxor    $in1,$inout2
4099         movdqu  $inout1,0x10($out)
4100          pxor   $inout1,$inout1         # clear register bank
4101         pxor    $in2,$inout3
4102         movdqu  $inout2,0x20($out)
4103          pxor   $inout2,$inout2
4104         pxor    $in3,$inout4
4105         movdqu  $inout3,0x30($out)
4106          pxor   $inout3,$inout3
4107         lea     0x40($out),$out
4108         movdqa  $inout4,$inout0
4109          pxor   $inout4,$inout4
4110          pxor   $inout5,$inout5
4111         sub     \$0x10,$len
4112         jmp     .Lcbc_dec_tail_collected
4113
4114 .align  16
4115 .Lcbc_dec_one:
4116         movaps  $inout0,$in0
4117 ___
4118         &aesni_generate1("dec",$key,$rounds);
4119 $code.=<<___;
4120         xorps   $iv,$inout0
4121         movaps  $in0,$iv
4122         jmp     .Lcbc_dec_tail_collected
4123 .align  16
4124 .Lcbc_dec_two:
4125         movaps  $inout1,$in1
4126         call    _aesni_decrypt2
4127         pxor    $iv,$inout0
4128         movaps  $in1,$iv
4129         pxor    $in0,$inout1
4130         movdqu  $inout0,($out)
4131         movdqa  $inout1,$inout0
4132          pxor   $inout1,$inout1         # clear register bank
4133         lea     0x10($out),$out
4134         jmp     .Lcbc_dec_tail_collected
4135 .align  16
4136 .Lcbc_dec_three:
4137         movaps  $inout2,$in2
4138         call    _aesni_decrypt3
4139         pxor    $iv,$inout0
4140         movaps  $in2,$iv
4141         pxor    $in0,$inout1
4142         movdqu  $inout0,($out)
4143         pxor    $in1,$inout2
4144         movdqu  $inout1,0x10($out)
4145          pxor   $inout1,$inout1         # clear register bank
4146         movdqa  $inout2,$inout0
4147          pxor   $inout2,$inout2
4148         lea     0x20($out),$out
4149         jmp     .Lcbc_dec_tail_collected
4150 .align  16
4151 .Lcbc_dec_four:
4152         movaps  $inout3,$in3
4153         call    _aesni_decrypt4
4154         pxor    $iv,$inout0
4155         movaps  $in3,$iv
4156         pxor    $in0,$inout1
4157         movdqu  $inout0,($out)
4158         pxor    $in1,$inout2
4159         movdqu  $inout1,0x10($out)
4160          pxor   $inout1,$inout1         # clear register bank
4161         pxor    $in2,$inout3
4162         movdqu  $inout2,0x20($out)
4163          pxor   $inout2,$inout2
4164         movdqa  $inout3,$inout0
4165          pxor   $inout3,$inout3
4166         lea     0x30($out),$out
4167         jmp     .Lcbc_dec_tail_collected
4168
4169 .align  16
4170 .Lcbc_dec_clear_tail_collected:
4171         pxor    $inout1,$inout1         # clear register bank
4172         pxor    $inout2,$inout2
4173         pxor    $inout3,$inout3
4174 ___
4175 $code.=<<___ if (!$win64);
4176         pxor    $inout4,$inout4         # %xmm6..9
4177         pxor    $inout5,$inout5
4178         pxor    $inout6,$inout6
4179         pxor    $inout7,$inout7
4180 ___
4181 $code.=<<___;
4182 .Lcbc_dec_tail_collected:
4183         movups  $iv,($ivp)
4184         and     \$15,$len
4185         jnz     .Lcbc_dec_tail_partial
4186         movups  $inout0,($out)
4187         pxor    $inout0,$inout0
4188         jmp     .Lcbc_dec_ret
4189 .align  16
4190 .Lcbc_dec_tail_partial:
4191         movaps  $inout0,(%rsp)
4192         pxor    $inout0,$inout0
4193         mov     \$16,%rcx
4194         mov     $out,%rdi
4195         sub     $len,%rcx
4196         lea     (%rsp),%rsi
4197         .long   0x9066A4F3              # rep movsb
4198         movdqa  $inout0,(%rsp)
4199
4200 .Lcbc_dec_ret:
4201         xorps   $rndkey0,$rndkey0       # %xmm0
4202         pxor    $rndkey1,$rndkey1
4203 ___
4204 $code.=<<___ if ($win64);
4205         movaps  0x10(%rsp),%xmm6
4206         movaps  %xmm0,0x10(%rsp)        # clear stack
4207         movaps  0x20(%rsp),%xmm7
4208         movaps  %xmm0,0x20(%rsp)
4209         movaps  0x30(%rsp),%xmm8
4210         movaps  %xmm0,0x30(%rsp)
4211         movaps  0x40(%rsp),%xmm9
4212         movaps  %xmm0,0x40(%rsp)
4213         movaps  0x50(%rsp),%xmm10
4214         movaps  %xmm0,0x50(%rsp)
4215         movaps  0x60(%rsp),%xmm11
4216         movaps  %xmm0,0x60(%rsp)
4217         movaps  0x70(%rsp),%xmm12
4218         movaps  %xmm0,0x70(%rsp)
4219         movaps  0x80(%rsp),%xmm13
4220         movaps  %xmm0,0x80(%rsp)
4221         movaps  0x90(%rsp),%xmm14
4222         movaps  %xmm0,0x90(%rsp)
4223         movaps  0xa0(%rsp),%xmm15
4224         movaps  %xmm0,0xa0(%rsp)
4225 ___
4226 $code.=<<___;
4227         mov     -8(%r11),%rbp
4228 .cfi_restore    %rbp
4229         lea     (%r11),%rsp
4230 .cfi_def_cfa_register   %rsp
4231 .Lcbc_ret:
4232         ret
4233 .cfi_endproc
4234 .size   ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt
4235 ___
4236\f
4237 # int ${PREFIX}_set_decrypt_key(const unsigned char *inp,
4238 #                               int bits, AES_KEY *key)
4239 #
4240 # input:        $inp    user-supplied key
4241 #               $bits   $inp length in bits
4242 #               $key    pointer to key schedule
4243 # output:       %eax    0 denoting success, -1 or -2 - failure (see C)
4244 #               *$key   key schedule
4245 #
4246 { my ($inp,$bits,$key) = @_4args;
4247   $bits =~ s/%r/%e/;
4248
4249 $code.=<<___;
4250 .globl  ${PREFIX}_set_decrypt_key
4251 .type   ${PREFIX}_set_decrypt_key,\@abi-omnipotent
4252 .align  16
4253 ${PREFIX}_set_decrypt_key:
4254 .cfi_startproc
4255         .byte   0x48,0x83,0xEC,0x08     # sub rsp,8
4256 .cfi_adjust_cfa_offset  8
4257         call    __aesni_set_encrypt_key
4258         shl     \$4,$bits               # rounds-1 after _aesni_set_encrypt_key
4259         test    %eax,%eax
4260         jnz     .Ldec_key_ret
4261         lea     16($key,$bits),$inp     # points at the end of key schedule
4262
4263         $movkey ($key),%xmm0            # just swap
4264         $movkey ($inp),%xmm1
4265         $movkey %xmm0,($inp)
4266         $movkey %xmm1,($key)
4267         lea     16($key),$key
4268         lea     -16($inp),$inp
4269
4270 .Ldec_key_inverse:
4271         $movkey ($key),%xmm0            # swap and inverse
4272         $movkey ($inp),%xmm1
4273         aesimc  %xmm0,%xmm0
4274         aesimc  %xmm1,%xmm1
4275         lea     16($key),$key
4276         lea     -16($inp),$inp
4277         $movkey %xmm0,16($inp)
4278         $movkey %xmm1,-16($key)
4279         cmp     $key,$inp
4280         ja      .Ldec_key_inverse
4281
4282         $movkey ($key),%xmm0            # inverse middle
4283         aesimc  %xmm0,%xmm0
4284         pxor    %xmm1,%xmm1
4285         $movkey %xmm0,($inp)
4286         pxor    %xmm0,%xmm0
4287 .Ldec_key_ret:
4288         add     \$8,%rsp
4289 .cfi_adjust_cfa_offset  -8
4290         ret
4291 .cfi_endproc
4292 .LSEH_end_set_decrypt_key:
4293 .size   ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key
4294 ___
4295 \f
4296 # This is based on submission by
4297 #
4298 #       Huang Ying <ying.huang@intel.com>
4299 #       Vinodh Gopal <vinodh.gopal@intel.com>
4300 #       Kahraman Akdemir
4301 #
4302 # Aggressively optimized in respect to aeskeygenassist's critical path
4303 # and is contained in %xmm0-5 to meet Win64 ABI requirement.
4304 #
4305 # int ${PREFIX}_set_encrypt_key(const unsigned char *inp,
4306 #                               int bits, AES_KEY * const key);
4307 #
4308 # input:        $inp    user-supplied key
4309 #               $bits   $inp length in bits
4310 #               $key    pointer to key schedule
4311 # output:       %eax    0 denoting success, -1 or -2 - failure (see C)
4312 #               $bits   rounds-1 (used in aesni_set_decrypt_key)
4313 #               *$key   key schedule
4314 #               $key    pointer to key schedule (used in
4315 #                       aesni_set_decrypt_key)
4316 #
4317 # Subroutine is frame-less, which means that only volatile registers
4318 # are used. Note that it's declared "abi-omnipotent", which means that
4319 # amount of volatile registers is smaller on Windows.
4320 #
4321 $code.=<<___;
4322 .globl  ${PREFIX}_set_encrypt_key
4323 .type   ${PREFIX}_set_encrypt_key,\@abi-omnipotent
4324 .align  16
4325 ${PREFIX}_set_encrypt_key:
4326 __aesni_set_encrypt_key:
4327 .cfi_startproc
4328         .byte   0x48,0x83,0xEC,0x08     # sub rsp,8
4329 .cfi_adjust_cfa_offset  8
4330         mov     \$-1,%rax
4331         test    $inp,$inp
4332         jz      .Lenc_key_ret
4333         test    $key,$key
4334         jz      .Lenc_key_ret
4335
4336         mov     \$`1<<28|1<<11`,%r10d   # AVX and XOP bits
4337         movups  ($inp),%xmm0            # pull first 128 bits of *userKey
4338         xorps   %xmm4,%xmm4             # low dword of xmm4 is assumed 0
4339         and     OPENSSL_ia32cap_P+4(%rip),%r10d
4340         lea     16($key),%rax           # %rax is used as modifiable copy of $key
4341         cmp     \$256,$bits
4342         je      .L14rounds
4343         cmp     \$192,$bits
4344         je      .L12rounds
4345         cmp     \$128,$bits
4346         jne     .Lbad_keybits
4347
4348 .L10rounds:
4349         mov     \$9,$bits                       # 10 rounds for 128-bit key
4350         cmp     \$`1<<28`,%r10d                 # AVX, bit no XOP
4351         je      .L10rounds_alt
4352
4353         $movkey %xmm0,($key)                    # round 0
4354         aeskeygenassist \$0x1,%xmm0,%xmm1       # round 1
4355         call            .Lkey_expansion_128_cold
4356         aeskeygenassist \$0x2,%xmm0,%xmm1       # round 2
4357         call            .Lkey_expansion_128
4358         aeskeygenassist \$0x4,%xmm0,%xmm1       # round 3
4359         call            .Lkey_expansion_128
4360         aeskeygenassist \$0x8,%xmm0,%xmm1       # round 4
4361         call            .Lkey_expansion_128
4362         aeskeygenassist \$0x10,%xmm0,%xmm1      # round 5
4363         call            .Lkey_expansion_128
4364         aeskeygenassist \$0x20,%xmm0,%xmm1      # round 6
4365         call            .Lkey_expansion_128
4366         aeskeygenassist \$0x40,%xmm0,%xmm1      # round 7
4367         call            .Lkey_expansion_128
4368         aeskeygenassist \$0x80,%xmm0,%xmm1      # round 8
4369         call            .Lkey_expansion_128
4370         aeskeygenassist \$0x1b,%xmm0,%xmm1      # round 9
4371         call            .Lkey_expansion_128
4372         aeskeygenassist \$0x36,%xmm0,%xmm1      # round 10
4373         call            .Lkey_expansion_128
4374         $movkey %xmm0,(%rax)
4375         mov     $bits,80(%rax)  # 240(%rdx)
4376         xor     %eax,%eax
4377         jmp     .Lenc_key_ret
4378
4379 .align  16
4380 .L10rounds_alt:
4381         movdqa  .Lkey_rotate(%rip),%xmm5
4382         mov     \$8,%r10d
4383         movdqa  .Lkey_rcon1(%rip),%xmm4
4384         movdqa  %xmm0,%xmm2
4385         movdqu  %xmm0,($key)
4386         jmp     .Loop_key128
4387
4388 .align  16
4389 .Loop_key128:
4390         pshufb          %xmm5,%xmm0
4391         aesenclast      %xmm4,%xmm0
4392         pslld           \$1,%xmm4
4393         lea             16(%rax),%rax
4394
4395         movdqa          %xmm2,%xmm3
4396         pslldq          \$4,%xmm2
4397         pxor            %xmm2,%xmm3
4398         pslldq          \$4,%xmm2
4399         pxor            %xmm2,%xmm3
4400         pslldq          \$4,%xmm2
4401         pxor            %xmm3,%xmm2
4402
4403         pxor            %xmm2,%xmm0
4404         movdqu          %xmm0,-16(%rax)
4405         movdqa          %xmm0,%xmm2
4406
4407         dec     %r10d
4408         jnz     .Loop_key128
4409
4410         movdqa          .Lkey_rcon1b(%rip),%xmm4
4411
4412         pshufb          %xmm5,%xmm0
4413         aesenclast      %xmm4,%xmm0
4414         pslld           \$1,%xmm4
4415
4416         movdqa          %xmm2,%xmm3
4417         pslldq          \$4,%xmm2
4418         pxor            %xmm2,%xmm3
4419         pslldq          \$4,%xmm2
4420         pxor            %xmm2,%xmm3
4421         pslldq          \$4,%xmm2
4422         pxor            %xmm3,%xmm2
4423
4424         pxor            %xmm2,%xmm0
4425         movdqu          %xmm0,(%rax)
4426
4427         movdqa          %xmm0,%xmm2
4428         pshufb          %xmm5,%xmm0
4429         aesenclast      %xmm4,%xmm0
4430
4431         movdqa          %xmm2,%xmm3
4432         pslldq          \$4,%xmm2
4433         pxor            %xmm2,%xmm3
4434         pslldq          \$4,%xmm2
4435         pxor            %xmm2,%xmm3
4436         pslldq          \$4,%xmm2
4437         pxor            %xmm3,%xmm2
4438
4439         pxor            %xmm2,%xmm0
4440         movdqu          %xmm0,16(%rax)
4441
4442         mov     $bits,96(%rax)  # 240($key)
4443         xor     %eax,%eax
4444         jmp     .Lenc_key_ret
4445
4446 .align  16
4447 .L12rounds:
4448         movq    16($inp),%xmm2                  # remaining 1/3 of *userKey
4449         mov     \$11,$bits                      # 12 rounds for 192
4450         cmp     \$`1<<28`,%r10d                 # AVX, but no XOP
4451         je      .L12rounds_alt
4452
4453         $movkey %xmm0,($key)                    # round 0
4454         aeskeygenassist \$0x1,%xmm2,%xmm1       # round 1,2
4455         call            .Lkey_expansion_192a_cold
4456         aeskeygenassist \$0x2,%xmm2,%xmm1       # round 2,3
4457         call            .Lkey_expansion_192b
4458         aeskeygenassist \$0x4,%xmm2,%xmm1       # round 4,5
4459         call            .Lkey_expansion_192a
4460         aeskeygenassist \$0x8,%xmm2,%xmm1       # round 5,6
4461         call            .Lkey_expansion_192b
4462         aeskeygenassist \$0x10,%xmm2,%xmm1      # round 7,8
4463         call            .Lkey_expansion_192a
4464         aeskeygenassist \$0x20,%xmm2,%xmm1      # round 8,9
4465         call            .Lkey_expansion_192b
4466         aeskeygenassist \$0x40,%xmm2,%xmm1      # round 10,11
4467         call            .Lkey_expansion_192a
4468         aeskeygenassist \$0x80,%xmm2,%xmm1      # round 11,12
4469         call            .Lkey_expansion_192b
4470         $movkey %xmm0,(%rax)
4471         mov     $bits,48(%rax)  # 240(%rdx)
4472         xor     %rax, %rax
4473         jmp     .Lenc_key_ret
4474
4475 .align  16
4476 .L12rounds_alt:
4477         movdqa  .Lkey_rotate192(%rip),%xmm5
4478         movdqa  .Lkey_rcon1(%rip),%xmm4
4479         mov     \$8,%r10d
4480         movdqu  %xmm0,($key)
4481         jmp     .Loop_key192
4482
4483 .align  16
4484 .Loop_key192:
4485         movq            %xmm2,0(%rax)
4486         movdqa          %xmm2,%xmm1
4487         pshufb          %xmm5,%xmm2
4488         aesenclast      %xmm4,%xmm2
4489         pslld           \$1, %xmm4
4490         lea             24(%rax),%rax
4491
4492         movdqa          %xmm0,%xmm3
4493         pslldq          \$4,%xmm0
4494         pxor            %xmm0,%xmm3
4495         pslldq          \$4,%xmm0
4496         pxor            %xmm0,%xmm3
4497         pslldq          \$4,%xmm0
4498         pxor            %xmm3,%xmm0
4499
4500         pshufd          \$0xff,%xmm0,%xmm3
4501         pxor            %xmm1,%xmm3
4502         pslldq          \$4,%xmm1
4503         pxor            %xmm1,%xmm3
4504
4505         pxor            %xmm2,%xmm0
4506         pxor            %xmm3,%xmm2
4507         movdqu          %xmm0,-16(%rax)
4508
4509         dec     %r10d
4510         jnz     .Loop_key192
4511
4512         mov     $bits,32(%rax)  # 240($key)
4513         xor     %eax,%eax
4514         jmp     .Lenc_key_ret
4515
4516 .align  16
4517 .L14rounds:
4518         movups  16($inp),%xmm2                  # remaning half of *userKey
4519         mov     \$13,$bits                      # 14 rounds for 256
4520         lea     16(%rax),%rax
4521         cmp     \$`1<<28`,%r10d                 # AVX, but no XOP
4522         je      .L14rounds_alt
4523
4524         $movkey %xmm0,($key)                    # round 0
4525         $movkey %xmm2,16($key)                  # round 1
4526         aeskeygenassist \$0x1,%xmm2,%xmm1       # round 2
4527         call            .Lkey_expansion_256a_cold
4528         aeskeygenassist \$0x1,%xmm0,%xmm1       # round 3
4529         call            .Lkey_expansion_256b
4530         aeskeygenassist \$0x2,%xmm2,%xmm1       # round 4
4531         call            .Lkey_expansion_256a
4532         aeskeygenassist \$0x2,%xmm0,%xmm1       # round 5
4533         call            .Lkey_expansion_256b
4534         aeskeygenassist \$0x4,%xmm2,%xmm1       # round 6
4535         call            .Lkey_expansion_256a
4536         aeskeygenassist \$0x4,%xmm0,%xmm1       # round 7
4537         call            .Lkey_expansion_256b
4538         aeskeygenassist \$0x8,%xmm2,%xmm1       # round 8
4539         call            .Lkey_expansion_256a
4540         aeskeygenassist \$0x8,%xmm0,%xmm1       # round 9
4541         call            .Lkey_expansion_256b
4542         aeskeygenassist \$0x10,%xmm2,%xmm1      # round 10
4543         call            .Lkey_expansion_256a
4544         aeskeygenassist \$0x10,%xmm0,%xmm1      # round 11
4545         call            .Lkey_expansion_256b
4546         aeskeygenassist \$0x20,%xmm2,%xmm1      # round 12
4547         call            .Lkey_expansion_256a
4548         aeskeygenassist \$0x20,%xmm0,%xmm1      # round 13
4549         call            .Lkey_expansion_256b
4550         aeskeygenassist \$0x40,%xmm2,%xmm1      # round 14
4551         call            .Lkey_expansion_256a
4552         $movkey %xmm0,(%rax)
4553         mov     $bits,16(%rax)  # 240(%rdx)
4554         xor     %rax,%rax
4555         jmp     .Lenc_key_ret
4556
4557 .align  16
4558 .L14rounds_alt:
4559         movdqa  .Lkey_rotate(%rip),%xmm5
4560         movdqa  .Lkey_rcon1(%rip),%xmm4
4561         mov     \$7,%r10d
4562         movdqu  %xmm0,0($key)
4563         movdqa  %xmm2,%xmm1
4564         movdqu  %xmm2,16($key)
4565         jmp     .Loop_key256
4566
4567 .align  16
4568 .Loop_key256:
4569         pshufb          %xmm5,%xmm2
4570         aesenclast      %xmm4,%xmm2
4571
4572         movdqa          %xmm0,%xmm3
4573         pslldq          \$4,%xmm0
4574         pxor            %xmm0,%xmm3
4575         pslldq          \$4,%xmm0
4576         pxor            %xmm0,%xmm3
4577         pslldq          \$4,%xmm0
4578         pxor            %xmm3,%xmm0
4579         pslld           \$1,%xmm4
4580
4581         pxor            %xmm2,%xmm0
4582         movdqu          %xmm0,(%rax)
4583
4584         dec     %r10d
4585         jz      .Ldone_key256
4586
4587         pshufd          \$0xff,%xmm0,%xmm2
4588         pxor            %xmm3,%xmm3
4589         aesenclast      %xmm3,%xmm2
4590
4591         movdqa          %xmm1,%xmm3
4592         pslldq          \$4,%xmm1
4593         pxor            %xmm1,%xmm3
4594         pslldq          \$4,%xmm1
4595         pxor            %xmm1,%xmm3
4596         pslldq          \$4,%xmm1
4597         pxor            %xmm3,%xmm1
4598
4599         pxor            %xmm1,%xmm2
4600         movdqu          %xmm2,16(%rax)
4601         lea             32(%rax),%rax
4602         movdqa          %xmm2,%xmm1
4603
4604         jmp     .Loop_key256
4605
4606 .Ldone_key256:
4607         mov     $bits,16(%rax)  # 240($key)
4608         xor     %eax,%eax
4609         jmp     .Lenc_key_ret
4610
4611 .align  16
4612 .Lbad_keybits:
4613         mov     \$-2,%rax
4614 .Lenc_key_ret:
4615         pxor    %xmm0,%xmm0
4616         pxor    %xmm1,%xmm1
4617         pxor    %xmm2,%xmm2
4618         pxor    %xmm3,%xmm3
4619         pxor    %xmm4,%xmm4
4620         pxor    %xmm5,%xmm5
4621         add     \$8,%rsp
4622 .cfi_adjust_cfa_offset  -8
4623         ret
4624 .cfi_endproc
4625 .LSEH_end_set_encrypt_key:
4626 \f
4627 .align  16
4628 .Lkey_expansion_128:
4629         $movkey %xmm0,(%rax)
4630         lea     16(%rax),%rax
4631 .Lkey_expansion_128_cold:
4632         shufps  \$0b00010000,%xmm0,%xmm4
4633         xorps   %xmm4, %xmm0
4634         shufps  \$0b10001100,%xmm0,%xmm4
4635         xorps   %xmm4, %xmm0
4636         shufps  \$0b11111111,%xmm1,%xmm1        # critical path
4637         xorps   %xmm1,%xmm0
4638         ret
4639
4640 .align 16
4641 .Lkey_expansion_192a:
4642         $movkey %xmm0,(%rax)
4643         lea     16(%rax),%rax
4644 .Lkey_expansion_192a_cold:
4645         movaps  %xmm2, %xmm5
4646 .Lkey_expansion_192b_warm:
4647         shufps  \$0b00010000,%xmm0,%xmm4
4648         movdqa  %xmm2,%xmm3
4649         xorps   %xmm4,%xmm0
4650         shufps  \$0b10001100,%xmm0,%xmm4
4651         pslldq  \$4,%xmm3
4652         xorps   %xmm4,%xmm0
4653         pshufd  \$0b01010101,%xmm1,%xmm1        # critical path
4654         pxor    %xmm3,%xmm2
4655         pxor    %xmm1,%xmm0
4656         pshufd  \$0b11111111,%xmm0,%xmm3
4657         pxor    %xmm3,%xmm2
4658         ret
4659
4660 .align 16
4661 .Lkey_expansion_192b:
4662         movaps  %xmm0,%xmm3
4663         shufps  \$0b01000100,%xmm0,%xmm5
4664         $movkey %xmm5,(%rax)
4665         shufps  \$0b01001110,%xmm2,%xmm3
4666         $movkey %xmm3,16(%rax)
4667         lea     32(%rax),%rax
4668         jmp     .Lkey_expansion_192b_warm
4669
4670 .align  16
4671 .Lkey_expansion_256a:
4672         $movkey %xmm2,(%rax)
4673         lea     16(%rax),%rax
4674 .Lkey_expansion_256a_cold:
4675         shufps  \$0b00010000,%xmm0,%xmm4
4676         xorps   %xmm4,%xmm0
4677         shufps  \$0b10001100,%xmm0,%xmm4
4678         xorps   %xmm4,%xmm0
4679         shufps  \$0b11111111,%xmm1,%xmm1        # critical path
4680         xorps   %xmm1,%xmm0
4681         ret
4682
4683 .align 16
4684 .Lkey_expansion_256b:
4685         $movkey %xmm0,(%rax)
4686         lea     16(%rax),%rax
4687
4688         shufps  \$0b00010000,%xmm2,%xmm4
4689         xorps   %xmm4,%xmm2
4690         shufps  \$0b10001100,%xmm2,%xmm4
4691         xorps   %xmm4,%xmm2
4692         shufps  \$0b10101010,%xmm1,%xmm1        # critical path
4693         xorps   %xmm1,%xmm2
4694         ret
4695 .size   ${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key
4696 .size   __aesni_set_encrypt_key,.-__aesni_set_encrypt_key
4697 ___
4698 }
4699 \f
4700 $code.=<<___;
4701 .align  64
4702 .Lbswap_mask:
4703         .byte   15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
4704 .Lincrement32:
4705         .long   6,6,6,0
4706 .Lincrement64:
4707         .long   1,0,0,0
4708 .Lxts_magic:
4709         .long   0x87,0,1,0
4710 .Lincrement1:
4711         .byte   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
4712 .Lkey_rotate:
4713         .long   0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d
4714 .Lkey_rotate192:
4715         .long   0x04070605,0x04070605,0x04070605,0x04070605
4716 .Lkey_rcon1:
4717         .long   1,1,1,1
4718 .Lkey_rcon1b:
4719         .long   0x1b,0x1b,0x1b,0x1b
4720
4721 .asciz  "AES for Intel AES-NI, CRYPTOGAMS by <appro\@openssl.org>"
4722 .align  64
4723 ___
4724
4725 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
4726 #               CONTEXT *context,DISPATCHER_CONTEXT *disp)
4727 if ($win64) {
4728 $rec="%rcx";
4729 $frame="%rdx";
4730 $context="%r8";
4731 $disp="%r9";
4732
4733 $code.=<<___;
4734 .extern __imp_RtlVirtualUnwind
4735 ___
4736 $code.=<<___ if ($PREFIX eq "aesni");
4737 .type   ecb_ccm64_se_handler,\@abi-omnipotent
4738 .align  16
4739 ecb_ccm64_se_handler:
4740         push    %rsi
4741         push    %rdi
4742         push    %rbx
4743         push    %rbp
4744         push    %r12
4745         push    %r13
4746         push    %r14
4747         push    %r15
4748         pushfq
4749         sub     \$64,%rsp
4750
4751         mov     120($context),%rax      # pull context->Rax
4752         mov     248($context),%rbx      # pull context->Rip
4753
4754         mov     8($disp),%rsi           # disp->ImageBase
4755         mov     56($disp),%r11          # disp->HandlerData
4756
4757         mov     0(%r11),%r10d           # HandlerData[0]
4758         lea     (%rsi,%r10),%r10        # prologue label
4759         cmp     %r10,%rbx               # context->Rip<prologue label
4760         jb      .Lcommon_seh_tail
4761
4762         mov     152($context),%rax      # pull context->Rsp
4763
4764         mov     4(%r11),%r10d           # HandlerData[1]
4765         lea     (%rsi,%r10),%r10        # epilogue label
4766         cmp     %r10,%rbx               # context->Rip>=epilogue label
4767         jae     .Lcommon_seh_tail
4768
4769         lea     0(%rax),%rsi            # %xmm save area
4770         lea     512($context),%rdi      # &context.Xmm6
4771         mov     \$8,%ecx                # 4*sizeof(%xmm0)/sizeof(%rax)
4772         .long   0xa548f3fc              # cld; rep movsq
4773         lea     0x58(%rax),%rax         # adjust stack pointer
4774
4775         jmp     .Lcommon_seh_tail
4776 .size   ecb_ccm64_se_handler,.-ecb_ccm64_se_handler
4777
4778 .type   ctr_xts_se_handler,\@abi-omnipotent
4779 .align  16
4780 ctr_xts_se_handler:
4781         push    %rsi
4782         push    %rdi
4783         push    %rbx
4784         push    %rbp
4785         push    %r12
4786         push    %r13
4787         push    %r14
4788         push    %r15
4789         pushfq
4790         sub     \$64,%rsp
4791
4792         mov     120($context),%rax      # pull context->Rax
4793         mov     248($context),%rbx      # pull context->Rip
4794
4795         mov     8($disp),%rsi           # disp->ImageBase
4796         mov     56($disp),%r11          # disp->HandlerData
4797
4798         mov     0(%r11),%r10d           # HandlerData[0]
4799         lea     (%rsi,%r10),%r10        # prologue lable
4800         cmp     %r10,%rbx               # context->Rip<prologue label
4801         jb      .Lcommon_seh_tail
4802
4803         mov     152($context),%rax      # pull context->Rsp
4804
4805         mov     4(%r11),%r10d           # HandlerData[1]
4806         lea     (%rsi,%r10),%r10        # epilogue label
4807         cmp     %r10,%rbx               # context->Rip>=epilogue label
4808         jae     .Lcommon_seh_tail
4809
4810         mov     208($context),%rax      # pull context->R11
4811
4812         lea     -0xa8(%rax),%rsi        # %xmm save area
4813         lea     512($context),%rdi      # & context.Xmm6
4814         mov     \$20,%ecx               # 10*sizeof(%xmm0)/sizeof(%rax)
4815         .long   0xa548f3fc              # cld; rep movsq
4816
4817         mov     -8(%rax),%rbp           # restore saved %rbp
4818         mov     %rbp,160($context)      # restore context->Rbp
4819         jmp     .Lcommon_seh_tail
4820 .size   ctr_xts_se_handler,.-ctr_xts_se_handler
4821
4822 .type   ocb_se_handler,\@abi-omnipotent
4823 .align  16
4824 ocb_se_handler:
4825         push    %rsi
4826         push    %rdi
4827         push    %rbx
4828         push    %rbp
4829         push    %r12
4830         push    %r13
4831         push    %r14
4832         push    %r15
4833         pushfq
4834         sub     \$64,%rsp
4835
4836         mov     120($context),%rax      # pull context->Rax
4837         mov     248($context),%rbx      # pull context->Rip
4838
4839         mov     8($disp),%rsi           # disp->ImageBase
4840         mov     56($disp),%r11          # disp->HandlerData
4841
4842         mov     0(%r11),%r10d           # HandlerData[0]
4843         lea     (%rsi,%r10),%r10        # prologue lable
4844         cmp     %r10,%rbx               # context->Rip<prologue label
4845         jb      .Lcommon_seh_tail
4846
4847         mov     4(%r11),%r10d           # HandlerData[1]
4848         lea     (%rsi,%r10),%r10        # epilogue label
4849         cmp     %r10,%rbx               # context->Rip>=epilogue label
4850         jae     .Lcommon_seh_tail
4851
4852         mov     8(%r11),%r10d           # HandlerData[2]
4853         lea     (%rsi,%r10),%r10
4854         cmp     %r10,%rbx               # context->Rip>=pop label
4855         jae     .Locb_no_xmm
4856
4857         mov     152($context),%rax      # pull context->Rsp
4858
4859         lea     (%rax),%rsi             # %xmm save area
4860         lea     512($context),%rdi      # & context.Xmm6
4861         mov     \$20,%ecx               # 10*sizeof(%xmm0)/sizeof(%rax)
4862         .long   0xa548f3fc              # cld; rep movsq
4863         lea     0xa0+0x28(%rax),%rax
4864
4865 .Locb_no_xmm:
4866         mov     -8(%rax),%rbx
4867         mov     -16(%rax),%rbp
4868         mov     -24(%rax),%r12
4869         mov     -32(%rax),%r13
4870         mov     -40(%rax),%r14
4871
4872         mov     %rbx,144($context)      # restore context->Rbx
4873         mov     %rbp,160($context)      # restore context->Rbp
4874         mov     %r12,216($context)      # restore context->R12
4875         mov     %r13,224($context)      # restore context->R13
4876         mov     %r14,232($context)      # restore context->R14
4877
4878         jmp     .Lcommon_seh_tail
4879 .size   ocb_se_handler,.-ocb_se_handler
4880 ___
4881 $code.=<<___;
4882 .type   cbc_se_handler,\@abi-omnipotent
4883 .align  16
4884 cbc_se_handler:
4885         push    %rsi
4886         push    %rdi
4887         push    %rbx
4888         push    %rbp
4889         push    %r12
4890         push    %r13
4891         push    %r14
4892         push    %r15
4893         pushfq
4894         sub     \$64,%rsp
4895
4896         mov     152($context),%rax      # pull context->Rsp
4897         mov     248($context),%rbx      # pull context->Rip
4898
4899         lea     .Lcbc_decrypt_bulk(%rip),%r10
4900         cmp     %r10,%rbx               # context->Rip<"prologue" label
4901         jb      .Lcommon_seh_tail
4902
4903         mov     120($context),%rax      # pull context->Rax
4904
4905         lea     .Lcbc_decrypt_body(%rip),%r10
4906         cmp     %r10,%rbx               # context->Rip<cbc_decrypt_body
4907         jb      .Lcommon_seh_tail
4908
4909         mov     152($context),%rax      # pull context->Rsp
4910
4911         lea     .Lcbc_ret(%rip),%r10
4912         cmp     %r10,%rbx               # context->Rip>="epilogue" label
4913         jae     .Lcommon_seh_tail
4914
4915         lea     16(%rax),%rsi           # %xmm save area
4916         lea     512($context),%rdi      # &context.Xmm6
4917         mov     \$20,%ecx               # 10*sizeof(%xmm0)/sizeof(%rax)
4918         .long   0xa548f3fc              # cld; rep movsq
4919
4920         mov     208($context),%rax      # pull context->R11
4921
4922         mov     -8(%rax),%rbp           # restore saved %rbp
4923         mov     %rbp,160($context)      # restore context->Rbp
4924
4925 .Lcommon_seh_tail:
4926         mov     8(%rax),%rdi
4927         mov     16(%rax),%rsi
4928         mov     %rax,152($context)      # restore context->Rsp
4929         mov     %rsi,168($context)      # restore context->Rsi
4930         mov     %rdi,176($context)      # restore context->Rdi
4931
4932         mov     40($disp),%rdi          # disp->ContextRecord
4933         mov     $context,%rsi           # context
4934         mov     \$154,%ecx              # sizeof(CONTEXT)
4935         .long   0xa548f3fc              # cld; rep movsq
4936
4937         mov     $disp,%rsi
4938         xor     %rcx,%rcx               # arg1, UNW_FLAG_NHANDLER
4939         mov     8(%rsi),%rdx            # arg2, disp->ImageBase
4940         mov     0(%rsi),%r8             # arg3, disp->ControlPc
4941         mov     16(%rsi),%r9            # arg4, disp->FunctionEntry
4942         mov     40(%rsi),%r10           # disp->ContextRecord
4943         lea     56(%rsi),%r11           # &disp->HandlerData
4944         lea     24(%rsi),%r12           # &disp->EstablisherFrame
4945         mov     %r10,32(%rsp)           # arg5
4946         mov     %r11,40(%rsp)           # arg6
4947         mov     %r12,48(%rsp)           # arg7
4948         mov     %rcx,56(%rsp)           # arg8, (NULL)
4949         call    *__imp_RtlVirtualUnwind(%rip)
4950
4951         mov     \$1,%eax                # ExceptionContinueSearch
4952         add     \$64,%rsp
4953         popfq
4954         pop     %r15
4955         pop     %r14
4956         pop     %r13
4957         pop     %r12
4958         pop     %rbp
4959         pop     %rbx
4960         pop     %rdi
4961         pop     %rsi
4962         ret
4963 .size   cbc_se_handler,.-cbc_se_handler
4964
4965 .section        .pdata
4966 .align  4
4967 ___
4968 $code.=<<___ if ($PREFIX eq "aesni");
4969         .rva    .LSEH_begin_aesni_ecb_encrypt
4970         .rva    .LSEH_end_aesni_ecb_encrypt
4971         .rva    .LSEH_info_ecb
4972
4973         .rva    .LSEH_begin_aesni_ccm64_encrypt_blocks
4974         .rva    .LSEH_end_aesni_ccm64_encrypt_blocks
4975         .rva    .LSEH_info_ccm64_enc
4976
4977         .rva    .LSEH_begin_aesni_ccm64_decrypt_blocks
4978         .rva    .LSEH_end_aesni_ccm64_decrypt_blocks
4979         .rva    .LSEH_info_ccm64_dec
4980
4981         .rva    .LSEH_begin_aesni_ctr32_encrypt_blocks
4982         .rva    .LSEH_end_aesni_ctr32_encrypt_blocks
4983         .rva    .LSEH_info_ctr32
4984
4985         .rva    .LSEH_begin_aesni_xts_encrypt
4986         .rva    .LSEH_end_aesni_xts_encrypt
4987         .rva    .LSEH_info_xts_enc
4988
4989         .rva    .LSEH_begin_aesni_xts_decrypt
4990         .rva    .LSEH_end_aesni_xts_decrypt
4991         .rva    .LSEH_info_xts_dec
4992
4993         .rva    .LSEH_begin_aesni_ocb_encrypt
4994         .rva    .LSEH_end_aesni_ocb_encrypt
4995         .rva    .LSEH_info_ocb_enc
4996
4997         .rva    .LSEH_begin_aesni_ocb_decrypt
4998         .rva    .LSEH_end_aesni_ocb_decrypt
4999         .rva    .LSEH_info_ocb_dec
5000 ___
5001 $code.=<<___;
5002         .rva    .LSEH_begin_${PREFIX}_cbc_encrypt
5003         .rva    .LSEH_end_${PREFIX}_cbc_encrypt
5004         .rva    .LSEH_info_cbc
5005
5006         .rva    ${PREFIX}_set_decrypt_key
5007         .rva    .LSEH_end_set_decrypt_key
5008         .rva    .LSEH_info_key
5009
5010         .rva    ${PREFIX}_set_encrypt_key
5011         .rva    .LSEH_end_set_encrypt_key
5012         .rva    .LSEH_info_key
5013 .section        .xdata
5014 .align  8
5015 ___
5016 $code.=<<___ if ($PREFIX eq "aesni");
5017 .LSEH_info_ecb:
5018         .byte   9,0,0,0
5019         .rva    ecb_ccm64_se_handler
5020         .rva    .Lecb_enc_body,.Lecb_enc_ret            # HandlerData[]
5021 .LSEH_info_ccm64_enc:
5022         .byte   9,0,0,0
5023         .rva    ecb_ccm64_se_handler
5024         .rva    .Lccm64_enc_body,.Lccm64_enc_ret        # HandlerData[]
5025 .LSEH_info_ccm64_dec:
5026         .byte   9,0,0,0
5027         .rva    ecb_ccm64_se_handler
5028         .rva    .Lccm64_dec_body,.Lccm64_dec_ret        # HandlerData[]
5029 .LSEH_info_ctr32:
5030         .byte   9,0,0,0
5031         .rva    ctr_xts_se_handler
5032         .rva    .Lctr32_body,.Lctr32_epilogue           # HandlerData[]
5033 .LSEH_info_xts_enc:
5034         .byte   9,0,0,0
5035         .rva    ctr_xts_se_handler
5036         .rva    .Lxts_enc_body,.Lxts_enc_epilogue       # HandlerData[]
5037 .LSEH_info_xts_dec:
5038         .byte   9,0,0,0
5039         .rva    ctr_xts_se_handler
5040         .rva    .Lxts_dec_body,.Lxts_dec_epilogue       # HandlerData[]
5041 .LSEH_info_ocb_enc:
5042         .byte   9,0,0,0
5043         .rva    ocb_se_handler
5044         .rva    .Locb_enc_body,.Locb_enc_epilogue       # HandlerData[]
5045         .rva    .Locb_enc_pop
5046         .long   0
5047 .LSEH_info_ocb_dec:
5048         .byte   9,0,0,0
5049         .rva    ocb_se_handler
5050         .rva    .Locb_dec_body,.Locb_dec_epilogue       # HandlerData[]
5051         .rva    .Locb_dec_pop
5052         .long   0
5053 ___
5054 $code.=<<___;
5055 .LSEH_info_cbc:
5056         .byte   9,0,0,0
5057         .rva    cbc_se_handler
5058 .LSEH_info_key:
5059         .byte   0x01,0x04,0x01,0x00
5060         .byte   0x04,0x02,0x00,0x00     # sub rsp,8
5061 ___
5062 }
5063
5064 sub rex {
5065   local *opcode=shift;
5066   my ($dst,$src)=@_;
5067   my $rex=0;
5068
5069     $rex|=0x04                  if($dst>=8);
5070     $rex|=0x01                  if($src>=8);
5071     push @opcode,$rex|0x40      if($rex);
5072 }
5073
5074 sub aesni {
5075   my $line=shift;
5076   my @opcode=(0x66);
5077
5078     if ($line=~/(aeskeygenassist)\s+\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
5079         rex(\@opcode,$4,$3);
5080         push @opcode,0x0f,0x3a,0xdf;
5081         push @opcode,0xc0|($3&7)|(($4&7)<<3);   # ModR/M
5082         my $c=$2;
5083         push @opcode,$c=~/^0/?oct($c):$c;
5084         return ".byte\t".join(',',@opcode);
5085     }
5086     elsif ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) {
5087         my %opcodelet = (
5088                 "aesimc" => 0xdb,
5089                 "aesenc" => 0xdc,       "aesenclast" => 0xdd,
5090                 "aesdec" => 0xde,       "aesdeclast" => 0xdf
5091         );
5092         return undef if (!defined($opcodelet{$1}));
5093         rex(\@opcode,$3,$2);
5094         push @opcode,0x0f,0x38,$opcodelet{$1};
5095         push @opcode,0xc0|($2&7)|(($3&7)<<3);   # ModR/M
5096         return ".byte\t".join(',',@opcode);
5097     }
5098     elsif ($line=~/(aes[a-z]+)\s+([0x1-9a-fA-F]*)\(%rsp\),\s*%xmm([0-9]+)/) {
5099         my %opcodelet = (
5100                 "aesenc" => 0xdc,       "aesenclast" => 0xdd,
5101                 "aesdec" => 0xde,       "aesdeclast" => 0xdf
5102         );
5103         return undef if (!defined($opcodelet{$1}));
5104         my $off = $2;
5105         push @opcode,0x44 if ($3>=8);
5106         push @opcode,0x0f,0x38,$opcodelet{$1};
5107         push @opcode,0x44|(($3&7)<<3),0x24;     # ModR/M
5108         push @opcode,($off=~/^0/?oct($off):$off)&0xff;
5109         return ".byte\t".join(',',@opcode);
5110     }
5111     return $line;
5112 }
5113
5114 sub movbe {
5115         ".byte  0x0f,0x38,0xf1,0x44,0x24,".shift;
5116 }
5117
5118 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
5119 $code =~ s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/gem;
5120 #$code =~ s/\bmovbe\s+%eax/bswap %eax; mov %eax/gm;     # debugging artefact
5121 $code =~ s/\bmovbe\s+%eax,\s*([0-9]+)\(%rsp\)/movbe($1)/gem;
5122
5123 print $code;
5124
5125 close STDOUT;