Following the license change, modify the boilerplates in crypto/aes/
[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 Apache License 2.0 (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 # "straightforward" 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 instructions
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 # utilizes 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 # Knights L     2.54/0.77       0.78    0.85    -       1.50
183 # Goldmont      3.82/1.26       1.26    1.29    1.29    1.50
184 # Bulldozer     5.77/0.70       0.72    0.90    0.70    0.95
185 # Ryzen         2.71/0.35       0.35    0.44    0.38    0.49
186 #
187 # (*)   Atom Silvermont ECB result is suboptimal because of penalties
188 #       incurred by operations on %xmm8-15. As ECB is not considered
189 #       critical, nothing was done to mitigate the problem.
190
191 $PREFIX="aesni";        # if $PREFIX is set to "AES", the script
192                         # generates drop-in replacement for
193                         # crypto/aes/asm/aes-x86_64.pl:-)
194
195 $flavour = shift;
196 $output  = shift;
197 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
198
199 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
200
201 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
202 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
203 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
204 die "can't locate x86_64-xlate.pl";
205
206 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
207 *STDOUT=*OUT;
208
209 $movkey = $PREFIX eq "aesni" ? "movups" : "movups";
210 @_4args=$win64? ("%rcx","%rdx","%r8", "%r9") :  # Win64 order
211                 ("%rdi","%rsi","%rdx","%rcx");  # Unix order
212
213 $code=".text\n";
214 $code.=".extern OPENSSL_ia32cap_P\n";
215
216 $rounds="%eax"; # input to and changed by aesni_[en|de]cryptN !!!
217 # this is natural Unix argument order for public $PREFIX_[ecb|cbc]_encrypt ...
218 $inp="%rdi";
219 $out="%rsi";
220 $len="%rdx";
221 $key="%rcx";    # input to and changed by aesni_[en|de]cryptN !!!
222 $ivp="%r8";     # cbc, ctr, ...
223
224 $rnds_="%r10d"; # backup copy for $rounds
225 $key_="%r11";   # backup copy for $key
226
227 # %xmm register layout
228 $rndkey0="%xmm0";       $rndkey1="%xmm1";
229 $inout0="%xmm2";        $inout1="%xmm3";
230 $inout2="%xmm4";        $inout3="%xmm5";
231 $inout4="%xmm6";        $inout5="%xmm7";
232 $inout6="%xmm8";        $inout7="%xmm9";
233
234 $in2="%xmm6";           $in1="%xmm7";   # used in CBC decrypt, CTR, ...
235 $in0="%xmm8";           $iv="%xmm9";
236 \f
237 # Inline version of internal aesni_[en|de]crypt1.
238 #
239 # Why folded loop? Because aes[enc|dec] is slow enough to accommodate
240 # cycles which take care of loop variables...
241 { my $sn;
242 sub aesni_generate1 {
243 my ($p,$key,$rounds,$inout,$ivec)=@_;   $inout=$inout0 if (!defined($inout));
244 ++$sn;
245 $code.=<<___;
246         $movkey ($key),$rndkey0
247         $movkey 16($key),$rndkey1
248 ___
249 $code.=<<___ if (defined($ivec));
250         xorps   $rndkey0,$ivec
251         lea     32($key),$key
252         xorps   $ivec,$inout
253 ___
254 $code.=<<___ if (!defined($ivec));
255         lea     32($key),$key
256         xorps   $rndkey0,$inout
257 ___
258 $code.=<<___;
259 .Loop_${p}1_$sn:
260         aes${p} $rndkey1,$inout
261         dec     $rounds
262         $movkey ($key),$rndkey1
263         lea     16($key),$key
264         jnz     .Loop_${p}1_$sn # loop body is 16 bytes
265         aes${p}last     $rndkey1,$inout
266 ___
267 }}
268 # void $PREFIX_[en|de]crypt (const void *inp,void *out,const AES_KEY *key);
269 #
270 { my ($inp,$out,$key) = @_4args;
271
272 $code.=<<___;
273 .globl  ${PREFIX}_encrypt
274 .type   ${PREFIX}_encrypt,\@abi-omnipotent
275 .align  16
276 ${PREFIX}_encrypt:
277         movups  ($inp),$inout0          # load input
278         mov     240($key),$rounds       # key->rounds
279 ___
280         &aesni_generate1("enc",$key,$rounds);
281 $code.=<<___;
282          pxor   $rndkey0,$rndkey0       # clear register bank
283          pxor   $rndkey1,$rndkey1
284         movups  $inout0,($out)          # output
285          pxor   $inout0,$inout0
286         ret
287 .size   ${PREFIX}_encrypt,.-${PREFIX}_encrypt
288
289 .globl  ${PREFIX}_decrypt
290 .type   ${PREFIX}_decrypt,\@abi-omnipotent
291 .align  16
292 ${PREFIX}_decrypt:
293         movups  ($inp),$inout0          # load input
294         mov     240($key),$rounds       # key->rounds
295 ___
296         &aesni_generate1("dec",$key,$rounds);
297 $code.=<<___;
298          pxor   $rndkey0,$rndkey0       # clear register bank
299          pxor   $rndkey1,$rndkey1
300         movups  $inout0,($out)          # output
301          pxor   $inout0,$inout0
302         ret
303 .size   ${PREFIX}_decrypt, .-${PREFIX}_decrypt
304 ___
305 }
306 \f
307 # _aesni_[en|de]cryptN are private interfaces, N denotes interleave
308 # factor. Why 3x subroutine were originally used in loops? Even though
309 # aes[enc|dec] latency was originally 6, it could be scheduled only
310 # every *2nd* cycle. Thus 3x interleave was the one providing optimal
311 # utilization, i.e. when subroutine's throughput is virtually same as
312 # of non-interleaved subroutine [for number of input blocks up to 3].
313 # This is why it originally made no sense to implement 2x subroutine.
314 # But times change and it became appropriate to spend extra 192 bytes
315 # on 2x subroutine on Atom Silvermont account. For processors that
316 # can schedule aes[enc|dec] every cycle optimal interleave factor
317 # equals to corresponding instructions latency. 8x is optimal for
318 # * Bridge and "super-optimal" for other Intel CPUs...
319
320 sub aesni_generate2 {
321 my $dir=shift;
322 # As already mentioned it takes in $key and $rounds, which are *not*
323 # preserved. $inout[0-1] is cipher/clear text...
324 $code.=<<___;
325 .type   _aesni_${dir}rypt2,\@abi-omnipotent
326 .align  16
327 _aesni_${dir}rypt2:
328         $movkey ($key),$rndkey0
329         shl     \$4,$rounds
330         $movkey 16($key),$rndkey1
331         xorps   $rndkey0,$inout0
332         xorps   $rndkey0,$inout1
333         $movkey 32($key),$rndkey0
334         lea     32($key,$rounds),$key
335         neg     %rax                            # $rounds
336         add     \$16,%rax
337
338 .L${dir}_loop2:
339         aes${dir}       $rndkey1,$inout0
340         aes${dir}       $rndkey1,$inout1
341         $movkey         ($key,%rax),$rndkey1
342         add             \$32,%rax
343         aes${dir}       $rndkey0,$inout0
344         aes${dir}       $rndkey0,$inout1
345         $movkey         -16($key,%rax),$rndkey0
346         jnz             .L${dir}_loop2
347
348         aes${dir}       $rndkey1,$inout0
349         aes${dir}       $rndkey1,$inout1
350         aes${dir}last   $rndkey0,$inout0
351         aes${dir}last   $rndkey0,$inout1
352         ret
353 .size   _aesni_${dir}rypt2,.-_aesni_${dir}rypt2
354 ___
355 }
356 sub aesni_generate3 {
357 my $dir=shift;
358 # As already mentioned it takes in $key and $rounds, which are *not*
359 # preserved. $inout[0-2] is cipher/clear text...
360 $code.=<<___;
361 .type   _aesni_${dir}rypt3,\@abi-omnipotent
362 .align  16
363 _aesni_${dir}rypt3:
364         $movkey ($key),$rndkey0
365         shl     \$4,$rounds
366         $movkey 16($key),$rndkey1
367         xorps   $rndkey0,$inout0
368         xorps   $rndkey0,$inout1
369         xorps   $rndkey0,$inout2
370         $movkey 32($key),$rndkey0
371         lea     32($key,$rounds),$key
372         neg     %rax                            # $rounds
373         add     \$16,%rax
374
375 .L${dir}_loop3:
376         aes${dir}       $rndkey1,$inout0
377         aes${dir}       $rndkey1,$inout1
378         aes${dir}       $rndkey1,$inout2
379         $movkey         ($key,%rax),$rndkey1
380         add             \$32,%rax
381         aes${dir}       $rndkey0,$inout0
382         aes${dir}       $rndkey0,$inout1
383         aes${dir}       $rndkey0,$inout2
384         $movkey         -16($key,%rax),$rndkey0
385         jnz             .L${dir}_loop3
386
387         aes${dir}       $rndkey1,$inout0
388         aes${dir}       $rndkey1,$inout1
389         aes${dir}       $rndkey1,$inout2
390         aes${dir}last   $rndkey0,$inout0
391         aes${dir}last   $rndkey0,$inout1
392         aes${dir}last   $rndkey0,$inout2
393         ret
394 .size   _aesni_${dir}rypt3,.-_aesni_${dir}rypt3
395 ___
396 }
397 # 4x interleave is implemented to improve small block performance,
398 # most notably [and naturally] 4 block by ~30%. One can argue that one
399 # should have implemented 5x as well, but improvement would be <20%,
400 # so it's not worth it...
401 sub aesni_generate4 {
402 my $dir=shift;
403 # As already mentioned it takes in $key and $rounds, which are *not*
404 # preserved. $inout[0-3] is cipher/clear text...
405 $code.=<<___;
406 .type   _aesni_${dir}rypt4,\@abi-omnipotent
407 .align  16
408 _aesni_${dir}rypt4:
409         $movkey ($key),$rndkey0
410         shl     \$4,$rounds
411         $movkey 16($key),$rndkey1
412         xorps   $rndkey0,$inout0
413         xorps   $rndkey0,$inout1
414         xorps   $rndkey0,$inout2
415         xorps   $rndkey0,$inout3
416         $movkey 32($key),$rndkey0
417         lea     32($key,$rounds),$key
418         neg     %rax                            # $rounds
419         .byte   0x0f,0x1f,0x00
420         add     \$16,%rax
421
422 .L${dir}_loop4:
423         aes${dir}       $rndkey1,$inout0
424         aes${dir}       $rndkey1,$inout1
425         aes${dir}       $rndkey1,$inout2
426         aes${dir}       $rndkey1,$inout3
427         $movkey         ($key,%rax),$rndkey1
428         add             \$32,%rax
429         aes${dir}       $rndkey0,$inout0
430         aes${dir}       $rndkey0,$inout1
431         aes${dir}       $rndkey0,$inout2
432         aes${dir}       $rndkey0,$inout3
433         $movkey         -16($key,%rax),$rndkey0
434         jnz             .L${dir}_loop4
435
436         aes${dir}       $rndkey1,$inout0
437         aes${dir}       $rndkey1,$inout1
438         aes${dir}       $rndkey1,$inout2
439         aes${dir}       $rndkey1,$inout3
440         aes${dir}last   $rndkey0,$inout0
441         aes${dir}last   $rndkey0,$inout1
442         aes${dir}last   $rndkey0,$inout2
443         aes${dir}last   $rndkey0,$inout3
444         ret
445 .size   _aesni_${dir}rypt4,.-_aesni_${dir}rypt4
446 ___
447 }
448 sub aesni_generate6 {
449 my $dir=shift;
450 # As already mentioned it takes in $key and $rounds, which are *not*
451 # preserved. $inout[0-5] is cipher/clear text...
452 $code.=<<___;
453 .type   _aesni_${dir}rypt6,\@abi-omnipotent
454 .align  16
455 _aesni_${dir}rypt6:
456         $movkey         ($key),$rndkey0
457         shl             \$4,$rounds
458         $movkey         16($key),$rndkey1
459         xorps           $rndkey0,$inout0
460         pxor            $rndkey0,$inout1
461         pxor            $rndkey0,$inout2
462         aes${dir}       $rndkey1,$inout0
463         lea             32($key,$rounds),$key
464         neg             %rax                    # $rounds
465         aes${dir}       $rndkey1,$inout1
466         pxor            $rndkey0,$inout3
467         pxor            $rndkey0,$inout4
468         aes${dir}       $rndkey1,$inout2
469         pxor            $rndkey0,$inout5
470         $movkey         ($key,%rax),$rndkey0
471         add             \$16,%rax
472         jmp             .L${dir}_loop6_enter
473 .align  16
474 .L${dir}_loop6:
475         aes${dir}       $rndkey1,$inout0
476         aes${dir}       $rndkey1,$inout1
477         aes${dir}       $rndkey1,$inout2
478 .L${dir}_loop6_enter:
479         aes${dir}       $rndkey1,$inout3
480         aes${dir}       $rndkey1,$inout4
481         aes${dir}       $rndkey1,$inout5
482         $movkey         ($key,%rax),$rndkey1
483         add             \$32,%rax
484         aes${dir}       $rndkey0,$inout0
485         aes${dir}       $rndkey0,$inout1
486         aes${dir}       $rndkey0,$inout2
487         aes${dir}       $rndkey0,$inout3
488         aes${dir}       $rndkey0,$inout4
489         aes${dir}       $rndkey0,$inout5
490         $movkey         -16($key,%rax),$rndkey0
491         jnz             .L${dir}_loop6
492
493         aes${dir}       $rndkey1,$inout0
494         aes${dir}       $rndkey1,$inout1
495         aes${dir}       $rndkey1,$inout2
496         aes${dir}       $rndkey1,$inout3
497         aes${dir}       $rndkey1,$inout4
498         aes${dir}       $rndkey1,$inout5
499         aes${dir}last   $rndkey0,$inout0
500         aes${dir}last   $rndkey0,$inout1
501         aes${dir}last   $rndkey0,$inout2
502         aes${dir}last   $rndkey0,$inout3
503         aes${dir}last   $rndkey0,$inout4
504         aes${dir}last   $rndkey0,$inout5
505         ret
506 .size   _aesni_${dir}rypt6,.-_aesni_${dir}rypt6
507 ___
508 }
509 sub aesni_generate8 {
510 my $dir=shift;
511 # As already mentioned it takes in $key and $rounds, which are *not*
512 # preserved. $inout[0-7] is cipher/clear text...
513 $code.=<<___;
514 .type   _aesni_${dir}rypt8,\@abi-omnipotent
515 .align  16
516 _aesni_${dir}rypt8:
517         $movkey         ($key),$rndkey0
518         shl             \$4,$rounds
519         $movkey         16($key),$rndkey1
520         xorps           $rndkey0,$inout0
521         xorps           $rndkey0,$inout1
522         pxor            $rndkey0,$inout2
523         pxor            $rndkey0,$inout3
524         pxor            $rndkey0,$inout4
525         lea             32($key,$rounds),$key
526         neg             %rax                    # $rounds
527         aes${dir}       $rndkey1,$inout0
528         pxor            $rndkey0,$inout5
529         pxor            $rndkey0,$inout6
530         aes${dir}       $rndkey1,$inout1
531         pxor            $rndkey0,$inout7
532         $movkey         ($key,%rax),$rndkey0
533         add             \$16,%rax
534         jmp             .L${dir}_loop8_inner
535 .align  16
536 .L${dir}_loop8:
537         aes${dir}       $rndkey1,$inout0
538         aes${dir}       $rndkey1,$inout1
539 .L${dir}_loop8_inner:
540         aes${dir}       $rndkey1,$inout2
541         aes${dir}       $rndkey1,$inout3
542         aes${dir}       $rndkey1,$inout4
543         aes${dir}       $rndkey1,$inout5
544         aes${dir}       $rndkey1,$inout6
545         aes${dir}       $rndkey1,$inout7
546 .L${dir}_loop8_enter:
547         $movkey         ($key,%rax),$rndkey1
548         add             \$32,%rax
549         aes${dir}       $rndkey0,$inout0
550         aes${dir}       $rndkey0,$inout1
551         aes${dir}       $rndkey0,$inout2
552         aes${dir}       $rndkey0,$inout3
553         aes${dir}       $rndkey0,$inout4
554         aes${dir}       $rndkey0,$inout5
555         aes${dir}       $rndkey0,$inout6
556         aes${dir}       $rndkey0,$inout7
557         $movkey         -16($key,%rax),$rndkey0
558         jnz             .L${dir}_loop8
559
560         aes${dir}       $rndkey1,$inout0
561         aes${dir}       $rndkey1,$inout1
562         aes${dir}       $rndkey1,$inout2
563         aes${dir}       $rndkey1,$inout3
564         aes${dir}       $rndkey1,$inout4
565         aes${dir}       $rndkey1,$inout5
566         aes${dir}       $rndkey1,$inout6
567         aes${dir}       $rndkey1,$inout7
568         aes${dir}last   $rndkey0,$inout0
569         aes${dir}last   $rndkey0,$inout1
570         aes${dir}last   $rndkey0,$inout2
571         aes${dir}last   $rndkey0,$inout3
572         aes${dir}last   $rndkey0,$inout4
573         aes${dir}last   $rndkey0,$inout5
574         aes${dir}last   $rndkey0,$inout6
575         aes${dir}last   $rndkey0,$inout7
576         ret
577 .size   _aesni_${dir}rypt8,.-_aesni_${dir}rypt8
578 ___
579 }
580 &aesni_generate2("enc") if ($PREFIX eq "aesni");
581 &aesni_generate2("dec");
582 &aesni_generate3("enc") if ($PREFIX eq "aesni");
583 &aesni_generate3("dec");
584 &aesni_generate4("enc") if ($PREFIX eq "aesni");
585 &aesni_generate4("dec");
586 &aesni_generate6("enc") if ($PREFIX eq "aesni");
587 &aesni_generate6("dec");
588 &aesni_generate8("enc") if ($PREFIX eq "aesni");
589 &aesni_generate8("dec");
590 \f
591 if ($PREFIX eq "aesni") {
592 ########################################################################
593 # void aesni_ecb_encrypt (const void *in, void *out,
594 #                         size_t length, const AES_KEY *key,
595 #                         int enc);
596 $code.=<<___;
597 .globl  aesni_ecb_encrypt
598 .type   aesni_ecb_encrypt,\@function,5
599 .align  16
600 aesni_ecb_encrypt:
601 ___
602 $code.=<<___ if ($win64);
603         lea     -0x58(%rsp),%rsp
604         movaps  %xmm6,(%rsp)            # offload $inout4..7
605         movaps  %xmm7,0x10(%rsp)
606         movaps  %xmm8,0x20(%rsp)
607         movaps  %xmm9,0x30(%rsp)
608 .Lecb_enc_body:
609 ___
610 $code.=<<___;
611         and     \$-16,$len              # if ($len<16)
612         jz      .Lecb_ret               # return
613
614         mov     240($key),$rounds       # key->rounds
615         $movkey ($key),$rndkey0
616         mov     $key,$key_              # backup $key
617         mov     $rounds,$rnds_          # backup $rounds
618         test    %r8d,%r8d               # 5th argument
619         jz      .Lecb_decrypt
620 #--------------------------- ECB ENCRYPT ------------------------------#
621         cmp     \$0x80,$len             # if ($len<8*16)
622         jb      .Lecb_enc_tail          # short input
623
624         movdqu  ($inp),$inout0          # load 8 input blocks
625         movdqu  0x10($inp),$inout1
626         movdqu  0x20($inp),$inout2
627         movdqu  0x30($inp),$inout3
628         movdqu  0x40($inp),$inout4
629         movdqu  0x50($inp),$inout5
630         movdqu  0x60($inp),$inout6
631         movdqu  0x70($inp),$inout7
632         lea     0x80($inp),$inp         # $inp+=8*16
633         sub     \$0x80,$len             # $len-=8*16 (can be zero)
634         jmp     .Lecb_enc_loop8_enter
635 .align 16
636 .Lecb_enc_loop8:
637         movups  $inout0,($out)          # store 8 output blocks
638         mov     $key_,$key              # restore $key
639         movdqu  ($inp),$inout0          # load 8 input blocks
640         mov     $rnds_,$rounds          # restore $rounds
641         movups  $inout1,0x10($out)
642         movdqu  0x10($inp),$inout1
643         movups  $inout2,0x20($out)
644         movdqu  0x20($inp),$inout2
645         movups  $inout3,0x30($out)
646         movdqu  0x30($inp),$inout3
647         movups  $inout4,0x40($out)
648         movdqu  0x40($inp),$inout4
649         movups  $inout5,0x50($out)
650         movdqu  0x50($inp),$inout5
651         movups  $inout6,0x60($out)
652         movdqu  0x60($inp),$inout6
653         movups  $inout7,0x70($out)
654         lea     0x80($out),$out         # $out+=8*16
655         movdqu  0x70($inp),$inout7
656         lea     0x80($inp),$inp         # $inp+=8*16
657 .Lecb_enc_loop8_enter:
658
659         call    _aesni_encrypt8
660
661         sub     \$0x80,$len
662         jnc     .Lecb_enc_loop8         # loop if $len-=8*16 didn't borrow
663
664         movups  $inout0,($out)          # store 8 output blocks
665         mov     $key_,$key              # restore $key
666         movups  $inout1,0x10($out)
667         mov     $rnds_,$rounds          # restore $rounds
668         movups  $inout2,0x20($out)
669         movups  $inout3,0x30($out)
670         movups  $inout4,0x40($out)
671         movups  $inout5,0x50($out)
672         movups  $inout6,0x60($out)
673         movups  $inout7,0x70($out)
674         lea     0x80($out),$out         # $out+=8*16
675         add     \$0x80,$len             # restore real remaining $len
676         jz      .Lecb_ret               # done if ($len==0)
677
678 .Lecb_enc_tail:                         # $len is less than 8*16
679         movups  ($inp),$inout0
680         cmp     \$0x20,$len
681         jb      .Lecb_enc_one
682         movups  0x10($inp),$inout1
683         je      .Lecb_enc_two
684         movups  0x20($inp),$inout2
685         cmp     \$0x40,$len
686         jb      .Lecb_enc_three
687         movups  0x30($inp),$inout3
688         je      .Lecb_enc_four
689         movups  0x40($inp),$inout4
690         cmp     \$0x60,$len
691         jb      .Lecb_enc_five
692         movups  0x50($inp),$inout5
693         je      .Lecb_enc_six
694         movdqu  0x60($inp),$inout6
695         xorps   $inout7,$inout7
696         call    _aesni_encrypt8
697         movups  $inout0,($out)          # store 7 output blocks
698         movups  $inout1,0x10($out)
699         movups  $inout2,0x20($out)
700         movups  $inout3,0x30($out)
701         movups  $inout4,0x40($out)
702         movups  $inout5,0x50($out)
703         movups  $inout6,0x60($out)
704         jmp     .Lecb_ret
705 .align  16
706 .Lecb_enc_one:
707 ___
708         &aesni_generate1("enc",$key,$rounds);
709 $code.=<<___;
710         movups  $inout0,($out)          # store one output block
711         jmp     .Lecb_ret
712 .align  16
713 .Lecb_enc_two:
714         call    _aesni_encrypt2
715         movups  $inout0,($out)          # store 2 output blocks
716         movups  $inout1,0x10($out)
717         jmp     .Lecb_ret
718 .align  16
719 .Lecb_enc_three:
720         call    _aesni_encrypt3
721         movups  $inout0,($out)          # store 3 output blocks
722         movups  $inout1,0x10($out)
723         movups  $inout2,0x20($out)
724         jmp     .Lecb_ret
725 .align  16
726 .Lecb_enc_four:
727         call    _aesni_encrypt4
728         movups  $inout0,($out)          # store 4 output blocks
729         movups  $inout1,0x10($out)
730         movups  $inout2,0x20($out)
731         movups  $inout3,0x30($out)
732         jmp     .Lecb_ret
733 .align  16
734 .Lecb_enc_five:
735         xorps   $inout5,$inout5
736         call    _aesni_encrypt6
737         movups  $inout0,($out)          # store 5 output blocks
738         movups  $inout1,0x10($out)
739         movups  $inout2,0x20($out)
740         movups  $inout3,0x30($out)
741         movups  $inout4,0x40($out)
742         jmp     .Lecb_ret
743 .align  16
744 .Lecb_enc_six:
745         call    _aesni_encrypt6
746         movups  $inout0,($out)          # store 6 output blocks
747         movups  $inout1,0x10($out)
748         movups  $inout2,0x20($out)
749         movups  $inout3,0x30($out)
750         movups  $inout4,0x40($out)
751         movups  $inout5,0x50($out)
752         jmp     .Lecb_ret
753 \f#--------------------------- ECB DECRYPT ------------------------------#
754 .align  16
755 .Lecb_decrypt:
756         cmp     \$0x80,$len             # if ($len<8*16)
757         jb      .Lecb_dec_tail          # short input
758
759         movdqu  ($inp),$inout0          # load 8 input blocks
760         movdqu  0x10($inp),$inout1
761         movdqu  0x20($inp),$inout2
762         movdqu  0x30($inp),$inout3
763         movdqu  0x40($inp),$inout4
764         movdqu  0x50($inp),$inout5
765         movdqu  0x60($inp),$inout6
766         movdqu  0x70($inp),$inout7
767         lea     0x80($inp),$inp         # $inp+=8*16
768         sub     \$0x80,$len             # $len-=8*16 (can be zero)
769         jmp     .Lecb_dec_loop8_enter
770 .align 16
771 .Lecb_dec_loop8:
772         movups  $inout0,($out)          # store 8 output blocks
773         mov     $key_,$key              # restore $key
774         movdqu  ($inp),$inout0          # load 8 input blocks
775         mov     $rnds_,$rounds          # restore $rounds
776         movups  $inout1,0x10($out)
777         movdqu  0x10($inp),$inout1
778         movups  $inout2,0x20($out)
779         movdqu  0x20($inp),$inout2
780         movups  $inout3,0x30($out)
781         movdqu  0x30($inp),$inout3
782         movups  $inout4,0x40($out)
783         movdqu  0x40($inp),$inout4
784         movups  $inout5,0x50($out)
785         movdqu  0x50($inp),$inout5
786         movups  $inout6,0x60($out)
787         movdqu  0x60($inp),$inout6
788         movups  $inout7,0x70($out)
789         lea     0x80($out),$out         # $out+=8*16
790         movdqu  0x70($inp),$inout7
791         lea     0x80($inp),$inp         # $inp+=8*16
792 .Lecb_dec_loop8_enter:
793
794         call    _aesni_decrypt8
795
796         $movkey ($key_),$rndkey0
797         sub     \$0x80,$len
798         jnc     .Lecb_dec_loop8         # loop if $len-=8*16 didn't borrow
799
800         movups  $inout0,($out)          # store 8 output blocks
801          pxor   $inout0,$inout0         # clear register bank
802         mov     $key_,$key              # restore $key
803         movups  $inout1,0x10($out)
804          pxor   $inout1,$inout1
805         mov     $rnds_,$rounds          # restore $rounds
806         movups  $inout2,0x20($out)
807          pxor   $inout2,$inout2
808         movups  $inout3,0x30($out)
809          pxor   $inout3,$inout3
810         movups  $inout4,0x40($out)
811          pxor   $inout4,$inout4
812         movups  $inout5,0x50($out)
813          pxor   $inout5,$inout5
814         movups  $inout6,0x60($out)
815          pxor   $inout6,$inout6
816         movups  $inout7,0x70($out)
817          pxor   $inout7,$inout7
818         lea     0x80($out),$out         # $out+=8*16
819         add     \$0x80,$len             # restore real remaining $len
820         jz      .Lecb_ret               # done if ($len==0)
821
822 .Lecb_dec_tail:
823         movups  ($inp),$inout0
824         cmp     \$0x20,$len
825         jb      .Lecb_dec_one
826         movups  0x10($inp),$inout1
827         je      .Lecb_dec_two
828         movups  0x20($inp),$inout2
829         cmp     \$0x40,$len
830         jb      .Lecb_dec_three
831         movups  0x30($inp),$inout3
832         je      .Lecb_dec_four
833         movups  0x40($inp),$inout4
834         cmp     \$0x60,$len
835         jb      .Lecb_dec_five
836         movups  0x50($inp),$inout5
837         je      .Lecb_dec_six
838         movups  0x60($inp),$inout6
839         $movkey ($key),$rndkey0
840         xorps   $inout7,$inout7
841         call    _aesni_decrypt8
842         movups  $inout0,($out)          # store 7 output blocks
843          pxor   $inout0,$inout0         # clear register bank
844         movups  $inout1,0x10($out)
845          pxor   $inout1,$inout1
846         movups  $inout2,0x20($out)
847          pxor   $inout2,$inout2
848         movups  $inout3,0x30($out)
849          pxor   $inout3,$inout3
850         movups  $inout4,0x40($out)
851          pxor   $inout4,$inout4
852         movups  $inout5,0x50($out)
853          pxor   $inout5,$inout5
854         movups  $inout6,0x60($out)
855          pxor   $inout6,$inout6
856          pxor   $inout7,$inout7
857         jmp     .Lecb_ret
858 .align  16
859 .Lecb_dec_one:
860 ___
861         &aesni_generate1("dec",$key,$rounds);
862 $code.=<<___;
863         movups  $inout0,($out)          # store one output block
864          pxor   $inout0,$inout0         # clear register bank
865         jmp     .Lecb_ret
866 .align  16
867 .Lecb_dec_two:
868         call    _aesni_decrypt2
869         movups  $inout0,($out)          # store 2 output blocks
870          pxor   $inout0,$inout0         # clear register bank
871         movups  $inout1,0x10($out)
872          pxor   $inout1,$inout1
873         jmp     .Lecb_ret
874 .align  16
875 .Lecb_dec_three:
876         call    _aesni_decrypt3
877         movups  $inout0,($out)          # store 3 output blocks
878          pxor   $inout0,$inout0         # clear register bank
879         movups  $inout1,0x10($out)
880          pxor   $inout1,$inout1
881         movups  $inout2,0x20($out)
882          pxor   $inout2,$inout2
883         jmp     .Lecb_ret
884 .align  16
885 .Lecb_dec_four:
886         call    _aesni_decrypt4
887         movups  $inout0,($out)          # store 4 output blocks
888          pxor   $inout0,$inout0         # clear register bank
889         movups  $inout1,0x10($out)
890          pxor   $inout1,$inout1
891         movups  $inout2,0x20($out)
892          pxor   $inout2,$inout2
893         movups  $inout3,0x30($out)
894          pxor   $inout3,$inout3
895         jmp     .Lecb_ret
896 .align  16
897 .Lecb_dec_five:
898         xorps   $inout5,$inout5
899         call    _aesni_decrypt6
900         movups  $inout0,($out)          # store 5 output blocks
901          pxor   $inout0,$inout0         # clear register bank
902         movups  $inout1,0x10($out)
903          pxor   $inout1,$inout1
904         movups  $inout2,0x20($out)
905          pxor   $inout2,$inout2
906         movups  $inout3,0x30($out)
907          pxor   $inout3,$inout3
908         movups  $inout4,0x40($out)
909          pxor   $inout4,$inout4
910          pxor   $inout5,$inout5
911         jmp     .Lecb_ret
912 .align  16
913 .Lecb_dec_six:
914         call    _aesni_decrypt6
915         movups  $inout0,($out)          # store 6 output blocks
916          pxor   $inout0,$inout0         # clear register bank
917         movups  $inout1,0x10($out)
918          pxor   $inout1,$inout1
919         movups  $inout2,0x20($out)
920          pxor   $inout2,$inout2
921         movups  $inout3,0x30($out)
922          pxor   $inout3,$inout3
923         movups  $inout4,0x40($out)
924          pxor   $inout4,$inout4
925         movups  $inout5,0x50($out)
926          pxor   $inout5,$inout5
927
928 .Lecb_ret:
929         xorps   $rndkey0,$rndkey0       # %xmm0
930         pxor    $rndkey1,$rndkey1
931 ___
932 $code.=<<___ if ($win64);
933         movaps  (%rsp),%xmm6
934         movaps  %xmm0,(%rsp)            # clear stack
935         movaps  0x10(%rsp),%xmm7
936         movaps  %xmm0,0x10(%rsp)
937         movaps  0x20(%rsp),%xmm8
938         movaps  %xmm0,0x20(%rsp)
939         movaps  0x30(%rsp),%xmm9
940         movaps  %xmm0,0x30(%rsp)
941         lea     0x58(%rsp),%rsp
942 .Lecb_enc_ret:
943 ___
944 $code.=<<___;
945         ret
946 .size   aesni_ecb_encrypt,.-aesni_ecb_encrypt
947 ___
948 \f
949 {
950 ######################################################################
951 # void aesni_ccm64_[en|de]crypt_blocks (const void *in, void *out,
952 #                         size_t blocks, const AES_KEY *key,
953 #                         const char *ivec,char *cmac);
954 #
955 # Handles only complete blocks, operates on 64-bit counter and
956 # does not update *ivec! Nor does it finalize CMAC value
957 # (see engine/eng_aesni.c for details)
958 #
959 {
960 my $cmac="%r9"; # 6th argument
961
962 my $increment="%xmm9";
963 my $iv="%xmm6";
964 my $bswap_mask="%xmm7";
965
966 $code.=<<___;
967 .globl  aesni_ccm64_encrypt_blocks
968 .type   aesni_ccm64_encrypt_blocks,\@function,6
969 .align  16
970 aesni_ccm64_encrypt_blocks:
971 ___
972 $code.=<<___ if ($win64);
973         lea     -0x58(%rsp),%rsp
974         movaps  %xmm6,(%rsp)            # $iv
975         movaps  %xmm7,0x10(%rsp)        # $bswap_mask
976         movaps  %xmm8,0x20(%rsp)        # $in0
977         movaps  %xmm9,0x30(%rsp)        # $increment
978 .Lccm64_enc_body:
979 ___
980 $code.=<<___;
981         mov     240($key),$rounds               # key->rounds
982         movdqu  ($ivp),$iv
983         movdqa  .Lincrement64(%rip),$increment
984         movdqa  .Lbswap_mask(%rip),$bswap_mask
985
986         shl     \$4,$rounds
987         mov     \$16,$rnds_
988         lea     0($key),$key_
989         movdqu  ($cmac),$inout1
990         movdqa  $iv,$inout0
991         lea     32($key,$rounds),$key           # end of key schedule
992         pshufb  $bswap_mask,$iv
993         sub     %rax,%r10                       # twisted $rounds
994         jmp     .Lccm64_enc_outer
995 .align  16
996 .Lccm64_enc_outer:
997         $movkey ($key_),$rndkey0
998         mov     %r10,%rax
999         movups  ($inp),$in0                     # load inp
1000
1001         xorps   $rndkey0,$inout0                # counter
1002         $movkey 16($key_),$rndkey1
1003         xorps   $in0,$rndkey0
1004         xorps   $rndkey0,$inout1                # cmac^=inp
1005         $movkey 32($key_),$rndkey0
1006
1007 .Lccm64_enc2_loop:
1008         aesenc  $rndkey1,$inout0
1009         aesenc  $rndkey1,$inout1
1010         $movkey ($key,%rax),$rndkey1
1011         add     \$32,%rax
1012         aesenc  $rndkey0,$inout0
1013         aesenc  $rndkey0,$inout1
1014         $movkey -16($key,%rax),$rndkey0
1015         jnz     .Lccm64_enc2_loop
1016         aesenc  $rndkey1,$inout0
1017         aesenc  $rndkey1,$inout1
1018         paddq   $increment,$iv
1019         dec     $len                            # $len-- ($len is in blocks)
1020         aesenclast      $rndkey0,$inout0
1021         aesenclast      $rndkey0,$inout1
1022
1023         lea     16($inp),$inp
1024         xorps   $inout0,$in0                    # inp ^= E(iv)
1025         movdqa  $iv,$inout0
1026         movups  $in0,($out)                     # save output
1027         pshufb  $bswap_mask,$inout0
1028         lea     16($out),$out                   # $out+=16
1029         jnz     .Lccm64_enc_outer               # loop if ($len!=0)
1030
1031          pxor   $rndkey0,$rndkey0               # clear register bank
1032          pxor   $rndkey1,$rndkey1
1033          pxor   $inout0,$inout0
1034         movups  $inout1,($cmac)                 # store resulting mac
1035          pxor   $inout1,$inout1
1036          pxor   $in0,$in0
1037          pxor   $iv,$iv
1038 ___
1039 $code.=<<___ if ($win64);
1040         movaps  (%rsp),%xmm6
1041         movaps  %xmm0,(%rsp)                    # clear stack
1042         movaps  0x10(%rsp),%xmm7
1043         movaps  %xmm0,0x10(%rsp)
1044         movaps  0x20(%rsp),%xmm8
1045         movaps  %xmm0,0x20(%rsp)
1046         movaps  0x30(%rsp),%xmm9
1047         movaps  %xmm0,0x30(%rsp)
1048         lea     0x58(%rsp),%rsp
1049 .Lccm64_enc_ret:
1050 ___
1051 $code.=<<___;
1052         ret
1053 .size   aesni_ccm64_encrypt_blocks,.-aesni_ccm64_encrypt_blocks
1054 ___
1055 ######################################################################
1056 $code.=<<___;
1057 .globl  aesni_ccm64_decrypt_blocks
1058 .type   aesni_ccm64_decrypt_blocks,\@function,6
1059 .align  16
1060 aesni_ccm64_decrypt_blocks:
1061 ___
1062 $code.=<<___ if ($win64);
1063         lea     -0x58(%rsp),%rsp
1064         movaps  %xmm6,(%rsp)            # $iv
1065         movaps  %xmm7,0x10(%rsp)        # $bswap_mask
1066         movaps  %xmm8,0x20(%rsp)        # $in8
1067         movaps  %xmm9,0x30(%rsp)        # $increment
1068 .Lccm64_dec_body:
1069 ___
1070 $code.=<<___;
1071         mov     240($key),$rounds               # key->rounds
1072         movups  ($ivp),$iv
1073         movdqu  ($cmac),$inout1
1074         movdqa  .Lincrement64(%rip),$increment
1075         movdqa  .Lbswap_mask(%rip),$bswap_mask
1076
1077         movaps  $iv,$inout0
1078         mov     $rounds,$rnds_
1079         mov     $key,$key_
1080         pshufb  $bswap_mask,$iv
1081 ___
1082         &aesni_generate1("enc",$key,$rounds);
1083 $code.=<<___;
1084         shl     \$4,$rnds_
1085         mov     \$16,$rounds
1086         movups  ($inp),$in0                     # load inp
1087         paddq   $increment,$iv
1088         lea     16($inp),$inp                   # $inp+=16
1089         sub     %r10,%rax                       # twisted $rounds
1090         lea     32($key_,$rnds_),$key           # end of key schedule
1091         mov     %rax,%r10
1092         jmp     .Lccm64_dec_outer
1093 .align  16
1094 .Lccm64_dec_outer:
1095         xorps   $inout0,$in0                    # inp ^= E(iv)
1096         movdqa  $iv,$inout0
1097         movups  $in0,($out)                     # save output
1098         lea     16($out),$out                   # $out+=16
1099         pshufb  $bswap_mask,$inout0
1100
1101         sub     \$1,$len                        # $len-- ($len is in blocks)
1102         jz      .Lccm64_dec_break               # if ($len==0) break
1103
1104         $movkey ($key_),$rndkey0
1105         mov     %r10,%rax
1106         $movkey 16($key_),$rndkey1
1107         xorps   $rndkey0,$in0
1108         xorps   $rndkey0,$inout0
1109         xorps   $in0,$inout1                    # cmac^=out
1110         $movkey 32($key_),$rndkey0
1111         jmp     .Lccm64_dec2_loop
1112 .align  16
1113 .Lccm64_dec2_loop:
1114         aesenc  $rndkey1,$inout0
1115         aesenc  $rndkey1,$inout1
1116         $movkey ($key,%rax),$rndkey1
1117         add     \$32,%rax
1118         aesenc  $rndkey0,$inout0
1119         aesenc  $rndkey0,$inout1
1120         $movkey -16($key,%rax),$rndkey0
1121         jnz     .Lccm64_dec2_loop
1122         movups  ($inp),$in0                     # load input
1123         paddq   $increment,$iv
1124         aesenc  $rndkey1,$inout0
1125         aesenc  $rndkey1,$inout1
1126         aesenclast      $rndkey0,$inout0
1127         aesenclast      $rndkey0,$inout1
1128         lea     16($inp),$inp                   # $inp+=16
1129         jmp     .Lccm64_dec_outer
1130
1131 .align  16
1132 .Lccm64_dec_break:
1133         #xorps  $in0,$inout1                    # cmac^=out
1134         mov     240($key_),$rounds
1135 ___
1136         &aesni_generate1("enc",$key_,$rounds,$inout1,$in0);
1137 $code.=<<___;
1138          pxor   $rndkey0,$rndkey0               # clear register bank
1139          pxor   $rndkey1,$rndkey1
1140          pxor   $inout0,$inout0
1141         movups  $inout1,($cmac)                 # store resulting mac
1142          pxor   $inout1,$inout1
1143          pxor   $in0,$in0
1144          pxor   $iv,$iv
1145 ___
1146 $code.=<<___ if ($win64);
1147         movaps  (%rsp),%xmm6
1148         movaps  %xmm0,(%rsp)                    # clear stack
1149         movaps  0x10(%rsp),%xmm7
1150         movaps  %xmm0,0x10(%rsp)
1151         movaps  0x20(%rsp),%xmm8
1152         movaps  %xmm0,0x20(%rsp)
1153         movaps  0x30(%rsp),%xmm9
1154         movaps  %xmm0,0x30(%rsp)
1155         lea     0x58(%rsp),%rsp
1156 .Lccm64_dec_ret:
1157 ___
1158 $code.=<<___;
1159         ret
1160 .size   aesni_ccm64_decrypt_blocks,.-aesni_ccm64_decrypt_blocks
1161 ___
1162 }\f
1163 ######################################################################
1164 # void aesni_ctr32_encrypt_blocks (const void *in, void *out,
1165 #                         size_t blocks, const AES_KEY *key,
1166 #                         const char *ivec);
1167 #
1168 # Handles only complete blocks, operates on 32-bit counter and
1169 # does not update *ivec! (see crypto/modes/ctr128.c for details)
1170 #
1171 # Overhaul based on suggestions from Shay Gueron and Vlad Krasnov,
1172 # http://rt.openssl.org/Ticket/Display.html?id=3021&user=guest&pass=guest.
1173 # Keywords are full unroll and modulo-schedule counter calculations
1174 # with zero-round key xor.
1175 {
1176 my ($in0,$in1,$in2,$in3,$in4,$in5)=map("%xmm$_",(10..15));
1177 my ($key0,$ctr)=("%ebp","${ivp}d");
1178 my $frame_size = 0x80 + ($win64?160:0);
1179
1180 $code.=<<___;
1181 .globl  aesni_ctr32_encrypt_blocks
1182 .type   aesni_ctr32_encrypt_blocks,\@function,5
1183 .align  16
1184 aesni_ctr32_encrypt_blocks:
1185 .cfi_startproc
1186         cmp     \$1,$len
1187         jne     .Lctr32_bulk
1188
1189         # handle single block without allocating stack frame,
1190         # useful when handling edges
1191         movups  ($ivp),$inout0
1192         movups  ($inp),$inout1
1193         mov     240($key),%edx                  # key->rounds
1194 ___
1195         &aesni_generate1("enc",$key,"%edx");
1196 $code.=<<___;
1197          pxor   $rndkey0,$rndkey0               # clear register bank
1198          pxor   $rndkey1,$rndkey1
1199         xorps   $inout1,$inout0
1200          pxor   $inout1,$inout1
1201         movups  $inout0,($out)
1202          xorps  $inout0,$inout0
1203         jmp     .Lctr32_epilogue
1204
1205 .align  16
1206 .Lctr32_bulk:
1207         lea     (%rsp),$key_                    # use $key_ as frame pointer
1208 .cfi_def_cfa_register   $key_
1209         push    %rbp
1210 .cfi_push       %rbp
1211         sub     \$$frame_size,%rsp
1212         and     \$-16,%rsp      # Linux kernel stack can be incorrectly seeded
1213 ___
1214 $code.=<<___ if ($win64);
1215         movaps  %xmm6,-0xa8($key_)              # offload everything
1216         movaps  %xmm7,-0x98($key_)
1217         movaps  %xmm8,-0x88($key_)
1218         movaps  %xmm9,-0x78($key_)
1219         movaps  %xmm10,-0x68($key_)
1220         movaps  %xmm11,-0x58($key_)
1221         movaps  %xmm12,-0x48($key_)
1222         movaps  %xmm13,-0x38($key_)
1223         movaps  %xmm14,-0x28($key_)
1224         movaps  %xmm15,-0x18($key_)
1225 .Lctr32_body:
1226 ___
1227 $code.=<<___;
1228
1229         # 8 16-byte words on top of stack are counter values
1230         # xor-ed with zero-round key
1231
1232         movdqu  ($ivp),$inout0
1233         movdqu  ($key),$rndkey0
1234         mov     12($ivp),$ctr                   # counter LSB
1235         pxor    $rndkey0,$inout0
1236         mov     12($key),$key0                  # 0-round key LSB
1237         movdqa  $inout0,0x00(%rsp)              # populate counter block
1238         bswap   $ctr
1239         movdqa  $inout0,$inout1
1240         movdqa  $inout0,$inout2
1241         movdqa  $inout0,$inout3
1242         movdqa  $inout0,0x40(%rsp)
1243         movdqa  $inout0,0x50(%rsp)
1244         movdqa  $inout0,0x60(%rsp)
1245         mov     %rdx,%r10                       # about to borrow %rdx
1246         movdqa  $inout0,0x70(%rsp)
1247
1248         lea     1($ctr),%rax
1249          lea    2($ctr),%rdx
1250         bswap   %eax
1251          bswap  %edx
1252         xor     $key0,%eax
1253          xor    $key0,%edx
1254         pinsrd  \$3,%eax,$inout1
1255         lea     3($ctr),%rax
1256         movdqa  $inout1,0x10(%rsp)
1257          pinsrd \$3,%edx,$inout2
1258         bswap   %eax
1259          mov    %r10,%rdx                       # restore %rdx
1260          lea    4($ctr),%r10
1261          movdqa $inout2,0x20(%rsp)
1262         xor     $key0,%eax
1263          bswap  %r10d
1264         pinsrd  \$3,%eax,$inout3
1265          xor    $key0,%r10d
1266         movdqa  $inout3,0x30(%rsp)
1267         lea     5($ctr),%r9
1268          mov    %r10d,0x40+12(%rsp)
1269         bswap   %r9d
1270          lea    6($ctr),%r10
1271         mov     240($key),$rounds               # key->rounds
1272         xor     $key0,%r9d
1273          bswap  %r10d
1274         mov     %r9d,0x50+12(%rsp)
1275          xor    $key0,%r10d
1276         lea     7($ctr),%r9
1277          mov    %r10d,0x60+12(%rsp)
1278         bswap   %r9d
1279          mov    OPENSSL_ia32cap_P+4(%rip),%r10d
1280         xor     $key0,%r9d
1281          and    \$`1<<26|1<<22`,%r10d           # isolate XSAVE+MOVBE
1282         mov     %r9d,0x70+12(%rsp)
1283
1284         $movkey 0x10($key),$rndkey1
1285
1286         movdqa  0x40(%rsp),$inout4
1287         movdqa  0x50(%rsp),$inout5
1288
1289         cmp     \$8,$len                # $len is in blocks
1290         jb      .Lctr32_tail            # short input if ($len<8)
1291
1292         sub     \$6,$len                # $len is biased by -6
1293         cmp     \$`1<<22`,%r10d         # check for MOVBE without XSAVE
1294         je      .Lctr32_6x              # [which denotes Atom Silvermont]
1295
1296         lea     0x80($key),$key         # size optimization
1297         sub     \$2,$len                # $len is biased by -8
1298         jmp     .Lctr32_loop8
1299
1300 .align  16
1301 .Lctr32_6x:
1302         shl     \$4,$rounds
1303         mov     \$48,$rnds_
1304         bswap   $key0
1305         lea     32($key,$rounds),$key   # end of key schedule
1306         sub     %rax,%r10               # twisted $rounds
1307         jmp     .Lctr32_loop6
1308
1309 .align  16
1310 .Lctr32_loop6:
1311          add    \$6,$ctr                # next counter value
1312         $movkey -48($key,$rnds_),$rndkey0
1313         aesenc  $rndkey1,$inout0
1314          mov    $ctr,%eax
1315          xor    $key0,%eax
1316         aesenc  $rndkey1,$inout1
1317          movbe  %eax,`0x00+12`(%rsp)    # store next counter value
1318          lea    1($ctr),%eax
1319         aesenc  $rndkey1,$inout2
1320          xor    $key0,%eax
1321          movbe  %eax,`0x10+12`(%rsp)
1322         aesenc  $rndkey1,$inout3
1323          lea    2($ctr),%eax
1324          xor    $key0,%eax
1325         aesenc  $rndkey1,$inout4
1326          movbe  %eax,`0x20+12`(%rsp)
1327          lea    3($ctr),%eax
1328         aesenc  $rndkey1,$inout5
1329         $movkey -32($key,$rnds_),$rndkey1
1330          xor    $key0,%eax
1331
1332         aesenc  $rndkey0,$inout0
1333          movbe  %eax,`0x30+12`(%rsp)
1334          lea    4($ctr),%eax
1335         aesenc  $rndkey0,$inout1
1336          xor    $key0,%eax
1337          movbe  %eax,`0x40+12`(%rsp)
1338         aesenc  $rndkey0,$inout2
1339          lea    5($ctr),%eax
1340          xor    $key0,%eax
1341         aesenc  $rndkey0,$inout3
1342          movbe  %eax,`0x50+12`(%rsp)
1343          mov    %r10,%rax               # mov   $rnds_,$rounds
1344         aesenc  $rndkey0,$inout4
1345         aesenc  $rndkey0,$inout5
1346         $movkey -16($key,$rnds_),$rndkey0
1347
1348         call    .Lenc_loop6
1349
1350         movdqu  ($inp),$inout6          # load 6 input blocks
1351         movdqu  0x10($inp),$inout7
1352         movdqu  0x20($inp),$in0
1353         movdqu  0x30($inp),$in1
1354         movdqu  0x40($inp),$in2
1355         movdqu  0x50($inp),$in3
1356         lea     0x60($inp),$inp         # $inp+=6*16
1357         $movkey -64($key,$rnds_),$rndkey1
1358         pxor    $inout0,$inout6         # inp^=E(ctr)
1359         movaps  0x00(%rsp),$inout0      # load next counter [xor-ed with 0 round]
1360         pxor    $inout1,$inout7
1361         movaps  0x10(%rsp),$inout1
1362         pxor    $inout2,$in0
1363         movaps  0x20(%rsp),$inout2
1364         pxor    $inout3,$in1
1365         movaps  0x30(%rsp),$inout3
1366         pxor    $inout4,$in2
1367         movaps  0x40(%rsp),$inout4
1368         pxor    $inout5,$in3
1369         movaps  0x50(%rsp),$inout5
1370         movdqu  $inout6,($out)          # store 6 output blocks
1371         movdqu  $inout7,0x10($out)
1372         movdqu  $in0,0x20($out)
1373         movdqu  $in1,0x30($out)
1374         movdqu  $in2,0x40($out)
1375         movdqu  $in3,0x50($out)
1376         lea     0x60($out),$out         # $out+=6*16
1377
1378         sub     \$6,$len
1379         jnc     .Lctr32_loop6           # loop if $len-=6 didn't borrow
1380
1381         add     \$6,$len                # restore real remaining $len
1382         jz      .Lctr32_done            # done if ($len==0)
1383
1384         lea     -48($rnds_),$rounds
1385         lea     -80($key,$rnds_),$key   # restore $key
1386         neg     $rounds
1387         shr     \$4,$rounds             # restore $rounds
1388         jmp     .Lctr32_tail
1389
1390 .align  32
1391 .Lctr32_loop8:
1392          add            \$8,$ctr                # next counter value
1393         movdqa          0x60(%rsp),$inout6
1394         aesenc          $rndkey1,$inout0
1395          mov            $ctr,%r9d
1396         movdqa          0x70(%rsp),$inout7
1397         aesenc          $rndkey1,$inout1
1398          bswap          %r9d
1399         $movkey         0x20-0x80($key),$rndkey0
1400         aesenc          $rndkey1,$inout2
1401          xor            $key0,%r9d
1402          nop
1403         aesenc          $rndkey1,$inout3
1404          mov            %r9d,0x00+12(%rsp)      # store next counter value
1405          lea            1($ctr),%r9
1406         aesenc          $rndkey1,$inout4
1407         aesenc          $rndkey1,$inout5
1408         aesenc          $rndkey1,$inout6
1409         aesenc          $rndkey1,$inout7
1410         $movkey         0x30-0x80($key),$rndkey1
1411 ___
1412 for($i=2;$i<8;$i++) {
1413 my $rndkeyx = ($i&1)?$rndkey1:$rndkey0;
1414 $code.=<<___;
1415          bswap          %r9d
1416         aesenc          $rndkeyx,$inout0
1417         aesenc          $rndkeyx,$inout1
1418          xor            $key0,%r9d
1419          .byte          0x66,0x90
1420         aesenc          $rndkeyx,$inout2
1421         aesenc          $rndkeyx,$inout3
1422          mov            %r9d,`0x10*($i-1)`+12(%rsp)
1423          lea            $i($ctr),%r9
1424         aesenc          $rndkeyx,$inout4
1425         aesenc          $rndkeyx,$inout5
1426         aesenc          $rndkeyx,$inout6
1427         aesenc          $rndkeyx,$inout7
1428         $movkey         `0x20+0x10*$i`-0x80($key),$rndkeyx
1429 ___
1430 }
1431 $code.=<<___;
1432          bswap          %r9d
1433         aesenc          $rndkey0,$inout0
1434         aesenc          $rndkey0,$inout1
1435         aesenc          $rndkey0,$inout2
1436          xor            $key0,%r9d
1437          movdqu         0x00($inp),$in0         # start loading input
1438         aesenc          $rndkey0,$inout3
1439          mov            %r9d,0x70+12(%rsp)
1440          cmp            \$11,$rounds
1441         aesenc          $rndkey0,$inout4
1442         aesenc          $rndkey0,$inout5
1443         aesenc          $rndkey0,$inout6
1444         aesenc          $rndkey0,$inout7
1445         $movkey         0xa0-0x80($key),$rndkey0
1446
1447         jb              .Lctr32_enc_done
1448
1449         aesenc          $rndkey1,$inout0
1450         aesenc          $rndkey1,$inout1
1451         aesenc          $rndkey1,$inout2
1452         aesenc          $rndkey1,$inout3
1453         aesenc          $rndkey1,$inout4
1454         aesenc          $rndkey1,$inout5
1455         aesenc          $rndkey1,$inout6
1456         aesenc          $rndkey1,$inout7
1457         $movkey         0xb0-0x80($key),$rndkey1
1458
1459         aesenc          $rndkey0,$inout0
1460         aesenc          $rndkey0,$inout1
1461         aesenc          $rndkey0,$inout2
1462         aesenc          $rndkey0,$inout3
1463         aesenc          $rndkey0,$inout4
1464         aesenc          $rndkey0,$inout5
1465         aesenc          $rndkey0,$inout6
1466         aesenc          $rndkey0,$inout7
1467         $movkey         0xc0-0x80($key),$rndkey0
1468         je              .Lctr32_enc_done
1469
1470         aesenc          $rndkey1,$inout0
1471         aesenc          $rndkey1,$inout1
1472         aesenc          $rndkey1,$inout2
1473         aesenc          $rndkey1,$inout3
1474         aesenc          $rndkey1,$inout4
1475         aesenc          $rndkey1,$inout5
1476         aesenc          $rndkey1,$inout6
1477         aesenc          $rndkey1,$inout7
1478         $movkey         0xd0-0x80($key),$rndkey1
1479
1480         aesenc          $rndkey0,$inout0
1481         aesenc          $rndkey0,$inout1
1482         aesenc          $rndkey0,$inout2
1483         aesenc          $rndkey0,$inout3
1484         aesenc          $rndkey0,$inout4
1485         aesenc          $rndkey0,$inout5
1486         aesenc          $rndkey0,$inout6
1487         aesenc          $rndkey0,$inout7
1488         $movkey         0xe0-0x80($key),$rndkey0
1489         jmp             .Lctr32_enc_done
1490
1491 .align  16
1492 .Lctr32_enc_done:
1493         movdqu          0x10($inp),$in1
1494         pxor            $rndkey0,$in0           # input^=round[last]
1495         movdqu          0x20($inp),$in2
1496         pxor            $rndkey0,$in1
1497         movdqu          0x30($inp),$in3
1498         pxor            $rndkey0,$in2
1499         movdqu          0x40($inp),$in4
1500         pxor            $rndkey0,$in3
1501         movdqu          0x50($inp),$in5
1502         pxor            $rndkey0,$in4
1503         pxor            $rndkey0,$in5
1504         aesenc          $rndkey1,$inout0
1505         aesenc          $rndkey1,$inout1
1506         aesenc          $rndkey1,$inout2
1507         aesenc          $rndkey1,$inout3
1508         aesenc          $rndkey1,$inout4
1509         aesenc          $rndkey1,$inout5
1510         aesenc          $rndkey1,$inout6
1511         aesenc          $rndkey1,$inout7
1512         movdqu          0x60($inp),$rndkey1     # borrow $rndkey1 for inp[6]
1513         lea             0x80($inp),$inp         # $inp+=8*16
1514
1515         aesenclast      $in0,$inout0            # $inN is inp[N]^round[last]
1516         pxor            $rndkey0,$rndkey1       # borrowed $rndkey
1517         movdqu          0x70-0x80($inp),$in0
1518         aesenclast      $in1,$inout1
1519         pxor            $rndkey0,$in0
1520         movdqa          0x00(%rsp),$in1         # load next counter block
1521         aesenclast      $in2,$inout2
1522         aesenclast      $in3,$inout3
1523         movdqa          0x10(%rsp),$in2
1524         movdqa          0x20(%rsp),$in3
1525         aesenclast      $in4,$inout4
1526         aesenclast      $in5,$inout5
1527         movdqa          0x30(%rsp),$in4
1528         movdqa          0x40(%rsp),$in5
1529         aesenclast      $rndkey1,$inout6
1530         movdqa          0x50(%rsp),$rndkey0
1531         $movkey         0x10-0x80($key),$rndkey1#real 1st-round key
1532         aesenclast      $in0,$inout7
1533
1534         movups          $inout0,($out)          # store 8 output blocks
1535         movdqa          $in1,$inout0
1536         movups          $inout1,0x10($out)
1537         movdqa          $in2,$inout1
1538         movups          $inout2,0x20($out)
1539         movdqa          $in3,$inout2
1540         movups          $inout3,0x30($out)
1541         movdqa          $in4,$inout3
1542         movups          $inout4,0x40($out)
1543         movdqa          $in5,$inout4
1544         movups          $inout5,0x50($out)
1545         movdqa          $rndkey0,$inout5
1546         movups          $inout6,0x60($out)
1547         movups          $inout7,0x70($out)
1548         lea             0x80($out),$out         # $out+=8*16
1549
1550         sub     \$8,$len
1551         jnc     .Lctr32_loop8                   # loop if $len-=8 didn't borrow
1552
1553         add     \$8,$len                        # restore real remaining $len
1554         jz      .Lctr32_done                    # done if ($len==0)
1555         lea     -0x80($key),$key
1556
1557 .Lctr32_tail:
1558         # note that at this point $inout0..5 are populated with
1559         # counter values xor-ed with 0-round key
1560         lea     16($key),$key
1561         cmp     \$4,$len
1562         jb      .Lctr32_loop3
1563         je      .Lctr32_loop4
1564
1565         # if ($len>4) compute 7 E(counter)
1566         shl             \$4,$rounds
1567         movdqa          0x60(%rsp),$inout6
1568         pxor            $inout7,$inout7
1569
1570         $movkey         16($key),$rndkey0
1571         aesenc          $rndkey1,$inout0
1572         aesenc          $rndkey1,$inout1
1573         lea             32-16($key,$rounds),$key# prepare for .Lenc_loop8_enter
1574         neg             %rax
1575         aesenc          $rndkey1,$inout2
1576         add             \$16,%rax               # prepare for .Lenc_loop8_enter
1577          movups         ($inp),$in0
1578         aesenc          $rndkey1,$inout3
1579         aesenc          $rndkey1,$inout4
1580          movups         0x10($inp),$in1         # pre-load input
1581          movups         0x20($inp),$in2
1582         aesenc          $rndkey1,$inout5
1583         aesenc          $rndkey1,$inout6
1584
1585         call            .Lenc_loop8_enter
1586
1587         movdqu  0x30($inp),$in3
1588         pxor    $in0,$inout0
1589         movdqu  0x40($inp),$in0
1590         pxor    $in1,$inout1
1591         movdqu  $inout0,($out)                  # store output
1592         pxor    $in2,$inout2
1593         movdqu  $inout1,0x10($out)
1594         pxor    $in3,$inout3
1595         movdqu  $inout2,0x20($out)
1596         pxor    $in0,$inout4
1597         movdqu  $inout3,0x30($out)
1598         movdqu  $inout4,0x40($out)
1599         cmp     \$6,$len
1600         jb      .Lctr32_done                    # $len was 5, stop store
1601
1602         movups  0x50($inp),$in1
1603         xorps   $in1,$inout5
1604         movups  $inout5,0x50($out)
1605         je      .Lctr32_done                    # $len was 6, stop store
1606
1607         movups  0x60($inp),$in2
1608         xorps   $in2,$inout6
1609         movups  $inout6,0x60($out)
1610         jmp     .Lctr32_done                    # $len was 7, stop store
1611
1612 .align  32
1613 .Lctr32_loop4:
1614         aesenc          $rndkey1,$inout0
1615         lea             16($key),$key
1616         dec             $rounds
1617         aesenc          $rndkey1,$inout1
1618         aesenc          $rndkey1,$inout2
1619         aesenc          $rndkey1,$inout3
1620         $movkey         ($key),$rndkey1
1621         jnz             .Lctr32_loop4
1622         aesenclast      $rndkey1,$inout0
1623         aesenclast      $rndkey1,$inout1
1624          movups         ($inp),$in0             # load input
1625          movups         0x10($inp),$in1
1626         aesenclast      $rndkey1,$inout2
1627         aesenclast      $rndkey1,$inout3
1628          movups         0x20($inp),$in2
1629          movups         0x30($inp),$in3
1630
1631         xorps   $in0,$inout0
1632         movups  $inout0,($out)                  # store output
1633         xorps   $in1,$inout1
1634         movups  $inout1,0x10($out)
1635         pxor    $in2,$inout2
1636         movdqu  $inout2,0x20($out)
1637         pxor    $in3,$inout3
1638         movdqu  $inout3,0x30($out)
1639         jmp     .Lctr32_done                    # $len was 4, stop store
1640
1641 .align  32
1642 .Lctr32_loop3:
1643         aesenc          $rndkey1,$inout0
1644         lea             16($key),$key
1645         dec             $rounds
1646         aesenc          $rndkey1,$inout1
1647         aesenc          $rndkey1,$inout2
1648         $movkey         ($key),$rndkey1
1649         jnz             .Lctr32_loop3
1650         aesenclast      $rndkey1,$inout0
1651         aesenclast      $rndkey1,$inout1
1652         aesenclast      $rndkey1,$inout2
1653
1654         movups  ($inp),$in0                     # load input
1655         xorps   $in0,$inout0
1656         movups  $inout0,($out)                  # store output
1657         cmp     \$2,$len
1658         jb      .Lctr32_done                    # $len was 1, stop store
1659
1660         movups  0x10($inp),$in1
1661         xorps   $in1,$inout1
1662         movups  $inout1,0x10($out)
1663         je      .Lctr32_done                    # $len was 2, stop store
1664
1665         movups  0x20($inp),$in2
1666         xorps   $in2,$inout2
1667         movups  $inout2,0x20($out)              # $len was 3, stop store
1668
1669 .Lctr32_done:
1670         xorps   %xmm0,%xmm0                     # clear register bank
1671         xor     $key0,$key0
1672         pxor    %xmm1,%xmm1
1673         pxor    %xmm2,%xmm2
1674         pxor    %xmm3,%xmm3
1675         pxor    %xmm4,%xmm4
1676         pxor    %xmm5,%xmm5
1677 ___
1678 $code.=<<___ if (!$win64);
1679         pxor    %xmm6,%xmm6
1680         pxor    %xmm7,%xmm7
1681         movaps  %xmm0,0x00(%rsp)                # clear stack
1682         pxor    %xmm8,%xmm8
1683         movaps  %xmm0,0x10(%rsp)
1684         pxor    %xmm9,%xmm9
1685         movaps  %xmm0,0x20(%rsp)
1686         pxor    %xmm10,%xmm10
1687         movaps  %xmm0,0x30(%rsp)
1688         pxor    %xmm11,%xmm11
1689         movaps  %xmm0,0x40(%rsp)
1690         pxor    %xmm12,%xmm12
1691         movaps  %xmm0,0x50(%rsp)
1692         pxor    %xmm13,%xmm13
1693         movaps  %xmm0,0x60(%rsp)
1694         pxor    %xmm14,%xmm14
1695         movaps  %xmm0,0x70(%rsp)
1696         pxor    %xmm15,%xmm15
1697 ___
1698 $code.=<<___ if ($win64);
1699         movaps  -0xa8($key_),%xmm6
1700         movaps  %xmm0,-0xa8($key_)              # clear stack
1701         movaps  -0x98($key_),%xmm7
1702         movaps  %xmm0,-0x98($key_)
1703         movaps  -0x88($key_),%xmm8
1704         movaps  %xmm0,-0x88($key_)
1705         movaps  -0x78($key_),%xmm9
1706         movaps  %xmm0,-0x78($key_)
1707         movaps  -0x68($key_),%xmm10
1708         movaps  %xmm0,-0x68($key_)
1709         movaps  -0x58($key_),%xmm11
1710         movaps  %xmm0,-0x58($key_)
1711         movaps  -0x48($key_),%xmm12
1712         movaps  %xmm0,-0x48($key_)
1713         movaps  -0x38($key_),%xmm13
1714         movaps  %xmm0,-0x38($key_)
1715         movaps  -0x28($key_),%xmm14
1716         movaps  %xmm0,-0x28($key_)
1717         movaps  -0x18($key_),%xmm15
1718         movaps  %xmm0,-0x18($key_)
1719         movaps  %xmm0,0x00(%rsp)
1720         movaps  %xmm0,0x10(%rsp)
1721         movaps  %xmm0,0x20(%rsp)
1722         movaps  %xmm0,0x30(%rsp)
1723         movaps  %xmm0,0x40(%rsp)
1724         movaps  %xmm0,0x50(%rsp)
1725         movaps  %xmm0,0x60(%rsp)
1726         movaps  %xmm0,0x70(%rsp)
1727 ___
1728 $code.=<<___;
1729         mov     -8($key_),%rbp
1730 .cfi_restore    %rbp
1731         lea     ($key_),%rsp
1732 .cfi_def_cfa_register   %rsp
1733 .Lctr32_epilogue:
1734         ret
1735 .cfi_endproc
1736 .size   aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks
1737 ___
1738 }
1739 \f
1740 ######################################################################
1741 # void aesni_xts_[en|de]crypt(const char *inp,char *out,size_t len,
1742 #       const AES_KEY *key1, const AES_KEY *key2
1743 #       const unsigned char iv[16]);
1744 #
1745 {
1746 my @tweak=map("%xmm$_",(10..15));
1747 my ($twmask,$twres,$twtmp)=("%xmm8","%xmm9",@tweak[4]);
1748 my ($key2,$ivp,$len_)=("%r8","%r9","%r9");
1749 my $frame_size = 0x70 + ($win64?160:0);
1750 my $key_ = "%rbp";      # override so that we can use %r11 as FP
1751
1752 $code.=<<___;
1753 .globl  aesni_xts_encrypt
1754 .type   aesni_xts_encrypt,\@function,6
1755 .align  16
1756 aesni_xts_encrypt:
1757 .cfi_startproc
1758         lea     (%rsp),%r11                     # frame pointer
1759 .cfi_def_cfa_register   %r11
1760         push    %rbp
1761 .cfi_push       %rbp
1762         sub     \$$frame_size,%rsp
1763         and     \$-16,%rsp      # Linux kernel stack can be incorrectly seeded
1764 ___
1765 $code.=<<___ if ($win64);
1766         movaps  %xmm6,-0xa8(%r11)               # offload everything
1767         movaps  %xmm7,-0x98(%r11)
1768         movaps  %xmm8,-0x88(%r11)
1769         movaps  %xmm9,-0x78(%r11)
1770         movaps  %xmm10,-0x68(%r11)
1771         movaps  %xmm11,-0x58(%r11)
1772         movaps  %xmm12,-0x48(%r11)
1773         movaps  %xmm13,-0x38(%r11)
1774         movaps  %xmm14,-0x28(%r11)
1775         movaps  %xmm15,-0x18(%r11)
1776 .Lxts_enc_body:
1777 ___
1778 $code.=<<___;
1779         movups  ($ivp),$inout0                  # load clear-text tweak
1780         mov     240(%r8),$rounds                # key2->rounds
1781         mov     240($key),$rnds_                # key1->rounds
1782 ___
1783         # generate the tweak
1784         &aesni_generate1("enc",$key2,$rounds,$inout0);
1785 $code.=<<___;
1786         $movkey ($key),$rndkey0                 # zero round key
1787         mov     $key,$key_                      # backup $key
1788         mov     $rnds_,$rounds                  # backup $rounds
1789         shl     \$4,$rnds_
1790         mov     $len,$len_                      # backup $len
1791         and     \$-16,$len
1792
1793         $movkey 16($key,$rnds_),$rndkey1        # last round key
1794
1795         movdqa  .Lxts_magic(%rip),$twmask
1796         movdqa  $inout0,@tweak[5]
1797         pshufd  \$0x5f,$inout0,$twres
1798         pxor    $rndkey0,$rndkey1
1799 ___
1800     # alternative tweak calculation algorithm is based on suggestions
1801     # by Shay Gueron. psrad doesn't conflict with AES-NI instructions
1802     # and should help in the future...
1803     for ($i=0;$i<4;$i++) {
1804     $code.=<<___;
1805         movdqa  $twres,$twtmp
1806         paddd   $twres,$twres
1807         movdqa  @tweak[5],@tweak[$i]
1808         psrad   \$31,$twtmp                     # broadcast upper bits
1809         paddq   @tweak[5],@tweak[5]
1810         pand    $twmask,$twtmp
1811         pxor    $rndkey0,@tweak[$i]
1812         pxor    $twtmp,@tweak[5]
1813 ___
1814     }
1815 $code.=<<___;
1816         movdqa  @tweak[5],@tweak[4]
1817         psrad   \$31,$twres
1818         paddq   @tweak[5],@tweak[5]
1819         pand    $twmask,$twres
1820         pxor    $rndkey0,@tweak[4]
1821         pxor    $twres,@tweak[5]
1822         movaps  $rndkey1,0x60(%rsp)             # save round[0]^round[last]
1823
1824         sub     \$16*6,$len
1825         jc      .Lxts_enc_short                 # if $len-=6*16 borrowed
1826
1827         mov     \$16+96,$rounds
1828         lea     32($key_,$rnds_),$key           # end of key schedule
1829         sub     %r10,%rax                       # twisted $rounds
1830         $movkey 16($key_),$rndkey1
1831         mov     %rax,%r10                       # backup twisted $rounds
1832         lea     .Lxts_magic(%rip),%r8
1833         jmp     .Lxts_enc_grandloop
1834
1835 .align  32
1836 .Lxts_enc_grandloop:
1837         movdqu  `16*0`($inp),$inout0            # load input
1838         movdqa  $rndkey0,$twmask
1839         movdqu  `16*1`($inp),$inout1
1840         pxor    @tweak[0],$inout0               # input^=tweak^round[0]
1841         movdqu  `16*2`($inp),$inout2
1842         pxor    @tweak[1],$inout1
1843          aesenc         $rndkey1,$inout0
1844         movdqu  `16*3`($inp),$inout3
1845         pxor    @tweak[2],$inout2
1846          aesenc         $rndkey1,$inout1
1847         movdqu  `16*4`($inp),$inout4
1848         pxor    @tweak[3],$inout3
1849          aesenc         $rndkey1,$inout2
1850         movdqu  `16*5`($inp),$inout5
1851         pxor    @tweak[5],$twmask               # round[0]^=tweak[5]
1852          movdqa 0x60(%rsp),$twres               # load round[0]^round[last]
1853         pxor    @tweak[4],$inout4
1854          aesenc         $rndkey1,$inout3
1855         $movkey 32($key_),$rndkey0
1856         lea     `16*6`($inp),$inp
1857         pxor    $twmask,$inout5
1858
1859          pxor   $twres,@tweak[0]                # calculate tweaks^round[last]
1860         aesenc          $rndkey1,$inout4
1861          pxor   $twres,@tweak[1]
1862          movdqa @tweak[0],`16*0`(%rsp)          # put aside tweaks^round[last]
1863         aesenc          $rndkey1,$inout5
1864         $movkey         48($key_),$rndkey1
1865          pxor   $twres,@tweak[2]
1866
1867         aesenc          $rndkey0,$inout0
1868          pxor   $twres,@tweak[3]
1869          movdqa @tweak[1],`16*1`(%rsp)
1870         aesenc          $rndkey0,$inout1
1871          pxor   $twres,@tweak[4]
1872          movdqa @tweak[2],`16*2`(%rsp)
1873         aesenc          $rndkey0,$inout2
1874         aesenc          $rndkey0,$inout3
1875          pxor   $twres,$twmask
1876          movdqa @tweak[4],`16*4`(%rsp)
1877         aesenc          $rndkey0,$inout4
1878         aesenc          $rndkey0,$inout5
1879         $movkey         64($key_),$rndkey0
1880          movdqa $twmask,`16*5`(%rsp)
1881         pshufd  \$0x5f,@tweak[5],$twres
1882         jmp     .Lxts_enc_loop6
1883 .align  32
1884 .Lxts_enc_loop6:
1885         aesenc          $rndkey1,$inout0
1886         aesenc          $rndkey1,$inout1
1887         aesenc          $rndkey1,$inout2
1888         aesenc          $rndkey1,$inout3
1889         aesenc          $rndkey1,$inout4
1890         aesenc          $rndkey1,$inout5
1891         $movkey         -64($key,%rax),$rndkey1
1892         add             \$32,%rax
1893
1894         aesenc          $rndkey0,$inout0
1895         aesenc          $rndkey0,$inout1
1896         aesenc          $rndkey0,$inout2
1897         aesenc          $rndkey0,$inout3
1898         aesenc          $rndkey0,$inout4
1899         aesenc          $rndkey0,$inout5
1900         $movkey         -80($key,%rax),$rndkey0
1901         jnz             .Lxts_enc_loop6
1902
1903         movdqa  (%r8),$twmask                   # start calculating next tweak
1904         movdqa  $twres,$twtmp
1905         paddd   $twres,$twres
1906          aesenc         $rndkey1,$inout0
1907         paddq   @tweak[5],@tweak[5]
1908         psrad   \$31,$twtmp
1909          aesenc         $rndkey1,$inout1
1910         pand    $twmask,$twtmp
1911         $movkey ($key_),@tweak[0]               # load round[0]
1912          aesenc         $rndkey1,$inout2
1913          aesenc         $rndkey1,$inout3
1914          aesenc         $rndkey1,$inout4
1915         pxor    $twtmp,@tweak[5]
1916         movaps  @tweak[0],@tweak[1]             # copy round[0]
1917          aesenc         $rndkey1,$inout5
1918          $movkey        -64($key),$rndkey1
1919
1920         movdqa  $twres,$twtmp
1921          aesenc         $rndkey0,$inout0
1922         paddd   $twres,$twres
1923         pxor    @tweak[5],@tweak[0]
1924          aesenc         $rndkey0,$inout1
1925         psrad   \$31,$twtmp
1926         paddq   @tweak[5],@tweak[5]
1927          aesenc         $rndkey0,$inout2
1928          aesenc         $rndkey0,$inout3
1929         pand    $twmask,$twtmp
1930         movaps  @tweak[1],@tweak[2]
1931          aesenc         $rndkey0,$inout4
1932         pxor    $twtmp,@tweak[5]
1933         movdqa  $twres,$twtmp
1934          aesenc         $rndkey0,$inout5
1935          $movkey        -48($key),$rndkey0
1936
1937         paddd   $twres,$twres
1938          aesenc         $rndkey1,$inout0
1939         pxor    @tweak[5],@tweak[1]
1940         psrad   \$31,$twtmp
1941          aesenc         $rndkey1,$inout1
1942         paddq   @tweak[5],@tweak[5]
1943         pand    $twmask,$twtmp
1944          aesenc         $rndkey1,$inout2
1945          aesenc         $rndkey1,$inout3
1946          movdqa @tweak[3],`16*3`(%rsp)
1947         pxor    $twtmp,@tweak[5]
1948          aesenc         $rndkey1,$inout4
1949         movaps  @tweak[2],@tweak[3]
1950         movdqa  $twres,$twtmp
1951          aesenc         $rndkey1,$inout5
1952          $movkey        -32($key),$rndkey1
1953
1954         paddd   $twres,$twres
1955          aesenc         $rndkey0,$inout0
1956         pxor    @tweak[5],@tweak[2]
1957         psrad   \$31,$twtmp
1958          aesenc         $rndkey0,$inout1
1959         paddq   @tweak[5],@tweak[5]
1960         pand    $twmask,$twtmp
1961          aesenc         $rndkey0,$inout2
1962          aesenc         $rndkey0,$inout3
1963          aesenc         $rndkey0,$inout4
1964         pxor    $twtmp,@tweak[5]
1965         movaps  @tweak[3],@tweak[4]
1966          aesenc         $rndkey0,$inout5
1967
1968         movdqa  $twres,$rndkey0
1969         paddd   $twres,$twres
1970          aesenc         $rndkey1,$inout0
1971         pxor    @tweak[5],@tweak[3]
1972         psrad   \$31,$rndkey0
1973          aesenc         $rndkey1,$inout1
1974         paddq   @tweak[5],@tweak[5]
1975         pand    $twmask,$rndkey0
1976          aesenc         $rndkey1,$inout2
1977          aesenc         $rndkey1,$inout3
1978         pxor    $rndkey0,@tweak[5]
1979         $movkey         ($key_),$rndkey0
1980          aesenc         $rndkey1,$inout4
1981          aesenc         $rndkey1,$inout5
1982         $movkey         16($key_),$rndkey1
1983
1984         pxor    @tweak[5],@tweak[4]
1985          aesenclast     `16*0`(%rsp),$inout0
1986         psrad   \$31,$twres
1987         paddq   @tweak[5],@tweak[5]
1988          aesenclast     `16*1`(%rsp),$inout1
1989          aesenclast     `16*2`(%rsp),$inout2
1990         pand    $twmask,$twres
1991         mov     %r10,%rax                       # restore $rounds
1992          aesenclast     `16*3`(%rsp),$inout3
1993          aesenclast     `16*4`(%rsp),$inout4
1994          aesenclast     `16*5`(%rsp),$inout5
1995         pxor    $twres,@tweak[5]
1996
1997         lea     `16*6`($out),$out               # $out+=6*16
1998         movups  $inout0,`-16*6`($out)           # store 6 output blocks
1999         movups  $inout1,`-16*5`($out)
2000         movups  $inout2,`-16*4`($out)
2001         movups  $inout3,`-16*3`($out)
2002         movups  $inout4,`-16*2`($out)
2003         movups  $inout5,`-16*1`($out)
2004         sub     \$16*6,$len
2005         jnc     .Lxts_enc_grandloop             # loop if $len-=6*16 didn't borrow
2006
2007         mov     \$16+96,$rounds
2008         sub     $rnds_,$rounds
2009         mov     $key_,$key                      # restore $key
2010         shr     \$4,$rounds                     # restore original value
2011
2012 .Lxts_enc_short:
2013         # at the point @tweak[0..5] are populated with tweak values
2014         mov     $rounds,$rnds_                  # backup $rounds
2015         pxor    $rndkey0,@tweak[0]
2016         add     \$16*6,$len                     # restore real remaining $len
2017         jz      .Lxts_enc_done                  # done if ($len==0)
2018
2019         pxor    $rndkey0,@tweak[1]
2020         cmp     \$0x20,$len
2021         jb      .Lxts_enc_one                   # $len is 1*16
2022         pxor    $rndkey0,@tweak[2]
2023         je      .Lxts_enc_two                   # $len is 2*16
2024
2025         pxor    $rndkey0,@tweak[3]
2026         cmp     \$0x40,$len
2027         jb      .Lxts_enc_three                 # $len is 3*16
2028         pxor    $rndkey0,@tweak[4]
2029         je      .Lxts_enc_four                  # $len is 4*16
2030
2031         movdqu  ($inp),$inout0                  # $len is 5*16
2032         movdqu  16*1($inp),$inout1
2033         movdqu  16*2($inp),$inout2
2034         pxor    @tweak[0],$inout0
2035         movdqu  16*3($inp),$inout3
2036         pxor    @tweak[1],$inout1
2037         movdqu  16*4($inp),$inout4
2038         lea     16*5($inp),$inp                 # $inp+=5*16
2039         pxor    @tweak[2],$inout2
2040         pxor    @tweak[3],$inout3
2041         pxor    @tweak[4],$inout4
2042         pxor    $inout5,$inout5
2043
2044         call    _aesni_encrypt6
2045
2046         xorps   @tweak[0],$inout0
2047         movdqa  @tweak[5],@tweak[0]
2048         xorps   @tweak[1],$inout1
2049         xorps   @tweak[2],$inout2
2050         movdqu  $inout0,($out)                  # store 5 output blocks
2051         xorps   @tweak[3],$inout3
2052         movdqu  $inout1,16*1($out)
2053         xorps   @tweak[4],$inout4
2054         movdqu  $inout2,16*2($out)
2055         movdqu  $inout3,16*3($out)
2056         movdqu  $inout4,16*4($out)
2057         lea     16*5($out),$out                 # $out+=5*16
2058         jmp     .Lxts_enc_done
2059
2060 .align  16
2061 .Lxts_enc_one:
2062         movups  ($inp),$inout0
2063         lea     16*1($inp),$inp                 # inp+=1*16
2064         xorps   @tweak[0],$inout0
2065 ___
2066         &aesni_generate1("enc",$key,$rounds);
2067 $code.=<<___;
2068         xorps   @tweak[0],$inout0
2069         movdqa  @tweak[1],@tweak[0]
2070         movups  $inout0,($out)                  # store one output block
2071         lea     16*1($out),$out                 # $out+=1*16
2072         jmp     .Lxts_enc_done
2073
2074 .align  16
2075 .Lxts_enc_two:
2076         movups  ($inp),$inout0
2077         movups  16($inp),$inout1
2078         lea     32($inp),$inp                   # $inp+=2*16
2079         xorps   @tweak[0],$inout0
2080         xorps   @tweak[1],$inout1
2081
2082         call    _aesni_encrypt2
2083
2084         xorps   @tweak[0],$inout0
2085         movdqa  @tweak[2],@tweak[0]
2086         xorps   @tweak[1],$inout1
2087         movups  $inout0,($out)                  # store 2 output blocks
2088         movups  $inout1,16*1($out)
2089         lea     16*2($out),$out                 # $out+=2*16
2090         jmp     .Lxts_enc_done
2091
2092 .align  16
2093 .Lxts_enc_three:
2094         movups  ($inp),$inout0
2095         movups  16*1($inp),$inout1
2096         movups  16*2($inp),$inout2
2097         lea     16*3($inp),$inp                 # $inp+=3*16
2098         xorps   @tweak[0],$inout0
2099         xorps   @tweak[1],$inout1
2100         xorps   @tweak[2],$inout2
2101
2102         call    _aesni_encrypt3
2103
2104         xorps   @tweak[0],$inout0
2105         movdqa  @tweak[3],@tweak[0]
2106         xorps   @tweak[1],$inout1
2107         xorps   @tweak[2],$inout2
2108         movups  $inout0,($out)                  # store 3 output blocks
2109         movups  $inout1,16*1($out)
2110         movups  $inout2,16*2($out)
2111         lea     16*3($out),$out                 # $out+=3*16
2112         jmp     .Lxts_enc_done
2113
2114 .align  16
2115 .Lxts_enc_four:
2116         movups  ($inp),$inout0
2117         movups  16*1($inp),$inout1
2118         movups  16*2($inp),$inout2
2119         xorps   @tweak[0],$inout0
2120         movups  16*3($inp),$inout3
2121         lea     16*4($inp),$inp                 # $inp+=4*16
2122         xorps   @tweak[1],$inout1
2123         xorps   @tweak[2],$inout2
2124         xorps   @tweak[3],$inout3
2125
2126         call    _aesni_encrypt4
2127
2128         pxor    @tweak[0],$inout0
2129         movdqa  @tweak[4],@tweak[0]
2130         pxor    @tweak[1],$inout1
2131         pxor    @tweak[2],$inout2
2132         movdqu  $inout0,($out)                  # store 4 output blocks
2133         pxor    @tweak[3],$inout3
2134         movdqu  $inout1,16*1($out)
2135         movdqu  $inout2,16*2($out)
2136         movdqu  $inout3,16*3($out)
2137         lea     16*4($out),$out                 # $out+=4*16
2138         jmp     .Lxts_enc_done
2139
2140 .align  16
2141 .Lxts_enc_done:
2142         and     \$15,$len_                      # see if $len%16 is 0
2143         jz      .Lxts_enc_ret
2144         mov     $len_,$len
2145
2146 .Lxts_enc_steal:
2147         movzb   ($inp),%eax                     # borrow $rounds ...
2148         movzb   -16($out),%ecx                  # ... and $key
2149         lea     1($inp),$inp
2150         mov     %al,-16($out)
2151         mov     %cl,0($out)
2152         lea     1($out),$out
2153         sub     \$1,$len
2154         jnz     .Lxts_enc_steal
2155
2156         sub     $len_,$out                      # rewind $out
2157         mov     $key_,$key                      # restore $key
2158         mov     $rnds_,$rounds                  # restore $rounds
2159
2160         movups  -16($out),$inout0
2161         xorps   @tweak[0],$inout0
2162 ___
2163         &aesni_generate1("enc",$key,$rounds);
2164 $code.=<<___;
2165         xorps   @tweak[0],$inout0
2166         movups  $inout0,-16($out)
2167
2168 .Lxts_enc_ret:
2169         xorps   %xmm0,%xmm0                     # clear register bank
2170         pxor    %xmm1,%xmm1
2171         pxor    %xmm2,%xmm2
2172         pxor    %xmm3,%xmm3
2173         pxor    %xmm4,%xmm4
2174         pxor    %xmm5,%xmm5
2175 ___
2176 $code.=<<___ if (!$win64);
2177         pxor    %xmm6,%xmm6
2178         pxor    %xmm7,%xmm7
2179         movaps  %xmm0,0x00(%rsp)                # clear stack
2180         pxor    %xmm8,%xmm8
2181         movaps  %xmm0,0x10(%rsp)
2182         pxor    %xmm9,%xmm9
2183         movaps  %xmm0,0x20(%rsp)
2184         pxor    %xmm10,%xmm10
2185         movaps  %xmm0,0x30(%rsp)
2186         pxor    %xmm11,%xmm11
2187         movaps  %xmm0,0x40(%rsp)
2188         pxor    %xmm12,%xmm12
2189         movaps  %xmm0,0x50(%rsp)
2190         pxor    %xmm13,%xmm13
2191         movaps  %xmm0,0x60(%rsp)
2192         pxor    %xmm14,%xmm14
2193         pxor    %xmm15,%xmm15
2194 ___
2195 $code.=<<___ if ($win64);
2196         movaps  -0xa8(%r11),%xmm6
2197         movaps  %xmm0,-0xa8(%r11)               # clear stack
2198         movaps  -0x98(%r11),%xmm7
2199         movaps  %xmm0,-0x98(%r11)
2200         movaps  -0x88(%r11),%xmm8
2201         movaps  %xmm0,-0x88(%r11)
2202         movaps  -0x78(%r11),%xmm9
2203         movaps  %xmm0,-0x78(%r11)
2204         movaps  -0x68(%r11),%xmm10
2205         movaps  %xmm0,-0x68(%r11)
2206         movaps  -0x58(%r11),%xmm11
2207         movaps  %xmm0,-0x58(%r11)
2208         movaps  -0x48(%r11),%xmm12
2209         movaps  %xmm0,-0x48(%r11)
2210         movaps  -0x38(%r11),%xmm13
2211         movaps  %xmm0,-0x38(%r11)
2212         movaps  -0x28(%r11),%xmm14
2213         movaps  %xmm0,-0x28(%r11)
2214         movaps  -0x18(%r11),%xmm15
2215         movaps  %xmm0,-0x18(%r11)
2216         movaps  %xmm0,0x00(%rsp)
2217         movaps  %xmm0,0x10(%rsp)
2218         movaps  %xmm0,0x20(%rsp)
2219         movaps  %xmm0,0x30(%rsp)
2220         movaps  %xmm0,0x40(%rsp)
2221         movaps  %xmm0,0x50(%rsp)
2222         movaps  %xmm0,0x60(%rsp)
2223 ___
2224 $code.=<<___;
2225         mov     -8(%r11),%rbp
2226 .cfi_restore    %rbp
2227         lea     (%r11),%rsp
2228 .cfi_def_cfa_register   %rsp
2229 .Lxts_enc_epilogue:
2230         ret
2231 .cfi_endproc
2232 .size   aesni_xts_encrypt,.-aesni_xts_encrypt
2233 ___
2234
2235 $code.=<<___;
2236 .globl  aesni_xts_decrypt
2237 .type   aesni_xts_decrypt,\@function,6
2238 .align  16
2239 aesni_xts_decrypt:
2240 .cfi_startproc
2241         lea     (%rsp),%r11                     # frame pointer
2242 .cfi_def_cfa_register   %r11
2243         push    %rbp
2244 .cfi_push       %rbp
2245         sub     \$$frame_size,%rsp
2246         and     \$-16,%rsp      # Linux kernel stack can be incorrectly seeded
2247 ___
2248 $code.=<<___ if ($win64);
2249         movaps  %xmm6,-0xa8(%r11)               # offload everything
2250         movaps  %xmm7,-0x98(%r11)
2251         movaps  %xmm8,-0x88(%r11)
2252         movaps  %xmm9,-0x78(%r11)
2253         movaps  %xmm10,-0x68(%r11)
2254         movaps  %xmm11,-0x58(%r11)
2255         movaps  %xmm12,-0x48(%r11)
2256         movaps  %xmm13,-0x38(%r11)
2257         movaps  %xmm14,-0x28(%r11)
2258         movaps  %xmm15,-0x18(%r11)
2259 .Lxts_dec_body:
2260 ___
2261 $code.=<<___;
2262         movups  ($ivp),$inout0                  # load clear-text tweak
2263         mov     240($key2),$rounds              # key2->rounds
2264         mov     240($key),$rnds_                # key1->rounds
2265 ___
2266         # generate the tweak
2267         &aesni_generate1("enc",$key2,$rounds,$inout0);
2268 $code.=<<___;
2269         xor     %eax,%eax                       # if ($len%16) len-=16;
2270         test    \$15,$len
2271         setnz   %al
2272         shl     \$4,%rax
2273         sub     %rax,$len
2274
2275         $movkey ($key),$rndkey0                 # zero round key
2276         mov     $key,$key_                      # backup $key
2277         mov     $rnds_,$rounds                  # backup $rounds
2278         shl     \$4,$rnds_
2279         mov     $len,$len_                      # backup $len
2280         and     \$-16,$len
2281
2282         $movkey 16($key,$rnds_),$rndkey1        # last round key
2283
2284         movdqa  .Lxts_magic(%rip),$twmask
2285         movdqa  $inout0,@tweak[5]
2286         pshufd  \$0x5f,$inout0,$twres
2287         pxor    $rndkey0,$rndkey1
2288 ___
2289     for ($i=0;$i<4;$i++) {
2290     $code.=<<___;
2291         movdqa  $twres,$twtmp
2292         paddd   $twres,$twres
2293         movdqa  @tweak[5],@tweak[$i]
2294         psrad   \$31,$twtmp                     # broadcast upper bits
2295         paddq   @tweak[5],@tweak[5]
2296         pand    $twmask,$twtmp
2297         pxor    $rndkey0,@tweak[$i]
2298         pxor    $twtmp,@tweak[5]
2299 ___
2300     }
2301 $code.=<<___;
2302         movdqa  @tweak[5],@tweak[4]
2303         psrad   \$31,$twres
2304         paddq   @tweak[5],@tweak[5]
2305         pand    $twmask,$twres
2306         pxor    $rndkey0,@tweak[4]
2307         pxor    $twres,@tweak[5]
2308         movaps  $rndkey1,0x60(%rsp)             # save round[0]^round[last]
2309
2310         sub     \$16*6,$len
2311         jc      .Lxts_dec_short                 # if $len-=6*16 borrowed
2312
2313         mov     \$16+96,$rounds
2314         lea     32($key_,$rnds_),$key           # end of key schedule
2315         sub     %r10,%rax                       # twisted $rounds
2316         $movkey 16($key_),$rndkey1
2317         mov     %rax,%r10                       # backup twisted $rounds
2318         lea     .Lxts_magic(%rip),%r8
2319         jmp     .Lxts_dec_grandloop
2320
2321 .align  32
2322 .Lxts_dec_grandloop:
2323         movdqu  `16*0`($inp),$inout0            # load input
2324         movdqa  $rndkey0,$twmask
2325         movdqu  `16*1`($inp),$inout1
2326         pxor    @tweak[0],$inout0               # intput^=tweak^round[0]
2327         movdqu  `16*2`($inp),$inout2
2328         pxor    @tweak[1],$inout1
2329          aesdec         $rndkey1,$inout0
2330         movdqu  `16*3`($inp),$inout3
2331         pxor    @tweak[2],$inout2
2332          aesdec         $rndkey1,$inout1
2333         movdqu  `16*4`($inp),$inout4
2334         pxor    @tweak[3],$inout3
2335          aesdec         $rndkey1,$inout2
2336         movdqu  `16*5`($inp),$inout5
2337         pxor    @tweak[5],$twmask               # round[0]^=tweak[5]
2338          movdqa 0x60(%rsp),$twres               # load round[0]^round[last]
2339         pxor    @tweak[4],$inout4
2340          aesdec         $rndkey1,$inout3
2341         $movkey 32($key_),$rndkey0
2342         lea     `16*6`($inp),$inp
2343         pxor    $twmask,$inout5
2344
2345          pxor   $twres,@tweak[0]                # calculate tweaks^round[last]
2346         aesdec          $rndkey1,$inout4
2347          pxor   $twres,@tweak[1]
2348          movdqa @tweak[0],`16*0`(%rsp)          # put aside tweaks^last round key
2349         aesdec          $rndkey1,$inout5
2350         $movkey         48($key_),$rndkey1
2351          pxor   $twres,@tweak[2]
2352
2353         aesdec          $rndkey0,$inout0
2354          pxor   $twres,@tweak[3]
2355          movdqa @tweak[1],`16*1`(%rsp)
2356         aesdec          $rndkey0,$inout1
2357          pxor   $twres,@tweak[4]
2358          movdqa @tweak[2],`16*2`(%rsp)
2359         aesdec          $rndkey0,$inout2
2360         aesdec          $rndkey0,$inout3
2361          pxor   $twres,$twmask
2362          movdqa @tweak[4],`16*4`(%rsp)
2363         aesdec          $rndkey0,$inout4
2364         aesdec          $rndkey0,$inout5
2365         $movkey         64($key_),$rndkey0
2366          movdqa $twmask,`16*5`(%rsp)
2367         pshufd  \$0x5f,@tweak[5],$twres
2368         jmp     .Lxts_dec_loop6
2369 .align  32
2370 .Lxts_dec_loop6:
2371         aesdec          $rndkey1,$inout0
2372         aesdec          $rndkey1,$inout1
2373         aesdec          $rndkey1,$inout2
2374         aesdec          $rndkey1,$inout3
2375         aesdec          $rndkey1,$inout4
2376         aesdec          $rndkey1,$inout5
2377         $movkey         -64($key,%rax),$rndkey1
2378         add             \$32,%rax
2379
2380         aesdec          $rndkey0,$inout0
2381         aesdec          $rndkey0,$inout1
2382         aesdec          $rndkey0,$inout2
2383         aesdec          $rndkey0,$inout3
2384         aesdec          $rndkey0,$inout4
2385         aesdec          $rndkey0,$inout5
2386         $movkey         -80($key,%rax),$rndkey0
2387         jnz             .Lxts_dec_loop6
2388
2389         movdqa  (%r8),$twmask                   # start calculating next tweak
2390         movdqa  $twres,$twtmp
2391         paddd   $twres,$twres
2392          aesdec         $rndkey1,$inout0
2393         paddq   @tweak[5],@tweak[5]
2394         psrad   \$31,$twtmp
2395          aesdec         $rndkey1,$inout1
2396         pand    $twmask,$twtmp
2397         $movkey ($key_),@tweak[0]               # load round[0]
2398          aesdec         $rndkey1,$inout2
2399          aesdec         $rndkey1,$inout3
2400          aesdec         $rndkey1,$inout4
2401         pxor    $twtmp,@tweak[5]
2402         movaps  @tweak[0],@tweak[1]             # copy round[0]
2403          aesdec         $rndkey1,$inout5
2404          $movkey        -64($key),$rndkey1
2405
2406         movdqa  $twres,$twtmp
2407          aesdec         $rndkey0,$inout0
2408         paddd   $twres,$twres
2409         pxor    @tweak[5],@tweak[0]
2410          aesdec         $rndkey0,$inout1
2411         psrad   \$31,$twtmp
2412         paddq   @tweak[5],@tweak[5]
2413          aesdec         $rndkey0,$inout2
2414          aesdec         $rndkey0,$inout3
2415         pand    $twmask,$twtmp
2416         movaps  @tweak[1],@tweak[2]
2417          aesdec         $rndkey0,$inout4
2418         pxor    $twtmp,@tweak[5]
2419         movdqa  $twres,$twtmp
2420          aesdec         $rndkey0,$inout5
2421          $movkey        -48($key),$rndkey0
2422
2423         paddd   $twres,$twres
2424          aesdec         $rndkey1,$inout0
2425         pxor    @tweak[5],@tweak[1]
2426         psrad   \$31,$twtmp
2427          aesdec         $rndkey1,$inout1
2428         paddq   @tweak[5],@tweak[5]
2429         pand    $twmask,$twtmp
2430          aesdec         $rndkey1,$inout2
2431          aesdec         $rndkey1,$inout3
2432          movdqa @tweak[3],`16*3`(%rsp)
2433         pxor    $twtmp,@tweak[5]
2434          aesdec         $rndkey1,$inout4
2435         movaps  @tweak[2],@tweak[3]
2436         movdqa  $twres,$twtmp
2437          aesdec         $rndkey1,$inout5
2438          $movkey        -32($key),$rndkey1
2439
2440         paddd   $twres,$twres
2441          aesdec         $rndkey0,$inout0
2442         pxor    @tweak[5],@tweak[2]
2443         psrad   \$31,$twtmp
2444          aesdec         $rndkey0,$inout1
2445         paddq   @tweak[5],@tweak[5]
2446         pand    $twmask,$twtmp
2447          aesdec         $rndkey0,$inout2
2448          aesdec         $rndkey0,$inout3
2449          aesdec         $rndkey0,$inout4
2450         pxor    $twtmp,@tweak[5]
2451         movaps  @tweak[3],@tweak[4]
2452          aesdec         $rndkey0,$inout5
2453
2454         movdqa  $twres,$rndkey0
2455         paddd   $twres,$twres
2456          aesdec         $rndkey1,$inout0
2457         pxor    @tweak[5],@tweak[3]
2458         psrad   \$31,$rndkey0
2459          aesdec         $rndkey1,$inout1
2460         paddq   @tweak[5],@tweak[5]
2461         pand    $twmask,$rndkey0
2462          aesdec         $rndkey1,$inout2
2463          aesdec         $rndkey1,$inout3
2464         pxor    $rndkey0,@tweak[5]
2465         $movkey         ($key_),$rndkey0
2466          aesdec         $rndkey1,$inout4
2467          aesdec         $rndkey1,$inout5
2468         $movkey         16($key_),$rndkey1
2469
2470         pxor    @tweak[5],@tweak[4]
2471          aesdeclast     `16*0`(%rsp),$inout0
2472         psrad   \$31,$twres
2473         paddq   @tweak[5],@tweak[5]
2474          aesdeclast     `16*1`(%rsp),$inout1
2475          aesdeclast     `16*2`(%rsp),$inout2
2476         pand    $twmask,$twres
2477         mov     %r10,%rax                       # restore $rounds
2478          aesdeclast     `16*3`(%rsp),$inout3
2479          aesdeclast     `16*4`(%rsp),$inout4
2480          aesdeclast     `16*5`(%rsp),$inout5
2481         pxor    $twres,@tweak[5]
2482
2483         lea     `16*6`($out),$out               # $out+=6*16
2484         movups  $inout0,`-16*6`($out)           # store 6 output blocks
2485         movups  $inout1,`-16*5`($out)
2486         movups  $inout2,`-16*4`($out)
2487         movups  $inout3,`-16*3`($out)
2488         movups  $inout4,`-16*2`($out)
2489         movups  $inout5,`-16*1`($out)
2490         sub     \$16*6,$len
2491         jnc     .Lxts_dec_grandloop             # loop if $len-=6*16 didn't borrow
2492
2493         mov     \$16+96,$rounds
2494         sub     $rnds_,$rounds
2495         mov     $key_,$key                      # restore $key
2496         shr     \$4,$rounds                     # restore original value
2497
2498 .Lxts_dec_short:
2499         # at the point @tweak[0..5] are populated with tweak values
2500         mov     $rounds,$rnds_                  # backup $rounds
2501         pxor    $rndkey0,@tweak[0]
2502         pxor    $rndkey0,@tweak[1]
2503         add     \$16*6,$len                     # restore real remaining $len
2504         jz      .Lxts_dec_done                  # done if ($len==0)
2505
2506         pxor    $rndkey0,@tweak[2]
2507         cmp     \$0x20,$len
2508         jb      .Lxts_dec_one                   # $len is 1*16
2509         pxor    $rndkey0,@tweak[3]
2510         je      .Lxts_dec_two                   # $len is 2*16
2511
2512         pxor    $rndkey0,@tweak[4]
2513         cmp     \$0x40,$len
2514         jb      .Lxts_dec_three                 # $len is 3*16
2515         je      .Lxts_dec_four                  # $len is 4*16
2516
2517         movdqu  ($inp),$inout0                  # $len is 5*16
2518         movdqu  16*1($inp),$inout1
2519         movdqu  16*2($inp),$inout2
2520         pxor    @tweak[0],$inout0
2521         movdqu  16*3($inp),$inout3
2522         pxor    @tweak[1],$inout1
2523         movdqu  16*4($inp),$inout4
2524         lea     16*5($inp),$inp                 # $inp+=5*16
2525         pxor    @tweak[2],$inout2
2526         pxor    @tweak[3],$inout3
2527         pxor    @tweak[4],$inout4
2528
2529         call    _aesni_decrypt6
2530
2531         xorps   @tweak[0],$inout0
2532         xorps   @tweak[1],$inout1
2533         xorps   @tweak[2],$inout2
2534         movdqu  $inout0,($out)                  # store 5 output blocks
2535         xorps   @tweak[3],$inout3
2536         movdqu  $inout1,16*1($out)
2537         xorps   @tweak[4],$inout4
2538         movdqu  $inout2,16*2($out)
2539          pxor           $twtmp,$twtmp
2540         movdqu  $inout3,16*3($out)
2541          pcmpgtd        @tweak[5],$twtmp
2542         movdqu  $inout4,16*4($out)
2543         lea     16*5($out),$out                 # $out+=5*16
2544          pshufd         \$0x13,$twtmp,@tweak[1] # $twres
2545         and     \$15,$len_
2546         jz      .Lxts_dec_ret
2547
2548         movdqa  @tweak[5],@tweak[0]
2549         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
2550         pand    $twmask,@tweak[1]               # isolate carry and residue
2551         pxor    @tweak[5],@tweak[1]
2552         jmp     .Lxts_dec_done2
2553
2554 .align  16
2555 .Lxts_dec_one:
2556         movups  ($inp),$inout0
2557         lea     16*1($inp),$inp                 # $inp+=1*16
2558         xorps   @tweak[0],$inout0
2559 ___
2560         &aesni_generate1("dec",$key,$rounds);
2561 $code.=<<___;
2562         xorps   @tweak[0],$inout0
2563         movdqa  @tweak[1],@tweak[0]
2564         movups  $inout0,($out)                  # store one output block
2565         movdqa  @tweak[2],@tweak[1]
2566         lea     16*1($out),$out                 # $out+=1*16
2567         jmp     .Lxts_dec_done
2568
2569 .align  16
2570 .Lxts_dec_two:
2571         movups  ($inp),$inout0
2572         movups  16($inp),$inout1
2573         lea     32($inp),$inp                   # $inp+=2*16
2574         xorps   @tweak[0],$inout0
2575         xorps   @tweak[1],$inout1
2576
2577         call    _aesni_decrypt2
2578
2579         xorps   @tweak[0],$inout0
2580         movdqa  @tweak[2],@tweak[0]
2581         xorps   @tweak[1],$inout1
2582         movdqa  @tweak[3],@tweak[1]
2583         movups  $inout0,($out)                  # store 2 output blocks
2584         movups  $inout1,16*1($out)
2585         lea     16*2($out),$out                 # $out+=2*16
2586         jmp     .Lxts_dec_done
2587
2588 .align  16
2589 .Lxts_dec_three:
2590         movups  ($inp),$inout0
2591         movups  16*1($inp),$inout1
2592         movups  16*2($inp),$inout2
2593         lea     16*3($inp),$inp                 # $inp+=3*16
2594         xorps   @tweak[0],$inout0
2595         xorps   @tweak[1],$inout1
2596         xorps   @tweak[2],$inout2
2597
2598         call    _aesni_decrypt3
2599
2600         xorps   @tweak[0],$inout0
2601         movdqa  @tweak[3],@tweak[0]
2602         xorps   @tweak[1],$inout1
2603         movdqa  @tweak[4],@tweak[1]
2604         xorps   @tweak[2],$inout2
2605         movups  $inout0,($out)                  # store 3 output blocks
2606         movups  $inout1,16*1($out)
2607         movups  $inout2,16*2($out)
2608         lea     16*3($out),$out                 # $out+=3*16
2609         jmp     .Lxts_dec_done
2610
2611 .align  16
2612 .Lxts_dec_four:
2613         movups  ($inp),$inout0
2614         movups  16*1($inp),$inout1
2615         movups  16*2($inp),$inout2
2616         xorps   @tweak[0],$inout0
2617         movups  16*3($inp),$inout3
2618         lea     16*4($inp),$inp                 # $inp+=4*16
2619         xorps   @tweak[1],$inout1
2620         xorps   @tweak[2],$inout2
2621         xorps   @tweak[3],$inout3
2622
2623         call    _aesni_decrypt4
2624
2625         pxor    @tweak[0],$inout0
2626         movdqa  @tweak[4],@tweak[0]
2627         pxor    @tweak[1],$inout1
2628         movdqa  @tweak[5],@tweak[1]
2629         pxor    @tweak[2],$inout2
2630         movdqu  $inout0,($out)                  # store 4 output blocks
2631         pxor    @tweak[3],$inout3
2632         movdqu  $inout1,16*1($out)
2633         movdqu  $inout2,16*2($out)
2634         movdqu  $inout3,16*3($out)
2635         lea     16*4($out),$out                 # $out+=4*16
2636         jmp     .Lxts_dec_done
2637
2638 .align  16
2639 .Lxts_dec_done:
2640         and     \$15,$len_                      # see if $len%16 is 0
2641         jz      .Lxts_dec_ret
2642 .Lxts_dec_done2:
2643         mov     $len_,$len
2644         mov     $key_,$key                      # restore $key
2645         mov     $rnds_,$rounds                  # restore $rounds
2646
2647         movups  ($inp),$inout0
2648         xorps   @tweak[1],$inout0
2649 ___
2650         &aesni_generate1("dec",$key,$rounds);
2651 $code.=<<___;
2652         xorps   @tweak[1],$inout0
2653         movups  $inout0,($out)
2654
2655 .Lxts_dec_steal:
2656         movzb   16($inp),%eax                   # borrow $rounds ...
2657         movzb   ($out),%ecx                     # ... and $key
2658         lea     1($inp),$inp
2659         mov     %al,($out)
2660         mov     %cl,16($out)
2661         lea     1($out),$out
2662         sub     \$1,$len
2663         jnz     .Lxts_dec_steal
2664
2665         sub     $len_,$out                      # rewind $out
2666         mov     $key_,$key                      # restore $key
2667         mov     $rnds_,$rounds                  # restore $rounds
2668
2669         movups  ($out),$inout0
2670         xorps   @tweak[0],$inout0
2671 ___
2672         &aesni_generate1("dec",$key,$rounds);
2673 $code.=<<___;
2674         xorps   @tweak[0],$inout0
2675         movups  $inout0,($out)
2676
2677 .Lxts_dec_ret:
2678         xorps   %xmm0,%xmm0                     # clear register bank
2679         pxor    %xmm1,%xmm1
2680         pxor    %xmm2,%xmm2
2681         pxor    %xmm3,%xmm3
2682         pxor    %xmm4,%xmm4
2683         pxor    %xmm5,%xmm5
2684 ___
2685 $code.=<<___ if (!$win64);
2686         pxor    %xmm6,%xmm6
2687         pxor    %xmm7,%xmm7
2688         movaps  %xmm0,0x00(%rsp)                # clear stack
2689         pxor    %xmm8,%xmm8
2690         movaps  %xmm0,0x10(%rsp)
2691         pxor    %xmm9,%xmm9
2692         movaps  %xmm0,0x20(%rsp)
2693         pxor    %xmm10,%xmm10
2694         movaps  %xmm0,0x30(%rsp)
2695         pxor    %xmm11,%xmm11
2696         movaps  %xmm0,0x40(%rsp)
2697         pxor    %xmm12,%xmm12
2698         movaps  %xmm0,0x50(%rsp)
2699         pxor    %xmm13,%xmm13
2700         movaps  %xmm0,0x60(%rsp)
2701         pxor    %xmm14,%xmm14
2702         pxor    %xmm15,%xmm15
2703 ___
2704 $code.=<<___ if ($win64);
2705         movaps  -0xa8(%r11),%xmm6
2706         movaps  %xmm0,-0xa8(%r11)               # clear stack
2707         movaps  -0x98(%r11),%xmm7
2708         movaps  %xmm0,-0x98(%r11)
2709         movaps  -0x88(%r11),%xmm8
2710         movaps  %xmm0,-0x88(%r11)
2711         movaps  -0x78(%r11),%xmm9
2712         movaps  %xmm0,-0x78(%r11)
2713         movaps  -0x68(%r11),%xmm10
2714         movaps  %xmm0,-0x68(%r11)
2715         movaps  -0x58(%r11),%xmm11
2716         movaps  %xmm0,-0x58(%r11)
2717         movaps  -0x48(%r11),%xmm12
2718         movaps  %xmm0,-0x48(%r11)
2719         movaps  -0x38(%r11),%xmm13
2720         movaps  %xmm0,-0x38(%r11)
2721         movaps  -0x28(%r11),%xmm14
2722         movaps  %xmm0,-0x28(%r11)
2723         movaps  -0x18(%r11),%xmm15
2724         movaps  %xmm0,-0x18(%r11)
2725         movaps  %xmm0,0x00(%rsp)
2726         movaps  %xmm0,0x10(%rsp)
2727         movaps  %xmm0,0x20(%rsp)
2728         movaps  %xmm0,0x30(%rsp)
2729         movaps  %xmm0,0x40(%rsp)
2730         movaps  %xmm0,0x50(%rsp)
2731         movaps  %xmm0,0x60(%rsp)
2732 ___
2733 $code.=<<___;
2734         mov     -8(%r11),%rbp
2735 .cfi_restore    %rbp
2736         lea     (%r11),%rsp
2737 .cfi_def_cfa_register   %rsp
2738 .Lxts_dec_epilogue:
2739         ret
2740 .cfi_endproc
2741 .size   aesni_xts_decrypt,.-aesni_xts_decrypt
2742 ___
2743 }
2744 \f
2745 ######################################################################
2746 # void aesni_ocb_[en|de]crypt(const char *inp, char *out, size_t blocks,
2747 #       const AES_KEY *key, unsigned int start_block_num,
2748 #       unsigned char offset_i[16], const unsigned char L_[][16],
2749 #       unsigned char checksum[16]);
2750 #
2751 {
2752 my @offset=map("%xmm$_",(10..15));
2753 my ($checksum,$rndkey0l)=("%xmm8","%xmm9");
2754 my ($block_num,$offset_p)=("%r8","%r9");                # 5th and 6th arguments
2755 my ($L_p,$checksum_p) = ("%rbx","%rbp");
2756 my ($i1,$i3,$i5) = ("%r12","%r13","%r14");
2757 my $seventh_arg = $win64 ? 56 : 8;
2758 my $blocks = $len;
2759
2760 $code.=<<___;
2761 .globl  aesni_ocb_encrypt
2762 .type   aesni_ocb_encrypt,\@function,6
2763 .align  32
2764 aesni_ocb_encrypt:
2765 .cfi_startproc
2766         lea     (%rsp),%rax
2767         push    %rbx
2768 .cfi_push       %rbx
2769         push    %rbp
2770 .cfi_push       %rbp
2771         push    %r12
2772 .cfi_push       %r12
2773         push    %r13
2774 .cfi_push       %r13
2775         push    %r14
2776 .cfi_push       %r14
2777 ___
2778 $code.=<<___ if ($win64);
2779         lea     -0xa0(%rsp),%rsp
2780         movaps  %xmm6,0x00(%rsp)                # offload everything
2781         movaps  %xmm7,0x10(%rsp)
2782         movaps  %xmm8,0x20(%rsp)
2783         movaps  %xmm9,0x30(%rsp)
2784         movaps  %xmm10,0x40(%rsp)
2785         movaps  %xmm11,0x50(%rsp)
2786         movaps  %xmm12,0x60(%rsp)
2787         movaps  %xmm13,0x70(%rsp)
2788         movaps  %xmm14,0x80(%rsp)
2789         movaps  %xmm15,0x90(%rsp)
2790 .Locb_enc_body:
2791 ___
2792 $code.=<<___;
2793         mov     $seventh_arg(%rax),$L_p         # 7th argument
2794         mov     $seventh_arg+8(%rax),$checksum_p# 8th argument
2795
2796         mov     240($key),$rnds_
2797         mov     $key,$key_
2798         shl     \$4,$rnds_
2799         $movkey ($key),$rndkey0l                # round[0]
2800         $movkey 16($key,$rnds_),$rndkey1        # round[last]
2801
2802         movdqu  ($offset_p),@offset[5]          # load last offset_i
2803         pxor    $rndkey1,$rndkey0l              # round[0] ^ round[last]
2804         pxor    $rndkey1,@offset[5]             # offset_i ^ round[last]
2805
2806         mov     \$16+32,$rounds
2807         lea     32($key_,$rnds_),$key
2808         $movkey 16($key_),$rndkey1              # round[1]
2809         sub     %r10,%rax                       # twisted $rounds
2810         mov     %rax,%r10                       # backup twisted $rounds
2811
2812         movdqu  ($L_p),@offset[0]               # L_0 for all odd-numbered blocks
2813         movdqu  ($checksum_p),$checksum         # load checksum
2814
2815         test    \$1,$block_num                  # is first block number odd?
2816         jnz     .Locb_enc_odd
2817
2818         bsf     $block_num,$i1
2819         add     \$1,$block_num
2820         shl     \$4,$i1
2821         movdqu  ($L_p,$i1),$inout5              # borrow
2822         movdqu  ($inp),$inout0
2823         lea     16($inp),$inp
2824
2825         call    __ocb_encrypt1
2826
2827         movdqa  $inout5,@offset[5]
2828         movups  $inout0,($out)
2829         lea     16($out),$out
2830         sub     \$1,$blocks
2831         jz      .Locb_enc_done
2832
2833 .Locb_enc_odd:
2834         lea     1($block_num),$i1               # even-numbered blocks
2835         lea     3($block_num),$i3
2836         lea     5($block_num),$i5
2837         lea     6($block_num),$block_num
2838         bsf     $i1,$i1                         # ntz(block)
2839         bsf     $i3,$i3
2840         bsf     $i5,$i5
2841         shl     \$4,$i1                         # ntz(block) -> table offset
2842         shl     \$4,$i3
2843         shl     \$4,$i5
2844
2845         sub     \$6,$blocks
2846         jc      .Locb_enc_short
2847         jmp     .Locb_enc_grandloop
2848
2849 .align  32
2850 .Locb_enc_grandloop:
2851         movdqu  `16*0`($inp),$inout0            # load input
2852         movdqu  `16*1`($inp),$inout1
2853         movdqu  `16*2`($inp),$inout2
2854         movdqu  `16*3`($inp),$inout3
2855         movdqu  `16*4`($inp),$inout4
2856         movdqu  `16*5`($inp),$inout5
2857         lea     `16*6`($inp),$inp
2858
2859         call    __ocb_encrypt6
2860
2861         movups  $inout0,`16*0`($out)            # store output
2862         movups  $inout1,`16*1`($out)
2863         movups  $inout2,`16*2`($out)
2864         movups  $inout3,`16*3`($out)
2865         movups  $inout4,`16*4`($out)
2866         movups  $inout5,`16*5`($out)
2867         lea     `16*6`($out),$out
2868         sub     \$6,$blocks
2869         jnc     .Locb_enc_grandloop
2870
2871 .Locb_enc_short:
2872         add     \$6,$blocks
2873         jz      .Locb_enc_done
2874
2875         movdqu  `16*0`($inp),$inout0
2876         cmp     \$2,$blocks
2877         jb      .Locb_enc_one
2878         movdqu  `16*1`($inp),$inout1
2879         je      .Locb_enc_two
2880
2881         movdqu  `16*2`($inp),$inout2
2882         cmp     \$4,$blocks
2883         jb      .Locb_enc_three
2884         movdqu  `16*3`($inp),$inout3
2885         je      .Locb_enc_four
2886
2887         movdqu  `16*4`($inp),$inout4
2888         pxor    $inout5,$inout5
2889
2890         call    __ocb_encrypt6
2891
2892         movdqa  @offset[4],@offset[5]
2893         movups  $inout0,`16*0`($out)
2894         movups  $inout1,`16*1`($out)
2895         movups  $inout2,`16*2`($out)
2896         movups  $inout3,`16*3`($out)
2897         movups  $inout4,`16*4`($out)
2898
2899         jmp     .Locb_enc_done
2900
2901 .align  16
2902 .Locb_enc_one:
2903         movdqa  @offset[0],$inout5              # borrow
2904
2905         call    __ocb_encrypt1
2906
2907         movdqa  $inout5,@offset[5]
2908         movups  $inout0,`16*0`($out)
2909         jmp     .Locb_enc_done
2910
2911 .align  16
2912 .Locb_enc_two:
2913         pxor    $inout2,$inout2
2914         pxor    $inout3,$inout3
2915
2916         call    __ocb_encrypt4
2917
2918         movdqa  @offset[1],@offset[5]
2919         movups  $inout0,`16*0`($out)
2920         movups  $inout1,`16*1`($out)
2921
2922         jmp     .Locb_enc_done
2923
2924 .align  16
2925 .Locb_enc_three:
2926         pxor    $inout3,$inout3
2927
2928         call    __ocb_encrypt4
2929
2930         movdqa  @offset[2],@offset[5]
2931         movups  $inout0,`16*0`($out)
2932         movups  $inout1,`16*1`($out)
2933         movups  $inout2,`16*2`($out)
2934
2935         jmp     .Locb_enc_done
2936
2937 .align  16
2938 .Locb_enc_four:
2939         call    __ocb_encrypt4
2940
2941         movdqa  @offset[3],@offset[5]
2942         movups  $inout0,`16*0`($out)
2943         movups  $inout1,`16*1`($out)
2944         movups  $inout2,`16*2`($out)
2945         movups  $inout3,`16*3`($out)
2946
2947 .Locb_enc_done:
2948         pxor    $rndkey0,@offset[5]             # "remove" round[last]
2949         movdqu  $checksum,($checksum_p)         # store checksum
2950         movdqu  @offset[5],($offset_p)          # store last offset_i
2951
2952         xorps   %xmm0,%xmm0                     # clear register bank
2953         pxor    %xmm1,%xmm1
2954         pxor    %xmm2,%xmm2
2955         pxor    %xmm3,%xmm3
2956         pxor    %xmm4,%xmm4
2957         pxor    %xmm5,%xmm5
2958 ___
2959 $code.=<<___ if (!$win64);
2960         pxor    %xmm6,%xmm6
2961         pxor    %xmm7,%xmm7
2962         pxor    %xmm8,%xmm8
2963         pxor    %xmm9,%xmm9
2964         pxor    %xmm10,%xmm10
2965         pxor    %xmm11,%xmm11
2966         pxor    %xmm12,%xmm12
2967         pxor    %xmm13,%xmm13
2968         pxor    %xmm14,%xmm14
2969         pxor    %xmm15,%xmm15
2970         lea     0x28(%rsp),%rax
2971 .cfi_def_cfa    %rax,8
2972 ___
2973 $code.=<<___ if ($win64);
2974         movaps  0x00(%rsp),%xmm6
2975         movaps  %xmm0,0x00(%rsp)                # clear stack
2976         movaps  0x10(%rsp),%xmm7
2977         movaps  %xmm0,0x10(%rsp)
2978         movaps  0x20(%rsp),%xmm8
2979         movaps  %xmm0,0x20(%rsp)
2980         movaps  0x30(%rsp),%xmm9
2981         movaps  %xmm0,0x30(%rsp)
2982         movaps  0x40(%rsp),%xmm10
2983         movaps  %xmm0,0x40(%rsp)
2984         movaps  0x50(%rsp),%xmm11
2985         movaps  %xmm0,0x50(%rsp)
2986         movaps  0x60(%rsp),%xmm12
2987         movaps  %xmm0,0x60(%rsp)
2988         movaps  0x70(%rsp),%xmm13
2989         movaps  %xmm0,0x70(%rsp)
2990         movaps  0x80(%rsp),%xmm14
2991         movaps  %xmm0,0x80(%rsp)
2992         movaps  0x90(%rsp),%xmm15
2993         movaps  %xmm0,0x90(%rsp)
2994         lea     0xa0+0x28(%rsp),%rax
2995 .Locb_enc_pop:
2996 ___
2997 $code.=<<___;
2998         mov     -40(%rax),%r14
2999 .cfi_restore    %r14
3000         mov     -32(%rax),%r13
3001 .cfi_restore    %r13
3002         mov     -24(%rax),%r12
3003 .cfi_restore    %r12
3004         mov     -16(%rax),%rbp
3005 .cfi_restore    %rbp
3006         mov     -8(%rax),%rbx
3007 .cfi_restore    %rbx
3008         lea     (%rax),%rsp
3009 .cfi_def_cfa_register   %rsp
3010 .Locb_enc_epilogue:
3011         ret
3012 .cfi_endproc
3013 .size   aesni_ocb_encrypt,.-aesni_ocb_encrypt
3014
3015 .type   __ocb_encrypt6,\@abi-omnipotent
3016 .align  32
3017 __ocb_encrypt6:
3018          pxor           $rndkey0l,@offset[5]    # offset_i ^ round[0]
3019          movdqu         ($L_p,$i1),@offset[1]
3020          movdqa         @offset[0],@offset[2]
3021          movdqu         ($L_p,$i3),@offset[3]
3022          movdqa         @offset[0],@offset[4]
3023          pxor           @offset[5],@offset[0]
3024          movdqu         ($L_p,$i5),@offset[5]
3025          pxor           @offset[0],@offset[1]
3026         pxor            $inout0,$checksum       # accumulate checksum
3027         pxor            @offset[0],$inout0      # input ^ round[0] ^ offset_i
3028          pxor           @offset[1],@offset[2]
3029         pxor            $inout1,$checksum
3030         pxor            @offset[1],$inout1
3031          pxor           @offset[2],@offset[3]
3032         pxor            $inout2,$checksum
3033         pxor            @offset[2],$inout2
3034          pxor           @offset[3],@offset[4]
3035         pxor            $inout3,$checksum
3036         pxor            @offset[3],$inout3
3037          pxor           @offset[4],@offset[5]
3038         pxor            $inout4,$checksum
3039         pxor            @offset[4],$inout4
3040         pxor            $inout5,$checksum
3041         pxor            @offset[5],$inout5
3042         $movkey         32($key_),$rndkey0
3043
3044         lea             1($block_num),$i1       # even-numbered blocks
3045         lea             3($block_num),$i3
3046         lea             5($block_num),$i5
3047         add             \$6,$block_num
3048          pxor           $rndkey0l,@offset[0]    # offset_i ^ round[last]
3049         bsf             $i1,$i1                 # ntz(block)
3050         bsf             $i3,$i3
3051         bsf             $i5,$i5
3052
3053         aesenc          $rndkey1,$inout0
3054         aesenc          $rndkey1,$inout1
3055         aesenc          $rndkey1,$inout2
3056         aesenc          $rndkey1,$inout3
3057          pxor           $rndkey0l,@offset[1]
3058          pxor           $rndkey0l,@offset[2]
3059         aesenc          $rndkey1,$inout4
3060          pxor           $rndkey0l,@offset[3]
3061          pxor           $rndkey0l,@offset[4]
3062         aesenc          $rndkey1,$inout5
3063         $movkey         48($key_),$rndkey1
3064          pxor           $rndkey0l,@offset[5]
3065
3066         aesenc          $rndkey0,$inout0
3067         aesenc          $rndkey0,$inout1
3068         aesenc          $rndkey0,$inout2
3069         aesenc          $rndkey0,$inout3
3070         aesenc          $rndkey0,$inout4
3071         aesenc          $rndkey0,$inout5
3072         $movkey         64($key_),$rndkey0
3073         shl             \$4,$i1                 # ntz(block) -> table offset
3074         shl             \$4,$i3
3075         jmp             .Locb_enc_loop6
3076
3077 .align  32
3078 .Locb_enc_loop6:
3079         aesenc          $rndkey1,$inout0
3080         aesenc          $rndkey1,$inout1
3081         aesenc          $rndkey1,$inout2
3082         aesenc          $rndkey1,$inout3
3083         aesenc          $rndkey1,$inout4
3084         aesenc          $rndkey1,$inout5
3085         $movkey         ($key,%rax),$rndkey1
3086         add             \$32,%rax
3087
3088         aesenc          $rndkey0,$inout0
3089         aesenc          $rndkey0,$inout1
3090         aesenc          $rndkey0,$inout2
3091         aesenc          $rndkey0,$inout3
3092         aesenc          $rndkey0,$inout4
3093         aesenc          $rndkey0,$inout5
3094         $movkey         -16($key,%rax),$rndkey0
3095         jnz             .Locb_enc_loop6
3096
3097         aesenc          $rndkey1,$inout0
3098         aesenc          $rndkey1,$inout1
3099         aesenc          $rndkey1,$inout2
3100         aesenc          $rndkey1,$inout3
3101         aesenc          $rndkey1,$inout4
3102         aesenc          $rndkey1,$inout5
3103         $movkey         16($key_),$rndkey1
3104         shl             \$4,$i5
3105
3106         aesenclast      @offset[0],$inout0
3107         movdqu          ($L_p),@offset[0]       # L_0 for all odd-numbered blocks
3108         mov             %r10,%rax               # restore twisted rounds
3109         aesenclast      @offset[1],$inout1
3110         aesenclast      @offset[2],$inout2
3111         aesenclast      @offset[3],$inout3
3112         aesenclast      @offset[4],$inout4
3113         aesenclast      @offset[5],$inout5
3114         ret
3115 .size   __ocb_encrypt6,.-__ocb_encrypt6
3116
3117 .type   __ocb_encrypt4,\@abi-omnipotent
3118 .align  32
3119 __ocb_encrypt4:
3120          pxor           $rndkey0l,@offset[5]    # offset_i ^ round[0]
3121          movdqu         ($L_p,$i1),@offset[1]
3122          movdqa         @offset[0],@offset[2]
3123          movdqu         ($L_p,$i3),@offset[3]
3124          pxor           @offset[5],@offset[0]
3125          pxor           @offset[0],@offset[1]
3126         pxor            $inout0,$checksum       # accumulate checksum
3127         pxor            @offset[0],$inout0      # input ^ round[0] ^ offset_i
3128          pxor           @offset[1],@offset[2]
3129         pxor            $inout1,$checksum
3130         pxor            @offset[1],$inout1
3131          pxor           @offset[2],@offset[3]
3132         pxor            $inout2,$checksum
3133         pxor            @offset[2],$inout2
3134         pxor            $inout3,$checksum
3135         pxor            @offset[3],$inout3
3136         $movkey         32($key_),$rndkey0
3137
3138          pxor           $rndkey0l,@offset[0]    # offset_i ^ round[last]
3139          pxor           $rndkey0l,@offset[1]
3140          pxor           $rndkey0l,@offset[2]
3141          pxor           $rndkey0l,@offset[3]
3142
3143         aesenc          $rndkey1,$inout0
3144         aesenc          $rndkey1,$inout1
3145         aesenc          $rndkey1,$inout2
3146         aesenc          $rndkey1,$inout3
3147         $movkey         48($key_),$rndkey1
3148
3149         aesenc          $rndkey0,$inout0
3150         aesenc          $rndkey0,$inout1
3151         aesenc          $rndkey0,$inout2
3152         aesenc          $rndkey0,$inout3
3153         $movkey         64($key_),$rndkey0
3154         jmp             .Locb_enc_loop4
3155
3156 .align  32
3157 .Locb_enc_loop4:
3158         aesenc          $rndkey1,$inout0
3159         aesenc          $rndkey1,$inout1
3160         aesenc          $rndkey1,$inout2
3161         aesenc          $rndkey1,$inout3
3162         $movkey         ($key,%rax),$rndkey1
3163         add             \$32,%rax
3164
3165         aesenc          $rndkey0,$inout0
3166         aesenc          $rndkey0,$inout1
3167         aesenc          $rndkey0,$inout2
3168         aesenc          $rndkey0,$inout3
3169         $movkey         -16($key,%rax),$rndkey0
3170         jnz             .Locb_enc_loop4
3171
3172         aesenc          $rndkey1,$inout0
3173         aesenc          $rndkey1,$inout1
3174         aesenc          $rndkey1,$inout2
3175         aesenc          $rndkey1,$inout3
3176         $movkey         16($key_),$rndkey1
3177         mov             %r10,%rax               # restore twisted rounds
3178
3179         aesenclast      @offset[0],$inout0
3180         aesenclast      @offset[1],$inout1
3181         aesenclast      @offset[2],$inout2
3182         aesenclast      @offset[3],$inout3
3183         ret
3184 .size   __ocb_encrypt4,.-__ocb_encrypt4
3185
3186 .type   __ocb_encrypt1,\@abi-omnipotent
3187 .align  32
3188 __ocb_encrypt1:
3189          pxor           @offset[5],$inout5      # offset_i
3190          pxor           $rndkey0l,$inout5       # offset_i ^ round[0]
3191         pxor            $inout0,$checksum       # accumulate checksum
3192         pxor            $inout5,$inout0         # input ^ round[0] ^ offset_i
3193         $movkey         32($key_),$rndkey0
3194
3195         aesenc          $rndkey1,$inout0
3196         $movkey         48($key_),$rndkey1
3197         pxor            $rndkey0l,$inout5       # offset_i ^ round[last]
3198
3199         aesenc          $rndkey0,$inout0
3200         $movkey         64($key_),$rndkey0
3201         jmp             .Locb_enc_loop1
3202
3203 .align  32
3204 .Locb_enc_loop1:
3205         aesenc          $rndkey1,$inout0
3206         $movkey         ($key,%rax),$rndkey1
3207         add             \$32,%rax
3208
3209         aesenc          $rndkey0,$inout0
3210         $movkey         -16($key,%rax),$rndkey0
3211         jnz             .Locb_enc_loop1
3212
3213         aesenc          $rndkey1,$inout0
3214         $movkey         16($key_),$rndkey1      # redundant in tail
3215         mov             %r10,%rax               # restore twisted rounds
3216
3217         aesenclast      $inout5,$inout0
3218         ret
3219 .size   __ocb_encrypt1,.-__ocb_encrypt1
3220
3221 .globl  aesni_ocb_decrypt
3222 .type   aesni_ocb_decrypt,\@function,6
3223 .align  32
3224 aesni_ocb_decrypt:
3225 .cfi_startproc
3226         lea     (%rsp),%rax
3227         push    %rbx
3228 .cfi_push       %rbx
3229         push    %rbp
3230 .cfi_push       %rbp
3231         push    %r12
3232 .cfi_push       %r12
3233         push    %r13
3234 .cfi_push       %r13
3235         push    %r14
3236 .cfi_push       %r14
3237 ___
3238 $code.=<<___ if ($win64);
3239         lea     -0xa0(%rsp),%rsp
3240         movaps  %xmm6,0x00(%rsp)                # offload everything
3241         movaps  %xmm7,0x10(%rsp)
3242         movaps  %xmm8,0x20(%rsp)
3243         movaps  %xmm9,0x30(%rsp)
3244         movaps  %xmm10,0x40(%rsp)
3245         movaps  %xmm11,0x50(%rsp)
3246         movaps  %xmm12,0x60(%rsp)
3247         movaps  %xmm13,0x70(%rsp)
3248         movaps  %xmm14,0x80(%rsp)
3249         movaps  %xmm15,0x90(%rsp)
3250 .Locb_dec_body:
3251 ___
3252 $code.=<<___;
3253         mov     $seventh_arg(%rax),$L_p         # 7th argument
3254         mov     $seventh_arg+8(%rax),$checksum_p# 8th argument
3255
3256         mov     240($key),$rnds_
3257         mov     $key,$key_
3258         shl     \$4,$rnds_
3259         $movkey ($key),$rndkey0l                # round[0]
3260         $movkey 16($key,$rnds_),$rndkey1        # round[last]
3261
3262         movdqu  ($offset_p),@offset[5]          # load last offset_i
3263         pxor    $rndkey1,$rndkey0l              # round[0] ^ round[last]
3264         pxor    $rndkey1,@offset[5]             # offset_i ^ round[last]
3265
3266         mov     \$16+32,$rounds
3267         lea     32($key_,$rnds_),$key
3268         $movkey 16($key_),$rndkey1              # round[1]
3269         sub     %r10,%rax                       # twisted $rounds
3270         mov     %rax,%r10                       # backup twisted $rounds
3271
3272         movdqu  ($L_p),@offset[0]               # L_0 for all odd-numbered blocks
3273         movdqu  ($checksum_p),$checksum         # load checksum
3274
3275         test    \$1,$block_num                  # is first block number odd?
3276         jnz     .Locb_dec_odd
3277
3278         bsf     $block_num,$i1
3279         add     \$1,$block_num
3280         shl     \$4,$i1
3281         movdqu  ($L_p,$i1),$inout5              # borrow
3282         movdqu  ($inp),$inout0
3283         lea     16($inp),$inp
3284
3285         call    __ocb_decrypt1
3286
3287         movdqa  $inout5,@offset[5]
3288         movups  $inout0,($out)
3289         xorps   $inout0,$checksum               # accumulate checksum
3290         lea     16($out),$out
3291         sub     \$1,$blocks
3292         jz      .Locb_dec_done
3293
3294 .Locb_dec_odd:
3295         lea     1($block_num),$i1               # even-numbered blocks
3296         lea     3($block_num),$i3
3297         lea     5($block_num),$i5
3298         lea     6($block_num),$block_num
3299         bsf     $i1,$i1                         # ntz(block)
3300         bsf     $i3,$i3
3301         bsf     $i5,$i5
3302         shl     \$4,$i1                         # ntz(block) -> table offset
3303         shl     \$4,$i3
3304         shl     \$4,$i5
3305
3306         sub     \$6,$blocks
3307         jc      .Locb_dec_short
3308         jmp     .Locb_dec_grandloop
3309
3310 .align  32
3311 .Locb_dec_grandloop:
3312         movdqu  `16*0`($inp),$inout0            # load input
3313         movdqu  `16*1`($inp),$inout1
3314         movdqu  `16*2`($inp),$inout2
3315         movdqu  `16*3`($inp),$inout3
3316         movdqu  `16*4`($inp),$inout4
3317         movdqu  `16*5`($inp),$inout5
3318         lea     `16*6`($inp),$inp
3319
3320         call    __ocb_decrypt6
3321
3322         movups  $inout0,`16*0`($out)            # store output
3323         pxor    $inout0,$checksum               # accumulate checksum
3324         movups  $inout1,`16*1`($out)
3325         pxor    $inout1,$checksum
3326         movups  $inout2,`16*2`($out)
3327         pxor    $inout2,$checksum
3328         movups  $inout3,`16*3`($out)
3329         pxor    $inout3,$checksum
3330         movups  $inout4,`16*4`($out)
3331         pxor    $inout4,$checksum
3332         movups  $inout5,`16*5`($out)
3333         pxor    $inout5,$checksum
3334         lea     `16*6`($out),$out
3335         sub     \$6,$blocks
3336         jnc     .Locb_dec_grandloop
3337
3338 .Locb_dec_short:
3339         add     \$6,$blocks
3340         jz      .Locb_dec_done
3341