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