xref: /openbsd-src/regress/lib/libcrypto/rc2/rc2_test.c (revision 08fd9a741ad85f9378f7de4b4bc40aff897574a7)
1 /*	$OpenBSD: rc2_test.c,v 1.3 2022/09/12 04:12:39 tb Exp $ */
2 /*
3  * Copyright (c) 2022 Joshua Sing <joshua@hypera.dev>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <openssl/evp.h>
19 #include <openssl/rc2.h>
20 
21 #include <stdint.h>
22 #include <string.h>
23 
24 struct rc2_test {
25 	const int mode;
26 	const uint8_t key[64];
27 	const int key_len;
28 	const int key_bits;
29 	const int len;
30 	const uint8_t in[8];
31 	const uint8_t out[8];
32 };
33 
34 static const struct rc2_test rc2_tests[] = {
35 	/* ECB (Test vectors from RFC 2268) */
36 	{
37 		.mode = NID_rc2_ecb,
38 		.key = {
39 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40 		},
41 		.key_len = 8,
42 		.key_bits = 63,
43 		.len = 8,
44 		.in = {
45 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 		},
47 		.out = {
48 			0xeb, 0xb7, 0x73, 0xf9, 0x93, 0x27, 0x8e, 0xff,
49 		},
50 	},
51 	{
52 		.mode = NID_rc2_ecb,
53 		.key = {
54 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
55 		},
56 		.key_len = 8,
57 		.key_bits = 64,
58 		.len = 8,
59 		.in = {
60 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
61 		},
62 		.out = {
63 			0x27, 0x8b, 0x27, 0xe4, 0x2e, 0x2f, 0x0d, 0x49,
64 		},
65 	},
66 	{
67 		.mode = NID_rc2_ecb,
68 		.key = {
69 			0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 		},
71 		.key_len = 8,
72 		.key_bits = 64,
73 		.len = 8,
74 		.in = {
75 			0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
76 		},
77 		.out = {
78 			0x30, 0x64, 0x9e, 0xdf, 0x9b, 0xe7, 0xd2, 0xc2,
79 		},
80 	},
81 	{
82 		.mode = NID_rc2_ecb,
83 		.key = {
84 			0x88,
85 		},
86 		.key_len = 1,
87 		.key_bits = 64,
88 		.len = 8,
89 		.in = {
90 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 		},
92 		.out = {
93 			0x61, 0xa8, 0xa2, 0x44, 0xad, 0xac, 0xcc, 0xf0,
94 		},
95 	},
96 	{
97 		.mode = NID_rc2_ecb,
98 		.key = {
99 			0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a,
100 		},
101 		.key_len = 7,
102 		.key_bits = 64,
103 		.len = 8,
104 		.in = {
105 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 		},
107 		.out = {
108 			0x6c, 0xcf, 0x43, 0x08, 0x97, 0x4c, 0x26, 0x7f,
109 		},
110 	},
111 	{
112 		.mode = NID_rc2_ecb,
113 		.key = {
114 			0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f,
115 			0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2,
116 		},
117 		.key_len = 16,
118 		.key_bits = 64,
119 		.len = 8,
120 		.in = {
121 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 		},
123 		.out = {
124 			0x1a, 0x80, 0x7d, 0x27, 0x2b, 0xbe, 0x5d, 0xb1,
125 		},
126 	},
127 	{
128 		.mode = NID_rc2_ecb,
129 		.key = {
130 			0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f,
131 			0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2,
132 		},
133 		.key_len = 16,
134 		.key_bits = 128,
135 		.len = 8,
136 		.in = {
137 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 		},
139 		.out = {
140 			0x22, 0x69, 0x55, 0x2a, 0xb0, 0xf8, 0x5c, 0xa6,
141 		},
142 	},
143 	{
144 		.mode = NID_rc2_ecb,
145 		.key = {
146 			0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f,
147 			0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2,
148 			0x16, 0xf8, 0x0a, 0x6f, 0x85, 0x92, 0x05, 0x84,
149 			0xc4, 0x2f, 0xce, 0xb0, 0xbe, 0x25, 0x5d, 0xaf,
150 			0x1e,
151 		},
152 		.key_len = 33,
153 		.key_bits = 129,
154 		.len = 8,
155 		.in = {
156 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 		},
158 		.out = {
159 			0x5b, 0x78, 0xd3, 0xa4, 0x3d, 0xff, 0xf1, 0xf1,
160 		},
161 	},
162 
163 	/* ECB (Test vectors from http://websites.umich.edu/~x509/ssleay/rrc2.html) */
164 	{
165 		.mode = NID_rc2_ecb,
166 		.key = {
167 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 		},
170 		.key_len = 16,
171 		.key_bits = 1024,
172 		.len = 8,
173 		.in = {
174 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 		},
176 		.out = {
177 			0x1c, 0x19, 0x8a, 0x83, 0x8d, 0xf0, 0x28, 0xb7,
178 		},
179 	},
180 	{
181 		.mode = NID_rc2_ecb,
182 		.key = {
183 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
185 		},
186 		.key_len = 16,
187 		.key_bits = 1024,
188 		.len = 8,
189 		.in = {
190 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 		},
192 		.out = {
193 			0x21, 0x82, 0x9C, 0x78, 0xA9, 0xF9, 0xC0, 0x74,
194 		},
195 	},
196 	{
197 		.mode = NID_rc2_ecb,
198 		.key = {
199 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 		},
202 		.key_len = 16,
203 		.key_bits = 1024,
204 		.len = 8,
205 		.in = {
206 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
207 		},
208 		.out = {
209 			0x13, 0xdb, 0x35, 0x17, 0xd3, 0x21, 0x86, 0x9e,
210 		},
211 	},
212 	{
213 		.mode = NID_rc2_ecb,
214 		.key = {
215 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
216 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
217 		},
218 		.key_len = 16,
219 		.key_bits = 1024,
220 		.len = 8,
221 		.in = {
222 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223 		},
224 		.out = {
225 			0x50, 0xdc, 0x01, 0x62, 0xbd, 0x75, 0x7f, 0x31,
226 		},
227 	},
228 };
229 
230 #define N_RC2_TESTS (sizeof(rc2_tests) / sizeof(rc2_tests[0]))
231 
232 static int
233 rc2_ecb_test(size_t test_number, const struct rc2_test *rt)
234 {
235 	RC2_KEY key;
236 	uint8_t out[8];
237 
238 	/* Encryption */
239 	memset(out, 0, sizeof(out));
240 	RC2_set_key(&key, rt->key_len, rt->key, rt->key_bits);
241 	RC2_ecb_encrypt(rt->in, out, &key, 1);
242 
243 	if (memcmp(rt->out, out, rt->len) != 0) {
244 		fprintf(stderr, "FAIL (%s:%zu): encryption mismatch\n",
245 		    SN_rc2_ecb, test_number);
246 		return 0;
247 	}
248 
249 	/* Decryption */
250 	memset(out, 0, sizeof(out));
251 	RC2_set_key(&key, rt->key_len, rt->key, rt->key_bits);
252 	RC2_ecb_encrypt(rt->out, out, &key, 0);
253 
254 	if (memcmp(rt->in, out, rt->len) != 0) {
255 		fprintf(stderr, "FAIL (%s:%zu): decryption mismatch\n",
256 		    SN_rc2_ecb, test_number);
257 		return 0;
258 	}
259 
260 	return 1;
261 }
262 
263 static int
264 rc2_evp_test(size_t test_number, const struct rc2_test *rt, const char *label, const EVP_CIPHER *cipher)
265 {
266 	EVP_CIPHER_CTX *ctx;
267 	uint8_t out[512];
268 	int in_len, out_len, total_len;
269 	int i;
270 	int success = 0;
271 
272 	if ((ctx = EVP_CIPHER_CTX_new()) == NULL) {
273 		fprintf(stderr, "FAIL (%s:%zu): EVP_CIPHER_CTX_new failed\n",
274 		    label, test_number);
275 		goto failed;
276 	}
277 
278 	/* EVP encryption */
279 	total_len = 0;
280 	memset(out, 0, sizeof(out));
281 	if (!EVP_EncryptInit(ctx, cipher, NULL, NULL)) {
282 		fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptInit failed\n",
283 		    label, test_number);
284 		goto failed;
285 	}
286 
287 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS,
288 	    rt->key_bits, NULL) <= 0) {
289 		fprintf(stderr, "FAIL (%s:%zu): EVP_CIPHER_CTX_ctrl failed\n",
290 		    label, test_number);
291 		goto failed;
292 	}
293 
294 	if (!EVP_CIPHER_CTX_set_key_length(ctx, rt->key_len)) {
295 		fprintf(stderr,
296 		    "FAIL (%s:%zu): EVP_CIPHER_CTX_set_key_length failed\n",
297 		    label, test_number);
298 		goto failed;
299 	}
300 
301 	if (!EVP_CIPHER_CTX_set_padding(ctx, 0)) {
302 		fprintf(stderr,
303 		    "FAIL (%s:%zu): EVP_CIPHER_CTX_set_padding failed\n",
304 		    label, test_number);
305 		goto failed;
306 	}
307 
308 	if (!EVP_EncryptInit(ctx, NULL, rt->key, NULL)) {
309 		fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptInit failed\n",
310 		    label, test_number);
311 		goto failed;
312 	}
313 
314 	for (i = 0; i < rt->len;) {
315 		in_len = arc4random_uniform(sizeof(rt->len) / 2);
316 		if (in_len > rt->len - i)
317 			in_len = rt->len - i;
318 
319 		if (!EVP_EncryptUpdate(ctx, out + total_len, &out_len,
320 			rt->in + i, in_len)) {
321 			fprintf(stderr,
322 			    "FAIL (%s:%zu): EVP_EncryptUpdate failed\n",
323 			    label, test_number);
324 			goto failed;
325 		}
326 
327 		i += in_len;
328 		total_len += out_len;
329 	}
330 
331 	if (!EVP_EncryptFinal_ex(ctx, out + out_len, &out_len)) {
332 		fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptFinal_ex failed\n",
333 		    label, test_number);
334 		goto failed;
335 	}
336 	total_len += out_len;
337 
338 	if (!EVP_CIPHER_CTX_reset(ctx)) {
339 		fprintf(stderr,
340 		    "FAIL (%s:%zu): EVP_CIPHER_CTX_reset failed\n",
341 		    label, test_number);
342 		goto failed;
343 	}
344 
345 	if (total_len != rt->len) {
346 		fprintf(stderr,
347 		    "FAIL (%s:%zu): EVP encryption length mismatch\n",
348 		    label, test_number);
349 		goto failed;
350 	}
351 
352 	if (memcmp(rt->out, out, rt->len) != 0) {
353 		fprintf(stderr, "FAIL (%s:%zu): EVP encryption mismatch\n",
354 		    label, test_number);
355 		goto failed;
356 	}
357 
358 	/* EVP decryption */
359 	total_len = 0;
360 	memset(out, 0, sizeof(out));
361 	if (!EVP_DecryptInit(ctx, cipher, NULL, NULL)) {
362 		fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptInit failed\n",
363 		    label, test_number);
364 		goto failed;
365 	}
366 
367 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS,
368 	    rt->key_bits, NULL) <= 0) {
369 		fprintf(stderr, "FAIL (%s:%zu): EVP_CIPHER_CTX_ctrl failed\n",
370 		    label, test_number);
371 		goto failed;
372 	}
373 
374 	if (!EVP_CIPHER_CTX_set_key_length(ctx, rt->key_len)) {
375 		fprintf(stderr,
376 		    "FAIL (%s:%zu): EVP_CIPHER_CTX_set_key_length failed\n",
377 		    label, test_number);
378 		goto failed;
379 	}
380 
381 	if (!EVP_CIPHER_CTX_set_padding(ctx, 0)) {
382 		fprintf(stderr,
383 		    "FAIL (%s:%zu): EVP_CIPHER_CTX_set_padding failed\n",
384 		    label, test_number);
385 		goto failed;
386 	}
387 
388 	if (!EVP_DecryptInit(ctx, NULL, rt->key, NULL)) {
389 		fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptInit failed\n",
390 		    label, test_number);
391 		goto failed;
392 	}
393 
394 	for (i = 0; i < rt->len;) {
395 		in_len = arc4random_uniform(sizeof(rt->len) / 2);
396 		if (in_len > rt->len - i)
397 			in_len = rt->len - i;
398 
399 		if (!EVP_DecryptUpdate(ctx, out + total_len, &out_len,
400 			rt->out + i, in_len)) {
401 			fprintf(stderr,
402 			    "FAIL (%s:%zu): EVP_DecryptUpdate failed\n",
403 			    label, test_number);
404 			goto failed;
405 		}
406 
407 		i += in_len;
408 		total_len += out_len;
409 	}
410 
411 	if (!EVP_DecryptFinal_ex(ctx, out + total_len, &out_len)) {
412 		fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptFinal_ex failed\n",
413 		    label, test_number);
414 		goto failed;
415 	}
416 	total_len += out_len;
417 
418 	if (!EVP_CIPHER_CTX_reset(ctx)) {
419 		fprintf(stderr,
420 		    "FAIL (%s:%zu): EVP_CIPHER_CTX_reset failed\n",
421 		    label, test_number);
422 		goto failed;
423 	}
424 
425 	if (total_len != rt->len) {
426 		fprintf(stderr,
427 		    "FAIL (%s:%zu): EVP decryption length mismatch\n",
428 		    label, test_number);
429 		goto failed;
430 	}
431 
432 	if (memcmp(rt->in, out, rt->len) != 0) {
433 		fprintf(stderr, "FAIL (%s:%zu): EVP decryption mismatch\n",
434 		    label, test_number);
435 		goto failed;
436 	}
437 
438 	success = 1;
439 
440  failed:
441 	EVP_CIPHER_CTX_free(ctx);
442 	return success;
443 }
444 
445 static int
446 rc2_test(void)
447 {
448 	const struct rc2_test *rt;
449 	const char *label;
450 	const EVP_CIPHER *cipher;
451 	size_t i;
452 	int failed = 1;
453 
454 	for (i = 0; i < N_RC2_TESTS; i++) {
455 		rt = &rc2_tests[i];
456 		switch (rt->mode) {
457 		case NID_rc2_ecb:
458 			label = SN_rc2_ecb;
459 			cipher = EVP_rc2_ecb();
460 			if (!rc2_ecb_test(i, rt))
461 				goto failed;
462 			break;
463 		default:
464 			fprintf(stderr, "FAIL: unknown mode (%d)\n",
465 			    rt->mode);
466 			goto failed;
467 		}
468 
469 		if (!rc2_evp_test(i, rt, label, cipher))
470 			goto failed;
471 	}
472 
473 	failed = 0;
474 
475  failed:
476 	return failed;
477 }
478 
479 int
480 main(int argc, char **argv)
481 {
482 	int failed = 0;
483 
484 	failed |= rc2_test();
485 
486 	return failed;
487 }
488