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