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