155714Skris#!/usr/local/bin/perl
255714Skris
355714Skris# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc)
455714Skris# des_cblock (*input);
555714Skris# des_cblock (*output);
655714Skris# long length;
755714Skris# des_key_schedule schedule;
855714Skris# des_cblock (*ivec);
955714Skris# int enc;
1055714Skris#
1155714Skris# calls
1255714Skris# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
1355714Skris#
1455714Skris
1555714Skris#&cbc("des_ncbc_encrypt","des_encrypt",0);
1655714Skris#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",
1755714Skris#	1,4,5,3,5,-1);
1855714Skris#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",
1955714Skris#	0,4,5,3,5,-1);
2055714Skris#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",
2155714Skris#	0,6,7,3,4,5);
2255714Skris#
2355714Skris# When doing a cipher that needs bigendian order,
2455714Skris# for encrypt, the iv is kept in bigendian form,
2555714Skris# while for decrypt, it is kept in little endian.
2655714Skrissub cbc
2755714Skris	{
2855714Skris	local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_;
2955714Skris	# name is the function name
3055714Skris	# enc_func and dec_func and the functions to call for encrypt/decrypt
3155714Skris	# swap is true if byte order needs to be reversed
3255714Skris	# iv_off is parameter number for the iv
3355714Skris	# enc_off is parameter number for the encrypt/decrypt flag
3455714Skris	# p1,p2,p3 are the offsets for parameters to be passed to the
3555714Skris	# underlying calls.
3655714Skris
3755714Skris	&function_begin_B($name,"");
3855714Skris	&comment("");
3955714Skris
4055714Skris	$in="esi";
4155714Skris	$out="edi";
4255714Skris	$count="ebp";
4355714Skris
4455714Skris	&push("ebp");
4555714Skris	&push("ebx");
4655714Skris	&push("esi");
4755714Skris	&push("edi");
4855714Skris
4955714Skris	$data_off=4;
5055714Skris	$data_off+=4 if ($p1 > 0);
5155714Skris	$data_off+=4 if ($p2 > 0);
5255714Skris	$data_off+=4 if ($p3 > 0);
5355714Skris
5455714Skris	&mov($count,	&wparam(2));	# length
5555714Skris
5655714Skris	&comment("getting iv ptr from parameter $iv_off");
5755714Skris	&mov("ebx",	&wparam($iv_off));	# Get iv ptr
5855714Skris
5955714Skris	&mov($in,	&DWP(0,"ebx","",0));#	iv[0]
6055714Skris	&mov($out,	&DWP(4,"ebx","",0));#	iv[1]
6155714Skris
6255714Skris	&push($out);
6355714Skris	&push($in);
6455714Skris	&push($out);	# used in decrypt for iv[1]
6555714Skris	&push($in);	# used in decrypt for iv[0]
6655714Skris
6755714Skris	&mov("ebx",	"esp");		# This is the address of tin[2]
6855714Skris
6955714Skris	&mov($in,	&wparam(0));	# in
7055714Skris	&mov($out,	&wparam(1));	# out
7155714Skris
7255714Skris	# We have loaded them all, how lets push things
7355714Skris	&comment("getting encrypt flag from parameter $enc_off");
7455714Skris	&mov("ecx",	&wparam($enc_off));	# Get enc flag
7555714Skris	if ($p3 > 0)
7655714Skris		{
7755714Skris		&comment("get and push parameter $p3");
7855714Skris		if ($enc_off != $p3)
7955714Skris			{ &mov("eax",	&wparam($p3)); &push("eax"); }
8055714Skris		else	{ &push("ecx"); }
8155714Skris		}
8255714Skris	if ($p2 > 0)
8355714Skris		{
8455714Skris		&comment("get and push parameter $p2");
8555714Skris		if ($enc_off != $p2)
8655714Skris			{ &mov("eax",	&wparam($p2)); &push("eax"); }
8755714Skris		else	{ &push("ecx"); }
8855714Skris		}
8955714Skris	if ($p1 > 0)
9055714Skris		{
9155714Skris		&comment("get and push parameter $p1");
9255714Skris		if ($enc_off != $p1)
9355714Skris			{ &mov("eax",	&wparam($p1)); &push("eax"); }
9455714Skris		else	{ &push("ecx"); }
9555714Skris		}
9655714Skris	&push("ebx");		# push data/iv
9755714Skris
9855714Skris	&cmp("ecx",0);
9955714Skris	&jz(&label("decrypt"));
10055714Skris
10155714Skris	&and($count,0xfffffff8);
10255714Skris	&mov("eax",	&DWP($data_off,"esp","",0));	# load iv[0]
10355714Skris	&mov("ebx",	&DWP($data_off+4,"esp","",0));	# load iv[1]
10455714Skris
10555714Skris	&jz(&label("encrypt_finish"));
10655714Skris
10755714Skris	#############################################################
10855714Skris
10955714Skris	&set_label("encrypt_loop");
11055714Skris	# encrypt start
11155714Skris	# "eax" and "ebx" hold iv (or the last cipher text)
11255714Skris
11355714Skris	&mov("ecx",	&DWP(0,$in,"",0));	# load first 4 bytes
11455714Skris	&mov("edx",	&DWP(4,$in,"",0));	# second 4 bytes
11555714Skris
11655714Skris	&xor("eax",	"ecx");
11755714Skris	&xor("ebx",	"edx");
11855714Skris
11955714Skris	&bswap("eax")	if $swap;
12055714Skris	&bswap("ebx")	if $swap;
12155714Skris
12255714Skris	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
12355714Skris	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
12455714Skris
12555714Skris	&call($enc_func);
12655714Skris
12755714Skris	&mov("eax",	&DWP($data_off,"esp","",0));
12855714Skris	&mov("ebx",	&DWP($data_off+4,"esp","",0));
12955714Skris
13055714Skris	&bswap("eax")	if $swap;
13155714Skris	&bswap("ebx")	if $swap;
13255714Skris
13355714Skris	&mov(&DWP(0,$out,"",0),"eax");
13455714Skris	&mov(&DWP(4,$out,"",0),"ebx");
13555714Skris
13655714Skris	# eax and ebx are the next iv.
13755714Skris
13855714Skris	&add($in,	8);
13955714Skris	&add($out,	8);
14055714Skris
14155714Skris	&sub($count,	8);
14255714Skris	&jnz(&label("encrypt_loop"));
14355714Skris
14455714Skris###################################################################3
14555714Skris	&set_label("encrypt_finish");
14655714Skris	&mov($count,	&wparam(2));	# length
14755714Skris	&and($count,	7);
14855714Skris	&jz(&label("finish"));
149109998Smarkm	&call(&label("PIC_point"));
150109998Smarkm&set_label("PIC_point");
151109998Smarkm	&blindpop("edx");
152109998Smarkm	&lea("ecx",&DWP(&label("cbc_enc_jmp_table")."-".&label("PIC_point"),"edx"));
153246772Sjkim	&mov($count,&DWP(0,"ecx",$count,4));
154109998Smarkm	&add($count,"edx");
15555714Skris	&xor("ecx","ecx");
15655714Skris	&xor("edx","edx");
157109998Smarkm	#&mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4));
15855714Skris	&jmp_ptr($count);
15955714Skris
16055714Skris&set_label("ej7");
16155714Skris	&movb(&HB("edx"),	&BP(6,$in,"",0));
16255714Skris	&shl("edx",8);
16355714Skris&set_label("ej6");
16455714Skris	&movb(&HB("edx"),	&BP(5,$in,"",0));
16555714Skris&set_label("ej5");
16655714Skris	&movb(&LB("edx"),	&BP(4,$in,"",0));
16755714Skris&set_label("ej4");
16855714Skris	&mov("ecx",		&DWP(0,$in,"",0));
16955714Skris	&jmp(&label("ejend"));
17055714Skris&set_label("ej3");
17155714Skris	&movb(&HB("ecx"),	&BP(2,$in,"",0));
17255714Skris	&shl("ecx",8);
17355714Skris&set_label("ej2");
17455714Skris	&movb(&HB("ecx"),	&BP(1,$in,"",0));
17555714Skris&set_label("ej1");
17655714Skris	&movb(&LB("ecx"),	&BP(0,$in,"",0));
17755714Skris&set_label("ejend");
17855714Skris
17955714Skris	&xor("eax",	"ecx");
18055714Skris	&xor("ebx",	"edx");
18155714Skris
18255714Skris	&bswap("eax")	if $swap;
18355714Skris	&bswap("ebx")	if $swap;
18455714Skris
18555714Skris	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
18655714Skris	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
18755714Skris
18855714Skris	&call($enc_func);
18955714Skris
19055714Skris	&mov("eax",	&DWP($data_off,"esp","",0));
19155714Skris	&mov("ebx",	&DWP($data_off+4,"esp","",0));
19255714Skris
19355714Skris	&bswap("eax")	if $swap;
19455714Skris	&bswap("ebx")	if $swap;
19555714Skris
19655714Skris	&mov(&DWP(0,$out,"",0),"eax");
19755714Skris	&mov(&DWP(4,$out,"",0),"ebx");
19855714Skris
19955714Skris	&jmp(&label("finish"));
20055714Skris
20155714Skris	#############################################################
20255714Skris	#############################################################
20355714Skris	&set_label("decrypt",1);
20455714Skris	# decrypt start
20555714Skris	&and($count,0xfffffff8);
20655714Skris	# The next 2 instructions are only for if the jz is taken
20755714Skris	&mov("eax",	&DWP($data_off+8,"esp","",0));	# get iv[0]
20855714Skris	&mov("ebx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
20955714Skris	&jz(&label("decrypt_finish"));
21055714Skris
21155714Skris	&set_label("decrypt_loop");
21255714Skris	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
21355714Skris	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
21455714Skris
21555714Skris	&bswap("eax")	if $swap;
21655714Skris	&bswap("ebx")	if $swap;
21755714Skris
21855714Skris	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
21955714Skris	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
22055714Skris
22155714Skris	&call($dec_func);
22255714Skris
22355714Skris	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
22455714Skris	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
22555714Skris
22655714Skris	&bswap("eax")	if $swap;
22755714Skris	&bswap("ebx")	if $swap;
22855714Skris
22955714Skris	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
23055714Skris	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
23155714Skris
23255714Skris	&xor("ecx",	"eax");
23355714Skris	&xor("edx",	"ebx");
23455714Skris
23555714Skris	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
23655714Skris	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
23755714Skris
23855714Skris	&mov(&DWP(0,$out,"",0),"ecx");
23955714Skris	&mov(&DWP(4,$out,"",0),"edx");
24055714Skris
24155714Skris	&mov(&DWP($data_off+8,"esp","",0),	"eax");	# save iv
24255714Skris	&mov(&DWP($data_off+12,"esp","",0),	"ebx");	#
24355714Skris
24455714Skris	&add($in,	8);
24555714Skris	&add($out,	8);
24655714Skris
24755714Skris	&sub($count,	8);
24855714Skris	&jnz(&label("decrypt_loop"));
24955714Skris############################ ENDIT #######################3
25055714Skris	&set_label("decrypt_finish");
25155714Skris	&mov($count,	&wparam(2));	# length
25255714Skris	&and($count,	7);
25355714Skris	&jz(&label("finish"));
25455714Skris
25555714Skris	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
25655714Skris	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
25755714Skris
25855714Skris	&bswap("eax")	if $swap;
25955714Skris	&bswap("ebx")	if $swap;
26055714Skris
26155714Skris	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
26255714Skris	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
26355714Skris
26455714Skris	&call($dec_func);
26555714Skris
26655714Skris	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
26755714Skris	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
26855714Skris
26955714Skris	&bswap("eax")	if $swap;
27055714Skris	&bswap("ebx")	if $swap;
27155714Skris
27255714Skris	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
27355714Skris	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
27455714Skris
27555714Skris	&xor("ecx",	"eax");
27655714Skris	&xor("edx",	"ebx");
27755714Skris
27855714Skris	# this is for when we exit
27955714Skris	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
28055714Skris	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
28155714Skris
28255714Skris&set_label("dj7");
28355714Skris	&rotr("edx",	16);
28455714Skris	&movb(&BP(6,$out,"",0),	&LB("edx"));
28555714Skris	&shr("edx",16);
28655714Skris&set_label("dj6");
28755714Skris	&movb(&BP(5,$out,"",0),	&HB("edx"));
28855714Skris&set_label("dj5");
28955714Skris	&movb(&BP(4,$out,"",0),	&LB("edx"));
29055714Skris&set_label("dj4");
29155714Skris	&mov(&DWP(0,$out,"",0),	"ecx");
29255714Skris	&jmp(&label("djend"));
29355714Skris&set_label("dj3");
29455714Skris	&rotr("ecx",	16);
29555714Skris	&movb(&BP(2,$out,"",0),	&LB("ecx"));
29655714Skris	&shl("ecx",16);
29755714Skris&set_label("dj2");
29855714Skris	&movb(&BP(1,$in,"",0),	&HB("ecx"));
29955714Skris&set_label("dj1");
30055714Skris	&movb(&BP(0,$in,"",0),	&LB("ecx"));
30155714Skris&set_label("djend");
30255714Skris
30355714Skris	# final iv is still in eax:ebx
30455714Skris	&jmp(&label("finish"));
30555714Skris
30655714Skris
30755714Skris############################ FINISH #######################3
30855714Skris	&set_label("finish",1);
30955714Skris	&mov("ecx",	&wparam($iv_off));	# Get iv ptr
31055714Skris
31155714Skris	#################################################
31255714Skris	$total=16+4;
31355714Skris	$total+=4 if ($p1 > 0);
31455714Skris	$total+=4 if ($p2 > 0);
31555714Skris	$total+=4 if ($p3 > 0);
31655714Skris	&add("esp",$total);
31755714Skris
31855714Skris	&mov(&DWP(0,"ecx","",0),	"eax");	# save iv
31955714Skris	&mov(&DWP(4,"ecx","",0),	"ebx");	# save iv
32055714Skris
32155714Skris	&function_end_A($name);
32255714Skris
323160814Ssimon	&align(64);
324160814Ssimon	&set_label("cbc_enc_jmp_table");
32555714Skris	&data_word("0");
326109998Smarkm	&data_word(&label("ej1")."-".&label("PIC_point"));
327109998Smarkm	&data_word(&label("ej2")."-".&label("PIC_point"));
328109998Smarkm	&data_word(&label("ej3")."-".&label("PIC_point"));
329109998Smarkm	&data_word(&label("ej4")."-".&label("PIC_point"));
330109998Smarkm	&data_word(&label("ej5")."-".&label("PIC_point"));
331109998Smarkm	&data_word(&label("ej6")."-".&label("PIC_point"));
332109998Smarkm	&data_word(&label("ej7")."-".&label("PIC_point"));
333109998Smarkm	# not used
334109998Smarkm	#&set_label("cbc_dec_jmp_table",1);
335109998Smarkm	#&data_word("0");
336109998Smarkm	#&data_word(&label("dj1")."-".&label("PIC_point"));
337109998Smarkm	#&data_word(&label("dj2")."-".&label("PIC_point"));
338109998Smarkm	#&data_word(&label("dj3")."-".&label("PIC_point"));
339109998Smarkm	#&data_word(&label("dj4")."-".&label("PIC_point"));
340109998Smarkm	#&data_word(&label("dj5")."-".&label("PIC_point"));
341109998Smarkm	#&data_word(&label("dj6")."-".&label("PIC_point"));
342109998Smarkm	#&data_word(&label("dj7")."-".&label("PIC_point"));
343160814Ssimon	&align(64);
34455714Skris
34555714Skris	&function_end_B($name);
34655714Skris
34755714Skris	}
34855714Skris
34955714Skris1;
350