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