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