xref: /freebsd/tools/tools/crypto/cryptocheck.c (revision c697fb7f)
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  *	hash		Run all hash tests
77  *	mac		Run all mac tests
78  *	cipher		Run all cipher tests
79  *	eta		Run all encrypt-then-authenticate tests
80  *	aead		Run all authenticated encryption with associated data
81  *			tests
82  *
83  * Hashes:
84  *	sha1		SHA-1
85  *	sha224		224-bit SHA-2
86  *	sha256		256-bit SHA-2
87  *	sha384		384-bit SHA-2
88  *	sha512		512-bit	SHA-2
89  *	blake2b		Blake2-B
90  *	blake2s		Blake2-S
91  *
92  * MACs:
93  *	sha1hmac	SHA-1 HMAC
94  *	sha224hmac	224-bit SHA-2 HMAC
95  *	sha256hmac	256-bit SHA-2 HMAC
96  *	sha384hmac	384-bit SHA-2 HMAC
97  *	sha512hmac	512-bit	SHA-2 HMAC
98  *
99  * Ciphers:
100  *	aes-cbc		128-bit AES-CBC
101  *	aes-cbc192	192-bit	AES-CBC
102  *	aes-cbc256	256-bit AES-CBC
103  *	aes-ctr		128-bit AES-CTR
104  *	aes-ctr192	192-bit AES-CTR
105  *	aes-ctr256	256-bit AES-CTR
106  *	aes-xts		128-bit AES-XTS
107  *	aes-xts256	256-bit AES-XTS
108  *	chacha20
109  *
110  * Encrypt then Authenticate:
111  *	<cipher>+<mac>
112  *
113  * Authenticated Encryption with Associated Data:
114  *	aes-gcm		128-bit AES-GCM
115  *	aes-gcm192	192-bit AES-GCM
116  *	aes-gcm256	256-bit AES-GCM
117  *	aes-ccm		128-bit AES-CCM
118  *	aes-ccm192	192-bit AES-CCM
119  *	aes-ccm256	256-bit AES-CCM
120  */
121 
122 #include <sys/param.h>
123 #include <sys/sysctl.h>
124 #include <assert.h>
125 #include <err.h>
126 #include <fcntl.h>
127 #include <libutil.h>
128 #include <stdbool.h>
129 #include <stdio.h>
130 #include <string.h>
131 #include <unistd.h>
132 
133 #include <openssl/err.h>
134 #include <openssl/hmac.h>
135 
136 #include <crypto/cryptodev.h>
137 
138 struct ocf_session {
139 	int fd;
140 	int ses;
141 	int crid;
142 };
143 
144 const struct alg {
145 	const char *name;
146 	int cipher;
147 	int mac;
148 	enum { T_HASH, T_HMAC, T_CIPHER, T_ETA, T_AEAD } type;
149 	const EVP_CIPHER *(*evp_cipher)(void);
150 	const EVP_MD *(*evp_md)(void);
151 } algs[] = {
152 	{ .name = "sha1", .mac = CRYPTO_SHA1, .type = T_HASH,
153 	  .evp_md = EVP_sha1 },
154 	{ .name = "sha224", .mac = CRYPTO_SHA2_224, .type = T_HASH,
155 	  .evp_md = EVP_sha224 },
156 	{ .name = "sha256", .mac = CRYPTO_SHA2_256, .type = T_HASH,
157 	  .evp_md = EVP_sha256 },
158 	{ .name = "sha384", .mac = CRYPTO_SHA2_384, .type = T_HASH,
159 	  .evp_md = EVP_sha384 },
160 	{ .name = "sha512", .mac = CRYPTO_SHA2_512, .type = T_HASH,
161 	  .evp_md = EVP_sha512 },
162 	{ .name = "sha1hmac", .mac = CRYPTO_SHA1_HMAC, .type = T_HMAC,
163 	  .evp_md = EVP_sha1 },
164 	{ .name = "sha224hmac", .mac = CRYPTO_SHA2_224_HMAC, .type = T_HMAC,
165 	  .evp_md = EVP_sha224 },
166 	{ .name = "sha256hmac", .mac = CRYPTO_SHA2_256_HMAC, .type = T_HMAC,
167 	  .evp_md = EVP_sha256 },
168 	{ .name = "sha384hmac", .mac = CRYPTO_SHA2_384_HMAC, .type = T_HMAC,
169 	  .evp_md = EVP_sha384 },
170 	{ .name = "sha512hmac", .mac = CRYPTO_SHA2_512_HMAC, .type = T_HMAC,
171 	  .evp_md = EVP_sha512 },
172 	{ .name = "blake2b", .mac = CRYPTO_BLAKE2B, .type = T_HASH,
173 	  .evp_md = EVP_blake2b512 },
174 	{ .name = "blake2s", .mac = CRYPTO_BLAKE2S, .type = T_HASH,
175 	  .evp_md = EVP_blake2s256 },
176 	{ .name = "aes-cbc", .cipher = CRYPTO_AES_CBC, .type = T_CIPHER,
177 	  .evp_cipher = EVP_aes_128_cbc },
178 	{ .name = "aes-cbc192", .cipher = CRYPTO_AES_CBC, .type = T_CIPHER,
179 	  .evp_cipher = EVP_aes_192_cbc },
180 	{ .name = "aes-cbc256", .cipher = CRYPTO_AES_CBC, .type = T_CIPHER,
181 	  .evp_cipher = EVP_aes_256_cbc },
182 	{ .name = "aes-ctr", .cipher = CRYPTO_AES_ICM, .type = T_CIPHER,
183 	  .evp_cipher = EVP_aes_128_ctr },
184 	{ .name = "aes-ctr192", .cipher = CRYPTO_AES_ICM, .type = T_CIPHER,
185 	  .evp_cipher = EVP_aes_192_ctr },
186 	{ .name = "aes-ctr256", .cipher = CRYPTO_AES_ICM, .type = T_CIPHER,
187 	  .evp_cipher = EVP_aes_256_ctr },
188 	{ .name = "aes-xts", .cipher = CRYPTO_AES_XTS, .type = T_CIPHER,
189 	  .evp_cipher = EVP_aes_128_xts },
190 	{ .name = "aes-xts256", .cipher = CRYPTO_AES_XTS, .type = T_CIPHER,
191 	  .evp_cipher = EVP_aes_256_xts },
192 	{ .name = "chacha20", .cipher = CRYPTO_CHACHA20, .type = T_CIPHER,
193 	  .evp_cipher = EVP_chacha20 },
194 	{ .name = "aes-gcm", .cipher = CRYPTO_AES_NIST_GCM_16,
195 	  .mac = CRYPTO_AES_128_NIST_GMAC, .type = T_AEAD,
196 	  .evp_cipher = EVP_aes_128_gcm },
197 	{ .name = "aes-gcm192", .cipher = CRYPTO_AES_NIST_GCM_16,
198 	  .mac = CRYPTO_AES_192_NIST_GMAC, .type = T_AEAD,
199 	  .evp_cipher = EVP_aes_192_gcm },
200 	{ .name = "aes-gcm256", .cipher = CRYPTO_AES_NIST_GCM_16,
201 	  .mac = CRYPTO_AES_256_NIST_GMAC, .type = T_AEAD,
202 	  .evp_cipher = EVP_aes_256_gcm },
203 	{ .name = "aes-ccm", .cipher = CRYPTO_AES_CCM_16,
204 	  .mac = CRYPTO_AES_CCM_CBC_MAC, .type = T_AEAD,
205 	  .evp_cipher = EVP_aes_128_ccm },
206 	{ .name = "aes-ccm192", .cipher = CRYPTO_AES_CCM_16,
207 	  .mac = CRYPTO_AES_CCM_CBC_MAC, .type = T_AEAD,
208 	  .evp_cipher = EVP_aes_192_ccm },
209 	{ .name = "aes-ccm256", .cipher = CRYPTO_AES_CCM_16,
210 	  .mac = CRYPTO_AES_CCM_CBC_MAC, .type = T_AEAD,
211 	  .evp_cipher = EVP_aes_256_ccm },
212 };
213 
214 static bool verbose;
215 static int crid;
216 static size_t aad_len;
217 
218 static void
219 usage(void)
220 {
221 	fprintf(stderr,
222 	    "usage: cryptocheck [-z] [-a algorithm] [-d dev] [size ...]\n");
223 	exit(1);
224 }
225 
226 static const struct alg *
227 find_alg(const char *name)
228 {
229 	u_int i;
230 
231 	for (i = 0; i < nitems(algs); i++)
232 		if (strcasecmp(algs[i].name, name) == 0)
233 			return (&algs[i]);
234 	return (NULL);
235 }
236 
237 static struct alg *
238 build_eta(const struct alg *cipher, const struct alg *mac)
239 {
240 	struct alg *eta;
241 	char *name;
242 
243 	assert(cipher->type == T_CIPHER);
244 	assert(mac->type == T_HMAC);
245 	eta = calloc(1, sizeof(*eta));
246 	asprintf(&name, "%s+%s", cipher->name, mac->name);
247 	eta->name = name;
248 	eta->cipher = cipher->cipher;
249 	eta->mac = mac->mac;
250 	eta->type = T_ETA;
251 	eta->evp_cipher = cipher->evp_cipher;
252 	eta->evp_md = mac->evp_md;
253 	return (eta);
254 }
255 
256 static void
257 free_eta(struct alg *eta)
258 {
259 	free(__DECONST(char *, eta->name));
260 	free(eta);
261 }
262 
263 static struct alg *
264 build_eta_name(const char *name)
265 {
266 	const struct alg *cipher, *mac;
267 	const char *mac_name;
268 	char *cp, *cipher_name;
269 
270 	cp = strchr(name, '+');
271 	cipher_name = strndup(name, cp - name);
272 	mac_name = cp + 1;
273 	cipher = find_alg(cipher_name);
274 	free(cipher_name);
275 	if (cipher == NULL || cipher->type != T_CIPHER)
276 		errx(1, "Invalid cipher %s", cipher_name);
277 	mac = find_alg(mac_name);
278 	if (mac == NULL || mac->type != T_HMAC)
279 		errx(1, "Invalid hmac %s", mac_name);
280 	return (build_eta(cipher, mac));
281 }
282 
283 static int
284 devcrypto(void)
285 {
286 	static int fd = -1;
287 
288 	if (fd < 0) {
289 		fd = open("/dev/crypto", O_RDWR | O_CLOEXEC, 0);
290 		if (fd < 0)
291 			err(1, "/dev/crypto");
292 	}
293 	return (fd);
294 }
295 
296 /*
297  * Called on exit to change kern.cryptodevallowsoft back to 0
298  */
299 #define CRYPT_SOFT_ALLOW	"kern.cryptodevallowsoft"
300 
301 static void
302 reset_user_soft(void)
303 {
304 	int off = 0;
305 	sysctlbyname(CRYPT_SOFT_ALLOW, NULL, NULL, &off, sizeof(off));
306 }
307 
308 static void
309 enable_user_soft(void)
310 {
311 	int curstate;
312 	int on = 1;
313 	size_t cursize = sizeof(curstate);
314 
315 	if (sysctlbyname(CRYPT_SOFT_ALLOW, &curstate, &cursize,
316 		&on, sizeof(on)) == 0) {
317 		if (curstate == 0)
318 			atexit(reset_user_soft);
319 	}
320 }
321 
322 static int
323 crlookup(const char *devname)
324 {
325 	struct crypt_find_op find;
326 
327 	if (strncmp(devname, "soft", 4) == 0) {
328 		enable_user_soft();
329 		return CRYPTO_FLAG_SOFTWARE;
330 	}
331 
332 	find.crid = -1;
333 	strlcpy(find.name, devname, sizeof(find.name));
334 	if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1)
335 		err(1, "ioctl(CIOCFINDDEV)");
336 	return (find.crid);
337 }
338 
339 const char *
340 crfind(int crid)
341 {
342 	static struct crypt_find_op find;
343 
344 	if (crid == CRYPTO_FLAG_SOFTWARE)
345 		return ("soft");
346 	else if (crid == CRYPTO_FLAG_HARDWARE)
347 		return ("unknown");
348 
349 	bzero(&find, sizeof(find));
350 	find.crid = crid;
351 	if (ioctl(devcrypto(), CRIOFINDDEV, &find) == -1)
352 		err(1, "ioctl(CIOCFINDDEV): crid %d", crid);
353 	return (find.name);
354 }
355 
356 static int
357 crget(void)
358 {
359 	int fd;
360 
361 	if (ioctl(devcrypto(), CRIOGET, &fd) == -1)
362 		err(1, "ioctl(CRIOGET)");
363 	if (fcntl(fd, F_SETFD, 1) == -1)
364 		err(1, "fcntl(F_SETFD) (crget)");
365 	return fd;
366 }
367 
368 static char
369 rdigit(void)
370 {
371 	const char a[] = {
372 		0x10,0x54,0x11,0x48,0x45,0x12,0x4f,0x13,0x49,0x53,0x14,0x41,
373 		0x15,0x16,0x4e,0x55,0x54,0x17,0x18,0x4a,0x4f,0x42,0x19,0x01
374 	};
375 	return 0x20+a[random()%nitems(a)];
376 }
377 
378 static char *
379 alloc_buffer(size_t len)
380 {
381 	char *buf;
382 	size_t i;
383 
384 	buf = malloc(len);
385 	for (i = 0; i < len; i++)
386 		buf[i] = rdigit();
387 	return (buf);
388 }
389 
390 static char *
391 generate_iv(size_t len, const struct alg *alg)
392 {
393 	char *iv;
394 
395 	iv = alloc_buffer(len);
396 	switch (alg->cipher) {
397 	case CRYPTO_AES_ICM:
398 		/* Clear the low 32 bits of the IV to hold the counter. */
399 		iv[len - 4] = 0;
400 		iv[len - 3] = 0;
401 		iv[len - 2] = 0;
402 		iv[len - 1] = 0;
403 		break;
404 	case CRYPTO_AES_XTS:
405 		/*
406 		 * Clear the low 64-bits to only store a 64-bit block
407 		 * number.
408 		 */
409 		iv[len - 8] = 0;
410 		iv[len - 7] = 0;
411 		iv[len - 6] = 0;
412 		iv[len - 5] = 0;
413 		iv[len - 4] = 0;
414 		iv[len - 3] = 0;
415 		iv[len - 2] = 0;
416 		iv[len - 1] = 0;
417 		break;
418 	}
419 	return (iv);
420 }
421 
422 static void
423 ocf_init_sop(struct session2_op *sop)
424 {
425 	memset(sop, 0, sizeof(*sop));
426 	sop->crid = crid;
427 }
428 
429 static bool
430 ocf_init_session(struct session2_op *sop, const char *type, const char *name,
431     struct ocf_session *ses)
432 {
433 	int fd;
434 
435 	fd = crget();
436 	if (ioctl(fd, CIOCGSESSION2, sop) < 0) {
437 		warn("cryptodev %s %s not supported for device %s",
438 		    type, name, crfind(crid));
439 		close(fd);
440 		ses->fd = -1;
441 		return (false);
442 	}
443 	ses->fd = fd;
444 	ses->ses = sop->ses;
445 	ses->crid = sop->crid;
446 	return (true);
447 }
448 
449 static void
450 ocf_destroy_session(struct ocf_session *ses)
451 {
452 	if (ses->fd == -1)
453 		return;
454 
455 	if (ioctl(ses->fd, CIOCFSESSION, &ses->ses) < 0)
456 		warn("ioctl(CIOCFSESSION)");
457 
458 	close(ses->fd);
459 }
460 
461 static void
462 ocf_init_cop(const struct ocf_session *ses, struct crypt_op *cop)
463 {
464 	memset(cop, 0, sizeof(*cop));
465 	cop->ses = ses->ses;
466 }
467 
468 static void
469 ocf_init_caead(const struct ocf_session *ses, struct crypt_aead *caead)
470 {
471 	memset(caead, 0, sizeof(*caead));
472 	caead->ses = ses->ses;
473 }
474 
475 static bool
476 ocf_hash(const struct alg *alg, const char *buffer, size_t size, char *digest,
477     int *cridp)
478 {
479 	struct ocf_session ses;
480 	struct session2_op sop;
481 	struct crypt_op cop;
482 	int error;
483 
484 	ocf_init_sop(&sop);
485 	sop.mac = alg->mac;
486 	if (!ocf_init_session(&sop, "HASH", alg->name, &ses))
487 		return (false);
488 
489 	ocf_init_cop(&ses, &cop);
490 	cop.op = 0;
491 	cop.len = size;
492 	cop.src = (char *)buffer;
493 	cop.mac = digest;
494 
495 	if (ioctl(ses.fd, CIOCCRYPT, &cop) < 0) {
496 		warn("cryptodev %s (%zu) HASH failed for device %s", alg->name,
497 		    size, crfind(crid));
498 		ocf_destroy_session(&ses);
499 		return (false);
500 	}
501 
502 	*cridp = ses.crid;
503 	ocf_destroy_session(&ses);
504 	return (true);
505 }
506 
507 static void
508 openssl_hash(const struct alg *alg, const EVP_MD *md, const void *buffer,
509     size_t size, void *digest_out, unsigned *digest_sz_out)
510 {
511 	EVP_MD_CTX *mdctx;
512 	const char *errs;
513 	int rc;
514 
515 	errs = "";
516 
517 	mdctx = EVP_MD_CTX_create();
518 	if (mdctx == NULL)
519 		goto err_out;
520 
521 	rc = EVP_DigestInit_ex(mdctx, md, NULL);
522 	if (rc != 1)
523 		goto err_out;
524 
525 	rc = EVP_DigestUpdate(mdctx, buffer, size);
526 	if (rc != 1)
527 		goto err_out;
528 
529 	rc = EVP_DigestFinal_ex(mdctx, digest_out, digest_sz_out);
530 	if (rc != 1)
531 		goto err_out;
532 
533 	EVP_MD_CTX_destroy(mdctx);
534 	return;
535 
536 err_out:
537 	errx(1, "OpenSSL %s HASH failed%s: %s", alg->name, errs,
538 	    ERR_error_string(ERR_get_error(), NULL));
539 }
540 
541 static void
542 run_hash_test(const struct alg *alg, size_t size)
543 {
544 	const EVP_MD *md;
545 	char *buffer;
546 	u_int digest_len;
547 	int crid;
548 	char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE];
549 
550 	memset(control_digest, 0x3c, sizeof(control_digest));
551 	memset(test_digest, 0x3c, sizeof(test_digest));
552 
553 	md = alg->evp_md();
554 	assert(EVP_MD_size(md) <= sizeof(control_digest));
555 
556 	buffer = alloc_buffer(size);
557 
558 	/* OpenSSL HASH. */
559 	digest_len = sizeof(control_digest);
560 	openssl_hash(alg, md, buffer, size, control_digest, &digest_len);
561 
562 	/* cryptodev HASH. */
563 	if (!ocf_hash(alg, buffer, size, test_digest, &crid))
564 		goto out;
565 	if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
566 		if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
567 			printf("%s (%zu) mismatch in trailer:\n",
568 			    alg->name, size);
569 		else
570 			printf("%s (%zu) mismatch:\n", alg->name, size);
571 		printf("control:\n");
572 		hexdump(control_digest, sizeof(control_digest), NULL, 0);
573 		printf("test (cryptodev device %s):\n", crfind(crid));
574 		hexdump(test_digest, sizeof(test_digest), NULL, 0);
575 		goto out;
576 	}
577 
578 	if (verbose)
579 		printf("%s (%zu) matched (cryptodev device %s)\n",
580 		    alg->name, size, crfind(crid));
581 
582 out:
583 	free(buffer);
584 }
585 
586 static bool
587 ocf_hmac(const struct alg *alg, const char *buffer, size_t size,
588     const char *key, size_t key_len, char *digest, int *cridp)
589 {
590 	struct ocf_session ses;
591 	struct session2_op sop;
592 	struct crypt_op cop;
593 
594 	ocf_init_sop(&sop);
595 	sop.mackeylen = key_len;
596 	sop.mackey = (char *)key;
597 	sop.mac = alg->mac;
598 	if (!ocf_init_session(&sop, "HMAC", alg->name, &ses))
599 		return (false);
600 
601 	ocf_init_cop(&ses, &cop);
602 	cop.op = 0;
603 	cop.len = size;
604 	cop.src = (char *)buffer;
605 	cop.mac = digest;
606 
607 	if (ioctl(ses.fd, CIOCCRYPT, &cop) < 0) {
608 		warn("cryptodev %s (%zu) HMAC failed for device %s", alg->name,
609 		    size, crfind(crid));
610 		ocf_destroy_session(&ses);
611 		return (false);
612 	}
613 
614 	*cridp = ses.crid;
615 	ocf_destroy_session(&ses);
616 	return (true);
617 }
618 
619 static void
620 run_hmac_test(const struct alg *alg, size_t size)
621 {
622 	const EVP_MD *md;
623 	char *key, *buffer;
624 	u_int key_len, digest_len;
625 	int crid;
626 	char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE];
627 
628 	memset(control_digest, 0x3c, sizeof(control_digest));
629 	memset(test_digest, 0x3c, sizeof(test_digest));
630 
631 	md = alg->evp_md();
632 	key_len = EVP_MD_size(md);
633 	assert(EVP_MD_size(md) <= sizeof(control_digest));
634 
635 	key = alloc_buffer(key_len);
636 	buffer = alloc_buffer(size);
637 
638 	/* OpenSSL HMAC. */
639 	digest_len = sizeof(control_digest);
640 	if (HMAC(md, key, key_len, (u_char *)buffer, size,
641 	    (u_char *)control_digest, &digest_len) == NULL)
642 		errx(1, "OpenSSL %s (%zu) HMAC failed: %s", alg->name,
643 		    size, ERR_error_string(ERR_get_error(), NULL));
644 
645 	/* cryptodev HMAC. */
646 	if (!ocf_hmac(alg, buffer, size, key, key_len, test_digest, &crid))
647 		goto out;
648 	if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
649 		if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
650 			printf("%s (%zu) mismatch in trailer:\n",
651 			    alg->name, size);
652 		else
653 			printf("%s (%zu) mismatch:\n", alg->name, size);
654 		printf("control:\n");
655 		hexdump(control_digest, sizeof(control_digest), NULL, 0);
656 		printf("test (cryptodev device %s):\n", crfind(crid));
657 		hexdump(test_digest, sizeof(test_digest), NULL, 0);
658 		goto out;
659 	}
660 
661 	if (verbose)
662 		printf("%s (%zu) matched (cryptodev device %s)\n",
663 		    alg->name, size, crfind(crid));
664 
665 out:
666 	free(buffer);
667 	free(key);
668 }
669 
670 static void
671 openssl_cipher(const struct alg *alg, const EVP_CIPHER *cipher, const char *key,
672     const char *iv, const char *input, char *output, size_t size, int enc)
673 {
674 	EVP_CIPHER_CTX *ctx;
675 	int outl, total;
676 
677 	ctx = EVP_CIPHER_CTX_new();
678 	if (ctx == NULL)
679 		errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
680 		    size, ERR_error_string(ERR_get_error(), NULL));
681 	if (EVP_CipherInit_ex(ctx, cipher, NULL, (const u_char *)key,
682 	    (const u_char *)iv, enc) != 1)
683 		errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
684 		    size, ERR_error_string(ERR_get_error(), NULL));
685 	EVP_CIPHER_CTX_set_padding(ctx, 0);
686 	if (EVP_CipherUpdate(ctx, (u_char *)output, &outl,
687 	    (const u_char *)input, size) != 1)
688 		errx(1, "OpenSSL %s (%zu) cipher update failed: %s", alg->name,
689 		    size, ERR_error_string(ERR_get_error(), NULL));
690 	total = outl;
691 	if (EVP_CipherFinal_ex(ctx, (u_char *)output + outl, &outl) != 1)
692 		errx(1, "OpenSSL %s (%zu) cipher final failed: %s", alg->name,
693 		    size, ERR_error_string(ERR_get_error(), NULL));
694 	total += outl;
695 	if (total != size)
696 		errx(1, "OpenSSL %s (%zu) cipher size mismatch: %d", alg->name,
697 		    size, total);
698 	EVP_CIPHER_CTX_free(ctx);
699 }
700 
701 static bool
702 ocf_init_cipher_session(const struct alg *alg, const char *key, size_t key_len,
703     struct ocf_session *ses)
704 {
705 	struct session2_op sop;
706 
707 	ocf_init_sop(&sop);
708 	sop.keylen = key_len;
709 	sop.key = (char *)key;
710 	sop.cipher = alg->cipher;
711 	return (ocf_init_session(&sop, "cipher", alg->name, ses));
712 }
713 
714 static bool
715 ocf_cipher(const struct ocf_session *ses, const struct alg *alg, const char *iv,
716     const char *input, char *output, size_t size, int op)
717 {
718 	struct crypt_op cop;
719 
720 	ocf_init_cop(ses, &cop);
721 	cop.op = op;
722 	cop.len = size;
723 	cop.src = (char *)input;
724 	cop.dst = output;
725 	cop.iv = (char *)iv;
726 
727 	if (ioctl(ses->fd, CIOCCRYPT, &cop) < 0) {
728 		warn("cryptodev %s (%zu) cipher failed for device %s",
729 		    alg->name, size, crfind(crid));
730 		return (false);
731 	}
732 
733 	return (true);
734 }
735 
736 static void
737 run_cipher_test(const struct alg *alg, size_t size)
738 {
739 	struct ocf_session ses;
740 	const EVP_CIPHER *cipher;
741 	char *buffer, *cleartext, *ciphertext;
742 	char *iv, *key;
743 	u_int iv_len, key_len;
744 
745 	cipher = alg->evp_cipher();
746 	if (size % EVP_CIPHER_block_size(cipher) != 0) {
747 		if (verbose)
748 			printf(
749 			    "%s (%zu): invalid buffer size (block size %d)\n",
750 			    alg->name, size, EVP_CIPHER_block_size(cipher));
751 		return;
752 	}
753 
754 	key_len = EVP_CIPHER_key_length(cipher);
755 	iv_len = EVP_CIPHER_iv_length(cipher);
756 
757 	key = alloc_buffer(key_len);
758 	iv = generate_iv(iv_len, alg);
759 	cleartext = alloc_buffer(size);
760 	buffer = malloc(size);
761 	ciphertext = malloc(size);
762 
763 	/* OpenSSL cipher. */
764 	openssl_cipher(alg, cipher, key, iv, cleartext, ciphertext, size, 1);
765 	if (size > 0 && memcmp(cleartext, ciphertext, size) == 0)
766 		errx(1, "OpenSSL %s (%zu): cipher text unchanged", alg->name,
767 		    size);
768 	openssl_cipher(alg, cipher, key, iv, ciphertext, buffer, size, 0);
769 	if (memcmp(cleartext, buffer, size) != 0) {
770 		printf("OpenSSL %s (%zu): cipher mismatch:", alg->name, size);
771 		printf("original:\n");
772 		hexdump(cleartext, size, NULL, 0);
773 		printf("decrypted:\n");
774 		hexdump(buffer, size, NULL, 0);
775 		exit(1);
776 	}
777 
778 	if (!ocf_init_cipher_session(alg, key, key_len, &ses))
779 		goto out;
780 
781 	/* OCF encrypt. */
782 	if (!ocf_cipher(&ses, alg, iv, cleartext, buffer, size, COP_ENCRYPT))
783 		goto out;
784 	if (memcmp(ciphertext, buffer, size) != 0) {
785 		printf("%s (%zu) encryption mismatch:\n", alg->name, size);
786 		printf("control:\n");
787 		hexdump(ciphertext, size, NULL, 0);
788 		printf("test (cryptodev device %s):\n", crfind(ses.crid));
789 		hexdump(buffer, size, NULL, 0);
790 		goto out;
791 	}
792 
793 	/* OCF decrypt. */
794 	if (!ocf_cipher(&ses, alg, iv, ciphertext, buffer, size, COP_DECRYPT))
795 		goto out;
796 	if (memcmp(cleartext, buffer, size) != 0) {
797 		printf("%s (%zu) decryption mismatch:\n", alg->name, size);
798 		printf("control:\n");
799 		hexdump(cleartext, size, NULL, 0);
800 		printf("test (cryptodev device %s):\n", crfind(ses.crid));
801 		hexdump(buffer, size, NULL, 0);
802 		goto out;
803 	}
804 
805 	if (verbose)
806 		printf("%s (%zu) matched (cryptodev device %s)\n",
807 		    alg->name, size, crfind(ses.crid));
808 
809 out:
810 	ocf_destroy_session(&ses);
811 	free(ciphertext);
812 	free(buffer);
813 	free(cleartext);
814 	free(iv);
815 	free(key);
816 }
817 
818 static bool
819 ocf_init_eta_session(const struct alg *alg, const char *cipher_key,
820     size_t cipher_key_len, const char *auth_key, size_t auth_key_len,
821     struct ocf_session *ses)
822 {
823 	struct session2_op sop;
824 
825 	ocf_init_sop(&sop);
826 	sop.keylen = cipher_key_len;
827 	sop.key = (char *)cipher_key;
828 	sop.cipher = alg->cipher;
829 	sop.mackeylen = auth_key_len;
830 	sop.mackey = (char *)auth_key;
831 	sop.mac = alg->mac;
832 	return (ocf_init_session(&sop, "ETA", alg->name, ses));
833 }
834 
835 static bool
836 ocf_eta(const struct ocf_session *ses, const struct alg *alg, const char *iv,
837     size_t iv_len, const char *aad, size_t aad_len, const char *input,
838     char *output, size_t size, char *digest, int op)
839 {
840 	int ret;
841 
842 	if (aad_len != 0) {
843 		struct crypt_aead caead;
844 
845 		ocf_init_caead(ses, &caead);
846 		caead.op = op;
847 		caead.flags = op == COP_ENCRYPT ? COP_F_CIPHER_FIRST : 0;
848 		caead.len = size;
849 		caead.aadlen = aad_len;
850 		caead.ivlen = iv_len;
851 		caead.src = (char *)input;
852 		caead.dst = output;
853 		caead.aad = (char *)aad;
854 		caead.tag = digest;
855 		caead.iv = (char *)iv;
856 
857 		ret = ioctl(ses->fd, CIOCCRYPTAEAD, &caead);
858 	} else {
859 		struct crypt_op cop;
860 
861 		ocf_init_cop(ses, &cop);
862 		cop.op = op;
863 		cop.flags = op == COP_ENCRYPT ? COP_F_CIPHER_FIRST : 0;
864 		cop.len = size;
865 		cop.src = (char *)input;
866 		cop.dst = output;
867 		cop.mac = digest;
868 		cop.iv = (char *)iv;
869 
870 		ret = ioctl(ses->fd, CIOCCRYPT, &cop);
871 	}
872 
873 	if (ret < 0) {
874 		warn("cryptodev %s (%zu) ETA failed for device %s",
875 		    alg->name, size, crfind(crid));
876 		return (false);
877 	}
878 
879 	return (true);
880 }
881 
882 static void
883 run_eta_test(const struct alg *alg, size_t size)
884 {
885 	struct ocf_session ses;
886 	const EVP_CIPHER *cipher;
887 	const EVP_MD *md;
888 	char *aad, *buffer, *cleartext, *ciphertext;
889 	char *iv, *auth_key, *cipher_key;
890 	u_int i, iv_len, auth_key_len, cipher_key_len, digest_len;
891 	char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE];
892 
893 	cipher = alg->evp_cipher();
894 	if (size % EVP_CIPHER_block_size(cipher) != 0) {
895 		if (verbose)
896 			printf(
897 			    "%s (%zu): invalid buffer size (block size %d)\n",
898 			    alg->name, size, EVP_CIPHER_block_size(cipher));
899 		return;
900 	}
901 
902 	memset(control_digest, 0x3c, sizeof(control_digest));
903 	memset(test_digest, 0x3c, sizeof(test_digest));
904 
905 	md = alg->evp_md();
906 
907 	cipher_key_len = EVP_CIPHER_key_length(cipher);
908 	iv_len = EVP_CIPHER_iv_length(cipher);
909 	auth_key_len = EVP_MD_size(md);
910 
911 	cipher_key = alloc_buffer(cipher_key_len);
912 	iv = generate_iv(iv_len, alg);
913 	auth_key = alloc_buffer(auth_key_len);
914 	cleartext = alloc_buffer(aad_len + size);
915 	buffer = malloc(aad_len + size);
916 	ciphertext = malloc(aad_len + size);
917 
918 	/* OpenSSL encrypt + HMAC. */
919 	if (aad_len != 0)
920 		memcpy(ciphertext, cleartext, aad_len);
921 	openssl_cipher(alg, cipher, cipher_key, iv, cleartext + aad_len,
922 	    ciphertext + aad_len, size, 1);
923 	if (size > 0 && memcmp(cleartext + aad_len, ciphertext + aad_len,
924 	    size) == 0)
925 		errx(1, "OpenSSL %s (%zu): cipher text unchanged", alg->name,
926 		    size);
927 	digest_len = sizeof(control_digest);
928 	if (HMAC(md, auth_key, auth_key_len, (u_char *)ciphertext,
929 	    aad_len + size, (u_char *)control_digest, &digest_len) == NULL)
930 		errx(1, "OpenSSL %s (%zu) HMAC failed: %s", alg->name,
931 		    size, ERR_error_string(ERR_get_error(), NULL));
932 
933 	if (!ocf_init_eta_session(alg, cipher_key, cipher_key_len, auth_key,
934 	    auth_key_len, &ses))
935 		goto out;
936 
937 	/* OCF encrypt + HMAC. */
938 	if (!ocf_eta(&ses, alg, iv, iv_len,
939 	    aad_len != 0 ? cleartext : NULL, aad_len, cleartext + aad_len,
940 	    buffer + aad_len, size, test_digest, COP_ENCRYPT))
941 		goto out;
942 	if (memcmp(ciphertext + aad_len, buffer + aad_len, size) != 0) {
943 		printf("%s (%zu) encryption mismatch:\n", alg->name, size);
944 		printf("control:\n");
945 		hexdump(ciphertext + aad_len, size, NULL, 0);
946 		printf("test (cryptodev device %s):\n", crfind(ses.crid));
947 		hexdump(buffer + aad_len, size, NULL, 0);
948 		goto out;
949 	}
950 	if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
951 		if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
952 			printf("%s (%zu) enc hash mismatch in trailer:\n",
953 			    alg->name, size);
954 		else
955 			printf("%s (%zu) enc hash mismatch:\n", alg->name,
956 			    size);
957 		printf("control:\n");
958 		hexdump(control_digest, sizeof(control_digest), NULL, 0);
959 		printf("test (cryptodev device %s):\n", crfind(ses.crid));
960 		hexdump(test_digest, sizeof(test_digest), NULL, 0);
961 		goto out;
962 	}
963 
964 	/* OCF HMAC + decrypt. */
965 	if (!ocf_eta(&ses, alg, iv, iv_len,
966 	    aad_len != 0 ? ciphertext : NULL, aad_len, ciphertext + aad_len,
967 	    buffer + aad_len, size, test_digest, COP_DECRYPT))
968 		goto out;
969 	if (memcmp(cleartext + aad_len, buffer + aad_len, size) != 0) {
970 		printf("%s (%zu) decryption mismatch:\n", alg->name, size);
971 		printf("control:\n");
972 		hexdump(cleartext, size, NULL, 0);
973 		printf("test (cryptodev device %s):\n", crfind(ses.crid));
974 		hexdump(buffer, size, NULL, 0);
975 		goto out;
976 	}
977 
978 	if (verbose)
979 		printf("%s (%zu) matched (cryptodev device %s)\n",
980 		    alg->name, size, crfind(ses.crid));
981 
982 out:
983 	ocf_destroy_session(&ses);
984 	free(ciphertext);
985 	free(buffer);
986 	free(cleartext);
987 	free(auth_key);
988 	free(iv);
989 	free(cipher_key);
990 }
991 
992 static void
993 openssl_gcm_encrypt(const struct alg *alg, const EVP_CIPHER *cipher,
994     const char *key, const char *iv, const char *aad, size_t aad_len,
995     const char *input, char *output, size_t size, char *tag)
996 {
997 	EVP_CIPHER_CTX *ctx;
998 	int outl, total;
999 
1000 	ctx = EVP_CIPHER_CTX_new();
1001 	if (ctx == NULL)
1002 		errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
1003 		    size, ERR_error_string(ERR_get_error(), NULL));
1004 	if (EVP_EncryptInit_ex(ctx, cipher, NULL, (const u_char *)key,
1005 	    (const u_char *)iv) != 1)
1006 		errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
1007 		    size, ERR_error_string(ERR_get_error(), NULL));
1008 	EVP_CIPHER_CTX_set_padding(ctx, 0);
1009 	if (aad != NULL) {
1010 		if (EVP_EncryptUpdate(ctx, NULL, &outl, (const u_char *)aad,
1011 		    aad_len) != 1)
1012 			errx(1, "OpenSSL %s (%zu) aad update failed: %s",
1013 			    alg->name, size,
1014 			    ERR_error_string(ERR_get_error(), NULL));
1015 	}
1016 	if (EVP_EncryptUpdate(ctx, (u_char *)output, &outl,
1017 	    (const u_char *)input, size) != 1)
1018 		errx(1, "OpenSSL %s (%zu) encrypt update failed: %s", alg->name,
1019 		    size, ERR_error_string(ERR_get_error(), NULL));
1020 	total = outl;
1021 	if (EVP_EncryptFinal_ex(ctx, (u_char *)output + outl, &outl) != 1)
1022 		errx(1, "OpenSSL %s (%zu) encrypt final failed: %s", alg->name,
1023 		    size, ERR_error_string(ERR_get_error(), NULL));
1024 	total += outl;
1025 	if (total != size)
1026 		errx(1, "OpenSSL %s (%zu) encrypt size mismatch: %d", alg->name,
1027 		    size, total);
1028 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, AES_GMAC_HASH_LEN,
1029 	    tag) != 1)
1030 		errx(1, "OpenSSL %s (%zu) get tag failed: %s", alg->name,
1031 		    size, ERR_error_string(ERR_get_error(), NULL));
1032 	EVP_CIPHER_CTX_free(ctx);
1033 }
1034 
1035 #ifdef notused
1036 static bool
1037 openssl_gcm_decrypt(const struct alg *alg, const EVP_CIPHER *cipher,
1038     const char *key, const char *iv, const char *aad, size_t aad_len,
1039     const char *input, char *output, size_t size, char *tag)
1040 {
1041 	EVP_CIPHER_CTX *ctx;
1042 	int outl, total;
1043 	bool valid;
1044 
1045 	ctx = EVP_CIPHER_CTX_new();
1046 	if (ctx == NULL)
1047 		errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
1048 		    size, ERR_error_string(ERR_get_error(), NULL));
1049 	if (EVP_DecryptInit_ex(ctx, cipher, NULL, (const u_char *)key,
1050 	    (const u_char *)iv) != 1)
1051 		errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
1052 		    size, ERR_error_string(ERR_get_error(), NULL));
1053 	EVP_CIPHER_CTX_set_padding(ctx, 0);
1054 	if (aad != NULL) {
1055 		if (EVP_DecryptUpdate(ctx, NULL, &outl, (const u_char *)aad,
1056 		    aad_len) != 1)
1057 			errx(1, "OpenSSL %s (%zu) aad update failed: %s",
1058 			    alg->name, size,
1059 			    ERR_error_string(ERR_get_error(), NULL));
1060 	}
1061 	if (EVP_DecryptUpdate(ctx, (u_char *)output, &outl,
1062 	    (const u_char *)input, size) != 1)
1063 		errx(1, "OpenSSL %s (%zu) decrypt update failed: %s", alg->name,
1064 		    size, ERR_error_string(ERR_get_error(), NULL));
1065 	total = outl;
1066 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AES_GMAC_HASH_LEN,
1067 	    tag) != 1)
1068 		errx(1, "OpenSSL %s (%zu) get tag failed: %s", alg->name,
1069 		    size, ERR_error_string(ERR_get_error(), NULL));
1070 	valid = (EVP_DecryptFinal_ex(ctx, (u_char *)output + outl, &outl) != 1);
1071 	total += outl;
1072 	if (total != size)
1073 		errx(1, "OpenSSL %s (%zu) decrypt size mismatch: %d", alg->name,
1074 		    size, total);
1075 	EVP_CIPHER_CTX_free(ctx);
1076 	return (valid);
1077 }
1078 #endif
1079 
1080 static void
1081 openssl_ccm_encrypt(const struct alg *alg, const EVP_CIPHER *cipher,
1082     const char *key, const char *iv, size_t iv_len, const char *aad,
1083     size_t aad_len, const char *input, char *output, size_t size, char *tag)
1084 {
1085 	EVP_CIPHER_CTX *ctx;
1086 	int outl, total;
1087 
1088 	ctx = EVP_CIPHER_CTX_new();
1089 	if (ctx == NULL)
1090 		errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
1091 		    size, ERR_error_string(ERR_get_error(), NULL));
1092 	if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
1093 		errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
1094 		    size, ERR_error_string(ERR_get_error(), NULL));
1095 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, iv_len, NULL) != 1)
1096 		errx(1, "OpenSSL %s (%zu) setting iv length failed: %s", alg->name,
1097 		    size, ERR_error_string(ERR_get_error(), NULL));
1098 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, AES_CBC_MAC_HASH_LEN, NULL) != 1)
1099 		errx(1, "OpenSSL %s (%zu) setting tag length failed: %s", alg->name,
1100 		     size, ERR_error_string(ERR_get_error(), NULL));
1101 	if (EVP_EncryptInit_ex(ctx, NULL, NULL, (const u_char *)key,
1102 	    (const u_char *)iv) != 1)
1103 		errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
1104 		    size, ERR_error_string(ERR_get_error(), NULL));
1105 	if (EVP_EncryptUpdate(ctx, NULL, &outl, NULL, size) != 1)
1106 		errx(1, "OpenSSL %s (%zu) unable to set data length: %s", alg->name,
1107 		     size, ERR_error_string(ERR_get_error(), NULL));
1108 
1109 	if (aad != NULL) {
1110 		if (EVP_EncryptUpdate(ctx, NULL, &outl, (const u_char *)aad,
1111 		    aad_len) != 1)
1112 			errx(1, "OpenSSL %s (%zu) aad update failed: %s",
1113 			    alg->name, size,
1114 			    ERR_error_string(ERR_get_error(), NULL));
1115 	}
1116 	if (EVP_EncryptUpdate(ctx, (u_char *)output, &outl,
1117 	    (const u_char *)input, size) != 1)
1118 		errx(1, "OpenSSL %s (%zu) encrypt update failed: %s", alg->name,
1119 		    size, ERR_error_string(ERR_get_error(), NULL));
1120 	total = outl;
1121 	if (EVP_EncryptFinal_ex(ctx, (u_char *)output + outl, &outl) != 1)
1122 		errx(1, "OpenSSL %s (%zu) encrypt final failed: %s", alg->name,
1123 		    size, ERR_error_string(ERR_get_error(), NULL));
1124 	total += outl;
1125 	if (total != size)
1126 		errx(1, "OpenSSL %s (%zu) encrypt size mismatch: %d", alg->name,
1127 		    size, total);
1128 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, AES_CBC_MAC_HASH_LEN,
1129 	    tag) != 1)
1130 		errx(1, "OpenSSL %s (%zu) get tag failed: %s", alg->name,
1131 		    size, ERR_error_string(ERR_get_error(), NULL));
1132 	EVP_CIPHER_CTX_free(ctx);
1133 }
1134 
1135 static bool
1136 ocf_init_aead_session(const struct alg *alg, const char *key, size_t key_len,
1137     struct ocf_session *ses)
1138 {
1139 	struct session2_op sop;
1140 
1141 	ocf_init_sop(&sop);
1142 	sop.keylen = key_len;
1143 	sop.key = (char *)key;
1144 	sop.cipher = alg->cipher;
1145 	sop.mackeylen = key_len;
1146 	sop.mackey = (char *)key;
1147 	sop.mac = alg->mac;
1148 	return (ocf_init_session(&sop, "AEAD", alg->name, ses));
1149 }
1150 
1151 static int
1152 ocf_aead(const struct ocf_session *ses, const struct alg *alg, const char *iv,
1153     size_t iv_len, const char *aad, size_t aad_len, const char *input,
1154     char *output, size_t size, char *tag, int op)
1155 {
1156 	struct crypt_aead caead;
1157 
1158 	ocf_init_caead(ses, &caead);
1159 	caead.op = op;
1160 	caead.len = size;
1161 	caead.aadlen = aad_len;
1162 	caead.ivlen = iv_len;
1163 	caead.src = (char *)input;
1164 	caead.dst = output;
1165 	caead.aad = (char *)aad;
1166 	caead.tag = tag;
1167 	caead.iv = (char *)iv;
1168 
1169 	if (ioctl(ses->fd, CIOCCRYPTAEAD, &caead) < 0)
1170 		return (errno);
1171 	return (0);
1172 }
1173 
1174 #define	AEAD_MAX_TAG_LEN	MAX(AES_GMAC_HASH_LEN, AES_CBC_MAC_HASH_LEN)
1175 
1176 static void
1177 run_aead_test(const struct alg *alg, size_t size)
1178 {
1179 	struct ocf_session ses;
1180 	const EVP_CIPHER *cipher;
1181 	char *aad, *buffer, *cleartext, *ciphertext;
1182 	char *iv, *key;
1183 	u_int iv_len, key_len;
1184 	int error;
1185 	char control_tag[AEAD_MAX_TAG_LEN], test_tag[AEAD_MAX_TAG_LEN];
1186 
1187 	cipher = alg->evp_cipher();
1188 	if (size % EVP_CIPHER_block_size(cipher) != 0) {
1189 		if (verbose)
1190 			printf(
1191 			    "%s (%zu): invalid buffer size (block size %d)\n",
1192 			    alg->name, size, EVP_CIPHER_block_size(cipher));
1193 		return;
1194 	}
1195 
1196 	memset(control_tag, 0x3c, sizeof(control_tag));
1197 	memset(test_tag, 0x3c, sizeof(test_tag));
1198 
1199 	key_len = EVP_CIPHER_key_length(cipher);
1200 	iv_len = EVP_CIPHER_iv_length(cipher);
1201 
1202 	/*
1203 	 * AES-CCM can have varying IV lengths; however, for the moment
1204 	 * we only support AES_CCM_IV_LEN (12).  So if the sizes are
1205 	 * different, we'll fail.
1206 	 */
1207 	if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE &&
1208 	    iv_len != AES_CCM_IV_LEN) {
1209 		if (verbose)
1210 			printf("OpenSSL CCM IV length (%d) != AES_CCM_IV_LEN",
1211 			    iv_len);
1212 		return;
1213 	}
1214 
1215 	key = alloc_buffer(key_len);
1216 	iv = generate_iv(iv_len, alg);
1217 	cleartext = alloc_buffer(size);
1218 	buffer = malloc(size);
1219 	ciphertext = malloc(size);
1220 	if (aad_len != 0)
1221 		aad = alloc_buffer(aad_len);
1222 	else
1223 		aad = NULL;
1224 
1225 	/* OpenSSL encrypt */
1226 	if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE)
1227 		openssl_ccm_encrypt(alg, cipher, key, iv, iv_len, aad,
1228 		    aad_len, cleartext, ciphertext, size, control_tag);
1229 	else
1230 		openssl_gcm_encrypt(alg, cipher, key, iv, aad, aad_len,
1231 		    cleartext, ciphertext, size, control_tag);
1232 
1233 	if (!ocf_init_aead_session(alg, key, key_len, &ses))
1234 		goto out;
1235 
1236 	/* OCF encrypt */
1237 	error = ocf_aead(&ses, alg, iv, iv_len, aad, aad_len, cleartext, buffer,
1238 	    size, test_tag, COP_ENCRYPT);
1239 	if (error != 0) {
1240 		warnc(error, "cryptodev %s (%zu) failed for device %s",
1241 		    alg->name, size, crfind(ses.crid));
1242 		goto out;
1243 	}
1244 	if (memcmp(ciphertext, buffer, size) != 0) {
1245 		printf("%s (%zu) encryption mismatch:\n", alg->name, size);
1246 		printf("control:\n");
1247 		hexdump(ciphertext, size, NULL, 0);
1248 		printf("test (cryptodev device %s):\n", crfind(crid));
1249 		hexdump(buffer, size, NULL, 0);
1250 		goto out;
1251 	}
1252 	if (memcmp(control_tag, test_tag, sizeof(control_tag)) != 0) {
1253 		printf("%s (%zu) enc tag mismatch:\n", alg->name, size);
1254 		printf("control:\n");
1255 		hexdump(control_tag, sizeof(control_tag), NULL, 0);
1256 		printf("test (cryptodev device %s):\n", crfind(crid));
1257 		hexdump(test_tag, sizeof(test_tag), NULL, 0);
1258 		goto out;
1259 	}
1260 
1261 	/* OCF decrypt */
1262 	error = ocf_aead(&ses, alg, iv, iv_len, aad, aad_len, ciphertext,
1263 	    buffer, size, control_tag, COP_DECRYPT);
1264 	if (error != 0) {
1265 		warnc(error, "cryptodev %s (%zu) failed for device %s",
1266 		    alg->name, size, crfind(ses.crid));
1267 		goto out;
1268 	}
1269 	if (memcmp(cleartext, buffer, size) != 0) {
1270 		printf("%s (%zu) decryption mismatch:\n", alg->name, size);
1271 		printf("control:\n");
1272 		hexdump(cleartext, size, NULL, 0);
1273 		printf("test (cryptodev device %s):\n", crfind(crid));
1274 		hexdump(buffer, size, NULL, 0);
1275 		goto out;
1276 	}
1277 
1278 	/* Verify OCF decrypt fails with busted tag. */
1279 	test_tag[0] ^= 0x1;
1280 	error = ocf_aead(&ses, alg, iv, iv_len, aad, aad_len, ciphertext,
1281 	    buffer, size, test_tag, COP_DECRYPT);
1282 	if (error != EBADMSG) {
1283 		if (error != 0)
1284 			warnc(error,
1285 		    "cryptodev %s (%zu) corrupt tag failed for device %s",
1286 			    alg->name, size, crfind(ses.crid));
1287 		else
1288 			warnx(
1289 		    "cryptodev %s (%zu) corrupt tag didn't fail for device %s",
1290 			    alg->name, size, crfind(ses.crid));
1291 		goto out;
1292 	}
1293 
1294 	if (verbose)
1295 		printf("%s (%zu) matched (cryptodev device %s)\n",
1296 		    alg->name, size, crfind(ses.crid));
1297 
1298 out:
1299 	ocf_destroy_session(&ses);
1300 	free(aad);
1301 	free(ciphertext);
1302 	free(buffer);
1303 	free(cleartext);
1304 	free(iv);
1305 	free(key);
1306 }
1307 
1308 static void
1309 run_test(const struct alg *alg, size_t size)
1310 {
1311 
1312 	switch (alg->type) {
1313 	case T_HASH:
1314 		run_hash_test(alg, size);
1315 		break;
1316 	case T_HMAC:
1317 		run_hmac_test(alg, size);
1318 		break;
1319 	case T_CIPHER:
1320 		run_cipher_test(alg, size);
1321 		break;
1322 	case T_ETA:
1323 		run_eta_test(alg, size);
1324 		break;
1325 	case T_AEAD:
1326 		run_aead_test(alg, size);
1327 		break;
1328 	}
1329 }
1330 
1331 static void
1332 run_test_sizes(const struct alg *alg, size_t *sizes, u_int nsizes)
1333 {
1334 	u_int i;
1335 
1336 	for (i = 0; i < nsizes; i++)
1337 		run_test(alg, sizes[i]);
1338 }
1339 
1340 static void
1341 run_hash_tests(size_t *sizes, u_int nsizes)
1342 {
1343 	u_int i;
1344 
1345 	for (i = 0; i < nitems(algs); i++)
1346 		if (algs[i].type == T_HASH)
1347 			run_test_sizes(&algs[i], sizes, nsizes);
1348 }
1349 
1350 static void
1351 run_mac_tests(size_t *sizes, u_int nsizes)
1352 {
1353 	u_int i;
1354 
1355 	for (i = 0; i < nitems(algs); i++)
1356 		if (algs[i].type == T_HMAC)
1357 			run_test_sizes(&algs[i], sizes, nsizes);
1358 }
1359 
1360 static void
1361 run_cipher_tests(size_t *sizes, u_int nsizes)
1362 {
1363 	u_int i;
1364 
1365 	for (i = 0; i < nitems(algs); i++)
1366 		if (algs[i].type == T_CIPHER)
1367 			run_test_sizes(&algs[i], sizes, nsizes);
1368 }
1369 
1370 static void
1371 run_eta_tests(size_t *sizes, u_int nsizes)
1372 {
1373 	const struct alg *cipher, *mac;
1374 	struct alg *eta;
1375 	u_int i, j;
1376 
1377 	for (i = 0; i < nitems(algs); i++) {
1378 		cipher = &algs[i];
1379 		if (cipher->type != T_CIPHER)
1380 			continue;
1381 		for (j = 0; j < nitems(algs); j++) {
1382 			mac = &algs[j];
1383 			if (mac->type != T_HMAC)
1384 				continue;
1385 			eta = build_eta(cipher, mac);
1386 			run_test_sizes(eta, sizes, nsizes);
1387 			free_eta(eta);
1388 		}
1389 	}
1390 }
1391 
1392 static void
1393 run_aead_tests(size_t *sizes, u_int nsizes)
1394 {
1395 	u_int i;
1396 
1397 	for (i = 0; i < nitems(algs); i++)
1398 		if (algs[i].type == T_AEAD)
1399 			run_test_sizes(&algs[i], sizes, nsizes);
1400 }
1401 
1402 int
1403 main(int ac, char **av)
1404 {
1405 	const char *algname;
1406 	const struct alg *alg;
1407 	struct alg *eta;
1408 	size_t sizes[128];
1409 	u_int i, nsizes;
1410 	bool testall;
1411 	int ch;
1412 
1413 	algname = NULL;
1414 	crid = CRYPTO_FLAG_HARDWARE;
1415 	testall = false;
1416 	verbose = false;
1417 	while ((ch = getopt(ac, av, "A:a:d:vz")) != -1)
1418 		switch (ch) {
1419 		case 'A':
1420 			aad_len = atoi(optarg);
1421 			break;
1422 		case 'a':
1423 			algname = optarg;
1424 			break;
1425 		case 'd':
1426 			crid = crlookup(optarg);
1427 			break;
1428 		case 'v':
1429 			verbose = true;
1430 			break;
1431 		case 'z':
1432 			testall = true;
1433 			break;
1434 		default:
1435 			usage();
1436 		}
1437 	ac -= optind;
1438 	av += optind;
1439 	nsizes = 0;
1440 	while (ac > 0) {
1441 		char *cp;
1442 
1443 		if (nsizes >= nitems(sizes)) {
1444 			warnx("Too many sizes, ignoring extras");
1445 			break;
1446 		}
1447 		sizes[nsizes] = strtol(av[0], &cp, 0);
1448 		if (*cp != '\0')
1449 			errx(1, "Bad size %s", av[0]);
1450 		nsizes++;
1451 		ac--;
1452 		av++;
1453 	}
1454 
1455 	if (algname == NULL)
1456 		errx(1, "Algorithm required");
1457 	if (nsizes == 0) {
1458 		sizes[0] = 16;
1459 		nsizes++;
1460 		if (testall) {
1461 			while (sizes[nsizes - 1] * 2 < 240 * 1024) {
1462 				assert(nsizes < nitems(sizes));
1463 				sizes[nsizes] = sizes[nsizes - 1] * 2;
1464 				nsizes++;
1465 			}
1466 			if (sizes[nsizes - 1] < 240 * 1024) {
1467 				assert(nsizes < nitems(sizes));
1468 				sizes[nsizes] = 240 * 1024;
1469 				nsizes++;
1470 			}
1471 		}
1472 	}
1473 
1474 	if (strcasecmp(algname, "hash") == 0)
1475 		run_hash_tests(sizes, nsizes);
1476 	else if (strcasecmp(algname, "mac") == 0)
1477 		run_mac_tests(sizes, nsizes);
1478 	else if (strcasecmp(algname, "cipher") == 0)
1479 		run_cipher_tests(sizes, nsizes);
1480 	else if (strcasecmp(algname, "eta") == 0)
1481 		run_eta_tests(sizes, nsizes);
1482 	else if (strcasecmp(algname, "aead") == 0)
1483 		run_aead_tests(sizes, nsizes);
1484 	else if (strcasecmp(algname, "all") == 0) {
1485 		run_hash_tests(sizes, nsizes);
1486 		run_mac_tests(sizes, nsizes);
1487 		run_cipher_tests(sizes, nsizes);
1488 		run_eta_tests(sizes, nsizes);
1489 		run_aead_tests(sizes, nsizes);
1490 	} else if (strchr(algname, '+') != NULL) {
1491 		eta = build_eta_name(algname);
1492 		run_test_sizes(eta, sizes, nsizes);
1493 		free_eta(eta);
1494 	} else {
1495 		alg = find_alg(algname);
1496 		if (alg == NULL)
1497 			errx(1, "Invalid algorithm %s", algname);
1498 		run_test_sizes(alg, sizes, nsizes);
1499 	}
1500 
1501 	return (0);
1502 }
1503