e_padlock-x86_64.pl: brown-bag bug in stack pointer handling.
[openssl.git] / engines / asm / e_padlock-x86_64.pl
1 #!/usr/bin/env perl
2
3 # ====================================================================
4 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
5 # project. The module is, however, dual licensed under OpenSSL and
6 # CRYPTOGAMS licenses depending on where you obtain it. For further
7 # details see http://www.openssl.org/~appro/cryptogams/.
8 # ====================================================================
9
10 # September 2011
11 #
12 # Assembler helpers for Padlock engine. See even e_padlock-x86.pl for
13 # details.
14
15 $flavour = shift;
16 $output  = shift;
17 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
18
19 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
20
21 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
22 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
23 ( $xlate="${dir}../../crypto/perlasm/x86_64-xlate.pl" and -f $xlate) or
24 die "can't locate x86_64-xlate.pl";
25
26 open STDOUT,"| $^X $xlate $flavour $output";
27
28 $code=".text\n";
29
30 $PADLOCK_CHUNK=512;     # Must be a power of 2 between 32 and 2^20
31
32 $ctx="%rdx";
33 $out="%rdi";
34 $inp="%rsi";
35 $len="%rcx";
36 $chunk="%rbx";
37
38 ($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order
39                                  ("%rdi","%rsi","%rdx","%rcx"); # Unix order
40
41 $code.=<<___;
42 .globl  padlock_capability
43 .type   padlock_capability,\@abi-omnipotent
44 .align  16
45 padlock_capability:
46         mov     %rbx,%r8
47         xor     %eax,%eax
48         cpuid
49         xor     %eax,%eax
50         cmp     \$`"0x".unpack("H*",'tneC')`,%ebx
51         jne     .Lnoluck
52         cmp     \$`"0x".unpack("H*",'Hrua')`,%edx
53         jne     .Lnoluck
54         cmp     \$`"0x".unpack("H*",'slua')`,%ecx
55         jne     .Lnoluck
56         mov     \$0xC0000000,%eax
57         cpuid
58         mov     %eax,%edx
59         xor     %eax,%eax
60         cmp     \$0xC0000001,%edx
61         jb      .Lnoluck
62         mov     \$0xC0000001,%eax
63         cpuid
64         mov     %edx,%eax
65         and     \$0xffffffef,%eax
66         or      \$0x10,%eax             # set Nano bit#4
67 .Lnoluck:
68         mov     %r8,%rbx
69         ret
70 .size   padlock_capability,.-padlock_capability
71
72 .globl  padlock_key_bswap
73 .type   padlock_key_bswap,\@abi-omnipotent,0
74 .align  16
75 padlock_key_bswap:
76         mov     240($arg1),%edx
77 .Lbswap_loop:
78         mov     ($arg1),%eax
79         bswap   %eax
80         mov     %eax,($arg1)
81         lea     4($arg1),$arg1
82         sub     \$1,%edx
83         jnz     .Lbswap_loop
84         ret
85 .size   padlock_key_bswap,.-padlock_key_bswap
86
87 .globl  padlock_verify_context
88 .type   padlock_verify_context,\@abi-omnipotent
89 .align  16
90 padlock_verify_context:
91         mov     $arg1,$ctx
92         pushf
93         lea     .Lpadlock_saved_context(%rip),%rax
94         call    _padlock_verify_ctx
95         lea     8(%rsp),%rsp
96         ret
97 .size   padlock_verify_context,.-padlock_verify_context
98
99 .type   _padlock_verify_ctx,\@abi-omnipotent
100 .align  16
101 _padlock_verify_ctx:
102         mov     8(%rsp),%r8
103         bt      \$30,%r8
104         jnc     .Lverified
105         cmp     (%rax),$ctx
106         je      .Lverified
107         pushf
108         popf
109 .Lverified:
110         mov     $ctx,(%rax)
111         ret
112 .size   _padlock_verify_ctx,.-_padlock_verify_ctx
113
114 .globl  padlock_reload_key
115 .type   padlock_reload_key,\@abi-omnipotent
116 .align  16
117 padlock_reload_key:
118         pushf
119         popf
120         ret
121 .size   padlock_reload_key,.-padlock_reload_key
122
123 .globl  padlock_aes_block
124 .type   padlock_aes_block,\@function,3
125 .align  16
126 padlock_aes_block:
127         mov     %rbx,%r8
128         mov     \$1,$len
129         lea     32($ctx),%rbx           # key
130         lea     16($ctx),$ctx           # control word
131         .byte   0xf3,0x0f,0xa7,0xc8     # rep xcryptecb
132         mov     %r8,%rbx
133         ret
134 .size   padlock_aes_block,.-padlock_aes_block
135
136 .globl  padlock_xstore
137 .type   padlock_xstore,\@function,2
138 .align  16
139 padlock_xstore:
140         mov     %esi,%edx
141         .byte   0x0f,0xa7,0xc0          # xstore
142         ret
143 .size   padlock_xstore,.-padlock_xstore
144
145 .globl  padlock_sha1_oneshot
146 .type   padlock_sha1_oneshot,\@function,3
147 .align  16
148 padlock_sha1_oneshot:
149         mov     %rdx,%rcx
150         mov     %rdi,%rdx               # put aside %rdi
151         movups  (%rdi),%xmm0            # copy-in context
152         sub     \$128+8,%rsp
153         mov     16(%rdi),%eax
154         movaps  %xmm0,(%rsp)
155         mov     %rsp,%rdi
156         mov     %eax,16(%rsp)
157         xor     %rax,%rax
158         .byte   0xf3,0x0f,0xa6,0xc8     # rep xsha1
159         movaps  (%rsp),%xmm0
160         mov     16(%rsp),%eax
161         add     \$128+8,%rsp
162         movups  %xmm0,(%rdx)            # copy-out context
163         mov     %eax,16(%rdx)
164         ret
165 .size   padlock_sha1_oneshot,.-padlock_sha1_oneshot
166
167 .globl  padlock_sha1_blocks
168 .type   padlock_sha1_blocks,\@function,3
169 .align  16
170 padlock_sha1_blocks:
171         mov     %rdx,%rcx
172         mov     %rdi,%rdx               # put aside %rdi
173         movups  (%rdi),%xmm0            # copy-in context
174         sub     \$128+8,%rsp
175         mov     16(%rdi),%eax
176         movaps  %xmm0,(%rsp)
177         mov     %rsp,%rdi
178         mov     %eax,16(%rsp)
179         mov     \$-1,%rax
180         .byte   0xf3,0x0f,0xa6,0xc8     # rep xsha1
181         movaps  (%rsp),%xmm0
182         mov     16(%rsp),%eax
183         add     \$128+8,%rsp
184         movups  %xmm0,(%rdx)            # copy-out context
185         mov     %eax,16(%rdx)
186         ret
187 .size   padlock_sha1_blocks,.-padlock_sha1_blocks
188
189 .globl  padlock_sha256_oneshot
190 .type   padlock_sha256_oneshot,\@function,3
191 .align  16
192 padlock_sha256_oneshot:
193         mov     %rdx,%rcx
194         mov     %rdi,%rdx               # put aside %rdi
195         movups  (%rdi),%xmm0            # copy-in context
196         sub     \$128+8,%rsp
197         movups  16(%rdi),%xmm1
198         movaps  %xmm0,(%rsp)
199         mov     %rsp,%rdi
200         movaps  %xmm1,16(%rsp)
201         xor     %rax,%rax
202         .byte   0xf3,0x0f,0xa6,0xd0     # rep xsha256
203         movaps  (%rsp),%xmm0
204         movaps  16(%rsp),%xmm1
205         add     \$128+8,%rsp
206         movups  %xmm0,(%rdx)            # copy-out context
207         movups  %xmm1,16(%rdx)
208         ret
209 .size   padlock_sha256_oneshot,.-padlock_sha256_oneshot
210
211 .globl  padlock_sha256_blocks
212 .type   padlock_sha256_blocks,\@function,3
213 .align  16
214 padlock_sha256_blocks:
215         mov     %rdx,%rcx
216         mov     %rdi,%rdx               # put aside %rdi
217         movups  (%rdi),%xmm0            # copy-in context
218         sub     \$128+8,%rsp
219         movups  16(%rdi),%xmm1
220         movaps  %xmm0,(%rsp)
221         mov     %rsp,%rdi
222         movaps  %xmm1,16(%rsp)
223         mov     \$-1,%rax
224         .byte   0xf3,0x0f,0xa6,0xd0     # rep xsha256
225         movaps  (%rsp),%xmm0
226         movaps  16(%rsp),%xmm1
227         add     \$128+8,%rsp
228         movups  %xmm0,(%rdx)            # copy-out context
229         movups  %xmm1,16(%rdx)
230         ret
231 .size   padlock_sha256_blocks,.-padlock_sha256_blocks
232
233 .globl  padlock_sha512_blocks
234 .type   padlock_sha512_blocks,\@function,3
235 .align  16
236 padlock_sha512_blocks:
237         mov     %rdx,%rcx
238         mov     %rdi,%rdx               # put aside %rdi
239         movups  (%rdi),%xmm0            # copy-in context
240         sub     \$128+8,%rsp
241         movups  16(%rdi),%xmm1
242         movups  32(%rdi),%xmm2
243         movups  48(%rdi),%xmm3
244         movaps  %xmm0,(%rsp)
245         mov     %rsp,%rdi
246         movaps  %xmm1,16(%rsp)
247         movaps  %xmm2,32(%rsp)
248         movaps  %xmm3,48(%rsp)
249         .byte   0xf3,0x0f,0xa6,0xe0     # rep xha512
250         movaps  (%rsp),%xmm0
251         movaps  16(%rsp),%xmm1
252         movaps  32(%rsp),%xmm2
253         movaps  48(%rsp),%xmm3
254         add     \$128+8,%rsp
255         movups  %xmm0,(%rdx)            # copy-out context
256         movups  %xmm1,16(%rdx)
257         movups  %xmm2,32(%rdx)
258         movups  %xmm3,48(%rdx)
259         ret
260 .size   padlock_sha512_blocks,.-padlock_sha512_blocks
261 ___
262
263 sub generate_mode {
264 my ($mode,$opcode) = @_;
265 # int padlock_$mode_encrypt(void *out, const void *inp,
266 #               struct padlock_cipher_data *ctx, size_t len);
267 $code.=<<___;
268 .globl  padlock_${mode}_encrypt
269 .type   padlock_${mode}_encrypt,\@function,4
270 .align  16
271 padlock_${mode}_encrypt:
272         push    %rbp
273         push    %rbx
274
275         xor     %eax,%eax
276         test    \$15,$ctx
277         jnz     .L${mode}_abort
278         test    \$15,$len
279         jnz     .L${mode}_abort
280         lea     .Lpadlock_saved_context(%rip),%rax
281         pushf
282         cld
283         call    _padlock_verify_ctx
284         lea     16($ctx),$ctx           # control word
285         xor     %eax,%eax
286         xor     %ebx,%ebx
287         testl   \$`1<<5`,($ctx)         # align bit in control word
288         jnz     .L${mode}_aligned
289         test    \$0x0f,$out
290         setz    %al                     # !out_misaligned
291         test    \$0x0f,$inp
292         setz    %bl                     # !inp_misaligned
293         test    %ebx,%eax
294         jnz     .L${mode}_aligned
295         neg     %rax
296         mov     \$$PADLOCK_CHUNK,$chunk
297         not     %rax                    # out_misaligned?-1:0
298         lea     (%rsp),%rbp
299         cmp     $chunk,$len
300         cmovc   $len,$chunk             # chunk=len>PADLOCK_CHUNK?PADLOCK_CHUNK:len
301         and     $chunk,%rax             # out_misaligned?chunk:0
302         mov     $len,$chunk
303         neg     %rax
304         and     \$$PADLOCK_CHUNK-1,$chunk       # chunk%=PADLOCK_CHUNK
305         lea     (%rax,%rbp),%rsp
306 ___
307 $code.=<<___                            if ($mode eq "ctr32");
308         mov     -4($ctx),%eax           # pull 32-bit counter
309         bswap   %eax
310         neg     %eax
311         and     \$`$PADLOCK_CHUNK/16-1`,%eax
312         jz      .L${mode}_loop
313         shl     \$4,%eax
314         cmp     %rax,$len
315         cmova   %rax,$chunk             # don't let counter cross PADLOCK_CHUNK
316 ___
317 $code.=<<___;
318         jmp     .L${mode}_loop
319 .align  16
320 .L${mode}_loop:
321         cmp     $len,$chunk             # ctr32 artefact
322         cmova   $len,$chunk             # ctr32 artefact
323         mov     $out,%r8                # save parameters
324         mov     $inp,%r9
325         mov     $len,%r10
326         mov     $chunk,$len
327         mov     $chunk,%r11
328         test    \$0x0f,$out             # out_misaligned
329         cmovnz  %rsp,$out
330         test    \$0x0f,$inp             # inp_misaligned
331         jz      .L${mode}_inp_aligned
332         shr     \$3,$len
333         .byte   0xf3,0x48,0xa5          # rep movsq
334         sub     $chunk,$out
335         mov     $chunk,$len
336         mov     $out,$inp
337 .L${mode}_inp_aligned:
338         lea     -16($ctx),%rax          # ivp
339         lea     16($ctx),%rbx           # key
340         shr     \$4,$len
341         .byte   0xf3,0x0f,0xa7,$opcode  # rep xcrypt*
342 ___
343 $code.=<<___                            if ($mode !~ /ecb|ctr/);
344         movdqa  (%rax),%xmm0
345         movdqa  %xmm0,-16($ctx)         # copy [or refresh] iv
346 ___
347 $code.=<<___                            if ($mode eq "ctr32");
348         mov     -4($ctx),%eax           # pull 32-bit counter
349         test    \$0xffff0000,%eax
350         jnz     .L${mode}_no_corr
351         bswap   %eax
352         add     \$0x10000,%eax
353         bswap   %eax
354         mov     %eax,-4($ctx)
355 .L${mode}_no_corr:
356 ___
357 $code.=<<___;
358         mov     %r8,$out                # restore paramters
359         mov     %r11,$chunk
360         test    \$0x0f,$out
361         jz      .L${mode}_out_aligned
362         mov     $chunk,$len
363         shr     \$3,$len
364         lea     (%rsp),$inp
365         .byte   0xf3,0x48,0xa5          # rep movsq
366         sub     $chunk,$out
367 .L${mode}_out_aligned:
368         mov     %r9,$inp
369         mov     %r10,$len
370         add     $chunk,$out
371         add     $chunk,$inp
372         sub     $chunk,$len
373         mov     \$$PADLOCK_CHUNK,$chunk
374         jnz     .L${mode}_loop
375
376         test    \$0x0f,$out
377         jz      .L${mode}_done
378
379         mov     %rbp,$len
380         mov     %rsp,$out
381         sub     %rsp,$len
382         xor     %rax,%rax
383         shr     \$3,$len
384         .byte   0xf3,0x48,0xab          # rep stosq
385 .L${mode}_done:
386         lea     (%rbp),%rsp
387         jmp     .L${mode}_exit
388
389 .align  16
390 .L${mode}_aligned:
391 ___
392 $code.=<<___                            if ($mode eq "ctr32");
393         mov     -4($ctx),%eax           # pull 32-bit counter
394         mov     \$`16*0x10000`,$chunk
395         bswap   %eax
396         cmp     $len,$chunk
397         cmova   $len,$chunk
398         neg     %eax
399         and     \$0xffff,%eax
400         jz      .L${mode}_aligned_loop
401         shl     \$4,%eax
402         cmp     %rax,$len
403         cmova   %rax,$chunk             # don't let counter cross 2^16
404         jmp     .L${mode}_aligned_loop
405 .align  16
406 .L${mode}_aligned_loop:
407         cmp     $len,$chunk
408         cmova   $len,$chunk
409         mov     $len,%r10               # save parameters
410         mov     $chunk,$len
411         mov     $chunk,%r11
412 ___
413 $code.=<<___;
414         lea     -16($ctx),%rax          # ivp
415         lea     16($ctx),%rbx           # key
416         shr     \$4,$len                # len/=AES_BLOCK_SIZE
417         .byte   0xf3,0x0f,0xa7,$opcode  # rep xcrypt*
418 ___
419 $code.=<<___                            if ($mode !~ /ecb|ctr/);
420         movdqa  (%rax),%xmm0
421         movdqa  %xmm0,-16($ctx)         # copy [or refresh] iv
422 ___
423 $code.=<<___                            if ($mode eq "ctr32");
424         mov     -4($ctx),%eax           # pull 32-bit counter
425         bswap   %eax
426         add     \$0x10000,%eax
427         bswap   %eax
428         mov     %eax,-4($ctx)
429
430         mov     %r11,$chunk             # restore paramters
431         mov     %r10,$len
432         sub     $chunk,$len
433         mov     \$`16*0x10000`,$chunk
434         jnz     .L${mode}_aligned_loop
435 ___
436 $code.=<<___;
437 .L${mode}_exit:
438         mov     \$1,%eax
439         lea     8(%rsp),%rsp
440 .L${mode}_abort:
441         pop     %rbx
442         pop     %rbp
443         ret
444 .size   padlock_${mode}_encrypt,.-padlock_${mode}_encrypt
445 ___
446 }
447
448 &generate_mode("ecb",0xc8);
449 &generate_mode("cbc",0xd0);
450 &generate_mode("cfb",0xe0);
451 &generate_mode("ofb",0xe8);
452 &generate_mode("ctr32",0xd8);   # all 64-bit CPUs have working CTR...
453
454 $code.=<<___;
455 .asciz  "VIA Padlock x86_64 module, CRYPTOGAMS by <appro\@openssl.org>"
456 .align  16
457 .data
458 .align  8
459 .Lpadlock_saved_context:
460         .quad   0
461 ___
462 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
463
464 print $code;
465
466 close STDOUT;