2 * Copyright (c) 2017 Chelsio Communications, Inc.
4 * Written by: John Baldwin <jhb@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
28 * Copyright (c) 2004 Sam Leffler, Errno Consulting
29 * All rights reserved.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
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.
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.
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.
68 * cryptocheck [-vz] [-A aad length] [-a algorithm] [-d dev] [size ...]
72 * -z Run all algorithms on a variety of buffer sizes.
74 * Supported algorithms:
76 * hmac Run all hmac tests
77 * blkcipher Run all block cipher tests
78 * authenc Run all authenticated encryption tests
79 * aead Run all authenticated encryption with associated data
84 * sha256 256-bit sha2 hmac
85 * sha384 384-bit sha2 hmac
86 * sha512 512-bit sha2 hmac
91 * aes-cbc 128-bit aes cbc
92 * aes-cbc192 192-bit aes cbc
93 * aes-cbc256 256-bit aes cbc
94 * aes-ctr 128-bit aes ctr
95 * aes-ctr192 192-bit aes ctr
96 * aes-ctr256 256-bit aes ctr
97 * aes-xts 128-bit aes xts
98 * aes-xts256 256-bit aes xts
101 * Authenticated Encryption:
102 * <block cipher>+<hmac>
104 * Authenticated Encryption with Associated Data:
105 * aes-gcm 128-bit aes gcm
106 * aes-gcm192 192-bit aes gcm
107 * aes-gcm256 256-bit aes gcm
110 #include <sys/param.h>
120 #include <openssl/err.h>
121 #include <openssl/hmac.h>
123 #include <crypto/cryptodev.h>
125 /* XXX: Temporary hack */
126 #ifndef COP_F_CIPHER_FIRST
127 #define COP_F_CIPHER_FIRST 0x0001 /* Cipher before MAC. */
134 enum { T_HMAC, T_BLKCIPHER, T_AUTHENC, T_GCM } type;
135 const EVP_CIPHER *(*evp_cipher)(void);
136 const EVP_MD *(*evp_md)(void);
138 { .name = "sha1", .mac = CRYPTO_SHA1_HMAC, .type = T_HMAC,
139 .evp_md = EVP_sha1 },
140 { .name = "sha256", .mac = CRYPTO_SHA2_256_HMAC, .type = T_HMAC,
141 .evp_md = EVP_sha256 },
142 { .name = "sha384", .mac = CRYPTO_SHA2_384_HMAC, .type = T_HMAC,
143 .evp_md = EVP_sha384 },
144 { .name = "sha512", .mac = CRYPTO_SHA2_512_HMAC, .type = T_HMAC,
145 .evp_md = EVP_sha512 },
146 { .name = "blake2b", .mac = CRYPTO_BLAKE2B, .type = T_HMAC,
147 .evp_md = EVP_blake2b512 },
148 { .name = "blake2s", .mac = CRYPTO_BLAKE2S, .type = T_HMAC,
149 .evp_md = EVP_blake2s256 },
150 { .name = "aes-cbc", .cipher = CRYPTO_AES_CBC, .type = T_BLKCIPHER,
151 .evp_cipher = EVP_aes_128_cbc },
152 { .name = "aes-cbc192", .cipher = CRYPTO_AES_CBC, .type = T_BLKCIPHER,
153 .evp_cipher = EVP_aes_192_cbc },
154 { .name = "aes-cbc256", .cipher = CRYPTO_AES_CBC, .type = T_BLKCIPHER,
155 .evp_cipher = EVP_aes_256_cbc },
156 { .name = "aes-ctr", .cipher = CRYPTO_AES_ICM, .type = T_BLKCIPHER,
157 .evp_cipher = EVP_aes_128_ctr },
158 { .name = "aes-ctr192", .cipher = CRYPTO_AES_ICM, .type = T_BLKCIPHER,
159 .evp_cipher = EVP_aes_192_ctr },
160 { .name = "aes-ctr256", .cipher = CRYPTO_AES_ICM, .type = T_BLKCIPHER,
161 .evp_cipher = EVP_aes_256_ctr },
162 { .name = "aes-xts", .cipher = CRYPTO_AES_XTS, .type = T_BLKCIPHER,
163 .evp_cipher = EVP_aes_128_xts },
164 { .name = "aes-xts256", .cipher = CRYPTO_AES_XTS, .type = T_BLKCIPHER,
165 .evp_cipher = EVP_aes_256_xts },
166 { .name = "chacha20", .cipher = CRYPTO_CHACHA20, .type = T_BLKCIPHER,
167 .evp_cipher = EVP_chacha20 },
168 { .name = "aes-gcm", .cipher = CRYPTO_AES_NIST_GCM_16,
169 .mac = CRYPTO_AES_128_NIST_GMAC, .type = T_GCM,
170 .evp_cipher = EVP_aes_128_gcm },
171 { .name = "aes-gcm192", .cipher = CRYPTO_AES_NIST_GCM_16,
172 .mac = CRYPTO_AES_192_NIST_GMAC, .type = T_GCM,
173 .evp_cipher = EVP_aes_192_gcm },
174 { .name = "aes-gcm256", .cipher = CRYPTO_AES_NIST_GCM_16,
175 .mac = CRYPTO_AES_256_NIST_GMAC, .type = T_GCM,
176 .evp_cipher = EVP_aes_256_gcm },
181 static size_t aad_len;
187 "usage: cryptocheck [-z] [-a algorithm] [-d dev] [size ...]\n");
192 find_alg(const char *name)
196 for (i = 0; i < nitems(algs); i++)
197 if (strcasecmp(algs[i].name, name) == 0)
203 build_authenc(struct alg *cipher, struct alg *hmac)
205 static struct alg authenc;
208 assert(cipher->type == T_BLKCIPHER);
209 assert(hmac->type == T_HMAC);
210 memset(&authenc, 0, sizeof(authenc));
211 asprintf(&name, "%s+%s", cipher->name, hmac->name);
213 authenc.cipher = cipher->cipher;
214 authenc.mac = hmac->mac;
215 authenc.type = T_AUTHENC;
216 authenc.evp_cipher = cipher->evp_cipher;
217 authenc.evp_md = hmac->evp_md;
222 build_authenc_name(const char *name)
224 struct alg *cipher, *hmac;
225 const char *hmac_name;
226 char *cp, *cipher_name;
228 cp = strchr(name, '+');
229 cipher_name = strndup(name, cp - name);
231 cipher = find_alg(cipher_name);
234 errx(1, "Invalid cipher %s", cipher_name);
235 hmac = find_alg(hmac_name);
237 errx(1, "Invalid hash %s", hmac_name);
238 return (build_authenc(cipher, hmac));
247 fd = open("/dev/crypto", O_RDWR | O_CLOEXEC, 0);
249 err(1, "/dev/crypto");
255 crlookup(const char *devname)
257 struct crypt_find_op find;
259 if (strncmp(devname, "soft", 4) == 0)
260 return CRYPTO_FLAG_SOFTWARE;
263 strlcpy(find.name, devname, sizeof(find.name));
264 if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1)
265 err(1, "ioctl(CIOCFINDDEV)");
272 static struct crypt_find_op find;
274 if (crid == CRYPTO_FLAG_SOFTWARE)
276 else if (crid == CRYPTO_FLAG_HARDWARE)
279 bzero(&find, sizeof(find));
281 if (ioctl(devcrypto(), CRIOFINDDEV, &find) == -1)
282 err(1, "ioctl(CIOCFINDDEV): crid %d", crid);
291 if (ioctl(devcrypto(), CRIOGET, &fd) == -1)
292 err(1, "ioctl(CRIOGET)");
293 if (fcntl(fd, F_SETFD, 1) == -1)
294 err(1, "fcntl(F_SETFD) (crget)");
302 0x10,0x54,0x11,0x48,0x45,0x12,0x4f,0x13,0x49,0x53,0x14,0x41,
303 0x15,0x16,0x4e,0x55,0x54,0x17,0x18,0x4a,0x4f,0x42,0x19,0x01
305 return 0x20+a[random()%nitems(a)];
309 alloc_buffer(size_t len)
315 for (i = 0; i < len; i++)
321 generate_iv(size_t len, struct alg *alg)
325 iv = alloc_buffer(len);
326 switch (alg->cipher) {
328 /* Clear the low 32 bits of the IV to hold the counter. */
336 * Clear the low 64-bits to only store a 64-bit block
353 ocf_hmac(struct alg *alg, const char *buffer, size_t size, const char *key,
354 size_t key_len, char *digest, int *cridp)
356 struct session2_op sop;
360 memset(&sop, 0, sizeof(sop));
361 memset(&cop, 0, sizeof(cop));
363 sop.mackeylen = key_len;
364 sop.mackey = (char *)key;
367 if (ioctl(fd, CIOCGSESSION2, &sop) < 0) {
368 warn("cryptodev %s HMAC not supported for device %s",
369 alg->name, crfind(crid));
377 cop.src = (char *)buffer;
382 if (ioctl(fd, CIOCCRYPT, &cop) < 0) {
383 warn("cryptodev %s (%zu) HMAC failed for device %s", alg->name,
389 if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0)
390 warn("ioctl(CIOCFSESSION)");
398 run_hmac_test(struct alg *alg, size_t size)
402 u_int key_len, digest_len;
404 char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE];
406 memset(control_digest, 0x3c, sizeof(control_digest));
407 memset(test_digest, 0x3c, sizeof(test_digest));
410 key_len = EVP_MD_size(md);
411 assert(EVP_MD_size(md) <= sizeof(control_digest));
413 key = alloc_buffer(key_len);
414 buffer = alloc_buffer(size);
417 digest_len = sizeof(control_digest);
418 if (HMAC(md, key, key_len, (u_char *)buffer, size,
419 (u_char *)control_digest, &digest_len) == NULL)
420 errx(1, "OpenSSL %s (%zu) HMAC failed: %s", alg->name,
421 size, ERR_error_string(ERR_get_error(), NULL));
423 /* cryptodev HMAC. */
424 if (!ocf_hmac(alg, buffer, size, key, key_len, test_digest, &crid))
426 if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
427 if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
428 printf("%s (%zu) mismatch in trailer:\n",
431 printf("%s (%zu) mismatch:\n", alg->name, size);
432 printf("control:\n");
433 hexdump(control_digest, sizeof(control_digest), NULL, 0);
434 printf("test (cryptodev device %s):\n", crfind(crid));
435 hexdump(test_digest, sizeof(test_digest), NULL, 0);
440 printf("%s (%zu) matched (cryptodev device %s)\n",
441 alg->name, size, crfind(crid));
449 openssl_cipher(struct alg *alg, const EVP_CIPHER *cipher, const char *key,
450 const char *iv, const char *input, char *output, size_t size, int enc)
455 ctx = EVP_CIPHER_CTX_new();
457 errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
458 size, ERR_error_string(ERR_get_error(), NULL));
459 if (EVP_CipherInit_ex(ctx, cipher, NULL, (const u_char *)key,
460 (const u_char *)iv, enc) != 1)
461 errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
462 size, ERR_error_string(ERR_get_error(), NULL));
463 EVP_CIPHER_CTX_set_padding(ctx, 0);
464 if (EVP_CipherUpdate(ctx, (u_char *)output, &outl,
465 (const u_char *)input, size) != 1)
466 errx(1, "OpenSSL %s (%zu) cipher update failed: %s", alg->name,
467 size, ERR_error_string(ERR_get_error(), NULL));
469 if (EVP_CipherFinal_ex(ctx, (u_char *)output + outl, &outl) != 1)
470 errx(1, "OpenSSL %s (%zu) cipher final failed: %s", alg->name,
471 size, ERR_error_string(ERR_get_error(), NULL));
474 errx(1, "OpenSSL %s (%zu) cipher size mismatch: %d", alg->name,
476 EVP_CIPHER_CTX_free(ctx);
480 ocf_cipher(struct alg *alg, const char *key, size_t key_len,
481 const char *iv, const char *input, char *output, size_t size, int enc,
484 struct session2_op sop;
488 memset(&sop, 0, sizeof(sop));
489 memset(&cop, 0, sizeof(cop));
491 sop.keylen = key_len;
492 sop.key = (char *)key;
493 sop.cipher = alg->cipher;
495 if (ioctl(fd, CIOCGSESSION2, &sop) < 0) {
496 warn("cryptodev %s block cipher not supported for device %s",
497 alg->name, crfind(crid));
503 cop.op = enc ? COP_ENCRYPT : COP_DECRYPT;
505 cop.src = (char *)input;
510 if (ioctl(fd, CIOCCRYPT, &cop) < 0) {
511 warn("cryptodev %s (%zu) block cipher failed for device %s",
512 alg->name, size, crfind(crid));
517 if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0)
518 warn("ioctl(CIOCFSESSION)");
526 run_blkcipher_test(struct alg *alg, size_t size)
528 const EVP_CIPHER *cipher;
529 char *buffer, *cleartext, *ciphertext;
531 u_int iv_len, key_len;
534 cipher = alg->evp_cipher();
535 if (size % EVP_CIPHER_block_size(cipher) != 0) {
538 "%s (%zu): invalid buffer size (block size %d)\n",
539 alg->name, size, EVP_CIPHER_block_size(cipher));
543 key_len = EVP_CIPHER_key_length(cipher);
544 iv_len = EVP_CIPHER_iv_length(cipher);
546 key = alloc_buffer(key_len);
547 iv = generate_iv(iv_len, alg);
548 cleartext = alloc_buffer(size);
549 buffer = malloc(size);
550 ciphertext = malloc(size);
552 /* OpenSSL cipher. */
553 openssl_cipher(alg, cipher, key, iv, cleartext, ciphertext, size, 1);
554 if (size > 0 && memcmp(cleartext, ciphertext, size) == 0)
555 errx(1, "OpenSSL %s (%zu): cipher text unchanged", alg->name,
557 openssl_cipher(alg, cipher, key, iv, ciphertext, buffer, size, 0);
558 if (memcmp(cleartext, buffer, size) != 0) {
559 printf("OpenSSL %s (%zu): cipher mismatch:", alg->name, size);
560 printf("original:\n");
561 hexdump(cleartext, size, NULL, 0);
562 printf("decrypted:\n");
563 hexdump(buffer, size, NULL, 0);
568 if (!ocf_cipher(alg, key, key_len, iv, cleartext, buffer, size, 1,
571 if (memcmp(ciphertext, buffer, size) != 0) {
572 printf("%s (%zu) encryption mismatch:\n", alg->name, size);
573 printf("control:\n");
574 hexdump(ciphertext, size, NULL, 0);
575 printf("test (cryptodev device %s):\n", crfind(crid));
576 hexdump(buffer, size, NULL, 0);
581 if (!ocf_cipher(alg, key, key_len, iv, ciphertext, buffer, size, 0,
584 if (memcmp(cleartext, buffer, size) != 0) {
585 printf("%s (%zu) decryption mismatch:\n", alg->name, size);
586 printf("control:\n");
587 hexdump(cleartext, size, NULL, 0);
588 printf("test (cryptodev device %s):\n", crfind(crid));
589 hexdump(buffer, size, NULL, 0);
594 printf("%s (%zu) matched (cryptodev device %s)\n",
595 alg->name, size, crfind(crid));
606 ocf_authenc(struct alg *alg, const char *cipher_key, size_t cipher_key_len,
607 const char *iv, size_t iv_len, const char *auth_key, size_t auth_key_len,
608 const char *aad, size_t aad_len, const char *input, char *output,
609 size_t size, char *digest, int enc, int *cridp)
611 struct session2_op sop;
614 memset(&sop, 0, sizeof(sop));
616 sop.keylen = cipher_key_len;
617 sop.key = (char *)cipher_key;
618 sop.cipher = alg->cipher;
619 sop.mackeylen = auth_key_len;
620 sop.mackey = (char *)auth_key;
623 if (ioctl(fd, CIOCGSESSION2, &sop) < 0) {
624 warn("cryptodev %s AUTHENC not supported for device %s",
625 alg->name, crfind(crid));
631 struct crypt_aead caead;
633 memset(&caead, 0, sizeof(caead));
635 caead.op = enc ? COP_ENCRYPT : COP_DECRYPT;
636 caead.flags = enc ? COP_F_CIPHER_FIRST : 0;
638 caead.aadlen = aad_len;
639 caead.ivlen = iv_len;
640 caead.src = (char *)input;
642 caead.aad = (char *)aad;
644 caead.iv = (char *)iv;
646 if (ioctl(fd, CIOCCRYPTAEAD, &caead) < 0) {
647 warn("cryptodev %s (%zu) failed for device %s",
648 alg->name, size, crfind(crid));
655 memset(&cop, 0, sizeof(cop));
657 cop.op = enc ? COP_ENCRYPT : COP_DECRYPT;
658 cop.flags = enc ? COP_F_CIPHER_FIRST : 0;
660 cop.src = (char *)input;
665 if (ioctl(fd, CIOCCRYPT, &cop) < 0) {
666 warn("cryptodev %s (%zu) AUTHENC failed for device %s",
667 alg->name, size, crfind(crid));
673 if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0)
674 warn("ioctl(CIOCFSESSION)");
682 run_authenc_test(struct alg *alg, size_t size)
684 const EVP_CIPHER *cipher;
686 char *aad, *buffer, *cleartext, *ciphertext;
687 char *iv, *auth_key, *cipher_key;
688 u_int iv_len, auth_key_len, cipher_key_len, digest_len;
690 char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE];
692 cipher = alg->evp_cipher();
693 if (size % EVP_CIPHER_block_size(cipher) != 0) {
696 "%s (%zu): invalid buffer size (block size %d)\n",
697 alg->name, size, EVP_CIPHER_block_size(cipher));
701 memset(control_digest, 0x3c, sizeof(control_digest));
702 memset(test_digest, 0x3c, sizeof(test_digest));
706 cipher_key_len = EVP_CIPHER_key_length(cipher);
707 iv_len = EVP_CIPHER_iv_length(cipher);
708 auth_key_len = EVP_MD_size(md);
710 cipher_key = alloc_buffer(cipher_key_len);
711 iv = generate_iv(iv_len, alg);
712 auth_key = alloc_buffer(auth_key_len);
713 cleartext = alloc_buffer(aad_len + size);
714 buffer = malloc(aad_len + size);
715 ciphertext = malloc(aad_len + size);
717 /* OpenSSL encrypt + HMAC. */
719 memcpy(ciphertext, cleartext, aad_len);
720 openssl_cipher(alg, cipher, cipher_key, iv, cleartext + aad_len,
721 ciphertext + aad_len, size, 1);
722 if (size > 0 && memcmp(cleartext + aad_len, ciphertext + aad_len,
724 errx(1, "OpenSSL %s (%zu): cipher text unchanged", alg->name,
726 digest_len = sizeof(control_digest);
727 if (HMAC(md, auth_key, auth_key_len, (u_char *)ciphertext,
728 aad_len + size, (u_char *)control_digest, &digest_len) == NULL)
729 errx(1, "OpenSSL %s (%zu) HMAC failed: %s", alg->name,
730 size, ERR_error_string(ERR_get_error(), NULL));
732 /* OCF encrypt + HMAC. */
733 if (!ocf_authenc(alg, cipher_key, cipher_key_len, iv, iv_len, auth_key,
734 auth_key_len, aad_len != 0 ? cleartext : NULL, aad_len,
735 cleartext + aad_len, buffer + aad_len, size, test_digest, 1, &crid))
737 if (memcmp(ciphertext + aad_len, buffer + aad_len, size) != 0) {
738 printf("%s (%zu) encryption mismatch:\n", alg->name, size);
739 printf("control:\n");
740 hexdump(ciphertext + aad_len, size, NULL, 0);
741 printf("test (cryptodev device %s):\n", crfind(crid));
742 hexdump(buffer + aad_len, size, NULL, 0);
745 if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
746 if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
747 printf("%s (%zu) enc hash mismatch in trailer:\n",
750 printf("%s (%zu) enc hash mismatch:\n", alg->name,
752 printf("control:\n");
753 hexdump(control_digest, sizeof(control_digest), NULL, 0);
754 printf("test (cryptodev device %s):\n", crfind(crid));
755 hexdump(test_digest, sizeof(test_digest), NULL, 0);
759 /* OCF HMAC + decrypt. */
760 memset(test_digest, 0x3c, sizeof(test_digest));
761 if (!ocf_authenc(alg, cipher_key, cipher_key_len, iv, iv_len, auth_key,
762 auth_key_len, aad_len != 0 ? ciphertext : NULL, aad_len,
763 ciphertext + aad_len, buffer + aad_len, size, test_digest, 0,
766 if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
767 if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
768 printf("%s (%zu) dec hash mismatch in trailer:\n",
771 printf("%s (%zu) dec hash mismatch:\n", alg->name,
773 printf("control:\n");
774 hexdump(control_digest, sizeof(control_digest), NULL, 0);
775 printf("test (cryptodev device %s):\n", crfind(crid));
776 hexdump(test_digest, sizeof(test_digest), NULL, 0);
779 if (memcmp(cleartext + aad_len, buffer + aad_len, size) != 0) {
780 printf("%s (%zu) decryption mismatch:\n", alg->name, size);
781 printf("control:\n");
782 hexdump(cleartext, size, NULL, 0);
783 printf("test (cryptodev device %s):\n", crfind(crid));
784 hexdump(buffer, size, NULL, 0);
789 printf("%s (%zu) matched (cryptodev device %s)\n",
790 alg->name, size, crfind(crid));
802 openssl_gcm_encrypt(struct alg *alg, const EVP_CIPHER *cipher, const char *key,
803 const char *iv, const char *aad, size_t aad_len, const char *input,
804 char *output, size_t size, char *tag)
809 ctx = EVP_CIPHER_CTX_new();
811 errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
812 size, ERR_error_string(ERR_get_error(), NULL));
813 if (EVP_EncryptInit_ex(ctx, cipher, NULL, (const u_char *)key,
814 (const u_char *)iv) != 1)
815 errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
816 size, ERR_error_string(ERR_get_error(), NULL));
817 EVP_CIPHER_CTX_set_padding(ctx, 0);
819 if (EVP_EncryptUpdate(ctx, NULL, &outl, (const u_char *)aad,
821 errx(1, "OpenSSL %s (%zu) aad update failed: %s",
823 ERR_error_string(ERR_get_error(), NULL));
825 if (EVP_EncryptUpdate(ctx, (u_char *)output, &outl,
826 (const u_char *)input, size) != 1)
827 errx(1, "OpenSSL %s (%zu) encrypt update failed: %s", alg->name,
828 size, ERR_error_string(ERR_get_error(), NULL));
830 if (EVP_EncryptFinal_ex(ctx, (u_char *)output + outl, &outl) != 1)
831 errx(1, "OpenSSL %s (%zu) encrypt final failed: %s", alg->name,
832 size, ERR_error_string(ERR_get_error(), NULL));
835 errx(1, "OpenSSL %s (%zu) encrypt size mismatch: %d", alg->name,
837 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, AES_GMAC_HASH_LEN,
839 errx(1, "OpenSSL %s (%zu) get tag failed: %s", alg->name,
840 size, ERR_error_string(ERR_get_error(), NULL));
841 EVP_CIPHER_CTX_free(ctx);
845 ocf_gcm(struct alg *alg, const char *key, size_t key_len, const char *iv,
846 size_t iv_len, const char *aad, size_t aad_len, const char *input,
847 char *output, size_t size, char *tag, int enc, int *cridp)
849 struct session2_op sop;
850 struct crypt_aead caead;
853 memset(&sop, 0, sizeof(sop));
854 memset(&caead, 0, sizeof(caead));
856 sop.keylen = key_len;
857 sop.key = (char *)key;
858 sop.cipher = alg->cipher;
859 sop.mackeylen = key_len;
860 sop.mackey = (char *)key;
863 if (ioctl(fd, CIOCGSESSION2, &sop) < 0) {
864 warn("cryptodev %s not supported for device %s",
865 alg->name, crfind(crid));
871 caead.op = enc ? COP_ENCRYPT : COP_DECRYPT;
873 caead.aadlen = aad_len;
874 caead.ivlen = iv_len;
875 caead.src = (char *)input;
877 caead.aad = (char *)aad;
879 caead.iv = (char *)iv;
881 if (ioctl(fd, CIOCCRYPTAEAD, &caead) < 0) {
882 warn("cryptodev %s (%zu) failed for device %s",
883 alg->name, size, crfind(crid));
888 if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0)
889 warn("ioctl(CIOCFSESSION)");
898 openssl_gcm_decrypt(struct alg *alg, const EVP_CIPHER *cipher, const char *key,
899 const char *iv, const char *aad, size_t aad_len, const char *input,
900 char *output, size_t size, char *tag)
906 ctx = EVP_CIPHER_CTX_new();
908 errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
909 size, ERR_error_string(ERR_get_error(), NULL));
910 if (EVP_DecryptInit_ex(ctx, cipher, NULL, (const u_char *)key,
911 (const u_char *)iv) != 1)
912 errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
913 size, ERR_error_string(ERR_get_error(), NULL));
914 EVP_CIPHER_CTX_set_padding(ctx, 0);
916 if (EVP_DecryptUpdate(ctx, NULL, &outl, (const u_char *)aad,
918 errx(1, "OpenSSL %s (%zu) aad update failed: %s",
920 ERR_error_string(ERR_get_error(), NULL));
922 if (EVP_DecryptUpdate(ctx, (u_char *)output, &outl,
923 (const u_char *)input, size) != 1)
924 errx(1, "OpenSSL %s (%zu) decrypt update failed: %s", alg->name,
925 size, ERR_error_string(ERR_get_error(), NULL));
927 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AES_GMAC_HASH_LEN,
929 errx(1, "OpenSSL %s (%zu) get tag failed: %s", alg->name,
930 size, ERR_error_string(ERR_get_error(), NULL));
931 valid = (EVP_DecryptFinal_ex(ctx, (u_char *)output + outl, &outl) != 1);
934 errx(1, "OpenSSL %s (%zu) decrypt size mismatch: %d", alg->name,
936 EVP_CIPHER_CTX_free(ctx);
942 run_gcm_test(struct alg *alg, size_t size)
944 const EVP_CIPHER *cipher;
945 char *aad, *buffer, *cleartext, *ciphertext;
947 u_int iv_len, key_len;
949 char control_tag[AES_GMAC_HASH_LEN], test_tag[AES_GMAC_HASH_LEN];
951 cipher = alg->evp_cipher();
952 if (size % EVP_CIPHER_block_size(cipher) != 0) {
955 "%s (%zu): invalid buffer size (block size %d)\n",
956 alg->name, size, EVP_CIPHER_block_size(cipher));
960 memset(control_tag, 0x3c, sizeof(control_tag));
961 memset(test_tag, 0x3c, sizeof(test_tag));
963 key_len = EVP_CIPHER_key_length(cipher);
964 iv_len = EVP_CIPHER_iv_length(cipher);
966 key = alloc_buffer(key_len);
967 iv = generate_iv(iv_len, alg);
968 cleartext = alloc_buffer(size);
969 buffer = malloc(size);
970 ciphertext = malloc(size);
972 aad = alloc_buffer(aad_len);
976 /* OpenSSL encrypt */
977 openssl_gcm_encrypt(alg, cipher, key, iv, aad, aad_len, cleartext,
978 ciphertext, size, control_tag);
981 if (!ocf_gcm(alg, key, key_len, iv, iv_len, aad, aad_len, cleartext,
982 buffer, size, test_tag, 1, &crid))
984 if (memcmp(ciphertext, buffer, size) != 0) {
985 printf("%s (%zu) encryption mismatch:\n", alg->name, size);
986 printf("control:\n");
987 hexdump(ciphertext, size, NULL, 0);
988 printf("test (cryptodev device %s):\n", crfind(crid));
989 hexdump(buffer, size, NULL, 0);
992 if (memcmp(control_tag, test_tag, sizeof(control_tag)) != 0) {
993 printf("%s (%zu) enc tag mismatch:\n", alg->name, size);
994 printf("control:\n");
995 hexdump(control_tag, sizeof(control_tag), NULL, 0);
996 printf("test (cryptodev device %s):\n", crfind(crid));
997 hexdump(test_tag, sizeof(test_tag), NULL, 0);
1002 if (!ocf_gcm(alg, key, key_len, iv, iv_len, aad, aad_len, ciphertext,
1003 buffer, size, control_tag, 0, &crid))
1005 if (memcmp(cleartext, buffer, size) != 0) {
1006 printf("%s (%zu) decryption mismatch:\n", alg->name, size);
1007 printf("control:\n");
1008 hexdump(cleartext, size, NULL, 0);
1009 printf("test (cryptodev device %s):\n", crfind(crid));
1010 hexdump(buffer, size, NULL, 0);
1015 printf("%s (%zu) matched (cryptodev device %s)\n",
1016 alg->name, size, crfind(crid));
1028 run_test(struct alg *alg, size_t size)
1031 switch (alg->type) {
1033 run_hmac_test(alg, size);
1036 run_blkcipher_test(alg, size);
1039 run_authenc_test(alg, size);
1042 run_gcm_test(alg, size);
1048 run_test_sizes(struct alg *alg, size_t *sizes, u_int nsizes)
1052 for (i = 0; i < nsizes; i++)
1053 run_test(alg, sizes[i]);
1057 run_hmac_tests(size_t *sizes, u_int nsizes)
1061 for (i = 0; i < nitems(algs); i++)
1062 if (algs[i].type == T_HMAC)
1063 run_test_sizes(&algs[i], sizes, nsizes);
1067 run_blkcipher_tests(size_t *sizes, u_int nsizes)
1071 for (i = 0; i < nitems(algs); i++)
1072 if (algs[i].type == T_BLKCIPHER)
1073 run_test_sizes(&algs[i], sizes, nsizes);
1077 run_authenc_tests(size_t *sizes, u_int nsizes)
1079 struct alg *authenc, *cipher, *hmac;
1082 for (i = 0; i < nitems(algs); i++) {
1084 if (cipher->type != T_BLKCIPHER)
1086 for (j = 0; j < nitems(algs); j++) {
1088 if (hmac->type != T_HMAC)
1090 authenc = build_authenc(cipher, hmac);
1091 run_test_sizes(authenc, sizes, nsizes);
1092 free((char *)authenc->name);
1098 run_aead_tests(size_t *sizes, u_int nsizes)
1102 for (i = 0; i < nitems(algs); i++)
1103 if (algs[i].type == T_GCM)
1104 run_test_sizes(&algs[i], sizes, nsizes);
1108 main(int ac, char **av)
1110 const char *algname;
1118 crid = CRYPTO_FLAG_HARDWARE;
1121 while ((ch = getopt(ac, av, "A:a:d:vz")) != -1)
1124 aad_len = atoi(optarg);
1130 crid = crlookup(optarg);
1147 if (nsizes >= nitems(sizes)) {
1148 warnx("Too many sizes, ignoring extras");
1151 sizes[nsizes] = strtol(av[0], &cp, 0);
1153 errx(1, "Bad size %s", av[0]);
1159 if (algname == NULL)
1160 errx(1, "Algorithm required");
1165 while (sizes[nsizes - 1] * 2 < 240 * 1024) {
1166 assert(nsizes < nitems(sizes));
1167 sizes[nsizes] = sizes[nsizes - 1] * 2;
1170 if (sizes[nsizes - 1] < 240 * 1024) {
1171 assert(nsizes < nitems(sizes));
1172 sizes[nsizes] = 240 * 1024;
1178 if (strcasecmp(algname, "hmac") == 0)
1179 run_hmac_tests(sizes, nsizes);
1180 else if (strcasecmp(algname, "blkcipher") == 0)
1181 run_blkcipher_tests(sizes, nsizes);
1182 else if (strcasecmp(algname, "authenc") == 0)
1183 run_authenc_tests(sizes, nsizes);
1184 else if (strcasecmp(algname, "aead") == 0)
1185 run_aead_tests(sizes, nsizes);
1186 else if (strcasecmp(algname, "all") == 0) {
1187 run_hmac_tests(sizes, nsizes);
1188 run_blkcipher_tests(sizes, nsizes);
1189 run_authenc_tests(sizes, nsizes);
1190 run_aead_tests(sizes, nsizes);
1191 } else if (strchr(algname, '+') != NULL) {
1192 alg = build_authenc_name(algname);
1193 run_test_sizes(alg, sizes, nsizes);
1195 alg = find_alg(algname);
1197 errx(1, "Invalid algorithm %s", algname);
1198 run_test_sizes(alg, sizes, nsizes);