x86_64 assembly pack: fill some blanks in Ryzen results.
[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    0.38    0.49
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&nb