1 /* $OpenBSD: evptest.c,v 1.12 2023/03/02 20:24:51 tb Exp $ */ 2 /* Written by Ben Laurie, 2001 */ 3 /* 4 * Copyright (c) 2001 The OpenSSL Project. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * 3. All advertising materials mentioning features or use of this 19 * software must display the following acknowledgment: 20 * "This product includes software developed by the OpenSSL Project 21 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 22 * 23 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 24 * endorse or promote products derived from this software without 25 * prior written permission. For written permission, please contact 26 * openssl-core@openssl.org. 27 * 28 * 5. Products derived from this software may not be called "OpenSSL" 29 * nor may "OpenSSL" appear in their names without prior written 30 * permission of the OpenSSL Project. 31 * 32 * 6. Redistributions of any form whatsoever must retain the following 33 * acknowledgment: 34 * "This product includes software developed by the OpenSSL Project 35 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 36 * 37 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 38 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 40 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 43 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 46 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 48 * OF THE POSSIBILITY OF SUCH DAMAGE. 49 */ 50 51 #include <stdio.h> 52 #include <string.h> 53 54 #include <openssl/opensslconf.h> 55 #include <openssl/evp.h> 56 #ifndef OPENSSL_NO_ENGINE 57 #include <openssl/engine.h> 58 #endif 59 #include <openssl/err.h> 60 #include <openssl/conf.h> 61 62 int verbose; 63 64 static void 65 hexdump(FILE *f, const char *title, const unsigned char *s, int l) 66 { 67 int n = 0; 68 69 fprintf(f, "%s",title); 70 for (; n < l; ++n) { 71 if ((n % 16) == 0) 72 fprintf(f, "\n%04x",n); 73 fprintf(f, " %02x",s[n]); 74 } 75 fprintf(f, "\n"); 76 } 77 78 static int 79 convert(unsigned char *s) 80 { 81 unsigned char *d; 82 83 for (d = s; *s; s += 2,++d) { 84 unsigned int n; 85 86 if (!s[1]) { 87 fprintf(stderr, "Odd number of hex digits!\n"); 88 exit(4); 89 } 90 if (sscanf((char *)s, "%2x", &n) != 1) { 91 fprintf(stderr, "Invalid hex value at %s\n", s); 92 exit(4); 93 } 94 95 *d = (unsigned char)n; 96 } 97 return s - d; 98 } 99 100 static char * 101 sstrsep(char **string, const char *delim) 102 { 103 char isdelim[256]; 104 char *token = *string; 105 106 if (**string == 0) 107 return NULL; 108 109 memset(isdelim, 0, 256); 110 isdelim[0] = 1; 111 112 while (*delim) { 113 isdelim[(unsigned char)(*delim)] = 1; 114 delim++; 115 } 116 117 while (!isdelim[(unsigned char)(**string)]) { 118 (*string)++; 119 } 120 121 if (**string) { 122 **string = 0; 123 (*string)++; 124 } 125 126 return token; 127 } 128 129 static unsigned char * 130 ustrsep(char **p, const char *sep) 131 { 132 return (unsigned char *)sstrsep(p, sep); 133 } 134 135 static int 136 test1_exit(int ec) 137 { 138 exit(ec); 139 return(0); /* To keep some compilers quiet */ 140 } 141 142 static void 143 test1(const EVP_CIPHER *c, const unsigned char *key, int kn, 144 const unsigned char *iv, int in, const unsigned char *plaintext, int pn, 145 const unsigned char *ciphertext, int cn, int encdec) 146 { 147 EVP_CIPHER_CTX *ctx; 148 unsigned char out[4096]; 149 const unsigned char *eiv; 150 int outl, outl2; 151 152 if (verbose) { 153 printf("Testing cipher %s%s\n", EVP_CIPHER_name(c), 154 (encdec == 1 ? "(encrypt)" : (encdec == 0 ? "(decrypt)" : "(encrypt/decrypt)"))); 155 hexdump(stdout, "Key",key,kn); 156 if (in) 157 hexdump(stdout, "IV",iv,in); 158 hexdump(stdout, "Plaintext",plaintext,pn); 159 hexdump(stdout, "Ciphertext",ciphertext,cn); 160 } 161 162 if (kn != EVP_CIPHER_key_length(c)) { 163 fprintf(stderr, "Key length doesn't match, got %d expected %lu\n",kn, 164 (unsigned long)EVP_CIPHER_key_length(c)); 165 test1_exit(5); 166 } 167 if ((ctx = EVP_CIPHER_CTX_new()) == NULL) { 168 fprintf(stderr, "EVP_CIPHER_CTX_new failed\n"); 169 ERR_print_errors_fp(stderr); 170 test1_exit(12); 171 } 172 EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); 173 if (encdec != 0) { 174 eiv = iv; 175 if (EVP_CIPHER_mode(c) == EVP_CIPH_WRAP_MODE && in == 0) 176 eiv = NULL; 177 if (!EVP_EncryptInit_ex(ctx, c, NULL, key, eiv)) { 178 fprintf(stderr, "EncryptInit failed\n"); 179 ERR_print_errors_fp(stderr); 180 test1_exit(10); 181 } 182 EVP_CIPHER_CTX_set_padding(ctx, 0); 183 184 if (!EVP_EncryptUpdate(ctx, out, &outl, plaintext, pn)) { 185 fprintf(stderr, "Encrypt failed\n"); 186 ERR_print_errors_fp(stderr); 187 test1_exit(6); 188 } 189 if (!EVP_EncryptFinal_ex(ctx, out + outl, &outl2)) { 190 fprintf(stderr, "EncryptFinal failed\n"); 191 ERR_print_errors_fp(stderr); 192 test1_exit(7); 193 } 194 195 if (outl + outl2 != cn) { 196 fprintf(stderr, "Ciphertext length mismatch got %d expected %d\n", 197 outl + outl2, cn); 198 test1_exit(8); 199 } 200 201 if (memcmp(out, ciphertext, cn)) { 202 fprintf(stderr, "Ciphertext mismatch\n"); 203 hexdump(stderr, "Got",out,cn); 204 hexdump(stderr, "Expected",ciphertext,cn); 205 test1_exit(9); 206 } 207 } 208 209 if (encdec <= 0) { 210 eiv = iv; 211 if (EVP_CIPHER_mode(c) == EVP_CIPH_WRAP_MODE && in == 0) 212 eiv = NULL; 213 if (!EVP_DecryptInit_ex(ctx, c,NULL, key, eiv)) { 214 fprintf(stderr, "DecryptInit failed\n"); 215 ERR_print_errors_fp(stderr); 216 test1_exit(11); 217 } 218 EVP_CIPHER_CTX_set_padding(ctx, 0); 219 220 if (!EVP_DecryptUpdate(ctx, out, &outl, ciphertext, cn)) { 221 fprintf(stderr, "Decrypt failed\n"); 222 ERR_print_errors_fp(stderr); 223 test1_exit(6); 224 } 225 if (!EVP_DecryptFinal_ex(ctx, out + outl, &outl2)) { 226 fprintf(stderr, "DecryptFinal failed\n"); 227 ERR_print_errors_fp(stderr); 228 test1_exit(7); 229 } 230 231 if (outl + outl2 != pn) { 232 fprintf(stderr, "Plaintext length mismatch got %d expected %d\n", 233 outl + outl2, pn); 234 test1_exit(8); 235 } 236 237 if (memcmp(out, plaintext, pn)) { 238 fprintf(stderr, "Plaintext mismatch\n"); 239 hexdump(stderr, "Got",out,pn); 240 hexdump(stderr, "Expected",plaintext,pn); 241 test1_exit(9); 242 } 243 } 244 245 EVP_CIPHER_CTX_free(ctx); 246 247 if (verbose) 248 printf("\n"); 249 } 250 251 static int 252 test_cipher(const char *cipher, const unsigned char *key, int kn, 253 const unsigned char *iv, int in, const unsigned char *plaintext, int pn, 254 const unsigned char *ciphertext, int cn, int encdec) 255 { 256 const EVP_CIPHER *c; 257 258 c = EVP_get_cipherbyname(cipher); 259 if (!c) 260 return 0; 261 262 test1(c, key, kn, iv, in, plaintext, pn, ciphertext, cn, encdec); 263 264 return 1; 265 } 266 267 static int 268 test_digest(const char *digest, const unsigned char *plaintext, int pn, 269 const unsigned char *ciphertext, unsigned int cn) 270 { 271 const EVP_MD *d; 272 EVP_MD_CTX *ctx; 273 unsigned char md[EVP_MAX_MD_SIZE]; 274 unsigned int mdn; 275 276 d = EVP_get_digestbyname(digest); 277 if (!d) 278 return 0; 279 280 if (verbose) { 281 printf("Testing digest %s\n",EVP_MD_name(d)); 282 hexdump(stdout, "Plaintext",plaintext,pn); 283 hexdump(stdout, "Digest",ciphertext,cn); 284 } 285 286 if ((ctx = EVP_MD_CTX_new()) == NULL) { 287 fprintf(stderr, "EVP_CIPHER_CTX_new failed\n"); 288 ERR_print_errors_fp(stderr); 289 test1_exit(104); 290 } 291 if (!EVP_DigestInit_ex(ctx, d, NULL)) { 292 fprintf(stderr, "DigestInit failed\n"); 293 ERR_print_errors_fp(stderr); 294 exit(100); 295 } 296 if (!EVP_DigestUpdate(ctx, plaintext, pn)) { 297 fprintf(stderr, "DigestUpdate failed\n"); 298 ERR_print_errors_fp(stderr); 299 exit(101); 300 } 301 if (!EVP_DigestFinal_ex(ctx, md, &mdn)) { 302 fprintf(stderr, "DigestFinal failed\n"); 303 ERR_print_errors_fp(stderr); 304 exit(101); 305 } 306 EVP_MD_CTX_free(ctx); 307 ctx = NULL; 308 309 if (mdn != cn) { 310 fprintf(stderr, "Digest length mismatch, got %d expected %d\n",mdn,cn); 311 exit(102); 312 } 313 314 if (memcmp(md, ciphertext, cn)) { 315 fprintf(stderr, "Digest mismatch\n"); 316 hexdump(stderr, "Got",md,cn); 317 hexdump(stderr, "Expected",ciphertext,cn); 318 exit(103); 319 } 320 if (verbose) 321 printf("\n"); 322 323 return 1; 324 } 325 326 int 327 main(int argc, char **argv) 328 { 329 const char *szTestFile; 330 FILE *f; 331 332 if (argc != 2 && argc != 3) { 333 fprintf(stderr, "%s <test file>\n",argv[0]); 334 exit(1); 335 } 336 if (argc == 3 && strcmp(argv[1], "-v") == 0) { 337 verbose = 1; 338 argv++; 339 argc--; 340 } 341 342 szTestFile = argv[1]; 343 344 f=fopen(szTestFile, "r"); 345 if (!f) { 346 perror(szTestFile); 347 exit(2); 348 } 349 350 /* Load up the software EVP_CIPHER and EVP_MD definitions */ 351 OpenSSL_add_all_ciphers(); 352 OpenSSL_add_all_digests(); 353 #ifndef OPENSSL_NO_ENGINE 354 /* Load all compiled-in ENGINEs */ 355 ENGINE_load_builtin_engines(); 356 #endif 357 #if 0 358 OPENSSL_config(); 359 #endif 360 #ifndef OPENSSL_NO_ENGINE 361 /* Register all available ENGINE implementations of ciphers and digests. 362 * This could perhaps be changed to "ENGINE_register_all_complete()"? */ 363 ENGINE_register_all_ciphers(); 364 ENGINE_register_all_digests(); 365 /* If we add command-line options, this statement should be switchable. 366 * It'll prevent ENGINEs being ENGINE_init()ialised for cipher/digest use if 367 * they weren't already initialised. */ 368 /* ENGINE_set_cipher_flags(ENGINE_CIPHER_FLAG_NOINIT); */ 369 #endif 370 371 for (;;) { 372 char line[8 * 1024]; 373 char *p; 374 char *cipher; 375 unsigned char *iv, *key, *plaintext, *ciphertext; 376 int encdec; 377 int kn, in, pn, cn; 378 379 if (!fgets((char *)line, sizeof line, f)) 380 break; 381 if (line[0] == '#' || line[0] == '\n') 382 continue; 383 p = line; 384 cipher=sstrsep(&p, ":"); 385 key=ustrsep(&p, ":"); 386 iv=ustrsep(&p, ":"); 387 plaintext=ustrsep(&p, ":"); 388 ciphertext=ustrsep(&p, ":"); 389 if (p[-1] == '\n') { 390 p[-1] = '\0'; 391 encdec = -1; 392 } else { 393 encdec = atoi(sstrsep(&p, "\n")); 394 } 395 396 397 kn = convert(key); 398 in = convert(iv); 399 pn = convert(plaintext); 400 cn = convert(ciphertext); 401 402 if (!test_cipher(cipher, key, kn, iv, in, plaintext, pn, ciphertext, cn, encdec) && 403 !test_digest(cipher, plaintext, pn, ciphertext, cn)) { 404 #ifdef OPENSSL_NO_AES 405 if (strstr(cipher, "AES") == cipher && verbose) { 406 if (verbose) 407 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 408 continue; 409 } 410 #endif 411 #ifdef OPENSSL_NO_DES 412 if (strstr(cipher, "DES") == cipher && verbose) { 413 if (verbose) 414 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 415 continue; 416 } 417 #endif 418 #ifdef OPENSSL_NO_RC4 419 if (strstr(cipher, "RC4") == cipher && verbose) { 420 if (verbose) 421 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 422 continue; 423 } 424 #endif 425 #ifdef OPENSSL_NO_CAMELLIA 426 if (strstr(cipher, "CAMELLIA") == cipher && verbose) { 427 if (verbose) 428 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 429 continue; 430 } 431 #endif 432 #ifdef OPENSSL_NO_SEED 433 if (strstr(cipher, "SEED") == cipher) { 434 if (verbose) 435 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 436 continue; 437 } 438 #endif 439 #ifdef OPENSSL_NO_CHACHA 440 if (strstr(cipher, "ChaCha") == cipher) { 441 if (verbose) 442 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 443 continue; 444 } 445 #endif 446 #ifdef OPENSSL_NO_GOST 447 if (strstr(cipher, "md_gost") == cipher || 448 strstr(cipher, "streebog") == cipher) { 449 if (verbose) 450 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 451 continue; 452 } 453 #endif 454 fprintf(stderr, "Can't find %s\n",cipher); 455 exit(3); 456 } 457 } 458 fclose(f); 459 460 #ifndef OPENSSL_NO_ENGINE 461 ENGINE_cleanup(); 462 #endif 463 EVP_cleanup(); 464 CRYPTO_cleanup_all_ex_data(); 465 ERR_remove_thread_state(NULL); 466 ERR_free_strings(); 467 CRYPTO_mem_leaks_fp(stderr); 468 469 return 0; 470 } 471