xref: /openbsd-src/regress/lib/libcrypto/rc2/rc2_test.c (revision 2b54cc578d9daa987da0c7dd62edab11514d005f)
1 /*	$OpenBSD: rc2_test.c,v 1.4 2022/09/12 13:09:01 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,
265     const EVP_CIPHER *cipher)
266 {
267 	EVP_CIPHER_CTX *ctx;
268 	uint8_t out[512];
269 	int in_len, out_len, total_len;
270 	int i;
271 	int success = 0;
272 
273 	if ((ctx = EVP_CIPHER_CTX_new()) == NULL) {
274 		fprintf(stderr, "FAIL (%s:%zu): EVP_CIPHER_CTX_new failed\n",
275 		    label, test_number);
276 		goto failed;
277 	}
278 
279 	/* EVP encryption */
280 	total_len = 0;
281 	memset(out, 0, sizeof(out));
282 	if (!EVP_EncryptInit(ctx, cipher, NULL, NULL)) {
283 		fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptInit failed\n",
284 		    label, test_number);
285 		goto failed;
286 	}
287 
288 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS,
289 	    rt->key_bits, NULL) <= 0) {
290 		fprintf(stderr, "FAIL (%s:%zu): EVP_CIPHER_CTX_ctrl failed\n",
291 		    label, test_number);
292 		goto failed;
293 	}
294 
295 	if (!EVP_CIPHER_CTX_set_key_length(ctx, rt->key_len)) {
296 		fprintf(stderr,
297 		    "FAIL (%s:%zu): EVP_CIPHER_CTX_set_key_length failed\n",
298 		    label, test_number);
299 		goto failed;
300 	}
301 
302 	if (!EVP_CIPHER_CTX_set_padding(ctx, 0)) {
303 		fprintf(stderr,
304 		    "FAIL (%s:%zu): EVP_CIPHER_CTX_set_padding failed\n",
305 		    label, test_number);
306 		goto failed;
307 	}
308 
309 	if (!EVP_EncryptInit(ctx, NULL, rt->key, NULL)) {
310 		fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptInit failed\n",
311 		    label, test_number);
312 		goto failed;
313 	}
314 
315 	for (i = 0; i < rt->len;) {
316 		in_len = arc4random_uniform(sizeof(rt->len) / 2);
317 		if (in_len > rt->len - i)
318 			in_len = rt->len - i;
319 
320 		if (!EVP_EncryptUpdate(ctx, out + total_len, &out_len,
321 		    rt->in + i, in_len)) {
322 			fprintf(stderr,
323 			    "FAIL (%s:%zu): EVP_EncryptUpdate failed\n",
324 			    label, test_number);
325 			goto failed;
326 		}
327 
328 		i += in_len;
329 		total_len += out_len;
330 	}
331 
332 	if (!EVP_EncryptFinal_ex(ctx, out + out_len, &out_len)) {
333 		fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptFinal_ex failed\n",
334 		    label, test_number);
335 		goto failed;
336 	}
337 	total_len += out_len;
338 
339 	if (!EVP_CIPHER_CTX_reset(ctx)) {
340 		fprintf(stderr,
341 		    "FAIL (%s:%zu): EVP_CIPHER_CTX_reset failed\n",
342 		    label, test_number);
343 		goto failed;
344 	}
345 
346 	if (total_len != rt->len) {
347 		fprintf(stderr,
348 		    "FAIL (%s:%zu): EVP encryption length mismatch\n",
349 		    label, test_number);
350 		goto failed;
351 	}
352 
353 	if (memcmp(rt->out, out, rt->len) != 0) {
354 		fprintf(stderr, "FAIL (%s:%zu): EVP encryption mismatch\n",
355 		    label, test_number);
356 		goto failed;
357 	}
358 
359 	/* EVP decryption */
360 	total_len = 0;
361 	memset(out, 0, sizeof(out));
362 	if (!EVP_DecryptInit(ctx, cipher, NULL, NULL)) {
363 		fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptInit failed\n",
364 		    label, test_number);
365 		goto failed;
366 	}
367 
368 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS,
369 	    rt->key_bits, NULL) <= 0) {
370 		fprintf(stderr, "FAIL (%s:%zu): EVP_CIPHER_CTX_ctrl failed\n",
371 		    label, test_number);
372 		goto failed;
373 	}
374 
375 	if (!EVP_CIPHER_CTX_set_key_length(ctx, rt->key_len)) {
376 		fprintf(stderr,
377 		    "FAIL (%s:%zu): EVP_CIPHER_CTX_set_key_length failed\n",
378 		    label, test_number);
379 		goto failed;
380 	}
381 
382 	if (!EVP_CIPHER_CTX_set_padding(ctx, 0)) {
383 		fprintf(stderr,
384 		    "FAIL (%s:%zu): EVP_CIPHER_CTX_set_padding failed\n",
385 		    label, test_number);
386 		goto failed;
387 	}
388 
389 	if (!EVP_DecryptInit(ctx, NULL, rt->key, NULL)) {
390 		fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptInit failed\n",
391 		    label, test_number);
392 		goto failed;
393 	}
394 
395 	for (i = 0; i < rt->len;) {
396 		in_len = arc4random_uniform(sizeof(rt->len) / 2);
397 		if (in_len > rt->len - i)
398 			in_len = rt->len - i;
399 
400 		if (!EVP_DecryptUpdate(ctx, out + total_len, &out_len,
401 		    rt->out + i, in_len)) {
402 			fprintf(stderr,
403 			    "FAIL (%s:%zu): EVP_DecryptUpdate failed\n",
404 			    label, test_number);
405 			goto failed;
406 		}
407 
408 		i += in_len;
409 		total_len += out_len;
410 	}
411 
412 	if (!EVP_DecryptFinal_ex(ctx, out + total_len, &out_len)) {
413 		fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptFinal_ex failed\n",
414 		    label, test_number);
415 		goto failed;
416 	}
417 	total_len += out_len;
418 
419 	if (!EVP_CIPHER_CTX_reset(ctx)) {
420 		fprintf(stderr,
421 		    "FAIL (%s:%zu): EVP_CIPHER_CTX_reset failed\n",
422 		    label, test_number);
423 		goto failed;
424 	}
425 
426 	if (total_len != rt->len) {
427 		fprintf(stderr,
428 		    "FAIL (%s:%zu): EVP decryption length mismatch\n",
429 		    label, test_number);
430 		goto failed;
431 	}
432 
433 	if (memcmp(rt->in, out, rt->len) != 0) {
434 		fprintf(stderr, "FAIL (%s:%zu): EVP decryption mismatch\n",
435 		    label, test_number);
436 		goto failed;
437 	}
438 
439 	success = 1;
440 
441  failed:
442 	EVP_CIPHER_CTX_free(ctx);
443 	return success;
444 }
445 
446 static int
447 rc2_test(void)
448 {
449 	const struct rc2_test *rt;
450 	const char *label;
451 	const EVP_CIPHER *cipher;
452 	size_t i;
453 	int failed = 1;
454 
455 	for (i = 0; i < N_RC2_TESTS; i++) {
456 		rt = &rc2_tests[i];
457 		switch (rt->mode) {
458 		case NID_rc2_ecb:
459 			label = SN_rc2_ecb;
460 			cipher = EVP_rc2_ecb();
461 			if (!rc2_ecb_test(i, rt))
462 				goto failed;
463 			break;
464 		default:
465 			fprintf(stderr, "FAIL: unknown mode (%d)\n",
466 			    rt->mode);
467 			goto failed;
468 		}
469 
470 		if (!rc2_evp_test(i, rt, label, cipher))
471 			goto failed;
472 	}
473 
474 	failed = 0;
475 
476  failed:
477 	return failed;
478 }
479 
480 int
481 main(int argc, char **argv)
482 {
483 	int failed = 0;
484 
485 	failed |= rc2_test();
486 
487 	return failed;
488 }
489