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