1#! /usr/bin/env perl
2# Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
3#
4# Licensed under the Apache License 2.0 (the "License").  You may not use
5# this file except in compliance with the License.  You can obtain a copy
6# in the file LICENSE in the source distribution or at
7# https://www.openssl.org/source/license.html
8
9
10# This flag makes the inner loop one cycle longer, but generates
11# code that runs %30 faster on the pentium pro/II, 44% faster
12# of PIII, while only %7 slower on the pentium.
13# By default, this flag is on.
14$ppro=1;
15
16$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
17push(@INC,"${dir}","${dir}../../perlasm");
18require "x86asm.pl";
19require "cbc.pl";
20
21$output=pop and open STDOUT,">$output";
22
23&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386");
24
25$CAST_ROUNDS=16;
26$L="edi";
27$R="esi";
28$K="ebp";
29$tmp1="ecx";
30$tmp2="ebx";
31$tmp3="eax";
32$tmp4="edx";
33$S1="CAST_S_table0";
34$S2="CAST_S_table1";
35$S3="CAST_S_table2";
36$S4="CAST_S_table3";
37
38@F1=("add","xor","sub");
39@F2=("xor","sub","add");
40@F3=("sub","add","xor");
41
42&CAST_encrypt("CAST_encrypt",1);
43&CAST_encrypt("CAST_decrypt",0);
44&cbc("CAST_cbc_encrypt","CAST_encrypt","CAST_decrypt",1,4,5,3,-1,-1);
45
46&asm_finish();
47
48close STDOUT or die "error closing STDOUT: $!";
49
50sub CAST_encrypt {
51    local($name,$enc)=@_;
52
53    local($win_ex)=<<"EOF";
54EXTERN	_CAST_S_table0:DWORD
55EXTERN	_CAST_S_table1:DWORD
56EXTERN	_CAST_S_table2:DWORD
57EXTERN	_CAST_S_table3:DWORD
58EOF
59    &main::external_label(
60			  "CAST_S_table0",
61			  "CAST_S_table1",
62			  "CAST_S_table2",
63			  "CAST_S_table3",
64			  );
65
66    &function_begin_B($name,$win_ex);
67
68    &comment("");
69
70    &push("ebp");
71    &push("ebx");
72    &mov($tmp2,&wparam(0));
73    &mov($K,&wparam(1));
74    &push("esi");
75    &push("edi");
76
77    &comment("Load the 2 words");
78    &mov($L,&DWP(0,$tmp2,"",0));
79    &mov($R,&DWP(4,$tmp2,"",0));
80
81    &comment('Get short key flag');
82    &mov($tmp3,&DWP(128,$K,"",0));
83    if($enc) {
84	&push($tmp3);
85    } else {
86	&or($tmp3,$tmp3);
87	&jnz(&label('cast_dec_skip'));
88    }
89
90    &xor($tmp3,	$tmp3);
91
92    # encrypting part
93
94    if ($enc) {
95	&E_CAST( 0,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
96	&E_CAST( 1,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
97	&E_CAST( 2,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
98	&E_CAST( 3,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
99	&E_CAST( 4,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
100	&E_CAST( 5,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
101	&E_CAST( 6,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
102	&E_CAST( 7,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
103	&E_CAST( 8,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
104	&E_CAST( 9,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
105	&E_CAST(10,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
106	&E_CAST(11,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
107	&comment('test short key flag');
108	&pop($tmp4);
109	&or($tmp4,$tmp4);
110	&jnz(&label('cast_enc_done'));
111	&E_CAST(12,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
112	&E_CAST(13,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
113	&E_CAST(14,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
114	&E_CAST(15,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
115    } else {
116	&E_CAST(15,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
117	&E_CAST(14,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
118	&E_CAST(13,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
119	&E_CAST(12,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
120	&set_label('cast_dec_skip');
121	&E_CAST(11,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
122	&E_CAST(10,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
123	&E_CAST( 9,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
124	&E_CAST( 8,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
125	&E_CAST( 7,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
126	&E_CAST( 6,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
127	&E_CAST( 5,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
128	&E_CAST( 4,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
129	&E_CAST( 3,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
130	&E_CAST( 2,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
131	&E_CAST( 1,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
132	&E_CAST( 0,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
133    }
134
135    &set_label('cast_enc_done') if $enc;
136# Why the nop? - Ben 17/1/99
137    &nop();
138    &mov($tmp3,&wparam(0));
139    &mov(&DWP(4,$tmp3,"",0),$L);
140    &mov(&DWP(0,$tmp3,"",0),$R);
141    &function_end($name);
142}
143
144sub E_CAST {
145    local($i,$S,$L,$R,$K,$OP1,$OP2,$OP3,$tmp1,$tmp2,$tmp3,$tmp4)=@_;
146    # Ri needs to have 16 pre added.
147
148    &comment("round $i");
149    &mov(	$tmp4,		&DWP($i*8,$K,"",1));
150
151    &mov(	$tmp1,		&DWP($i*8+4,$K,"",1));
152    &$OP1(	$tmp4,		$R);
153
154    &rotl(	$tmp4,		&LB($tmp1));
155
156    if ($ppro) {
157	&xor(	$tmp1,		$tmp1);
158	&mov(	$tmp2,		0xff);
159
160	&movb(	&LB($tmp1),	&HB($tmp4));	# A
161	&and(	$tmp2,		$tmp4);
162
163	&shr(	$tmp4,		16); 		#
164	&xor(	$tmp3,		$tmp3);
165    } else {
166	&mov(	$tmp2,		$tmp4);		# B
167	&movb(	&LB($tmp1),	&HB($tmp4));	# A	# BAD BAD BAD
168
169	&shr(	$tmp4,		16); 		#
170	&and(	$tmp2,		0xff);
171    }
172
173    &movb(	&LB($tmp3),	&HB($tmp4));	# C	# BAD BAD BAD
174    &and(	$tmp4,		0xff);		# D
175
176    &mov(	$tmp1,		&DWP($S1,"",$tmp1,4));
177    &mov(	$tmp2,		&DWP($S2,"",$tmp2,4));
178
179    &$OP2(	$tmp1,		$tmp2);
180    &mov(	$tmp2,		&DWP($S3,"",$tmp3,4));
181
182    &$OP3(	$tmp1,		$tmp2);
183    &mov(	$tmp2,		&DWP($S4,"",$tmp4,4));
184
185    &$OP1(	$tmp1,		$tmp2);
186    # XXX
187
188    &xor(	$L,		$tmp1);
189    # XXX
190}
191
192