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