xref: /freebsd/tools/tools/crypto/cryptocheck.c (revision 85732ac8)
1 /*-
2  * Copyright (c) 2017 Chelsio Communications, Inc.
3  * All rights reserved.
4  * Written by: John Baldwin <jhb@FreeBSD.org>
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  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 /*-
28  * Copyright (c) 2004 Sam Leffler, Errno Consulting
29  * All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  * 1. Redistributions of source code must retain the above copyright
35  *    notice, this list of conditions and the following disclaimer,
36  *    without modification.
37  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
38  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
39  *    redistribution must be conditioned upon including a substantially
40  *    similar Disclaimer requirement for further binary redistribution.
41  * 3. Neither the names of the above-listed copyright holders nor the names
42  *    of any contributors may be used to endorse or promote products derived
43  *    from this software without specific prior written permission.
44  *
45  * NO WARRANTY
46  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
47  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
48  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
49  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
50  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
51  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
53  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
54  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
56  * THE POSSIBILITY OF SUCH DAMAGES.
57  *
58  * $FreeBSD$
59  */
60 
61 /*
62  * A different tool for checking hardware crypto support.  Whereas
63  * cryptotest is focused on simple performance numbers, this tool is
64  * focused on correctness.  For each crypto operation, it performs the
65  * operation once in software via OpenSSL and a second time via
66  * OpenCrypto and compares the results.
67  *
68  * cryptocheck [-vz] [-A aad length] [-a algorithm] [-d dev] [size ...]
69  *
70  * Options:
71  *	-v	Verbose.
72  *	-z	Run all algorithms on a variety of buffer sizes.
73  *
74  * Supported algorithms:
75  *	all		Run all tests
76  *	hmac		Run all hmac tests
77  *	blkcipher	Run all block cipher tests
78  *	authenc		Run all authenticated encryption tests
79  *	aead		Run all authenticated encryption with associated data
80  *			tests
81  *
82  * HMACs:
83  *	sha1		sha1 hmac
84  *	sha256		256-bit sha2 hmac
85  *	sha384		384-bit sha2 hmac
86  *	sha512		512-bit	sha2 hmac
87  *	blake2b		Blake2-B
88  *	blake2s		Blake2-S
89  *
90  * Block Ciphers:
91  *	aes-cbc		128-bit aes cbc
92  *	aes-cbc192	192-bit	aes cbc
93  *	aes-cbc256	256-bit aes cbc
94  *	aes-ctr		128-bit aes ctr
95  *	aes-ctr192	192-bit aes ctr
96  *	aes-ctr256	256-bit aes ctr
97  *	aes-xts		128-bit aes xts
98  *	aes-xts256	256-bit aes xts
99  *	chacha20
100  *
101  * Authenticated Encryption:
102  *	<block cipher>+<hmac>
103  *
104  * Authenticated Encryption with Associated Data:
105  *	aes-gcm		128-bit aes gcm
106  *	aes-gcm192	192-bit aes gcm
107  *	aes-gcm256	256-bit aes gcm
108  */
109 
110 #include <sys/param.h>
111 #include <assert.h>
112 #include <err.h>
113 #include <fcntl.h>
114 #include <libutil.h>
115 #include <stdbool.h>
116 #include <stdio.h>
117 #include <string.h>
118 #include <unistd.h>
119 
120 #include <openssl/err.h>
121 #include <openssl/hmac.h>
122 
123 #include <crypto/cryptodev.h>
124 
125 /* XXX: Temporary hack */
126 #ifndef COP_F_CIPHER_FIRST
127 #define	COP_F_CIPHER_FIRST	0x0001	/* Cipher before MAC. */
128 #endif
129 
130 struct alg {
131 	const char *name;
132 	int cipher;
133 	int mac;
134 	enum { T_HASH, T_HMAC, T_BLKCIPHER, T_AUTHENC, T_GCM } type;
135 	const EVP_CIPHER *(*evp_cipher)(void);
136 	const EVP_MD *(*evp_md)(void);
137 } algs[] = {
138 	{ .name = "sha1", .mac = CRYPTO_SHA1, .type = T_HASH,
139 	  .evp_md = EVP_sha1 },
140 	{ .name = "sha224", .mac = CRYPTO_SHA2_224, .type = T_HASH,
141 	  .evp_md = EVP_sha224 },
142 	{ .name = "sha256", .mac = CRYPTO_SHA2_256, .type = T_HASH,
143 	  .evp_md = EVP_sha256 },
144 	{ .name = "sha384", .mac = CRYPTO_SHA2_384, .type = T_HASH,
145 	  .evp_md = EVP_sha384 },
146 	{ .name = "sha512", .mac = CRYPTO_SHA2_512, .type = T_HASH,
147 	  .evp_md = EVP_sha512 },
148 	{ .name = "sha1hmac", .mac = CRYPTO_SHA1_HMAC, .type = T_HMAC,
149 	  .evp_md = EVP_sha1 },
150 	{ .name = "sha224hmac", .mac = CRYPTO_SHA2_224_HMAC, .type = T_HMAC,
151 	  .evp_md = EVP_sha224 },
152 	{ .name = "sha256hmac", .mac = CRYPTO_SHA2_256_HMAC, .type = T_HMAC,
153 	  .evp_md = EVP_sha256 },
154 	{ .name = "sha384hmac", .mac = CRYPTO_SHA2_384_HMAC, .type = T_HMAC,
155 	  .evp_md = EVP_sha384 },
156 	{ .name = "sha512hmac", .mac = CRYPTO_SHA2_512_HMAC, .type = T_HMAC,
157 	  .evp_md = EVP_sha512 },
158 	{ .name = "blake2b", .mac = CRYPTO_BLAKE2B, .type = T_HASH,
159 	  .evp_md = EVP_blake2b512 },
160 	{ .name = "blake2s", .mac = CRYPTO_BLAKE2S, .type = T_HASH,
161 	  .evp_md = EVP_blake2s256 },
162 	{ .name = "aes-cbc", .cipher = CRYPTO_AES_CBC, .type = T_BLKCIPHER,
163 	  .evp_cipher = EVP_aes_128_cbc },
164 	{ .name = "aes-cbc192", .cipher = CRYPTO_AES_CBC, .type = T_BLKCIPHER,
165 	  .evp_cipher = EVP_aes_192_cbc },
166 	{ .name = "aes-cbc256", .cipher = CRYPTO_AES_CBC, .type = T_BLKCIPHER,
167 	  .evp_cipher = EVP_aes_256_cbc },
168 	{ .name = "aes-ctr", .cipher = CRYPTO_AES_ICM, .type = T_BLKCIPHER,
169 	  .evp_cipher = EVP_aes_128_ctr },
170 	{ .name = "aes-ctr192", .cipher = CRYPTO_AES_ICM, .type = T_BLKCIPHER,
171 	  .evp_cipher = EVP_aes_192_ctr },
172 	{ .name = "aes-ctr256", .cipher = CRYPTO_AES_ICM, .type = T_BLKCIPHER,
173 	  .evp_cipher = EVP_aes_256_ctr },
174 	{ .name = "aes-xts", .cipher = CRYPTO_AES_XTS, .type = T_BLKCIPHER,
175 	  .evp_cipher = EVP_aes_128_xts },
176 	{ .name = "aes-xts256", .cipher = CRYPTO_AES_XTS, .type = T_BLKCIPHER,
177 	  .evp_cipher = EVP_aes_256_xts },
178 	{ .name = "chacha20", .cipher = CRYPTO_CHACHA20, .type = T_BLKCIPHER,
179 	  .evp_cipher = EVP_chacha20 },
180 	{ .name = "aes-gcm", .cipher = CRYPTO_AES_NIST_GCM_16,
181 	  .mac = CRYPTO_AES_128_NIST_GMAC, .type = T_GCM,
182 	  .evp_cipher = EVP_aes_128_gcm },
183 	{ .name = "aes-gcm192", .cipher = CRYPTO_AES_NIST_GCM_16,
184 	  .mac = CRYPTO_AES_192_NIST_GMAC, .type = T_GCM,
185 	  .evp_cipher = EVP_aes_192_gcm },
186 	{ .name = "aes-gcm256", .cipher = CRYPTO_AES_NIST_GCM_16,
187 	  .mac = CRYPTO_AES_256_NIST_GMAC, .type = T_GCM,
188 	  .evp_cipher = EVP_aes_256_gcm },
189 };
190 
191 static bool verbose;
192 static int crid;
193 static size_t aad_len;
194 
195 static void
196 usage(void)
197 {
198 	fprintf(stderr,
199 	    "usage: cryptocheck [-z] [-a algorithm] [-d dev] [size ...]\n");
200 	exit(1);
201 }
202 
203 static struct alg *
204 find_alg(const char *name)
205 {
206 	u_int i;
207 
208 	for (i = 0; i < nitems(algs); i++)
209 		if (strcasecmp(algs[i].name, name) == 0)
210 			return (&algs[i]);
211 	return (NULL);
212 }
213 
214 static struct alg *
215 build_authenc(struct alg *cipher, struct alg *hmac)
216 {
217 	static struct alg authenc;
218 	char *name;
219 
220 	assert(cipher->type == T_BLKCIPHER);
221 	assert(hmac->type == T_HMAC);
222 	memset(&authenc, 0, sizeof(authenc));
223 	asprintf(&name, "%s+%s", cipher->name, hmac->name);
224 	authenc.name = name;
225 	authenc.cipher = cipher->cipher;
226 	authenc.mac = hmac->mac;
227 	authenc.type = T_AUTHENC;
228 	authenc.evp_cipher = cipher->evp_cipher;
229 	authenc.evp_md = hmac->evp_md;
230 	return (&authenc);
231 }
232 
233 static struct alg *
234 build_authenc_name(const char *name)
235 {
236 	struct alg *cipher, *hmac;
237 	const char *hmac_name;
238 	char *cp, *cipher_name;
239 
240 	cp = strchr(name, '+');
241 	cipher_name = strndup(name, cp - name);
242 	hmac_name = cp + 1;
243 	cipher = find_alg(cipher_name);
244 	free(cipher_name);
245 	if (cipher == NULL)
246 		errx(1, "Invalid cipher %s", cipher_name);
247 	hmac = find_alg(hmac_name);
248 	if (hmac == NULL)
249 		errx(1, "Invalid hash %s", hmac_name);
250 	return (build_authenc(cipher, hmac));
251 }
252 
253 static int
254 devcrypto(void)
255 {
256 	static int fd = -1;
257 
258 	if (fd < 0) {
259 		fd = open("/dev/crypto", O_RDWR | O_CLOEXEC, 0);
260 		if (fd < 0)
261 			err(1, "/dev/crypto");
262 	}
263 	return (fd);
264 }
265 
266 static int
267 crlookup(const char *devname)
268 {
269 	struct crypt_find_op find;
270 
271 	if (strncmp(devname, "soft", 4) == 0)
272 		return CRYPTO_FLAG_SOFTWARE;
273 
274 	find.crid = -1;
275 	strlcpy(find.name, devname, sizeof(find.name));
276 	if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1)
277 		err(1, "ioctl(CIOCFINDDEV)");
278 	return (find.crid);
279 }
280 
281 const char *
282 crfind(int crid)
283 {
284 	static struct crypt_find_op find;
285 
286 	if (crid == CRYPTO_FLAG_SOFTWARE)
287 		return ("soft");
288 	else if (crid == CRYPTO_FLAG_HARDWARE)
289 		return ("unknown");
290 
291 	bzero(&find, sizeof(find));
292 	find.crid = crid;
293 	if (ioctl(devcrypto(), CRIOFINDDEV, &find) == -1)
294 		err(1, "ioctl(CIOCFINDDEV): crid %d", crid);
295 	return (find.name);
296 }
297 
298 static int
299 crget(void)
300 {
301 	int fd;
302 
303 	if (ioctl(devcrypto(), CRIOGET, &fd) == -1)
304 		err(1, "ioctl(CRIOGET)");
305 	if (fcntl(fd, F_SETFD, 1) == -1)
306 		err(1, "fcntl(F_SETFD) (crget)");
307 	return fd;
308 }
309 
310 static char
311 rdigit(void)
312 {
313 	const char a[] = {
314 		0x10,0x54,0x11,0x48,0x45,0x12,0x4f,0x13,0x49,0x53,0x14,0x41,
315 		0x15,0x16,0x4e,0x55,0x54,0x17,0x18,0x4a,0x4f,0x42,0x19,0x01
316 	};
317 	return 0x20+a[random()%nitems(a)];
318 }
319 
320 static char *
321 alloc_buffer(size_t len)
322 {
323 	char *buf;
324 	size_t i;
325 
326 	buf = malloc(len);
327 	for (i = 0; i < len; i++)
328 		buf[i] = rdigit();
329 	return (buf);
330 }
331 
332 static char *
333 generate_iv(size_t len, struct alg *alg)
334 {
335 	char *iv;
336 
337 	iv = alloc_buffer(len);
338 	switch (alg->cipher) {
339 	case CRYPTO_AES_ICM:
340 		/* Clear the low 32 bits of the IV to hold the counter. */
341 		iv[len - 4] = 0;
342 		iv[len - 3] = 0;
343 		iv[len - 2] = 0;
344 		iv[len - 1] = 0;
345 		break;
346 	case CRYPTO_AES_XTS:
347 		/*
348 		 * Clear the low 64-bits to only store a 64-bit block
349 		 * number.
350 		 */
351 		iv[len - 8] = 0;
352 		iv[len - 7] = 0;
353 		iv[len - 6] = 0;
354 		iv[len - 5] = 0;
355 		iv[len - 4] = 0;
356 		iv[len - 3] = 0;
357 		iv[len - 2] = 0;
358 		iv[len - 1] = 0;
359 		break;
360 	}
361 	return (iv);
362 }
363 
364 static bool
365 ocf_hash(struct alg *alg, const char *buffer, size_t size, char *digest,
366     int *cridp)
367 {
368 	struct session2_op sop;
369 	struct crypt_op cop;
370 	int fd;
371 
372 	memset(&sop, 0, sizeof(sop));
373 	memset(&cop, 0, sizeof(cop));
374 	sop.crid = crid;
375 	sop.mac = alg->mac;
376 	fd = crget();
377 	if (ioctl(fd, CIOCGSESSION2, &sop) < 0) {
378 		warn("cryptodev %s HASH not supported for device %s",
379 		    alg->name, crfind(crid));
380 		close(fd);
381 		return (false);
382 	}
383 
384 	cop.ses = sop.ses;
385 	cop.op = 0;
386 	cop.len = size;
387 	cop.src = (char *)buffer;
388 	cop.dst = NULL;
389 	cop.mac = digest;
390 	cop.iv = NULL;
391 
392 	if (ioctl(fd, CIOCCRYPT, &cop) < 0) {
393 		warn("cryptodev %s (%zu) HASH failed for device %s", alg->name,
394 		    size, crfind(crid));
395 		close(fd);
396 		return (false);
397 	}
398 
399 	if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0)
400 		warn("ioctl(CIOCFSESSION)");
401 
402 	close(fd);
403 	*cridp = sop.crid;
404 	return (true);
405 }
406 
407 static void
408 openssl_hash(struct alg *alg, const EVP_MD *md, const void *buffer,
409     size_t size, void *digest_out, unsigned *digest_sz_out)
410 {
411 	EVP_MD_CTX *mdctx;
412 	const char *errs;
413 	int rc;
414 
415 	errs = "";
416 
417 	mdctx = EVP_MD_CTX_create();
418 	if (mdctx == NULL)
419 		goto err_out;
420 
421 	rc = EVP_DigestInit_ex(mdctx, md, NULL);
422 	if (rc != 1)
423 		goto err_out;
424 
425 	rc = EVP_DigestUpdate(mdctx, buffer, size);
426 	if (rc != 1)
427 		goto err_out;
428 
429 	rc = EVP_DigestFinal_ex(mdctx, digest_out, digest_sz_out);
430 	if (rc != 1)
431 		goto err_out;
432 
433 	EVP_MD_CTX_destroy(mdctx);
434 	return;
435 
436 err_out:
437 	errx(1, "OpenSSL %s HASH failed%s: %s", alg->name, errs,
438 	    ERR_error_string(ERR_get_error(), NULL));
439 }
440 
441 static void
442 run_hash_test(struct alg *alg, size_t size)
443 {
444 	const EVP_MD *md;
445 	char *buffer;
446 	u_int digest_len;
447 	int crid;
448 	char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE];
449 
450 	memset(control_digest, 0x3c, sizeof(control_digest));
451 	memset(test_digest, 0x3c, sizeof(test_digest));
452 
453 	md = alg->evp_md();
454 	assert(EVP_MD_size(md) <= sizeof(control_digest));
455 
456 	buffer = alloc_buffer(size);
457 
458 	/* OpenSSL HASH. */
459 	digest_len = sizeof(control_digest);
460 	openssl_hash(alg, md, buffer, size, control_digest, &digest_len);
461 
462 	/* cryptodev HASH. */
463 	if (!ocf_hash(alg, buffer, size, test_digest, &crid))
464 		goto out;
465 	if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
466 		if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
467 			printf("%s (%zu) mismatch in trailer:\n",
468 			    alg->name, size);
469 		else
470 			printf("%s (%zu) mismatch:\n", alg->name, size);
471 		printf("control:\n");
472 		hexdump(control_digest, sizeof(control_digest), NULL, 0);
473 		printf("test (cryptodev device %s):\n", crfind(crid));
474 		hexdump(test_digest, sizeof(test_digest), NULL, 0);
475 		goto out;
476 	}
477 
478 	if (verbose)
479 		printf("%s (%zu) matched (cryptodev device %s)\n",
480 		    alg->name, size, crfind(crid));
481 
482 out:
483 	free(buffer);
484 }
485 
486 static bool
487 ocf_hmac(struct alg *alg, const char *buffer, size_t size, const char *key,
488     size_t key_len, char *digest, int *cridp)
489 {
490 	struct session2_op sop;
491 	struct crypt_op cop;
492 	int fd;
493 
494 	memset(&sop, 0, sizeof(sop));
495 	memset(&cop, 0, sizeof(cop));
496 	sop.crid = crid;
497 	sop.mackeylen = key_len;
498 	sop.mackey = (char *)key;
499 	sop.mac = alg->mac;
500 	fd = crget();
501 	if (ioctl(fd, CIOCGSESSION2, &sop) < 0) {
502 		warn("cryptodev %s HMAC not supported for device %s",
503 		    alg->name, crfind(crid));
504 		close(fd);
505 		return (false);
506 	}
507 
508 	cop.ses = sop.ses;
509 	cop.op = 0;
510 	cop.len = size;
511 	cop.src = (char *)buffer;
512 	cop.dst = NULL;
513 	cop.mac = digest;
514 	cop.iv = NULL;
515 
516 	if (ioctl(fd, CIOCCRYPT, &cop) < 0) {
517 		warn("cryptodev %s (%zu) HMAC failed for device %s", alg->name,
518 		    size, crfind(crid));
519 		close(fd);
520 		return (false);
521 	}
522 
523 	if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0)
524 		warn("ioctl(CIOCFSESSION)");
525 
526 	close(fd);
527 	*cridp = sop.crid;
528 	return (true);
529 }
530 
531 static void
532 run_hmac_test(struct alg *alg, size_t size)
533 {
534 	const EVP_MD *md;
535 	char *key, *buffer;
536 	u_int key_len, digest_len;
537 	int crid;
538 	char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE];
539 
540 	memset(control_digest, 0x3c, sizeof(control_digest));
541 	memset(test_digest, 0x3c, sizeof(test_digest));
542 
543 	md = alg->evp_md();
544 	key_len = EVP_MD_size(md);
545 	assert(EVP_MD_size(md) <= sizeof(control_digest));
546 
547 	key = alloc_buffer(key_len);
548 	buffer = alloc_buffer(size);
549 
550 	/* OpenSSL HMAC. */
551 	digest_len = sizeof(control_digest);
552 	if (HMAC(md, key, key_len, (u_char *)buffer, size,
553 	    (u_char *)control_digest, &digest_len) == NULL)
554 		errx(1, "OpenSSL %s (%zu) HMAC failed: %s", alg->name,
555 		    size, ERR_error_string(ERR_get_error(), NULL));
556 
557 	/* cryptodev HMAC. */
558 	if (!ocf_hmac(alg, buffer, size, key, key_len, test_digest, &crid))
559 		goto out;
560 	if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
561 		if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
562 			printf("%s (%zu) mismatch in trailer:\n",
563 			    alg->name, size);
564 		else
565 			printf("%s (%zu) mismatch:\n", alg->name, size);
566 		printf("control:\n");
567 		hexdump(control_digest, sizeof(control_digest), NULL, 0);
568 		printf("test (cryptodev device %s):\n", crfind(crid));
569 		hexdump(test_digest, sizeof(test_digest), NULL, 0);
570 		goto out;
571 	}
572 
573 	if (verbose)
574 		printf("%s (%zu) matched (cryptodev device %s)\n",
575 		    alg->name, size, crfind(crid));
576 
577 out:
578 	free(buffer);
579 	free(key);
580 }
581 
582 static void
583 openssl_cipher(struct alg *alg, const EVP_CIPHER *cipher, const char *key,
584     const char *iv, const char *input, char *output, size_t size, int enc)
585 {
586 	EVP_CIPHER_CTX *ctx;
587 	int outl, total;
588 
589 	ctx = EVP_CIPHER_CTX_new();
590 	if (ctx == NULL)
591 		errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
592 		    size, ERR_error_string(ERR_get_error(), NULL));
593 	if (EVP_CipherInit_ex(ctx, cipher, NULL, (const u_char *)key,
594 	    (const u_char *)iv, enc) != 1)
595 		errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
596 		    size, ERR_error_string(ERR_get_error(), NULL));
597 	EVP_CIPHER_CTX_set_padding(ctx, 0);
598 	if (EVP_CipherUpdate(ctx, (u_char *)output, &outl,
599 	    (const u_char *)input, size) != 1)
600 		errx(1, "OpenSSL %s (%zu) cipher update failed: %s", alg->name,
601 		    size, ERR_error_string(ERR_get_error(), NULL));
602 	total = outl;
603 	if (EVP_CipherFinal_ex(ctx, (u_char *)output + outl, &outl) != 1)
604 		errx(1, "OpenSSL %s (%zu) cipher final failed: %s", alg->name,
605 		    size, ERR_error_string(ERR_get_error(), NULL));
606 	total += outl;
607 	if (total != size)
608 		errx(1, "OpenSSL %s (%zu) cipher size mismatch: %d", alg->name,
609 		    size, total);
610 	EVP_CIPHER_CTX_free(ctx);
611 }
612 
613 static bool
614 ocf_cipher(struct alg *alg, const char *key, size_t key_len,
615     const char *iv, const char *input, char *output, size_t size, int enc,
616     int *cridp)
617 {
618 	struct session2_op sop;
619 	struct crypt_op cop;
620 	int fd;
621 
622 	memset(&sop, 0, sizeof(sop));
623 	memset(&cop, 0, sizeof(cop));
624 	sop.crid = crid;
625 	sop.keylen = key_len;
626 	sop.key = (char *)key;
627 	sop.cipher = alg->cipher;
628 	fd = crget();
629 	if (ioctl(fd, CIOCGSESSION2, &sop) < 0) {
630 		warn("cryptodev %s block cipher not supported for device %s",
631 		    alg->name, crfind(crid));
632 		close(fd);
633 		return (false);
634 	}
635 
636 	cop.ses = sop.ses;
637 	cop.op = enc ? COP_ENCRYPT : COP_DECRYPT;
638 	cop.len = size;
639 	cop.src = (char *)input;
640 	cop.dst = output;
641 	cop.mac = NULL;
642 	cop.iv = (char *)iv;
643 
644 	if (ioctl(fd, CIOCCRYPT, &cop) < 0) {
645 		warn("cryptodev %s (%zu) block cipher failed for device %s",
646 		    alg->name, size, crfind(crid));
647 		close(fd);
648 		return (false);
649 	}
650 
651 	if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0)
652 		warn("ioctl(CIOCFSESSION)");
653 
654 	close(fd);
655 	*cridp = sop.crid;
656 	return (true);
657 }
658 
659 static void
660 run_blkcipher_test(struct alg *alg, size_t size)
661 {
662 	const EVP_CIPHER *cipher;
663 	char *buffer, *cleartext, *ciphertext;
664 	char *iv, *key;
665 	u_int iv_len, key_len;
666 	int crid;
667 
668 	cipher = alg->evp_cipher();
669 	if (size % EVP_CIPHER_block_size(cipher) != 0) {
670 		if (verbose)
671 			printf(
672 			    "%s (%zu): invalid buffer size (block size %d)\n",
673 			    alg->name, size, EVP_CIPHER_block_size(cipher));
674 		return;
675 	}
676 
677 	key_len = EVP_CIPHER_key_length(cipher);
678 	iv_len = EVP_CIPHER_iv_length(cipher);
679 
680 	key = alloc_buffer(key_len);
681 	iv = generate_iv(iv_len, alg);
682 	cleartext = alloc_buffer(size);
683 	buffer = malloc(size);
684 	ciphertext = malloc(size);
685 
686 	/* OpenSSL cipher. */
687 	openssl_cipher(alg, cipher, key, iv, cleartext, ciphertext, size, 1);
688 	if (size > 0 && memcmp(cleartext, ciphertext, size) == 0)
689 		errx(1, "OpenSSL %s (%zu): cipher text unchanged", alg->name,
690 		    size);
691 	openssl_cipher(alg, cipher, key, iv, ciphertext, buffer, size, 0);
692 	if (memcmp(cleartext, buffer, size) != 0) {
693 		printf("OpenSSL %s (%zu): cipher mismatch:", alg->name, size);
694 		printf("original:\n");
695 		hexdump(cleartext, size, NULL, 0);
696 		printf("decrypted:\n");
697 		hexdump(buffer, size, NULL, 0);
698 		exit(1);
699 	}
700 
701 	/* OCF encrypt. */
702 	if (!ocf_cipher(alg, key, key_len, iv, cleartext, buffer, size, 1,
703 	    &crid))
704 		goto out;
705 	if (memcmp(ciphertext, buffer, size) != 0) {
706 		printf("%s (%zu) encryption mismatch:\n", alg->name, size);
707 		printf("control:\n");
708 		hexdump(ciphertext, size, NULL, 0);
709 		printf("test (cryptodev device %s):\n", crfind(crid));
710 		hexdump(buffer, size, NULL, 0);
711 		goto out;
712 	}
713 
714 	/* OCF decrypt. */
715 	if (!ocf_cipher(alg, key, key_len, iv, ciphertext, buffer, size, 0,
716 	    &crid))
717 		goto out;
718 	if (memcmp(cleartext, buffer, size) != 0) {
719 		printf("%s (%zu) decryption mismatch:\n", alg->name, size);
720 		printf("control:\n");
721 		hexdump(cleartext, size, NULL, 0);
722 		printf("test (cryptodev device %s):\n", crfind(crid));
723 		hexdump(buffer, size, NULL, 0);
724 		goto out;
725 	}
726 
727 	if (verbose)
728 		printf("%s (%zu) matched (cryptodev device %s)\n",
729 		    alg->name, size, crfind(crid));
730 
731 out:
732 	free(ciphertext);
733 	free(buffer);
734 	free(cleartext);
735 	free(iv);
736 	free(key);
737 }
738 
739 static bool
740 ocf_authenc(struct alg *alg, const char *cipher_key, size_t cipher_key_len,
741     const char *iv, size_t iv_len, const char *auth_key, size_t auth_key_len,
742     const char *aad, size_t aad_len, const char *input, char *output,
743     size_t size, char *digest, int enc, int *cridp)
744 {
745 	struct session2_op sop;
746 	int fd;
747 
748 	memset(&sop, 0, sizeof(sop));
749 	sop.crid = crid;
750 	sop.keylen = cipher_key_len;
751 	sop.key = (char *)cipher_key;
752 	sop.cipher = alg->cipher;
753 	sop.mackeylen = auth_key_len;
754 	sop.mackey = (char *)auth_key;
755 	sop.mac = alg->mac;
756 	fd = crget();
757 	if (ioctl(fd, CIOCGSESSION2, &sop) < 0) {
758 		warn("cryptodev %s AUTHENC not supported for device %s",
759 		    alg->name, crfind(crid));
760 		close(fd);
761 		return (false);
762 	}
763 
764 	if (aad_len != 0) {
765 		struct crypt_aead caead;
766 
767 		memset(&caead, 0, sizeof(caead));
768 		caead.ses = sop.ses;
769 		caead.op = enc ? COP_ENCRYPT : COP_DECRYPT;
770 		caead.flags = enc ? COP_F_CIPHER_FIRST : 0;
771 		caead.len = size;
772 		caead.aadlen = aad_len;
773 		caead.ivlen = iv_len;
774 		caead.src = (char *)input;
775 		caead.dst = output;
776 		caead.aad = (char *)aad;
777 		caead.tag = digest;
778 		caead.iv = (char *)iv;
779 
780 		if (ioctl(fd, CIOCCRYPTAEAD, &caead) < 0) {
781 			warn("cryptodev %s (%zu) failed for device %s",
782 			    alg->name, size, crfind(crid));
783 			close(fd);
784 			return (false);
785 		}
786 	} else {
787 		struct crypt_op cop;
788 
789 		memset(&cop, 0, sizeof(cop));
790 		cop.ses = sop.ses;
791 		cop.op = enc ? COP_ENCRYPT : COP_DECRYPT;
792 		cop.flags = enc ? COP_F_CIPHER_FIRST : 0;
793 		cop.len = size;
794 		cop.src = (char *)input;
795 		cop.dst = output;
796 		cop.mac = digest;
797 		cop.iv = (char *)iv;
798 
799 		if (ioctl(fd, CIOCCRYPT, &cop) < 0) {
800 			warn("cryptodev %s (%zu) AUTHENC failed for device %s",
801 			    alg->name, size, crfind(crid));
802 			close(fd);
803 			return (false);
804 		}
805 	}
806 
807 	if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0)
808 		warn("ioctl(CIOCFSESSION)");
809 
810 	close(fd);
811 	*cridp = sop.crid;
812 	return (true);
813 }
814 
815 static void
816 run_authenc_test(struct alg *alg, size_t size)
817 {
818 	const EVP_CIPHER *cipher;
819 	const EVP_MD *md;
820 	char *aad, *buffer, *cleartext, *ciphertext;
821 	char *iv, *auth_key, *cipher_key;
822 	u_int iv_len, auth_key_len, cipher_key_len, digest_len;
823 	int crid;
824 	char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE];
825 
826 	cipher = alg->evp_cipher();
827 	if (size % EVP_CIPHER_block_size(cipher) != 0) {
828 		if (verbose)
829 			printf(
830 			    "%s (%zu): invalid buffer size (block size %d)\n",
831 			    alg->name, size, EVP_CIPHER_block_size(cipher));
832 		return;
833 	}
834 
835 	memset(control_digest, 0x3c, sizeof(control_digest));
836 	memset(test_digest, 0x3c, sizeof(test_digest));
837 
838 	md = alg->evp_md();
839 
840 	cipher_key_len = EVP_CIPHER_key_length(cipher);
841 	iv_len = EVP_CIPHER_iv_length(cipher);
842 	auth_key_len = EVP_MD_size(md);
843 
844 	cipher_key = alloc_buffer(cipher_key_len);
845 	iv = generate_iv(iv_len, alg);
846 	auth_key = alloc_buffer(auth_key_len);
847 	cleartext = alloc_buffer(aad_len + size);
848 	buffer = malloc(aad_len + size);
849 	ciphertext = malloc(aad_len + size);
850 
851 	/* OpenSSL encrypt + HMAC. */
852 	if (aad_len != 0)
853 		memcpy(ciphertext, cleartext, aad_len);
854 	openssl_cipher(alg, cipher, cipher_key, iv, cleartext + aad_len,
855 	    ciphertext + aad_len, size, 1);
856 	if (size > 0 && memcmp(cleartext + aad_len, ciphertext + aad_len,
857 	    size) == 0)
858 		errx(1, "OpenSSL %s (%zu): cipher text unchanged", alg->name,
859 		    size);
860 	digest_len = sizeof(control_digest);
861 	if (HMAC(md, auth_key, auth_key_len, (u_char *)ciphertext,
862 	    aad_len + size, (u_char *)control_digest, &digest_len) == NULL)
863 		errx(1, "OpenSSL %s (%zu) HMAC failed: %s", alg->name,
864 		    size, ERR_error_string(ERR_get_error(), NULL));
865 
866 	/* OCF encrypt + HMAC. */
867 	if (!ocf_authenc(alg, cipher_key, cipher_key_len, iv, iv_len, auth_key,
868 	    auth_key_len, aad_len != 0 ? cleartext : NULL, aad_len,
869 	    cleartext + aad_len, buffer + aad_len, size, test_digest, 1, &crid))
870 		goto out;
871 	if (memcmp(ciphertext + aad_len, buffer + aad_len, size) != 0) {
872 		printf("%s (%zu) encryption mismatch:\n", alg->name, size);
873 		printf("control:\n");
874 		hexdump(ciphertext + aad_len, size, NULL, 0);
875 		printf("test (cryptodev device %s):\n", crfind(crid));
876 		hexdump(buffer + aad_len, size, NULL, 0);
877 		goto out;
878 	}
879 	if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
880 		if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
881 			printf("%s (%zu) enc hash mismatch in trailer:\n",
882 			    alg->name, size);
883 		else
884 			printf("%s (%zu) enc hash mismatch:\n", alg->name,
885 			    size);
886 		printf("control:\n");
887 		hexdump(control_digest, sizeof(control_digest), NULL, 0);
888 		printf("test (cryptodev device %s):\n", crfind(crid));
889 		hexdump(test_digest, sizeof(test_digest), NULL, 0);
890 		goto out;
891 	}
892 
893 	/* OCF HMAC + decrypt. */
894 	memset(test_digest, 0x3c, sizeof(test_digest));
895 	if (!ocf_authenc(alg, cipher_key, cipher_key_len, iv, iv_len, auth_key,
896 	    auth_key_len, aad_len != 0 ? ciphertext : NULL, aad_len,
897 	    ciphertext + aad_len, buffer + aad_len, size, test_digest, 0,
898 	    &crid))
899 		goto out;
900 	if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
901 		if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
902 			printf("%s (%zu) dec hash mismatch in trailer:\n",
903 			    alg->name, size);
904 		else
905 			printf("%s (%zu) dec hash mismatch:\n", alg->name,
906 			    size);
907 		printf("control:\n");
908 		hexdump(control_digest, sizeof(control_digest), NULL, 0);
909 		printf("test (cryptodev device %s):\n", crfind(crid));
910 		hexdump(test_digest, sizeof(test_digest), NULL, 0);
911 		goto out;
912 	}
913 	if (memcmp(cleartext + aad_len, buffer + aad_len, size) != 0) {
914 		printf("%s (%zu) decryption mismatch:\n", alg->name, size);
915 		printf("control:\n");
916 		hexdump(cleartext, size, NULL, 0);
917 		printf("test (cryptodev device %s):\n", crfind(crid));
918 		hexdump(buffer, size, NULL, 0);
919 		goto out;
920 	}
921 
922 	if (verbose)
923 		printf("%s (%zu) matched (cryptodev device %s)\n",
924 		    alg->name, size, crfind(crid));
925 
926 out:
927 	free(ciphertext);
928 	free(buffer);
929 	free(cleartext);
930 	free(auth_key);
931 	free(iv);
932 	free(cipher_key);
933 }
934 
935 static void
936 openssl_gcm_encrypt(struct alg *alg, const EVP_CIPHER *cipher, const char *key,
937     const char *iv, const char *aad, size_t aad_len, const char *input,
938     char *output, size_t size, char *tag)
939 {
940 	EVP_CIPHER_CTX *ctx;
941 	int outl, total;
942 
943 	ctx = EVP_CIPHER_CTX_new();
944 	if (ctx == NULL)
945 		errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
946 		    size, ERR_error_string(ERR_get_error(), NULL));
947 	if (EVP_EncryptInit_ex(ctx, cipher, NULL, (const u_char *)key,
948 	    (const u_char *)iv) != 1)
949 		errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
950 		    size, ERR_error_string(ERR_get_error(), NULL));
951 	EVP_CIPHER_CTX_set_padding(ctx, 0);
952 	if (aad != NULL) {
953 		if (EVP_EncryptUpdate(ctx, NULL, &outl, (const u_char *)aad,
954 		    aad_len) != 1)
955 			errx(1, "OpenSSL %s (%zu) aad update failed: %s",
956 			    alg->name, size,
957 			    ERR_error_string(ERR_get_error(), NULL));
958 	}
959 	if (EVP_EncryptUpdate(ctx, (u_char *)output, &outl,
960 	    (const u_char *)input, size) != 1)
961 		errx(1, "OpenSSL %s (%zu) encrypt update failed: %s", alg->name,
962 		    size, ERR_error_string(ERR_get_error(), NULL));
963 	total = outl;
964 	if (EVP_EncryptFinal_ex(ctx, (u_char *)output + outl, &outl) != 1)
965 		errx(1, "OpenSSL %s (%zu) encrypt final failed: %s", alg->name,
966 		    size, ERR_error_string(ERR_get_error(), NULL));
967 	total += outl;
968 	if (total != size)
969 		errx(1, "OpenSSL %s (%zu) encrypt size mismatch: %d", alg->name,
970 		    size, total);
971 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, AES_GMAC_HASH_LEN,
972 	    tag) != 1)
973 		errx(1, "OpenSSL %s (%zu) get tag failed: %s", alg->name,
974 		    size, ERR_error_string(ERR_get_error(), NULL));
975 	EVP_CIPHER_CTX_free(ctx);
976 }
977 
978 static bool
979 ocf_gcm(struct alg *alg, const char *key, size_t key_len, const char *iv,
980     size_t iv_len, const char *aad, size_t aad_len, const char *input,
981     char *output, size_t size, char *tag, int enc, int *cridp)
982 {
983 	struct session2_op sop;
984 	struct crypt_aead caead;
985 	int fd;
986 
987 	memset(&sop, 0, sizeof(sop));
988 	memset(&caead, 0, sizeof(caead));
989 	sop.crid = crid;
990 	sop.keylen = key_len;
991 	sop.key = (char *)key;
992 	sop.cipher = alg->cipher;
993 	sop.mackeylen = key_len;
994 	sop.mackey = (char *)key;
995 	sop.mac = alg->mac;
996 	fd = crget();
997 	if (ioctl(fd, CIOCGSESSION2, &sop) < 0) {
998 		warn("cryptodev %s not supported for device %s",
999 		    alg->name, crfind(crid));
1000 		close(fd);
1001 		return (false);
1002 	}
1003 
1004 	caead.ses = sop.ses;
1005 	caead.op = enc ? COP_ENCRYPT : COP_DECRYPT;
1006 	caead.len = size;
1007 	caead.aadlen = aad_len;
1008 	caead.ivlen = iv_len;
1009 	caead.src = (char *)input;
1010 	caead.dst = output;
1011 	caead.aad = (char *)aad;
1012 	caead.tag = tag;
1013 	caead.iv = (char *)iv;
1014 
1015 	if (ioctl(fd, CIOCCRYPTAEAD, &caead) < 0) {
1016 		warn("cryptodev %s (%zu) failed for device %s",
1017 		    alg->name, size, crfind(crid));
1018 		close(fd);
1019 		return (false);
1020 	}
1021 
1022 	if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0)
1023 		warn("ioctl(CIOCFSESSION)");
1024 
1025 	close(fd);
1026 	*cridp = sop.crid;
1027 	return (true);
1028 }
1029 
1030 #ifdef notused
1031 static bool
1032 openssl_gcm_decrypt(struct alg *alg, const EVP_CIPHER *cipher, const char *key,
1033     const char *iv, const char *aad, size_t aad_len, const char *input,
1034     char *output, size_t size, char *tag)
1035 {
1036 	EVP_CIPHER_CTX *ctx;
1037 	int outl, total;
1038 	bool valid;
1039 
1040 	ctx = EVP_CIPHER_CTX_new();
1041 	if (ctx == NULL)
1042 		errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
1043 		    size, ERR_error_string(ERR_get_error(), NULL));
1044 	if (EVP_DecryptInit_ex(ctx, cipher, NULL, (const u_char *)key,
1045 	    (const u_char *)iv) != 1)
1046 		errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
1047 		    size, ERR_error_string(ERR_get_error(), NULL));
1048 	EVP_CIPHER_CTX_set_padding(ctx, 0);
1049 	if (aad != NULL) {
1050 		if (EVP_DecryptUpdate(ctx, NULL, &outl, (const u_char *)aad,
1051 		    aad_len) != 1)
1052 			errx(1, "OpenSSL %s (%zu) aad update failed: %s",
1053 			    alg->name, size,
1054 			    ERR_error_string(ERR_get_error(), NULL));
1055 	}
1056 	if (EVP_DecryptUpdate(ctx, (u_char *)output, &outl,
1057 	    (const u_char *)input, size) != 1)
1058 		errx(1, "OpenSSL %s (%zu) decrypt update failed: %s", alg->name,
1059 		    size, ERR_error_string(ERR_get_error(), NULL));
1060 	total = outl;
1061 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AES_GMAC_HASH_LEN,
1062 	    tag) != 1)
1063 		errx(1, "OpenSSL %s (%zu) get tag failed: %s", alg->name,
1064 		    size, ERR_error_string(ERR_get_error(), NULL));
1065 	valid = (EVP_DecryptFinal_ex(ctx, (u_char *)output + outl, &outl) != 1);
1066 	total += outl;
1067 	if (total != size)
1068 		errx(1, "OpenSSL %s (%zu) decrypt size mismatch: %d", alg->name,
1069 		    size, total);
1070 	EVP_CIPHER_CTX_free(ctx);
1071 	return (valid);
1072 }
1073 #endif
1074 
1075 static void
1076 run_gcm_test(struct alg *alg, size_t size)
1077 {
1078 	const EVP_CIPHER *cipher;
1079 	char *aad, *buffer, *cleartext, *ciphertext;
1080 	char *iv, *key;
1081 	u_int iv_len, key_len;
1082 	int crid;
1083 	char control_tag[AES_GMAC_HASH_LEN], test_tag[AES_GMAC_HASH_LEN];
1084 
1085 	cipher = alg->evp_cipher();
1086 	if (size % EVP_CIPHER_block_size(cipher) != 0) {
1087 		if (verbose)
1088 			printf(
1089 			    "%s (%zu): invalid buffer size (block size %d)\n",
1090 			    alg->name, size, EVP_CIPHER_block_size(cipher));
1091 		return;
1092 	}
1093 
1094 	memset(control_tag, 0x3c, sizeof(control_tag));
1095 	memset(test_tag, 0x3c, sizeof(test_tag));
1096 
1097 	key_len = EVP_CIPHER_key_length(cipher);
1098 	iv_len = EVP_CIPHER_iv_length(cipher);
1099 
1100 	key = alloc_buffer(key_len);
1101 	iv = generate_iv(iv_len, alg);
1102 	cleartext = alloc_buffer(size);
1103 	buffer = malloc(size);
1104 	ciphertext = malloc(size);
1105 	if (aad_len != 0)
1106 		aad = alloc_buffer(aad_len);
1107 	else
1108 		aad = NULL;
1109 
1110 	/* OpenSSL encrypt */
1111 	openssl_gcm_encrypt(alg, cipher, key, iv, aad, aad_len, cleartext,
1112 	    ciphertext, size, control_tag);
1113 
1114 	/* OCF encrypt */
1115 	if (!ocf_gcm(alg, key, key_len, iv, iv_len, aad, aad_len, cleartext,
1116 	    buffer, size, test_tag, 1, &crid))
1117 		goto out;
1118 	if (memcmp(ciphertext, buffer, size) != 0) {
1119 		printf("%s (%zu) encryption mismatch:\n", alg->name, size);
1120 		printf("control:\n");
1121 		hexdump(ciphertext, size, NULL, 0);
1122 		printf("test (cryptodev device %s):\n", crfind(crid));
1123 		hexdump(buffer, size, NULL, 0);
1124 		goto out;
1125 	}
1126 	if (memcmp(control_tag, test_tag, sizeof(control_tag)) != 0) {
1127 		printf("%s (%zu) enc tag mismatch:\n", alg->name, size);
1128 		printf("control:\n");
1129 		hexdump(control_tag, sizeof(control_tag), NULL, 0);
1130 		printf("test (cryptodev device %s):\n", crfind(crid));
1131 		hexdump(test_tag, sizeof(test_tag), NULL, 0);
1132 		goto out;
1133 	}
1134 
1135 	/* OCF decrypt */
1136 	if (!ocf_gcm(alg, key, key_len, iv, iv_len, aad, aad_len, ciphertext,
1137 	    buffer, size, control_tag, 0, &crid))
1138 		goto out;
1139 	if (memcmp(cleartext, buffer, size) != 0) {
1140 		printf("%s (%zu) decryption mismatch:\n", alg->name, size);
1141 		printf("control:\n");
1142 		hexdump(cleartext, size, NULL, 0);
1143 		printf("test (cryptodev device %s):\n", crfind(crid));
1144 		hexdump(buffer, size, NULL, 0);
1145 		goto out;
1146 	}
1147 
1148 	if (verbose)
1149 		printf("%s (%zu) matched (cryptodev device %s)\n",
1150 		    alg->name, size, crfind(crid));
1151 
1152 out:
1153 	free(aad);
1154 	free(ciphertext);
1155 	free(buffer);
1156 	free(cleartext);
1157 	free(iv);
1158 	free(key);
1159 }
1160 
1161 static void
1162 run_test(struct alg *alg, size_t size)
1163 {
1164 
1165 	switch (alg->type) {
1166 	case T_HASH:
1167 		run_hash_test(alg, size);
1168 		break;
1169 	case T_HMAC:
1170 		run_hmac_test(alg, size);
1171 		break;
1172 	case T_BLKCIPHER:
1173 		run_blkcipher_test(alg, size);
1174 		break;
1175 	case T_AUTHENC:
1176 		run_authenc_test(alg, size);
1177 		break;
1178 	case T_GCM:
1179 		run_gcm_test(alg, size);
1180 		break;
1181 	}
1182 }
1183 
1184 static void
1185 run_test_sizes(struct alg *alg, size_t *sizes, u_int nsizes)
1186 {
1187 	u_int i;
1188 
1189 	for (i = 0; i < nsizes; i++)
1190 		run_test(alg, sizes[i]);
1191 }
1192 
1193 static void
1194 run_hash_tests(size_t *sizes, u_int nsizes)
1195 {
1196 	u_int i;
1197 
1198 	for (i = 0; i < nitems(algs); i++)
1199 		if (algs[i].type == T_HASH)
1200 			run_test_sizes(&algs[i], sizes, nsizes);
1201 }
1202 
1203 static void
1204 run_hmac_tests(size_t *sizes, u_int nsizes)
1205 {
1206 	u_int i;
1207 
1208 	for (i = 0; i < nitems(algs); i++)
1209 		if (algs[i].type == T_HMAC)
1210 			run_test_sizes(&algs[i], sizes, nsizes);
1211 }
1212 
1213 static void
1214 run_blkcipher_tests(size_t *sizes, u_int nsizes)
1215 {
1216 	u_int i;
1217 
1218 	for (i = 0; i < nitems(algs); i++)
1219 		if (algs[i].type == T_BLKCIPHER)
1220 			run_test_sizes(&algs[i], sizes, nsizes);
1221 }
1222 
1223 static void
1224 run_authenc_tests(size_t *sizes, u_int nsizes)
1225 {
1226 	struct alg *authenc, *cipher, *hmac;
1227 	u_int i, j;
1228 
1229 	for (i = 0; i < nitems(algs); i++) {
1230 		cipher = &algs[i];
1231 		if (cipher->type != T_BLKCIPHER)
1232 			continue;
1233 		for (j = 0; j < nitems(algs); j++) {
1234 			hmac = &algs[j];
1235 			if (hmac->type != T_HMAC)
1236 				continue;
1237 			authenc = build_authenc(cipher, hmac);
1238 			run_test_sizes(authenc, sizes, nsizes);
1239 			free((char *)authenc->name);
1240 		}
1241 	}
1242 }
1243 
1244 static void
1245 run_aead_tests(size_t *sizes, u_int nsizes)
1246 {
1247 	u_int i;
1248 
1249 	for (i = 0; i < nitems(algs); i++)
1250 		if (algs[i].type == T_GCM)
1251 			run_test_sizes(&algs[i], sizes, nsizes);
1252 }
1253 
1254 int
1255 main(int ac, char **av)
1256 {
1257 	const char *algname;
1258 	struct alg *alg;
1259 	size_t sizes[128];
1260 	u_int i, nsizes;
1261 	bool testall;
1262 	int ch;
1263 
1264 	algname = NULL;
1265 	crid = CRYPTO_FLAG_HARDWARE;
1266 	testall = false;
1267 	verbose = false;
1268 	while ((ch = getopt(ac, av, "A:a:d:vz")) != -1)
1269 		switch (ch) {
1270 		case 'A':
1271 			aad_len = atoi(optarg);
1272 			break;
1273 		case 'a':
1274 			algname = optarg;
1275 			break;
1276 		case 'd':
1277 			crid = crlookup(optarg);
1278 			break;
1279 		case 'v':
1280 			verbose = true;
1281 			break;
1282 		case 'z':
1283 			testall = true;
1284 			break;
1285 		default:
1286 			usage();
1287 		}
1288 	ac -= optind;
1289 	av += optind;
1290 	nsizes = 0;
1291 	while (ac > 0) {
1292 		char *cp;
1293 
1294 		if (nsizes >= nitems(sizes)) {
1295 			warnx("Too many sizes, ignoring extras");
1296 			break;
1297 		}
1298 		sizes[nsizes] = strtol(av[0], &cp, 0);
1299 		if (*cp != '\0')
1300 			errx(1, "Bad size %s", av[0]);
1301 		nsizes++;
1302 		ac--;
1303 		av++;
1304 	}
1305 
1306 	if (algname == NULL)
1307 		errx(1, "Algorithm required");
1308 	if (nsizes == 0) {
1309 		sizes[0] = 16;
1310 		nsizes++;
1311 		if (testall) {
1312 			while (sizes[nsizes - 1] * 2 < 240 * 1024) {
1313 				assert(nsizes < nitems(sizes));
1314 				sizes[nsizes] = sizes[nsizes - 1] * 2;
1315 				nsizes++;
1316 			}
1317 			if (sizes[nsizes - 1] < 240 * 1024) {
1318 				assert(nsizes < nitems(sizes));
1319 				sizes[nsizes] = 240 * 1024;
1320 				nsizes++;
1321 			}
1322 		}
1323 	}
1324 
1325 	if (strcasecmp(algname, "hash") == 0)
1326 		run_hash_tests(sizes, nsizes);
1327 	else if (strcasecmp(algname, "hmac") == 0)
1328 		run_hmac_tests(sizes, nsizes);
1329 	else if (strcasecmp(algname, "blkcipher") == 0)
1330 		run_blkcipher_tests(sizes, nsizes);
1331 	else if (strcasecmp(algname, "authenc") == 0)
1332 		run_authenc_tests(sizes, nsizes);
1333 	else if (strcasecmp(algname, "aead") == 0)
1334 		run_aead_tests(sizes, nsizes);
1335 	else if (strcasecmp(algname, "all") == 0) {
1336 		run_hash_tests(sizes, nsizes);
1337 		run_hmac_tests(sizes, nsizes);
1338 		run_blkcipher_tests(sizes, nsizes);
1339 		run_authenc_tests(sizes, nsizes);
1340 		run_aead_tests(sizes, nsizes);
1341 	} else if (strchr(algname, '+') != NULL) {
1342 		alg = build_authenc_name(algname);
1343 		run_test_sizes(alg, sizes, nsizes);
1344 	} else {
1345 		alg = find_alg(algname);
1346 		if (alg == NULL)
1347 			errx(1, "Invalid algorithm %s", algname);
1348 		run_test_sizes(alg, sizes, nsizes);
1349 	}
1350 
1351 	return (0);
1352 }
1353