1#!/usr/local/bin/perl
2
3$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
4push(@INC,"${dir}","${dir}../../perlasm");
5require "x86asm.pl";
6require "cbc.pl";
7
8&asm_init($ARGV[0],"bf-586.pl",$ARGV[$#ARGV] eq "386");
9
10$BF_ROUNDS=16;
11$BF_OFF=($BF_ROUNDS+2)*4;
12$L="edi";
13$R="esi";
14$P="ebp";
15$tmp1="eax";
16$tmp2="ebx";
17$tmp3="ecx";
18$tmp4="edx";
19
20&BF_encrypt("BF_encrypt",1);
21&BF_encrypt("BF_decrypt",0);
22&cbc("BF_cbc_encrypt","BF_encrypt","BF_decrypt",1,4,5,3,-1,-1);
23&asm_finish();
24
25sub BF_encrypt
26	{
27	local($name,$enc)=@_;
28
29	&function_begin_B($name,"");
30
31	&comment("");
32
33	&push("ebp");
34	&push("ebx");
35	&mov($tmp2,&wparam(0));
36	&mov($P,&wparam(1));
37	&push("esi");
38	&push("edi");
39
40	&comment("Load the 2 words");
41	&mov($L,&DWP(0,$tmp2,"",0));
42	&mov($R,&DWP(4,$tmp2,"",0));
43
44	&xor(	$tmp1,	$tmp1);
45
46	# encrypting part
47
48	if ($enc)
49		{
50		 &mov($tmp2,&DWP(0,$P,"",0));
51		&xor(	$tmp3,	$tmp3);
52
53		&xor($L,$tmp2);
54		for ($i=0; $i<$BF_ROUNDS; $i+=2)
55			{
56			&comment("");
57			&comment("Round $i");
58			&BF_ENCRYPT($i+1,$R,$L,$P,$tmp1,$tmp2,$tmp3,$tmp4,1);
59
60			&comment("");
61			&comment("Round ".sprintf("%d",$i+1));
62			&BF_ENCRYPT($i+2,$L,$R,$P,$tmp1,$tmp2,$tmp3,$tmp4,1);
63			}
64		# &mov($tmp1,&wparam(0)); In last loop
65		&mov($tmp4,&DWP(($BF_ROUNDS+1)*4,$P,"",0));
66		}
67	else
68		{
69		 &mov($tmp2,&DWP(($BF_ROUNDS+1)*4,$P,"",0));
70		&xor(	$tmp3,	$tmp3);
71
72		&xor($L,$tmp2);
73		for ($i=$BF_ROUNDS; $i>0; $i-=2)
74			{
75			&comment("");
76			&comment("Round $i");
77			&BF_ENCRYPT($i,$R,$L,$P,$tmp1,$tmp2,$tmp3,$tmp4,0);
78			&comment("");
79			&comment("Round ".sprintf("%d",$i-1));
80			&BF_ENCRYPT($i-1,$L,$R,$P,$tmp1,$tmp2,$tmp3,$tmp4,0);
81			}
82		# &mov($tmp1,&wparam(0)); In last loop
83		&mov($tmp4,&DWP(0,$P,"",0));
84		}
85
86	&xor($R,$tmp4);
87	&mov(&DWP(4,$tmp1,"",0),$L);
88
89	&mov(&DWP(0,$tmp1,"",0),$R);
90	&function_end($name);
91	}
92
93sub BF_ENCRYPT
94	{
95	local($i,$L,$R,$P,$tmp1,$tmp2,$tmp3,$tmp4,$enc)=@_;
96
97	&mov(	$tmp4,		&DWP(&n2a($i*4),$P,"",0)); # for next round
98
99	&mov(	$tmp2,		$R);
100	&xor(	$L,		$tmp4);
101
102	&shr(	$tmp2,		16);
103	&mov(	$tmp4,		$R);
104
105	&movb(	&LB($tmp1),	&HB($tmp2));	# A
106	&and(	$tmp2,		0xff);		# B
107
108	&movb(	&LB($tmp3),	&HB($tmp4));	# C
109	&and(	$tmp4,		0xff);		# D
110
111	&mov(	$tmp1,		&DWP(&n2a($BF_OFF+0x0000),$P,$tmp1,4));
112	&mov(	$tmp2,		&DWP(&n2a($BF_OFF+0x0400),$P,$tmp2,4));
113
114	&add(	$tmp2,		$tmp1);
115	&mov(	$tmp1,		&DWP(&n2a($BF_OFF+0x0800),$P,$tmp3,4));
116
117	&xor(	$tmp2,		$tmp1);
118	&mov(	$tmp4,		&DWP(&n2a($BF_OFF+0x0C00),$P,$tmp4,4));
119
120	&add(	$tmp2,		$tmp4);
121	if (($enc && ($i != 16)) || ((!$enc) && ($i != 1)))
122		{ &xor(	$tmp1,		$tmp1); }
123	else
124		{
125		&comment("Load parameter 0 ($i) enc=$enc");
126		&mov($tmp1,&wparam(0));
127		} # In last loop
128
129	&xor(	$L,		$tmp2);
130	# delay
131	}
132
133sub n2a
134	{
135	sprintf("%d",$_[0]);
136	}
137
138