RAND_DRBG: add a callback data for entropy and nonce callbacks
[openssl.git] / crypto / x86_64cpuid.pl
1 #! /usr/bin/env perl
2 # Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the Apache License 2.0 (the "License").  You may not use
5 # this file except in compliance with the License.  You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
8
9
10 # $output is the last argument if it looks like a file (it has an extension)
11 # $flavour is the first argument if it doesn't look like a file
12 $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
13 $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
14
15 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
16
17 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
18 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
19 ( $xlate="${dir}perlasm/x86_64-xlate.pl" and -f $xlate) or
20 die "can't locate x86_64-xlate.pl";
21
22 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
23      or die "can't call $xlate: $!";
24 *STDOUT=*OUT;
25
26 ($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order
27                                  ("%rdi","%rsi","%rdx","%rcx"); # Unix order
28
29 print<<___;
30 .extern         OPENSSL_cpuid_setup
31 .hidden         OPENSSL_cpuid_setup
32 .section        .init
33         call    OPENSSL_cpuid_setup
34
35 .hidden OPENSSL_ia32cap_P
36 .comm   OPENSSL_ia32cap_P,16,4
37
38 .text
39
40 .globl  OPENSSL_atomic_add
41 .type   OPENSSL_atomic_add,\@abi-omnipotent
42 .align  16
43 OPENSSL_atomic_add:
44 .cfi_startproc
45         movl    ($arg1),%eax
46 .Lspin: leaq    ($arg2,%rax),%r8
47         .byte   0xf0            # lock
48         cmpxchgl        %r8d,($arg1)
49         jne     .Lspin
50         movl    %r8d,%eax
51         .byte   0x48,0x98       # cltq/cdqe
52         ret
53 .cfi_endproc
54 .size   OPENSSL_atomic_add,.-OPENSSL_atomic_add
55
56 .globl  OPENSSL_rdtsc
57 .type   OPENSSL_rdtsc,\@abi-omnipotent
58 .align  16
59 OPENSSL_rdtsc:
60 .cfi_startproc
61         rdtsc
62         shl     \$32,%rdx
63         or      %rdx,%rax
64         ret
65 .cfi_endproc
66 .size   OPENSSL_rdtsc,.-OPENSSL_rdtsc
67
68 .globl  OPENSSL_ia32_cpuid
69 .type   OPENSSL_ia32_cpuid,\@function,1
70 .align  16
71 OPENSSL_ia32_cpuid:
72 .cfi_startproc
73         mov     %rbx,%r8                # save %rbx
74 .cfi_register   %rbx,%r8
75
76         xor     %eax,%eax
77         mov     %rax,8(%rdi)            # clear extended feature flags
78         cpuid
79         mov     %eax,%r11d              # max value for standard query level
80
81         xor     %eax,%eax
82         cmp     \$0x756e6547,%ebx       # "Genu"
83         setne   %al
84         mov     %eax,%r9d
85         cmp     \$0x49656e69,%edx       # "ineI"
86         setne   %al
87         or      %eax,%r9d
88         cmp     \$0x6c65746e,%ecx       # "ntel"
89         setne   %al
90         or      %eax,%r9d               # 0 indicates Intel CPU
91         jz      .Lintel
92
93         cmp     \$0x68747541,%ebx       # "Auth"
94         setne   %al
95         mov     %eax,%r10d
96         cmp     \$0x69746E65,%edx       # "enti"
97         setne   %al
98         or      %eax,%r10d
99         cmp     \$0x444D4163,%ecx       # "cAMD"
100         setne   %al
101         or      %eax,%r10d              # 0 indicates AMD CPU
102         jnz     .Lintel
103
104         # AMD specific
105         mov     \$0x80000000,%eax
106         cpuid
107         cmp     \$0x80000001,%eax
108         jb      .Lintel
109         mov     %eax,%r10d
110         mov     \$0x80000001,%eax
111         cpuid
112         or      %ecx,%r9d
113         and     \$0x00000801,%r9d       # isolate AMD XOP bit, 1<<11
114
115         cmp     \$0x80000008,%r10d
116         jb      .Lintel
117
118         mov     \$0x80000008,%eax
119         cpuid
120         movzb   %cl,%r10                # number of cores - 1
121         inc     %r10                    # number of cores
122
123         mov     \$1,%eax
124         cpuid
125         bt      \$28,%edx               # test hyper-threading bit
126         jnc     .Lgeneric
127         shr     \$16,%ebx               # number of logical processors
128         cmp     %r10b,%bl
129         ja      .Lgeneric
130         and     \$0xefffffff,%edx       # ~(1<<28)
131         jmp     .Lgeneric
132
133 .Lintel:
134         cmp     \$4,%r11d
135         mov     \$-1,%r10d
136         jb      .Lnocacheinfo
137
138         mov     \$4,%eax
139         mov     \$0,%ecx                # query L1D
140         cpuid
141         mov     %eax,%r10d
142         shr     \$14,%r10d
143         and     \$0xfff,%r10d           # number of cores -1 per L1D
144
145 .Lnocacheinfo:
146         mov     \$1,%eax
147         cpuid
148         movd    %eax,%xmm0              # put aside processor id
149         and     \$0xbfefffff,%edx       # force reserved bits to 0
150         cmp     \$0,%r9d
151         jne     .Lnotintel
152         or      \$0x40000000,%edx       # set reserved bit#30 on Intel CPUs
153         and     \$15,%ah
154         cmp     \$15,%ah                # examine Family ID
155         jne     .LnotP4
156         or      \$0x00100000,%edx       # set reserved bit#20 to engage RC4_CHAR
157 .LnotP4:
158         cmp     \$6,%ah
159         jne     .Lnotintel
160         and     \$0x0fff0ff0,%eax
161         cmp     \$0x00050670,%eax       # Knights Landing
162         je      .Lknights
163         cmp     \$0x00080650,%eax       # Knights Mill (according to sde)
164         jne     .Lnotintel
165 .Lknights:
166         and     \$0xfbffffff,%ecx       # clear XSAVE flag to mimic Silvermont
167
168 .Lnotintel:
169         bt      \$28,%edx               # test hyper-threading bit
170         jnc     .Lgeneric
171         and     \$0xefffffff,%edx       # ~(1<<28)
172         cmp     \$0,%r10d
173         je      .Lgeneric
174
175         or      \$0x10000000,%edx       # 1<<28
176         shr     \$16,%ebx
177         cmp     \$1,%bl                 # see if cache is shared
178         ja      .Lgeneric
179         and     \$0xefffffff,%edx       # ~(1<<28)
180 .Lgeneric:
181         and     \$0x00000800,%r9d       # isolate AMD XOP flag
182         and     \$0xfffff7ff,%ecx
183         or      %ecx,%r9d               # merge AMD XOP flag
184
185         mov     %edx,%r10d              # %r9d:%r10d is copy of %ecx:%edx
186
187         cmp     \$7,%r11d
188         jb      .Lno_extended_info
189         mov     \$7,%eax
190         xor     %ecx,%ecx
191         cpuid
192         bt      \$26,%r9d               # check XSAVE bit, cleared on Knights
193         jc      .Lnotknights
194         and     \$0xfff7ffff,%ebx       # clear ADCX/ADOX flag
195 .Lnotknights:
196         movd    %xmm0,%eax              # restore processor id
197         and     \$0x0fff0ff0,%eax
198         cmp     \$0x00050650,%eax       # Skylake-X
199         jne     .Lnotskylakex
200         and     \$0xfffeffff,%ebx       # ~(1<<16)
201                                         # suppress AVX512F flag on Skylake-X
202 .Lnotskylakex:
203         mov     %ebx,8(%rdi)            # save extended feature flags
204         mov     %ecx,12(%rdi)
205 .Lno_extended_info:
206
207         bt      \$27,%r9d               # check OSXSAVE bit
208         jnc     .Lclear_avx
209         xor     %ecx,%ecx               # XCR0
210         .byte   0x0f,0x01,0xd0          # xgetbv
211         and     \$0xe6,%eax             # isolate XMM, YMM and ZMM state support
212         cmp     \$0xe6,%eax
213         je      .Ldone
214         andl    \$0x3fdeffff,8(%rdi)    # ~(1<<31|1<<30|1<<21|1<<16)
215                                         # clear AVX512F+BW+VL+FIMA, all of
216                                         # them are EVEX-encoded, which requires
217                                         # ZMM state support even if one uses
218                                         # only XMM and YMM :-(
219         and     \$6,%eax                # isolate XMM and YMM state support
220         cmp     \$6,%eax
221         je      .Ldone
222 .Lclear_avx:
223         mov     \$0xefffe7ff,%eax       # ~(1<<28|1<<12|1<<11)
224         and     %eax,%r9d               # clear AVX, FMA and AMD XOP bits
225         mov     \$0x3fdeffdf,%eax       # ~(1<<31|1<<30|1<<21|1<<16|1<<5)
226         and     %eax,8(%rdi)            # clear AVX2 and AVX512* bits
227 .Ldone:
228         shl     \$32,%r9
229         mov     %r10d,%eax
230         mov     %r8,%rbx                # restore %rbx
231 .cfi_restore    %rbx
232         or      %r9,%rax
233         ret
234 .cfi_endproc
235 .size   OPENSSL_ia32_cpuid,.-OPENSSL_ia32_cpuid
236
237 .globl  OPENSSL_cleanse
238 .type   OPENSSL_cleanse,\@abi-omnipotent
239 .align  16
240 OPENSSL_cleanse:
241 .cfi_startproc
242         xor     %rax,%rax
243         cmp     \$15,$arg2
244         jae     .Lot
245         cmp     \$0,$arg2
246         je      .Lret
247 .Little:
248         mov     %al,($arg1)
249         sub     \$1,$arg2
250         lea     1($arg1),$arg1
251         jnz     .Little
252 .Lret:
253         ret
254 .align  16
255 .Lot:
256         test    \$7,$arg1
257         jz      .Laligned
258         mov     %al,($arg1)
259         lea     -1($arg2),$arg2
260         lea     1($arg1),$arg1
261         jmp     .Lot
262 .Laligned:
263         mov     %rax,($arg1)
264         lea     -8($arg2),$arg2
265         test    \$-8,$arg2
266         lea     8($arg1),$arg1
267         jnz     .Laligned
268         cmp     \$0,$arg2
269         jne     .Little
270         ret
271 .cfi_endproc
272 .size   OPENSSL_cleanse,.-OPENSSL_cleanse
273
274 .globl  CRYPTO_memcmp
275 .type   CRYPTO_memcmp,\@abi-omnipotent
276 .align  16
277 CRYPTO_memcmp:
278 .cfi_startproc
279         xor     %rax,%rax
280         xor     %r10,%r10
281         cmp     \$0,$arg3
282         je      .Lno_data
283         cmp     \$16,$arg3
284         jne     .Loop_cmp
285         mov     ($arg1),%r10
286         mov     8($arg1),%r11
287         mov     \$1,$arg3
288         xor     ($arg2),%r10
289         xor     8($arg2),%r11
290         or      %r11,%r10
291         cmovnz  $arg3,%rax
292         ret
293
294 .align  16
295 .Loop_cmp:
296         mov     ($arg1),%r10b
297         lea     1($arg1),$arg1
298         xor     ($arg2),%r10b
299         lea     1($arg2),$arg2
300         or      %r10b,%al
301         dec     $arg3
302         jnz     .Loop_cmp
303         neg     %rax
304         shr     \$63,%rax
305 .Lno_data:
306         ret
307 .cfi_endproc
308 .size   CRYPTO_memcmp,.-CRYPTO_memcmp
309 ___
310
311 print<<___ if (!$win64);
312 .globl  OPENSSL_wipe_cpu
313 .type   OPENSSL_wipe_cpu,\@abi-omnipotent
314 .align  16
315 OPENSSL_wipe_cpu:
316 .cfi_startproc
317         pxor    %xmm0,%xmm0
318         pxor    %xmm1,%xmm1
319         pxor    %xmm2,%xmm2
320         pxor    %xmm3,%xmm3
321         pxor    %xmm4,%xmm4
322         pxor    %xmm5,%xmm5
323         pxor    %xmm6,%xmm6
324         pxor    %xmm7,%xmm7
325         pxor    %xmm8,%xmm8
326         pxor    %xmm9,%xmm9
327         pxor    %xmm10,%xmm10
328         pxor    %xmm11,%xmm11
329         pxor    %xmm12,%xmm12
330         pxor    %xmm13,%xmm13
331         pxor    %xmm14,%xmm14
332         pxor    %xmm15,%xmm15
333         xorq    %rcx,%rcx
334         xorq    %rdx,%rdx
335         xorq    %rsi,%rsi
336         xorq    %rdi,%rdi
337         xorq    %r8,%r8
338         xorq    %r9,%r9
339         xorq    %r10,%r10
340         xorq    %r11,%r11
341         leaq    8(%rsp),%rax
342         ret
343 .cfi_endproc
344 .size   OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu
345 ___
346 print<<___ if ($win64);
347 .globl  OPENSSL_wipe_cpu
348 .type   OPENSSL_wipe_cpu,\@abi-omnipotent
349 .align  16
350 OPENSSL_wipe_cpu:
351         pxor    %xmm0,%xmm0
352         pxor    %xmm1,%xmm1
353         pxor    %xmm2,%xmm2
354         pxor    %xmm3,%xmm3
355         pxor    %xmm4,%xmm4
356         pxor    %xmm5,%xmm5
357         xorq    %rcx,%rcx
358         xorq    %rdx,%rdx
359         xorq    %r8,%r8
360         xorq    %r9,%r9
361         xorq    %r10,%r10
362         xorq    %r11,%r11
363         leaq    8(%rsp),%rax
364         ret
365 .size   OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu
366 ___
367 {
368 my $out="%r10";
369 my $cnt="%rcx";
370 my $max="%r11";
371 my $lasttick="%r8d";
372 my $lastdiff="%r9d";
373 my $redzone=win64?8:-8;
374
375 print<<___;
376 .globl  OPENSSL_instrument_bus
377 .type   OPENSSL_instrument_bus,\@abi-omnipotent
378 .align  16
379 OPENSSL_instrument_bus:
380 .cfi_startproc
381         mov     $arg1,$out      # tribute to Win64
382         mov     $arg2,$cnt
383         mov     $arg2,$max
384
385         rdtsc                   # collect 1st tick
386         mov     %eax,$lasttick  # lasttick = tick
387         mov     \$0,$lastdiff   # lastdiff = 0
388         clflush ($out)
389         .byte   0xf0            # lock
390         add     $lastdiff,($out)
391         jmp     .Loop
392 .align  16
393 .Loop:  rdtsc
394         mov     %eax,%edx
395         sub     $lasttick,%eax
396         mov     %edx,$lasttick
397         mov     %eax,$lastdiff
398         clflush ($out)
399         .byte   0xf0            # lock
400         add     %eax,($out)
401         lea     4($out),$out
402         sub     \$1,$cnt
403         jnz     .Loop
404
405         mov     $max,%rax
406         ret
407 .cfi_endproc
408 .size   OPENSSL_instrument_bus,.-OPENSSL_instrument_bus
409
410 .globl  OPENSSL_instrument_bus2
411 .type   OPENSSL_instrument_bus2,\@abi-omnipotent
412 .align  16
413 OPENSSL_instrument_bus2:
414 .cfi_startproc
415         mov     $arg1,$out      # tribute to Win64
416         mov     $arg2,$cnt
417         mov     $arg3,$max
418         mov     $cnt,$redzone(%rsp)
419
420         rdtsc                   # collect 1st tick
421         mov     %eax,$lasttick  # lasttick = tick
422         mov     \$0,$lastdiff   # lastdiff = 0
423
424         clflush ($out)
425         .byte   0xf0            # lock
426         add     $lastdiff,($out)
427
428         rdtsc                   # collect 1st diff
429         mov     %eax,%edx
430         sub     $lasttick,%eax  # diff
431         mov     %edx,$lasttick  # lasttick = tick
432         mov     %eax,$lastdiff  # lastdiff = diff
433 .Loop2:
434         clflush ($out)
435         .byte   0xf0            # lock
436         add     %eax,($out)     # accumulate diff
437
438         sub     \$1,$max
439         jz      .Ldone2
440
441         rdtsc
442         mov     %eax,%edx
443         sub     $lasttick,%eax  # diff
444         mov     %edx,$lasttick  # lasttick = tick
445         cmp     $lastdiff,%eax
446         mov     %eax,$lastdiff  # lastdiff = diff
447         mov     \$0,%edx
448         setne   %dl
449         sub     %rdx,$cnt       # conditional --$cnt
450         lea     ($out,%rdx,4),$out      # conditional ++$out
451         jnz     .Loop2
452
453 .Ldone2:
454         mov     $redzone(%rsp),%rax
455         sub     $cnt,%rax
456         ret
457 .cfi_endproc
458 .size   OPENSSL_instrument_bus2,.-OPENSSL_instrument_bus2
459 ___
460 }
461
462 sub gen_random {
463 my $rdop = shift;
464 print<<___;
465 .globl  OPENSSL_ia32_${rdop}_bytes
466 .type   OPENSSL_ia32_${rdop}_bytes,\@abi-omnipotent
467 .align  16
468 OPENSSL_ia32_${rdop}_bytes:
469 .cfi_startproc
470         xor     %rax, %rax      # return value
471         cmp     \$0,$arg2
472         je      .Ldone_${rdop}_bytes
473
474         mov     \$8,%r11
475 .Loop_${rdop}_bytes:
476         ${rdop} %r10
477         jc      .Lbreak_${rdop}_bytes
478         dec     %r11
479         jnz     .Loop_${rdop}_bytes
480         jmp     .Ldone_${rdop}_bytes
481
482 .align  16
483 .Lbreak_${rdop}_bytes:
484         cmp     \$8,$arg2
485         jb      .Ltail_${rdop}_bytes
486         mov     %r10,($arg1)
487         lea     8($arg1),$arg1
488         add     \$8,%rax
489         sub     \$8,$arg2
490         jz      .Ldone_${rdop}_bytes
491         mov     \$8,%r11
492         jmp     .Loop_${rdop}_bytes
493
494 .align  16
495 .Ltail_${rdop}_bytes:
496         mov     %r10b,($arg1)
497         lea     1($arg1),$arg1
498         inc     %rax
499         shr     \$8,%r10
500         dec     $arg2
501         jnz     .Ltail_${rdop}_bytes
502
503 .Ldone_${rdop}_bytes:
504         xor     %r10,%r10       # Clear sensitive data from register
505         ret
506 .cfi_endproc
507 .size   OPENSSL_ia32_${rdop}_bytes,.-OPENSSL_ia32_${rdop}_bytes
508 ___
509 }
510 gen_random("rdrand");
511 gen_random("rdseed");
512
513 close STDOUT or die "error closing STDOUT";     # flush