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