1 /**********************************************************************\
2 * To commemorate the 1996 RSA Data Security Conference, the following  *
3 * code is released into the public domain by its author.  Prost!       *
4 *                                                                      *
5 * This cipher uses 16-bit words and little-endian byte ordering.       *
6 * I wonder which processor it was optimized for?                       *
7 *                                                                      *
8 * Thanks to CodeView, SoftIce, and D86 for helping bring this code to  *
9 * the public.                                                          *
10 \**********************************************************************/
11 
12 /* modified in order to use the libmcrypt API by Nikos Mavroyanopoulos
13  * All modifications are placed under the license of libmcrypt.
14  */
15 
16 /* $Id: rc2.c,v 1.14 2003/01/19 17:48:27 nmav Exp $ */
17 
18 #include <libdefs.h>
19 
20 #include <mcrypt_modules.h>
21 /* #include <assert.h> */
22 #include "rc2.h"
23 
24 #define _mcrypt_set_key rc2_LTX__mcrypt_set_key
25 #define _mcrypt_encrypt rc2_LTX__mcrypt_encrypt
26 #define _mcrypt_decrypt rc2_LTX__mcrypt_decrypt
27 #define _mcrypt_get_size rc2_LTX__mcrypt_get_size
28 #define _mcrypt_get_block_size rc2_LTX__mcrypt_get_block_size
29 #define _is_block_algorithm rc2_LTX__is_block_algorithm
30 #define _mcrypt_get_key_size rc2_LTX__mcrypt_get_key_size
31 #define _mcrypt_get_supported_key_sizes rc2_LTX__mcrypt_get_supported_key_sizes
32 #define _mcrypt_get_algorithms_name rc2_LTX__mcrypt_get_algorithms_name
33 #define _mcrypt_self_test rc2_LTX__mcrypt_self_test
34 #define _mcrypt_algorithm_version rc2_LTX__mcrypt_algorithm_version
35 
36 /**********************************************************************\
37 * Expand a variable-length user key (between 1 and 128 bytes) to a     *
38 * 64-short working rc2 key, of at most "bits" effective key bits.      *
39 * The effective key bits parameter looks like an export control hack.  *
40 * For normal use, it should always be set to 1024.  For convenience,   *
41 * zero is accepted as an alias for 1024.                               *
42 \**********************************************************************/
43 
44 WIN32DLL_DEFINE
_mcrypt_set_key(word16 * xkey,const byte * key,unsigned int len)45     int _mcrypt_set_key(word16 * xkey, const byte * key, unsigned int len)
46 {
47 	unsigned int j;
48 	byte *xkey_p = (void *) xkey;
49 	int i;
50 
51 	/* 256-entry permutation table, probably derived somehow from pi */
52 	static const byte permute[256] = {
53 		217, 120, 249, 196, 25, 221, 181, 237, 40, 233, 253, 121,
54 		74, 160, 216, 157,
55 		198, 126, 55, 131, 43, 118, 83, 142, 98, 76, 100, 136,
56 		68, 139, 251, 162,
57 		23, 154, 89, 245, 135, 179, 79, 19, 97, 69, 109, 141, 9,
58 		129, 125, 50,
59 		189, 143, 64, 235, 134, 183, 123, 11, 240, 149, 33, 34,
60 		92, 107, 78, 130,
61 		84, 214, 101, 147, 206, 96, 178, 28, 115, 86, 192, 20,
62 		167, 140, 241, 220,
63 		18, 117, 202, 31, 59, 190, 228, 209, 66, 61, 212, 48,
64 		163, 60, 182, 38,
65 		111, 191, 14, 218, 70, 105, 7, 87, 39, 242, 29, 155, 188,
66 		148, 67, 3,
67 		248, 17, 199, 246, 144, 239, 62, 231, 6, 195, 213, 47,
68 		200, 102, 30, 215,
69 		8, 232, 234, 222, 128, 82, 238, 247, 132, 170, 114, 172,
70 		53, 77, 106, 42,
71 		150, 26, 210, 113, 90, 21, 73, 116, 75, 159, 208, 94, 4,
72 		24, 164, 236,
73 		194, 224, 65, 110, 15, 81, 203, 204, 36, 145, 175, 80,
74 		161, 244, 112, 57,
75 		153, 124, 58, 133, 35, 184, 180, 122, 252, 2, 54, 91, 37,
76 		85, 151, 49,
77 		45, 93, 250, 152, 227, 138, 146, 174, 5, 223, 41, 16,
78 		103, 108, 186, 201,
79 		211, 0, 230, 207, 225, 158, 168, 44, 99, 22, 1, 63, 88,
80 		226, 137, 169,
81 		13, 56, 52, 27, 171, 51, 255, 176, 187, 72, 12, 95, 185,
82 		177, 205, 46,
83 		197, 243, 219, 71, 229, 165, 156, 119, 10, 166, 32, 104,
84 		254, 127, 193, 173
85 	};
86 
87 /*	assert(len > 0 && len <= 128); */
88 
89 	memmove(xkey, key, len);
90 
91 	/* Phase 1: Expand input key to 128 bytes */
92 
93 	for (j = len; j < 128; j++) {
94 		xkey_p[j] =
95 		    permute[(xkey_p[j - len] + xkey_p[j - 1]) % 256];
96 	}
97 
98 	xkey_p[0] = permute[xkey_p[0]];
99 
100 	/* Phase 2 - reduce effective key size to "bits" */
101 	/* stripped */
102 
103 	/* Phase 3 - copy to xkey in little-endian order */
104 	i = 63;
105 	do {
106 		xkey[i] = xkey_p[2 * i] + (xkey_p[2 * i + 1] << 8);
107 	} while (i--);
108 
109 	return 0;
110 }
111 
112 
113 /**********************************************************************\
114 * Encrypt an 8-byte block of plaintext using the given key.            *
115 \**********************************************************************/
116 
_mcrypt_encrypt(const word16 * xkey,word16 * plain)117 WIN32DLL_DEFINE void _mcrypt_encrypt(const word16 * xkey, word16 * plain)
118 {
119 	word16 x3, x2, x1, x0, i;
120 
121 #ifdef WORDS_BIGENDIAN
122 	x3 = byteswap16(plain[3]);
123 	x2 = byteswap16(plain[2]);
124 	x1 = byteswap16(plain[1]);
125 	x0 = byteswap16(plain[0]);
126 #else
127 	x3 = plain[3];
128 	x2 = plain[2];
129 	x1 = plain[1];
130 	x0 = plain[0];
131 #endif
132 
133 	for (i = 0; i < 16; i++) {
134 		x0 += (x1 & ~x3) + (x2 & x3) + xkey[4 * i + 0];
135 		x0 = rotl16(x0, 1);
136 
137 		x1 += (x2 & ~x0) + (x3 & x0) + xkey[4 * i + 1];
138 		x1 = rotl16(x1, 2);
139 
140 		x2 += (x3 & ~x1) + (x0 & x1) + xkey[4 * i + 2];
141 		x2 = rotl16(x2, 3);
142 
143 		x3 += (x0 & ~x2) + (x1 & x2) + xkey[4 * i + 3];
144 		x3 = rotl16(x3, 5);
145 
146 		if (i == 4 || i == 10) {
147 			x0 += xkey[x3 & 63];
148 			x1 += xkey[x0 & 63];
149 			x2 += xkey[x1 & 63];
150 			x3 += xkey[x2 & 63];
151 		}
152 	}
153 
154 #ifdef WORDS_BIGENDIAN
155 	plain[0] = byteswap16(x0);
156 	plain[1] = byteswap16(x1);
157 	plain[2] = byteswap16(x2);
158 	plain[3] = byteswap16(x3);
159 #else
160 	plain[0] = (x0);
161 	plain[1] = (x1);
162 	plain[2] = (x2);
163 	plain[3] = (x3);
164 
165 #endif
166 
167 }
168 
169 /**********************************************************************\
170 * Decrypt an 8-byte block of ciphertext using the given key.           *
171 \**********************************************************************/
172 
_mcrypt_decrypt(const word16 * xkey,word16 * plain)173 WIN32DLL_DEFINE void _mcrypt_decrypt(const word16 * xkey, word16 * plain)
174 {
175 	word16 x3, x2, x1, x0, i;
176 
177 #ifndef WORDS_BIGENDIAN
178 	x3 = plain[3];
179 	x2 = plain[2];
180 	x1 = plain[1];
181 	x0 = plain[0];
182 #else
183 	x3 = byteswap16(plain[3]);
184 	x2 = byteswap16(plain[2]);
185 	x1 = byteswap16(plain[1]);
186 	x0 = byteswap16(plain[0]);
187 #endif
188 
189 
190 	i = 15;
191 	do {
192 		x3 = rotr16(x3, 5);
193 		x3 -= (x0 & ~x2) + (x1 & x2) + xkey[4 * i + 3];
194 
195 		x2 = rotr16(x2, 3);
196 		x2 -= (x3 & ~x1) + (x0 & x1) + xkey[4 * i + 2];
197 
198 		x1 = rotr16(x1, 2);
199 		x1 -= (x2 & ~x0) + (x3 & x0) + xkey[4 * i + 1];
200 
201 		x0 = rotr16(x0, 1);
202 		x0 -= (x1 & ~x3) + (x2 & x3) + xkey[4 * i + 0];
203 
204 		if (i == 5 || i == 11) {
205 			x3 -= xkey[x2 & 63];
206 			x2 -= xkey[x1 & 63];
207 			x1 -= xkey[x0 & 63];
208 			x0 -= xkey[x3 & 63];
209 		}
210 	} while (i--);
211 
212 #ifdef WORDS_BIGENDIAN
213 	plain[0] = byteswap16(x0);
214 	plain[1] = byteswap16(x1);
215 	plain[2] = byteswap16(x2);
216 	plain[3] = byteswap16(x3);
217 #else
218 	plain[0] = x0;
219 	plain[1] = x1;
220 	plain[2] = x2;
221 	plain[3] = x3;
222 #endif
223 }
224 
_mcrypt_get_size()225 WIN32DLL_DEFINE int _mcrypt_get_size()
226 {
227 	return 64 * sizeof(word16);
228 }
_mcrypt_get_block_size()229 WIN32DLL_DEFINE int _mcrypt_get_block_size()
230 {
231 	return 8;
232 }
_is_block_algorithm()233 WIN32DLL_DEFINE int _is_block_algorithm()
234 {
235 	return 1;
236 }
_mcrypt_get_key_size()237 WIN32DLL_DEFINE int _mcrypt_get_key_size()
238 {
239 	return 128;
240 }
241 
_mcrypt_get_supported_key_sizes(int * len)242 WIN32DLL_DEFINE const int *_mcrypt_get_supported_key_sizes(int *len)
243 {
244 	*len = 0;
245 	return NULL;
246 }
_mcrypt_get_algorithms_name()247 WIN32DLL_DEFINE char *_mcrypt_get_algorithms_name()
248 {
249 return "RC2";
250 }
251 
252 #define CIPHER "becbe4c8e6237a14"
253 
_mcrypt_self_test()254 WIN32DLL_DEFINE int _mcrypt_self_test()
255 {
256 	char *keyword;
257 	unsigned char plaintext[16];
258 	unsigned char ciphertext[16];
259 	int blocksize = _mcrypt_get_block_size(), j;
260 	void *key;
261 	unsigned char cipher_tmp[200];
262 
263 	keyword = calloc(1, _mcrypt_get_key_size());
264 	if (keyword == NULL)
265 		return -1;
266 
267 	for (j = 0; j < _mcrypt_get_key_size(); j++) {
268 		keyword[j] = ((j * 2 + 10) % 256);
269 	}
270 
271 	for (j = 0; j < blocksize; j++) {
272 		plaintext[j] = j % 256;
273 	}
274 
275 	key = malloc(_mcrypt_get_size());
276 	if (key == NULL) {
277 		free(keyword);
278 		return -1;
279 	}
280 
281 	memcpy(ciphertext, plaintext, blocksize);
282 
283 	_mcrypt_set_key(key, (void *) keyword, _mcrypt_get_key_size());
284 	free(keyword);
285 
286 	_mcrypt_encrypt(key, (void *) ciphertext);
287 
288 	for (j = 0; j < blocksize; j++) {
289 		sprintf(&((char *) cipher_tmp)[2 * j], "%.2x",
290 			ciphertext[j]);
291 	}
292 
293 	if (strcmp((char *) cipher_tmp, CIPHER) != 0) {
294 		printf("failed compatibility\n");
295 		printf("Expected: %s\nGot: %s\n", CIPHER,
296 		       (char *) cipher_tmp);
297 		free(key);
298 		return -1;
299 	}
300 	_mcrypt_decrypt(key, (void *) ciphertext);
301 	free(key);
302 
303 	if (strcmp(ciphertext, plaintext) != 0) {
304 		printf("failed internally\n");
305 		return -1;
306 	}
307 
308 	return 0;
309 }
310 
_mcrypt_algorithm_version()311 WIN32DLL_DEFINE word32 _mcrypt_algorithm_version()
312 {
313 	return 20010801;
314 }
315 
316 #ifdef WIN32
317 # ifdef USE_LTDL
main(void)318 WIN32DLL_DEFINE int main (void)
319 {
320        /* empty main function to avoid linker error (see cygwin FAQ) */
321 }
322 # endif
323 #endif
324