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