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 * 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
85 * sha224 224-bit SHA-2
86 * sha256 256-bit SHA-2
87 * sha384 384-bit SHA-2
88 * sha512 512-bit SHA-2
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
100 * aes-cbc 128-bit AES-CBC
101 * aes-cbc192 192-bit AES-CBC
102 * aes-cbc256 256-bit AES-CBC
103 * aes-ctr 128-bit AES-CTR
104 * aes-ctr192 192-bit AES-CTR
105 * aes-ctr256 256-bit AES-CTR
106 * aes-xts 128-bit AES-XTS
107 * aes-xts256 256-bit AES-XTS
110 * Encrypt then Authenticate:
113 * Authenticated Encryption with Associated Data:
114 * aes-gcm 128-bit AES-GCM
115 * aes-gcm192 192-bit AES-GCM
116 * aes-gcm256 256-bit AES-GCM
117 * aes-ccm 128-bit AES-CCM
118 * aes-ccm192 192-bit AES-CCM
119 * aes-ccm256 256-bit AES-CCM
122 #include <sys/param.h>
123 #include <sys/sysctl.h>
133 #include <openssl/err.h>
134 #include <openssl/hmac.h>
136 #include <crypto/cryptodev.h>
148 enum { T_HASH, T_HMAC, T_CIPHER, T_ETA, T_AEAD } type;
149 const EVP_CIPHER *(*evp_cipher)(void);
150 const EVP_MD *(*evp_md)(void);
152 { .name = "sha1", .mac = CRYPTO_SHA1, .type = T_HASH,
153 .evp_md = EVP_sha1 },
154 { .name = "sha224", .mac = CRYPTO_SHA2_224, .type = T_HASH,
155 .evp_md = EVP_sha224 },
156 { .name = "sha256", .mac = CRYPTO_SHA2_256, .type = T_HASH,
157 .evp_md = EVP_sha256 },
158 { .name = "sha384", .mac = CRYPTO_SHA2_384, .type = T_HASH,
159 .evp_md = EVP_sha384 },
160 { .name = "sha512", .mac = CRYPTO_SHA2_512, .type = T_HASH,
161 .evp_md = EVP_sha512 },
162 { .name = "sha1hmac", .mac = CRYPTO_SHA1_HMAC, .type = T_HMAC,
163 .evp_md = EVP_sha1 },
164 { .name = "sha224hmac", .mac = CRYPTO_SHA2_224_HMAC, .type = T_HMAC,
165 .evp_md = EVP_sha224 },
166 { .name = "sha256hmac", .mac = CRYPTO_SHA2_256_HMAC, .type = T_HMAC,
167 .evp_md = EVP_sha256 },
168 { .name = "sha384hmac", .mac = CRYPTO_SHA2_384_HMAC, .type = T_HMAC,
169 .evp_md = EVP_sha384 },
170 { .name = "sha512hmac", .mac = CRYPTO_SHA2_512_HMAC, .type = T_HMAC,
171 .evp_md = EVP_sha512 },
172 { .name = "blake2b", .mac = CRYPTO_BLAKE2B, .type = T_HASH,
173 .evp_md = EVP_blake2b512 },
174 { .name = "blake2s", .mac = CRYPTO_BLAKE2S, .type = T_HASH,
175 .evp_md = EVP_blake2s256 },
176 { .name = "aes-cbc", .cipher = CRYPTO_AES_CBC, .type = T_CIPHER,
177 .evp_cipher = EVP_aes_128_cbc },
178 { .name = "aes-cbc192", .cipher = CRYPTO_AES_CBC, .type = T_CIPHER,
179 .evp_cipher = EVP_aes_192_cbc },
180 { .name = "aes-cbc256", .cipher = CRYPTO_AES_CBC, .type = T_CIPHER,
181 .evp_cipher = EVP_aes_256_cbc },
182 { .name = "aes-ctr", .cipher = CRYPTO_AES_ICM, .type = T_CIPHER,
183 .evp_cipher = EVP_aes_128_ctr },
184 { .name = "aes-ctr192", .cipher = CRYPTO_AES_ICM, .type = T_CIPHER,
185 .evp_cipher = EVP_aes_192_ctr },
186 { .name = "aes-ctr256", .cipher = CRYPTO_AES_ICM, .type = T_CIPHER,
187 .evp_cipher = EVP_aes_256_ctr },
188 { .name = "aes-xts", .cipher = CRYPTO_AES_XTS, .type = T_CIPHER,
189 .evp_cipher = EVP_aes_128_xts },
190 { .name = "aes-xts256", .cipher = CRYPTO_AES_XTS, .type = T_CIPHER,
191 .evp_cipher = EVP_aes_256_xts },
192 { .name = "chacha20", .cipher = CRYPTO_CHACHA20, .type = T_CIPHER,
193 .evp_cipher = EVP_chacha20 },
194 { .name = "aes-gcm", .cipher = CRYPTO_AES_NIST_GCM_16,
195 .mac = CRYPTO_AES_128_NIST_GMAC, .type = T_AEAD,
196 .evp_cipher = EVP_aes_128_gcm },
197 { .name = "aes-gcm192", .cipher = CRYPTO_AES_NIST_GCM_16,
198 .mac = CRYPTO_AES_192_NIST_GMAC, .type = T_AEAD,
199 .evp_cipher = EVP_aes_192_gcm },
200 { .name = "aes-gcm256", .cipher = CRYPTO_AES_NIST_GCM_16,
201 .mac = CRYPTO_AES_256_NIST_GMAC, .type = T_AEAD,
202 .evp_cipher = EVP_aes_256_gcm },
203 { .name = "aes-ccm", .cipher = CRYPTO_AES_CCM_16,
204 .mac = CRYPTO_AES_CCM_CBC_MAC, .type = T_AEAD,
205 .evp_cipher = EVP_aes_128_ccm },
206 { .name = "aes-ccm192", .cipher = CRYPTO_AES_CCM_16,
207 .mac = CRYPTO_AES_CCM_CBC_MAC, .type = T_AEAD,
208 .evp_cipher = EVP_aes_192_ccm },
209 { .name = "aes-ccm256", .cipher = CRYPTO_AES_CCM_16,
210 .mac = CRYPTO_AES_CCM_CBC_MAC, .type = T_AEAD,
211 .evp_cipher = EVP_aes_256_ccm },
216 static size_t aad_len;
222 "usage: cryptocheck [-z] [-a algorithm] [-d dev] [size ...]\n");
226 static const struct alg *
227 find_alg(const char *name)
231 for (i = 0; i < nitems(algs); i++)
232 if (strcasecmp(algs[i].name, name) == 0)
238 build_eta(const struct alg *cipher, const struct alg *mac)
243 assert(cipher->type == T_CIPHER);
244 assert(mac->type == T_HMAC);
245 eta = calloc(1, sizeof(*eta));
246 asprintf(&name, "%s+%s", cipher->name, mac->name);
248 eta->cipher = cipher->cipher;
251 eta->evp_cipher = cipher->evp_cipher;
252 eta->evp_md = mac->evp_md;
257 free_eta(struct alg *eta)
259 free(__DECONST(char *, eta->name));
264 build_eta_name(const char *name)
266 const struct alg *cipher, *mac;
267 const char *mac_name;
268 char *cp, *cipher_name;
270 cp = strchr(name, '+');
271 cipher_name = strndup(name, cp - name);
273 cipher = find_alg(cipher_name);
275 if (cipher == NULL || cipher->type != T_CIPHER)
276 errx(1, "Invalid cipher %s", cipher_name);
277 mac = find_alg(mac_name);
278 if (mac == NULL || mac->type != T_HMAC)
279 errx(1, "Invalid hmac %s", mac_name);
280 return (build_eta(cipher, mac));
289 fd = open("/dev/crypto", O_RDWR | O_CLOEXEC, 0);
291 err(1, "/dev/crypto");
297 * Called on exit to change kern.cryptodevallowsoft back to 0
299 #define CRYPT_SOFT_ALLOW "kern.cryptodevallowsoft"
302 reset_user_soft(void)
305 sysctlbyname(CRYPT_SOFT_ALLOW, NULL, NULL, &off, sizeof(off));
309 enable_user_soft(void)
313 size_t cursize = sizeof(curstate);
315 if (sysctlbyname(CRYPT_SOFT_ALLOW, &curstate, &cursize,
316 &on, sizeof(on)) == 0) {
318 atexit(reset_user_soft);
323 crlookup(const char *devname)
325 struct crypt_find_op find;
327 if (strncmp(devname, "soft", 4) == 0) {
329 return CRYPTO_FLAG_SOFTWARE;
333 strlcpy(find.name, devname, sizeof(find.name));
334 if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1)
335 err(1, "ioctl(CIOCFINDDEV)");
342 static struct crypt_find_op find;
344 if (crid == CRYPTO_FLAG_SOFTWARE)
346 else if (crid == CRYPTO_FLAG_HARDWARE)
349 bzero(&find, sizeof(find));
351 if (ioctl(devcrypto(), CRIOFINDDEV, &find) == -1)
352 err(1, "ioctl(CIOCFINDDEV): crid %d", crid);
361 if (ioctl(devcrypto(), CRIOGET, &fd) == -1)
362 err(1, "ioctl(CRIOGET)");
363 if (fcntl(fd, F_SETFD, 1) == -1)
364 err(1, "fcntl(F_SETFD) (crget)");
372 0x10,0x54,0x11,0x48,0x45,0x12,0x4f,0x13,0x49,0x53,0x14,0x41,
373 0x15,0x16,0x4e,0x55,0x54,0x17,0x18,0x4a,0x4f,0x42,0x19,0x01
375 return 0x20+a[random()%nitems(a)];
379 alloc_buffer(size_t len)
385 for (i = 0; i < len; i++)
391 generate_iv(size_t len, const struct alg *alg)
395 iv = alloc_buffer(len);
396 switch (alg->cipher) {
398 /* Clear the low 32 bits of the IV to hold the counter. */
406 * Clear the low 64-bits to only store a 64-bit block
423 ocf_init_sop(struct session2_op *sop)
425 memset(sop, 0, sizeof(*sop));
430 ocf_init_session(struct session2_op *sop, const char *type, const char *name,
431 struct ocf_session *ses)
436 if (ioctl(fd, CIOCGSESSION2, sop) < 0) {
437 warn("cryptodev %s %s not supported for device %s",
438 type, name, crfind(crid));
445 ses->crid = sop->crid;
450 ocf_destroy_session(struct ocf_session *ses)
455 if (ioctl(ses->fd, CIOCFSESSION, &ses->ses) < 0)
456 warn("ioctl(CIOCFSESSION)");
462 ocf_init_cop(const struct ocf_session *ses, struct crypt_op *cop)
464 memset(cop, 0, sizeof(*cop));
469 ocf_init_caead(const struct ocf_session *ses, struct crypt_aead *caead)
471 memset(caead, 0, sizeof(*caead));
472 caead->ses = ses->ses;
476 ocf_hash(const struct alg *alg, const char *buffer, size_t size, char *digest,
479 struct ocf_session ses;
480 struct session2_op sop;
486 if (!ocf_init_session(&sop, "HASH", alg->name, &ses))
489 ocf_init_cop(&ses, &cop);
492 cop.src = (char *)buffer;
495 if (ioctl(ses.fd, CIOCCRYPT, &cop) < 0) {
496 warn("cryptodev %s (%zu) HASH failed for device %s", alg->name,
498 ocf_destroy_session(&ses);
503 ocf_destroy_session(&ses);
508 openssl_hash(const struct alg *alg, const EVP_MD *md, const void *buffer,
509 size_t size, void *digest_out, unsigned *digest_sz_out)
517 mdctx = EVP_MD_CTX_create();
521 rc = EVP_DigestInit_ex(mdctx, md, NULL);
525 rc = EVP_DigestUpdate(mdctx, buffer, size);
529 rc = EVP_DigestFinal_ex(mdctx, digest_out, digest_sz_out);
533 EVP_MD_CTX_destroy(mdctx);
537 errx(1, "OpenSSL %s HASH failed%s: %s", alg->name, errs,
538 ERR_error_string(ERR_get_error(), NULL));
542 run_hash_test(const struct alg *alg, size_t size)
548 char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE];
550 memset(control_digest, 0x3c, sizeof(control_digest));
551 memset(test_digest, 0x3c, sizeof(test_digest));
554 assert(EVP_MD_size(md) <= sizeof(control_digest));
556 buffer = alloc_buffer(size);
559 digest_len = sizeof(control_digest);
560 openssl_hash(alg, md, buffer, size, control_digest, &digest_len);
562 /* cryptodev HASH. */
563 if (!ocf_hash(alg, buffer, size, test_digest, &crid))
565 if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
566 if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
567 printf("%s (%zu) mismatch in trailer:\n",
570 printf("%s (%zu) mismatch:\n", alg->name, size);
571 printf("control:\n");
572 hexdump(control_digest, sizeof(control_digest), NULL, 0);
573 printf("test (cryptodev device %s):\n", crfind(crid));
574 hexdump(test_digest, sizeof(test_digest), NULL, 0);
579 printf("%s (%zu) matched (cryptodev device %s)\n",
580 alg->name, size, crfind(crid));
587 ocf_hmac(const struct alg *alg, const char *buffer, size_t size,
588 const char *key, size_t key_len, char *digest, int *cridp)
590 struct ocf_session ses;
591 struct session2_op sop;
595 sop.mackeylen = key_len;
596 sop.mackey = (char *)key;
598 if (!ocf_init_session(&sop, "HMAC", alg->name, &ses))
601 ocf_init_cop(&ses, &cop);
604 cop.src = (char *)buffer;
607 if (ioctl(ses.fd, CIOCCRYPT, &cop) < 0) {
608 warn("cryptodev %s (%zu) HMAC failed for device %s", alg->name,
610 ocf_destroy_session(&ses);
615 ocf_destroy_session(&ses);
620 run_hmac_test(const struct alg *alg, size_t size)
624 u_int key_len, digest_len;
626 char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE];
628 memset(control_digest, 0x3c, sizeof(control_digest));
629 memset(test_digest, 0x3c, sizeof(test_digest));
632 key_len = EVP_MD_size(md);
633 assert(EVP_MD_size(md) <= sizeof(control_digest));
635 key = alloc_buffer(key_len);
636 buffer = alloc_buffer(size);
639 digest_len = sizeof(control_digest);
640 if (HMAC(md, key, key_len, (u_char *)buffer, size,
641 (u_char *)control_digest, &digest_len) == NULL)
642 errx(1, "OpenSSL %s (%zu) HMAC failed: %s", alg->name,
643 size, ERR_error_string(ERR_get_error(), NULL));
645 /* cryptodev HMAC. */
646 if (!ocf_hmac(alg, buffer, size, key, key_len, test_digest, &crid))
648 if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
649 if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
650 printf("%s (%zu) mismatch in trailer:\n",
653 printf("%s (%zu) mismatch:\n", alg->name, size);
654 printf("control:\n");
655 hexdump(control_digest, sizeof(control_digest), NULL, 0);
656 printf("test (cryptodev device %s):\n", crfind(crid));
657 hexdump(test_digest, sizeof(test_digest), NULL, 0);
662 printf("%s (%zu) matched (cryptodev device %s)\n",
663 alg->name, size, crfind(crid));
671 openssl_cipher(const struct alg *alg, const EVP_CIPHER *cipher, const char *key,
672 const char *iv, const char *input, char *output, size_t size, int enc)
677 ctx = EVP_CIPHER_CTX_new();
679 errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
680 size, ERR_error_string(ERR_get_error(), NULL));
681 if (EVP_CipherInit_ex(ctx, cipher, NULL, (const u_char *)key,
682 (const u_char *)iv, enc) != 1)
683 errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
684 size, ERR_error_string(ERR_get_error(), NULL));
685 EVP_CIPHER_CTX_set_padding(ctx, 0);
686 if (EVP_CipherUpdate(ctx, (u_char *)output, &outl,
687 (const u_char *)input, size) != 1)
688 errx(1, "OpenSSL %s (%zu) cipher update failed: %s", alg->name,
689 size, ERR_error_string(ERR_get_error(), NULL));
691 if (EVP_CipherFinal_ex(ctx, (u_char *)output + outl, &outl) != 1)
692 errx(1, "OpenSSL %s (%zu) cipher final failed: %s", alg->name,
693 size, ERR_error_string(ERR_get_error(), NULL));
696 errx(1, "OpenSSL %s (%zu) cipher size mismatch: %d", alg->name,
698 EVP_CIPHER_CTX_free(ctx);
702 ocf_init_cipher_session(const struct alg *alg, const char *key, size_t key_len,
703 struct ocf_session *ses)
705 struct session2_op sop;
708 sop.keylen = key_len;
709 sop.key = (char *)key;
710 sop.cipher = alg->cipher;
711 return (ocf_init_session(&sop, "cipher", alg->name, ses));
715 ocf_cipher(const struct ocf_session *ses, const struct alg *alg, const char *iv,
716 const char *input, char *output, size_t size, int op)
720 ocf_init_cop(ses, &cop);
723 cop.src = (char *)input;
727 if (ioctl(ses->fd, CIOCCRYPT, &cop) < 0) {
728 warn("cryptodev %s (%zu) cipher failed for device %s",
729 alg->name, size, crfind(crid));
737 run_cipher_test(const struct alg *alg, size_t size)
739 struct ocf_session ses;
740 const EVP_CIPHER *cipher;
741 char *buffer, *cleartext, *ciphertext;
743 u_int iv_len, key_len;
745 cipher = alg->evp_cipher();
746 if (size % EVP_CIPHER_block_size(cipher) != 0) {
749 "%s (%zu): invalid buffer size (block size %d)\n",
750 alg->name, size, EVP_CIPHER_block_size(cipher));
754 key_len = EVP_CIPHER_key_length(cipher);
755 iv_len = EVP_CIPHER_iv_length(cipher);
757 key = alloc_buffer(key_len);
758 iv = generate_iv(iv_len, alg);
759 cleartext = alloc_buffer(size);
760 buffer = malloc(size);
761 ciphertext = malloc(size);
763 /* OpenSSL cipher. */
764 openssl_cipher(alg, cipher, key, iv, cleartext, ciphertext, size, 1);
765 if (size > 0 && memcmp(cleartext, ciphertext, size) == 0)
766 errx(1, "OpenSSL %s (%zu): cipher text unchanged", alg->name,
768 openssl_cipher(alg, cipher, key, iv, ciphertext, buffer, size, 0);
769 if (memcmp(cleartext, buffer, size) != 0) {
770 printf("OpenSSL %s (%zu): cipher mismatch:", alg->name, size);
771 printf("original:\n");
772 hexdump(cleartext, size, NULL, 0);
773 printf("decrypted:\n");
774 hexdump(buffer, size, NULL, 0);
778 if (!ocf_init_cipher_session(alg, key, key_len, &ses))
782 if (!ocf_cipher(&ses, alg, iv, cleartext, buffer, size, COP_ENCRYPT))
784 if (memcmp(ciphertext, buffer, size) != 0) {
785 printf("%s (%zu) encryption mismatch:\n", alg->name, size);
786 printf("control:\n");
787 hexdump(ciphertext, size, NULL, 0);
788 printf("test (cryptodev device %s):\n", crfind(ses.crid));
789 hexdump(buffer, size, NULL, 0);
794 if (!ocf_cipher(&ses, alg, iv, ciphertext, buffer, size, COP_DECRYPT))
796 if (memcmp(cleartext, buffer, size) != 0) {
797 printf("%s (%zu) decryption mismatch:\n", alg->name, size);
798 printf("control:\n");
799 hexdump(cleartext, size, NULL, 0);
800 printf("test (cryptodev device %s):\n", crfind(ses.crid));
801 hexdump(buffer, size, NULL, 0);
806 printf("%s (%zu) matched (cryptodev device %s)\n",
807 alg->name, size, crfind(ses.crid));
810 ocf_destroy_session(&ses);
819 ocf_init_eta_session(const struct alg *alg, const char *cipher_key,
820 size_t cipher_key_len, const char *auth_key, size_t auth_key_len,
821 struct ocf_session *ses)
823 struct session2_op sop;
826 sop.keylen = cipher_key_len;
827 sop.key = (char *)cipher_key;
828 sop.cipher = alg->cipher;
829 sop.mackeylen = auth_key_len;
830 sop.mackey = (char *)auth_key;
832 return (ocf_init_session(&sop, "ETA", alg->name, ses));
836 ocf_eta(const struct ocf_session *ses, const struct alg *alg, const char *iv,
837 size_t iv_len, const char *aad, size_t aad_len, const char *input,
838 char *output, size_t size, char *digest, int op)
843 struct crypt_aead caead;
845 ocf_init_caead(ses, &caead);
847 caead.flags = op == COP_ENCRYPT ? COP_F_CIPHER_FIRST : 0;
849 caead.aadlen = aad_len;
850 caead.ivlen = iv_len;
851 caead.src = (char *)input;
853 caead.aad = (char *)aad;
855 caead.iv = (char *)iv;
857 ret = ioctl(ses->fd, CIOCCRYPTAEAD, &caead);
861 ocf_init_cop(ses, &cop);
863 cop.flags = op == COP_ENCRYPT ? COP_F_CIPHER_FIRST : 0;
865 cop.src = (char *)input;
870 ret = ioctl(ses->fd, CIOCCRYPT, &cop);
874 warn("cryptodev %s (%zu) ETA failed for device %s",
875 alg->name, size, crfind(crid));
883 run_eta_test(const struct alg *alg, size_t size)
885 struct ocf_session ses;
886 const EVP_CIPHER *cipher;
888 char *aad, *buffer, *cleartext, *ciphertext;
889 char *iv, *auth_key, *cipher_key;
890 u_int i, iv_len, auth_key_len, cipher_key_len, digest_len;
891 char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE];
893 cipher = alg->evp_cipher();
894 if (size % EVP_CIPHER_block_size(cipher) != 0) {
897 "%s (%zu): invalid buffer size (block size %d)\n",
898 alg->name, size, EVP_CIPHER_block_size(cipher));
902 memset(control_digest, 0x3c, sizeof(control_digest));
903 memset(test_digest, 0x3c, sizeof(test_digest));
907 cipher_key_len = EVP_CIPHER_key_length(cipher);
908 iv_len = EVP_CIPHER_iv_length(cipher);
909 auth_key_len = EVP_MD_size(md);
911 cipher_key = alloc_buffer(cipher_key_len);
912 iv = generate_iv(iv_len, alg);
913 auth_key = alloc_buffer(auth_key_len);
914 cleartext = alloc_buffer(aad_len + size);
915 buffer = malloc(aad_len + size);
916 ciphertext = malloc(aad_len + size);
918 /* OpenSSL encrypt + HMAC. */
920 memcpy(ciphertext, cleartext, aad_len);
921 openssl_cipher(alg, cipher, cipher_key, iv, cleartext + aad_len,
922 ciphertext + aad_len, size, 1);
923 if (size > 0 && memcmp(cleartext + aad_len, ciphertext + aad_len,
925 errx(1, "OpenSSL %s (%zu): cipher text unchanged", alg->name,
927 digest_len = sizeof(control_digest);
928 if (HMAC(md, auth_key, auth_key_len, (u_char *)ciphertext,
929 aad_len + size, (u_char *)control_digest, &digest_len) == NULL)
930 errx(1, "OpenSSL %s (%zu) HMAC failed: %s", alg->name,
931 size, ERR_error_string(ERR_get_error(), NULL));
933 if (!ocf_init_eta_session(alg, cipher_key, cipher_key_len, auth_key,
937 /* OCF encrypt + HMAC. */
938 if (!ocf_eta(&ses, alg, iv, iv_len,
939 aad_len != 0 ? cleartext : NULL, aad_len, cleartext + aad_len,
940 buffer + aad_len, size, test_digest, COP_ENCRYPT))
942 if (memcmp(ciphertext + aad_len, buffer + aad_len, size) != 0) {
943 printf("%s (%zu) encryption mismatch:\n", alg->name, size);
944 printf("control:\n");
945 hexdump(ciphertext + aad_len, size, NULL, 0);
946 printf("test (cryptodev device %s):\n", crfind(ses.crid));
947 hexdump(buffer + aad_len, size, NULL, 0);
950 if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
951 if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
952 printf("%s (%zu) enc hash mismatch in trailer:\n",
955 printf("%s (%zu) enc hash mismatch:\n", alg->name,
957 printf("control:\n");
958 hexdump(control_digest, sizeof(control_digest), NULL, 0);
959 printf("test (cryptodev device %s):\n", crfind(ses.crid));
960 hexdump(test_digest, sizeof(test_digest), NULL, 0);
964 /* OCF HMAC + decrypt. */
965 if (!ocf_eta(&ses, alg, iv, iv_len,
966 aad_len != 0 ? ciphertext : NULL, aad_len, ciphertext + aad_len,
967 buffer + aad_len, size, test_digest, COP_DECRYPT))
969 if (memcmp(cleartext + aad_len, buffer + aad_len, size) != 0) {
970 printf("%s (%zu) decryption mismatch:\n", alg->name, size);
971 printf("control:\n");
972 hexdump(cleartext, size, NULL, 0);
973 printf("test (cryptodev device %s):\n", crfind(ses.crid));
974 hexdump(buffer, size, NULL, 0);
979 printf("%s (%zu) matched (cryptodev device %s)\n",
980 alg->name, size, crfind(ses.crid));
983 ocf_destroy_session(&ses);
993 openssl_gcm_encrypt(const struct alg *alg, const EVP_CIPHER *cipher,
994 const char *key, const char *iv, const char *aad, size_t aad_len,
995 const char *input, char *output, size_t size, char *tag)
1000 ctx = EVP_CIPHER_CTX_new();
1002 errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
1003 size, ERR_error_string(ERR_get_error(), NULL));
1004 if (EVP_EncryptInit_ex(ctx, cipher, NULL, (const u_char *)key,
1005 (const u_char *)iv) != 1)
1006 errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
1007 size, ERR_error_string(ERR_get_error(), NULL));
1008 EVP_CIPHER_CTX_set_padding(ctx, 0);
1010 if (EVP_EncryptUpdate(ctx, NULL, &outl, (const u_char *)aad,
1012 errx(1, "OpenSSL %s (%zu) aad update failed: %s",
1014 ERR_error_string(ERR_get_error(), NULL));
1016 if (EVP_EncryptUpdate(ctx, (u_char *)output, &outl,
1017 (const u_char *)input, size) != 1)
1018 errx(1, "OpenSSL %s (%zu) encrypt update failed: %s", alg->name,
1019 size, ERR_error_string(ERR_get_error(), NULL));
1021 if (EVP_EncryptFinal_ex(ctx, (u_char *)output + outl, &outl) != 1)
1022 errx(1, "OpenSSL %s (%zu) encrypt final failed: %s", alg->name,
1023 size, ERR_error_string(ERR_get_error(), NULL));
1026 errx(1, "OpenSSL %s (%zu) encrypt size mismatch: %d", alg->name,
1028 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, AES_GMAC_HASH_LEN,
1030 errx(1, "OpenSSL %s (%zu) get tag failed: %s", alg->name,
1031 size, ERR_error_string(ERR_get_error(), NULL));
1032 EVP_CIPHER_CTX_free(ctx);
1037 openssl_gcm_decrypt(const struct alg *alg, const EVP_CIPHER *cipher,
1038 const char *key, const char *iv, const char *aad, size_t aad_len,
1039 const char *input, char *output, size_t size, char *tag)
1041 EVP_CIPHER_CTX *ctx;
1045 ctx = EVP_CIPHER_CTX_new();
1047 errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
1048 size, ERR_error_string(ERR_get_error(), NULL));
1049 if (EVP_DecryptInit_ex(ctx, cipher, NULL, (const u_char *)key,
1050 (const u_char *)iv) != 1)
1051 errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
1052 size, ERR_error_string(ERR_get_error(), NULL));
1053 EVP_CIPHER_CTX_set_padding(ctx, 0);
1055 if (EVP_DecryptUpdate(ctx, NULL, &outl, (const u_char *)aad,
1057 errx(1, "OpenSSL %s (%zu) aad update failed: %s",
1059 ERR_error_string(ERR_get_error(), NULL));
1061 if (EVP_DecryptUpdate(ctx, (u_char *)output, &outl,
1062 (const u_char *)input, size) != 1)
1063 errx(1, "OpenSSL %s (%zu) decrypt update failed: %s", alg->name,
1064 size, ERR_error_string(ERR_get_error(), NULL));
1066 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AES_GMAC_HASH_LEN,
1068 errx(1, "OpenSSL %s (%zu) get tag failed: %s", alg->name,
1069 size, ERR_error_string(ERR_get_error(), NULL));
1070 valid = (EVP_DecryptFinal_ex(ctx, (u_char *)output + outl, &outl) != 1);
1073 errx(1, "OpenSSL %s (%zu) decrypt size mismatch: %d", alg->name,
1075 EVP_CIPHER_CTX_free(ctx);
1081 openssl_ccm_encrypt(const struct alg *alg, const EVP_CIPHER *cipher,
1082 const char *key, const char *iv, size_t iv_len, const char *aad,
1083 size_t aad_len, const char *input, char *output, size_t size, char *tag)
1085 EVP_CIPHER_CTX *ctx;
1088 ctx = EVP_CIPHER_CTX_new();
1090 errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name,
1091 size, ERR_error_string(ERR_get_error(), NULL));
1092 if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
1093 errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
1094 size, ERR_error_string(ERR_get_error(), NULL));
1095 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, iv_len, NULL) != 1)
1096 errx(1, "OpenSSL %s (%zu) setting iv length failed: %s", alg->name,
1097 size, ERR_error_string(ERR_get_error(), NULL));
1098 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, AES_CBC_MAC_HASH_LEN, NULL) != 1)
1099 errx(1, "OpenSSL %s (%zu) setting tag length failed: %s", alg->name,
1100 size, ERR_error_string(ERR_get_error(), NULL));
1101 if (EVP_EncryptInit_ex(ctx, NULL, NULL, (const u_char *)key,
1102 (const u_char *)iv) != 1)
1103 errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name,
1104 size, ERR_error_string(ERR_get_error(), NULL));
1105 if (EVP_EncryptUpdate(ctx, NULL, &outl, NULL, size) != 1)
1106 errx(1, "OpenSSL %s (%zu) unable to set data length: %s", alg->name,
1107 size, ERR_error_string(ERR_get_error(), NULL));
1110 if (EVP_EncryptUpdate(ctx, NULL, &outl, (const u_char *)aad,
1112 errx(1, "OpenSSL %s (%zu) aad update failed: %s",
1114 ERR_error_string(ERR_get_error(), NULL));
1116 if (EVP_EncryptUpdate(ctx, (u_char *)output, &outl,
1117 (const u_char *)input, size) != 1)
1118 errx(1, "OpenSSL %s (%zu) encrypt update failed: %s", alg->name,
1119 size, ERR_error_string(ERR_get_error(), NULL));
1121 if (EVP_EncryptFinal_ex(ctx, (u_char *)output + outl, &outl) != 1)
1122 errx(1, "OpenSSL %s (%zu) encrypt final failed: %s", alg->name,
1123 size, ERR_error_string(ERR_get_error(), NULL));
1126 errx(1, "OpenSSL %s (%zu) encrypt size mismatch: %d", alg->name,
1128 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, AES_CBC_MAC_HASH_LEN,
1130 errx(1, "OpenSSL %s (%zu) get tag failed: %s", alg->name,
1131 size, ERR_error_string(ERR_get_error(), NULL));
1132 EVP_CIPHER_CTX_free(ctx);
1136 ocf_init_aead_session(const struct alg *alg, const char *key, size_t key_len,
1137 struct ocf_session *ses)
1139 struct session2_op sop;
1142 sop.keylen = key_len;
1143 sop.key = (char *)key;
1144 sop.cipher = alg->cipher;
1145 sop.mackeylen = key_len;
1146 sop.mackey = (char *)key;
1148 return (ocf_init_session(&sop, "AEAD", alg->name, ses));
1152 ocf_aead(const struct ocf_session *ses, const struct alg *alg, const char *iv,
1153 size_t iv_len, const char *aad, size_t aad_len, const char *input,
1154 char *output, size_t size, char *tag, int op)
1156 struct crypt_aead caead;
1158 ocf_init_caead(ses, &caead);
1161 caead.aadlen = aad_len;
1162 caead.ivlen = iv_len;
1163 caead.src = (char *)input;
1165 caead.aad = (char *)aad;
1167 caead.iv = (char *)iv;
1169 if (ioctl(ses->fd, CIOCCRYPTAEAD, &caead) < 0)
1174 #define AEAD_MAX_TAG_LEN MAX(AES_GMAC_HASH_LEN, AES_CBC_MAC_HASH_LEN)
1177 run_aead_test(const struct alg *alg, size_t size)
1179 struct ocf_session ses;
1180 const EVP_CIPHER *cipher;
1181 char *aad, *buffer, *cleartext, *ciphertext;
1183 u_int iv_len, key_len;
1185 char control_tag[AEAD_MAX_TAG_LEN], test_tag[AEAD_MAX_TAG_LEN];
1187 cipher = alg->evp_cipher();
1188 if (size % EVP_CIPHER_block_size(cipher) != 0) {
1191 "%s (%zu): invalid buffer size (block size %d)\n",
1192 alg->name, size, EVP_CIPHER_block_size(cipher));
1196 memset(control_tag, 0x3c, sizeof(control_tag));
1197 memset(test_tag, 0x3c, sizeof(test_tag));
1199 key_len = EVP_CIPHER_key_length(cipher);
1200 iv_len = EVP_CIPHER_iv_length(cipher);
1203 * AES-CCM can have varying IV lengths; however, for the moment
1204 * we only support AES_CCM_IV_LEN (12). So if the sizes are
1205 * different, we'll fail.
1207 if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE &&
1208 iv_len != AES_CCM_IV_LEN) {
1210 printf("OpenSSL CCM IV length (%d) != AES_CCM_IV_LEN",
1215 key = alloc_buffer(key_len);
1216 iv = generate_iv(iv_len, alg);
1217 cleartext = alloc_buffer(size);
1218 buffer = malloc(size);
1219 ciphertext = malloc(size);
1221 aad = alloc_buffer(aad_len);
1225 /* OpenSSL encrypt */
1226 if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE)
1227 openssl_ccm_encrypt(alg, cipher, key, iv, iv_len, aad,
1228 aad_len, cleartext, ciphertext, size, control_tag);
1230 openssl_gcm_encrypt(alg, cipher, key, iv, aad, aad_len,
1231 cleartext, ciphertext, size, control_tag);
1233 if (!ocf_init_aead_session(alg, key, key_len, &ses))
1237 error = ocf_aead(&ses, alg, iv, iv_len, aad, aad_len, cleartext, buffer,
1238 size, test_tag, COP_ENCRYPT);
1240 warnc(error, "cryptodev %s (%zu) failed for device %s",
1241 alg->name, size, crfind(ses.crid));
1244 if (memcmp(ciphertext, buffer, size) != 0) {
1245 printf("%s (%zu) encryption mismatch:\n", alg->name, size);
1246 printf("control:\n");
1247 hexdump(ciphertext, size, NULL, 0);
1248 printf("test (cryptodev device %s):\n", crfind(crid));
1249 hexdump(buffer, size, NULL, 0);
1252 if (memcmp(control_tag, test_tag, sizeof(control_tag)) != 0) {
1253 printf("%s (%zu) enc tag mismatch:\n", alg->name, size);
1254 printf("control:\n");
1255 hexdump(control_tag, sizeof(control_tag), NULL, 0);
1256 printf("test (cryptodev device %s):\n", crfind(crid));
1257 hexdump(test_tag, sizeof(test_tag), NULL, 0);
1262 error = ocf_aead(&ses, alg, iv, iv_len, aad, aad_len, ciphertext,
1263 buffer, size, control_tag, COP_DECRYPT);
1265 warnc(error, "cryptodev %s (%zu) failed for device %s",
1266 alg->name, size, crfind(ses.crid));
1269 if (memcmp(cleartext, buffer, size) != 0) {
1270 printf("%s (%zu) decryption mismatch:\n", alg->name, size);
1271 printf("control:\n");
1272 hexdump(cleartext, size, NULL, 0);
1273 printf("test (cryptodev device %s):\n", crfind(crid));
1274 hexdump(buffer, size, NULL, 0);
1278 /* Verify OCF decrypt fails with busted tag. */
1280 error = ocf_aead(&ses, alg, iv, iv_len, aad, aad_len, ciphertext,
1281 buffer, size, test_tag, COP_DECRYPT);
1282 if (error != EBADMSG) {
1285 "cryptodev %s (%zu) corrupt tag failed for device %s",
1286 alg->name, size, crfind(ses.crid));
1289 "cryptodev %s (%zu) corrupt tag didn't fail for device %s",
1290 alg->name, size, crfind(ses.crid));
1295 printf("%s (%zu) matched (cryptodev device %s)\n",
1296 alg->name, size, crfind(ses.crid));
1299 ocf_destroy_session(&ses);
1309 run_test(const struct alg *alg, size_t size)
1312 switch (alg->type) {
1314 run_hash_test(alg, size);
1317 run_hmac_test(alg, size);
1320 run_cipher_test(alg, size);
1323 run_eta_test(alg, size);
1326 run_aead_test(alg, size);
1332 run_test_sizes(const struct alg *alg, size_t *sizes, u_int nsizes)
1336 for (i = 0; i < nsizes; i++)
1337 run_test(alg, sizes[i]);
1341 run_hash_tests(size_t *sizes, u_int nsizes)
1345 for (i = 0; i < nitems(algs); i++)
1346 if (algs[i].type == T_HASH)
1347 run_test_sizes(&algs[i], sizes, nsizes);
1351 run_mac_tests(size_t *sizes, u_int nsizes)
1355 for (i = 0; i < nitems(algs); i++)
1356 if (algs[i].type == T_HMAC)
1357 run_test_sizes(&algs[i], sizes, nsizes);
1361 run_cipher_tests(size_t *sizes, u_int nsizes)
1365 for (i = 0; i < nitems(algs); i++)
1366 if (algs[i].type == T_CIPHER)
1367 run_test_sizes(&algs[i], sizes, nsizes);
1371 run_eta_tests(size_t *sizes, u_int nsizes)
1373 const struct alg *cipher, *mac;
1377 for (i = 0; i < nitems(algs); i++) {
1379 if (cipher->type != T_CIPHER)
1381 for (j = 0; j < nitems(algs); j++) {
1383 if (mac->type != T_HMAC)
1385 eta = build_eta(cipher, mac);
1386 run_test_sizes(eta, sizes, nsizes);
1393 run_aead_tests(size_t *sizes, u_int nsizes)
1397 for (i = 0; i < nitems(algs); i++)
1398 if (algs[i].type == T_AEAD)
1399 run_test_sizes(&algs[i], sizes, nsizes);
1403 main(int ac, char **av)
1405 const char *algname;
1406 const struct alg *alg;
1414 crid = CRYPTO_FLAG_HARDWARE;
1417 while ((ch = getopt(ac, av, "A:a:d:vz")) != -1)
1420 aad_len = atoi(optarg);
1426 crid = crlookup(optarg);
1443 if (nsizes >= nitems(sizes)) {
1444 warnx("Too many sizes, ignoring extras");
1447 sizes[nsizes] = strtol(av[0], &cp, 0);
1449 errx(1, "Bad size %s", av[0]);
1455 if (algname == NULL)
1456 errx(1, "Algorithm required");
1461 while (sizes[nsizes - 1] * 2 < 240 * 1024) {
1462 assert(nsizes < nitems(sizes));
1463 sizes[nsizes] = sizes[nsizes - 1] * 2;
1466 if (sizes[nsizes - 1] < 240 * 1024) {
1467 assert(nsizes < nitems(sizes));
1468 sizes[nsizes] = 240 * 1024;
1474 if (strcasecmp(algname, "hash") == 0)
1475 run_hash_tests(sizes, nsizes);
1476 else if (strcasecmp(algname, "mac") == 0)
1477 run_mac_tests(sizes, nsizes);
1478 else if (strcasecmp(algname, "cipher") == 0)
1479 run_cipher_tests(sizes, nsizes);
1480 else if (strcasecmp(algname, "eta") == 0)
1481 run_eta_tests(sizes, nsizes);
1482 else if (strcasecmp(algname, "aead") == 0)
1483 run_aead_tests(sizes, nsizes);
1484 else if (strcasecmp(algname, "all") == 0) {
1485 run_hash_tests(sizes, nsizes);
1486 run_mac_tests(sizes, nsizes);
1487 run_cipher_tests(sizes, nsizes);
1488 run_eta_tests(sizes, nsizes);
1489 run_aead_tests(sizes, nsizes);
1490 } else if (strchr(algname, '+') != NULL) {
1491 eta = build_eta_name(algname);
1492 run_test_sizes(eta, sizes, nsizes);
1495 alg = find_alg(algname);
1497 errx(1, "Invalid algorithm %s", algname);
1498 run_test_sizes(alg, sizes, nsizes);