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