1/* $OpenBSD: evptest.c,v 1.15 2024/03/30 09:49:59 tb Exp $ */ 2/* Written by Ben Laurie, 2001 */ 3/* 4 * Copyright (c) 2001 The OpenSSL Project. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * 3. All advertising materials mentioning features or use of this 19 * software must display the following acknowledgment: 20 * "This product includes software developed by the OpenSSL Project 21 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 22 * 23 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 24 * endorse or promote products derived from this software without 25 * prior written permission. For written permission, please contact 26 * openssl-core@openssl.org. 27 * 28 * 5. Products derived from this software may not be called "OpenSSL" 29 * nor may "OpenSSL" appear in their names without prior written 30 * permission of the OpenSSL Project. 31 * 32 * 6. Redistributions of any form whatsoever must retain the following 33 * acknowledgment: 34 * "This product includes software developed by the OpenSSL Project 35 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 36 * 37 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 38 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 40 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 43 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 46 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 48 * OF THE POSSIBILITY OF SUCH DAMAGE. 49 */ 50 51#include <stdio.h> 52#include <stdlib.h> 53#include <string.h> 54 55#include <openssl/opensslconf.h> 56#include <openssl/evp.h> 57#include <openssl/err.h> 58#include <openssl/conf.h> 59 60int verbose; 61 62static void 63hexdump(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 77convert(unsigned char *s) 78{ 79 unsigned char *d; 80 81 for (d = s; *s; s += 2,++d) { 82 unsigned int n; 83 84 if (!s[1]) { 85 fprintf(stderr, "Odd number of hex digits!\n"); 86 exit(4); 87 } 88 if (sscanf((char *)s, "%2x", &n) != 1) { 89 fprintf(stderr, "Invalid hex value at %s\n", s); 90 exit(4); 91 } 92 93 *d = (unsigned char)n; 94 } 95 return s - d; 96} 97 98static char * 99sstrsep(char **string, const char *delim) 100{ 101 char isdelim[256]; 102 char *token = *string; 103 104 if (**string == 0) 105 return NULL; 106 107 memset(isdelim, 0, 256); 108 isdelim[0] = 1; 109 110 while (*delim) { 111 isdelim[(unsigned char)(*delim)] = 1; 112 delim++; 113 } 114 115 while (!isdelim[(unsigned char)(**string)]) { 116 (*string)++; 117 } 118 119 if (**string) { 120 **string = 0; 121 (*string)++; 122 } 123 124 return token; 125} 126 127static unsigned char * 128ustrsep(char **p, const char *sep) 129{ 130 return (unsigned char *)sstrsep(p, sep); 131} 132 133static void 134test1(const EVP_CIPHER *c, const unsigned char *key, int kn, 135 const unsigned char *iv, int in, const unsigned char *plaintext, int pn, 136 const unsigned char *ciphertext, int cn, int encdec) 137{ 138 EVP_CIPHER_CTX *ctx; 139 unsigned char out[4096]; 140 const unsigned char *eiv; 141 int outl, outl2; 142 143 if (verbose) { 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 153 if (kn != EVP_CIPHER_key_length(c)) { 154 fprintf(stderr, "Key length doesn't match, got %d expected %lu\n",kn, 155 (unsigned long)EVP_CIPHER_key_length(c)); 156 exit(5); 157 } 158 if ((ctx = EVP_CIPHER_CTX_new()) == NULL) { 159 fprintf(stderr, "EVP_CIPHER_CTX_new failed\n"); 160 ERR_print_errors_fp(stderr); 161 exit(12); 162 } 163 EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); 164 if (encdec != 0) { 165 eiv = iv; 166 if (EVP_CIPHER_mode(c) == EVP_CIPH_WRAP_MODE && in == 0) 167 eiv = NULL; 168 if (!EVP_EncryptInit_ex(ctx, c, NULL, key, eiv)) { 169 fprintf(stderr, "EncryptInit failed\n"); 170 ERR_print_errors_fp(stderr); 171 exit(10); 172 } 173 EVP_CIPHER_CTX_set_padding(ctx, 0); 174 175 if (!EVP_EncryptUpdate(ctx, out, &outl, plaintext, pn)) { 176 fprintf(stderr, "Encrypt failed\n"); 177 ERR_print_errors_fp(stderr); 178 exit(6); 179 } 180 if (!EVP_EncryptFinal_ex(ctx, out + outl, &outl2)) { 181 fprintf(stderr, "EncryptFinal failed\n"); 182 ERR_print_errors_fp(stderr); 183 exit(7); 184 } 185 186 if (outl + outl2 != cn) { 187 fprintf(stderr, "Ciphertext length mismatch got %d expected %d\n", 188 outl + outl2, cn); 189 exit(8); 190 } 191 192 if (memcmp(out, ciphertext, cn)) { 193 fprintf(stderr, "Ciphertext mismatch\n"); 194 hexdump(stderr, "Got",out,cn); 195 hexdump(stderr, "Expected",ciphertext,cn); 196 exit(9); 197 } 198 } 199 200 if (encdec <= 0) { 201 eiv = iv; 202 if (EVP_CIPHER_mode(c) == EVP_CIPH_WRAP_MODE && in == 0) 203 eiv = NULL; 204 if (!EVP_DecryptInit_ex(ctx, c,NULL, key, eiv)) { 205 fprintf(stderr, "DecryptInit failed\n"); 206 ERR_print_errors_fp(stderr); 207 exit(11); 208 } 209 EVP_CIPHER_CTX_set_padding(ctx, 0); 210 211 if (!EVP_DecryptUpdate(ctx, out, &outl, ciphertext, cn)) { 212 fprintf(stderr, "Decrypt failed\n"); 213 ERR_print_errors_fp(stderr); 214 exit(6); 215 } 216 if (!EVP_DecryptFinal_ex(ctx, out + outl, &outl2)) { 217 fprintf(stderr, "DecryptFinal failed\n"); 218 ERR_print_errors_fp(stderr); 219 exit(7); 220 } 221 222 if (outl + outl2 != pn) { 223 fprintf(stderr, "Plaintext length mismatch got %d expected %d\n", 224 outl + outl2, pn); 225 exit(8); 226 } 227 228 if (memcmp(out, plaintext, pn)) { 229 fprintf(stderr, "Plaintext mismatch\n"); 230 hexdump(stderr, "Got",out,pn); 231 hexdump(stderr, "Expected",plaintext,pn); 232 exit(9); 233 } 234 } 235 236 EVP_CIPHER_CTX_free(ctx); 237 238 if (verbose) 239 printf("\n"); 240} 241 242static int 243test_cipher(const char *cipher, const unsigned char *key, int kn, 244 const unsigned char *iv, int in, const unsigned char *plaintext, int pn, 245 const unsigned char *ciphertext, int cn, int encdec) 246{ 247 const EVP_CIPHER *c; 248 249 c = EVP_get_cipherbyname(cipher); 250 if (!c) 251 return 0; 252 253 test1(c, key, kn, iv, in, plaintext, pn, ciphertext, cn, encdec); 254 255 return 1; 256} 257 258static int 259test_digest(const char *digest, const unsigned char *plaintext, int pn, 260 const unsigned char *ciphertext, unsigned int cn) 261{ 262 const EVP_MD *d; 263 EVP_MD_CTX *ctx; 264 unsigned char md[EVP_MAX_MD_SIZE]; 265 unsigned int mdn; 266 267 d = EVP_get_digestbyname(digest); 268 if (!d) 269 return 0; 270 271 if (verbose) { 272 printf("Testing digest %s\n",EVP_MD_name(d)); 273 hexdump(stdout, "Plaintext",plaintext,pn); 274 hexdump(stdout, "Digest",ciphertext,cn); 275 } 276 277 if ((ctx = EVP_MD_CTX_new()) == NULL) { 278 fprintf(stderr, "EVP_CIPHER_CTX_new failed\n"); 279 ERR_print_errors_fp(stderr); 280 exit(104); 281 } 282 if (!EVP_DigestInit_ex(ctx, d, NULL)) { 283 fprintf(stderr, "DigestInit failed\n"); 284 ERR_print_errors_fp(stderr); 285 exit(100); 286 } 287 if (!EVP_DigestUpdate(ctx, plaintext, pn)) { 288 fprintf(stderr, "DigestUpdate failed\n"); 289 ERR_print_errors_fp(stderr); 290 exit(101); 291 } 292 if (!EVP_DigestFinal_ex(ctx, md, &mdn)) { 293 fprintf(stderr, "DigestFinal failed\n"); 294 ERR_print_errors_fp(stderr); 295 exit(101); 296 } 297 EVP_MD_CTX_free(ctx); 298 ctx = NULL; 299 300 if (mdn != cn) { 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 fprintf(stderr, "Digest mismatch\n"); 307 hexdump(stderr, "Got",md,cn); 308 hexdump(stderr, "Expected",ciphertext,cn); 309 exit(103); 310 } 311 if (verbose) 312 printf("\n"); 313 314 return 1; 315} 316 317int 318main(int argc, char **argv) 319{ 320 const char *szTestFile; 321 FILE *f; 322 323 if (argc != 2 && argc != 3) { 324 fprintf(stderr, "%s <test file>\n",argv[0]); 325 exit(1); 326 } 327 if (argc == 3 && strcmp(argv[1], "-v") == 0) { 328 verbose = 1; 329 argv++; 330 argc--; 331 } 332 333 szTestFile = argv[1]; 334 335 f=fopen(szTestFile, "r"); 336 if (!f) { 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 345 for (;;) { 346 char line[8 * 1024]; 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 371 kn = convert(key); 372 in = convert(iv); 373 pn = convert(plaintext); 374 cn = convert(ciphertext); 375 376 if (!test_cipher(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 && verbose) { 380 if (verbose) 381 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 382 continue; 383 } 384#endif 385#ifdef OPENSSL_NO_DES 386 if (strstr(cipher, "DES") == cipher && verbose) { 387 if (verbose) 388 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 389 continue; 390 } 391#endif 392#ifdef OPENSSL_NO_RC4 393 if (strstr(cipher, "RC4") == cipher && verbose) { 394 if (verbose) 395 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 396 continue; 397 } 398#endif 399#ifdef OPENSSL_NO_CAMELLIA 400 if (strstr(cipher, "CAMELLIA") == cipher && verbose) { 401 if (verbose) 402 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 403 continue; 404 } 405#endif 406#ifdef OPENSSL_NO_SEED 407 if (strstr(cipher, "SEED") == cipher) { 408 if (verbose) 409 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 410 continue; 411 } 412#endif 413#ifdef OPENSSL_NO_CHACHA 414 if (strstr(cipher, "ChaCha") == cipher) { 415 if (verbose) 416 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 417 continue; 418 } 419#endif 420#ifdef OPENSSL_NO_GOST 421 if (strstr(cipher, "md_gost") == cipher || 422 strstr(cipher, "streebog") == cipher) { 423 if (verbose) 424 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 425 continue; 426 } 427#endif 428 fprintf(stderr, "Can't find %s\n",cipher); 429 exit(3); 430 } 431 } 432 fclose(f); 433 434 EVP_cleanup(); 435 CRYPTO_cleanup_all_ex_data(); 436 ERR_remove_thread_state(NULL); 437 ERR_free_strings(); 438 439 return 0; 440} 441