1 /* $OpenBSD: evptest.c,v 1.11 2021/11/18 21:18:28 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 static void 63 hexdump(FILE *f, const char *title, const unsigned char *s, int l) 64 { 65 int n = 0; 66 67 fprintf(f, "%s",title); 68 for (; n < l; ++n) { 69 if ((n % 16) == 0) 70 fprintf(f, "\n%04x",n); 71 fprintf(f, " %02x",s[n]); 72 } 73 fprintf(f, "\n"); 74 } 75 76 static int 77 convert(unsigned char *s) 78 { 79 unsigned char *d; 80 81 for (d = s; *s; s += 2,++d) { 82 unsigned int n; 83 84 if (!s[1]) { 85 fprintf(stderr, "Odd number of hex digits!\n"); 86 exit(4); 87 } 88 if (sscanf((char *)s, "%2x", &n) != 1) { 89 fprintf(stderr, "Invalid hex value at %s\n", s); 90 exit(4); 91 } 92 93 *d = (unsigned char)n; 94 } 95 return s - d; 96 } 97 98 static char * 99 sstrsep(char **string, const char *delim) 100 { 101 char isdelim[256]; 102 char *token = *string; 103 104 if (**string == 0) 105 return NULL; 106 107 memset(isdelim, 0, 256); 108 isdelim[0] = 1; 109 110 while (*delim) { 111 isdelim[(unsigned char)(*delim)] = 1; 112 delim++; 113 } 114 115 while (!isdelim[(unsigned char)(**string)]) { 116 (*string)++; 117 } 118 119 if (**string) { 120 **string = 0; 121 (*string)++; 122 } 123 124 return token; 125 } 126 127 static unsigned char * 128 ustrsep(char **p, const char *sep) 129 { 130 return (unsigned char *)sstrsep(p, sep); 131 } 132 133 static int 134 test1_exit(int ec) 135 { 136 exit(ec); 137 return(0); /* To keep some compilers quiet */ 138 } 139 140 static void 141 test1(const EVP_CIPHER *c, const unsigned char *key, int kn, 142 const unsigned char *iv, int in, const unsigned char *plaintext, int pn, 143 const unsigned char *ciphertext, int cn, int encdec) 144 { 145 EVP_CIPHER_CTX *ctx; 146 unsigned char out[4096]; 147 const unsigned char *eiv; 148 int outl, outl2; 149 150 printf("Testing cipher %s%s\n", EVP_CIPHER_name(c), 151 (encdec == 1 ? "(encrypt)" : (encdec == 0 ? "(decrypt)" : "(encrypt/decrypt)"))); 152 hexdump(stdout, "Key",key,kn); 153 if (in) 154 hexdump(stdout, "IV",iv,in); 155 hexdump(stdout, "Plaintext",plaintext,pn); 156 hexdump(stdout, "Ciphertext",ciphertext,cn); 157 158 if (kn != EVP_CIPHER_key_length(c)) { 159 fprintf(stderr, "Key length doesn't match, got %d expected %lu\n",kn, 160 (unsigned long)EVP_CIPHER_key_length(c)); 161 test1_exit(5); 162 } 163 if ((ctx = EVP_CIPHER_CTX_new()) == NULL) { 164 fprintf(stderr, "EVP_CIPHER_CTX_new failed\n"); 165 ERR_print_errors_fp(stderr); 166 test1_exit(12); 167 } 168 EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); 169 if (encdec != 0) { 170 eiv = iv; 171 if (EVP_CIPHER_mode(c) == EVP_CIPH_WRAP_MODE && in == 0) 172 eiv = NULL; 173 if (!EVP_EncryptInit_ex(ctx, c, NULL, key, eiv)) { 174 fprintf(stderr, "EncryptInit failed\n"); 175 ERR_print_errors_fp(stderr); 176 test1_exit(10); 177 } 178 EVP_CIPHER_CTX_set_padding(ctx, 0); 179 180 if (!EVP_EncryptUpdate(ctx, out, &outl, plaintext, pn)) { 181 fprintf(stderr, "Encrypt failed\n"); 182 ERR_print_errors_fp(stderr); 183 test1_exit(6); 184 } 185 if (!EVP_EncryptFinal_ex(ctx, out + outl, &outl2)) { 186 fprintf(stderr, "EncryptFinal failed\n"); 187 ERR_print_errors_fp(stderr); 188 test1_exit(7); 189 } 190 191 if (outl + outl2 != cn) { 192 fprintf(stderr, "Ciphertext length mismatch got %d expected %d\n", 193 outl + outl2, cn); 194 test1_exit(8); 195 } 196 197 if (memcmp(out, ciphertext, cn)) { 198 fprintf(stderr, "Ciphertext mismatch\n"); 199 hexdump(stderr, "Got",out,cn); 200 hexdump(stderr, "Expected",ciphertext,cn); 201 test1_exit(9); 202 } 203 } 204 205 if (encdec <= 0) { 206 eiv = iv; 207 if (EVP_CIPHER_mode(c) == EVP_CIPH_WRAP_MODE && in == 0) 208 eiv = NULL; 209 if (!EVP_DecryptInit_ex(ctx, c,NULL, key, eiv)) { 210 fprintf(stderr, "DecryptInit failed\n"); 211 ERR_print_errors_fp(stderr); 212 test1_exit(11); 213 } 214 EVP_CIPHER_CTX_set_padding(ctx, 0); 215 216 if (!EVP_DecryptUpdate(ctx, out, &outl, ciphertext, cn)) { 217 fprintf(stderr, "Decrypt failed\n"); 218 ERR_print_errors_fp(stderr); 219 test1_exit(6); 220 } 221 if (!EVP_DecryptFinal_ex(ctx, out + outl, &outl2)) { 222 fprintf(stderr, "DecryptFinal failed\n"); 223 ERR_print_errors_fp(stderr); 224 test1_exit(7); 225 } 226 227 if (outl + outl2 != pn) { 228 fprintf(stderr, "Plaintext length mismatch got %d expected %d\n", 229 outl + outl2, pn); 230 test1_exit(8); 231 } 232 233 if (memcmp(out, plaintext, pn)) { 234 fprintf(stderr, "Plaintext mismatch\n"); 235 hexdump(stderr, "Got",out,pn); 236 hexdump(stderr, "Expected",plaintext,pn); 237 test1_exit(9); 238 } 239 } 240 241 EVP_CIPHER_CTX_free(ctx); 242 243 printf("\n"); 244 } 245 246 static int 247 test_cipher(const char *cipher, const unsigned char *key, int kn, 248 const unsigned char *iv, int in, const unsigned char *plaintext, int pn, 249 const unsigned char *ciphertext, int cn, int encdec) 250 { 251 const EVP_CIPHER *c; 252 253 c = EVP_get_cipherbyname(cipher); 254 if (!c) 255 return 0; 256 257 test1(c, key, kn, iv, in, plaintext, pn, ciphertext, cn, encdec); 258 259 return 1; 260 } 261 262 static int 263 test_digest(const char *digest, const unsigned char *plaintext, int pn, 264 const unsigned char *ciphertext, unsigned int cn) 265 { 266 const EVP_MD *d; 267 EVP_MD_CTX *ctx; 268 unsigned char md[EVP_MAX_MD_SIZE]; 269 unsigned int mdn; 270 271 d = EVP_get_digestbyname(digest); 272 if (!d) 273 return 0; 274 275 printf("Testing digest %s\n",EVP_MD_name(d)); 276 hexdump(stdout, "Plaintext",plaintext,pn); 277 hexdump(stdout, "Digest",ciphertext,cn); 278 279 if ((ctx = EVP_MD_CTX_new()) == NULL) { 280 fprintf(stderr, "EVP_CIPHER_CTX_new failed\n"); 281 ERR_print_errors_fp(stderr); 282 test1_exit(104); 283 } 284 if (!EVP_DigestInit_ex(ctx, d, NULL)) { 285 fprintf(stderr, "DigestInit failed\n"); 286 ERR_print_errors_fp(stderr); 287 exit(100); 288 } 289 if (!EVP_DigestUpdate(ctx, plaintext, pn)) { 290 fprintf(stderr, "DigestUpdate failed\n"); 291 ERR_print_errors_fp(stderr); 292 exit(101); 293 } 294 if (!EVP_DigestFinal_ex(ctx, md, &mdn)) { 295 fprintf(stderr, "DigestFinal failed\n"); 296 ERR_print_errors_fp(stderr); 297 exit(101); 298 } 299 EVP_MD_CTX_free(ctx); 300 ctx = NULL; 301 302 if (mdn != cn) { 303 fprintf(stderr, "Digest length mismatch, got %d expected %d\n",mdn,cn); 304 exit(102); 305 } 306 307 if (memcmp(md, ciphertext, cn)) { 308 fprintf(stderr, "Digest mismatch\n"); 309 hexdump(stderr, "Got",md,cn); 310 hexdump(stderr, "Expected",ciphertext,cn); 311 exit(103); 312 } 313 314 printf("\n"); 315 316 return 1; 317 } 318 319 int 320 main(int argc, char **argv) 321 { 322 const char *szTestFile; 323 FILE *f; 324 325 if (argc != 2) { 326 fprintf(stderr, "%s <test file>\n",argv[0]); 327 exit(1); 328 } 329 330 szTestFile = argv[1]; 331 332 f=fopen(szTestFile, "r"); 333 if (!f) { 334 perror(szTestFile); 335 exit(2); 336 } 337 338 /* Load up the software EVP_CIPHER and EVP_MD definitions */ 339 OpenSSL_add_all_ciphers(); 340 OpenSSL_add_all_digests(); 341 #ifndef OPENSSL_NO_ENGINE 342 /* Load all compiled-in ENGINEs */ 343 ENGINE_load_builtin_engines(); 344 #endif 345 #if 0 346 OPENSSL_config(); 347 #endif 348 #ifndef OPENSSL_NO_ENGINE 349 /* Register all available ENGINE implementations of ciphers and digests. 350 * This could perhaps be changed to "ENGINE_register_all_complete()"? */ 351 ENGINE_register_all_ciphers(); 352 ENGINE_register_all_digests(); 353 /* If we add command-line options, this statement should be switchable. 354 * It'll prevent ENGINEs being ENGINE_init()ialised for cipher/digest use if 355 * they weren't already initialised. */ 356 /* ENGINE_set_cipher_flags(ENGINE_CIPHER_FLAG_NOINIT); */ 357 #endif 358 359 for (;;) { 360 char line[8 * 1024]; 361 char *p; 362 char *cipher; 363 unsigned char *iv, *key, *plaintext, *ciphertext; 364 int encdec; 365 int kn, in, pn, cn; 366 367 if (!fgets((char *)line, sizeof line, f)) 368 break; 369 if (line[0] == '#' || line[0] == '\n') 370 continue; 371 p = line; 372 cipher=sstrsep(&p, ":"); 373 key=ustrsep(&p, ":"); 374 iv=ustrsep(&p, ":"); 375 plaintext=ustrsep(&p, ":"); 376 ciphertext=ustrsep(&p, ":"); 377 if (p[-1] == '\n') { 378 p[-1] = '\0'; 379 encdec = -1; 380 } else { 381 encdec = atoi(sstrsep(&p, "\n")); 382 } 383 384 385 kn = convert(key); 386 in = convert(iv); 387 pn = convert(plaintext); 388 cn = convert(ciphertext); 389 390 if (!test_cipher(cipher, key, kn, iv, in, plaintext, pn, ciphertext, cn, encdec) && 391 !test_digest(cipher, plaintext, pn, ciphertext, cn)) { 392 #ifdef OPENSSL_NO_AES 393 if (strstr(cipher, "AES") == cipher) { 394 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 395 continue; 396 } 397 #endif 398 #ifdef OPENSSL_NO_DES 399 if (strstr(cipher, "DES") == cipher) { 400 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 401 continue; 402 } 403 #endif 404 #ifdef OPENSSL_NO_RC4 405 if (strstr(cipher, "RC4") == cipher) { 406 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 407 continue; 408 } 409 #endif 410 #ifdef OPENSSL_NO_CAMELLIA 411 if (strstr(cipher, "CAMELLIA") == cipher) { 412 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 413 continue; 414 } 415 #endif 416 #ifdef OPENSSL_NO_SEED 417 if (strstr(cipher, "SEED") == cipher) { 418 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 419 continue; 420 } 421 #endif 422 #ifdef OPENSSL_NO_CHACHA 423 if (strstr(cipher, "ChaCha") == cipher) { 424 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 425 continue; 426 } 427 #endif 428 #ifdef OPENSSL_NO_GOST 429 if (strstr(cipher, "md_gost") == cipher || 430 strstr(cipher, "streebog") == cipher) { 431 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 432 continue; 433 } 434 #endif 435 fprintf(stderr, "Can't find %s\n",cipher); 436 exit(3); 437 } 438 } 439 fclose(f); 440 441 #ifndef OPENSSL_NO_ENGINE 442 ENGINE_cleanup(); 443 #endif 444 EVP_cleanup(); 445 CRYPTO_cleanup_all_ex_data(); 446 ERR_remove_thread_state(NULL); 447 ERR_free_strings(); 448 CRYPTO_mem_leaks_fp(stderr); 449 450 return 0; 451 } 452