2 # Copyright 2009-2019 The OpenSSL Project Authors. All Rights Reserved.
4 # Licensed under the OpenSSL license (the "License"). You may not use
5 # this file except in compliance with the License. You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
10 # ====================================================================
11 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
12 # project. The module is, however, dual licensed under OpenSSL and
13 # CRYPTOGAMS licenses depending on where you obtain it. For further
14 # details see http://www.openssl.org/~appro/cryptogams/.
15 # ====================================================================
17 # This module implements support for Intel AES-NI extension. In
18 # OpenSSL context it's used with Intel engine, but can also be used as
19 # drop-in replacement for crypto/aes/asm/aes-x86_64.pl [see below for
24 # Given aes(enc|dec) instructions' latency asymptotic performance for
25 # non-parallelizable modes such as CBC encrypt is 3.75 cycles per byte
26 # processed with 128-bit key. And given their throughput asymptotic
27 # performance for parallelizable modes is 1.25 cycles per byte. Being
28 # asymptotic limit it's not something you commonly achieve in reality,
29 # but how close does one get? Below are results collected for
30 # different modes and block sized. Pairs of numbers are for en-/
33 # 16-byte 64-byte 256-byte 1-KB 8-KB
34 # ECB 4.25/4.25 1.38/1.38 1.28/1.28 1.26/1.26 1.26/1.26
35 # CTR 5.42/5.42 1.92/1.92 1.44/1.44 1.28/1.28 1.26/1.26
36 # CBC 4.38/4.43 4.15/1.43 4.07/1.32 4.07/1.29 4.06/1.28
37 # CCM 5.66/9.42 4.42/5.41 4.16/4.40 4.09/4.15 4.06/4.07
38 # OFB 5.42/5.42 4.64/4.64 4.44/4.44 4.39/4.39 4.38/4.38
39 # CFB 5.73/5.85 5.56/5.62 5.48/5.56 5.47/5.55 5.47/5.55
41 # ECB, CTR, CBC and CCM results are free from EVP overhead. This means
42 # that otherwise used 'openssl speed -evp aes-128-??? -engine aesni
43 # [-decrypt]' will exhibit 10-15% worse results for smaller blocks.
44 # The results were collected with specially crafted speed.c benchmark
45 # in order to compare them with results reported in "Intel Advanced
46 # Encryption Standard (AES) New Instruction Set" White Paper Revision
47 # 3.0 dated May 2010. All above results are consistently better. This
48 # module also provides better performance for block sizes smaller than
49 # 128 bytes in points *not* represented in the above table.
51 # Looking at the results for 8-KB buffer.
53 # CFB and OFB results are far from the limit, because implementation
54 # uses "generic" CRYPTO_[c|o]fb128_encrypt interfaces relying on
55 # single-block aesni_encrypt, which is not the most optimal way to go.
56 # CBC encrypt result is unexpectedly high and there is no documented
57 # explanation for it. Seemingly there is a small penalty for feeding
58 # the result back to AES unit the way it's done in CBC mode. There is
59 # nothing one can do and the result appears optimal. CCM result is
60 # identical to CBC, because CBC-MAC is essentially CBC encrypt without
61 # saving output. CCM CTR "stays invisible," because it's neatly
62 # interleaved with CBC-MAC. This provides ~30% improvement over
63 # "straightforward" CCM implementation with CTR and CBC-MAC performed
64 # disjointly. Parallelizable modes practically achieve the theoretical
67 # Looking at how results vary with buffer size.
69 # Curves are practically saturated at 1-KB buffer size. In most cases
70 # "256-byte" performance is >95%, and "64-byte" is ~90% of "8-KB" one.
71 # CTR curve doesn't follow this pattern and is "slowest" changing one
72 # with "256-byte" result being 87% of "8-KB." This is because overhead
73 # in CTR mode is most computationally intensive. Small-block CCM
74 # decrypt is slower than encrypt, because first CTR and last CBC-MAC
75 # iterations can't be interleaved.
77 # Results for 192- and 256-bit keys.
79 # EVP-free results were observed to scale perfectly with number of
80 # rounds for larger block sizes, i.e. 192-bit result being 10/12 times
81 # lower and 256-bit one - 10/14. Well, in CBC encrypt case differences
82 # are a tad smaller, because the above mentioned penalty biases all
83 # results by same constant value. In similar way function call
84 # overhead affects small-block performance, as well as OFB and CFB
85 # results. Differences are not large, most common coefficients are
86 # 10/11.7 and 10/13.4 (as opposite to 10/12.0 and 10/14.0), but one
87 # observe even 10/11.2 and 10/12.4 (CTR, OFB, CFB)...
91 # While Westmere processor features 6 cycles latency for aes[enc|dec]
92 # instructions, which can be scheduled every second cycle, Sandy
93 # Bridge spends 8 cycles per instruction, but it can schedule them
94 # every cycle. This means that code targeting Westmere would perform
95 # suboptimally on Sandy Bridge. Therefore this update.
97 # In addition, non-parallelizable CBC encrypt (as well as CCM) is
98 # optimized. Relative improvement might appear modest, 8% on Westmere,
99 # but in absolute terms it's 3.77 cycles per byte encrypted with
100 # 128-bit key on Westmere, and 5.07 - on Sandy Bridge. These numbers
101 # should be compared to asymptotic limits of 3.75 for Westmere and
102 # 5.00 for Sandy Bridge. Actually, the fact that they get this close
103 # to asymptotic limits is quite amazing. Indeed, the limit is
104 # calculated as latency times number of rounds, 10 for 128-bit key,
105 # and divided by 16, the number of bytes in block, or in other words
106 # it accounts *solely* for aesenc instructions. But there are extra
107 # instructions, and numbers so close to the asymptotic limits mean
108 # that it's as if it takes as little as *one* additional cycle to
109 # execute all of them. How is it possible? It is possible thanks to
110 # out-of-order execution logic, which manages to overlap post-
111 # processing of previous block, things like saving the output, with
112 # actual encryption of current block, as well as pre-processing of
113 # current block, things like fetching input and xor-ing it with
114 # 0-round element of the key schedule, with actual encryption of
115 # previous block. Keep this in mind...
117 # For parallelizable modes, such as ECB, CBC decrypt, CTR, higher
118 # performance is achieved by interleaving instructions working on
119 # independent blocks. In which case asymptotic limit for such modes
120 # can be obtained by dividing above mentioned numbers by AES
121 # instructions' interleave factor. Westmere can execute at most 3
122 # instructions at a time, meaning that optimal interleave factor is 3,
123 # and that's where the "magic" number of 1.25 come from. "Optimal
124 # interleave factor" means that increase of interleave factor does
125 # not improve performance. The formula has proven to reflect reality
126 # pretty well on Westmere... Sandy Bridge on the other hand can
127 # execute up to 8 AES instructions at a time, so how does varying
128 # interleave factor affect the performance? Here is table for ECB
129 # (numbers are cycles per byte processed with 128-bit key):
131 # instruction interleave factor 3x 6x 8x
132 # theoretical asymptotic limit 1.67 0.83 0.625
133 # measured performance for 8KB block 1.05 0.86 0.84
135 # "as if" interleave factor 4.7x 5.8x 6.0x
137 # Further data for other parallelizable modes:
139 # CBC decrypt 1.16 0.93 0.74
142 # Well, given 3x column it's probably inappropriate to call the limit
143 # asymptotic, if it can be surpassed, isn't it? What happens there?
144 # Rewind to CBC paragraph for the answer. Yes, out-of-order execution
145 # magic is responsible for this. Processor overlaps not only the
146 # additional instructions with AES ones, but even AES instructions
147 # processing adjacent triplets of independent blocks. In the 6x case
148 # additional instructions still claim disproportionally small amount
149 # of additional cycles, but in 8x case number of instructions must be
150 # a tad too high for out-of-order logic to cope with, and AES unit
151 # remains underutilized... As you can see 8x interleave is hardly
152 # justifiable, so there no need to feel bad that 32-bit aesni-x86.pl
153 # utilizes 6x interleave because of limited register bank capacity.
155 # Higher interleave factors do have negative impact on Westmere
156 # performance. While for ECB mode it's negligible ~1.5%, other
157 # parallelizables perform ~5% worse, which is outweighed by ~25%
158 # improvement on Sandy Bridge. To balance regression on Westmere
159 # CTR mode was implemented with 6x aesenc interleave factor.
163 # Add aesni_xts_[en|de]crypt. Westmere spends 1.25 cycles processing
164 # one byte out of 8KB with 128-bit key, Sandy Bridge - 0.90. Just like
165 # in CTR mode AES instruction interleave factor was chosen to be 6x.
169 # Add aesni_ocb_[en|de]crypt. AES instruction interleave factor was
172 ######################################################################
173 # Current large-block performance in cycles per byte processed with
174 # 128-bit key (less is better).
176 # CBC en-/decrypt CTR XTS ECB OCB
177 # Westmere 3.77/1.25 1.25 1.25 1.26
178 # * Bridge 5.07/0.74 0.75 0.90 0.85 0.98
179 # Haswell 4.44/0.63 0.63 0.73 0.63 0.70
180 # Skylake 2.62/0.63 0.63 0.63 0.63
181 # Silvermont 5.75/3.54 3.56 4.12 3.87(*) 4.11
182 # Knights L 2.54/0.77 0.78 0.85 - 1.50
183 # Goldmont 3.82/1.26 1.26 1.29 1.29 1.50
184 # Bulldozer 5.77/0.70 0.72 0.90 0.70 0.95
185 # Ryzen 2.71/0.35 0.35 0.44 0.38 0.49
187 # (*) Atom Silvermont ECB result is suboptimal because of penalties
188 # incurred by operations on %xmm8-15. As ECB is not considered
189 # critical, nothing was done to mitigate the problem.
191 $PREFIX="aesni"; # if $PREFIX is set to "AES", the script
192 # generates drop-in replacement for
193 # crypto/aes/asm/aes-x86_64.pl:-)
197 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
199 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
201 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
202 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
203 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
204 die "can't locate x86_64-xlate.pl";
206 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
209 $movkey = $PREFIX eq "aesni" ? "movups" : "movups";
210 @_4args=$win64? ("%rcx","%rdx","%r8", "%r9") : # Win64 order
211 ("%rdi","%rsi","%rdx","%rcx"); # Unix order
214 $code.=".extern OPENSSL_ia32cap_P\n";
216 $rounds="%eax"; # input to and changed by aesni_[en|de]cryptN !!!
217 # this is natural Unix argument order for public $PREFIX_[ecb|cbc]_encrypt ...
221 $key="%rcx"; # input to and changed by aesni_[en|de]cryptN !!!
222 $ivp="%r8"; # cbc, ctr, ...
224 $rnds_="%r10d"; # backup copy for $rounds
225 $key_="%r11"; # backup copy for $key
227 # %xmm register layout
228 $rndkey0="%xmm0"; $rndkey1="%xmm1";
229 $inout0="%xmm2"; $inout1="%xmm3";
230 $inout2="%xmm4"; $inout3="%xmm5";
231 $inout4="%xmm6"; $inout5="%xmm7";
232 $inout6="%xmm8"; $inout7="%xmm9";
234 $in2="%xmm6"; $in1="%xmm7"; # used in CBC decrypt, CTR, ...
235 $in0="%xmm8"; $iv="%xmm9";
237 # Inline version of internal aesni_[en|de]crypt1.
239 # Why folded loop? Because aes[enc|dec] is slow enough to accommodate
240 # cycles which take care of loop variables...
242 sub aesni_generate1 {
243 my ($p,$key,$rounds,$inout,$ivec)=@_; $inout=$inout0 if (!defined($inout));
246 $movkey ($key),$rndkey0
247 $movkey 16($key),$rndkey1
249 $code.=<<___ if (defined($ivec));
254 $code.=<<___ if (!defined($ivec));
256 xorps $rndkey0,$inout
260 aes${p} $rndkey1,$inout
262 $movkey ($key),$rndkey1
264 jnz .Loop_${p}1_$sn # loop body is 16 bytes
265 aes${p}last $rndkey1,$inout
268 # void $PREFIX_[en|de]crypt (const void *inp,void *out,const AES_KEY *key);
270 { my ($inp,$out,$key) = @_4args;
273 .globl ${PREFIX}_encrypt
274 .type ${PREFIX}_encrypt,\@abi-omnipotent
278 movups ($inp),$inout0 # load input
279 mov 240($key),$rounds # key->rounds
281 &aesni_generate1("enc",$key,$rounds);
283 pxor $rndkey0,$rndkey0 # clear register bank
284 pxor $rndkey1,$rndkey1
285 movups $inout0,($out) # output
289 .size ${PREFIX}_encrypt,.-${PREFIX}_encrypt
291 .globl ${PREFIX}_decrypt
292 .type ${PREFIX}_decrypt,\@abi-omnipotent
296 movups ($inp),$inout0 # load input
297 mov 240($key),$rounds # key->rounds
299 &aesni_generate1("dec",$key,$rounds);
301 pxor $rndkey0,$rndkey0 # clear register bank
302 pxor $rndkey1,$rndkey1
303 movups $inout0,($out) # output
307 .size ${PREFIX}_decrypt, .-${PREFIX}_decrypt
311 # _aesni_[en|de]cryptN are private interfaces, N denotes interleave
312 # factor. Why 3x subroutine were originally used in loops? Even though
313 # aes[enc|dec] latency was originally 6, it could be scheduled only
314 # every *2nd* cycle. Thus 3x interleave was the one providing optimal
315 # utilization, i.e. when subroutine's throughput is virtually same as
316 # of non-interleaved subroutine [for number of input blocks up to 3].
317 # This is why it originally made no sense to implement 2x subroutine.
318 # But times change and it became appropriate to spend extra 192 bytes
319 # on 2x subroutine on Atom Silvermont account. For processors that
320 # can schedule aes[enc|dec] every cycle optimal interleave factor
321 # equals to corresponding instructions latency. 8x is optimal for
322 # * Bridge and "super-optimal" for other Intel CPUs...
324 sub aesni_generate2 {
326 # As already mentioned it takes in $key and $rounds, which are *not*
327 # preserved. $inout[0-1] is cipher/clear text...
329 .type _aesni_${dir}rypt2,\@abi-omnipotent
333 $movkey ($key),$rndkey0
335 $movkey 16($key),$rndkey1
336 xorps $rndkey0,$inout0
337 xorps $rndkey0,$inout1
338 $movkey 32($key),$rndkey0
339 lea 32($key,$rounds),$key
344 aes${dir} $rndkey1,$inout0
345 aes${dir} $rndkey1,$inout1
346 $movkey ($key,%rax),$rndkey1
348 aes${dir} $rndkey0,$inout0
349 aes${dir} $rndkey0,$inout1
350 $movkey -16($key,%rax),$rndkey0
353 aes${dir} $rndkey1,$inout0
354 aes${dir} $rndkey1,$inout1
355 aes${dir}last $rndkey0,$inout0
356 aes${dir}last $rndkey0,$inout1
359 .size _aesni_${dir}rypt2,.-_aesni_${dir}rypt2
362 sub aesni_generate3 {
364 # As already mentioned it takes in $key and $rounds, which are *not*
365 # preserved. $inout[0-2] is cipher/clear text...
367 .type _aesni_${dir}rypt3,\@abi-omnipotent
371 $movkey ($key),$rndkey0
373 $movkey 16($key),$rndkey1
374 xorps $rndkey0,$inout0
375 xorps $rndkey0,$inout1
376 xorps $rndkey0,$inout2
377 $movkey 32($key),$rndkey0
378 lea 32($key,$rounds),$key
383 aes${dir} $rndkey1,$inout0
384 aes${dir} $rndkey1,$inout1
385 aes${dir} $rndkey1,$inout2
386 $movkey ($key,%rax),$rndkey1
388 aes${dir} $rndkey0,$inout0
389 aes${dir} $rndkey0,$inout1
390 aes${dir} $rndkey0,$inout2
391 $movkey -16($key,%rax),$rndkey0
394 aes${dir} $rndkey1,$inout0
395 aes${dir} $rndkey1,$inout1
396 aes${dir} $rndkey1,$inout2
397 aes${dir}last $rndkey0,$inout0
398 aes${dir}last $rndkey0,$inout1
399 aes${dir}last $rndkey0,$inout2
402 .size _aesni_${dir}rypt3,.-_aesni_${dir}rypt3
405 # 4x interleave is implemented to improve small block performance,
406 # most notably [and naturally] 4 block by ~30%. One can argue that one
407 # should have implemented 5x as well, but improvement would be <20%,
408 # so it's not worth it...
409 sub aesni_generate4 {
411 # As already mentioned it takes in $key and $rounds, which are *not*
412 # preserved. $inout[0-3] is cipher/clear text...
414 .type _aesni_${dir}rypt4,\@abi-omnipotent
418 $movkey ($key),$rndkey0
420 $movkey 16($key),$rndkey1
421 xorps $rndkey0,$inout0
422 xorps $rndkey0,$inout1
423 xorps $rndkey0,$inout2
424 xorps $rndkey0,$inout3
425 $movkey 32($key),$rndkey0
426 lea 32($key,$rounds),$key
432 aes${dir} $rndkey1,$inout0
433 aes${dir} $rndkey1,$inout1
434 aes${dir} $rndkey1,$inout2
435 aes${dir} $rndkey1,$inout3
436 $movkey ($key,%rax),$rndkey1
438 aes${dir} $rndkey0,$inout0
439 aes${dir} $rndkey0,$inout1
440 aes${dir} $rndkey0,$inout2
441 aes${dir} $rndkey0,$inout3
442 $movkey -16($key,%rax),$rndkey0
445 aes${dir} $rndkey1,$inout0
446 aes${dir} $rndkey1,$inout1
447 aes${dir} $rndkey1,$inout2
448 aes${dir} $rndkey1,$inout3
449 aes${dir}last $rndkey0,$inout0
450 aes${dir}last $rndkey0,$inout1
451 aes${dir}last $rndkey0,$inout2
452 aes${dir}last $rndkey0,$inout3
455 .size _aesni_${dir}rypt4,.-_aesni_${dir}rypt4
458 sub aesni_generate6 {
460 # As already mentioned it takes in $key and $rounds, which are *not*
461 # preserved. $inout[0-5] is cipher/clear text...
463 .type _aesni_${dir}rypt6,\@abi-omnipotent
467 $movkey ($key),$rndkey0
469 $movkey 16($key),$rndkey1
470 xorps $rndkey0,$inout0
471 pxor $rndkey0,$inout1
472 pxor $rndkey0,$inout2
473 aes${dir} $rndkey1,$inout0
474 lea 32($key,$rounds),$key
476 aes${dir} $rndkey1,$inout1
477 pxor $rndkey0,$inout3
478 pxor $rndkey0,$inout4
479 aes${dir} $rndkey1,$inout2
480 pxor $rndkey0,$inout5
481 $movkey ($key,%rax),$rndkey0
483 jmp .L${dir}_loop6_enter
486 aes${dir} $rndkey1,$inout0
487 aes${dir} $rndkey1,$inout1
488 aes${dir} $rndkey1,$inout2
489 .L${dir}_loop6_enter:
490 aes${dir} $rndkey1,$inout3
491 aes${dir} $rndkey1,$inout4
492 aes${dir} $rndkey1,$inout5
493 $movkey ($key,%rax),$rndkey1
495 aes${dir} $rndkey0,$inout0
496 aes${dir} $rndkey0,$inout1
497 aes${dir} $rndkey0,$inout2
498 aes${dir} $rndkey0,$inout3
499 aes${dir} $rndkey0,$inout4
500 aes${dir} $rndkey0,$inout5
501 $movkey -16($key,%rax),$rndkey0
504 aes${dir} $rndkey1,$inout0
505 aes${dir} $rndkey1,$inout1
506 aes${dir} $rndkey1,$inout2
507 aes${dir} $rndkey1,$inout3
508 aes${dir} $rndkey1,$inout4
509 aes${dir} $rndkey1,$inout5
510 aes${dir}last $rndkey0,$inout0
511 aes${dir}last $rndkey0,$inout1
512 aes${dir}last $rndkey0,$inout2
513 aes${dir}last $rndkey0,$inout3
514 aes${dir}last $rndkey0,$inout4
515 aes${dir}last $rndkey0,$inout5
518 .size _aesni_${dir}rypt6,.-_aesni_${dir}rypt6
521 sub aesni_generate8 {
523 # As already mentioned it takes in $key and $rounds, which are *not*
524 # preserved. $inout[0-7] is cipher/clear text...
526 .type _aesni_${dir}rypt8,\@abi-omnipotent
530 $movkey ($key),$rndkey0
532 $movkey 16($key),$rndkey1
533 xorps $rndkey0,$inout0
534 xorps $rndkey0,$inout1
535 pxor $rndkey0,$inout2
536 pxor $rndkey0,$inout3
537 pxor $rndkey0,$inout4
538 lea 32($key,$rounds),$key
540 aes${dir} $rndkey1,$inout0
541 pxor $rndkey0,$inout5
542 pxor $rndkey0,$inout6
543 aes${dir} $rndkey1,$inout1
544 pxor $rndkey0,$inout7
545 $movkey ($key,%rax),$rndkey0
547 jmp .L${dir}_loop8_inner
550 aes${dir} $rndkey1,$inout0
551 aes${dir} $rndkey1,$inout1
552 .L${dir}_loop8_inner:
553 aes${dir} $rndkey1,$inout2
554 aes${dir} $rndkey1,$inout3
555 aes${dir} $rndkey1,$inout4
556 aes${dir} $rndkey1,$inout5
557 aes${dir} $rndkey1,$inout6
558 aes${dir} $rndkey1,$inout7
559 .L${dir}_loop8_enter:
560 $movkey ($key,%rax),$rndkey1
562 aes${dir} $rndkey0,$inout0
563 aes${dir} $rndkey0,$inout1
564 aes${dir} $rndkey0,$inout2
565 aes${dir} $rndkey0,$inout3
566 aes${dir} $rndkey0,$inout4
567 aes${dir} $rndkey0,$inout5
568 aes${dir} $rndkey0,$inout6
569 aes${dir} $rndkey0,$inout7
570 $movkey -16($key,%rax),$rndkey0
573 aes${dir} $rndkey1,$inout0
574 aes${dir} $rndkey1,$inout1
575 aes${dir} $rndkey1,$inout2
576 aes${dir} $rndkey1,$inout3
577 aes${dir} $rndkey1,$inout4
578 aes${dir} $rndkey1,$inout5
579 aes${dir} $rndkey1,$inout6
580 aes${dir} $rndkey1,$inout7
581 aes${dir}last $rndkey0,$inout0
582 aes${dir}last $rndkey0,$inout1
583 aes${dir}last $rndkey0,$inout2
584 aes${dir}last $rndkey0,$inout3
585 aes${dir}last $rndkey0,$inout4
586 aes${dir}last $rndkey0,$inout5
587 aes${dir}last $rndkey0,$inout6
588 aes${dir}last $rndkey0,$inout7
591 .size _aesni_${dir}rypt8,.-_aesni_${dir}rypt8
594 &aesni_generate2("enc") if ($PREFIX eq "aesni");
595 &aesni_generate2("dec");
596 &aesni_generate3("enc") if ($PREFIX eq "aesni");
597 &aesni_generate3("dec");
598 &aesni_generate4("enc") if ($PREFIX eq "aesni");
599 &aesni_generate4("dec");
600 &aesni_generate6("enc") if ($PREFIX eq "aesni");
601 &aesni_generate6("dec");
602 &aesni_generate8("enc") if ($PREFIX eq "aesni");
603 &aesni_generate8("dec");
605 if ($PREFIX eq "aesni") {
606 ########################################################################
607 # void aesni_ecb_encrypt (const void *in, void *out,
608 # size_t length, const AES_KEY *key,
611 .globl aesni_ecb_encrypt
612 .type aesni_ecb_encrypt,\@function,5
617 $code.=<<___ if ($win64);
619 movaps %xmm6,(%rsp) # offload $inout4..7
620 movaps %xmm7,0x10(%rsp)
621 movaps %xmm8,0x20(%rsp)
622 movaps %xmm9,0x30(%rsp)
626 and \$-16,$len # if ($len<16)
627 jz .Lecb_ret # return
629 mov 240($key),$rounds # key->rounds
630 $movkey ($key),$rndkey0
631 mov $key,$key_ # backup $key
632 mov $rounds,$rnds_ # backup $rounds
633 test %r8d,%r8d # 5th argument
635 #--------------------------- ECB ENCRYPT ------------------------------#
636 cmp \$0x80,$len # if ($len<8*16)
637 jb .Lecb_enc_tail # short input
639 movdqu ($inp),$inout0 # load 8 input blocks
640 movdqu 0x10($inp),$inout1
641 movdqu 0x20($inp),$inout2
642 movdqu 0x30($inp),$inout3
643 movdqu 0x40($inp),$inout4
644 movdqu 0x50($inp),$inout5
645 movdqu 0x60($inp),$inout6
646 movdqu 0x70($inp),$inout7
647 lea 0x80($inp),$inp # $inp+=8*16
648 sub \$0x80,$len # $len-=8*16 (can be zero)
649 jmp .Lecb_enc_loop8_enter
652 movups $inout0,($out) # store 8 output blocks
653 mov $key_,$key # restore $key
654 movdqu ($inp),$inout0 # load 8 input blocks
655 mov $rnds_,$rounds # restore $rounds
656 movups $inout1,0x10($out)
657 movdqu 0x10($inp),$inout1
658 movups $inout2,0x20($out)
659 movdqu 0x20($inp),$inout2
660 movups $inout3,0x30($out)
661 movdqu 0x30($inp),$inout3
662 movups $inout4,0x40($out)
663 movdqu 0x40($inp),$inout4
664 movups $inout5,0x50($out)
665 movdqu 0x50($inp),$inout5
666 movups $inout6,0x60($out)
667 movdqu 0x60($inp),$inout6
668 movups $inout7,0x70($out)
669 lea 0x80($out),$out # $out+=8*16
670 movdqu 0x70($inp),$inout7
671 lea 0x80($inp),$inp # $inp+=8*16
672 .Lecb_enc_loop8_enter:
677 jnc .Lecb_enc_loop8 # loop if $len-=8*16 didn't borrow
679 movups $inout0,($out) # store 8 output blocks
680 mov $key_,$key # restore $key
681 movups $inout1,0x10($out)
682 mov $rnds_,$rounds # restore $rounds
683 movups $inout2,0x20($out)
684 movups $inout3,0x30($out)
685 movups $inout4,0x40($out)
686 movups $inout5,0x50($out)
687 movups $inout6,0x60($out)
688 movups $inout7,0x70($out)
689 lea 0x80($out),$out # $out+=8*16
690 add \$0x80,$len # restore real remaining $len
691 jz .Lecb_ret # done if ($len==0)
693 .Lecb_enc_tail: # $len is less than 8*16
694 movups ($inp),$inout0
697 movups 0x10($inp),$inout1
699 movups 0x20($inp),$inout2
702 movups 0x30($inp),$inout3
704 movups 0x40($inp),$inout4
707 movups 0x50($inp),$inout5
709 movdqu 0x60($inp),$inout6
710 xorps $inout7,$inout7
712 movups $inout0,($out) # store 7 output blocks
713 movups $inout1,0x10($out)
714 movups $inout2,0x20($out)
715 movups $inout3,0x30($out)
716 movups $inout4,0x40($out)
717 movups $inout5,0x50($out)
718 movups $inout6,0x60($out)
723 &aesni_generate1("enc",$key,$rounds);
725 movups $inout0,($out) # store one output block
730 movups $inout0,($out) # store 2 output blocks
731 movups $inout1,0x10($out)
736 movups $inout0,($out) # store 3 output blocks
737 movups $inout1,0x10($out)
738 movups $inout2,0x20($out)
743 movups $inout0,($out) # store 4 output blocks
744 movups $inout1,0x10($out)
745 movups $inout2,0x20($out)
746 movups $inout3,0x30($out)
750 xorps $inout5,$inout5
752 movups $inout0,($out) # store 5 output blocks
753 movups $inout1,0x10($out)
754 movups $inout2,0x20($out)
755 movups $inout3,0x30($out)
756 movups $inout4,0x40($out)
761 movups $inout0,($out) # store 6 output blocks
762 movups $inout1,0x10($out)
763 movups $inout2,0x20($out)
764 movups $inout3,0x30($out)
765 movups $inout4,0x40($out)
766 movups $inout5,0x50($out)
768 \f#--------------------------- ECB DECRYPT ------------------------------#
771 cmp \$0x80,$len # if ($len<8*16)
772 jb .Lecb_dec_tail # short input
774 movdqu ($inp),$inout0 # load 8 input blocks
775 movdqu 0x10($inp),$inout1
776 movdqu 0x20($inp),$inout2
777 movdqu 0x30($inp),$inout3
778 movdqu 0x40($inp),$inout4
779 movdqu 0x50($inp),$inout5
780 movdqu 0x60($inp),$inout6
781 movdqu 0x70($inp),$inout7
782 lea 0x80($inp),$inp # $inp+=8*16
783 sub \$0x80,$len # $len-=8*16 (can be zero)
784 jmp .Lecb_dec_loop8_enter
787 movups $inout0,($out) # store 8 output blocks
788 mov $key_,$key # restore $key
789 movdqu ($inp),$inout0 # load 8 input blocks
790 mov $rnds_,$rounds # restore $rounds
791 movups $inout1,0x10($out)
792 movdqu 0x10($inp),$inout1
793 movups $inout2,0x20($out)
794 movdqu 0x20($inp),$inout2
795 movups $inout3,0x30($out)
796 movdqu 0x30($inp),$inout3
797 movups $inout4,0x40($out)
798 movdqu 0x40($inp),$inout4
799 movups $inout5,0x50($out)
800 movdqu 0x50($inp),$inout5
801 movups $inout6,0x60($out)
802 movdqu 0x60($inp),$inout6
803 movups $inout7,0x70($out)
804 lea 0x80($out),$out # $out+=8*16
805 movdqu 0x70($inp),$inout7
806 lea 0x80($inp),$inp # $inp+=8*16
807 .Lecb_dec_loop8_enter:
811 $movkey ($key_),$rndkey0
813 jnc .Lecb_dec_loop8 # loop if $len-=8*16 didn't borrow
815 movups $inout0,($out) # store 8 output blocks
816 pxor $inout0,$inout0 # clear register bank
817 mov $key_,$key # restore $key
818 movups $inout1,0x10($out)
820 mov $rnds_,$rounds # restore $rounds
821 movups $inout2,0x20($out)
823 movups $inout3,0x30($out)
825 movups $inout4,0x40($out)
827 movups $inout5,0x50($out)
829 movups $inout6,0x60($out)
831 movups $inout7,0x70($out)
833 lea 0x80($out),$out # $out+=8*16
834 add \$0x80,$len # restore real remaining $len
835 jz .Lecb_ret # done if ($len==0)
838 movups ($inp),$inout0
841 movups 0x10($inp),$inout1
843 movups 0x20($inp),$inout2
846 movups 0x30($inp),$inout3
848 movups 0x40($inp),$inout4
851 movups 0x50($inp),$inout5
853 movups 0x60($inp),$inout6
854 $movkey ($key),$rndkey0
855 xorps $inout7,$inout7
857 movups $inout0,($out) # store 7 output blocks
858 pxor $inout0,$inout0 # clear register bank
859 movups $inout1,0x10($out)
861 movups $inout2,0x20($out)
863 movups $inout3,0x30($out)
865 movups $inout4,0x40($out)
867 movups $inout5,0x50($out)
869 movups $inout6,0x60($out)
876 &aesni_generate1("dec",$key,$rounds);
878 movups $inout0,($out) # store one output block
879 pxor $inout0,$inout0 # clear register bank
884 movups $inout0,($out) # store 2 output blocks
885 pxor $inout0,$inout0 # clear register bank
886 movups $inout1,0x10($out)
892 movups $inout0,($out) # store 3 output blocks
893 pxor $inout0,$inout0 # clear register bank
894 movups $inout1,0x10($out)
896 movups $inout2,0x20($out)
902 movups $inout0,($out) # store 4 output blocks
903 pxor $inout0,$inout0 # clear register bank
904 movups $inout1,0x10($out)
906 movups $inout2,0x20($out)
908 movups $inout3,0x30($out)
913 xorps $inout5,$inout5
915 movups $inout0,($out) # store 5 output blocks
916 pxor $inout0,$inout0 # clear register bank
917 movups $inout1,0x10($out)
919 movups $inout2,0x20($out)
921 movups $inout3,0x30($out)
923 movups $inout4,0x40($out)
930 movups $inout0,($out) # store 6 output blocks
931 pxor $inout0,$inout0 # clear register bank
932 movups $inout1,0x10($out)
934 movups $inout2,0x20($out)
936 movups $inout3,0x30($out)
938 movups $inout4,0x40($out)
940 movups $inout5,0x50($out)
944 xorps $rndkey0,$rndkey0 # %xmm0
945 pxor $rndkey1,$rndkey1
947 $code.=<<___ if ($win64);
949 movaps %xmm0,(%rsp) # clear stack
950 movaps 0x10(%rsp),%xmm7
951 movaps %xmm0,0x10(%rsp)
952 movaps 0x20(%rsp),%xmm8
953 movaps %xmm0,0x20(%rsp)
954 movaps 0x30(%rsp),%xmm9
955 movaps %xmm0,0x30(%rsp)
962 .size aesni_ecb_encrypt,.-aesni_ecb_encrypt
966 ######################################################################
967 # void aesni_ccm64_[en|de]crypt_blocks (const void *in, void *out,
968 # size_t blocks, const AES_KEY *key,
969 # const char *ivec,char *cmac);
971 # Handles only complete blocks, operates on 64-bit counter and
972 # does not update *ivec! Nor does it finalize CMAC value
973 # (see engine/eng_aesni.c for details)
976 my $cmac="%r9"; # 6th argument
978 my $increment="%xmm9";
980 my $bswap_mask="%xmm7";
983 .globl aesni_ccm64_encrypt_blocks
984 .type aesni_ccm64_encrypt_blocks,\@function,6
986 aesni_ccm64_encrypt_blocks:
989 $code.=<<___ if ($win64);
991 movaps %xmm6,(%rsp) # $iv
992 movaps %xmm7,0x10(%rsp) # $bswap_mask
993 movaps %xmm8,0x20(%rsp) # $in0
994 movaps %xmm9,0x30(%rsp) # $increment
998 mov 240($key),$rounds # key->rounds
1000 movdqa .Lincrement64(%rip),$increment
1001 movdqa .Lbswap_mask(%rip),$bswap_mask
1006 movdqu ($cmac),$inout1
1008 lea 32($key,$rounds),$key # end of key schedule
1009 pshufb $bswap_mask,$iv
1010 sub %rax,%r10 # twisted $rounds
1011 jmp .Lccm64_enc_outer
1014 $movkey ($key_),$rndkey0
1016 movups ($inp),$in0 # load inp
1018 xorps $rndkey0,$inout0 # counter
1019 $movkey 16($key_),$rndkey1
1021 xorps $rndkey0,$inout1 # cmac^=inp
1022 $movkey 32($key_),$rndkey0
1025 aesenc $rndkey1,$inout0
1026 aesenc $rndkey1,$inout1
1027 $movkey ($key,%rax),$rndkey1
1029 aesenc $rndkey0,$inout0
1030 aesenc $rndkey0,$inout1
1031 $movkey -16($key,%rax),$rndkey0
1032 jnz .Lccm64_enc2_loop
1033 aesenc $rndkey1,$inout0
1034 aesenc $rndkey1,$inout1
1035 paddq $increment,$iv
1036 dec $len # $len-- ($len is in blocks)
1037 aesenclast $rndkey0,$inout0
1038 aesenclast $rndkey0,$inout1
1041 xorps $inout0,$in0 # inp ^= E(iv)
1043 movups $in0,($out) # save output
1044 pshufb $bswap_mask,$inout0
1045 lea 16($out),$out # $out+=16
1046 jnz .Lccm64_enc_outer # loop if ($len!=0)
1048 pxor $rndkey0,$rndkey0 # clear register bank
1049 pxor $rndkey1,$rndkey1
1050 pxor $inout0,$inout0
1051 movups $inout1,($cmac) # store resulting mac
1052 pxor $inout1,$inout1
1056 $code.=<<___ if ($win64);
1058 movaps %xmm0,(%rsp) # clear stack
1059 movaps 0x10(%rsp),%xmm7
1060 movaps %xmm0,0x10(%rsp)
1061 movaps 0x20(%rsp),%xmm8
1062 movaps %xmm0,0x20(%rsp)
1063 movaps 0x30(%rsp),%xmm9
1064 movaps %xmm0,0x30(%rsp)
1071 .size aesni_ccm64_encrypt_blocks,.-aesni_ccm64_encrypt_blocks
1073 ######################################################################
1075 .globl aesni_ccm64_decrypt_blocks
1076 .type aesni_ccm64_decrypt_blocks,\@function,6
1078 aesni_ccm64_decrypt_blocks:
1081 $code.=<<___ if ($win64);
1082 lea -0x58(%rsp),%rsp
1083 movaps %xmm6,(%rsp) # $iv
1084 movaps %xmm7,0x10(%rsp) # $bswap_mask
1085 movaps %xmm8,0x20(%rsp) # $in8
1086 movaps %xmm9,0x30(%rsp) # $increment
1090 mov 240($key),$rounds # key->rounds
1092 movdqu ($cmac),$inout1
1093 movdqa .Lincrement64(%rip),$increment
1094 movdqa .Lbswap_mask(%rip),$bswap_mask
1099 pshufb $bswap_mask,$iv
1101 &aesni_generate1("enc",$key,$rounds);
1105 movups ($inp),$in0 # load inp
1106 paddq $increment,$iv
1107 lea 16($inp),$inp # $inp+=16
1108 sub %r10,%rax # twisted $rounds
1109 lea 32($key_,$rnds_),$key # end of key schedule
1111 jmp .Lccm64_dec_outer
1114 xorps $inout0,$in0 # inp ^= E(iv)
1116 movups $in0,($out) # save output
1117 lea 16($out),$out # $out+=16
1118 pshufb $bswap_mask,$inout0
1120 sub \$1,$len # $len-- ($len is in blocks)
1121 jz .Lccm64_dec_break # if ($len==0) break
1123 $movkey ($key_),$rndkey0
1125 $movkey 16($key_),$rndkey1
1127 xorps $rndkey0,$inout0
1128 xorps $in0,$inout1 # cmac^=out
1129 $movkey 32($key_),$rndkey0
1130 jmp .Lccm64_dec2_loop
1133 aesenc $rndkey1,$inout0
1134 aesenc $rndkey1,$inout1
1135 $movkey ($key,%rax),$rndkey1
1137 aesenc $rndkey0,$inout0
1138 aesenc $rndkey0,$inout1
1139 $movkey -16($key,%rax),$rndkey0
1140 jnz .Lccm64_dec2_loop
1141 movups ($inp),$in0 # load input
1142 paddq $increment,$iv
1143 aesenc $rndkey1,$inout0
1144 aesenc $rndkey1,$inout1
1145 aesenclast $rndkey0,$inout0
1146 aesenclast $rndkey0,$inout1
1147 lea 16($inp),$inp # $inp+=16
1148 jmp .Lccm64_dec_outer
1152 #xorps $in0,$inout1 # cmac^=out
1153 mov 240($key_),$rounds
1155 &aesni_generate1("enc",$key_,$rounds,$inout1,$in0);
1157 pxor $rndkey0,$rndkey0 # clear register bank
1158 pxor $rndkey1,$rndkey1
1159 pxor $inout0,$inout0
1160 movups $inout1,($cmac) # store resulting mac
1161 pxor $inout1,$inout1
1165 $code.=<<___ if ($win64);
1167 movaps %xmm0,(%rsp) # clear stack
1168 movaps 0x10(%rsp),%xmm7
1169 movaps %xmm0,0x10(%rsp)
1170 movaps 0x20(%rsp),%xmm8
1171 movaps %xmm0,0x20(%rsp)
1172 movaps 0x30(%rsp),%xmm9
1173 movaps %xmm0,0x30(%rsp)
1180 .size aesni_ccm64_decrypt_blocks,.-aesni_ccm64_decrypt_blocks
1183 ######################################################################
1184 # void aesni_ctr32_encrypt_blocks (const void *in, void *out,
1185 # size_t blocks, const AES_KEY *key,
1186 # const char *ivec);
1188 # Handles only complete blocks, operates on 32-bit counter and
1189 # does not update *ivec! (see crypto/modes/ctr128.c for details)
1191 # Overhaul based on suggestions from Shay Gueron and Vlad Krasnov,
1192 # http://rt.openssl.org/Ticket/Display.html?id=3021&user=guest&pass=guest.
1193 # Keywords are full unroll and modulo-schedule counter calculations
1194 # with zero-round key xor.
1196 my ($in0,$in1,$in2,$in3,$in4,$in5)=map("%xmm$_",(10..15));
1197 my ($key0,$ctr)=("%ebp","${ivp}d");
1198 my $frame_size = 0x80 + ($win64?160:0);
1201 .globl aesni_ctr32_encrypt_blocks
1202 .type aesni_ctr32_encrypt_blocks,\@function,5
1204 aesni_ctr32_encrypt_blocks:
1209 # handle single block without allocating stack frame,
1210 # useful when handling edges
1211 movups ($ivp),$inout0
1212 movups ($inp),$inout1
1213 mov 240($key),%edx # key->rounds
1215 &aesni_generate1("enc",$key,"%edx");
1217 pxor $rndkey0,$rndkey0 # clear register bank
1218 pxor $rndkey1,$rndkey1
1219 xorps $inout1,$inout0
1220 pxor $inout1,$inout1
1221 movups $inout0,($out)
1222 xorps $inout0,$inout0
1223 jmp .Lctr32_epilogue
1227 lea (%rsp),$key_ # use $key_ as frame pointer
1228 .cfi_def_cfa_register $key_
1231 sub \$$frame_size,%rsp
1232 and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
1234 $code.=<<___ if ($win64);
1235 movaps %xmm6,-0xa8($key_) # offload everything
1236 movaps %xmm7,-0x98($key_)
1237 movaps %xmm8,-0x88($key_)
1238 movaps %xmm9,-0x78($key_)
1239 movaps %xmm10,-0x68($key_)
1240 movaps %xmm11,-0x58($key_)
1241 movaps %xmm12,-0x48($key_)
1242 movaps %xmm13,-0x38($key_)
1243 movaps %xmm14,-0x28($key_)
1244 movaps %xmm15,-0x18($key_)
1249 # 8 16-byte words on top of stack are counter values
1250 # xor-ed with zero-round key
1252 movdqu ($ivp),$inout0
1253 movdqu ($key),$rndkey0
1254 mov 12($ivp),$ctr # counter LSB
1255 pxor $rndkey0,$inout0
1256 mov 12($key),$key0 # 0-round key LSB
1257 movdqa $inout0,0x00(%rsp) # populate counter block
1259 movdqa $inout0,$inout1
1260 movdqa $inout0,$inout2
1261 movdqa $inout0,$inout3
1262 movdqa $inout0,0x40(%rsp)
1263 movdqa $inout0,0x50(%rsp)
1264 movdqa $inout0,0x60(%rsp)
1265 mov %rdx,%r10 # about to borrow %rdx
1266 movdqa $inout0,0x70(%rsp)
1274 pinsrd \$3,%eax,$inout1
1276 movdqa $inout1,0x10(%rsp)
1277 pinsrd \$3,%edx,$inout2
1279 mov %r10,%rdx # restore %rdx
1281 movdqa $inout2,0x20(%rsp)
1284 pinsrd \$3,%eax,$inout3
1286 movdqa $inout3,0x30(%rsp)
1288 mov %r10d,0x40+12(%rsp)
1291 mov 240($key),$rounds # key->rounds
1294 mov %r9d,0x50+12(%rsp)
1297 mov %r10d,0x60+12(%rsp)
1299 mov OPENSSL_ia32cap_P+4(%rip),%r10d
1301 and \$`1<<26|1<<22`,%r10d # isolate XSAVE+MOVBE
1302 mov %r9d,0x70+12(%rsp)
1304 $movkey 0x10($key),$rndkey1
1306 movdqa 0x40(%rsp),$inout4
1307 movdqa 0x50(%rsp),$inout5
1309 cmp \$8,$len # $len is in blocks
1310 jb .Lctr32_tail # short input if ($len<8)
1312 sub \$6,$len # $len is biased by -6
1313 cmp \$`1<<22`,%r10d # check for MOVBE without XSAVE
1314 je .Lctr32_6x # [which denotes Atom Silvermont]
1316 lea 0x80($key),$key # size optimization
1317 sub \$2,$len # $len is biased by -8
1325 lea 32($key,$rounds),$key # end of key schedule
1326 sub %rax,%r10 # twisted $rounds
1331 add \$6,$ctr # next counter value
1332 $movkey -48($key,$rnds_),$rndkey0
1333 aesenc $rndkey1,$inout0
1336 aesenc $rndkey1,$inout1
1337 movbe %eax,`0x00+12`(%rsp) # store next counter value
1339 aesenc $rndkey1,$inout2
1341 movbe %eax,`0x10+12`(%rsp)
1342 aesenc $rndkey1,$inout3
1345 aesenc $rndkey1,$inout4
1346 movbe %eax,`0x20+12`(%rsp)
1348 aesenc $rndkey1,$inout5
1349 $movkey -32($key,$rnds_),$rndkey1
1352 aesenc $rndkey0,$inout0
1353 movbe %eax,`0x30+12`(%rsp)
1355 aesenc $rndkey0,$inout1
1357 movbe %eax,`0x40+12`(%rsp)
1358 aesenc $rndkey0,$inout2
1361 aesenc $rndkey0,$inout3
1362 movbe %eax,`0x50+12`(%rsp)
1363 mov %r10,%rax # mov $rnds_,$rounds
1364 aesenc $rndkey0,$inout4
1365 aesenc $rndkey0,$inout5
1366 $movkey -16($key,$rnds_),$rndkey0
1370 movdqu ($inp),$inout6 # load 6 input blocks
1371 movdqu 0x10($inp),$inout7
1372 movdqu 0x20($inp),$in0
1373 movdqu 0x30($inp),$in1
1374 movdqu 0x40($inp),$in2
1375 movdqu 0x50($inp),$in3
1376 lea 0x60($inp),$inp # $inp+=6*16
1377 $movkey -64($key,$rnds_),$rndkey1
1378 pxor $inout0,$inout6 # inp^=E(ctr)
1379 movaps 0x00(%rsp),$inout0 # load next counter [xor-ed with 0 round]
1380 pxor $inout1,$inout7
1381 movaps 0x10(%rsp),$inout1
1383 movaps 0x20(%rsp),$inout2
1385 movaps 0x30(%rsp),$inout3
1387 movaps 0x40(%rsp),$inout4
1389 movaps 0x50(%rsp),$inout5
1390 movdqu $inout6,($out) # store 6 output blocks
1391 movdqu $inout7,0x10($out)
1392 movdqu $in0,0x20($out)
1393 movdqu $in1,0x30($out)
1394 movdqu $in2,0x40($out)
1395 movdqu $in3,0x50($out)
1396 lea 0x60($out),$out # $out+=6*16
1399 jnc .Lctr32_loop6 # loop if $len-=6 didn't borrow
1401 add \$6,$len # restore real remaining $len
1402 jz .Lctr32_done # done if ($len==0)
1404 lea -48($rnds_),$rounds
1405 lea -80($key,$rnds_),$key # restore $key
1407 shr \$4,$rounds # restore $rounds
1412 add \$8,$ctr # next counter value
1413 movdqa 0x60(%rsp),$inout6
1414 aesenc $rndkey1,$inout0
1416 movdqa 0x70(%rsp),$inout7
1417 aesenc $rndkey1,$inout1
1419 $movkey 0x20-0x80($key),$rndkey0
1420 aesenc $rndkey1,$inout2
1423 aesenc $rndkey1,$inout3
1424 mov %r9d,0x00+12(%rsp) # store next counter value
1426 aesenc $rndkey1,$inout4
1427 aesenc $rndkey1,$inout5
1428 aesenc $rndkey1,$inout6
1429 aesenc $rndkey1,$inout7
1430 $movkey 0x30-0x80($key),$rndkey1
1432 for($i=2;$i<8;$i++) {
1433 my $rndkeyx = ($i&1)?$rndkey1:$rndkey0;
1436 aesenc $rndkeyx,$inout0
1437 aesenc $rndkeyx,$inout1
1440 aesenc $rndkeyx,$inout2
1441 aesenc $rndkeyx,$inout3
1442 mov %r9d,`0x10*($i-1)`+12(%rsp)
1444 aesenc $rndkeyx,$inout4
1445 aesenc $rndkeyx,$inout5
1446 aesenc $rndkeyx,$inout6
1447 aesenc $rndkeyx,$inout7
1448 $movkey `0x20+0x10*$i`-0x80($key),$rndkeyx
1453 aesenc $rndkey0,$inout0
1454 aesenc $rndkey0,$inout1
1455 aesenc $rndkey0,$inout2
1457 movdqu 0x00($inp),$in0 # start loading input
1458 aesenc $rndkey0,$inout3
1459 mov %r9d,0x70+12(%rsp)
1461 aesenc $rndkey0,$inout4
1462 aesenc $rndkey0,$inout5
1463 aesenc $rndkey0,$inout6
1464 aesenc $rndkey0,$inout7
1465 $movkey 0xa0-0x80($key),$rndkey0
1469 aesenc $rndkey1,$inout0
1470 aesenc $rndkey1,$inout1
1471 aesenc $rndkey1,$inout2
1472 aesenc $rndkey1,$inout3
1473 aesenc $rndkey1,$inout4
1474 aesenc $rndkey1,$inout5
1475 aesenc $rndkey1,$inout6
1476 aesenc $rndkey1,$inout7
1477 $movkey 0xb0-0x80($key),$rndkey1
1479 aesenc $rndkey0,$inout0
1480 aesenc $rndkey0,$inout1
1481 aesenc $rndkey0,$inout2
1482 aesenc $rndkey0,$inout3
1483 aesenc $rndkey0,$inout4
1484 aesenc $rndkey0,$inout5
1485 aesenc $rndkey0,$inout6
1486 aesenc $rndkey0,$inout7
1487 $movkey 0xc0-0x80($key),$rndkey0
1490 aesenc $rndkey1,$inout0
1491 aesenc $rndkey1,$inout1
1492 aesenc $rndkey1,$inout2
1493 aesenc $rndkey1,$inout3
1494 aesenc $rndkey1,$inout4
1495 aesenc $rndkey1,$inout5
1496 aesenc $rndkey1,$inout6
1497 aesenc $rndkey1,$inout7
1498 $movkey 0xd0-0x80($key),$rndkey1
1500 aesenc $rndkey0,$inout0
1501 aesenc $rndkey0,$inout1
1502 aesenc $rndkey0,$inout2
1503 aesenc $rndkey0,$inout3
1504 aesenc $rndkey0,$inout4
1505 aesenc $rndkey0,$inout5
1506 aesenc $rndkey0,$inout6
1507 aesenc $rndkey0,$inout7
1508 $movkey 0xe0-0x80($key),$rndkey0
1509 jmp .Lctr32_enc_done
1513 movdqu 0x10($inp),$in1
1514 pxor $rndkey0,$in0 # input^=round[last]
1515 movdqu 0x20($inp),$in2
1517 movdqu 0x30($inp),$in3
1519 movdqu 0x40($inp),$in4
1521 movdqu 0x50($inp),$in5
1524 aesenc $rndkey1,$inout0
1525 aesenc $rndkey1,$inout1
1526 aesenc $rndkey1,$inout2
1527 aesenc $rndkey1,$inout3
1528 aesenc $rndkey1,$inout4
1529 aesenc $rndkey1,$inout5
1530 aesenc $rndkey1,$inout6
1531 aesenc $rndkey1,$inout7
1532 movdqu 0x60($inp),$rndkey1 # borrow $rndkey1 for inp[6]
1533 lea 0x80($inp),$inp # $inp+=8*16
1535 aesenclast $in0,$inout0 # $inN is inp[N]^round[last]
1536 pxor $rndkey0,$rndkey1 # borrowed $rndkey
1537 movdqu 0x70-0x80($inp),$in0
1538 aesenclast $in1,$inout1
1540 movdqa 0x00(%rsp),$in1 # load next counter block
1541 aesenclast $in2,$inout2
1542 aesenclast $in3,$inout3
1543 movdqa 0x10(%rsp),$in2
1544 movdqa 0x20(%rsp),$in3
1545 aesenclast $in4,$inout4
1546 aesenclast $in5,$inout5
1547 movdqa 0x30(%rsp),$in4
1548 movdqa 0x40(%rsp),$in5
1549 aesenclast $rndkey1,$inout6
1550 movdqa 0x50(%rsp),$rndkey0
1551 $movkey 0x10-0x80($key),$rndkey1#real 1st-round key
1552 aesenclast $in0,$inout7
1554 movups $inout0,($out) # store 8 output blocks
1556 movups $inout1,0x10($out)
1558 movups $inout2,0x20($out)
1560 movups $inout3,0x30($out)
1562 movups $inout4,0x40($out)
1564 movups $inout5,0x50($out)
1565 movdqa $rndkey0,$inout5
1566 movups $inout6,0x60($out)
1567 movups $inout7,0x70($out)
1568 lea 0x80($out),$out # $out+=8*16
1571 jnc .Lctr32_loop8 # loop if $len-=8 didn't borrow
1573 add \$8,$len # restore real remaining $len
1574 jz .Lctr32_done # done if ($len==0)
1575 lea -0x80($key),$key
1578 # note that at this point $inout0..5 are populated with
1579 # counter values xor-ed with 0-round key
1585 # if ($len>4) compute 7 E(counter)
1587 movdqa 0x60(%rsp),$inout6
1588 pxor $inout7,$inout7
1590 $movkey 16($key),$rndkey0
1591 aesenc $rndkey1,$inout0
1592 aesenc $rndkey1,$inout1
1593 lea 32-16($key,$rounds),$key# prepare for .Lenc_loop8_enter
1595 aesenc $rndkey1,$inout2
1596 add \$16,%rax # prepare for .Lenc_loop8_enter
1598 aesenc $rndkey1,$inout3
1599 aesenc $rndkey1,$inout4
1600 movups 0x10($inp),$in1 # pre-load input
1601 movups 0x20($inp),$in2
1602 aesenc $rndkey1,$inout5
1603 aesenc $rndkey1,$inout6
1605 call .Lenc_loop8_enter
1607 movdqu 0x30($inp),$in3
1609 movdqu 0x40($inp),$in0
1611 movdqu $inout0,($out) # store output
1613 movdqu $inout1,0x10($out)
1615 movdqu $inout2,0x20($out)
1617 movdqu $inout3,0x30($out)
1618 movdqu $inout4,0x40($out)
1620 jb .Lctr32_done # $len was 5, stop store
1622 movups 0x50($inp),$in1
1624 movups $inout5,0x50($out)
1625 je .Lctr32_done # $len was 6, stop store
1627 movups 0x60($inp),$in2
1629 movups $inout6,0x60($out)
1630 jmp .Lctr32_done # $len was 7, stop store
1634 aesenc $rndkey1,$inout0
1637 aesenc $rndkey1,$inout1
1638 aesenc $rndkey1,$inout2
1639 aesenc $rndkey1,$inout3
1640 $movkey ($key),$rndkey1
1642 aesenclast $rndkey1,$inout0
1643 aesenclast $rndkey1,$inout1
1644 movups ($inp),$in0 # load input
1645 movups 0x10($inp),$in1
1646 aesenclast $rndkey1,$inout2
1647 aesenclast $rndkey1,$inout3
1648 movups 0x20($inp),$in2
1649 movups 0x30($inp),$in3
1652 movups $inout0,($out) # store output
1654 movups $inout1,0x10($out)
1656 movdqu $inout2,0x20($out)
1658 movdqu $inout3,0x30($out)
1659 jmp .Lctr32_done # $len was 4, stop store
1663 aesenc $rndkey1,$inout0
1666 aesenc $rndkey1,$inout1
1667 aesenc $rndkey1,$inout2
1668 $movkey ($key),$rndkey1
1670 aesenclast $rndkey1,$inout0
1671 aesenclast $rndkey1,$inout1
1672 aesenclast $rndkey1,$inout2
1674 movups ($inp),$in0 # load input
1676 movups $inout0,($out) # store output
1678 jb .Lctr32_done # $len was 1, stop store
1680 movups 0x10($inp),$in1
1682 movups $inout1,0x10($out)
1683 je .Lctr32_done # $len was 2, stop store
1685 movups 0x20($inp),$in2
1687 movups $inout2,0x20($out) # $len was 3, stop store
1690 xorps %xmm0,%xmm0 # clear register bank
1698 $code.=<<___ if (!$win64);
1701 movaps %xmm0,0x00(%rsp) # clear stack
1703 movaps %xmm0,0x10(%rsp)
1705 movaps %xmm0,0x20(%rsp)
1707 movaps %xmm0,0x30(%rsp)
1709 movaps %xmm0,0x40(%rsp)
1711 movaps %xmm0,0x50(%rsp)
1713 movaps %xmm0,0x60(%rsp)
1715 movaps %xmm0,0x70(%rsp)
1718 $code.=<<___ if ($win64);
1719 movaps -0xa8($key_),%xmm6
1720 movaps %xmm0,-0xa8($key_) # clear stack
1721 movaps -0x98($key_),%xmm7
1722 movaps %xmm0,-0x98($key_)
1723 movaps -0x88($key_),%xmm8
1724 movaps %xmm0,-0x88($key_)
1725 movaps -0x78($key_),%xmm9
1726 movaps %xmm0,-0x78($key_)
1727 movaps -0x68($key_),%xmm10
1728 movaps %xmm0,-0x68($key_)
1729 movaps -0x58($key_),%xmm11
1730 movaps %xmm0,-0x58($key_)
1731 movaps -0x48($key_),%xmm12
1732 movaps %xmm0,-0x48($key_)
1733 movaps -0x38($key_),%xmm13
1734 movaps %xmm0,-0x38($key_)
1735 movaps -0x28($key_),%xmm14
1736 movaps %xmm0,-0x28($key_)
1737 movaps -0x18($key_),%xmm15
1738 movaps %xmm0,-0x18($key_)
1739 movaps %xmm0,0x00(%rsp)
1740 movaps %xmm0,0x10(%rsp)
1741 movaps %xmm0,0x20(%rsp)
1742 movaps %xmm0,0x30(%rsp)
1743 movaps %xmm0,0x40(%rsp)
1744 movaps %xmm0,0x50(%rsp)
1745 movaps %xmm0,0x60(%rsp)
1746 movaps %xmm0,0x70(%rsp)
1752 .cfi_def_cfa_register %rsp
1756 .size aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks
1760 ######################################################################
1761 # void aesni_xts_[en|de]crypt(const char *inp,char *out,size_t len,
1762 # const AES_KEY *key1, const AES_KEY *key2
1763 # const unsigned char iv[16]);
1766 my @tweak=map("%xmm$_",(10..15));
1767 my ($twmask,$twres,$twtmp)=("%xmm8","%xmm9",@tweak[4]);
1768 my ($key2,$ivp,$len_)=("%r8","%r9","%r9");
1769 my $frame_size = 0x70 + ($win64?160:0);
1770 my $key_ = "%rbp"; # override so that we can use %r11 as FP
1773 .globl aesni_xts_encrypt
1774 .type aesni_xts_encrypt,\@function,6
1778 lea (%rsp),%r11 # frame pointer
1779 .cfi_def_cfa_register %r11
1782 sub \$$frame_size,%rsp
1783 and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
1785 $code.=<<___ if ($win64);
1786 movaps %xmm6,-0xa8(%r11) # offload everything
1787 movaps %xmm7,-0x98(%r11)
1788 movaps %xmm8,-0x88(%r11)
1789 movaps %xmm9,-0x78(%r11)
1790 movaps %xmm10,-0x68(%r11)
1791 movaps %xmm11,-0x58(%r11)
1792 movaps %xmm12,-0x48(%r11)
1793 movaps %xmm13,-0x38(%r11)
1794 movaps %xmm14,-0x28(%r11)
1795 movaps %xmm15,-0x18(%r11)
1799 movups ($ivp),$inout0 # load clear-text tweak
1800 mov 240(%r8),$rounds # key2->rounds
1801 mov 240($key),$rnds_ # key1->rounds
1803 # generate the tweak
1804 &aesni_generate1("enc",$key2,$rounds,$inout0);
1806 $movkey ($key),$rndkey0 # zero round key
1807 mov $key,$key_ # backup $key
1808 mov $rnds_,$rounds # backup $rounds
1810 mov $len,$len_ # backup $len
1813 $movkey 16($key,$rnds_),$rndkey1 # last round key
1815 movdqa .Lxts_magic(%rip),$twmask
1816 movdqa $inout0,@tweak[5]
1817 pshufd \$0x5f,$inout0,$twres
1818 pxor $rndkey0,$rndkey1
1820 # alternative tweak calculation algorithm is based on suggestions
1821 # by Shay Gueron. psrad doesn't conflict with AES-NI instructions
1822 # and should help in the future...
1823 for ($i=0;$i<4;$i++) {
1825 movdqa $twres,$twtmp
1827 movdqa @tweak[5],@tweak[$i]
1828 psrad \$31,$twtmp # broadcast upper bits
1829 paddq @tweak[5],@tweak[5]
1831 pxor $rndkey0,@tweak[$i]
1832 pxor $twtmp,@tweak[5]
1836 movdqa @tweak[5],@tweak[4]
1838 paddq @tweak[5],@tweak[5]
1840 pxor $rndkey0,@tweak[4]
1841 pxor $twres,@tweak[5]
1842 movaps $rndkey1,0x60(%rsp) # save round[0]^round[last]
1845 jc .Lxts_enc_short # if $len-=6*16 borrowed
1848 lea 32($key_,$rnds_),$key # end of key schedule
1849 sub %r10,%rax # twisted $rounds
1850 $movkey 16($key_),$rndkey1
1851 mov %rax,%r10 # backup twisted $rounds
1852 lea .Lxts_magic(%rip),%r8
1853 jmp .Lxts_enc_grandloop
1856 .Lxts_enc_grandloop:
1857 movdqu `16*0`($inp),$inout0 # load input
1858 movdqa $rndkey0,$twmask
1859 movdqu `16*1`($inp),$inout1
1860 pxor @tweak[0],$inout0 # input^=tweak^round[0]
1861 movdqu `16*2`($inp),$inout2
1862 pxor @tweak[1],$inout1
1863 aesenc $rndkey1,$inout0
1864 movdqu `16*3`($inp),$inout3
1865 pxor @tweak[2],$inout2
1866 aesenc $rndkey1,$inout1
1867 movdqu `16*4`($inp),$inout4
1868 pxor @tweak[3],$inout3
1869 aesenc $rndkey1,$inout2
1870 movdqu `16*5`($inp),$inout5
1871 pxor @tweak[5],$twmask # round[0]^=tweak[5]
1872 movdqa 0x60(%rsp),$twres # load round[0]^round[last]
1873 pxor @tweak[4],$inout4
1874 aesenc $rndkey1,$inout3
1875 $movkey 32($key_),$rndkey0
1876 lea `16*6`($inp),$inp
1877 pxor $twmask,$inout5
1879 pxor $twres,@tweak[0] # calculate tweaks^round[last]
1880 aesenc $rndkey1,$inout4
1881 pxor $twres,@tweak[1]
1882 movdqa @tweak[0],`16*0`(%rsp) # put aside tweaks^round[last]
1883 aesenc $rndkey1,$inout5
1884 $movkey 48($key_),$rndkey1
1885 pxor $twres,@tweak[2]
1887 aesenc $rndkey0,$inout0
1888 pxor $twres,@tweak[3]
1889 movdqa @tweak[1],`16*1`(%rsp)
1890 aesenc $rndkey0,$inout1
1891 pxor $twres,@tweak[4]
1892 movdqa @tweak[2],`16*2`(%rsp)
1893 aesenc $rndkey0,$inout2
1894 aesenc $rndkey0,$inout3
1896 movdqa @tweak[4],`16*4`(%rsp)
1897 aesenc $rndkey0,$inout4
1898 aesenc $rndkey0,$inout5
1899 $movkey 64($key_),$rndkey0
1900 movdqa $twmask,`16*5`(%rsp)
1901 pshufd \$0x5f,@tweak[5],$twres
1905 aesenc $rndkey1,$inout0
1906 aesenc $rndkey1,$inout1
1907 aesenc $rndkey1,$inout2
1908 aesenc $rndkey1,$inout3
1909 aesenc $rndkey1,$inout4
1910 aesenc $rndkey1,$inout5
1911 $movkey -64($key,%rax),$rndkey1
1914 aesenc $rndkey0,$inout0
1915 aesenc $rndkey0,$inout1
1916 aesenc $rndkey0,$inout2
1917 aesenc $rndkey0,$inout3
1918 aesenc $rndkey0,$inout4
1919 aesenc $rndkey0,$inout5
1920 $movkey -80($key,%rax),$rndkey0
1923 movdqa (%r8),$twmask # start calculating next tweak
1924 movdqa $twres,$twtmp
1926 aesenc $rndkey1,$inout0
1927 paddq @tweak[5],@tweak[5]
1929 aesenc $rndkey1,$inout1
1931 $movkey ($key_),@tweak[0] # load round[0]
1932 aesenc $rndkey1,$inout2
1933 aesenc $rndkey1,$inout3
1934 aesenc $rndkey1,$inout4
1935 pxor $twtmp,@tweak[5]
1936 movaps @tweak[0],@tweak[1] # copy round[0]
1937 aesenc $rndkey1,$inout5
1938 $movkey -64($key),$rndkey1
1940 movdqa $twres,$twtmp
1941 aesenc $rndkey0,$inout0
1943 pxor @tweak[5],@tweak[0]
1944 aesenc $rndkey0,$inout1
1946 paddq @tweak[5],@tweak[5]
1947 aesenc $rndkey0,$inout2
1948 aesenc $rndkey0,$inout3
1950 movaps @tweak[1],@tweak[2]
1951 aesenc $rndkey0,$inout4
1952 pxor $twtmp,@tweak[5]
1953 movdqa $twres,$twtmp
1954 aesenc $rndkey0,$inout5
1955 $movkey -48($key),$rndkey0
1958 aesenc $rndkey1,$inout0
1959 pxor @tweak[5],@tweak[1]
1961 aesenc $rndkey1,$inout1
1962 paddq @tweak[5],@tweak[5]
1964 aesenc $rndkey1,$inout2
1965 aesenc $rndkey1,$inout3
1966 movdqa @tweak[3],`16*3`(%rsp)
1967 pxor $twtmp,@tweak[5]
1968 aesenc $rndkey1,$inout4
1969 movaps @tweak[2],@tweak[3]
1970 movdqa $twres,$twtmp
1971 aesenc $rndkey1,$inout5
1972 $movkey -32($key),$rndkey1
1975 aesenc $rndkey0,$inout0
1976 pxor @tweak[5],@tweak[2]
1978 aesenc $rndkey0,$inout1
1979 paddq @tweak[5],@tweak[5]
1981 aesenc $rndkey0,$inout2
1982 aesenc $rndkey0,$inout3
1983 aesenc $rndkey0,$inout4
1984 pxor $twtmp,@tweak[5]
1985 movaps @tweak[3],@tweak[4]
1986 aesenc $rndkey0,$inout5
1988 movdqa $twres,$rndkey0
1990 aesenc $rndkey1,$inout0
1991 pxor @tweak[5],@tweak[3]
1993 aesenc $rndkey1,$inout1
1994 paddq @tweak[5],@tweak[5]
1995 pand $twmask,$rndkey0
1996 aesenc $rndkey1,$inout2
1997 aesenc $rndkey1,$inout3
1998 pxor $rndkey0,@tweak[5]
1999 $movkey ($key_),$rndkey0
2000 aesenc $rndkey1,$inout4
2001 aesenc $rndkey1,$inout5
2002 $movkey 16($key_),$rndkey1
2004 pxor @tweak[5],@tweak[4]
2005 aesenclast `16*0`(%rsp),$inout0
2007 paddq @tweak[5],@tweak[5]
2008 aesenclast `16*1`(%rsp),$inout1
2009 aesenclast `16*2`(%rsp),$inout2
2011 mov %r10,%rax # restore $rounds
2012 aesenclast `16*3`(%rsp),$inout3
2013 aesenclast `16*4`(%rsp),$inout4
2014 aesenclast `16*5`(%rsp),$inout5
2015 pxor $twres,@tweak[5]
2017 lea `16*6`($out),$out # $out+=6*16
2018 movups $inout0,`-16*6`($out) # store 6 output blocks
2019 movups $inout1,`-16*5`($out)
2020 movups $inout2,`-16*4`($out)
2021 movups $inout3,`-16*3`($out)
2022 movups $inout4,`-16*2`($out)
2023 movups $inout5,`-16*1`($out)
2025 jnc .Lxts_enc_grandloop # loop if $len-=6*16 didn't borrow
2029 mov $key_,$key # restore $key
2030 shr \$4,$rounds # restore original value
2033 # at the point @tweak[0..5] are populated with tweak values
2034 mov $rounds,$rnds_ # backup $rounds
2035 pxor $rndkey0,@tweak[0]
2036 add \$16*6,$len # restore real remaining $len
2037 jz .Lxts_enc_done # done if ($len==0)
2039 pxor $rndkey0,@tweak[1]
2041 jb .Lxts_enc_one # $len is 1*16
2042 pxor $rndkey0,@tweak[2]
2043 je .Lxts_enc_two # $len is 2*16
2045 pxor $rndkey0,@tweak[3]
2047 jb .Lxts_enc_three # $len is 3*16
2048 pxor $rndkey0,@tweak[4]
2049 je .Lxts_enc_four # $len is 4*16
2051 movdqu ($inp),$inout0 # $len is 5*16
2052 movdqu 16*1($inp),$inout1
2053 movdqu 16*2($inp),$inout2
2054 pxor @tweak[0],$inout0
2055 movdqu 16*3($inp),$inout3
2056 pxor @tweak[1],$inout1
2057 movdqu 16*4($inp),$inout4
2058 lea 16*5($inp),$inp # $inp+=5*16
2059 pxor @tweak[2],$inout2
2060 pxor @tweak[3],$inout3
2061 pxor @tweak[4],$inout4
2062 pxor $inout5,$inout5
2064 call _aesni_encrypt6
2066 xorps @tweak[0],$inout0
2067 movdqa @tweak[5],@tweak[0]
2068 xorps @tweak[1],$inout1
2069 xorps @tweak[2],$inout2
2070 movdqu $inout0,($out) # store 5 output blocks
2071 xorps @tweak[3],$inout3
2072 movdqu $inout1,16*1($out)
2073 xorps @tweak[4],$inout4
2074 movdqu $inout2,16*2($out)
2075 movdqu $inout3,16*3($out)
2076 movdqu $inout4,16*4($out)
2077 lea 16*5($out),$out # $out+=5*16
2082 movups ($inp),$inout0
2083 lea 16*1($inp),$inp # inp+=1*16
2084 xorps @tweak[0],$inout0
2086 &aesni_generate1("enc",$key,$rounds);
2088 xorps @tweak[0],$inout0
2089 movdqa @tweak[1],@tweak[0]
2090 movups $inout0,($out) # store one output block
2091 lea 16*1($out),$out # $out+=1*16
2096 movups ($inp),$inout0
2097 movups 16($inp),$inout1
2098 lea 32($inp),$inp # $inp+=2*16
2099 xorps @tweak[0],$inout0
2100 xorps @tweak[1],$inout1
2102 call _aesni_encrypt2
2104 xorps @tweak[0],$inout0
2105 movdqa @tweak[2],@tweak[0]
2106 xorps @tweak[1],$inout1
2107 movups $inout0,($out) # store 2 output blocks
2108 movups $inout1,16*1($out)
2109 lea 16*2($out),$out # $out+=2*16
2114 movups ($inp),$inout0
2115 movups 16*1($inp),$inout1
2116 movups 16*2($inp),$inout2
2117 lea 16*3($inp),$inp # $inp+=3*16
2118 xorps @tweak[0],$inout0
2119 xorps @tweak[1],$inout1
2120 xorps @tweak[2],$inout2
2122 call _aesni_encrypt3
2124 xorps @tweak[0],$inout0
2125 movdqa @tweak[3],@tweak[0]
2126 xorps @tweak[1],$inout1
2127 xorps @tweak[2],$inout2
2128 movups $inout0,($out) # store 3 output blocks
2129 movups $inout1,16*1($out)
2130 movups $inout2,16*2($out)
2131 lea 16*3($out),$out # $out+=3*16
2136 movups ($inp),$inout0
2137 movups 16*1($inp),$inout1
2138 movups 16*2($inp),$inout2
2139 xorps @tweak[0],$inout0
2140 movups 16*3($inp),$inout3
2141 lea 16*4($inp),$inp # $inp+=4*16
2142 xorps @tweak[1],$inout1
2143 xorps @tweak[2],$inout2
2144 xorps @tweak[3],$inout3
2146 call _aesni_encrypt4
2148 pxor @tweak[0],$inout0
2149 movdqa @tweak[4],@tweak[0]
2150 pxor @tweak[1],$inout1
2151 pxor @tweak[2],$inout2
2152 movdqu $inout0,($out) # store 4 output blocks
2153 pxor @tweak[3],$inout3
2154 movdqu $inout1,16*1($out)
2155 movdqu $inout2,16*2($out)
2156 movdqu $inout3,16*3($out)
2157 lea 16*4($out),$out # $out+=4*16
2162 and \$15,$len_ # see if $len%16 is 0
2167 movzb ($inp),%eax # borrow $rounds ...
2168 movzb -16($out),%ecx # ... and $key
2176 sub $len_,$out # rewind $out
2177 mov $key_,$key # restore $key
2178 mov $rnds_,$rounds # restore $rounds
2180 movups -16($out),$inout0
2181 xorps @tweak[0],$inout0
2183 &aesni_generate1("enc",$key,$rounds);
2185 xorps @tweak[0],$inout0
2186 movups $inout0,-16($out)
2189 xorps %xmm0,%xmm0 # clear register bank
2196 $code.=<<___ if (!$win64);
2199 movaps %xmm0,0x00(%rsp) # clear stack
2201 movaps %xmm0,0x10(%rsp)
2203 movaps %xmm0,0x20(%rsp)
2205 movaps %xmm0,0x30(%rsp)
2207 movaps %xmm0,0x40(%rsp)
2209 movaps %xmm0,0x50(%rsp)
2211 movaps %xmm0,0x60(%rsp)
2215 $code.=<<___ if ($win64);
2216 movaps -0xa8(%r11),%xmm6
2217 movaps %xmm0,-0xa8(%r11) # clear stack
2218 movaps -0x98(%r11),%xmm7
2219 movaps %xmm0,-0x98(%r11)
2220 movaps -0x88(%r11),%xmm8
2221 movaps %xmm0,-0x88(%r11)
2222 movaps -0x78(%r11),%xmm9
2223 movaps %xmm0,-0x78(%r11)
2224 movaps -0x68(%r11),%xmm10
2225 movaps %xmm0,-0x68(%r11)
2226 movaps -0x58(%r11),%xmm11
2227 movaps %xmm0,-0x58(%r11)
2228 movaps -0x48(%r11),%xmm12
2229 movaps %xmm0,-0x48(%r11)
2230 movaps -0x38(%r11),%xmm13
2231 movaps %xmm0,-0x38(%r11)
2232 movaps -0x28(%r11),%xmm14
2233 movaps %xmm0,-0x28(%r11)
2234 movaps -0x18(%r11),%xmm15
2235 movaps %xmm0,-0x18(%r11)
2236 movaps %xmm0,0x00(%rsp)
2237 movaps %xmm0,0x10(%rsp)
2238 movaps %xmm0,0x20(%rsp)
2239 movaps %xmm0,0x30(%rsp)
2240 movaps %xmm0,0x40(%rsp)
2241 movaps %xmm0,0x50(%rsp)
2242 movaps %xmm0,0x60(%rsp)
2248 .cfi_def_cfa_register %rsp
2252 .size aesni_xts_encrypt,.-aesni_xts_encrypt
2256 .globl aesni_xts_decrypt
2257 .type aesni_xts_decrypt,\@function,6
2261 lea (%rsp),%r11 # frame pointer
2262 .cfi_def_cfa_register %r11
2265 sub \$$frame_size,%rsp
2266 and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
2268 $code.=<<___ if ($win64);
2269 movaps %xmm6,-0xa8(%r11) # offload everything
2270 movaps %xmm7,-0x98(%r11)
2271 movaps %xmm8,-0x88(%r11)
2272 movaps %xmm9,-0x78(%r11)
2273 movaps %xmm10,-0x68(%r11)
2274 movaps %xmm11,-0x58(%r11)
2275 movaps %xmm12,-0x48(%r11)
2276 movaps %xmm13,-0x38(%r11)
2277 movaps %xmm14,-0x28(%r11)
2278 movaps %xmm15,-0x18(%r11)
2282 movups ($ivp),$inout0 # load clear-text tweak
2283 mov 240($key2),$rounds # key2->rounds
2284 mov 240($key),$rnds_ # key1->rounds
2286 # generate the tweak
2287 &aesni_generate1("enc",$key2,$rounds,$inout0);
2289 xor %eax,%eax # if ($len%16) len-=16;
2295 $movkey ($key),$rndkey0 # zero round key
2296 mov $key,$key_ # backup $key
2297 mov $rnds_,$rounds # backup $rounds
2299 mov $len,$len_ # backup $len
2302 $movkey 16($key,$rnds_),$rndkey1 # last round key
2304 movdqa .Lxts_magic(%rip),$twmask
2305 movdqa $inout0,@tweak[5]
2306 pshufd \$0x5f,$inout0,$twres
2307 pxor $rndkey0,$rndkey1
2309 for ($i=0;$i<4;$i++) {
2311 movdqa $twres,$twtmp
2313 movdqa @tweak[5],@tweak[$i]
2314 psrad \$31,$twtmp # broadcast upper bits
2315 paddq @tweak[5],@tweak[5]
2317 pxor $rndkey0,@tweak[$i]
2318 pxor $twtmp,@tweak[5]
2322 movdqa @tweak[5],@tweak[4]
2324 paddq @tweak[5],@tweak[5]
2326 pxor $rndkey0,@tweak[4]
2327 pxor $twres,@tweak[5]
2328 movaps $rndkey1,0x60(%rsp) # save round[0]^round[last]
2331 jc .Lxts_dec_short # if $len-=6*16 borrowed
2334 lea 32($key_,$rnds_),$key # end of key schedule
2335 sub %r10,%rax # twisted $rounds
2336 $movkey 16($key_),$rndkey1
2337 mov %rax,%r10 # backup twisted $rounds
2338 lea .Lxts_magic(%rip),%r8
2339 jmp .Lxts_dec_grandloop
2342 .Lxts_dec_grandloop:
2343 movdqu `16*0`($inp),$inout0 # load input
2344 movdqa $rndkey0,$twmask
2345 movdqu `16*1`($inp),$inout1
2346 pxor @tweak[0],$inout0 # intput^=tweak^round[0]
2347 movdqu `16*2`($inp),$inout2
2348 pxor @tweak[1],$inout1
2349 aesdec $rndkey1,$inout0
2350 movdqu `16*3`($inp),$inout3
2351 pxor @tweak[2],$inout2
2352 aesdec $rndkey1,$inout1
2353 movdqu `16*4`($inp),$inout4
2354 pxor @tweak[3],$inout3
2355 aesdec $rndkey1,$inout2
2356 movdqu `16*5`($inp),$inout5
2357 pxor @tweak[5],$twmask # round[0]^=tweak[5]
2358 movdqa 0x60(%rsp),$twres # load round[0]^round[last]
2359 pxor @tweak[4],$inout4
2360 aesdec $rndkey1,$inout3
2361 $movkey 32($key_),$rndkey0
2362 lea `16*6`($inp),$inp
2363 pxor $twmask,$inout5
2365 pxor $twres,@tweak[0] # calculate tweaks^round[last]
2366 aesdec $rndkey1,$inout4
2367 pxor $twres,@tweak[1]
2368 movdqa @tweak[0],`16*0`(%rsp) # put aside tweaks^last round key
2369 aesdec $rndkey1,$inout5
2370 $movkey 48($key_),$rndkey1
2371 pxor $twres,@tweak[2]
2373 aesdec $rndkey0,$inout0
2374 pxor $twres,@tweak[3]
2375 movdqa @tweak[1],`16*1`(%rsp)
2376 aesdec $rndkey0,$inout1
2377 pxor $twres,@tweak[4]
2378 movdqa @tweak[2],`16*2`(%rsp)
2379 aesdec $rndkey0,$inout2
2380 aesdec $rndkey0,$inout3
2382 movdqa @tweak[4],`16*4`(%rsp)
2383 aesdec $rndkey0,$inout4
2384 aesdec $rndkey0,$inout5
2385 $movkey 64($key_),$rndkey0
2386 movdqa $twmask,`16*5`(%rsp)
2387 pshufd \$0x5f,@tweak[5],$twres
2391 aesdec $rndkey1,$inout0
2392 aesdec $rndkey1,$inout1
2393 aesdec $rndkey1,$inout2
2394 aesdec $rndkey1,$inout3
2395 aesdec $rndkey1,$inout4
2396 aesdec $rndkey1,$inout5
2397 $movkey -64($key,%rax),$rndkey1
2400 aesdec $rndkey0,$inout0
2401 aesdec $rndkey0,$inout1
2402 aesdec $rndkey0,$inout2
2403 aesdec $rndkey0,$inout3
2404 aesdec $rndkey0,$inout4
2405 aesdec $rndkey0,$inout5
2406 $movkey -80($key,%rax),$rndkey0
2409 movdqa (%r8),$twmask # start calculating next tweak
2410 movdqa $twres,$twtmp
2412 aesdec $rndkey1,$inout0
2413 paddq @tweak[5],@tweak[5]
2415 aesdec $rndkey1,$inout1
2417 $movkey ($key_),@tweak[0] # load round[0]
2418 aesdec $rndkey1,$inout2
2419 aesdec $rndkey1,$inout3
2420 aesdec $rndkey1,$inout4
2421 pxor $twtmp,@tweak[5]
2422 movaps @tweak[0],@tweak[1] # copy round[0]
2423 aesdec $rndkey1,$inout5
2424 $movkey -64($key),$rndkey1
2426 movdqa $twres,$twtmp
2427 aesdec $rndkey0,$inout0
2429 pxor @tweak[5],@tweak[0]
2430 aesdec $rndkey0,$inout1
2432 paddq @tweak[5],@tweak[5]
2433 aesdec $rndkey0,$inout2
2434 aesdec $rndkey0,$inout3
2436 movaps @tweak[1],@tweak[2]
2437 aesdec $rndkey0,$inout4
2438 pxor $twtmp,@tweak[5]
2439 movdqa $twres,$twtmp
2440 aesdec $rndkey0,$inout5
2441 $movkey -48($key),$rndkey0
2444 aesdec $rndkey1,$inout0
2445 pxor @tweak[5],@tweak[1]
2447 aesdec $rndkey1,$inout1
2448 paddq @tweak[5],@tweak[5]
2450 aesdec $rndkey1,$inout2
2451 aesdec $rndkey1,$inout3
2452 movdqa @tweak[3],`16*3`(%rsp)
2453 pxor $twtmp,@tweak[5]
2454 aesdec $rndkey1,$inout4
2455 movaps @tweak[2],@tweak[3]
2456 movdqa $twres,$twtmp
2457 aesdec $rndkey1,$inout5
2458 $movkey -32($key),$rndkey1
2461 aesdec $rndkey0,$inout0
2462 pxor @tweak[5],@tweak[2]
2464 aesdec $rndkey0,$inout1
2465 paddq @tweak[5],@tweak[5]
2467 aesdec $rndkey0,$inout2
2468 aesdec $rndkey0,$inout3
2469 aesdec $rndkey0,$inout4
2470 pxor $twtmp,@tweak[5]
2471 movaps @tweak[3],@tweak[4]
2472 aesdec $rndkey0,$inout5
2474 movdqa $twres,$rndkey0
2476 aesdec $rndkey1,$inout0
2477 pxor @tweak[5],@tweak[3]
2479 aesdec $rndkey1,$inout1
2480 paddq @tweak[5],@tweak[5]
2481 pand $twmask,$rndkey0
2482 aesdec $rndkey1,$inout2
2483 aesdec $rndkey1,$inout3
2484 pxor $rndkey0,@tweak[5]
2485 $movkey ($key_),$rndkey0
2486 aesdec $rndkey1,$inout4
2487 aesdec $rndkey1,$inout5
2488 $movkey 16($key_),$rndkey1
2490 pxor @tweak[5],@tweak[4]
2491 aesdeclast `16*0`(%rsp),$inout0
2493 paddq @tweak[5],@tweak[5]
2494 aesdeclast `16*1`(%rsp),$inout1
2495 aesdeclast `16*2`(%rsp),$inout2
2497 mov %r10,%rax # restore $rounds
2498 aesdeclast `16*3`(%rsp),$inout3
2499 aesdeclast `16*4`(%rsp),$inout4
2500 aesdeclast `16*5`(%rsp),$inout5
2501 pxor $twres,@tweak[5]
2503 lea `16*6`($out),$out # $out+=6*16
2504 movups $inout0,`-16*6`($out) # store 6 output blocks
2505 movups $inout1,`-16*5`($out)
2506 movups $inout2,`-16*4`($out)
2507 movups $inout3,`-16*3`($out)
2508 movups $inout4,`-16*2`($out)
2509 movups $inout5,`-16*1`($out)
2511 jnc .Lxts_dec_grandloop # loop if $len-=6*16 didn't borrow
2515 mov $key_,$key # restore $key
2516 shr \$4,$rounds # restore original value
2519 # at the point @tweak[0..5] are populated with tweak values
2520 mov $rounds,$rnds_ # backup $rounds
2521 pxor $rndkey0,@tweak[0]
2522 pxor $rndkey0,@tweak[1]
2523 add \$16*6,$len # restore real remaining $len
2524 jz .Lxts_dec_done # done if ($len==0)
2526 pxor $rndkey0,@tweak[2]
2528 jb .Lxts_dec_one # $len is 1*16
2529 pxor $rndkey0,@tweak[3]
2530 je .Lxts_dec_two # $len is 2*16
2532 pxor $rndkey0,@tweak[4]
2534 jb .Lxts_dec_three # $len is 3*16
2535 je .Lxts_dec_four # $len is 4*16
2537 movdqu ($inp),$inout0 # $len is 5*16
2538 movdqu 16*1($inp),$inout1
2539 movdqu 16*2($inp),$inout2
2540 pxor @tweak[0],$inout0
2541 movdqu 16*3($inp),$inout3
2542 pxor @tweak[1],$inout1
2543 movdqu 16*4($inp),$inout4
2544 lea 16*5($inp),$inp # $inp+=5*16
2545 pxor @tweak[2],$inout2
2546 pxor @tweak[3],$inout3
2547 pxor @tweak[4],$inout4
2549 call _aesni_decrypt6
2551 xorps @tweak[0],$inout0
2552 xorps @tweak[1],$inout1
2553 xorps @tweak[2],$inout2
2554 movdqu $inout0,($out) # store 5 output blocks
2555 xorps @tweak[3],$inout3
2556 movdqu $inout1,16*1($out)
2557 xorps @tweak[4],$inout4
2558 movdqu $inout2,16*2($out)
2560 movdqu $inout3,16*3($out)
2561 pcmpgtd @tweak[5],$twtmp
2562 movdqu $inout4,16*4($out)
2563 lea 16*5($out),$out # $out+=5*16
2564 pshufd \$0x13,$twtmp,@tweak[1] # $twres
2568 movdqa @tweak[5],@tweak[0]
2569 paddq @tweak[5],@tweak[5] # psllq 1,$tweak
2570 pand $twmask,@tweak[1] # isolate carry and residue
2571 pxor @tweak[5],@tweak[1]
2576 movups ($inp),$inout0
2577 lea 16*1($inp),$inp # $inp+=1*16
2578 xorps @tweak[0],$inout0
2580 &aesni_generate1("dec",$key,$rounds);
2582 xorps @tweak[0],$inout0
2583 movdqa @tweak[1],@tweak[0]
2584 movups $inout0,($out) # store one output block
2585 movdqa @tweak[2],@tweak[1]
2586 lea 16*1($out),$out # $out+=1*16
2591 movups ($inp),$inout0
2592 movups 16($inp),$inout1
2593 lea 32($inp),$inp # $inp+=2*16
2594 xorps @tweak[0],$inout0
2595 xorps @tweak[1],$inout1
2597 call _aesni_decrypt2
2599 xorps @tweak[0],$inout0
2600 movdqa @tweak[2],@tweak[0]
2601 xorps @tweak[1],$inout1
2602 movdqa @tweak[3],@tweak[1]
2603 movups $inout0,($out) # store 2 output blocks
2604 movups $inout1,16*1($out)
2605 lea 16*2($out),$out # $out+=2*16
2610 movups ($inp),$inout0
2611 movups 16*1($inp),$inout1
2612 movups 16*2($inp),$inout2
2613 lea 16*3($inp),$inp # $inp+=3*16
2614 xorps @tweak[0],$inout0
2615 xorps @tweak[1],$inout1
2616 xorps @tweak[2],$inout2
2618 call _aesni_decrypt3
2620 xorps @tweak[0],$inout0
2621 movdqa @tweak[3],@tweak[0]
2622 xorps @tweak[1],$inout1
2623 movdqa @tweak[4],@tweak[1]
2624 xorps @tweak[2],$inout2
2625 movups $inout0,($out) # store 3 output blocks
2626 movups $inout1,16*1($out)
2627 movups $inout2,16*2($out)
2628 lea 16*3($out),$out # $out+=3*16
2633 movups ($inp),$inout0
2634 movups 16*1($inp),$inout1
2635 movups 16*2($inp),$inout2
2636 xorps @tweak[0],$inout0
2637 movups 16*3($inp),$inout3
2638 lea 16*4($inp),$inp # $inp+=4*16
2639 xorps @tweak[1],$inout1
2640 xorps @tweak[2],$inout2
2641 xorps @tweak[3],$inout3
2643 call _aesni_decrypt4
2645 pxor @tweak[0],$inout0
2646 movdqa @tweak[4],@tweak[0]
2647 pxor @tweak[1],$inout1
2648 movdqa @tweak[5],@tweak[1]
2649 pxor @tweak[2],$inout2
2650 movdqu $inout0,($out) # store 4 output blocks
2651 pxor @tweak[3],$inout3
2652 movdqu $inout1,16*1($out)
2653 movdqu $inout2,16*2($out)
2654 movdqu $inout3,16*3($out)
2655 lea 16*4($out),$out # $out+=4*16
2660 and \$15,$len_ # see if $len%16 is 0
2664 mov $key_,$key # restore $key
2665 mov $rnds_,$rounds # restore $rounds
2667 movups ($inp),$inout0
2668 xorps @tweak[1],$inout0
2670 &aesni_generate1("dec",$key,$rounds);
2672 xorps @tweak[1],$inout0
2673 movups $inout0,($out)
2676 movzb 16($inp),%eax # borrow $rounds ...
2677 movzb ($out),%ecx # ... and $key
2685 sub $len_,$out # rewind $out
2686 mov $key_,$key # restore $key
2687 mov $rnds_,$rounds # restore $rounds
2689 movups ($out),$inout0
2690 xorps @tweak[0],$inout0
2692 &aesni_generate1("dec",$key,$rounds);
2694 xorps @tweak[0],$inout0
2695 movups $inout0,($out)
2698 xorps %xmm0,%xmm0 # clear register bank
2705 $code.=<<___ if (!$win64);
2708 movaps %xmm0,0x00(%rsp) # clear stack
2710 movaps %xmm0,0x10(%rsp)
2712 movaps %xmm0,0x20(%rsp)
2714 movaps %xmm0,0x30(%rsp)
2716 movaps %xmm0,0x40(%rsp)
2718 movaps %xmm0,0x50(%rsp)
2720 movaps %xmm0,0x60(%rsp)
2724 $code.=<<___ if ($win64);
2725 movaps -0xa8(%r11),%xmm6
2726 movaps %xmm0,-0xa8(%r11) # clear stack
2727 movaps -0x98(%r11),%xmm7
2728 movaps %xmm0,-0x98(%r11)
2729 movaps -0x88(%r11),%xmm8
2730 movaps %xmm0,-0x88(%r11)
2731 movaps -0x78(%r11),%xmm9
2732 movaps %xmm0,-0x78(%r11)
2733 movaps -0x68(%r11),%xmm10
2734 movaps %xmm0,-0x68(%r11)
2735 movaps -0x58(%r11),%xmm11
2736 movaps %xmm0,-0x58(%r11)
2737 movaps -0x48(%r11),%xmm12
2738 movaps %xmm0,-0x48(%r11)
2739 movaps -0x38(%r11),%xmm13
2740 movaps %xmm0,-0x38(%r11)
2741 movaps -0x28(%r11),%xmm14
2742 movaps %xmm0,-0x28(%r11)
2743 movaps -0x18(%r11),%xmm15
2744 movaps %xmm0,-0x18(%r11)
2745 movaps %xmm0,0x00(%rsp)
2746 movaps %xmm0,0x10(%rsp)
2747 movaps %xmm0,0x20(%rsp)
2748 movaps %xmm0,0x30(%rsp)
2749 movaps %xmm0,0x40(%rsp)
2750 movaps %xmm0,0x50(%rsp)
2751 movaps %xmm0,0x60(%rsp)
2757 .cfi_def_cfa_register %rsp
2761 .size aesni_xts_decrypt,.-aesni_xts_decrypt
2765 ######################################################################
2766 # void aesni_ocb_[en|de]crypt(const char *inp, char *out, size_t blocks,
2767 # const AES_KEY *key, unsigned int start_block_num,
2768 # unsigned char offset_i[16], const unsigned char L_[][16],
2769 # unsigned char checksum[16]);
2772 my @offset=map("%xmm$_",(10..15));
2773 my ($checksum,$rndkey0l)=("%xmm8","%xmm9");
2774 my ($block_num,$offset_p)=("%r8","%r9"); # 5th and 6th arguments
2775 my ($L_p,$checksum_p) = ("%rbx","%rbp");
2776 my ($i1,$i3,$i5) = ("%r12","%r13","%r14");
2777 my $seventh_arg = $win64 ? 56 : 8;
2781 .globl aesni_ocb_encrypt
2782 .type aesni_ocb_encrypt,\@function,6
2798 $code.=<<___ if ($win64);
2799 lea -0xa0(%rsp),%rsp
2800 movaps %xmm6,0x00(%rsp) # offload everything
2801 movaps %xmm7,0x10(%rsp)
2802 movaps %xmm8,0x20(%rsp)
2803 movaps %xmm9,0x30(%rsp)
2804 movaps %xmm10,0x40(%rsp)
2805 movaps %xmm11,0x50(%rsp)
2806 movaps %xmm12,0x60(%rsp)
2807 movaps %xmm13,0x70(%rsp)
2808 movaps %xmm14,0x80(%rsp)
2809 movaps %xmm15,0x90(%rsp)
2813 mov $seventh_arg(%rax),$L_p # 7th argument
2814 mov $seventh_arg+8(%rax),$checksum_p# 8th argument
2816 mov 240($key),$rnds_
2819 $movkey ($key),$rndkey0l # round[0]
2820 $movkey 16($key,$rnds_),$rndkey1 # round[last]
2822 movdqu ($offset_p),@offset[5] # load last offset_i
2823 pxor $rndkey1,$rndkey0l # round[0] ^ round[last]
2824 pxor $rndkey1,@offset[5] # offset_i ^ round[last]
2827 lea 32($key_,$rnds_),$key
2828 $movkey 16($key_),$rndkey1 # round[1]
2829 sub %r10,%rax # twisted $rounds
2830 mov %rax,%r10 # backup twisted $rounds
2832 movdqu ($L_p),@offset[0] # L_0 for all odd-numbered blocks
2833 movdqu ($checksum_p),$checksum # load checksum
2835 test \$1,$block_num # is first block number odd?
2841 movdqu ($L_p,$i1),$inout5 # borrow
2842 movdqu ($inp),$inout0
2847 movdqa $inout5,@offset[5]
2848 movups $inout0,($out)
2854 lea 1($block_num),$i1 # even-numbered blocks
2855 lea 3($block_num),$i3
2856 lea 5($block_num),$i5
2857 lea 6($block_num),$block_num
2858 bsf $i1,$i1 # ntz(block)
2861 shl \$4,$i1 # ntz(block) -> table offset
2867 jmp .Locb_enc_grandloop
2870 .Locb_enc_grandloop:
2871 movdqu `16*0`($inp),$inout0 # load input
2872 movdqu `16*1`($inp),$inout1
2873 movdqu `16*2`($inp),$inout2
2874 movdqu `16*3`($inp),$inout3
2875 movdqu `16*4`($inp),$inout4
2876 movdqu `16*5`($inp),$inout5
2877 lea `16*6`($inp),$inp
2881 movups $inout0,`16*0`($out) # store output
2882 movups $inout1,`16*1`($out)
2883 movups $inout2,`16*2`($out)
2884 movups $inout3,`16*3`($out)
2885 movups $inout4,`16*4`($out)
2886 movups $inout5,`16*5`($out)
2887 lea `16*6`($out),$out
2889 jnc .Locb_enc_grandloop
2895 movdqu `16*0`($inp),$inout0
2898 movdqu `16*1`($inp),$inout1
2901 movdqu `16*2`($inp),$inout2
2904 movdqu `16*3`($inp),$inout3
2907 movdqu `16*4`($inp),$inout4
2908 pxor $inout5,$inout5
2912 movdqa @offset[4],@offset[5]
2913 movups $inout0,`16*0`($out)
2914 movups $inout1,`16*1`($out)
2915 movups $inout2,`16*2`($out)
2916 movups $inout3,`16*3`($out)
2917 movups $inout4,`16*4`($out)
2923 movdqa @offset[0],$inout5 # borrow
2927 movdqa $inout5,@offset[5]
2928 movups $inout0,`16*0`($out)
2933 pxor $inout2,$inout2
2934 pxor $inout3,$inout3
2938 movdqa @offset[1],@offset[5]
2939 movups $inout0,`16*0`($out)
2940 movups $inout1,`16*1`($out)
2946 pxor $inout3,$inout3
2950 movdqa @offset[2],@offset[5]
2951 movups $inout0,`16*0`($out)
2952 movups $inout1,`16*1`($out)
2953 movups $inout2,`16*2`($out)
2961 movdqa @offset[3],@offset[5]
2962 movups $inout0,`16*0`($out)
2963 movups $inout1,`16*1`($out)
2964 movups $inout2,`16*2`($out)
2965 movups $inout3,`16*3`($out)
2968 pxor $rndkey0,@offset[5] # "remove" round[last]
2969 movdqu $checksum,($checksum_p) # store checksum
2970 movdqu @offset[5],($offset_p) # store last offset_i
2972 xorps %xmm0,%xmm0 # clear register bank
2979 $code.=<<___ if (!$win64);
2993 $code.=<<___ if ($win64);
2994 movaps 0x00(%rsp),%xmm6
2995 movaps %xmm0,0x00(%rsp) # clear stack
2996 movaps 0x10(%rsp),%xmm7
2997 movaps %xmm0,0x10(%rsp)
2998 movaps 0x20(%rsp),%xmm8
2999 movaps %xmm0,0x20(%rsp)
3000 movaps 0x30(%rsp),%xmm9
3001 movaps %xmm0,0x30(%rsp)
3002 movaps 0x40(%rsp),%xmm10
3003 movaps %xmm0,0x40(%rsp)
3004 movaps 0x50(%rsp),%xmm11
3005 movaps %xmm0,0x50(%rsp)
3006 movaps 0x60(%rsp),%xmm12
3007 movaps %xmm0,0x60(%rsp)
3008 movaps 0x70(%rsp),%xmm13
3009 movaps %xmm0,0x70(%rsp)
3010 movaps 0x80(%rsp),%xmm14
3011 movaps %xmm0,0x80(%rsp)
3012 movaps 0x90(%rsp),%xmm15
3013 movaps %xmm0,0x90(%rsp)
3014 lea 0xa0+0x28(%rsp),%rax
3029 .cfi_def_cfa_register %rsp
3033 .size aesni_ocb_encrypt,.-aesni_ocb_encrypt
3035 .type __ocb_encrypt6,\@abi-omnipotent
3039 pxor $rndkey0l,@offset[5] # offset_i ^ round[0]
3040 movdqu ($L_p,$i1),@offset[1]
3041 movdqa @offset[0],@offset[2]
3042 movdqu ($L_p,$i3),@offset[3]
3043 movdqa @offset[0],@offset[4]
3044 pxor @offset[5],@offset[0]
3045 movdqu ($L_p,$i5),@offset[5]
3046 pxor @offset[0],@offset[1]
3047 pxor $inout0,$checksum # accumulate checksum
3048 pxor @offset[0],$inout0 # input ^ round[0] ^ offset_i
3049 pxor @offset[1],@offset[2]
3050 pxor $inout1,$checksum
3051 pxor @offset[1],$inout1
3052 pxor @offset[2],@offset[3]
3053 pxor $inout2,$checksum
3054 pxor @offset[2],$inout2
3055 pxor @offset[3],@offset[4]
3056 pxor $inout3,$checksum
3057 pxor @offset[3],$inout3
3058 pxor @offset[4],@offset[5]
3059 pxor $inout4,$checksum
3060 pxor @offset[4],$inout4
3061 pxor $inout5,$checksum
3062 pxor @offset[5],$inout5
3063 $movkey 32($key_),$rndkey0
3065 lea 1($block_num),$i1 # even-numbered blocks
3066 lea 3($block_num),$i3
3067 lea 5($block_num),$i5
3069 pxor $rndkey0l,@offset[0] # offset_i ^ round[last]
3070 bsf $i1,$i1 # ntz(block)
3074 aesenc $rndkey1,$inout0
3075 aesenc $rndkey1,$inout1
3076 aesenc $rndkey1,$inout2
3077 aesenc $rndkey1,$inout3
3078 pxor $rndkey0l,@offset[1]
3079 pxor $rndkey0l,@offset[2]
3080 aesenc $rndkey1,$inout4
3081 pxor $rndkey0l,@offset[3]
3082 pxor $rndkey0l,@offset[4]
3083 aesenc $rndkey1,$inout5
3084 $movkey 48($key_),$rndkey1
3085 pxor $rndkey0l,@offset[5]
3087 aesenc $rndkey0,$inout0
3088 aesenc $rndkey0,$inout1
3089 aesenc $rndkey0,$inout2
3090 aesenc $rndkey0,$inout3
3091 aesenc $rndkey0,$inout4
3092 aesenc $rndkey0,$inout5
3093 $movkey 64($key_),$rndkey0
3094 shl \$4,$i1 # ntz(block) -> table offset
3100 aesenc $rndkey1,$inout0
3101 aesenc $rndkey1,$inout1
3102 aesenc $rndkey1,$inout2
3103 aesenc $rndkey1,$inout3
3104 aesenc $rndkey1,$inout4
3105 aesenc $rndkey1,$inout5
3106 $movkey ($key,%rax),$rndkey1
3109 aesenc $rndkey0,$inout0
3110 aesenc $rndkey0,$inout1
3111 aesenc $rndkey0,$inout2
3112 aesenc $rndkey0,$inout3
3113 aesenc $rndkey0,$inout4
3114 aesenc $rndkey0,$inout5
3115 $movkey -16($key,%rax),$rndkey0
3118 aesenc $rndkey1,$inout0
3119 aesenc $rndkey1,$inout1
3120 aesenc $rndkey1,$inout2
3121 aesenc $rndkey1,$inout3
3122 aesenc $rndkey1,$inout4
3123 aesenc $rndkey1,$inout5
3124 $movkey 16($key_),$rndkey1
3127 aesenclast @offset[0],$inout0
3128 movdqu ($L_p),@offset[0] # L_0 for all odd-numbered blocks
3129 mov %r10,%rax # restore twisted rounds
3130 aesenclast @offset[1],$inout1
3131 aesenclast @offset[2],$inout2
3132 aesenclast @offset[3],$inout3
3133 aesenclast @offset[4],$inout4
3134 aesenclast @offset[5],$inout5
3137 .size __ocb_encrypt6,.-__ocb_encrypt6
3139 .type __ocb_encrypt4,\@abi-omnipotent
3143 pxor $rndkey0l,@offset[5] # offset_i ^ round[0]
3144 movdqu ($L_p,$i1),@offset[1]
3145 movdqa @offset[0],@offset[2]
3146 movdqu ($L_p,$i3),@offset[3]
3147 pxor @offset[5],@offset[0]
3148 pxor @offset[0],@offset[1]
3149 pxor $inout0,$checksum # accumulate checksum
3150 pxor @offset[0],$inout0 # input ^ round[0] ^ offset_i
3151 pxor @offset[1],@offset[2]
3152 pxor $inout1,$checksum
3153 pxor @offset[1],$inout1
3154 pxor @offset[2],@offset[3]
3155 pxor $inout2,$checksum
3156 pxor @offset[2],$inout2
3157 pxor $inout3,$checksum
3158 pxor @offset[3],$inout3
3159 $movkey 32($key_),$rndkey0
3161 pxor $rndkey0l,@offset[0] # offset_i ^ round[last]
3162 pxor $rndkey0l,@offset[1]
3163 pxor $rndkey0l,@offset[2]
3164 pxor $rndkey0l,@offset[3]
3166 aesenc $rndkey1,$inout0
3167 aesenc $rndkey1,$inout1
3168 aesenc $rndkey1,$inout2
3169 aesenc $rndkey1,$inout3
3170 $movkey 48($key_),$rndkey1
3172 aesenc $rndkey0,$inout0
3173 aesenc $rndkey0,$inout1
3174 aesenc $rndkey0,$inout2
3175 aesenc $rndkey0,$inout3
3176 $movkey 64($key_),$rndkey0
3181 aesenc $rndkey1,$inout0
3182 aesenc $rndkey1,$inout1
3183 aesenc $rndkey1,$inout2
3184 aesenc $rndkey1,$inout3
3185 $movkey ($key,%rax),$rndkey1
3188 aesenc $rndkey0,$inout0
3189 aesenc $rndkey0,$inout1
3190 aesenc $rndkey0,$inout2
3191 aesenc $rndkey0,$inout3
3192 $movkey -16($key,%rax),$rndkey0
3195 aesenc $rndkey1,$inout0
3196 aesenc $rndkey1,$inout1
3197 aesenc $rndkey1,$inout2
3198 aesenc $rndkey1,$inout3
3199 $movkey 16($key_),$rndkey1
3200 mov %r10,%rax # restore twisted rounds
3202 aesenclast @offset[0],$inout0
3203 aesenclast @offset[1],$inout1
3204 aesenclast @offset[2],$inout2
3205 aesenclast @offset[3],$inout3
3208 .size __ocb_encrypt4,.-__ocb_encrypt4
3210 .type __ocb_encrypt1,\@abi-omnipotent
3214 pxor @offset[5],$inout5 # offset_i
3215 pxor $rndkey0l,$inout5 # offset_i ^ round[0]
3216 pxor $inout0,$checksum # accumulate checksum
3217 pxor $inout5,$inout0 # input ^ round[0] ^ offset_i
3218 $movkey 32($key_),$rndkey0
3220 aesenc $rndkey1,$inout0
3221 $movkey 48($key_),$rndkey1
3222 pxor $rndkey0l,$inout5 # offset_i ^ round[last]
3224 aesenc $rndkey0,$inout0
3225 $movkey 64($key_),$rndkey0
3230 aesenc $rndkey1,$inout0
3231 $movkey ($key,%rax),$rndkey1
3234 aesenc $rndkey0,$inout0
3235 $movkey -16($key,%rax),$rndkey0
3238 aesenc $rndkey1,$inout0
3239 $movkey 16($key_),$rndkey1 # redundant in tail
3240 mov %r10,%rax # restore twisted rounds
3242 aesenclast $inout5,$inout0
3245 .size __ocb_encrypt1,.-__ocb_encrypt1
3247 .globl aesni_ocb_decrypt
3248 .type aesni_ocb_decrypt,\@function,6
3264 $code.=<<___ if ($win64);
3265 lea -0xa0(%rsp),%rsp
3266 movaps %xmm6,0x00(%rsp) # offload everything
3267 movaps %xmm7,0x10(%rsp)
3268 movaps %xmm8,0x20(%rsp)
3269 movaps %xmm9,0x30(%rsp)
3270 movaps %xmm10,0x40(%rsp)
3271 movaps %xmm11,0x50(%rsp)
3272 movaps %xmm12,0x60(%rsp)
3273 movaps %xmm13,0x70(%rsp)
3274 movaps %xmm14,0x80(%rsp)
3275 movaps %xmm15,0x90(%rsp)
3279 mov $seventh_arg(%rax),$L_p # 7th argument
3280 mov $seventh_arg+8(%rax),$checksum_p# 8th argument
3282 mov 240($key),$rnds_
3285 $movkey ($key),$rndkey0l # round[0]
3286 $movkey 16($key,$rnds_),$rndkey1 # round[last]
3288 movdqu ($offset_p),@offset[5] # load last offset_i
3289 pxor $rndkey1,$rndkey0l # round[0] ^ round[last]
3290 pxor $rndkey1,@offset[5] # offset_i ^ round[last]
3293 lea 32($key_,$rnds_),$key
3294 $movkey 16($key_),$rndkey1 # round[1]
3295 sub %r10,%rax # twisted $rounds
3296 mov %rax,%r10 # backup twisted $rounds
3298 movdqu ($L_p),@offset[0] # L_0 for all odd-numbered blocks
3299 movdqu ($checksum_p),$checksum # load checksum
3301 test \$1,$block_num # is first block number odd?
3307 movdqu ($L_p,$i1),$inout5 # borrow
3308 movdqu ($inp),$inout0
3313 movdqa $inout5,@offset[5]
3314 movups $inout0,($out)
3315 xorps $inout0,$checksum # accumulate checksum
3321 lea 1($block_num),$i1 # even-numbered blocks
3322 lea 3($block_num),$i3
3323 lea 5($block_num),$i5
3324 lea 6($block_num),$block_num
3325 bsf $i1,$i1 # ntz(block)
3328 shl \$4,$i1 # ntz(block) -> table offset
3334 jmp .Locb_dec_grandloop
3337 .Locb_dec_grandloop:
3338 movdqu `16*0`($inp),$inout0 # load input
3339 movdqu `16*1`($inp),$inout1
3340 movdqu `16*2`($inp),$inout2
3341 movdqu `16*3`($inp),$inout3
3342 movdqu `16*4`($inp),$inout4
3343 movdqu `16*5`($inp),$inout5
3344 lea `16*6`($inp),$inp
3348 movups $inout0,`16*0`($out) # store output
3349 pxor $inout0,$checksum # accumulate checksum
3350 movups $inout1,`16*1`($out)
3351 pxor $inout1,$checksum
3352 movups $inout2,`16*2`($out)
3353 pxor $inout2,$checksum
3354 movups $inout3,`16*3`($out)
3355 pxor $inout3,$checksum
3356 movups $inout4,`16*4`($out)
3357 pxor $inout4,$checksum
3358 movups $inout5,`16*5`($out)
3359 pxor $inout5,$checksum
3360 lea `16*6`($out),$out
3362 jnc .Locb_dec_grandloop
3368 movdqu `16*0`($inp),$inout0
3371 movdqu `16*1`($inp),$inout1
3374 movdqu `16*2`($inp),$inout2
3377 movdqu `16*3`($inp),$inout3
3380 movdqu `16*4`($inp),$inout4
3381 pxor $inout5,$inout5
3385 movdqa @offset[4],@offset[5]
3386 movups $inout0,`16*0`($out) # store output
3387 pxor $inout0,$checksum # accumulate checksum
3388 movups $inout1,`16*1`($out)
3389 pxor $inout1,$checksum
3390 movups $inout2,`16*2`($out)
3391 pxor $inout2,$checksum
3392 movups $inout3,`16*3`($out)
3393 pxor $inout3,$checksum
3394 movups $inout4,`16*4`($out)
3395 pxor $inout4,$checksum
3401 movdqa @offset[0],$inout5 # borrow
3405 movdqa $inout5,@offset[5]
3406 movups $inout0,`16*0`($out) # store output
3407 xorps $inout0,$checksum # accumulate checksum
3412 pxor $inout2,$inout2
3413 pxor $inout3,$inout3
3417 movdqa @offset[1],@offset[5]
3418 movups $inout0,`16*0`($out) # store output
3419 xorps $inout0,$checksum # accumulate checksum
3420 movups $inout1,`16*1`($out)
3421 xorps $inout1,$checksum
3427 pxor $inout3,$inout3
3431 movdqa @offset[2],@offset[5]
3432 movups $inout0,`16*0`($out) # store output
3433 xorps $inout0,$checksum # accumulate checksum
3434 movups $inout1,`16*1`($out)
3435 xorps $inout1,$checksum
3436 movups $inout2,`16*2`($out)
3437 xorps $inout2,$checksum
3445 movdqa @offset[3],@offset[5]
3446 movups $inout0,`16*0`($out) # store output
3447 pxor $inout0,$checksum # accumulate checksum
3448 movups $inout1,`16*1`($out)
3449 pxor $inout1,$checksum
3450 movups $inout2,`16*2`($out)
3451 pxor $inout2,$checksum
3452 movups $inout3,`16*3`($out)
3453 pxor $inout3,$checksum
3456 pxor $rndkey0,@offset[5] # "remove" round[last]
3457 movdqu $checksum,($checksum_p) # store checksum
3458 movdqu @offset[5],($offset_p) # store last offset_i
3460 xorps %xmm0,%xmm0 # clear register bank
3467 $code.=<<___ if (!$win64);
3481 $code.=<<___ if ($win64);
3482 movaps 0x00(%rsp),%xmm6
3483 movaps %xmm0,0x00(%rsp) # clear stack
3484 movaps 0x10(%rsp),%xmm7
3485 movaps %xmm0,0x10(%rsp)
3486 movaps 0x20(%rsp),%xmm8
3487 movaps %xmm0,0x20(%rsp)
3488 movaps 0x30(%rsp),%xmm9
3489 movaps %xmm0,0x30(%rsp)
3490 movaps 0x40(%rsp),%xmm10
3491 movaps %xmm0,0x40(%rsp)
3492 movaps 0x50(%rsp),%xmm11
3493 movaps %xmm0,0x50(%rsp)
3494 movaps 0x60(%rsp),%xmm12
3495 movaps %xmm0,0x60(%rsp)
3496 movaps 0x70(%rsp),%xmm13
3497 movaps %xmm0,0x70(%rsp)
3498 movaps 0x80(%rsp),%xmm14
3499 movaps %xmm0,0x80(%rsp)
3500 movaps 0x90(%rsp),%xmm15
3501 movaps %xmm0,0x90(%rsp)
3502 lea 0xa0+0x28(%rsp),%rax
3517 .cfi_def_cfa_register %rsp
3521 .size aesni_ocb_decrypt,.-aesni_ocb_decrypt
3523 .type __ocb_decrypt6,\@abi-omnipotent
3527 pxor $rndkey0l,@offset[5] # offset_i ^ round[0]
3528 movdqu ($L_p,$i1),@offset[1]
3529 movdqa @offset[0],@offset[2]
3530 movdqu ($L_p,$i3),@offset[3]
3531 movdqa @offset[0],@offset[4]
3532 pxor @offset[5],@offset[0]
3533 movdqu ($L_p,$i5),@offset[5]
3534 pxor @offset[0],@offset[1]
3535 pxor @offset[0],$inout0 # input ^ round[0] ^ offset_i
3536 pxor @offset[1],@offset[2]
3537 pxor @offset[1],$inout1
3538 pxor @offset[2],@offset[3]
3539 pxor @offset[2],$inout2
3540 pxor @offset[3],@offset[4]
3541 pxor @offset[3],$inout3
3542 pxor @offset[4],@offset[5]
3543 pxor @offset[4],$inout4
3544 pxor @offset[5],$inout5
3545 $movkey 32($key_),$rndkey0
3547 lea 1($block_num),$i1 # even-numbered blocks
3548 lea 3($block_num),$i3
3549 lea 5($block_num),$i5
3551 pxor $rndkey0l,@offset[0] # offset_i ^ round[last]
3552 bsf $i1,$i1 # ntz(block)
3556 aesdec $rndkey1,$inout0
3557 aesdec $rndkey1,$inout1
3558 aesdec $rndkey1,$inout2
3559 aesdec $rndkey1,$inout3
3560 pxor $rndkey0l,@offset[1]
3561 pxor $rndkey0l,@offset[2]
3562 aesdec $rndkey1,$inout4
3563 pxor $rndkey0l,@offset[3]
3564 pxor $rndkey0l,@offset[4]
3565 aesdec $rndkey1,$inout5
3566 $movkey 48($key_),$rndkey1
3567 pxor $rndkey0l,@offset[5]
3569 aesdec $rndkey0,$inout0
3570 aesdec $rndkey0,$inout1
3571 aesdec $rndkey0,$inout2
3572 aesdec $rndkey0,$inout3
3573 aesdec $rndkey0,$inout4
3574 aesdec $rndkey0,$inout5
3575 $movkey 64($key_),$rndkey0
3576 shl \$4,$i1 # ntz(block) -> table offset
3582 aesdec $rndkey1,$inout0
3583 aesdec $rndkey1,$inout1
3584 aesdec $rndkey1,$inout2
3585 aesdec $rndkey1,$inout3
3586 aesdec $rndkey1,$inout4
3587 aesdec $rndkey1,$inout5
3588 $movkey ($key,%rax),$rndkey1
3591 aesdec $rndkey0,$inout0
3592 aesdec $rndkey0,$inout1
3593 aesdec $rndkey0,$inout2
3594 aesdec $rndkey0,$inout3
3595 aesdec $rndkey0,$inout4
3596 aesdec $rndkey0,$inout5
3597 $movkey -16($key,%rax),$rndkey0
3600 aesdec $rndkey1,$inout0
3601 aesdec $rndkey1,$inout1
3602 aesdec $rndkey1,$inout2
3603 aesdec $rndkey1,$inout3
3604 aesdec $rndkey1,$inout4
3605 aesdec $rndkey1,$inout5
3606 $movkey 16($key_),$rndkey1
3609 aesdeclast @offset[0],$inout0
3610 movdqu ($L_p),@offset[0] # L_0 for all odd-numbered blocks
3611 mov %r10,%rax # restore twisted rounds
3612 aesdeclast @offset[1],$inout1
3613 aesdeclast @offset[2],$inout2
3614 aesdeclast @offset[3],$inout3
3615 aesdeclast @offset[4],$inout4
3616 aesdeclast @offset[5],$inout5
3619 .size __ocb_decrypt6,.-__ocb_decrypt6
3621 .type __ocb_decrypt4,\@abi-omnipotent
3625 pxor $rndkey0l,@offset[5] # offset_i ^ round[0]
3626 movdqu ($L_p,$i1),@offset[1]
3627 movdqa @offset[0],@offset[2]
3628 movdqu ($L_p,$i3),@offset[3]
3629 pxor @offset[5],@offset[0]
3630 pxor @offset[0],@offset[1]
3631 pxor @offset[0],$inout0 # input ^ round[0] ^ offset_i
3632 pxor @offset[1],@offset[2]
3633 pxor @offset[1],$inout1
3634 pxor @offset[2],@offset[3]
3635 pxor @offset[2],$inout2
3636 pxor @offset[3],$inout3
3637 $movkey 32($key_),$rndkey0
3639 pxor $rndkey0l,@offset[0] # offset_i ^ round[last]
3640 pxor $rndkey0l,@offset[1]
3641 pxor $rndkey0l,@offset[2]
3642 pxor $rndkey0l,@offset[3]
3644 aesdec $rndkey1,$inout0
3645 aesdec $rndkey1,$inout1
3646 aesdec $rndkey1,$inout2
3647 aesdec $rndkey1,$inout3
3648 $movkey 48($key_),$rndkey1
3650 aesdec $rndkey0,$inout0
3651 aesdec $rndkey0,$inout1
3652 aesdec $rndkey0,$inout2
3653 aesdec $rndkey0,$inout3
3654 $movkey 64($key_),$rndkey0
3659 aesdec $rndkey1,$inout0
3660 aesdec $rndkey1,$inout1
3661 aesdec $rndkey1,$inout2
3662 aesdec $rndkey1,$inout3
3663 $movkey ($key,%rax),$rndkey1
3666 aesdec $rndkey0,$inout0
3667 aesdec $rndkey0,$inout1
3668 aesdec $rndkey0,$inout2
3669 aesdec $rndkey0,$inout3
3670 $movkey -16($key,%rax),$rndkey0
3673 aesdec $rndkey1,$inout0
3674 aesdec $rndkey1,$inout1
3675 aesdec $rndkey1,$inout2
3676 aesdec $rndkey1,$inout3
3677 $movkey 16($key_),$rndkey1
3678 mov %r10,%rax # restore twisted rounds
3680 aesdeclast @offset[0],$inout0
3681 aesdeclast @offset[1],$inout1
3682 aesdeclast @offset[2],$inout2
3683 aesdeclast @offset[3],$inout3
3686 .size __ocb_decrypt4,.-__ocb_decrypt4
3688 .type __ocb_decrypt1,\@abi-omnipotent
3692 pxor @offset[5],$inout5 # offset_i
3693 pxor $rndkey0l,$inout5 # offset_i ^ round[0]
3694 pxor $inout5,$inout0 # input ^ round[0] ^ offset_i
3695 $movkey 32($key_),$rndkey0
3697 aesdec $rndkey1,$inout0
3698 $movkey 48($key_),$rndkey1
3699 pxor $rndkey0l,$inout5 # offset_i ^ round[last]
3701 aesdec $rndkey0,$inout0
3702 $movkey 64($key_),$rndkey0
3707 aesdec $rndkey1,$inout0
3708 $movkey ($key,%rax),$rndkey1
3711 aesdec $rndkey0,$inout0
3712 $movkey -16($key,%rax),$rndkey0
3715 aesdec $rndkey1,$inout0
3716 $movkey 16($key_),$rndkey1 # redundant in tail
3717 mov %r10,%rax # restore twisted rounds
3719 aesdeclast $inout5,$inout0
3722 .size __ocb_decrypt1,.-__ocb_decrypt1
3726 ########################################################################
3727 # void $PREFIX_cbc_encrypt (const void *inp, void *out,
3728 # size_t length, const AES_KEY *key,
3729 # unsigned char *ivp,const int enc);
3731 my $frame_size = 0x10 + ($win64?0xa0:0); # used in decrypt
3732 my ($iv,$in0,$in1,$in2,$in3,$in4)=map("%xmm$_",(10..15));
3735 .globl ${PREFIX}_cbc_encrypt
3736 .type ${PREFIX}_cbc_encrypt,\@function,6
3738 ${PREFIX}_cbc_encrypt:
3740 test $len,$len # check length
3743 mov 240($key),$rnds_ # key->rounds
3744 mov $key,$key_ # backup $key
3745 test %r9d,%r9d # 6th argument
3747 #--------------------------- CBC ENCRYPT ------------------------------#
3748 movups ($ivp),$inout0 # load iv as initial state
3756 movups ($inp),$inout1 # load input
3758 #xorps $inout1,$inout0
3760 &aesni_generate1("enc",$key,$rounds,$inout0,$inout1);
3762 mov $rnds_,$rounds # restore $rounds
3763 mov $key_,$key # restore $key
3764 movups $inout0,0($out) # store output
3770 pxor $rndkey0,$rndkey0 # clear register bank
3771 pxor $rndkey1,$rndkey1
3772 movups $inout0,($ivp)
3773 pxor $inout0,$inout0
3774 pxor $inout1,$inout1
3778 mov $len,%rcx # zaps $key
3779 xchg $inp,$out # $inp is %rsi and $out is %rdi now
3780 .long 0x9066A4F3 # rep movsb
3781 mov \$16,%ecx # zero tail
3784 .long 0x9066AAF3 # rep stosb
3785 lea -16(%rdi),%rdi # rewind $out by 1 block
3786 mov $rnds_,$rounds # restore $rounds
3787 mov %rdi,%rsi # $inp and $out are the same
3788 mov $key_,$key # restore $key
3789 xor $len,$len # len=16
3790 jmp .Lcbc_enc_loop # one more spin
3791 \f#--------------------------- CBC DECRYPT ------------------------------#
3795 jne .Lcbc_decrypt_bulk
3797 # handle single block without allocating stack frame,
3798 # useful in ciphertext stealing mode
3799 movdqu ($inp),$inout0 # load input
3800 movdqu ($ivp),$inout1 # load iv
3801 movdqa $inout0,$inout2 # future iv
3803 &aesni_generate1("dec",$key,$rnds_);
3805 pxor $rndkey0,$rndkey0 # clear register bank
3806 pxor $rndkey1,$rndkey1
3807 movdqu $inout2,($ivp) # store iv
3808 xorps $inout1,$inout0 # ^=iv
3809 pxor $inout1,$inout1
3810 movups $inout0,($out) # store output
3811 pxor $inout0,$inout0
3815 lea (%rsp),%r11 # frame pointer
3816 .cfi_def_cfa_register %r11
3819 sub \$$frame_size,%rsp
3820 and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
3822 $code.=<<___ if ($win64);
3823 movaps %xmm6,0x10(%rsp)
3824 movaps %xmm7,0x20(%rsp)
3825 movaps %xmm8,0x30(%rsp)
3826 movaps %xmm9,0x40(%rsp)
3827 movaps %xmm10,0x50(%rsp)
3828 movaps %xmm11,0x60(%rsp)
3829 movaps %xmm12,0x70(%rsp)
3830 movaps %xmm13,0x80(%rsp)
3831 movaps %xmm14,0x90(%rsp)
3832 movaps %xmm15,0xa0(%rsp)
3836 my $inp_=$key_="%rbp"; # reassign $key_
3839 mov $key,$key_ # [re-]backup $key [after reassignment]
3845 $movkey ($key),$rndkey0
3846 movdqu 0x00($inp),$inout0 # load input
3847 movdqu 0x10($inp),$inout1
3849 movdqu 0x20($inp),$inout2
3851 movdqu 0x30($inp),$inout3
3853 movdqu 0x40($inp),$inout4
3855 movdqu 0x50($inp),$inout5
3857 mov OPENSSL_ia32cap_P+4(%rip),%r9d
3859 jbe .Lcbc_dec_six_or_seven
3861 and \$`1<<26|1<<22`,%r9d # isolate XSAVE+MOVBE
3862 sub \$0x50,$len # $len is biased by -5*16
3863 cmp \$`1<<22`,%r9d # check for MOVBE without XSAVE
3864 je .Lcbc_dec_loop6_enter # [which denotes Atom Silvermont]
3865 sub \$0x20,$len # $len is biased by -7*16
3866 lea 0x70($key),$key # size optimization
3867 jmp .Lcbc_dec_loop8_enter
3870 movups $inout7,($out)
3872 .Lcbc_dec_loop8_enter:
3873 movdqu 0x60($inp),$inout6
3874 pxor $rndkey0,$inout0
3875 movdqu 0x70($inp),$inout7
3876 pxor $rndkey0,$inout1
3877 $movkey 0x10-0x70($key),$rndkey1
3878 pxor $rndkey0,$inout2
3880 cmp \$0x70,$len # is there at least 0x60 bytes ahead?
3881 pxor $rndkey0,$inout3
3882 pxor $rndkey0,$inout4
3883 pxor $rndkey0,$inout5
3884 pxor $rndkey0,$inout6
3886 aesdec $rndkey1,$inout0
3887 pxor $rndkey0,$inout7
3888 $movkey 0x20-0x70($key),$rndkey0
3889 aesdec $rndkey1,$inout1
3890 aesdec $rndkey1,$inout2
3891 aesdec $rndkey1,$inout3
3892 aesdec $rndkey1,$inout4
3893 aesdec $rndkey1,$inout5
3894 aesdec $rndkey1,$inout6
3897 aesdec $rndkey1,$inout7
3899 $movkey 0x30-0x70($key),$rndkey1
3901 for($i=1;$i<12;$i++) {
3902 my $rndkeyx = ($i&1)?$rndkey0:$rndkey1;
3903 $code.=<<___ if ($i==7);
3907 aesdec $rndkeyx,$inout0
3908 aesdec $rndkeyx,$inout1
3909 aesdec $rndkeyx,$inout2
3910 aesdec $rndkeyx,$inout3
3911 aesdec $rndkeyx,$inout4
3912 aesdec $rndkeyx,$inout5
3913 aesdec $rndkeyx,$inout6
3914 aesdec $rndkeyx,$inout7
3915 $movkey `0x30+0x10*$i`-0x70($key),$rndkeyx
3917 $code.=<<___ if ($i<6 || (!($i&1) && $i>7));
3920 $code.=<<___ if ($i==7);
3923 $code.=<<___ if ($i==9);
3926 $code.=<<___ if ($i==11);
3933 aesdec $rndkey1,$inout0
3934 aesdec $rndkey1,$inout1
3937 aesdec $rndkey1,$inout2
3938 aesdec $rndkey1,$inout3
3941 aesdec $rndkey1,$inout4
3942 aesdec $rndkey1,$inout5
3945 aesdec $rndkey1,$inout6
3946 aesdec $rndkey1,$inout7
3947 movdqu 0x50($inp),$rndkey1
3949 aesdeclast $iv,$inout0
3950 movdqu 0x60($inp),$iv # borrow $iv
3951 pxor $rndkey0,$rndkey1
3952 aesdeclast $in0,$inout1
3954 movdqu 0x70($inp),$rndkey0 # next IV
3955 aesdeclast $in1,$inout2
3957 movdqu 0x00($inp_),$in0
3958 aesdeclast $in2,$inout3
3959 aesdeclast $in3,$inout4
3960 movdqu 0x10($inp_),$in1
3961 movdqu 0x20($inp_),$in2
3962 aesdeclast $in4,$inout5
3963 aesdeclast $rndkey1,$inout6
3964 movdqu 0x30($inp_),$in3
3965 movdqu 0x40($inp_),$in4
3966 aesdeclast $iv,$inout7
3967 movdqa $rndkey0,$iv # return $iv
3968 movdqu 0x50($inp_),$rndkey1
3969 $movkey -0x70($key),$rndkey0
3971 movups $inout0,($out) # store output
3973 movups $inout1,0x10($out)
3975 movups $inout2,0x20($out)
3977 movups $inout3,0x30($out)
3979 movups $inout4,0x40($out)
3981 movups $inout5,0x50($out)
3982 movdqa $rndkey1,$inout5
3983 movups $inout6,0x60($out)
3989 movaps $inout7,$inout0
3990 lea -0x70($key),$key
3992 jle .Lcbc_dec_clear_tail_collected
3993 movups $inout7,($out)
3999 .Lcbc_dec_six_or_seven:
4003 movaps $inout5,$inout6
4004 call _aesni_decrypt6
4005 pxor $iv,$inout0 # ^= IV
4008 movdqu $inout0,($out)
4010 movdqu $inout1,0x10($out)
4011 pxor $inout1,$inout1 # clear register bank
4013 movdqu $inout2,0x20($out)
4014 pxor $inout2,$inout2
4016 movdqu $inout3,0x30($out)
4017 pxor $inout3,$inout3
4019 movdqu $inout4,0x40($out)
4020 pxor $inout4,$inout4
4022 movdqa $inout5,$inout0
4023 pxor $inout5,$inout5
4024 jmp .Lcbc_dec_tail_collected
4028 movups 0x60($inp),$inout6
4029 xorps $inout7,$inout7
4030 call _aesni_decrypt8
4031 movups 0x50($inp),$inout7
4032 pxor $iv,$inout0 # ^= IV
4033 movups 0x60($inp),$iv
4035 movdqu $inout0,($out)
4037 movdqu $inout1,0x10($out)
4038 pxor $inout1,$inout1 # clear register bank
4040 movdqu $inout2,0x20($out)
4041 pxor $inout2,$inout2
4043 movdqu $inout3,0x30($out)
4044 pxor $inout3,$inout3
4046 movdqu $inout4,0x40($out)
4047 pxor $inout4,$inout4
4048 pxor $inout7,$inout6
4049 movdqu $inout5,0x50($out)
4050 pxor $inout5,$inout5
4052 movdqa $inout6,$inout0
4053 pxor $inout6,$inout6
4054 pxor $inout7,$inout7
4055 jmp .Lcbc_dec_tail_collected
4059 movups $inout5,($out)
4061 movdqu 0x00($inp),$inout0 # load input
4062 movdqu 0x10($inp),$inout1
4064 movdqu 0x20($inp),$inout2
4066 movdqu 0x30($inp),$inout3
4068 movdqu 0x40($inp),$inout4
4070 movdqu 0x50($inp),$inout5
4072 .Lcbc_dec_loop6_enter:
4074 movdqa $inout5,$inout6
4076 call _aesni_decrypt6
4078 pxor $iv,$inout0 # ^= IV
4081 movdqu $inout0,($out)
4083 movdqu $inout1,0x10($out)
4085 movdqu $inout2,0x20($out)
4088 movdqu $inout3,0x30($out)
4091 movdqu $inout4,0x40($out)
4096 movdqa $inout5,$inout0
4098 jle .Lcbc_dec_clear_tail_collected
4099 movups $inout5,($out)
4103 movups ($inp),$inout0
4105 jbe .Lcbc_dec_one # $len is 1*16 or less
4107 movups 0x10($inp),$inout1
4110 jbe .Lcbc_dec_two # $len is 2*16 or less
4112 movups 0x20($inp),$inout2
4115 jbe .Lcbc_dec_three # $len is 3*16 or less
4117 movups 0x30($inp),$inout3
4120 jbe .Lcbc_dec_four # $len is 4*16 or less
4122 movups 0x40($inp),$inout4 # $len is 5*16 or less
4125 xorps $inout5,$inout5
4126 call _aesni_decrypt6
4130 movdqu $inout0,($out)
4132 movdqu $inout1,0x10($out)
4133 pxor $inout1,$inout1 # clear register bank
4135 movdqu $inout2,0x20($out)
4136 pxor $inout2,$inout2
4138 movdqu $inout3,0x30($out)
4139 pxor $inout3,$inout3
4141 movdqa $inout4,$inout0
4142 pxor $inout4,$inout4
4143 pxor $inout5,$inout5
4145 jmp .Lcbc_dec_tail_collected
4151 &aesni_generate1("dec",$key,$rounds);
4155 jmp .Lcbc_dec_tail_collected
4159 call _aesni_decrypt2
4163 movdqu $inout0,($out)
4164 movdqa $inout1,$inout0
4165 pxor $inout1,$inout1 # clear register bank
4167 jmp .Lcbc_dec_tail_collected
4171 call _aesni_decrypt3
4175 movdqu $inout0,($out)
4177 movdqu $inout1,0x10($out)
4178 pxor $inout1,$inout1 # clear register bank
4179 movdqa $inout2,$inout0
4180 pxor $inout2,$inout2
4182 jmp .Lcbc_dec_tail_collected
4186 call _aesni_decrypt4
4190 movdqu $inout0,($out)
4192 movdqu $inout1,0x10($out)
4193 pxor $inout1,$inout1 # clear register bank
4195 movdqu $inout2,0x20($out)
4196 pxor $inout2,$inout2
4197 movdqa $inout3,$inout0
4198 pxor $inout3,$inout3
4200 jmp .Lcbc_dec_tail_collected
4203 .Lcbc_dec_clear_tail_collected:
4204 pxor $inout1,$inout1 # clear register bank
4205 pxor $inout2,$inout2
4206 pxor $inout3,$inout3
4208 $code.=<<___ if (!$win64);
4209 pxor $inout4,$inout4 # %xmm6..9
4210 pxor $inout5,$inout5
4211 pxor $inout6,$inout6
4212 pxor $inout7,$inout7
4215 .Lcbc_dec_tail_collected:
4218 jnz .Lcbc_dec_tail_partial
4219 movups $inout0,($out)
4220 pxor $inout0,$inout0
4223 .Lcbc_dec_tail_partial:
4224 movaps $inout0,(%rsp)
4225 pxor $inout0,$inout0
4230 .long 0x9066A4F3 # rep movsb
4231 movdqa $inout0,(%rsp)
4234 xorps $rndkey0,$rndkey0 # %xmm0
4235 pxor $rndkey1,$rndkey1
4237 $code.=<<___ if ($win64);
4238 movaps 0x10(%rsp),%xmm6
4239 movaps %xmm0,0x10(%rsp) # clear stack
4240 movaps 0x20(%rsp),%xmm7
4241 movaps %xmm0,0x20(%rsp)
4242 movaps 0x30(%rsp),%xmm8
4243 movaps %xmm0,0x30(%rsp)
4244 movaps 0x40(%rsp),%xmm9
4245 movaps %xmm0,0x40(%rsp)
4246 movaps 0x50(%rsp),%xmm10
4247 movaps %xmm0,0x50(%rsp)
4248 movaps 0x60(%rsp),%xmm11
4249 movaps %xmm0,0x60(%rsp)
4250 movaps 0x70(%rsp),%xmm12
4251 movaps %xmm0,0x70(%rsp)
4252 movaps 0x80(%rsp),%xmm13
4253 movaps %xmm0,0x80(%rsp)
4254 movaps 0x90(%rsp),%xmm14
4255 movaps %xmm0,0x90(%rsp)
4256 movaps 0xa0(%rsp),%xmm15
4257 movaps %xmm0,0xa0(%rsp)
4263 .cfi_def_cfa_register %rsp
4267 .size ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt
4270 # int ${PREFIX}_set_decrypt_key(const unsigned char *inp,
4271 # int bits, AES_KEY *key)
4273 # input: $inp user-supplied key
4274 # $bits $inp length in bits
4275 # $key pointer to key schedule
4276 # output: %eax 0 denoting success, -1 or -2 - failure (see C)
4277 # *$key key schedule
4279 { my ($inp,$bits,$key) = @_4args;
4283 .globl ${PREFIX}_set_decrypt_key
4284 .type ${PREFIX}_set_decrypt_key,\@abi-omnipotent
4286 ${PREFIX}_set_decrypt_key:
4288 .byte 0x48,0x83,0xEC,0x08 # sub rsp,8
4289 .cfi_adjust_cfa_offset 8
4290 call __aesni_set_encrypt_key
4291 shl \$4,$bits # rounds-1 after _aesni_set_encrypt_key
4294 lea 16($key,$bits),$inp # points at the end of key schedule
4296 $movkey ($key),%xmm0 # just swap
4297 $movkey ($inp),%xmm1
4298 $movkey %xmm0,($inp)
4299 $movkey %xmm1,($key)
4304 $movkey ($key),%xmm0 # swap and inverse
4305 $movkey ($inp),%xmm1
4310 $movkey %xmm0,16($inp)
4311 $movkey %xmm1,-16($key)
4313 ja .Ldec_key_inverse
4315 $movkey ($key),%xmm0 # inverse middle
4318 $movkey %xmm0,($inp)
4322 .cfi_adjust_cfa_offset -8
4325 .LSEH_end_set_decrypt_key:
4326 .size ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key
4329 # This is based on submission from Intel by
4334 # Aggressively optimized in respect to aeskeygenassist's critical path
4335 # and is contained in %xmm0-5 to meet Win64 ABI requirement.
4337 # int ${PREFIX}_set_encrypt_key(const unsigned char *inp,
4338 # int bits, AES_KEY * const key);
4340 # input: $inp user-supplied key
4341 # $bits $inp length in bits
4342 # $key pointer to key schedule
4343 # output: %eax 0 denoting success, -1 or -2 - failure (see C)
4344 # $bits rounds-1 (used in aesni_set_decrypt_key)
4345 # *$key key schedule
4346 # $key pointer to key schedule (used in
4347 # aesni_set_decrypt_key)
4349 # Subroutine is frame-less, which means that only volatile registers
4350 # are used. Note that it's declared "abi-omnipotent", which means that
4351 # amount of volatile registers is smaller on Windows.
4354 .globl ${PREFIX}_set_encrypt_key
4355 .type ${PREFIX}_set_encrypt_key,\@abi-omnipotent
4357 ${PREFIX}_set_encrypt_key:
4358 __aesni_set_encrypt_key:
4360 .byte 0x48,0x83,0xEC,0x08 # sub rsp,8
4361 .cfi_adjust_cfa_offset 8
4368 mov \$`1<<28|1<<11`,%r10d # AVX and XOP bits
4369 movups ($inp),%xmm0 # pull first 128 bits of *userKey
4370 xorps %xmm4,%xmm4 # low dword of xmm4 is assumed 0
4371 and OPENSSL_ia32cap_P+4(%rip),%r10d
4372 lea 16($key),%rax # %rax is used as modifiable copy of $key
4381 mov \$9,$bits # 10 rounds for 128-bit key
4382 cmp \$`1<<28`,%r10d # AVX, bit no XOP
4385 $movkey %xmm0,($key) # round 0
4386 aeskeygenassist \$0x1,%xmm0,%xmm1 # round 1
4387 call .Lkey_expansion_128_cold
4388 aeskeygenassist \$0x2,%xmm0,%xmm1 # round 2
4389 call .Lkey_expansion_128
4390 aeskeygenassist \$0x4,%xmm0,%xmm1 # round 3
4391 call .Lkey_expansion_128
4392 aeskeygenassist \$0x8,%xmm0,%xmm1 # round 4
4393 call .Lkey_expansion_128
4394 aeskeygenassist \$0x10,%xmm0,%xmm1 # round 5
4395 call .Lkey_expansion_128
4396 aeskeygenassist \$0x20,%xmm0,%xmm1 # round 6
4397 call .Lkey_expansion_128
4398 aeskeygenassist \$0x40,%xmm0,%xmm1 # round 7
4399 call .Lkey_expansion_128
4400 aeskeygenassist \$0x80,%xmm0,%xmm1 # round 8
4401 call .Lkey_expansion_128
4402 aeskeygenassist \$0x1b,%xmm0,%xmm1 # round 9
4403 call .Lkey_expansion_128
4404 aeskeygenassist \$0x36,%xmm0,%xmm1 # round 10
4405 call .Lkey_expansion_128
4406 $movkey %xmm0,(%rax)
4407 mov $bits,80(%rax) # 240(%rdx)
4413 movdqa .Lkey_rotate(%rip),%xmm5
4415 movdqa .Lkey_rcon1(%rip),%xmm4
4423 aesenclast %xmm4,%xmm0
4436 movdqu %xmm0,-16(%rax)
4442 movdqa .Lkey_rcon1b(%rip),%xmm4
4445 aesenclast %xmm4,%xmm0
4461 aesenclast %xmm4,%xmm0
4472 movdqu %xmm0,16(%rax)
4474 mov $bits,96(%rax) # 240($key)
4480 movq 16($inp),%xmm2 # remaining 1/3 of *userKey
4481 mov \$11,$bits # 12 rounds for 192
4482 cmp \$`1<<28`,%r10d # AVX, but no XOP
4485 $movkey %xmm0,($key) # round 0
4486 aeskeygenassist \$0x1,%xmm2,%xmm1 # round 1,2
4487 call .Lkey_expansion_192a_cold
4488 aeskeygenassist \$0x2,%xmm2,%xmm1 # round 2,3
4489 call .Lkey_expansion_192b
4490 aeskeygenassist \$0x4,%xmm2,%xmm1 # round 4,5
4491 call .Lkey_expansion_192a
4492 aeskeygenassist \$0x8,%xmm2,%xmm1 # round 5,6
4493 call .Lkey_expansion_192b
4494 aeskeygenassist \$0x10,%xmm2,%xmm1 # round 7,8
4495 call .Lkey_expansion_192a
4496 aeskeygenassist \$0x20,%xmm2,%xmm1 # round 8,9
4497 call .Lkey_expansion_192b
4498 aeskeygenassist \$0x40,%xmm2,%xmm1 # round 10,11
4499 call .Lkey_expansion_192a
4500 aeskeygenassist \$0x80,%xmm2,%xmm1 # round 11,12
4501 call .Lkey_expansion_192b
4502 $movkey %xmm0,(%rax)
4503 mov $bits,48(%rax) # 240(%rdx)
4509 movdqa .Lkey_rotate192(%rip),%xmm5
4510 movdqa .Lkey_rcon1(%rip),%xmm4
4520 aesenclast %xmm4,%xmm2
4532 pshufd \$0xff,%xmm0,%xmm3
4539 movdqu %xmm0,-16(%rax)
4544 mov $bits,32(%rax) # 240($key)
4550 movups 16($inp),%xmm2 # remaining half of *userKey
4551 mov \$13,$bits # 14 rounds for 256
4553 cmp \$`1<<28`,%r10d # AVX, but no XOP
4556 $movkey %xmm0,($key) # round 0
4557 $movkey %xmm2,16($key) # round 1
4558 aeskeygenassist \$0x1,%xmm2,%xmm1 # round 2
4559 call .Lkey_expansion_256a_cold
4560 aeskeygenassist \$0x1,%xmm0,%xmm1 # round 3
4561 call .Lkey_expansion_256b
4562 aeskeygenassist \$0x2,%xmm2,%xmm1 # round 4
4563 call .Lkey_expansion_256a
4564 aeskeygenassist \$0x2,%xmm0,%xmm1 # round 5
4565 call .Lkey_expansion_256b
4566 aeskeygenassist \$0x4,%xmm2,%xmm1 # round 6
4567 call .Lkey_expansion_256a
4568 aeskeygenassist \$0x4,%xmm0,%xmm1 # round 7
4569 call .Lkey_expansion_256b
4570 aeskeygenassist \$0x8,%xmm2,%xmm1 # round 8
4571 call .Lkey_expansion_256a
4572 aeskeygenassist \$0x8,%xmm0,%xmm1 # round 9
4573 call .Lkey_expansion_256b
4574 aeskeygenassist \$0x10,%xmm2,%xmm1 # round 10
4575 call .Lkey_expansion_256a
4576 aeskeygenassist \$0x10,%xmm0,%xmm1 # round 11
4577 call .Lkey_expansion_256b
4578 aeskeygenassist \$0x20,%xmm2,%xmm1 # round 12
4579 call .Lkey_expansion_256a
4580 aeskeygenassist \$0x20,%xmm0,%xmm1 # round 13
4581 call .Lkey_expansion_256b
4582 aeskeygenassist \$0x40,%xmm2,%xmm1 # round 14
4583 call .Lkey_expansion_256a
4584 $movkey %xmm0,(%rax)
4585 mov $bits,16(%rax) # 240(%rdx)
4591 movdqa .Lkey_rotate(%rip),%xmm5
4592 movdqa .Lkey_rcon1(%rip),%xmm4
4594 movdqu %xmm0,0($key)
4596 movdqu %xmm2,16($key)
4602 aesenclast %xmm4,%xmm2
4619 pshufd \$0xff,%xmm0,%xmm2
4621 aesenclast %xmm3,%xmm2
4632 movdqu %xmm2,16(%rax)
4639 mov $bits,16(%rax) # 240($key)
4654 .cfi_adjust_cfa_offset -8
4656 .LSEH_end_set_encrypt_key:
4659 .Lkey_expansion_128:
4660 $movkey %xmm0,(%rax)
4662 .Lkey_expansion_128_cold:
4663 shufps \$0b00010000,%xmm0,%xmm4
4665 shufps \$0b10001100,%xmm0,%xmm4
4667 shufps \$0b11111111,%xmm1,%xmm1 # critical path
4672 .Lkey_expansion_192a:
4673 $movkey %xmm0,(%rax)
4675 .Lkey_expansion_192a_cold:
4677 .Lkey_expansion_192b_warm:
4678 shufps \$0b00010000,%xmm0,%xmm4
4681 shufps \$0b10001100,%xmm0,%xmm4
4684 pshufd \$0b01010101,%xmm1,%xmm1 # critical path
4687 pshufd \$0b11111111,%xmm0,%xmm3
4692 .Lkey_expansion_192b:
4694 shufps \$0b01000100,%xmm0,%xmm5
4695 $movkey %xmm5,(%rax)
4696 shufps \$0b01001110,%xmm2,%xmm3
4697 $movkey %xmm3,16(%rax)
4699 jmp .Lkey_expansion_192b_warm
4702 .Lkey_expansion_256a:
4703 $movkey %xmm2,(%rax)
4705 .Lkey_expansion_256a_cold:
4706 shufps \$0b00010000,%xmm0,%xmm4
4708 shufps \$0b10001100,%xmm0,%xmm4
4710 shufps \$0b11111111,%xmm1,%xmm1 # critical path
4715 .Lkey_expansion_256b:
4716 $movkey %xmm0,(%rax)
4719 shufps \$0b00010000,%xmm2,%xmm4
4721 shufps \$0b10001100,%xmm2,%xmm4
4723 shufps \$0b10101010,%xmm1,%xmm1 # critical path
4727 .size ${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key
4728 .size __aesni_set_encrypt_key,.-__aesni_set_encrypt_key
4735 .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
4743 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
4745 .long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d
4747 .long 0x04070605,0x04070605,0x04070605,0x04070605
4751 .long 0x1b,0x1b,0x1b,0x1b
4753 .asciz "AES for Intel AES-NI, CRYPTOGAMS by <appro\@openssl.org>"
4757 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
4758 # CONTEXT *context,DISPATCHER_CONTEXT *disp)
4766 .extern __imp_RtlVirtualUnwind
4768 $code.=<<___ if ($PREFIX eq "aesni");
4769 .type ecb_ccm64_se_handler,\@abi-omnipotent
4771 ecb_ccm64_se_handler:
4783 mov 120($context),%rax # pull context->Rax
4784 mov 248($context),%rbx # pull context->Rip
4786 mov 8($disp),%rsi # disp->ImageBase
4787 mov 56($disp),%r11 # disp->HandlerData
4789 mov 0(%r11),%r10d # HandlerData[0]
4790 lea (%rsi,%r10),%r10 # prologue label
4791 cmp %r10,%rbx # context->Rip<prologue label
4792 jb .Lcommon_seh_tail
4794 mov 152($context),%rax # pull context->Rsp
4796 mov 4(%r11),%r10d # HandlerData[1]
4797 lea (%rsi,%r10),%r10 # epilogue label
4798 cmp %r10,%rbx # context->Rip>=epilogue label
4799 jae .Lcommon_seh_tail
4801 lea 0(%rax),%rsi # %xmm save area
4802 lea 512($context),%rdi # &context.Xmm6
4803 mov \$8,%ecx # 4*sizeof(%xmm0)/sizeof(%rax)
4804 .long 0xa548f3fc # cld; rep movsq
4805 lea 0x58(%rax),%rax # adjust stack pointer
4807 jmp .Lcommon_seh_tail
4808 .size ecb_ccm64_se_handler,.-ecb_ccm64_se_handler
4810 .type ctr_xts_se_handler,\@abi-omnipotent
4824 mov 120($context),%rax # pull context->Rax
4825 mov 248($context),%rbx # pull context->Rip
4827 mov 8($disp),%rsi # disp->ImageBase
4828 mov 56($disp),%r11 # disp->HandlerData
4830 mov 0(%r11),%r10d # HandlerData[0]
4831 lea (%rsi,%r10),%r10 # prologue lable
4832 cmp %r10,%rbx # context->Rip<prologue label
4833 jb .Lcommon_seh_tail
4835 mov 152($context),%rax # pull context->Rsp
4837 mov 4(%r11),%r10d # HandlerData[1]
4838 lea (%rsi,%r10),%r10 # epilogue label
4839 cmp %r10,%rbx # context->Rip>=epilogue label
4840 jae .Lcommon_seh_tail
4842 mov 208($context),%rax # pull context->R11
4844 lea -0xa8(%rax),%rsi # %xmm save area
4845 lea 512($context),%rdi # & context.Xmm6
4846 mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax)
4847 .long 0xa548f3fc # cld; rep movsq
4849 mov -8(%rax),%rbp # restore saved %rbp
4850 mov %rbp,160($context) # restore context->Rbp
4851 jmp .Lcommon_seh_tail
4852 .size ctr_xts_se_handler,.-ctr_xts_se_handler
4854 .type ocb_se_handler,\@abi-omnipotent
4868 mov 120($context),%rax # pull context->Rax
4869 mov 248($context),%rbx # pull context->Rip
4871 mov 8($disp),%rsi # disp->ImageBase
4872 mov 56($disp),%r11 # disp->HandlerData
4874 mov 0(%r11),%r10d # HandlerData[0]
4875 lea (%rsi,%r10),%r10 # prologue lable
4876 cmp %r10,%rbx # context->Rip<prologue label
4877 jb .Lcommon_seh_tail
4879 mov 4(%r11),%r10d # HandlerData[1]
4880 lea (%rsi,%r10),%r10 # epilogue label
4881 cmp %r10,%rbx # context->Rip>=epilogue label
4882 jae .Lcommon_seh_tail
4884 mov 8(%r11),%r10d # HandlerData[2]
4885 lea (%rsi,%r10),%r10
4886 cmp %r10,%rbx # context->Rip>=pop label
4889 mov 152($context),%rax # pull context->Rsp
4891 lea (%rax),%rsi # %xmm save area
4892 lea 512($context),%rdi # & context.Xmm6
4893 mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax)
4894 .long 0xa548f3fc # cld; rep movsq
4895 lea 0xa0+0x28(%rax),%rax
4904 mov %rbx,144($context) # restore context->Rbx
4905 mov %rbp,160($context) # restore context->Rbp
4906 mov %r12,216($context) # restore context->R12
4907 mov %r13,224($context) # restore context->R13
4908 mov %r14,232($context) # restore context->R14
4910 jmp .Lcommon_seh_tail
4911 .size ocb_se_handler,.-ocb_se_handler
4914 .type cbc_se_handler,\@abi-omnipotent
4928 mov 152($context),%rax # pull context->Rsp
4929 mov 248($context),%rbx # pull context->Rip
4931 lea .Lcbc_decrypt_bulk(%rip),%r10
4932 cmp %r10,%rbx # context->Rip<"prologue" label
4933 jb .Lcommon_seh_tail
4935 mov 120($context),%rax # pull context->Rax
4937 lea .Lcbc_decrypt_body(%rip),%r10
4938 cmp %r10,%rbx # context->Rip<cbc_decrypt_body
4939 jb .Lcommon_seh_tail
4941 mov 152($context),%rax # pull context->Rsp
4943 lea .Lcbc_ret(%rip),%r10
4944 cmp %r10,%rbx # context->Rip>="epilogue" label
4945 jae .Lcommon_seh_tail
4947 lea 16(%rax),%rsi # %xmm save area
4948 lea 512($context),%rdi # &context.Xmm6
4949 mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax)
4950 .long 0xa548f3fc # cld; rep movsq
4952 mov 208($context),%rax # pull context->R11
4954 mov -8(%rax),%rbp # restore saved %rbp
4955 mov %rbp,160($context) # restore context->Rbp
4960 mov %rax,152($context) # restore context->Rsp
4961 mov %rsi,168($context) # restore context->Rsi
4962 mov %rdi,176($context) # restore context->Rdi
4964 mov 40($disp),%rdi # disp->ContextRecord
4965 mov $context,%rsi # context
4966 mov \$154,%ecx # sizeof(CONTEXT)
4967 .long 0xa548f3fc # cld; rep movsq
4970 xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
4971 mov 8(%rsi),%rdx # arg2, disp->ImageBase
4972 mov 0(%rsi),%r8 # arg3, disp->ControlPc
4973 mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
4974 mov 40(%rsi),%r10 # disp->ContextRecord
4975 lea 56(%rsi),%r11 # &disp->HandlerData
4976 lea 24(%rsi),%r12 # &disp->EstablisherFrame
4977 mov %r10,32(%rsp) # arg5
4978 mov %r11,40(%rsp) # arg6
4979 mov %r12,48(%rsp) # arg7
4980 mov %rcx,56(%rsp) # arg8, (NULL)
4981 call *__imp_RtlVirtualUnwind(%rip)
4983 mov \$1,%eax # ExceptionContinueSearch
4995 .size cbc_se_handler,.-cbc_se_handler
5000 $code.=<<___ if ($PREFIX eq "aesni");
5001 .rva .LSEH_begin_aesni_ecb_encrypt
5002 .rva .LSEH_end_aesni_ecb_encrypt
5005 .rva .LSEH_begin_aesni_ccm64_encrypt_blocks
5006 .rva .LSEH_end_aesni_ccm64_encrypt_blocks
5007 .rva .LSEH_info_ccm64_enc
5009 .rva .LSEH_begin_aesni_ccm64_decrypt_blocks
5010 .rva .LSEH_end_aesni_ccm64_decrypt_blocks
5011 .rva .LSEH_info_ccm64_dec
5013 .rva .LSEH_begin_aesni_ctr32_encrypt_blocks
5014 .rva .LSEH_end_aesni_ctr32_encrypt_blocks
5015 .rva .LSEH_info_ctr32
5017 .rva .LSEH_begin_aesni_xts_encrypt
5018 .rva .LSEH_end_aesni_xts_encrypt
5019 .rva .LSEH_info_xts_enc
5021 .rva .LSEH_begin_aesni_xts_decrypt
5022 .rva .LSEH_end_aesni_xts_decrypt
5023 .rva .LSEH_info_xts_dec
5025 .rva .LSEH_begin_aesni_ocb_encrypt
5026 .rva .LSEH_end_aesni_ocb_encrypt
5027 .rva .LSEH_info_ocb_enc
5029 .rva .LSEH_begin_aesni_ocb_decrypt
5030 .rva .LSEH_end_aesni_ocb_decrypt
5031 .rva .LSEH_info_ocb_dec
5034 .rva .LSEH_begin_${PREFIX}_cbc_encrypt
5035 .rva .LSEH_end_${PREFIX}_cbc_encrypt
5038 .rva ${PREFIX}_set_decrypt_key
5039 .rva .LSEH_end_set_decrypt_key
5042 .rva ${PREFIX}_set_encrypt_key
5043 .rva .LSEH_end_set_encrypt_key
5048 $code.=<<___ if ($PREFIX eq "aesni");
5051 .rva ecb_ccm64_se_handler
5052 .rva .Lecb_enc_body,.Lecb_enc_ret # HandlerData[]
5053 .LSEH_info_ccm64_enc:
5055 .rva ecb_ccm64_se_handler
5056 .rva .Lccm64_enc_body,.Lccm64_enc_ret # HandlerData[]
5057 .LSEH_info_ccm64_dec:
5059 .rva ecb_ccm64_se_handler
5060 .rva .Lccm64_dec_body,.Lccm64_dec_ret # HandlerData[]
5063 .rva ctr_xts_se_handler
5064 .rva .Lctr32_body,.Lctr32_epilogue # HandlerData[]
5067 .rva ctr_xts_se_handler
5068 .rva .Lxts_enc_body,.Lxts_enc_epilogue # HandlerData[]
5071 .rva ctr_xts_se_handler
5072 .rva .Lxts_dec_body,.Lxts_dec_epilogue # HandlerData[]
5076 .rva .Locb_enc_body,.Locb_enc_epilogue # HandlerData[]
5082 .rva .Locb_dec_body,.Locb_dec_epilogue # HandlerData[]
5091 .byte 0x01,0x04,0x01,0x00
5092 .byte 0x04,0x02,0x00,0x00 # sub rsp,8
5097 local *opcode=shift;
5101 $rex|=0x04 if($dst>=8);
5102 $rex|=0x01 if($src>=8);
5103 push @opcode,$rex|0x40 if($rex);
5110 if ($line=~/(aeskeygenassist)\s+\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
5111 rex(\@opcode,$4,$3);
5112 push @opcode,0x0f,0x3a,0xdf;
5113 push @opcode,0xc0|($3&7)|(($4&7)<<3); # ModR/M
5115 push @opcode,$c=~/^0/?oct($c):$c;
5116 return ".byte\t".join(',',@opcode);
5118 elsif ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) {
5121 "aesenc" => 0xdc, "aesenclast" => 0xdd,
5122 "aesdec" => 0xde, "aesdeclast" => 0xdf
5124 return undef if (!defined($opcodelet{$1}));
5125 rex(\@opcode,$3,$2);
5126 push @opcode,0x0f,0x38,$opcodelet{$1};
5127 push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M
5128 return ".byte\t".join(',',@opcode);
5130 elsif ($line=~/(aes[a-z]+)\s+([0x1-9a-fA-F]*)\(%rsp\),\s*%xmm([0-9]+)/) {
5132 "aesenc" => 0xdc, "aesenclast" => 0xdd,
5133 "aesdec" => 0xde, "aesdeclast" => 0xdf
5135 return undef if (!defined($opcodelet{$1}));
5137 push @opcode,0x44 if ($3>=8);
5138 push @opcode,0x0f,0x38,$opcodelet{$1};
5139 push @opcode,0x44|(($3&7)<<3),0x24; # ModR/M
5140 push @opcode,($off=~/^0/?oct($off):$off)&0xff;
5141 return ".byte\t".join(',',@opcode);
5147 ".byte 0x0f,0x38,0xf1,0x44,0x24,".shift;
5150 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
5151 $code =~ s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/gem;
5152 #$code =~ s/\bmovbe\s+%eax/bswap %eax; mov %eax/gm; # debugging artefact
5153 $code =~ s/\bmovbe\s+%eax,\s*([0-9]+)\(%rsp\)/movbe($1)/gem;