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
60 int verbose;
61
62 static void
hexdump(FILE * f,const char * title,const unsigned char * s,int l)63 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
76 static int
convert(unsigned char * s)77 convert(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
98 static char *
sstrsep(char ** string,const char * delim)99 sstrsep(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
127 static unsigned char *
ustrsep(char ** p,const char * sep)128 ustrsep(char **p, const char *sep)
129 {
130 return (unsigned char *)sstrsep(p, sep);
131 }
132
133 static void
test1(const EVP_CIPHER * c,const unsigned char * key,int kn,const unsigned char * iv,int in,const unsigned char * plaintext,int pn,const unsigned char * ciphertext,int cn,int encdec)134 test1(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
242 static int
test_cipher(const char * cipher,const unsigned char * key,int kn,const unsigned char * iv,int in,const unsigned char * plaintext,int pn,const unsigned char * ciphertext,int cn,int encdec)243 test_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
258 static int
test_digest(const char * digest,const unsigned char * plaintext,int pn,const unsigned char * ciphertext,unsigned int cn)259 test_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
317 int
main(int argc,char ** argv)318 main(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