diff options
| author | deraadt <> | 2004-02-03 08:48:26 +0000 |
|---|---|---|
| committer | deraadt <> | 2004-02-03 08:48:26 +0000 |
| commit | b6361823f347e3fac478dfe9ca17ff60e7ffd362 (patch) | |
| tree | 5f37ce8ce7c2d9df69cab4efc13c9031eb58e57f /src/lib/libcrypto/engine/hw_cryptodev.c | |
| parent | 88dce049d2200f8e66f2fe6a8c21518b467f3762 (diff) | |
| download | openbsd-b6361823f347e3fac478dfe9ca17ff60e7ffd362.tar.gz openbsd-b6361823f347e3fac478dfe9ca17ff60e7ffd362.tar.bz2 openbsd-b6361823f347e3fac478dfe9ca17ff60e7ffd362.zip | |
If on an i386, detect existance of the VIA C3 xcrypt-* using sysctl of
the machdep.xcrypt node. If they exist, use the xcrypt-cbc instruction
to accelerate aes-{128,192,256}-cbc, for more than 100x performance
increase. This code has no effect on any cpu... Tested thus far using
openssl speed command, and of course, ssh. 778MB/sec AES-128-CBC
performance at 8192 byte block size.
Diffstat (limited to 'src/lib/libcrypto/engine/hw_cryptodev.c')
| -rw-r--r-- | src/lib/libcrypto/engine/hw_cryptodev.c | 178 |
1 files changed, 174 insertions, 4 deletions
diff --git a/src/lib/libcrypto/engine/hw_cryptodev.c b/src/lib/libcrypto/engine/hw_cryptodev.c index b502d12b6d..4959c67e92 100644 --- a/src/lib/libcrypto/engine/hw_cryptodev.c +++ b/src/lib/libcrypto/engine/hw_cryptodev.c | |||
| @@ -49,11 +49,12 @@ ENGINE_load_cryptodev(void) | |||
| 49 | return; | 49 | return; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | #else | 52 | #else |
| 53 | 53 | ||
| 54 | #include <sys/types.h> | 54 | #include <sys/types.h> |
| 55 | #include <crypto/cryptodev.h> | 55 | #include <crypto/cryptodev.h> |
| 56 | #include <sys/ioctl.h> | 56 | #include <sys/ioctl.h> |
| 57 | |||
| 57 | #include <errno.h> | 58 | #include <errno.h> |
| 58 | #include <stdio.h> | 59 | #include <stdio.h> |
| 59 | #include <unistd.h> | 60 | #include <unistd.h> |
| @@ -63,6 +64,13 @@ ENGINE_load_cryptodev(void) | |||
| 63 | #include <errno.h> | 64 | #include <errno.h> |
| 64 | #include <string.h> | 65 | #include <string.h> |
| 65 | 66 | ||
| 67 | #ifdef __i386__ | ||
| 68 | #include <sys/sysctl.h> | ||
| 69 | #include <machine/cpu.h> | ||
| 70 | #include <machine/specialreg.h> | ||
| 71 | static void check_viac3aes(void); | ||
| 72 | #endif | ||
| 73 | |||
| 66 | struct dev_crypto_state { | 74 | struct dev_crypto_state { |
| 67 | struct session_op d_sess; | 75 | struct session_op d_sess; |
| 68 | int d_fd; | 76 | int d_fd; |
| @@ -246,6 +254,14 @@ get_cryptodev_ciphers(const int **cnids) | |||
| 246 | } | 254 | } |
| 247 | close(fd); | 255 | close(fd); |
| 248 | 256 | ||
| 257 | #if defined(__i386__) | ||
| 258 | /* | ||
| 259 | * On i386, always check for the VIA C3 AES instructions; | ||
| 260 | * even if /dev/crypto is disabled. | ||
| 261 | */ | ||
| 262 | check_viac3aes(); | ||
| 263 | #endif | ||
| 264 | |||
| 249 | if (count > 0) | 265 | if (count > 0) |
| 250 | *cnids = nids; | 266 | *cnids = nids; |
| 251 | else | 267 | else |
| @@ -518,7 +534,7 @@ const EVP_CIPHER cryptodev_cast_cbc = { | |||
| 518 | NULL | 534 | NULL |
| 519 | }; | 535 | }; |
| 520 | 536 | ||
| 521 | const EVP_CIPHER cryptodev_aes_128_cbc = { | 537 | EVP_CIPHER cryptodev_aes_128_cbc = { |
| 522 | NID_aes_128_cbc, | 538 | NID_aes_128_cbc, |
| 523 | 16, 16, 16, | 539 | 16, 16, 16, |
| 524 | EVP_CIPH_CBC_MODE, | 540 | EVP_CIPH_CBC_MODE, |
| @@ -531,7 +547,7 @@ const EVP_CIPHER cryptodev_aes_128_cbc = { | |||
| 531 | NULL | 547 | NULL |
| 532 | }; | 548 | }; |
| 533 | 549 | ||
| 534 | const EVP_CIPHER cryptodev_aes_192_cbc = { | 550 | EVP_CIPHER cryptodev_aes_192_cbc = { |
| 535 | NID_aes_192_cbc, | 551 | NID_aes_192_cbc, |
| 536 | 16, 24, 16, | 552 | 16, 24, 16, |
| 537 | EVP_CIPH_CBC_MODE, | 553 | EVP_CIPH_CBC_MODE, |
| @@ -544,7 +560,7 @@ const EVP_CIPHER cryptodev_aes_192_cbc = { | |||
| 544 | NULL | 560 | NULL |
| 545 | }; | 561 | }; |
| 546 | 562 | ||
| 547 | const EVP_CIPHER cryptodev_aes_256_cbc = { | 563 | EVP_CIPHER cryptodev_aes_256_cbc = { |
| 548 | NID_aes_256_cbc, | 564 | NID_aes_256_cbc, |
| 549 | 16, 32, 16, | 565 | 16, 32, 16, |
| 550 | EVP_CIPH_CBC_MODE, | 566 | EVP_CIPH_CBC_MODE, |
| @@ -557,6 +573,160 @@ const EVP_CIPHER cryptodev_aes_256_cbc = { | |||
| 557 | NULL | 573 | NULL |
| 558 | }; | 574 | }; |
| 559 | 575 | ||
| 576 | #if defined(__i386__) | ||
| 577 | |||
| 578 | volatile static void | ||
| 579 | viac3_crypto(int *cw, const void *src, void *dst, void *key, int rep, | ||
| 580 | void *iv) | ||
| 581 | { | ||
| 582 | #ifdef notdef | ||
| 583 | printf("cw %x[%x %x %x %x] src %x dst %x key %x rep %x iv %x\n", | ||
| 584 | cw, cw[0], cw[1], cw[2], cw[3], | ||
| 585 | src, dst, key, rep, iv); | ||
| 586 | #endif | ||
| 587 | /* | ||
| 588 | * Clear bit 30 of EFLAGS. | ||
| 589 | */ | ||
| 590 | __asm __volatile("pushfl; popfl"); | ||
| 591 | |||
| 592 | /* | ||
| 593 | * Cannot simply place key into "b" register, since the compiler | ||
| 594 | * -pic mode uses that register; so instead we must dance a little. | ||
| 595 | */ | ||
| 596 | __asm __volatile("pushl %%ebx; movl %0, %%ebx; rep xcrypt-cbc; popl %%ebx" : | ||
| 597 | : "mr" (key), "a" (iv), "c" (rep), "d" (cw), "S" (src), "D" (dst) | ||
| 598 | : "memory", "cc"); | ||
| 599 | } | ||
| 600 | |||
| 601 | #define ISUNALIGNED(x) ((long)(x)) & 15 | ||
| 602 | #define DOALIGN(v) ((void *)(((long)(v) + 15) & ~15)) | ||
| 603 | |||
| 604 | static int | ||
| 605 | xcrypt_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | ||
| 606 | const unsigned char *in, unsigned int inl) | ||
| 607 | { | ||
| 608 | unsigned char *save_iv_store[EVP_MAX_IV_LENGTH + 15]; | ||
| 609 | unsigned char *save_iv = DOALIGN(save_iv_store); | ||
| 610 | unsigned char *ivs_store[EVP_MAX_IV_LENGTH + 15]; | ||
| 611 | unsigned char *ivs = DOALIGN(ivs_store); | ||
| 612 | void *iiv, *iv = NULL, *ivp = NULL; | ||
| 613 | const void *usein = in; | ||
| 614 | void *useout = out, *spare; | ||
| 615 | int cws[4 + 3], *cw = DOALIGN(cws); | ||
| 616 | |||
| 617 | if (!inl) | ||
| 618 | return (1); | ||
| 619 | if ((inl % ctx->cipher->block_size) != 0) | ||
| 620 | return (0); | ||
| 621 | |||
| 622 | if (ISUNALIGNED(in) || ISUNALIGNED(out)) { | ||
| 623 | spare = malloc(inl); | ||
| 624 | if (spare == NULL) | ||
| 625 | return (0); | ||
| 626 | |||
| 627 | if (ISUNALIGNED(in)) { | ||
| 628 | bcopy(in, spare, inl); | ||
| 629 | usein = spare; | ||
| 630 | } | ||
| 631 | if (ISUNALIGNED(out)) | ||
| 632 | useout = spare; | ||
| 633 | } | ||
| 634 | |||
| 635 | cw[0] = C3_CRYPT_CWLO_ALG_AES | C3_CRYPT_CWLO_KEYGEN_HW | | ||
| 636 | C3_CRYPT_CWLO_NORMAL | | ||
| 637 | ctx->encrypt ? C3_CRYPT_CWLO_ENCRYPT : C3_CRYPT_CWLO_DECRYPT; | ||
| 638 | cw[1] = cw[2] = cw[3] = 0; | ||
| 639 | |||
| 640 | switch (ctx->key_len * 8) { | ||
| 641 | case 128: | ||
| 642 | cw[0] |= C3_CRYPT_CWLO_KEY128; | ||
| 643 | break; | ||
| 644 | case 192: | ||
| 645 | cw[0] |= C3_CRYPT_CWLO_KEY192; | ||
| 646 | break; | ||
| 647 | case 256: | ||
| 648 | cw[0] |= C3_CRYPT_CWLO_KEY256; | ||
| 649 | break; | ||
| 650 | } | ||
| 651 | |||
| 652 | if (ctx->cipher->iv_len) { | ||
| 653 | iv = (caddr_t) ctx->iv; | ||
| 654 | if (!ctx->encrypt) { | ||
| 655 | iiv = (void *) in + inl - ctx->cipher->iv_len; | ||
| 656 | memcpy(save_iv, iiv, ctx->cipher->iv_len); | ||
| 657 | } | ||
| 658 | } | ||
| 659 | |||
| 660 | ivp = iv; | ||
| 661 | if (ISUNALIGNED(iv)) { | ||
| 662 | bcopy(iv, ivs, ctx->cipher->iv_len); | ||
| 663 | ivp = ivs; | ||
| 664 | } | ||
| 665 | |||
| 666 | viac3_crypto(cw, usein, useout, ctx->cipher_data, inl / 16, ivp); | ||
| 667 | |||
| 668 | if (ISUNALIGNED(out)) { | ||
| 669 | bcopy(spare, out, inl); | ||
| 670 | free(spare); | ||
| 671 | } | ||
| 672 | |||
| 673 | if (ivp == ivs) | ||
| 674 | bcopy(ivp, iv, ctx->cipher->iv_len); | ||
| 675 | |||
| 676 | if (ctx->cipher->iv_len) { | ||
| 677 | if (ctx->encrypt) | ||
| 678 | iiv = (void *) out + inl - ctx->cipher->iv_len; | ||
| 679 | else | ||
| 680 | iiv = save_iv; | ||
| 681 | memcpy(ctx->iv, iiv, ctx->cipher->iv_len); | ||
| 682 | } | ||
| 683 | return (1); | ||
| 684 | } | ||
| 685 | |||
| 686 | static int | ||
| 687 | xcrypt_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, | ||
| 688 | const unsigned char *iv, int enc) | ||
| 689 | { | ||
| 690 | bcopy(key, ctx->cipher_data, ctx->key_len); | ||
| 691 | return (1); | ||
| 692 | } | ||
| 693 | |||
| 694 | static int | ||
| 695 | xcrypt_cleanup(EVP_CIPHER_CTX *ctx) | ||
| 696 | { | ||
| 697 | bzero(ctx->cipher_data, ctx->key_len); | ||
| 698 | return (1); | ||
| 699 | } | ||
| 700 | |||
| 701 | static void | ||
| 702 | check_viac3aes(void) | ||
| 703 | { | ||
| 704 | int mib[2] = { CTL_MACHDEP, CPU_XCRYPT }, value; | ||
| 705 | size_t size = sizeof(value); | ||
| 706 | |||
| 707 | if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, | ||
| 708 | NULL, 0) < 0) | ||
| 709 | return; | ||
| 710 | if (value == 0) | ||
| 711 | return; | ||
| 712 | |||
| 713 | cryptodev_aes_128_cbc.init = xcrypt_init_key; | ||
| 714 | cryptodev_aes_128_cbc.do_cipher = xcrypt_cipher; | ||
| 715 | cryptodev_aes_128_cbc.cleanup = xcrypt_cleanup; | ||
| 716 | cryptodev_aes_128_cbc.ctx_size = 128; | ||
| 717 | |||
| 718 | cryptodev_aes_192_cbc.init = xcrypt_init_key; | ||
| 719 | cryptodev_aes_192_cbc.do_cipher = xcrypt_cipher; | ||
| 720 | cryptodev_aes_192_cbc.cleanup = xcrypt_cleanup; | ||
| 721 | cryptodev_aes_192_cbc.ctx_size = 128; | ||
| 722 | |||
| 723 | cryptodev_aes_256_cbc.init = xcrypt_init_key; | ||
| 724 | cryptodev_aes_256_cbc.do_cipher = xcrypt_cipher; | ||
| 725 | cryptodev_aes_256_cbc.cleanup = xcrypt_cleanup; | ||
| 726 | cryptodev_aes_256_cbc.ctx_size = 128; | ||
| 727 | } | ||
| 728 | #endif /* __i386__ */ | ||
| 729 | |||
| 560 | /* | 730 | /* |
| 561 | * Registered by the ENGINE when used to find out how to deal with | 731 | * Registered by the ENGINE when used to find out how to deal with |
| 562 | * a particular NID in the ENGINE. this says what we'll do at the | 732 | * a particular NID in the ENGINE. this says what we'll do at the |
