1#!/usr/local/bin/perl
2#
3# The inner loop instruction sequence and the IP/FP modifications are from
4# Svend Olaf Mikkelsen <svolaf@inet.uni-c.dk>
5#
6
7push(@INC,"perlasm","../../perlasm");
8require "x86asm.pl";
9require "cbc.pl";
10require "desboth.pl";
11
12# base code is in microsft
13# op dest, source
14# format.
15#
16
17&asm_init($ARGV[0],"des-586.pl");
18
19$L="edi";
20$R="esi";
21
22&external_label("DES_SPtrans");
23&DES_encrypt("DES_encrypt1",1);
24&DES_encrypt("DES_encrypt2",0);
25&DES_encrypt3("DES_encrypt3",1);
26&DES_encrypt3("DES_decrypt3",0);
27&cbc("DES_ncbc_encrypt","DES_encrypt1","DES_encrypt1",0,4,5,3,5,-1);
28&cbc("DES_ede3_cbc_encrypt","DES_encrypt3","DES_decrypt3",0,6,7,3,4,5);
29
30&asm_finish();
31
32sub DES_encrypt
33	{
34	local($name,$do_ip)=@_;
35
36	&function_begin_B($name,"EXTRN   _DES_SPtrans:DWORD");
37
38	&push("esi");
39	&push("edi");
40
41	&comment("");
42	&comment("Load the 2 words");
43	$trans="ebp";
44
45	if ($do_ip)
46		{
47		&mov($R,&wparam(0));
48		 &xor(	"ecx",		"ecx"		);
49
50		&push("ebx");
51		&push("ebp");
52
53		&mov("eax",&DWP(0,$R,"",0));
54		 &mov("ebx",&wparam(2));	# get encrypt flag
55		&mov($L,&DWP(4,$R,"",0));
56		&comment("");
57		&comment("IP");
58		&IP_new("eax",$L,$R,3);
59		}
60	else
61		{
62		&mov("eax",&wparam(0));
63		 &xor(	"ecx",		"ecx"		);
64
65		&push("ebx");
66		&push("ebp");
67
68		&mov($R,&DWP(0,"eax","",0));
69		 &mov("ebx",&wparam(2));	# get encrypt flag
70		&rotl($R,3);
71		&mov($L,&DWP(4,"eax","",0));
72		&rotl($L,3);
73		}
74
75	# PIC-ification:-)
76	&picmeup($trans,"DES_SPtrans");
77	#if ($cpp)	{ &picmeup($trans,"DES_SPtrans");   }
78	#else		{ &lea($trans,&DWP("DES_SPtrans")); }
79
80	&mov(	"ecx",	&wparam(1)	);
81	&cmp("ebx","0");
82	&je(&label("start_decrypt"));
83
84	for ($i=0; $i<16; $i+=2)
85		{
86		&comment("");
87		&comment("Round $i");
88		&D_ENCRYPT($i,$L,$R,$i*2,$trans,"eax","ebx","ecx","edx");
89
90		&comment("");
91		&comment("Round ".sprintf("%d",$i+1));
92		&D_ENCRYPT($i+1,$R,$L,($i+1)*2,$trans,"eax","ebx","ecx","edx");
93		}
94	&jmp(&label("end"));
95
96	&set_label("start_decrypt");
97
98	for ($i=15; $i>0; $i-=2)
99		{
100		&comment("");
101		&comment("Round $i");
102		&D_ENCRYPT(15-$i,$L,$R,$i*2,$trans,"eax","ebx","ecx","edx");
103		&comment("");
104		&comment("Round ".sprintf("%d",$i-1));
105		&D_ENCRYPT(15-$i+1,$R,$L,($i-1)*2,$trans,"eax","ebx","ecx","edx");
106		}
107
108	&set_label("end");
109
110	if ($do_ip)
111		{
112		&comment("");
113		&comment("FP");
114		&mov("edx",&wparam(0));
115		&FP_new($L,$R,"eax",3);
116
117		&mov(&DWP(0,"edx","",0),"eax");
118		&mov(&DWP(4,"edx","",0),$R);
119		}
120	else
121		{
122		&comment("");
123		&comment("Fixup");
124		&rotr($L,3);		# r
125		 &mov("eax",&wparam(0));
126		&rotr($R,3);		# l
127		 &mov(&DWP(0,"eax","",0),$L);
128		 &mov(&DWP(4,"eax","",0),$R);
129		}
130
131	&pop("ebp");
132	&pop("ebx");
133	&pop("edi");
134	&pop("esi");
135	&ret();
136
137	&function_end_B($name);
138	}
139
140sub D_ENCRYPT
141	{
142	local($r,$L,$R,$S,$trans,$u,$tmp1,$tmp2,$t)=@_;
143
144	 &mov(	$u,		&DWP(&n2a($S*4),$tmp2,"",0));
145	&xor(	$tmp1,		$tmp1);
146	 &mov(	$t,		&DWP(&n2a(($S+1)*4),$tmp2,"",0));
147	&xor(	$u,		$R);
148	&xor(	$tmp2,		$tmp2);
149	 &xor(	$t,		$R);
150	&and(	$u,		"0xfcfcfcfc"	);
151	 &and(	$t,		"0xcfcfcfcf"	);
152	&movb(	&LB($tmp1),	&LB($u)	);
153	 &movb(	&LB($tmp2),	&HB($u)	);
154	&rotr(	$t,		4		);
155	&xor(	$L,		&DWP("     ",$trans,$tmp1,0));
156	 &movb(	&LB($tmp1),	&LB($t)	);
157	 &xor(	$L,		&DWP("0x200",$trans,$tmp2,0));
158	 &movb(	&LB($tmp2),	&HB($t)	);
159	&shr(	$u,		16);
160	 &xor(	$L,		&DWP("0x100",$trans,$tmp1,0));
161	 &movb(	&LB($tmp1),	&HB($u)	);
162	&shr(	$t,		16);
163	 &xor(	$L,		&DWP("0x300",$trans,$tmp2,0));
164	&movb(	&LB($tmp2),	&HB($t)	);
165	 &and(	$u,		"0xff"	);
166	&and(	$t,		"0xff"	);
167	 &xor(	$L,		&DWP("0x600",$trans,$tmp1,0));
168	 &xor(	$L,		&DWP("0x700",$trans,$tmp2,0));
169	&mov(	$tmp2,		&wparam(1)	);
170	 &xor(	$L,		&DWP("0x400",$trans,$u,0));
171	 &xor(	$L,		&DWP("0x500",$trans,$t,0));
172	}
173
174sub n2a
175	{
176	sprintf("%d",$_[0]);
177	}
178
179# now has a side affect of rotating $a by $shift
180sub R_PERM_OP
181	{
182	local($a,$b,$tt,$shift,$mask,$last)=@_;
183
184	&rotl(	$a,		$shift		) if ($shift != 0);
185	&mov(	$tt,		$a		);
186	&xor(	$a,		$b		);
187	&and(	$a,		$mask		);
188	# This can never succeed, and besides it is difficult to see what the
189	# idea was - Ben 13 Feb 99
190	if (!$last eq $b)
191		{
192		&xor(	$b,		$a		);
193		&xor(	$tt,		$a		);
194		}
195	else
196		{
197		&xor(	$tt,		$a		);
198		&xor(	$b,		$a		);
199		}
200	&comment("");
201	}
202
203sub IP_new
204	{
205	local($l,$r,$tt,$lr)=@_;
206
207	&R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l);
208	&R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l);
209	&R_PERM_OP($l,$tt,$r,14,"0x33333333",$r);
210	&R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r);
211	&R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r);
212
213	if ($lr != 3)
214		{
215		if (($lr-3) < 0)
216			{ &rotr($tt,	3-$lr); }
217		else	{ &rotl($tt,	$lr-3); }
218		}
219	if ($lr != 2)
220		{
221		if (($lr-2) < 0)
222			{ &rotr($r,	2-$lr); }
223		else	{ &rotl($r,	$lr-2); }
224		}
225	}
226
227sub FP_new
228	{
229	local($l,$r,$tt,$lr)=@_;
230
231	if ($lr != 2)
232		{
233		if (($lr-2) < 0)
234			{ &rotl($r,	2-$lr); }
235		else	{ &rotr($r,	$lr-2); }
236		}
237	if ($lr != 3)
238		{
239		if (($lr-3) < 0)
240			{ &rotl($l,	3-$lr); }
241		else	{ &rotr($l,	$lr-3); }
242		}
243
244	&R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r);
245	&R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r);
246	&R_PERM_OP($l,$r,$tt,10,"0x33333333",$l);
247	&R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l);
248	&R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r);
249	&rotr($tt	, 4);
250	}
251
252