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