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