mirror of https://github.com/openssl/openssl.git
				
				
				
			
		
			
	
	
		
			125 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
		
		
			
		
	
	
			125 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| 
								 | 
							
								The perl scripts in this directory are my 'hack' to generate
							 | 
						||
| 
								 | 
							
								multiple different assembler formats via the one origional script.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The way to use this library is to start with adding the path to this directory
							 | 
						||
| 
								 | 
							
								and then include it.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								push(@INC,"perlasm","../../perlasm");
							 | 
						||
| 
								 | 
							
								require "x86asm.pl";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The first thing we do is setup the file and type of assember
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								&asm_init($ARGV[0],$0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The first argument is the 'type'.  Currently
							 | 
						||
| 
								 | 
							
								'cpp', 'sol', 'a.out', 'elf' or 'win32'.
							 | 
						||
| 
								 | 
							
								Argument 2 is the file name.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The reciprocal function is
							 | 
						||
| 
								 | 
							
								&asm_finish() which should be called at the end.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								There are 2 main 'packages'. x86ms.pl, which is the microsoft assembler,
							 | 
						||
| 
								 | 
							
								and x86unix.pl which is the unix (gas) version.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Functions of interest are:
							 | 
						||
| 
								 | 
							
								&external_label("des_SPtrans");	declare and external variable
							 | 
						||
| 
								 | 
							
								&LB(reg);			Low byte for a register
							 | 
						||
| 
								 | 
							
								&HB(reg);			High byte for a register
							 | 
						||
| 
								 | 
							
								&BP(off,base,index,scale)	Byte pointer addressing
							 | 
						||
| 
								 | 
							
								&DWP(off,base,index,scale)	Word pointer addressing
							 | 
						||
| 
								 | 
							
								&stack_push(num)		Basically a 'sub esp, num*4' with extra
							 | 
						||
| 
								 | 
							
								&stack_pop(num)			inverse of stack_push
							 | 
						||
| 
								 | 
							
								&function_begin(name,extra)	Start a function with pushing of
							 | 
						||
| 
								 | 
							
												edi, esi, ebx and ebp.  extra is extra win32
							 | 
						||
| 
								 | 
							
												external info that may be required.
							 | 
						||
| 
								 | 
							
								&function_begin_B(name,extra)	Same as norma function_begin but no pushing.
							 | 
						||
| 
								 | 
							
								&function_end(name)		Call at end of function.
							 | 
						||
| 
								 | 
							
								&function_end_A(name)		Standard pop and ret, for use inside functions
							 | 
						||
| 
								 | 
							
								&function_end_B(name)		Call at end but with poping or 'ret'.
							 | 
						||
| 
								 | 
							
								&swtmp(num)			Address on stack temp word.
							 | 
						||
| 
								 | 
							
								&wparam(num)			Parameter number num, that was push
							 | 
						||
| 
								 | 
							
												in C convention.  This all works over pushes
							 | 
						||
| 
								 | 
							
												and pops.
							 | 
						||
| 
								 | 
							
								&comment("hello there")		Put in a comment.
							 | 
						||
| 
								 | 
							
								&label("loop")			Refer to a label, normally a jmp target.
							 | 
						||
| 
								 | 
							
								&set_label("loop")		Set a label at this point.
							 | 
						||
| 
								 | 
							
								&data_word(word)		Put in a word of data.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								So how does this all hold together?  Given
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int calc(int len, int *data)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									int i,j=0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (i=0; i<len; i++)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
										j+=other(data[i]);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								So a very simple version of this function could be coded as
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									push(@INC,"perlasm","../../perlasm");
							 | 
						||
| 
								 | 
							
									require "x86asm.pl";
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									&asm_init($ARGV[0],"cacl.pl");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									&external_label("other");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									$tmp1=	"eax";
							 | 
						||
| 
								 | 
							
									$j=	"edi";
							 | 
						||
| 
								 | 
							
									$data=	"esi";
							 | 
						||
| 
								 | 
							
									$i=	"ebp";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									&comment("a simple function");
							 | 
						||
| 
								 | 
							
									&function_begin("calc");
							 | 
						||
| 
								 | 
							
									&mov(	$data,		&wparam(1)); # data
							 | 
						||
| 
								 | 
							
									&xor(	$j,		$j);
							 | 
						||
| 
								 | 
							
									&xor(	$i,		$i);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									&set_label("loop");
							 | 
						||
| 
								 | 
							
									&cmp(	$i,		&wparam(0));
							 | 
						||
| 
								 | 
							
									&jge(	&label("end"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									&mov(	$tmp1,		&DWP(0,$data,$i,4));
							 | 
						||
| 
								 | 
							
									&push(	$tmp1);
							 | 
						||
| 
								 | 
							
									&call(	"other");
							 | 
						||
| 
								 | 
							
									&add(	$j,		"eax");
							 | 
						||
| 
								 | 
							
									&pop(	$tmp1);
							 | 
						||
| 
								 | 
							
									&inc(	$i);
							 | 
						||
| 
								 | 
							
									&jmp(	&label("loop"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									&set_label("end");
							 | 
						||
| 
								 | 
							
									&mov(	"eax",		$j);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									&function_end("calc");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									&asm_finish();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The above example is very very unoptimised but gives an idea of how
							 | 
						||
| 
								 | 
							
								things work.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								There is also a cbc mode function generator in cbc.pl
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								&cbc(	$name,
							 | 
						||
| 
								 | 
							
									$encrypt_function_name,
							 | 
						||
| 
								 | 
							
									$decrypt_function_name,
							 | 
						||
| 
								 | 
							
									$true_if_byte_swap_needed,
							 | 
						||
| 
								 | 
							
									$parameter_number_for_iv,
							 | 
						||
| 
								 | 
							
									$parameter_number_for_encrypt_flag,
							 | 
						||
| 
								 | 
							
									$first_parameter_to_pass,
							 | 
						||
| 
								 | 
							
									$second_parameter_to_pass,
							 | 
						||
| 
								 | 
							
									$third_parameter_to_pass);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								So for example, given
							 | 
						||
| 
								 | 
							
								void BF_encrypt(BF_LONG *data,BF_KEY *key);
							 | 
						||
| 
								 | 
							
								void BF_decrypt(BF_LONG *data,BF_KEY *key);
							 | 
						||
| 
								 | 
							
								void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length,
							 | 
						||
| 
								 | 
							
								        BF_KEY *ks, unsigned char *iv, int enc);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1);
							 | 
						||
| 
								 | 
							
								&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5);
							 | 
						||
| 
								 | 
							
								
							 |