xref: /openbsd-src/regress/lib/libcrypto/evp/evptest.c (revision e5fae9e65e1d65fd45ccaed4c62ee85a739895a5)
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