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