| 
									
										
										
										
											2016-04-20 10:10:43 +08:00
										 |  |  | #! /usr/bin/env perl | 
					
						
							| 
									
										
										
										
											2020-04-23 20:55:52 +08:00
										 |  |  | # Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2016-04-20 10:10:43 +08:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2018-12-06 21:03:01 +08:00
										 |  |  | # Licensed under the Apache License 2.0 (the "License").  You may not use | 
					
						
							| 
									
										
										
										
											2016-04-20 10:10:43 +08:00
										 |  |  | # this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  | # in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  | # https://www.openssl.org/source/license.html | 
					
						
							| 
									
										
										
										
											2004-07-27 04:18:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-06 06:28:38 +08:00
										 |  |  | $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; | 
					
						
							|  |  |  | push(@INC, "${dir}perlasm", "perlasm"); | 
					
						
							| 
									
										
										
										
											2004-07-27 04:18:55 +08:00
										 |  |  | require "x86asm.pl"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Unify all assembler file generators
They now generally conform to the following argument sequence:
    script.pl "$(PERLASM_SCHEME)" [ C preprocessor arguments ... ] \
              $(PROCESSOR) <output file>
However, in the spirit of being able to use these scripts manually,
they also allow for no argument, or for only the flavour, or for only
the output file.  This is done by only using the last argument as
output file if it's a file (it has an extension), and only using the
first argument as flavour if it isn't a file (it doesn't have an
extension).
While we're at it, we make all $xlate calls the same, i.e. the $output
argument is always quoted, and we always die on error when trying to
start $xlate.
There's a perl lesson in this, regarding operator priority...
This will always succeed, even when it fails:
    open FOO, "something" || die "ERR: $!";
The reason is that '||' has higher priority than list operators (a
function is essentially a list operator and gobbles up everything
following it that isn't lower priority), and since a non-empty string
is always true, so that ends up being exactly the same as:
    open FOO, "something";
This, however, will fail if "something" can't be opened:
    open FOO, "something" or die "ERR: $!";
The reason is that 'or' has lower priority that list operators,
i.e. it's performed after the 'open' call.
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9884)
											
										 
											2019-09-13 06:06:46 +08:00
										 |  |  | $output = pop and open STDOUT,">$output"; | 
					
						
							| 
									
										
										
										
											2016-03-07 22:00:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 02:24:56 +08:00
										 |  |  | &asm_init($ARGV[0]); | 
					
						
							| 
									
										
										
										
											2004-07-27 04:18:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-18 16:42:08 +08:00
										 |  |  | for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 04:18:55 +08:00
										 |  |  | &function_begin("OPENSSL_ia32_cpuid"); | 
					
						
							|  |  |  | 	&xor	("edx","edx"); | 
					
						
							|  |  |  | 	&pushf	(); | 
					
						
							|  |  |  | 	&pop	("eax"); | 
					
						
							|  |  |  | 	&mov	("ecx","eax"); | 
					
						
							|  |  |  | 	&xor	("eax",1<<21); | 
					
						
							|  |  |  | 	&push	("eax"); | 
					
						
							|  |  |  | 	&popf	(); | 
					
						
							|  |  |  | 	&pushf	(); | 
					
						
							|  |  |  | 	&pop	("eax"); | 
					
						
							|  |  |  | 	&xor	("ecx","eax"); | 
					
						
							| 
									
										
										
										
											2007-04-02 01:28:08 +08:00
										 |  |  | 	&xor	("eax","eax"); | 
					
						
							| 
									
										
										
										
											2017-03-12 21:45:06 +08:00
										 |  |  | 	&mov	("esi",&wparam(0)); | 
					
						
							|  |  |  | 	&mov	(&DWP(8,"esi"),"eax");	# clear extended feature flags | 
					
						
							| 
									
										
										
										
											2012-02-28 22:20:21 +08:00
										 |  |  | 	&bt	("ecx",21); | 
					
						
							|  |  |  | 	&jnc	(&label("nocpuid")); | 
					
						
							| 
									
										
										
										
											2007-04-02 01:28:08 +08:00
										 |  |  | 	&cpuid	(); | 
					
						
							| 
									
										
										
										
											2009-05-15 02:17:26 +08:00
										 |  |  | 	&mov	("edi","eax");		# max value for standard query level | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-02 01:28:08 +08:00
										 |  |  | 	&xor	("eax","eax"); | 
					
						
							|  |  |  | 	&cmp	("ebx",0x756e6547);	# "Genu" | 
					
						
							|  |  |  | 	&setne	(&LB("eax")); | 
					
						
							|  |  |  | 	&mov	("ebp","eax"); | 
					
						
							|  |  |  | 	&cmp	("edx",0x49656e69);	# "ineI" | 
					
						
							|  |  |  | 	&setne	(&LB("eax")); | 
					
						
							|  |  |  | 	&or	("ebp","eax"); | 
					
						
							|  |  |  | 	&cmp	("ecx",0x6c65746e);	# "ntel" | 
					
						
							|  |  |  | 	&setne	(&LB("eax")); | 
					
						
							| 
									
										
										
										
											2009-05-13 05:19:41 +08:00
										 |  |  | 	&or	("ebp","eax");		# 0 indicates Intel CPU | 
					
						
							|  |  |  | 	&jz	(&label("intel")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&cmp	("ebx",0x68747541);	# "Auth" | 
					
						
							|  |  |  | 	&setne	(&LB("eax")); | 
					
						
							|  |  |  | 	&mov	("esi","eax"); | 
					
						
							|  |  |  | 	&cmp	("edx",0x69746E65);	# "enti" | 
					
						
							|  |  |  | 	&setne	(&LB("eax")); | 
					
						
							|  |  |  | 	&or	("esi","eax"); | 
					
						
							|  |  |  | 	&cmp	("ecx",0x444D4163);	# "cAMD" | 
					
						
							|  |  |  | 	&setne	(&LB("eax")); | 
					
						
							|  |  |  | 	&or	("esi","eax");		# 0 indicates AMD CPU | 
					
						
							|  |  |  | 	&jnz	(&label("intel")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-15 02:17:26 +08:00
										 |  |  | 	# AMD specific | 
					
						
							| 
									
										
										
										
											2009-05-13 05:19:41 +08:00
										 |  |  | 	&mov	("eax",0x80000000); | 
					
						
							|  |  |  | 	&cpuid	(); | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&cmp	("eax",0x80000001); | 
					
						
							|  |  |  | 	&jb	(&label("intel")); | 
					
						
							|  |  |  | 	&mov	("esi","eax"); | 
					
						
							|  |  |  | 	&mov	("eax",0x80000001); | 
					
						
							|  |  |  | 	&cpuid	(); | 
					
						
							|  |  |  | 	&or	("ebp","ecx"); | 
					
						
							|  |  |  | 	&and	("ebp",1<<11|1);	# isolate XOP bit | 
					
						
							|  |  |  | 	&cmp	("esi",0x80000008); | 
					
						
							| 
									
										
										
										
											2009-05-13 05:19:41 +08:00
										 |  |  | 	&jb	(&label("intel")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&mov	("eax",0x80000008); | 
					
						
							|  |  |  | 	&cpuid	(); | 
					
						
							|  |  |  | 	&movz	("esi",&LB("ecx"));	# number of cores - 1 | 
					
						
							|  |  |  | 	&inc	("esi");		# number of cores | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-15 02:17:26 +08:00
										 |  |  | 	&mov	("eax",1); | 
					
						
							| 
									
										
										
										
											2013-03-05 03:05:04 +08:00
										 |  |  | 	&xor	("ecx","ecx"); | 
					
						
							| 
									
										
										
										
											2009-05-15 02:17:26 +08:00
										 |  |  | 	&cpuid	(); | 
					
						
							|  |  |  | 	&bt	("edx",28); | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&jnc	(&label("generic")); | 
					
						
							| 
									
										
										
										
											2009-05-15 02:17:26 +08:00
										 |  |  | 	&shr	("ebx",16); | 
					
						
							|  |  |  | 	&and	("ebx",0xff); | 
					
						
							|  |  |  | 	&cmp	("ebx","esi"); | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&ja	(&label("generic")); | 
					
						
							| 
									
										
										
										
											2009-05-15 02:17:26 +08:00
										 |  |  | 	&and	("edx",0xefffffff);	# clear hyper-threading bit | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&jmp	(&label("generic")); | 
					
						
							| 
									
										
										
										
											2016-10-11 00:01:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-13 05:19:41 +08:00
										 |  |  | &set_label("intel"); | 
					
						
							| 
									
										
										
										
											2009-05-15 02:17:26 +08:00
										 |  |  | 	&cmp	("edi",4); | 
					
						
							| 
									
										
										
										
											2017-03-12 21:45:06 +08:00
										 |  |  | 	&mov	("esi",-1); | 
					
						
							| 
									
										
										
										
											2009-05-15 02:17:26 +08:00
										 |  |  | 	&jb	(&label("nocacheinfo")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&mov	("eax",4); | 
					
						
							|  |  |  | 	&mov	("ecx",0);		# query L1D | 
					
						
							|  |  |  | 	&cpuid	(); | 
					
						
							| 
									
										
										
										
											2017-03-12 21:45:06 +08:00
										 |  |  | 	&mov	("esi","eax"); | 
					
						
							|  |  |  | 	&shr	("esi",14); | 
					
						
							|  |  |  | 	&and	("esi",0xfff);		# number of cores -1 per L1D | 
					
						
							| 
									
										
										
										
											2009-05-15 02:17:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | &set_label("nocacheinfo"); | 
					
						
							| 
									
										
										
										
											2004-07-27 04:18:55 +08:00
										 |  |  | 	&mov	("eax",1); | 
					
						
							| 
									
										
										
										
											2013-03-05 03:05:04 +08:00
										 |  |  | 	&xor	("ecx","ecx"); | 
					
						
							| 
									
										
										
										
											2004-07-27 04:18:55 +08:00
										 |  |  | 	&cpuid	(); | 
					
						
							| 
									
										
										
										
											2011-05-29 20:50:02 +08:00
										 |  |  | 	&and	("edx",0xbfefffff);	# force reserved bits #20, #30 to 0 | 
					
						
							| 
									
										
										
										
											2007-04-02 01:28:08 +08:00
										 |  |  | 	&cmp	("ebp",0); | 
					
						
							| 
									
										
										
										
											2011-05-27 23:32:43 +08:00
										 |  |  | 	&jne	(&label("notintel")); | 
					
						
							|  |  |  | 	&or	("edx",1<<30);		# set reserved bit#30 on Intel CPUs | 
					
						
							| 
									
										
										
										
											2017-11-12 08:03:10 +08:00
										 |  |  | 	&and	(&HB("eax"),15);	# family ID | 
					
						
							| 
									
										
										
										
											2007-07-21 22:46:27 +08:00
										 |  |  | 	&cmp	(&HB("eax"),15);	# P4? | 
					
						
							| 
									
										
										
										
											2011-05-27 23:32:43 +08:00
										 |  |  | 	&jne	(&label("notintel")); | 
					
						
							|  |  |  | 	&or	("edx",1<<20);		# set reserved bit#20 to engage RC4_CHAR | 
					
						
							|  |  |  | &set_label("notintel"); | 
					
						
							| 
									
										
										
										
											2007-07-21 22:46:27 +08:00
										 |  |  | 	&bt	("edx",28);		# test hyper-threading bit | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&jnc	(&label("generic")); | 
					
						
							| 
									
										
										
										
											2009-05-15 02:17:26 +08:00
										 |  |  | 	&and	("edx",0xefffffff); | 
					
						
							| 
									
										
										
										
											2017-03-12 21:45:06 +08:00
										 |  |  | 	&cmp	("esi",0); | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&je	(&label("generic")); | 
					
						
							| 
									
										
										
										
											2009-05-15 02:17:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	&or	("edx",0x10000000); | 
					
						
							| 
									
										
										
										
											2007-04-02 01:28:08 +08:00
										 |  |  | 	&shr	("ebx",16); | 
					
						
							| 
									
										
										
										
											2009-05-15 02:17:26 +08:00
										 |  |  | 	&cmp	(&LB("ebx"),1); | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&ja	(&label("generic")); | 
					
						
							| 
									
										
										
										
											2007-05-20 01:52:51 +08:00
										 |  |  | 	&and	("edx",0xefffffff);	# clear hyper-threading bit if not | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | &set_label("generic"); | 
					
						
							|  |  |  | 	&and	("ebp",1<<11);		# isolate AMD XOP flag | 
					
						
							| 
									
										
										
										
											2011-05-29 20:50:02 +08:00
										 |  |  | 	&and	("ecx",0xfffff7ff);	# force 11th bit to 0 | 
					
						
							| 
									
										
										
										
											2017-03-12 21:45:06 +08:00
										 |  |  | 	&mov	("esi","edx");		# %ebp:%esi is copy of %ecx:%edx | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&or	("ebp","ecx");		# merge AMD XOP flag | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-12 21:45:06 +08:00
										 |  |  | 	&cmp	("edi",7); | 
					
						
							|  |  |  | 	&mov	("edi",&wparam(0)); | 
					
						
							|  |  |  | 	&jb	(&label("no_extended_info")); | 
					
						
							|  |  |  | 	&mov	("eax",7); | 
					
						
							|  |  |  | 	&xor	("ecx","ecx"); | 
					
						
							|  |  |  | 	&cpuid	(); | 
					
						
							| 
									
										
										
										
											2024-12-05 02:29:23 +08:00
										 |  |  | 	&mov	(&DWP(8,"edi"),"ebx");	# save cpuid(EAX=0x7, ECX=0x0).EBX to OPENSSL_ia32cap_P[2] | 
					
						
							|  |  |  | 	&mov	(&DWP(12,"edi"),"ecx");	# save cpuid(EAX=0x7, ECX=0x0).ECX to OPENSSL_ia32cap_P[3] | 
					
						
							|  |  |  | 	&mov	(&DWP(16,"edi"),"edx");	# save cpuid(EAX=0x7, ECX=0x0).EDX to OPENSSL_ia32cap_P[4] | 
					
						
							|  |  |  | 	&cmp	("eax",1);				# Do we have cpuid(EAX=0x7, ECX=0x1)? | 
					
						
							|  |  |  | 	&jb	(&label("no_extended_info")); | 
					
						
							|  |  |  | 	&mov	("eax",7); | 
					
						
							|  |  |  | 	&mov	("ecx",1); | 
					
						
							|  |  |  | 	&cpuid	();						# cpuid(EAX=0x7, ECX=0x1) | 
					
						
							|  |  |  | 	&mov	(&DWP(20,"edi"),"eax");	# save cpuid(EAX=0x7, ECX=0x1).EAX to OPENSSL_ia32cap_P[5] | 
					
						
							|  |  |  | 	&mov	(&DWP(24,"edi"),"edx");	# save cpuid(EAX=0x7, ECX=0x1).EDX to OPENSSL_ia32cap_P[6] | 
					
						
							|  |  |  | 	&mov	(&DWP(28,"edi"),"ebx");	# save cpuid(EAX=0x7, ECX=0x1).EBX to OPENSSL_ia32cap_P[7] | 
					
						
							|  |  |  | 	&mov	(&DWP(32,"edi"),"ecx");	# save cpuid(EAX=0x7, ECX=0x1).ECX to OPENSSL_ia32cap_P[8] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&and	("edx",0x80000);		# Mask cpuid(EAX=0x7, ECX=0x1).EDX bit 19 to detect AVX10 support | 
					
						
							|  |  |  | 	&cmp	("edx",0x0); | 
					
						
							|  |  |  | 	&je (&label("no_extended_info")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&mov	("eax",0x24);			# Have AVX10 Support, query for details | 
					
						
							|  |  |  | 	&mov	("ecx",0x0); | 
					
						
							|  |  |  | 	&cpuid	();						# cpuid(EAX=0x24, ECX=0x0) AVX10 Leaf | 
					
						
							|  |  |  | 	&mov	(&DWP(36,"edi"),"ebx");	# save cpuid(EAX=0x24, ECX=0x0).EBX to OPENSSL_ia32cap_P[9] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-12 21:45:06 +08:00
										 |  |  | &set_label("no_extended_info"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&bt	("ebp",27);		# check OSXSAVE bit | 
					
						
							| 
									
										
										
										
											2011-11-05 18:44:12 +08:00
										 |  |  | 	&jnc	(&label("clear_avx")); | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&xor	("ecx","ecx"); | 
					
						
							|  |  |  | 	&data_byte(0x0f,0x01,0xd0);	# xgetbv | 
					
						
							|  |  |  | 	&and	("eax",6); | 
					
						
							|  |  |  | 	&cmp	("eax",6); | 
					
						
							|  |  |  | 	&je	(&label("done")); | 
					
						
							|  |  |  | 	&cmp	("eax",2); | 
					
						
							|  |  |  | 	&je	(&label("clear_avx")); | 
					
						
							|  |  |  | &set_label("clear_xmm"); | 
					
						
							| 
									
										
										
										
											2011-05-29 20:50:02 +08:00
										 |  |  | 	&and	("ebp",0xfdfffffd);	# clear AESNI and PCLMULQDQ bits | 
					
						
							|  |  |  | 	&and	("esi",0xfeffffff);	# clear FXSR | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | &set_label("clear_avx"); | 
					
						
							| 
									
										
										
										
											2011-05-29 20:50:02 +08:00
										 |  |  | 	&and	("ebp",0xefffe7ff);	# clear AVX, FMA and AMD XOP bits | 
					
						
							| 
									
										
										
										
											2024-12-05 02:29:23 +08:00
										 |  |  | 	&and	(&DWP(20,"edi"),0xff7fffff);	# ~(1<<23) clear AVXIFMA, | 
					
						
							|  |  |  | 											# which is VEX-encoded | 
					
						
							|  |  |  | 											# and requires YMM state support | 
					
						
							| 
									
										
										
										
											2012-11-18 03:04:15 +08:00
										 |  |  | 	&and	(&DWP(8,"edi"),0xffffffdf);	# clear AVX2 | 
					
						
							| 
									
										
										
										
											2007-07-21 22:46:27 +08:00
										 |  |  | &set_label("done"); | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&mov	("eax","esi"); | 
					
						
							|  |  |  | 	&mov	("edx","ebp"); | 
					
						
							| 
									
										
										
										
											2012-02-28 22:20:21 +08:00
										 |  |  | &set_label("nocpuid"); | 
					
						
							| 
									
										
										
										
											2004-07-27 04:18:55 +08:00
										 |  |  | &function_end("OPENSSL_ia32_cpuid"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-30 00:36:05 +08:00
										 |  |  | &external_label("OPENSSL_ia32cap_P"); | 
					
						
							| 
									
										
										
										
											2004-07-27 04:18:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-30 00:36:05 +08:00
										 |  |  | &function_begin_B("OPENSSL_rdtsc","EXTRN\t_OPENSSL_ia32cap_P:DWORD"); | 
					
						
							| 
									
										
										
										
											2004-07-27 04:18:55 +08:00
										 |  |  | 	&xor	("eax","eax"); | 
					
						
							|  |  |  | 	&xor	("edx","edx"); | 
					
						
							| 
									
										
										
										
											2004-08-30 00:36:05 +08:00
										 |  |  | 	&picmeup("ecx","OPENSSL_ia32cap_P"); | 
					
						
							| 
									
										
										
										
											2004-07-27 04:18:55 +08:00
										 |  |  | 	&bt	(&DWP(0,"ecx"),4); | 
					
						
							|  |  |  | 	&jnc	(&label("notsc")); | 
					
						
							|  |  |  | 	&rdtsc	(); | 
					
						
							|  |  |  | &set_label("notsc"); | 
					
						
							|  |  |  | 	&ret	(); | 
					
						
							|  |  |  | &function_end_B("OPENSSL_rdtsc"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-09 20:02:20 +08:00
										 |  |  | # This works in Ring 0 only [read DJGPP+MS-DOS+privileged DPMI host], | 
					
						
							| 
									
										
										
										
											2004-09-09 22:50:32 +08:00
										 |  |  | # but it's safe to call it on any [supported] 32-bit platform... | 
					
						
							|  |  |  | # Just check for [non-]zero return value... | 
					
						
							|  |  |  | &function_begin_B("OPENSSL_instrument_halt","EXTRN\t_OPENSSL_ia32cap_P:DWORD"); | 
					
						
							|  |  |  | 	&picmeup("ecx","OPENSSL_ia32cap_P"); | 
					
						
							|  |  |  | 	&bt	(&DWP(0,"ecx"),4); | 
					
						
							|  |  |  | 	&jnc	(&label("nohalt"));	# no TSC | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&data_word(0x9058900e);		# push %cs; pop %eax | 
					
						
							|  |  |  | 	&and	("eax",3); | 
					
						
							|  |  |  | 	&jnz	(&label("nohalt"));	# not enough privileges | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&pushf	(); | 
					
						
							| 
									
										
										
										
											2012-04-28 18:36:58 +08:00
										 |  |  | 	&pop	("eax"); | 
					
						
							| 
									
										
										
										
											2004-09-09 22:50:32 +08:00
										 |  |  | 	&bt	("eax",9); | 
					
						
							|  |  |  | 	&jnc	(&label("nohalt"));	# interrupts are disabled | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&rdtsc	(); | 
					
						
							|  |  |  | 	&push	("edx"); | 
					
						
							|  |  |  | 	&push	("eax"); | 
					
						
							|  |  |  | 	&halt	(); | 
					
						
							|  |  |  | 	&rdtsc	(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&sub	("eax",&DWP(0,"esp")); | 
					
						
							|  |  |  | 	&sbb	("edx",&DWP(4,"esp")); | 
					
						
							|  |  |  | 	&add	("esp",8); | 
					
						
							|  |  |  | 	&ret	(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | &set_label("nohalt"); | 
					
						
							|  |  |  | 	&xor	("eax","eax"); | 
					
						
							|  |  |  | 	&xor	("edx","edx"); | 
					
						
							|  |  |  | 	&ret	(); | 
					
						
							|  |  |  | &function_end_B("OPENSSL_instrument_halt"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-09 20:02:20 +08:00
										 |  |  | # Essentially there is only one use for this function. Under DJGPP: | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | #	#include <go32.h> | 
					
						
							|  |  |  | #	... | 
					
						
							|  |  |  | #	i=OPENSSL_far_spin(_dos_ds,0x46c); | 
					
						
							|  |  |  | #	... | 
					
						
							|  |  |  | # to obtain the number of spins till closest timer interrupt. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | &function_begin_B("OPENSSL_far_spin"); | 
					
						
							|  |  |  | 	&pushf	(); | 
					
						
							|  |  |  | 	&pop	("eax"); | 
					
						
							|  |  |  | 	&bt	("eax",9); | 
					
						
							|  |  |  | 	&jnc	(&label("nospin"));	# interrupts are disabled | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&mov	("eax",&DWP(4,"esp")); | 
					
						
							|  |  |  | 	&mov	("ecx",&DWP(8,"esp")); | 
					
						
							|  |  |  | 	&data_word (0x90d88e1e);	# push %ds, mov %eax,%ds | 
					
						
							|  |  |  | 	&xor	("eax","eax"); | 
					
						
							|  |  |  | 	&mov	("edx",&DWP(0,"ecx")); | 
					
						
							|  |  |  | 	&jmp	(&label("spin")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&align	(16); | 
					
						
							|  |  |  | &set_label("spin"); | 
					
						
							|  |  |  | 	&inc	("eax"); | 
					
						
							|  |  |  | 	&cmp	("edx",&DWP(0,"ecx")); | 
					
						
							|  |  |  | 	&je	(&label("spin")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&data_word (0x1f909090);	# pop	%ds | 
					
						
							|  |  |  | 	&ret	(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | &set_label("nospin"); | 
					
						
							|  |  |  | 	&xor	("eax","eax"); | 
					
						
							|  |  |  | 	&xor	("edx","edx"); | 
					
						
							|  |  |  | 	&ret	(); | 
					
						
							|  |  |  | &function_end_B("OPENSSL_far_spin"); | 
					
						
							| 
									
										
										
										
											2005-05-04 05:05:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | &function_begin_B("OPENSSL_atomic_add"); | 
					
						
							|  |  |  | 	&mov	("edx",&DWP(4,"esp"));	# fetch the pointer, 1st arg | 
					
						
							|  |  |  | 	&mov	("ecx",&DWP(8,"esp"));	# fetch the increment, 2nd arg | 
					
						
							|  |  |  | 	&push	("ebx"); | 
					
						
							|  |  |  | 	&nop	(); | 
					
						
							|  |  |  | 	&mov	("eax",&DWP(0,"edx")); | 
					
						
							|  |  |  | &set_label("spin"); | 
					
						
							|  |  |  | 	&lea	("ebx",&DWP(0,"eax","ecx")); | 
					
						
							|  |  |  | 	&nop	(); | 
					
						
							| 
									
										
										
										
											2017-03-29 05:57:28 +08:00
										 |  |  | 	&data_word(0x1ab10ff0);	# lock;	cmpxchg	%ebx,(%edx)	# %eax is involved and is always reloaded | 
					
						
							| 
									
										
										
										
											2005-05-04 05:05:06 +08:00
										 |  |  | 	&jne	(&label("spin")); | 
					
						
							|  |  |  | 	&mov	("eax","ebx");	# OpenSSL expects the new value | 
					
						
							|  |  |  | 	&pop	("ebx"); | 
					
						
							|  |  |  | 	&ret	(); | 
					
						
							|  |  |  | &function_end_B("OPENSSL_atomic_add"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-15 05:35:25 +08:00
										 |  |  | &function_begin_B("OPENSSL_cleanse"); | 
					
						
							|  |  |  | 	&mov	("edx",&wparam(0)); | 
					
						
							|  |  |  | 	&mov	("ecx",&wparam(1)); | 
					
						
							|  |  |  | 	&xor	("eax","eax"); | 
					
						
							|  |  |  | 	&cmp	("ecx",7); | 
					
						
							|  |  |  | 	&jae	(&label("lot")); | 
					
						
							| 
									
										
										
										
											2010-01-24 22:54:24 +08:00
										 |  |  | 	&cmp	("ecx",0); | 
					
						
							|  |  |  | 	&je	(&label("ret")); | 
					
						
							| 
									
										
										
										
											2007-05-15 05:35:25 +08:00
										 |  |  | &set_label("little"); | 
					
						
							|  |  |  | 	&mov	(&BP(0,"edx"),"al"); | 
					
						
							|  |  |  | 	&sub	("ecx",1); | 
					
						
							|  |  |  | 	&lea	("edx",&DWP(1,"edx")); | 
					
						
							|  |  |  | 	&jnz	(&label("little")); | 
					
						
							| 
									
										
										
										
											2010-01-24 22:54:24 +08:00
										 |  |  | &set_label("ret"); | 
					
						
							| 
									
										
										
										
											2007-05-15 05:35:25 +08:00
										 |  |  | 	&ret	(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | &set_label("lot",16); | 
					
						
							|  |  |  | 	&test	("edx",3); | 
					
						
							|  |  |  | 	&jz	(&label("aligned")); | 
					
						
							|  |  |  | 	&mov	(&BP(0,"edx"),"al"); | 
					
						
							|  |  |  | 	&lea	("ecx",&DWP(-1,"ecx")); | 
					
						
							|  |  |  | 	&lea	("edx",&DWP(1,"edx")); | 
					
						
							|  |  |  | 	&jmp	(&label("lot")); | 
					
						
							|  |  |  | &set_label("aligned"); | 
					
						
							|  |  |  | 	&mov	(&DWP(0,"edx"),"eax"); | 
					
						
							|  |  |  | 	&lea	("ecx",&DWP(-4,"ecx")); | 
					
						
							|  |  |  | 	&test	("ecx",-4); | 
					
						
							|  |  |  | 	&lea	("edx",&DWP(4,"edx")); | 
					
						
							|  |  |  | 	&jnz	(&label("aligned")); | 
					
						
							|  |  |  | 	&cmp	("ecx",0); | 
					
						
							|  |  |  | 	&jne	(&label("little")); | 
					
						
							|  |  |  | 	&ret	(); | 
					
						
							|  |  |  | &function_end_B("OPENSSL_cleanse"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-15 23:01:15 +08:00
										 |  |  | &function_begin_B("CRYPTO_memcmp"); | 
					
						
							|  |  |  | 	&push	("esi"); | 
					
						
							|  |  |  | 	&push	("edi"); | 
					
						
							|  |  |  | 	&mov	("esi",&wparam(0)); | 
					
						
							|  |  |  | 	&mov	("edi",&wparam(1)); | 
					
						
							|  |  |  | 	&mov	("ecx",&wparam(2)); | 
					
						
							|  |  |  | 	&xor	("eax","eax"); | 
					
						
							|  |  |  | 	&xor	("edx","edx"); | 
					
						
							|  |  |  | 	&cmp	("ecx",0); | 
					
						
							|  |  |  | 	&je	(&label("no_data")); | 
					
						
							|  |  |  | &set_label("loop"); | 
					
						
							|  |  |  | 	&mov	("dl",&BP(0,"esi")); | 
					
						
							|  |  |  | 	&lea	("esi",&DWP(1,"esi")); | 
					
						
							|  |  |  | 	&xor	("dl",&BP(0,"edi")); | 
					
						
							|  |  |  | 	&lea	("edi",&DWP(1,"edi")); | 
					
						
							|  |  |  | 	&or	("al","dl"); | 
					
						
							|  |  |  | 	&dec	("ecx"); | 
					
						
							|  |  |  | 	&jnz	(&label("loop")); | 
					
						
							|  |  |  | 	&neg	("eax"); | 
					
						
							|  |  |  | 	&shr	("eax",31); | 
					
						
							|  |  |  | &set_label("no_data"); | 
					
						
							|  |  |  | 	&pop	("edi"); | 
					
						
							|  |  |  | 	&pop	("esi"); | 
					
						
							|  |  |  | 	&ret	(); | 
					
						
							|  |  |  | &function_end_B("CRYPTO_memcmp"); | 
					
						
							| 
									
										
										
										
											2011-04-17 20:46:00 +08:00
										 |  |  | { | 
					
						
							|  |  |  | my $lasttick = "esi"; | 
					
						
							|  |  |  | my $lastdiff = "ebx"; | 
					
						
							|  |  |  | my $out = "edi"; | 
					
						
							|  |  |  | my $cnt = "ecx"; | 
					
						
							|  |  |  | my $max = "ebp"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | &function_begin("OPENSSL_instrument_bus"); | 
					
						
							|  |  |  |     &mov	("eax",0); | 
					
						
							|  |  |  |     if ($sse2) { | 
					
						
							|  |  |  | 	&picmeup("edx","OPENSSL_ia32cap_P"); | 
					
						
							|  |  |  | 	&bt	(&DWP(0,"edx"),4); | 
					
						
							|  |  |  | 	&jnc	(&label("nogo"));	# no TSC | 
					
						
							|  |  |  | 	&bt	(&DWP(0,"edx"),19); | 
					
						
							|  |  |  | 	&jnc	(&label("nogo"));	# no CLFLUSH | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&mov	($out,&wparam(0));	# load arguments | 
					
						
							|  |  |  | 	&mov	($cnt,&wparam(1)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# collect 1st tick | 
					
						
							|  |  |  | 	&rdtsc	(); | 
					
						
							|  |  |  | 	&mov	($lasttick,"eax");	# lasttick = tick | 
					
						
							|  |  |  | 	&mov	($lastdiff,0);		# lastdiff = 0 | 
					
						
							|  |  |  | 	&clflush(&DWP(0,$out)); | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&data_byte(0xf0);		# lock | 
					
						
							| 
									
										
										
										
											2011-04-17 20:46:00 +08:00
										 |  |  | 	&add	(&DWP(0,$out),$lastdiff); | 
					
						
							|  |  |  | 	&jmp	(&label("loop")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | &set_label("loop",16); | 
					
						
							|  |  |  | 	&rdtsc	(); | 
					
						
							|  |  |  | 	&mov	("edx","eax");		# put aside tick (yes, I neglect edx) | 
					
						
							|  |  |  | 	&sub	("eax",$lasttick);	# diff | 
					
						
							|  |  |  | 	&mov	($lasttick,"edx");	# lasttick = tick | 
					
						
							|  |  |  | 	&mov	($lastdiff,"eax");	# lastdiff = diff | 
					
						
							|  |  |  | 	&clflush(&DWP(0,$out)); | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&data_byte(0xf0);		# lock | 
					
						
							| 
									
										
										
										
											2011-04-17 20:46:00 +08:00
										 |  |  | 	&add	(&DWP(0,$out),"eax");	# accumulate diff | 
					
						
							|  |  |  | 	&lea	($out,&DWP(4,$out));	# ++$out | 
					
						
							|  |  |  | 	&sub	($cnt,1);		# --$cnt | 
					
						
							|  |  |  | 	&jnz	(&label("loop")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&mov	("eax",&wparam(1)); | 
					
						
							|  |  |  | &set_label("nogo"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | &function_end("OPENSSL_instrument_bus"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | &function_begin("OPENSSL_instrument_bus2"); | 
					
						
							|  |  |  |     &mov	("eax",0); | 
					
						
							|  |  |  |     if ($sse2) { | 
					
						
							|  |  |  | 	&picmeup("edx","OPENSSL_ia32cap_P"); | 
					
						
							|  |  |  | 	&bt	(&DWP(0,"edx"),4); | 
					
						
							|  |  |  | 	&jnc	(&label("nogo"));	# no TSC | 
					
						
							|  |  |  | 	&bt	(&DWP(0,"edx"),19); | 
					
						
							|  |  |  | 	&jnc	(&label("nogo"));	# no CLFLUSH | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&mov	($out,&wparam(0));	# load arguments | 
					
						
							|  |  |  | 	&mov	($cnt,&wparam(1)); | 
					
						
							|  |  |  | 	&mov	($max,&wparam(2)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&rdtsc	();			# collect 1st tick | 
					
						
							|  |  |  | 	&mov	($lasttick,"eax");	# lasttick = tick | 
					
						
							|  |  |  | 	&mov	($lastdiff,0);		# lastdiff = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&clflush(&DWP(0,$out)); | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&data_byte(0xf0);		# lock | 
					
						
							| 
									
										
										
										
											2011-04-17 20:46:00 +08:00
										 |  |  | 	&add	(&DWP(0,$out),$lastdiff); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&rdtsc	();			# collect 1st diff | 
					
						
							|  |  |  | 	&mov	("edx","eax");		# put aside tick (yes, I neglect edx) | 
					
						
							|  |  |  | 	&sub	("eax",$lasttick);	# diff | 
					
						
							|  |  |  | 	&mov	($lasttick,"edx");	# lasttick = tick | 
					
						
							|  |  |  | 	&mov	($lastdiff,"eax");	# lastdiff = diff | 
					
						
							|  |  |  | 	&jmp	(&label("loop2")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | &set_label("loop2",16); | 
					
						
							|  |  |  | 	&clflush(&DWP(0,$out)); | 
					
						
							| 
									
										
										
										
											2011-05-17 04:35:11 +08:00
										 |  |  | 	&data_byte(0xf0);		# lock | 
					
						
							| 
									
										
										
										
											2011-04-17 20:46:00 +08:00
										 |  |  | 	&add	(&DWP(0,$out),"eax");	# accumulate diff | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&sub	($max,1); | 
					
						
							|  |  |  | 	&jz	(&label("done2")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&rdtsc	(); | 
					
						
							|  |  |  | 	&mov	("edx","eax");		# put aside tick (yes, I neglect edx) | 
					
						
							|  |  |  | 	&sub	("eax",$lasttick);	# diff | 
					
						
							|  |  |  | 	&mov	($lasttick,"edx");	# lasttick = tick | 
					
						
							|  |  |  | 	&cmp	("eax",$lastdiff); | 
					
						
							|  |  |  | 	&mov	($lastdiff,"eax");	# lastdiff = diff | 
					
						
							|  |  |  | 	&mov	("edx",0); | 
					
						
							|  |  |  | 	&setne	("dl"); | 
					
						
							|  |  |  | 	&sub	($cnt,"edx");		# conditional --$cnt | 
					
						
							|  |  |  | 	&lea	($out,&DWP(0,$out,"edx",4));	# conditional ++$out | 
					
						
							|  |  |  | 	&jnz	(&label("loop2")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | &set_label("done2"); | 
					
						
							|  |  |  | 	&mov	("eax",&wparam(1)); | 
					
						
							|  |  |  | 	&sub	("eax",$cnt); | 
					
						
							|  |  |  | &set_label("nogo"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | &function_end("OPENSSL_instrument_bus2"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-10 18:05:43 +08:00
										 |  |  | sub gen_random { | 
					
						
							|  |  |  | my $rdop = shift; | 
					
						
							|  |  |  | &function_begin_B("OPENSSL_ia32_${rdop}_bytes"); | 
					
						
							|  |  |  | 	&push	("edi"); | 
					
						
							|  |  |  | 	&push	("ebx"); | 
					
						
							|  |  |  | 	&xor	("eax","eax");		# return value | 
					
						
							|  |  |  | 	&mov	("edi",&wparam(0)); | 
					
						
							|  |  |  | 	&mov	("ebx",&wparam(1)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	&cmp	("ebx",0); | 
					
						
							|  |  |  | 	&je	(&label("done")); | 
					
						
							| 
									
										
										
										
											2011-06-04 20:20:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-15 00:24:12 +08:00
										 |  |  | 	&mov	("ecx",8); | 
					
						
							|  |  |  | &set_label("loop"); | 
					
						
							| 
									
										
										
										
											2016-07-10 18:05:43 +08:00
										 |  |  | 	&${rdop}("edx"); | 
					
						
							| 
									
										
										
										
											2014-02-15 00:24:12 +08:00
										 |  |  | 	&jc	(&label("break")); | 
					
						
							|  |  |  | 	&loop	(&label("loop")); | 
					
						
							| 
									
										
										
										
											2016-07-10 18:05:43 +08:00
										 |  |  | 	&jmp	(&label("done")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | &set_label("break",16); | 
					
						
							|  |  |  | 	&cmp	("ebx",4); | 
					
						
							|  |  |  | 	&jb	(&label("tail")); | 
					
						
							|  |  |  | 	&mov	(&DWP(0,"edi"),"edx"); | 
					
						
							|  |  |  | 	&lea	("edi",&DWP(4,"edi")); | 
					
						
							|  |  |  | 	&add	("eax",4); | 
					
						
							|  |  |  | 	&sub	("ebx",4); | 
					
						
							|  |  |  | 	&jz	(&label("done")); | 
					
						
							|  |  |  | 	&mov	("ecx",8); | 
					
						
							|  |  |  | 	&jmp	(&label("loop")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | &set_label("tail",16); | 
					
						
							|  |  |  | 	&mov	(&BP(0,"edi"),"dl"); | 
					
						
							|  |  |  | 	&lea	("edi",&DWP(1,"edi")); | 
					
						
							|  |  |  | 	&inc	("eax"); | 
					
						
							|  |  |  | 	&shr	("edx",8); | 
					
						
							|  |  |  | 	&dec	("ebx"); | 
					
						
							|  |  |  | 	&jnz	(&label("tail")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | &set_label("done"); | 
					
						
							| 
									
										
											  
											
												Fix issues in ia32 RDRAND asm leading to reduced entropy
This patch fixes two issues in the ia32 RDRAND assembly code that result in a
(possibly significant) loss of entropy.
The first, less significant, issue is that, by returning success as 0 from
OPENSSL_ia32_rdrand() and OPENSSL_ia32_rdseed(), a subtle bias was introduced.
Specifically, because the assembly routine copied the remaining number of
retries over the result when RDRAND/RDSEED returned 'successful but zero', a
bias towards values 1-8 (primarily 8) was introduced.
The second, more worrying issue was that, due to a mixup in registers, when a
buffer that was not size 0 or 1 mod 8 was passed to OPENSSL_ia32_rdrand_bytes
or OPENSSL_ia32_rdseed_bytes, the last (n mod 8) bytes were all the same value.
This issue impacts only the 64-bit variant of the assembly.
This change fixes both issues by first eliminating the only use of
OPENSSL_ia32_rdrand, replacing it with OPENSSL_ia32_rdrand_bytes, and fixes the
register mixup in OPENSSL_ia32_rdrand_bytes. It also adds a sanity test for
OPENSSL_ia32_rdrand_bytes and OPENSSL_ia32_rdseed_bytes to help catch problems
of this nature in the future.
Reviewed-by: Andy Polyakov <appro@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5342)
											
										 
											2018-03-08 05:01:06 +08:00
										 |  |  | 	&xor	("edx","edx");		# Clear random value from registers | 
					
						
							| 
									
										
										
										
											2016-07-10 18:05:43 +08:00
										 |  |  | 	&pop	("ebx"); | 
					
						
							|  |  |  | 	&pop	("edi"); | 
					
						
							| 
									
										
										
										
											2014-02-15 00:24:12 +08:00
										 |  |  | 	&ret	(); | 
					
						
							| 
									
										
										
										
											2016-07-10 18:05:43 +08:00
										 |  |  | &function_end_B("OPENSSL_ia32_${rdop}_bytes"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | &gen_random("rdrand"); | 
					
						
							|  |  |  | &gen_random("rdseed"); | 
					
						
							| 
									
										
										
										
											2014-02-15 00:24:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-29 22:19:59 +08:00
										 |  |  | &hidden("OPENSSL_cpuid_setup"); | 
					
						
							|  |  |  | &hidden("OPENSSL_ia32cap_P"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 04:18:55 +08:00
										 |  |  | &asm_finish(); | 
					
						
							| 
									
										
										
										
											2016-03-07 22:00:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-17 10:17:53 +08:00
										 |  |  | close STDOUT or die "error closing STDOUT: $!"; |