xref: /openbsd/lib/libcrypto/perlasm/cbc.pl (revision 0bd8ca4a)
1913ec974Sbeck#!/usr/local/bin/perl
25b37fcf3Sryker
35b37fcf3Sryker# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc)
45b37fcf3Sryker# des_cblock (*input);
55b37fcf3Sryker# des_cblock (*output);
65b37fcf3Sryker# long length;
75b37fcf3Sryker# des_key_schedule schedule;
85b37fcf3Sryker# des_cblock (*ivec);
95b37fcf3Sryker# int enc;
105b37fcf3Sryker#
115b37fcf3Sryker# calls
125b37fcf3Sryker# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
135b37fcf3Sryker#
145b37fcf3Sryker
155b37fcf3Sryker#&cbc("des_ncbc_encrypt","des_encrypt",0);
165b37fcf3Sryker#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",
175b37fcf3Sryker#	1,4,5,3,5,-1);
185b37fcf3Sryker#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",
195b37fcf3Sryker#	0,4,5,3,5,-1);
205b37fcf3Sryker#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",
215b37fcf3Sryker#	0,6,7,3,4,5);
225b37fcf3Sryker#
235b37fcf3Sryker# When doing a cipher that needs bigendian order,
245b37fcf3Sryker# for encrypt, the iv is kept in bigendian form,
255b37fcf3Sryker# while for decrypt, it is kept in little endian.
265b37fcf3Srykersub cbc
275b37fcf3Sryker	{
285b37fcf3Sryker	local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_;
295b37fcf3Sryker	# name is the function name
305b37fcf3Sryker	# enc_func and dec_func and the functions to call for encrypt/decrypt
315b37fcf3Sryker	# swap is true if byte order needs to be reversed
325b37fcf3Sryker	# iv_off is parameter number for the iv
335b37fcf3Sryker	# enc_off is parameter number for the encrypt/decrypt flag
345b37fcf3Sryker	# p1,p2,p3 are the offsets for parameters to be passed to the
355b37fcf3Sryker	# underlying calls.
365b37fcf3Sryker
37*0bd8ca4aSmiod&static_label("cbc_enc_jmp_table_".$name);
38*0bd8ca4aSmiod&static_label("ej1_".$name);
39*0bd8ca4aSmiod&static_label("ej2_".$name);
40*0bd8ca4aSmiod&static_label("ej3_".$name);
41*0bd8ca4aSmiod&static_label("ej4_".$name);
42*0bd8ca4aSmiod&static_label("ej5_".$name);
43*0bd8ca4aSmiod&static_label("ej6_".$name);
44*0bd8ca4aSmiod&static_label("ej7_".$name);
45*0bd8ca4aSmiod
465b37fcf3Sryker	&function_begin_B($name,"");
475b37fcf3Sryker	&comment("");
485b37fcf3Sryker
495b37fcf3Sryker	$in="esi";
505b37fcf3Sryker	$out="edi";
515b37fcf3Sryker	$count="ebp";
525b37fcf3Sryker
535b37fcf3Sryker	&push("ebp");
545b37fcf3Sryker	&push("ebx");
555b37fcf3Sryker	&push("esi");
565b37fcf3Sryker	&push("edi");
575b37fcf3Sryker
585b37fcf3Sryker	$data_off=4;
595b37fcf3Sryker	$data_off+=4 if ($p1 > 0);
605b37fcf3Sryker	$data_off+=4 if ($p2 > 0);
615b37fcf3Sryker	$data_off+=4 if ($p3 > 0);
625b37fcf3Sryker
635b37fcf3Sryker	&mov($count,	&wparam(2));	# length
645b37fcf3Sryker
655b37fcf3Sryker	&comment("getting iv ptr from parameter $iv_off");
665b37fcf3Sryker	&mov("ebx",	&wparam($iv_off));	# Get iv ptr
675b37fcf3Sryker
685b37fcf3Sryker	&mov($in,	&DWP(0,"ebx","",0));#	iv[0]
695b37fcf3Sryker	&mov($out,	&DWP(4,"ebx","",0));#	iv[1]
705b37fcf3Sryker
715b37fcf3Sryker	&push($out);
725b37fcf3Sryker	&push($in);
735b37fcf3Sryker	&push($out);	# used in decrypt for iv[1]
745b37fcf3Sryker	&push($in);	# used in decrypt for iv[0]
755b37fcf3Sryker
765b37fcf3Sryker	&mov("ebx",	"esp");		# This is the address of tin[2]
775b37fcf3Sryker
785b37fcf3Sryker	&mov($in,	&wparam(0));	# in
795b37fcf3Sryker	&mov($out,	&wparam(1));	# out
805b37fcf3Sryker
815b37fcf3Sryker	# We have loaded them all, how lets push things
825b37fcf3Sryker	&comment("getting encrypt flag from parameter $enc_off");
835b37fcf3Sryker	&mov("ecx",	&wparam($enc_off));	# Get enc flag
845b37fcf3Sryker	if ($p3 > 0)
855b37fcf3Sryker		{
865b37fcf3Sryker		&comment("get and push parameter $p3");
875b37fcf3Sryker		if ($enc_off != $p3)
885b37fcf3Sryker			{ &mov("eax",	&wparam($p3)); &push("eax"); }
895b37fcf3Sryker		else	{ &push("ecx"); }
905b37fcf3Sryker		}
915b37fcf3Sryker	if ($p2 > 0)
925b37fcf3Sryker		{
935b37fcf3Sryker		&comment("get and push parameter $p2");
945b37fcf3Sryker		if ($enc_off != $p2)
955b37fcf3Sryker			{ &mov("eax",	&wparam($p2)); &push("eax"); }
965b37fcf3Sryker		else	{ &push("ecx"); }
975b37fcf3Sryker		}
985b37fcf3Sryker	if ($p1 > 0)
995b37fcf3Sryker		{
1005b37fcf3Sryker		&comment("get and push parameter $p1");
1015b37fcf3Sryker		if ($enc_off != $p1)
1025b37fcf3Sryker			{ &mov("eax",	&wparam($p1)); &push("eax"); }
1035b37fcf3Sryker		else	{ &push("ecx"); }
1045b37fcf3Sryker		}
1055b37fcf3Sryker	&push("ebx");		# push data/iv
1065b37fcf3Sryker
1075b37fcf3Sryker	&cmp("ecx",0);
1085b37fcf3Sryker	&jz(&label("decrypt"));
1095b37fcf3Sryker
1105b37fcf3Sryker	&and($count,0xfffffff8);
1115b37fcf3Sryker	&mov("eax",	&DWP($data_off,"esp","",0));	# load iv[0]
1125b37fcf3Sryker	&mov("ebx",	&DWP($data_off+4,"esp","",0));	# load iv[1]
1135b37fcf3Sryker
1145b37fcf3Sryker	&jz(&label("encrypt_finish"));
1155b37fcf3Sryker
1165b37fcf3Sryker	#############################################################
1175b37fcf3Sryker
1185b37fcf3Sryker	&set_label("encrypt_loop");
1195b37fcf3Sryker	# encrypt start
1205b37fcf3Sryker	# "eax" and "ebx" hold iv (or the last cipher text)
1215b37fcf3Sryker
1225b37fcf3Sryker	&mov("ecx",	&DWP(0,$in,"",0));	# load first 4 bytes
1235b37fcf3Sryker	&mov("edx",	&DWP(4,$in,"",0));	# second 4 bytes
1245b37fcf3Sryker
1255b37fcf3Sryker	&xor("eax",	"ecx");
1265b37fcf3Sryker	&xor("ebx",	"edx");
1275b37fcf3Sryker
1285b37fcf3Sryker	&bswap("eax")	if $swap;
1295b37fcf3Sryker	&bswap("ebx")	if $swap;
1305b37fcf3Sryker
1315b37fcf3Sryker	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
1325b37fcf3Sryker	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
1335b37fcf3Sryker
1345b37fcf3Sryker	&call($enc_func);
1355b37fcf3Sryker
1365b37fcf3Sryker	&mov("eax",	&DWP($data_off,"esp","",0));
1375b37fcf3Sryker	&mov("ebx",	&DWP($data_off+4,"esp","",0));
1385b37fcf3Sryker
1395b37fcf3Sryker	&bswap("eax")	if $swap;
1405b37fcf3Sryker	&bswap("ebx")	if $swap;
1415b37fcf3Sryker
1425b37fcf3Sryker	&mov(&DWP(0,$out,"",0),"eax");
1435b37fcf3Sryker	&mov(&DWP(4,$out,"",0),"ebx");
1445b37fcf3Sryker
1455b37fcf3Sryker	# eax and ebx are the next iv.
1465b37fcf3Sryker
1475b37fcf3Sryker	&add($in,	8);
1485b37fcf3Sryker	&add($out,	8);
1495b37fcf3Sryker
1505b37fcf3Sryker	&sub($count,	8);
1515b37fcf3Sryker	&jnz(&label("encrypt_loop"));
1525b37fcf3Sryker
1535b37fcf3Sryker###################################################################3
1545b37fcf3Sryker	&set_label("encrypt_finish");
1555b37fcf3Sryker	&mov($count,	&wparam(2));	# length
1565b37fcf3Sryker	&and($count,	7);
1575b37fcf3Sryker	&jz(&label("finish"));
158*0bd8ca4aSmiod
159*0bd8ca4aSmiod	&picsetup("edx");
160*0bd8ca4aSmiod	&picsymbol("ecx", &label("cbc_enc_jmp_table_".$name), "edx")
16197222eddSmiod	&mov($count,&DWP(0,"ecx",$count,4));
162*0bd8ca4aSmiod	&picadjust($count, "edx");
163*0bd8ca4aSmiod
1645b37fcf3Sryker	&xor("ecx","ecx");
1655b37fcf3Sryker	&xor("edx","edx");
1665b37fcf3Sryker	&jmp_ptr($count);
1675b37fcf3Sryker
168*0bd8ca4aSmiod&set_label("ej7_".$name);
1695b37fcf3Sryker	&movb(&HB("edx"),	&BP(6,$in,"",0));
1705b37fcf3Sryker	&shl("edx",8);
171*0bd8ca4aSmiod&set_label("ej6_".$name);
1725b37fcf3Sryker	&movb(&HB("edx"),	&BP(5,$in,"",0));
173*0bd8ca4aSmiod&set_label("ej5_".$name);
1745b37fcf3Sryker	&movb(&LB("edx"),	&BP(4,$in,"",0));
175*0bd8ca4aSmiod&set_label("ej4_".$name);
1765b37fcf3Sryker	&mov("ecx",		&DWP(0,$in,"",0));
1775b37fcf3Sryker	&jmp(&label("ejend"));
178*0bd8ca4aSmiod&set_label("ej3_".$name);
1795b37fcf3Sryker	&movb(&HB("ecx"),	&BP(2,$in,"",0));
1805b37fcf3Sryker	&shl("ecx",8);
181*0bd8ca4aSmiod&set_label("ej2_".$name);
1825b37fcf3Sryker	&movb(&HB("ecx"),	&BP(1,$in,"",0));
183*0bd8ca4aSmiod&set_label("ej1_".$name);
1845b37fcf3Sryker	&movb(&LB("ecx"),	&BP(0,$in,"",0));
1855b37fcf3Sryker&set_label("ejend");
1865b37fcf3Sryker
1875b37fcf3Sryker	&xor("eax",	"ecx");
1885b37fcf3Sryker	&xor("ebx",	"edx");
1895b37fcf3Sryker
1905b37fcf3Sryker	&bswap("eax")	if $swap;
1915b37fcf3Sryker	&bswap("ebx")	if $swap;
1925b37fcf3Sryker
1935b37fcf3Sryker	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
1945b37fcf3Sryker	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
1955b37fcf3Sryker
1965b37fcf3Sryker	&call($enc_func);
1975b37fcf3Sryker
1985b37fcf3Sryker	&mov("eax",	&DWP($data_off,"esp","",0));
1995b37fcf3Sryker	&mov("ebx",	&DWP($data_off+4,"esp","",0));
2005b37fcf3Sryker
2015b37fcf3Sryker	&bswap("eax")	if $swap;
2025b37fcf3Sryker	&bswap("ebx")	if $swap;
2035b37fcf3Sryker
2045b37fcf3Sryker	&mov(&DWP(0,$out,"",0),"eax");
2055b37fcf3Sryker	&mov(&DWP(4,$out,"",0),"ebx");
2065b37fcf3Sryker
2075b37fcf3Sryker	&jmp(&label("finish"));
2085b37fcf3Sryker
2095b37fcf3Sryker	#############################################################
2105b37fcf3Sryker	#############################################################
2115b37fcf3Sryker	&set_label("decrypt",1);
2125b37fcf3Sryker	# decrypt start
2135b37fcf3Sryker	&and($count,0xfffffff8);
2145b37fcf3Sryker	# The next 2 instructions are only for if the jz is taken
2155b37fcf3Sryker	&mov("eax",	&DWP($data_off+8,"esp","",0));	# get iv[0]
2165b37fcf3Sryker	&mov("ebx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
2175b37fcf3Sryker	&jz(&label("decrypt_finish"));
2185b37fcf3Sryker
2195b37fcf3Sryker	&set_label("decrypt_loop");
2205b37fcf3Sryker	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
2215b37fcf3Sryker	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
2225b37fcf3Sryker
2235b37fcf3Sryker	&bswap("eax")	if $swap;
2245b37fcf3Sryker	&bswap("ebx")	if $swap;
2255b37fcf3Sryker
2265b37fcf3Sryker	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
2275b37fcf3Sryker	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
2285b37fcf3Sryker
2295b37fcf3Sryker	&call($dec_func);
2305b37fcf3Sryker
2315b37fcf3Sryker	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
2325b37fcf3Sryker	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
2335b37fcf3Sryker
2345b37fcf3Sryker	&bswap("eax")	if $swap;
2355b37fcf3Sryker	&bswap("ebx")	if $swap;
2365b37fcf3Sryker
2375b37fcf3Sryker	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
2385b37fcf3Sryker	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
2395b37fcf3Sryker
2405b37fcf3Sryker	&xor("ecx",	"eax");
2415b37fcf3Sryker	&xor("edx",	"ebx");
2425b37fcf3Sryker
2435b37fcf3Sryker	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
2445b37fcf3Sryker	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
2455b37fcf3Sryker
2465b37fcf3Sryker	&mov(&DWP(0,$out,"",0),"ecx");
2475b37fcf3Sryker	&mov(&DWP(4,$out,"",0),"edx");
2485b37fcf3Sryker
2495b37fcf3Sryker	&mov(&DWP($data_off+8,"esp","",0),	"eax");	# save iv
2505b37fcf3Sryker	&mov(&DWP($data_off+12,"esp","",0),	"ebx");	#
2515b37fcf3Sryker
2525b37fcf3Sryker	&add($in,	8);
2535b37fcf3Sryker	&add($out,	8);
2545b37fcf3Sryker
2555b37fcf3Sryker	&sub($count,	8);
2565b37fcf3Sryker	&jnz(&label("decrypt_loop"));
2575b37fcf3Sryker############################ ENDIT #######################3
2585b37fcf3Sryker	&set_label("decrypt_finish");
2595b37fcf3Sryker	&mov($count,	&wparam(2));	# length
2605b37fcf3Sryker	&and($count,	7);
2615b37fcf3Sryker	&jz(&label("finish"));
2625b37fcf3Sryker
2635b37fcf3Sryker	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
2645b37fcf3Sryker	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
2655b37fcf3Sryker
2665b37fcf3Sryker	&bswap("eax")	if $swap;
2675b37fcf3Sryker	&bswap("ebx")	if $swap;
2685b37fcf3Sryker
2695b37fcf3Sryker	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
2705b37fcf3Sryker	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
2715b37fcf3Sryker
2725b37fcf3Sryker	&call($dec_func);
2735b37fcf3Sryker
2745b37fcf3Sryker	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
2755b37fcf3Sryker	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
2765b37fcf3Sryker
2775b37fcf3Sryker	&bswap("eax")	if $swap;
2785b37fcf3Sryker	&bswap("ebx")	if $swap;
2795b37fcf3Sryker
2805b37fcf3Sryker	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
2815b37fcf3Sryker	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
2825b37fcf3Sryker
2835b37fcf3Sryker	&xor("ecx",	"eax");
2845b37fcf3Sryker	&xor("edx",	"ebx");
2855b37fcf3Sryker
2865b37fcf3Sryker	# this is for when we exit
2875b37fcf3Sryker	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
2885b37fcf3Sryker	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
2895b37fcf3Sryker
2905b37fcf3Sryker	&rotr("edx",	16);
2915b37fcf3Sryker	&movb(&BP(6,$out,"",0),	&LB("edx"));
2925b37fcf3Sryker	&shr("edx",16);
2935b37fcf3Sryker	&movb(&BP(5,$out,"",0),	&HB("edx"));
2945b37fcf3Sryker	&movb(&BP(4,$out,"",0),	&LB("edx"));
2955b37fcf3Sryker	&mov(&DWP(0,$out,"",0),	"ecx");
2965b37fcf3Sryker
2975b37fcf3Sryker	# final iv is still in eax:ebx
2985b37fcf3Sryker
2995b37fcf3Sryker############################ FINISH #######################3
3005b37fcf3Sryker	&set_label("finish",1);
3015b37fcf3Sryker	&mov("ecx",	&wparam($iv_off));	# Get iv ptr
3025b37fcf3Sryker
3035b37fcf3Sryker	#################################################
3045b37fcf3Sryker	$total=16+4;
3055b37fcf3Sryker	$total+=4 if ($p1 > 0);
3065b37fcf3Sryker	$total+=4 if ($p2 > 0);
3075b37fcf3Sryker	$total+=4 if ($p3 > 0);
3085b37fcf3Sryker	&add("esp",$total);
3095b37fcf3Sryker
3105b37fcf3Sryker	&mov(&DWP(0,"ecx","",0),	"eax");	# save iv
3115b37fcf3Sryker	&mov(&DWP(4,"ecx","",0),	"ebx");	# save iv
3125b37fcf3Sryker
3135b37fcf3Sryker	&function_end_A($name);
3145b37fcf3Sryker	&function_end_B($name);
3155b37fcf3Sryker
316*0bd8ca4aSmiod	&rodataseg();
317*0bd8ca4aSmiod	&align(64);
318*0bd8ca4aSmiod	&set_label("cbc_enc_jmp_table_".$name);
319*0bd8ca4aSmiod	&data_word("0");
320*0bd8ca4aSmiod	&data_word(&code_sym(&label("ej1_".$name)));
321*0bd8ca4aSmiod	&data_word(&code_sym(&label("ej2_".$name)));
322*0bd8ca4aSmiod	&data_word(&code_sym(&label("ej3_".$name)));
323*0bd8ca4aSmiod	&data_word(&code_sym(&label("ej4_".$name)));
324*0bd8ca4aSmiod	&data_word(&code_sym(&label("ej5_".$name)));
325*0bd8ca4aSmiod	&data_word(&code_sym(&label("ej6_".$name)));
326*0bd8ca4aSmiod	&data_word(&code_sym(&label("ej7_".$name)));
327*0bd8ca4aSmiod	&previous();
328*0bd8ca4aSmiod
3295b37fcf3Sryker	}
3305b37fcf3Sryker
3315b37fcf3Sryker1;
332