1/*- 2 * Copyright (c) 2017 Chelsio Communications, Inc. 3 * All rights reserved. 4 * Written by: John Baldwin <jhb@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27/*- 28 * Copyright (c) 2004 Sam Leffler, Errno Consulting 29 * All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 1. Redistributions of source code must retain the above copyright 35 * notice, this list of conditions and the following disclaimer, 36 * without modification. 37 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 38 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 39 * redistribution must be conditioned upon including a substantially 40 * similar Disclaimer requirement for further binary redistribution. 41 * 3. Neither the names of the above-listed copyright holders nor the names 42 * of any contributors may be used to endorse or promote products derived 43 * from this software without specific prior written permission. 44 * 45 * NO WARRANTY 46 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 47 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 48 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 49 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 50 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 51 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 54 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 56 * THE POSSIBILITY OF SUCH DAMAGES. 57 * 58 * $FreeBSD: stable/11/tools/tools/crypto/cryptocheck.c 345028 2019-03-11 21:37:58Z jhb $ 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 * 88 * Block Ciphers: 89 * aes-cbc 128-bit aes cbc 90 * aes-cbc192 192-bit aes cbc 91 * aes-cbc256 256-bit aes cbc 92 * aes-ctr 128-bit aes ctr 93 * aes-ctr192 192-bit aes ctr 94 * aes-ctr256 256-bit aes ctr 95 * aes-xts 128-bit aes xts 96 * aes-xts256 256-bit aes xts 97 * 98 * Authenticated Encryption: 99 * <block cipher>+<hmac> 100 * 101 * Authenticated Encryption with Associated Data: 102 * aes-gcm 128-bit aes gcm 103 * aes-gcm192 192-bit aes gcm 104 * aes-gcm256 256-bit aes gcm 105 */ 106 107#include <sys/param.h> 108#include <assert.h> 109#include <err.h> 110#include <fcntl.h> 111#include <libutil.h> 112#include <stdbool.h> 113#include <stdio.h> 114#include <string.h> 115#include <unistd.h> 116 117#include <openssl/err.h> 118#include <openssl/hmac.h> 119 120#include <crypto/cryptodev.h> 121 122/* XXX: Temporary hack */ 123#ifndef COP_F_CIPHER_FIRST 124#define COP_F_CIPHER_FIRST 0x0001 /* Cipher before MAC. */ 125#endif 126 127struct alg { 128 const char *name; 129 int cipher; 130 int mac; 131 enum { T_HMAC, T_BLKCIPHER, T_AUTHENC, T_GCM } type; 132 const EVP_CIPHER *(*evp_cipher)(void); 133 const EVP_MD *(*evp_md)(void); 134} algs[] = { 135 { .name = "sha1", .mac = CRYPTO_SHA1_HMAC, .type = T_HMAC, 136 .evp_md = EVP_sha1 }, 137 { .name = "sha256", .mac = CRYPTO_SHA2_256_HMAC, .type = T_HMAC, 138 .evp_md = EVP_sha256 }, 139 { .name = "sha384", .mac = CRYPTO_SHA2_384_HMAC, .type = T_HMAC, 140 .evp_md = EVP_sha384 }, 141 { .name = "sha512", .mac = CRYPTO_SHA2_512_HMAC, .type = T_HMAC, 142 .evp_md = EVP_sha512 }, 143 { .name = "aes-cbc", .cipher = CRYPTO_AES_CBC, .type = T_BLKCIPHER, 144 .evp_cipher = EVP_aes_128_cbc }, 145 { .name = "aes-cbc192", .cipher = CRYPTO_AES_CBC, .type = T_BLKCIPHER, 146 .evp_cipher = EVP_aes_192_cbc }, 147 { .name = "aes-cbc256", .cipher = CRYPTO_AES_CBC, .type = T_BLKCIPHER, 148 .evp_cipher = EVP_aes_256_cbc }, 149 { .name = "aes-ctr", .cipher = CRYPTO_AES_ICM, .type = T_BLKCIPHER, 150 .evp_cipher = EVP_aes_128_ctr }, 151 { .name = "aes-ctr192", .cipher = CRYPTO_AES_ICM, .type = T_BLKCIPHER, 152 .evp_cipher = EVP_aes_192_ctr }, 153 { .name = "aes-ctr256", .cipher = CRYPTO_AES_ICM, .type = T_BLKCIPHER, 154 .evp_cipher = EVP_aes_256_ctr }, 155 { .name = "aes-xts", .cipher = CRYPTO_AES_XTS, .type = T_BLKCIPHER, 156 .evp_cipher = EVP_aes_128_xts }, 157 { .name = "aes-xts256", .cipher = CRYPTO_AES_XTS, .type = T_BLKCIPHER, 158 .evp_cipher = EVP_aes_256_xts }, 159 { .name = "aes-gcm", .cipher = CRYPTO_AES_NIST_GCM_16, 160 .mac = CRYPTO_AES_128_NIST_GMAC, .type = T_GCM, 161 .evp_cipher = EVP_aes_128_gcm }, 162 { .name = "aes-gcm192", .cipher = CRYPTO_AES_NIST_GCM_16, 163 .mac = CRYPTO_AES_192_NIST_GMAC, .type = T_GCM, 164 .evp_cipher = EVP_aes_192_gcm }, 165 { .name = "aes-gcm256", .cipher = CRYPTO_AES_NIST_GCM_16, 166 .mac = CRYPTO_AES_256_NIST_GMAC, .type = T_GCM, 167 .evp_cipher = EVP_aes_256_gcm }, 168}; 169 170static bool verbose; 171static int crid; 172static size_t aad_len; 173 174static void 175usage(void) 176{ 177 fprintf(stderr, 178 "usage: cryptocheck [-z] [-a algorithm] [-d dev] [size ...]\n"); 179 exit(1); 180} 181 182static struct alg * 183find_alg(const char *name) 184{ 185 u_int i; 186 187 for (i = 0; i < nitems(algs); i++) 188 if (strcasecmp(algs[i].name, name) == 0) 189 return (&algs[i]); 190 return (NULL); 191} 192 193static struct alg * 194build_authenc(struct alg *cipher, struct alg *hmac) 195{ 196 static struct alg authenc; 197 char *name; 198 199 assert(cipher->type == T_BLKCIPHER); 200 assert(hmac->type == T_HMAC); 201 memset(&authenc, 0, sizeof(authenc)); 202 asprintf(&name, "%s+%s", cipher->name, hmac->name); 203 authenc.name = name; 204 authenc.cipher = cipher->cipher; 205 authenc.mac = hmac->mac; 206 authenc.type = T_AUTHENC; 207 authenc.evp_cipher = cipher->evp_cipher; 208 authenc.evp_md = hmac->evp_md; 209 return (&authenc); 210} 211 212static struct alg * 213build_authenc_name(const char *name) 214{ 215 struct alg *cipher, *hmac; 216 const char *hmac_name; 217 char *cp, *cipher_name; 218 219 cp = strchr(name, '+'); 220 cipher_name = strndup(name, cp - name); 221 hmac_name = cp + 1; 222 cipher = find_alg(cipher_name); 223 free(cipher_name); 224 if (cipher == NULL) 225 errx(1, "Invalid cipher %s", cipher_name); 226 hmac = find_alg(hmac_name); 227 if (hmac == NULL) 228 errx(1, "Invalid hash %s", hmac_name); 229 return (build_authenc(cipher, hmac)); 230} 231 232static int 233devcrypto(void) 234{ 235 static int fd = -1; 236 237 if (fd < 0) { 238 fd = open("/dev/crypto", O_RDWR | O_CLOEXEC, 0); 239 if (fd < 0) 240 err(1, "/dev/crypto"); 241 } 242 return (fd); 243} 244 245static int 246crlookup(const char *devname) 247{ 248 struct crypt_find_op find; 249 250 if (strncmp(devname, "soft", 4) == 0) 251 return CRYPTO_FLAG_SOFTWARE; 252 253 find.crid = -1; 254 strlcpy(find.name, devname, sizeof(find.name)); 255 if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) 256 err(1, "ioctl(CIOCFINDDEV)"); 257 return (find.crid); 258} 259 260const char * 261crfind(int crid) 262{ 263 static struct crypt_find_op find; 264 265 if (crid == CRYPTO_FLAG_SOFTWARE) 266 return ("soft"); 267 else if (crid == CRYPTO_FLAG_HARDWARE) 268 return ("unknown"); 269 270 bzero(&find, sizeof(find)); 271 find.crid = crid; 272 if (ioctl(devcrypto(), CRIOFINDDEV, &find) == -1) 273 err(1, "ioctl(CIOCFINDDEV): crid %d", crid); 274 return (find.name); 275} 276 277static int 278crget(void) 279{ 280 int fd; 281 282 if (ioctl(devcrypto(), CRIOGET, &fd) == -1) 283 err(1, "ioctl(CRIOGET)"); 284 if (fcntl(fd, F_SETFD, 1) == -1) 285 err(1, "fcntl(F_SETFD) (crget)"); 286 return fd; 287} 288 289static char 290rdigit(void) 291{ 292 const char a[] = { 293 0x10,0x54,0x11,0x48,0x45,0x12,0x4f,0x13,0x49,0x53,0x14,0x41, 294 0x15,0x16,0x4e,0x55,0x54,0x17,0x18,0x4a,0x4f,0x42,0x19,0x01 295 }; 296 return 0x20+a[random()%nitems(a)]; 297} 298 299static char * 300alloc_buffer(size_t len) 301{ 302 char *buf; 303 size_t i; 304 305 buf = malloc(len); 306 for (i = 0; i < len; i++) 307 buf[i] = rdigit(); 308 return (buf); 309} 310 311static char * 312generate_iv(size_t len, struct alg *alg) 313{ 314 char *iv; 315 316 iv = alloc_buffer(len); 317 switch (alg->cipher) { 318 case CRYPTO_AES_ICM: 319 /* Clear the low 32 bits of the IV to hold the counter. */ 320 iv[len - 4] = 0; 321 iv[len - 3] = 0; 322 iv[len - 2] = 0; 323 iv[len - 1] = 0; 324 break; 325 case CRYPTO_AES_XTS: 326 /* 327 * Clear the low 64-bits to only store a 64-bit block 328 * number. 329 */ 330 iv[len - 8] = 0; 331 iv[len - 7] = 0; 332 iv[len - 6] = 0; 333 iv[len - 5] = 0; 334 iv[len - 4] = 0; 335 iv[len - 3] = 0; 336 iv[len - 2] = 0; 337 iv[len - 1] = 0; 338 break; 339 } 340 return (iv); 341} 342 343static bool 344ocf_hmac(struct alg *alg, const char *buffer, size_t size, const char *key, 345 size_t key_len, char *digest, int *cridp) 346{ 347 struct session2_op sop; 348 struct crypt_op cop; 349 int fd; 350 351 memset(&sop, 0, sizeof(sop)); 352 memset(&cop, 0, sizeof(cop)); 353 sop.crid = crid; 354 sop.mackeylen = key_len; 355 sop.mackey = (char *)key; 356 sop.mac = alg->mac; 357 fd = crget(); 358 if (ioctl(fd, CIOCGSESSION2, &sop) < 0) { 359 warn("cryptodev %s HMAC not supported for device %s", 360 alg->name, crfind(crid)); 361 close(fd); 362 return (false); 363 } 364 365 cop.ses = sop.ses; 366 cop.op = 0; 367 cop.len = size; 368 cop.src = (char *)buffer; 369 cop.dst = NULL; 370 cop.mac = digest; 371 cop.iv = NULL; 372 373 if (ioctl(fd, CIOCCRYPT, &cop) < 0) { 374 warn("cryptodev %s (%zu) HMAC failed for device %s", alg->name, 375 size, crfind(crid)); 376 close(fd); 377 return (false); 378 } 379 380 if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0) 381 warn("ioctl(CIOCFSESSION)"); 382 383 close(fd); 384 *cridp = sop.crid; 385 return (true); 386} 387 388static void 389run_hmac_test(struct alg *alg, size_t size) 390{ 391 const EVP_MD *md; 392 char *key, *buffer; 393 u_int key_len, digest_len; 394 int crid; 395 char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE]; 396 397 memset(control_digest, 0x3c, sizeof(control_digest)); 398 memset(test_digest, 0x3c, sizeof(test_digest)); 399 400 md = alg->evp_md(); 401 key_len = EVP_MD_size(md); 402 assert(EVP_MD_size(md) <= sizeof(control_digest)); 403 404 key = alloc_buffer(key_len); 405 buffer = alloc_buffer(size); 406 407 /* OpenSSL HMAC. */ 408 digest_len = sizeof(control_digest); 409 if (HMAC(md, key, key_len, (u_char *)buffer, size, 410 (u_char *)control_digest, &digest_len) == NULL) 411 errx(1, "OpenSSL %s (%zu) HMAC failed: %s", alg->name, 412 size, ERR_error_string(ERR_get_error(), NULL)); 413 414 /* cryptodev HMAC. */ 415 if (!ocf_hmac(alg, buffer, size, key, key_len, test_digest, &crid)) 416 goto out; 417 if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) { 418 if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0) 419 printf("%s (%zu) mismatch in trailer:\n", 420 alg->name, size); 421 else 422 printf("%s (%zu) mismatch:\n", alg->name, size); 423 printf("control:\n"); 424 hexdump(control_digest, sizeof(control_digest), NULL, 0); 425 printf("test (cryptodev device %s):\n", crfind(crid)); 426 hexdump(test_digest, sizeof(test_digest), NULL, 0); 427 goto out; 428 } 429 430 if (verbose) 431 printf("%s (%zu) matched (cryptodev device %s)\n", 432 alg->name, size, crfind(crid)); 433 434out: 435 free(buffer); 436 free(key); 437} 438 439static void 440openssl_cipher(struct alg *alg, const EVP_CIPHER *cipher, const char *key, 441 const char *iv, const char *input, char *output, size_t size, int enc) 442{ 443 EVP_CIPHER_CTX *ctx; 444 int outl, total; 445 446 ctx = EVP_CIPHER_CTX_new(); 447 if (ctx == NULL) 448 errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name, 449 size, ERR_error_string(ERR_get_error(), NULL)); 450 if (EVP_CipherInit_ex(ctx, cipher, NULL, (const u_char *)key, 451 (const u_char *)iv, enc) != 1) 452 errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name, 453 size, ERR_error_string(ERR_get_error(), NULL)); 454 EVP_CIPHER_CTX_set_padding(ctx, 0); 455 if (EVP_CipherUpdate(ctx, (u_char *)output, &outl, 456 (const u_char *)input, size) != 1) 457 errx(1, "OpenSSL %s (%zu) cipher update failed: %s", alg->name, 458 size, ERR_error_string(ERR_get_error(), NULL)); 459 total = outl; 460 if (EVP_CipherFinal_ex(ctx, (u_char *)output + outl, &outl) != 1) 461 errx(1, "OpenSSL %s (%zu) cipher final failed: %s", alg->name, 462 size, ERR_error_string(ERR_get_error(), NULL)); 463 total += outl; 464 if (total != size) 465 errx(1, "OpenSSL %s (%zu) cipher size mismatch: %d", alg->name, 466 size, total); 467 EVP_CIPHER_CTX_free(ctx); 468} 469 470static bool 471ocf_cipher(struct alg *alg, const char *key, size_t key_len, 472 const char *iv, const char *input, char *output, size_t size, int enc, 473 int *cridp) 474{ 475 struct session2_op sop; 476 struct crypt_op cop; 477 int fd; 478 479 memset(&sop, 0, sizeof(sop)); 480 memset(&cop, 0, sizeof(cop)); 481 sop.crid = crid; 482 sop.keylen = key_len; 483 sop.key = (char *)key; 484 sop.cipher = alg->cipher; 485 fd = crget(); 486 if (ioctl(fd, CIOCGSESSION2, &sop) < 0) { 487 warn("cryptodev %s block cipher not supported for device %s", 488 alg->name, crfind(crid)); 489 close(fd); 490 return (false); 491 } 492 493 cop.ses = sop.ses; 494 cop.op = enc ? COP_ENCRYPT : COP_DECRYPT; 495 cop.len = size; 496 cop.src = (char *)input; 497 cop.dst = output; 498 cop.mac = NULL; 499 cop.iv = (char *)iv; 500 501 if (ioctl(fd, CIOCCRYPT, &cop) < 0) { 502 warn("cryptodev %s (%zu) block cipher failed for device %s", 503 alg->name, size, crfind(crid)); 504 close(fd); 505 return (false); 506 } 507 508 if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0) 509 warn("ioctl(CIOCFSESSION)"); 510 511 close(fd); 512 *cridp = sop.crid; 513 return (true); 514} 515 516static void 517run_blkcipher_test(struct alg *alg, size_t size) 518{ 519 const EVP_CIPHER *cipher; 520 char *buffer, *cleartext, *ciphertext; 521 char *iv, *key; 522 u_int iv_len, key_len; 523 int crid; 524 525 cipher = alg->evp_cipher(); 526 if (size % EVP_CIPHER_block_size(cipher) != 0) { 527 if (verbose) 528 printf( 529 "%s (%zu): invalid buffer size (block size %d)\n", 530 alg->name, size, EVP_CIPHER_block_size(cipher)); 531 return; 532 } 533 534 key_len = EVP_CIPHER_key_length(cipher); 535 iv_len = EVP_CIPHER_iv_length(cipher); 536 537 key = alloc_buffer(key_len); 538 iv = generate_iv(iv_len, alg); 539 cleartext = alloc_buffer(size); 540 buffer = malloc(size); 541 ciphertext = malloc(size); 542 543 /* OpenSSL cipher. */ 544 openssl_cipher(alg, cipher, key, iv, cleartext, ciphertext, size, 1); 545 if (size > 0 && memcmp(cleartext, ciphertext, size) == 0) 546 errx(1, "OpenSSL %s (%zu): cipher text unchanged", alg->name, 547 size); 548 openssl_cipher(alg, cipher, key, iv, ciphertext, buffer, size, 0); 549 if (memcmp(cleartext, buffer, size) != 0) { 550 printf("OpenSSL %s (%zu): cipher mismatch:", alg->name, size); 551 printf("original:\n"); 552 hexdump(cleartext, size, NULL, 0); 553 printf("decrypted:\n"); 554 hexdump(buffer, size, NULL, 0); 555 exit(1); 556 } 557 558 /* OCF encrypt. */ 559 if (!ocf_cipher(alg, key, key_len, iv, cleartext, buffer, size, 1, 560 &crid)) 561 goto out; 562 if (memcmp(ciphertext, buffer, size) != 0) { 563 printf("%s (%zu) encryption mismatch:\n", alg->name, size); 564 printf("control:\n"); 565 hexdump(ciphertext, size, NULL, 0); 566 printf("test (cryptodev device %s):\n", crfind(crid)); 567 hexdump(buffer, size, NULL, 0); 568 goto out; 569 } 570 571 /* OCF decrypt. */ 572 if (!ocf_cipher(alg, key, key_len, iv, ciphertext, buffer, size, 0, 573 &crid)) 574 goto out; 575 if (memcmp(cleartext, buffer, size) != 0) { 576 printf("%s (%zu) decryption mismatch:\n", alg->name, size); 577 printf("control:\n"); 578 hexdump(cleartext, size, NULL, 0); 579 printf("test (cryptodev device %s):\n", crfind(crid)); 580 hexdump(buffer, size, NULL, 0); 581 goto out; 582 } 583 584 if (verbose) 585 printf("%s (%zu) matched (cryptodev device %s)\n", 586 alg->name, size, crfind(crid)); 587 588out: 589 free(ciphertext); 590 free(buffer); 591 free(cleartext); 592 free(iv); 593 free(key); 594} 595 596static bool 597ocf_authenc(struct alg *alg, const char *cipher_key, size_t cipher_key_len, 598 const char *iv, size_t iv_len, const char *auth_key, size_t auth_key_len, 599 const char *aad, size_t aad_len, const char *input, char *output, 600 size_t size, char *digest, int enc, int *cridp) 601{ 602 struct session2_op sop; 603 int fd; 604 605 memset(&sop, 0, sizeof(sop)); 606 sop.crid = crid; 607 sop.keylen = cipher_key_len; 608 sop.key = (char *)cipher_key; 609 sop.cipher = alg->cipher; 610 sop.mackeylen = auth_key_len; 611 sop.mackey = (char *)auth_key; 612 sop.mac = alg->mac; 613 fd = crget(); 614 if (ioctl(fd, CIOCGSESSION2, &sop) < 0) { 615 warn("cryptodev %s AUTHENC not supported for device %s", 616 alg->name, crfind(crid)); 617 close(fd); 618 return (false); 619 } 620 621 if (aad_len != 0) { 622 struct crypt_aead caead; 623 624 memset(&caead, 0, sizeof(caead)); 625 caead.ses = sop.ses; 626 caead.op = enc ? COP_ENCRYPT : COP_DECRYPT; 627 caead.flags = enc ? COP_F_CIPHER_FIRST : 0; 628 caead.len = size; 629 caead.aadlen = aad_len; 630 caead.ivlen = iv_len; 631 caead.src = (char *)input; 632 caead.dst = output; 633 caead.aad = (char *)aad; 634 caead.tag = digest; 635 caead.iv = (char *)iv; 636 637 if (ioctl(fd, CIOCCRYPTAEAD, &caead) < 0) { 638 warn("cryptodev %s (%zu) failed for device %s", 639 alg->name, size, crfind(crid)); 640 close(fd); 641 return (false); 642 } 643 } else { 644 struct crypt_op cop; 645 646 memset(&cop, 0, sizeof(cop)); 647 cop.ses = sop.ses; 648 cop.op = enc ? COP_ENCRYPT : COP_DECRYPT; 649 cop.flags = enc ? COP_F_CIPHER_FIRST : 0; 650 cop.len = size; 651 cop.src = (char *)input; 652 cop.dst = output; 653 cop.mac = digest; 654 cop.iv = (char *)iv; 655 656 if (ioctl(fd, CIOCCRYPT, &cop) < 0) { 657 warn("cryptodev %s (%zu) AUTHENC failed for device %s", 658 alg->name, size, crfind(crid)); 659 close(fd); 660 return (false); 661 } 662 } 663 664 if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0) 665 warn("ioctl(CIOCFSESSION)"); 666 667 close(fd); 668 *cridp = sop.crid; 669 return (true); 670} 671 672static void 673run_authenc_test(struct alg *alg, size_t size) 674{ 675 const EVP_CIPHER *cipher; 676 const EVP_MD *md; 677 char *aad, *buffer, *cleartext, *ciphertext; 678 char *iv, *auth_key, *cipher_key; 679 u_int iv_len, auth_key_len, cipher_key_len, digest_len; 680 int crid; 681 char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE]; 682 683 cipher = alg->evp_cipher(); 684 if (size % EVP_CIPHER_block_size(cipher) != 0) { 685 if (verbose) 686 printf( 687 "%s (%zu): invalid buffer size (block size %d)\n", 688 alg->name, size, EVP_CIPHER_block_size(cipher)); 689 return; 690 } 691 692 memset(control_digest, 0x3c, sizeof(control_digest)); 693 memset(test_digest, 0x3c, sizeof(test_digest)); 694 695 md = alg->evp_md(); 696 697 cipher_key_len = EVP_CIPHER_key_length(cipher); 698 iv_len = EVP_CIPHER_iv_length(cipher); 699 auth_key_len = EVP_MD_size(md); 700 701 cipher_key = alloc_buffer(cipher_key_len); 702 iv = generate_iv(iv_len, alg); 703 auth_key = alloc_buffer(auth_key_len); 704 cleartext = alloc_buffer(aad_len + size); 705 buffer = malloc(aad_len + size); 706 ciphertext = malloc(aad_len + size); 707 708 /* OpenSSL encrypt + HMAC. */ 709 if (aad_len != 0) 710 memcpy(ciphertext, cleartext, aad_len); 711 openssl_cipher(alg, cipher, cipher_key, iv, cleartext + aad_len, 712 ciphertext + aad_len, size, 1); 713 if (size > 0 && memcmp(cleartext + aad_len, ciphertext + aad_len, 714 size) == 0) 715 errx(1, "OpenSSL %s (%zu): cipher text unchanged", alg->name, 716 size); 717 digest_len = sizeof(control_digest); 718 if (HMAC(md, auth_key, auth_key_len, (u_char *)ciphertext, 719 aad_len + size, (u_char *)control_digest, &digest_len) == NULL) 720 errx(1, "OpenSSL %s (%zu) HMAC failed: %s", alg->name, 721 size, ERR_error_string(ERR_get_error(), NULL)); 722 723 /* OCF encrypt + HMAC. */ 724 if (!ocf_authenc(alg, cipher_key, cipher_key_len, iv, iv_len, auth_key, 725 auth_key_len, aad_len != 0 ? cleartext : NULL, aad_len, 726 cleartext + aad_len, buffer + aad_len, size, test_digest, 1, &crid)) 727 goto out; 728 if (memcmp(ciphertext + aad_len, buffer + aad_len, size) != 0) { 729 printf("%s (%zu) encryption mismatch:\n", alg->name, size); 730 printf("control:\n"); 731 hexdump(ciphertext + aad_len, size, NULL, 0); 732 printf("test (cryptodev device %s):\n", crfind(crid)); 733 hexdump(buffer + aad_len, size, NULL, 0); 734 goto out; 735 } 736 if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) { 737 if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0) 738 printf("%s (%zu) enc hash mismatch in trailer:\n", 739 alg->name, size); 740 else 741 printf("%s (%zu) enc hash mismatch:\n", alg->name, 742 size); 743 printf("control:\n"); 744 hexdump(control_digest, sizeof(control_digest), NULL, 0); 745 printf("test (cryptodev device %s):\n", crfind(crid)); 746 hexdump(test_digest, sizeof(test_digest), NULL, 0); 747 goto out; 748 } 749 750 /* OCF HMAC + decrypt. */ 751 memset(test_digest, 0x3c, sizeof(test_digest)); 752 if (!ocf_authenc(alg, cipher_key, cipher_key_len, iv, iv_len, auth_key, 753 auth_key_len, aad_len != 0 ? ciphertext : NULL, aad_len, 754 ciphertext + aad_len, buffer + aad_len, size, test_digest, 0, 755 &crid)) 756 goto out; 757 if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) { 758 if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0) 759 printf("%s (%zu) dec hash mismatch in trailer:\n", 760 alg->name, size); 761 else 762 printf("%s (%zu) dec hash mismatch:\n", alg->name, 763 size); 764 printf("control:\n"); 765 hexdump(control_digest, sizeof(control_digest), NULL, 0); 766 printf("test (cryptodev device %s):\n", crfind(crid)); 767 hexdump(test_digest, sizeof(test_digest), NULL, 0); 768 goto out; 769 } 770 if (memcmp(cleartext + aad_len, buffer + aad_len, size) != 0) { 771 printf("%s (%zu) decryption mismatch:\n", alg->name, size); 772 printf("control:\n"); 773 hexdump(cleartext, size, NULL, 0); 774 printf("test (cryptodev device %s):\n", crfind(crid)); 775 hexdump(buffer, size, NULL, 0); 776 goto out; 777 } 778 779 if (verbose) 780 printf("%s (%zu) matched (cryptodev device %s)\n", 781 alg->name, size, crfind(crid)); 782 783out: 784 free(ciphertext); 785 free(buffer); 786 free(cleartext); 787 free(auth_key); 788 free(iv); 789 free(cipher_key); 790} 791 792static void 793openssl_gcm_encrypt(struct alg *alg, const EVP_CIPHER *cipher, const char *key, 794 const char *iv, const char *aad, size_t aad_len, const char *input, 795 char *output, size_t size, char *tag) 796{ 797 EVP_CIPHER_CTX *ctx; 798 int outl, total; 799 800 ctx = EVP_CIPHER_CTX_new(); 801 if (ctx == NULL) 802 errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name, 803 size, ERR_error_string(ERR_get_error(), NULL)); 804 if (EVP_EncryptInit_ex(ctx, cipher, NULL, (const u_char *)key, 805 (const u_char *)iv) != 1) 806 errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name, 807 size, ERR_error_string(ERR_get_error(), NULL)); 808 EVP_CIPHER_CTX_set_padding(ctx, 0); 809 if (aad != NULL) { 810 if (EVP_EncryptUpdate(ctx, NULL, &outl, (const u_char *)aad, 811 aad_len) != 1) 812 errx(1, "OpenSSL %s (%zu) aad update failed: %s", 813 alg->name, size, 814 ERR_error_string(ERR_get_error(), NULL)); 815 } 816 if (EVP_EncryptUpdate(ctx, (u_char *)output, &outl, 817 (const u_char *)input, size) != 1) 818 errx(1, "OpenSSL %s (%zu) encrypt update failed: %s", alg->name, 819 size, ERR_error_string(ERR_get_error(), NULL)); 820 total = outl; 821 if (EVP_EncryptFinal_ex(ctx, (u_char *)output + outl, &outl) != 1) 822 errx(1, "OpenSSL %s (%zu) encrypt final failed: %s", alg->name, 823 size, ERR_error_string(ERR_get_error(), NULL)); 824 total += outl; 825 if (total != size) 826 errx(1, "OpenSSL %s (%zu) encrypt size mismatch: %d", alg->name, 827 size, total); 828 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, AES_GMAC_HASH_LEN, 829 tag) != 1) 830 errx(1, "OpenSSL %s (%zu) get tag failed: %s", alg->name, 831 size, ERR_error_string(ERR_get_error(), NULL)); 832 EVP_CIPHER_CTX_free(ctx); 833} 834 835static bool 836ocf_gcm(struct alg *alg, const char *key, size_t key_len, 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 *tag, int enc, int *cridp) 839{ 840 struct session2_op sop; 841 struct crypt_aead caead; 842 int fd; 843 844 memset(&sop, 0, sizeof(sop)); 845 memset(&caead, 0, sizeof(caead)); 846 sop.crid = crid; 847 sop.keylen = key_len; 848 sop.key = (char *)key; 849 sop.cipher = alg->cipher; 850 sop.mackeylen = key_len; 851 sop.mackey = (char *)key; 852 sop.mac = alg->mac; 853 fd = crget(); 854 if (ioctl(fd, CIOCGSESSION2, &sop) < 0) { 855 warn("cryptodev %s not supported for device %s", 856 alg->name, crfind(crid)); 857 close(fd); 858 return (false); 859 } 860 861 caead.ses = sop.ses; 862 caead.op = enc ? COP_ENCRYPT : COP_DECRYPT; 863 caead.len = size; 864 caead.aadlen = aad_len; 865 caead.ivlen = iv_len; 866 caead.src = (char *)input; 867 caead.dst = output; 868 caead.aad = (char *)aad; 869 caead.tag = tag; 870 caead.iv = (char *)iv; 871 872 if (ioctl(fd, CIOCCRYPTAEAD, &caead) < 0) { 873 warn("cryptodev %s (%zu) failed for device %s", 874 alg->name, size, crfind(crid)); 875 close(fd); 876 return (false); 877 } 878 879 if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0) 880 warn("ioctl(CIOCFSESSION)"); 881 882 close(fd); 883 *cridp = sop.crid; 884 return (true); 885} 886 887#ifdef notused 888static bool 889openssl_gcm_decrypt(struct alg *alg, const EVP_CIPHER *cipher, const char *key, 890 const char *iv, const char *aad, size_t aad_len, const char *input, 891 char *output, size_t size, char *tag) 892{ 893 EVP_CIPHER_CTX *ctx; 894 int outl, total; 895 bool valid; 896 897 ctx = EVP_CIPHER_CTX_new(); 898 if (ctx == NULL) 899 errx(1, "OpenSSL %s (%zu) ctx new failed: %s", alg->name, 900 size, ERR_error_string(ERR_get_error(), NULL)); 901 if (EVP_DecryptInit_ex(ctx, cipher, NULL, (const u_char *)key, 902 (const u_char *)iv) != 1) 903 errx(1, "OpenSSL %s (%zu) ctx init failed: %s", alg->name, 904 size, ERR_error_string(ERR_get_error(), NULL)); 905 EVP_CIPHER_CTX_set_padding(ctx, 0); 906 if (aad != NULL) { 907 if (EVP_DecryptUpdate(ctx, NULL, &outl, (const u_char *)aad, 908 aad_len) != 1) 909 errx(1, "OpenSSL %s (%zu) aad update failed: %s", 910 alg->name, size, 911 ERR_error_string(ERR_get_error(), NULL)); 912 } 913 if (EVP_DecryptUpdate(ctx, (u_char *)output, &outl, 914 (const u_char *)input, size) != 1) 915 errx(1, "OpenSSL %s (%zu) decrypt update failed: %s", alg->name, 916 size, ERR_error_string(ERR_get_error(), NULL)); 917 total = outl; 918 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AES_GMAC_HASH_LEN, 919 tag) != 1) 920 errx(1, "OpenSSL %s (%zu) get tag failed: %s", alg->name, 921 size, ERR_error_string(ERR_get_error(), NULL)); 922 valid = (EVP_DecryptFinal_ex(ctx, (u_char *)output + outl, &outl) != 1); 923 total += outl; 924 if (total != size) 925 errx(1, "OpenSSL %s (%zu) decrypt size mismatch: %d", alg->name, 926 size, total); 927 EVP_CIPHER_CTX_free(ctx); 928 return (valid); 929} 930#endif 931 932static void 933run_gcm_test(struct alg *alg, size_t size) 934{ 935 const EVP_CIPHER *cipher; 936 char *aad, *buffer, *cleartext, *ciphertext; 937 char *iv, *key; 938 u_int iv_len, key_len; 939 int crid; 940 char control_tag[AES_GMAC_HASH_LEN], test_tag[AES_GMAC_HASH_LEN]; 941 942 cipher = alg->evp_cipher(); 943 if (size % EVP_CIPHER_block_size(cipher) != 0) { 944 if (verbose) 945 printf( 946 "%s (%zu): invalid buffer size (block size %d)\n", 947 alg->name, size, EVP_CIPHER_block_size(cipher)); 948 return; 949 } 950 951 memset(control_tag, 0x3c, sizeof(control_tag)); 952 memset(test_tag, 0x3c, sizeof(test_tag)); 953 954 key_len = EVP_CIPHER_key_length(cipher); 955 iv_len = EVP_CIPHER_iv_length(cipher); 956 957 key = alloc_buffer(key_len); 958 iv = generate_iv(iv_len, alg); 959 cleartext = alloc_buffer(size); 960 buffer = malloc(size); 961 ciphertext = malloc(size); 962 if (aad_len != 0) 963 aad = alloc_buffer(aad_len); 964 else 965 aad = NULL; 966 967 /* OpenSSL encrypt */ 968 openssl_gcm_encrypt(alg, cipher, key, iv, aad, aad_len, cleartext, 969 ciphertext, size, control_tag); 970 971 /* OCF encrypt */ 972 if (!ocf_gcm(alg, key, key_len, iv, iv_len, aad, aad_len, cleartext, 973 buffer, size, test_tag, 1, &crid)) 974 goto out; 975 if (memcmp(ciphertext, buffer, size) != 0) { 976 printf("%s (%zu) encryption mismatch:\n", alg->name, size); 977 printf("control:\n"); 978 hexdump(ciphertext, size, NULL, 0); 979 printf("test (cryptodev device %s):\n", crfind(crid)); 980 hexdump(buffer, size, NULL, 0); 981 goto out; 982 } 983 if (memcmp(control_tag, test_tag, sizeof(control_tag)) != 0) { 984 printf("%s (%zu) enc tag mismatch:\n", alg->name, size); 985 printf("control:\n"); 986 hexdump(control_tag, sizeof(control_tag), NULL, 0); 987 printf("test (cryptodev device %s):\n", crfind(crid)); 988 hexdump(test_tag, sizeof(test_tag), NULL, 0); 989 goto out; 990 } 991 992 /* OCF decrypt */ 993 if (!ocf_gcm(alg, key, key_len, iv, iv_len, aad, aad_len, ciphertext, 994 buffer, size, control_tag, 0, &crid)) 995 goto out; 996 if (memcmp(cleartext, buffer, size) != 0) { 997 printf("%s (%zu) decryption mismatch:\n", alg->name, size); 998 printf("control:\n"); 999 hexdump(cleartext, size, NULL, 0); 1000 printf("test (cryptodev device %s):\n", crfind(crid)); 1001 hexdump(buffer, size, NULL, 0); 1002 goto out; 1003 } 1004 1005 if (verbose) 1006 printf("%s (%zu) matched (cryptodev device %s)\n", 1007 alg->name, size, crfind(crid)); 1008 1009out: 1010 free(aad); 1011 free(ciphertext); 1012 free(buffer); 1013 free(cleartext); 1014 free(iv); 1015 free(key); 1016} 1017 1018static void 1019run_test(struct alg *alg, size_t size) 1020{ 1021 1022 switch (alg->type) { 1023 case T_HMAC: 1024 run_hmac_test(alg, size); 1025 break; 1026 case T_BLKCIPHER: 1027 run_blkcipher_test(alg, size); 1028 break; 1029 case T_AUTHENC: 1030 run_authenc_test(alg, size); 1031 break; 1032 case T_GCM: 1033 run_gcm_test(alg, size); 1034 break; 1035 } 1036} 1037 1038static void 1039run_test_sizes(struct alg *alg, size_t *sizes, u_int nsizes) 1040{ 1041 u_int i; 1042 1043 for (i = 0; i < nsizes; i++) 1044 run_test(alg, sizes[i]); 1045} 1046 1047static void 1048run_hmac_tests(size_t *sizes, u_int nsizes) 1049{ 1050 u_int i; 1051 1052 for (i = 0; i < nitems(algs); i++) 1053 if (algs[i].type == T_HMAC) 1054 run_test_sizes(&algs[i], sizes, nsizes); 1055} 1056 1057static void 1058run_blkcipher_tests(size_t *sizes, u_int nsizes) 1059{ 1060 u_int i; 1061 1062 for (i = 0; i < nitems(algs); i++) 1063 if (algs[i].type == T_BLKCIPHER) 1064 run_test_sizes(&algs[i], sizes, nsizes); 1065} 1066 1067static void 1068run_authenc_tests(size_t *sizes, u_int nsizes) 1069{ 1070 struct alg *authenc, *cipher, *hmac; 1071 u_int i, j; 1072 1073 for (i = 0; i < nitems(algs); i++) { 1074 cipher = &algs[i]; 1075 if (cipher->type != T_BLKCIPHER) 1076 continue; 1077 for (j = 0; j < nitems(algs); j++) { 1078 hmac = &algs[j]; 1079 if (hmac->type != T_HMAC) 1080 continue; 1081 authenc = build_authenc(cipher, hmac); 1082 run_test_sizes(authenc, sizes, nsizes); 1083 free((char *)authenc->name); 1084 } 1085 } 1086} 1087 1088static void 1089run_aead_tests(size_t *sizes, u_int nsizes) 1090{ 1091 u_int i; 1092 1093 for (i = 0; i < nitems(algs); i++) 1094 if (algs[i].type == T_GCM) 1095 run_test_sizes(&algs[i], sizes, nsizes); 1096} 1097 1098int 1099main(int ac, char **av) 1100{ 1101 const char *algname; 1102 struct alg *alg; 1103 size_t sizes[128]; 1104 u_int i, nsizes; 1105 bool testall; 1106 int ch; 1107 1108 algname = NULL; 1109 crid = CRYPTO_FLAG_HARDWARE; 1110 testall = false; 1111 verbose = false; 1112 while ((ch = getopt(ac, av, "A:a:d:vz")) != -1) 1113 switch (ch) { 1114 case 'A': 1115 aad_len = atoi(optarg); 1116 break; 1117 case 'a': 1118 algname = optarg; 1119 break; 1120 case 'd': 1121 crid = crlookup(optarg); 1122 break; 1123 case 'v': 1124 verbose = true; 1125 break; 1126 case 'z': 1127 testall = true; 1128 break; 1129 default: 1130 usage(); 1131 } 1132 ac -= optind; 1133 av += optind; 1134 nsizes = 0; 1135 while (ac > 0) { 1136 char *cp; 1137 1138 if (nsizes >= nitems(sizes)) { 1139 warnx("Too many sizes, ignoring extras"); 1140 break; 1141 } 1142 sizes[nsizes] = strtol(av[0], &cp, 0); 1143 if (*cp != '\0') 1144 errx(1, "Bad size %s", av[0]); 1145 nsizes++; 1146 ac--; 1147 av++; 1148 } 1149 1150 if (algname == NULL) 1151 errx(1, "Algorithm required"); 1152 if (nsizes == 0) { 1153 sizes[0] = 16; 1154 nsizes++; 1155 if (testall) { 1156 while (sizes[nsizes - 1] * 2 < 240 * 1024) { 1157 assert(nsizes < nitems(sizes)); 1158 sizes[nsizes] = sizes[nsizes - 1] * 2; 1159 nsizes++; 1160 } 1161 if (sizes[nsizes - 1] < 240 * 1024) { 1162 assert(nsizes < nitems(sizes)); 1163 sizes[nsizes] = 240 * 1024; 1164 nsizes++; 1165 } 1166 } 1167 } 1168 1169 if (strcasecmp(algname, "hmac") == 0) 1170 run_hmac_tests(sizes, nsizes); 1171 else if (strcasecmp(algname, "blkcipher") == 0) 1172 run_blkcipher_tests(sizes, nsizes); 1173 else if (strcasecmp(algname, "authenc") == 0) 1174 run_authenc_tests(sizes, nsizes); 1175 else if (strcasecmp(algname, "aead") == 0) 1176 run_aead_tests(sizes, nsizes); 1177 else if (strcasecmp(algname, "all") == 0) { 1178 run_hmac_tests(sizes, nsizes); 1179 run_blkcipher_tests(sizes, nsizes); 1180 run_authenc_tests(sizes, nsizes); 1181 run_aead_tests(sizes, nsizes); 1182 } else if (strchr(algname, '+') != NULL) { 1183 alg = build_authenc_name(algname); 1184 run_test_sizes(alg, sizes, nsizes); 1185 } else { 1186 alg = find_alg(algname); 1187 if (alg == NULL) 1188 errx(1, "Invalid algorithm %s", algname); 1189 run_test_sizes(alg, sizes, nsizes); 1190 } 1191 1192 return (0); 1193} 1194