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