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