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