diff options
author | jsing <> | 2022-05-07 07:47:24 +0000 |
---|---|---|
committer | jsing <> | 2022-05-07 07:47:24 +0000 |
commit | 06373cf29b7f2f1c4fdd09ce26d5671ac29e3675 (patch) | |
tree | fea88905a338e173a2ff4c9ba0fb67b479b0ff6c | |
parent | 14f29f49d99785d2e275fd406ac4227273b08b7e (diff) | |
download | openbsd-06373cf29b7f2f1c4fdd09ce26d5671ac29e3675.tar.gz openbsd-06373cf29b7f2f1c4fdd09ce26d5671ac29e3675.tar.bz2 openbsd-06373cf29b7f2f1c4fdd09ce26d5671ac29e3675.zip |
Avoid strict aliasing violations in BN_nist_mod_*()
The optimised code path switches from processing data via unsigned long to
processing data via unsigned int, which requires type punning. This is
currently attempted via a union (for one case), however this fails since
a pointer to a union member is passed to another function (these unions
were added to "fix strict-aliasing compiler warning" - it would seem the
warnings stopped but the undefined behaviour remained). The second case
does not use a union and simply casts from one type to another.
Undefined behaviour is currently triggered when compiling with clang 14
using -03 and -fstrict-aliasing, while disabling assembly (in order to use
this C code). The resulting binary produces incorrect results.
Avoid strict aliasing violations by copying from an unsigned long array to
an unsigned int array, then copying back the result. Any sensible compiler
will omit the copies, while avoiding undefined behaviour that would result
from unsafe type punning via pointer type casting.
Thanks to Guido Vranken for reporting the issue and testing the fix.
ok tb@
-rw-r--r-- | src/lib/libcrypto/bn/bn_nist.c | 223 |
1 files changed, 137 insertions, 86 deletions
diff --git a/src/lib/libcrypto/bn/bn_nist.c b/src/lib/libcrypto/bn/bn_nist.c index 3a04c471c4..871b37cf89 100644 --- a/src/lib/libcrypto/bn/bn_nist.c +++ b/src/lib/libcrypto/bn/bn_nist.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: bn_nist.c,v 1.19 2021/11/09 18:40:20 bcook Exp $ */ | 1 | /* $OpenBSD: bn_nist.c,v 1.20 2022/05/07 07:47:24 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Written by Nils Larsch for the OpenSSL project | 3 | * Written by Nils Larsch for the OpenSSL project |
4 | */ | 4 | */ |
@@ -62,6 +62,9 @@ | |||
62 | 62 | ||
63 | #include "bn_lcl.h" | 63 | #include "bn_lcl.h" |
64 | 64 | ||
65 | #define CTASSERT(x) extern char _ctassert[(x) ? 1 : -1 ] \ | ||
66 | __attribute__((__unused__)) | ||
67 | |||
65 | #define BN_NIST_192_TOP (192+BN_BITS2-1)/BN_BITS2 | 68 | #define BN_NIST_192_TOP (192+BN_BITS2-1)/BN_BITS2 |
66 | #define BN_NIST_224_TOP (224+BN_BITS2-1)/BN_BITS2 | 69 | #define BN_NIST_224_TOP (224+BN_BITS2-1)/BN_BITS2 |
67 | #define BN_NIST_256_TOP (256+BN_BITS2-1)/BN_BITS2 | 70 | #define BN_NIST_256_TOP (256+BN_BITS2-1)/BN_BITS2 |
@@ -425,11 +428,7 @@ BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
425 | int top = a->top, i; | 428 | int top = a->top, i; |
426 | int carry; | 429 | int carry; |
427 | BN_ULONG *r_d, *a_d = a->d; | 430 | BN_ULONG *r_d, *a_d = a->d; |
428 | union { | 431 | BN_ULONG bnbuf[BN_NIST_192_TOP] = { 0 }; |
429 | BN_ULONG bn[BN_NIST_192_TOP]; | ||
430 | unsigned int ui[BN_NIST_192_TOP * | ||
431 | sizeof(BN_ULONG) / sizeof(unsigned int)]; | ||
432 | } buf; | ||
433 | BN_ULONG c_d[BN_NIST_192_TOP], *res; | 432 | BN_ULONG c_d[BN_NIST_192_TOP], *res; |
434 | uintptr_t mask; | 433 | uintptr_t mask; |
435 | static const BIGNUM _bignum_nist_p_192_sqr = { | 434 | static const BIGNUM _bignum_nist_p_192_sqr = { |
@@ -460,14 +459,31 @@ BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
460 | } else | 459 | } else |
461 | r_d = a_d; | 460 | r_d = a_d; |
462 | 461 | ||
463 | nist_cp_bn_0(buf.bn, a_d + BN_NIST_192_TOP, top - BN_NIST_192_TOP, | 462 | nist_cp_bn_0(bnbuf, a_d + BN_NIST_192_TOP, top - BN_NIST_192_TOP, |
464 | BN_NIST_192_TOP); | 463 | BN_NIST_192_TOP); |
465 | 464 | ||
466 | #if defined(NIST_INT64) | 465 | #if defined(NIST_INT64) |
467 | { | 466 | { |
468 | NIST_INT64 acc; /* accumulator */ | 467 | NIST_INT64 acc; /* accumulator */ |
469 | unsigned int *rp = (unsigned int *)r_d; | 468 | unsigned int bbuf[BN_NIST_192_TOP * |
470 | const unsigned int *bp = (const unsigned int *)buf.ui; | 469 | sizeof(BN_ULONG) / sizeof(unsigned int)]; |
470 | unsigned int rbuf[BN_NIST_192_TOP * | ||
471 | sizeof(BN_ULONG) / sizeof(unsigned int)]; | ||
472 | const unsigned int *bp = bbuf; | ||
473 | unsigned int *rp = rbuf; | ||
474 | |||
475 | CTASSERT(sizeof(bbuf) == sizeof(bnbuf)); | ||
476 | CTASSERT(sizeof(rbuf) == sizeof(bnbuf)); | ||
477 | |||
478 | /* | ||
479 | * Avoid strict aliasing violations by copying from an unsigned | ||
480 | * long array to an unsigned int array, then copying back the | ||
481 | * result. Any sensible compiler will omit the copies, while | ||
482 | * avoiding undefined behaviour that would result from unsafe | ||
483 | * type punning via pointer type casting. | ||
484 | */ | ||
485 | memcpy(bbuf, bnbuf, sizeof(bbuf)); | ||
486 | memcpy(rbuf, r_d, sizeof(rbuf)); | ||
471 | 487 | ||
472 | acc = rp[0]; | 488 | acc = rp[0]; |
473 | acc += bp[3 * 2 - 6]; | 489 | acc += bp[3 * 2 - 6]; |
@@ -506,17 +522,19 @@ BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
506 | acc += bp[5 * 2 - 5]; | 522 | acc += bp[5 * 2 - 5]; |
507 | rp[5] = (unsigned int)acc; | 523 | rp[5] = (unsigned int)acc; |
508 | 524 | ||
525 | memcpy(r_d, rbuf, sizeof(rbuf)); | ||
526 | |||
509 | carry = (int)(acc >> 32); | 527 | carry = (int)(acc >> 32); |
510 | } | 528 | } |
511 | #else | 529 | #else |
512 | { | 530 | { |
513 | BN_ULONG t_d[BN_NIST_192_TOP] = {0}; | 531 | BN_ULONG t_d[BN_NIST_192_TOP] = {0}; |
514 | 532 | ||
515 | nist_set_192(t_d, buf.bn, 0, 3, 3); | 533 | nist_set_192(t_d, bnbuf, 0, 3, 3); |
516 | carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP); | 534 | carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP); |
517 | nist_set_192(t_d, buf.bn, 4, 4, 0); | 535 | nist_set_192(t_d, bnbuf, 4, 4, 0); |
518 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP); | 536 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP); |
519 | nist_set_192(t_d, buf.bn, 5, 5, 5) | 537 | nist_set_192(t_d, bnbuf, 5, 5, 5) |
520 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP); | 538 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP); |
521 | } | 539 | } |
522 | #endif | 540 | #endif |
@@ -564,17 +582,10 @@ BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
564 | int top = a->top, i; | 582 | int top = a->top, i; |
565 | int carry; | 583 | int carry; |
566 | BN_ULONG *r_d, *a_d = a->d; | 584 | BN_ULONG *r_d, *a_d = a->d; |
567 | union { | 585 | BN_ULONG bnbuf[BN_NIST_224_TOP] = { 0 }; |
568 | BN_ULONG bn[BN_NIST_224_TOP]; | ||
569 | unsigned int ui[BN_NIST_224_TOP * | ||
570 | sizeof(BN_ULONG) / sizeof(unsigned int)]; | ||
571 | } buf; | ||
572 | BN_ULONG c_d[BN_NIST_224_TOP], *res; | 586 | BN_ULONG c_d[BN_NIST_224_TOP], *res; |
573 | uintptr_t mask; | 587 | uintptr_t mask; |
574 | union { | 588 | bn_addsub_f addsubf; |
575 | bn_addsub_f f; | ||
576 | uintptr_t p; | ||
577 | } u; | ||
578 | static const BIGNUM _bignum_nist_p_224_sqr = { | 589 | static const BIGNUM _bignum_nist_p_224_sqr = { |
579 | (BN_ULONG *)_nist_p_224_sqr, | 590 | (BN_ULONG *)_nist_p_224_sqr, |
580 | sizeof(_nist_p_224_sqr) / sizeof(_nist_p_224_sqr[0]), | 591 | sizeof(_nist_p_224_sqr) / sizeof(_nist_p_224_sqr[0]), |
@@ -603,26 +614,43 @@ BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
603 | } else | 614 | } else |
604 | r_d = a_d; | 615 | r_d = a_d; |
605 | 616 | ||
606 | memset(&buf, 0, sizeof(buf)); | 617 | memset(&bnbuf, 0, sizeof(bnbuf)); |
607 | 618 | ||
608 | #if BN_BITS2==64 | 619 | #if BN_BITS2==64 |
609 | /* copy upper 256 bits of 448 bit number ... */ | 620 | /* copy upper 256 bits of 448 bit number ... */ |
610 | nist_cp_bn_0(c_d, a_d + (BN_NIST_224_TOP - 1), | 621 | nist_cp_bn_0(c_d, a_d + (BN_NIST_224_TOP - 1), |
611 | top - (BN_NIST_224_TOP - 1), BN_NIST_224_TOP); | 622 | top - (BN_NIST_224_TOP - 1), BN_NIST_224_TOP); |
612 | /* ... and right shift by 32 to obtain upper 224 bits */ | 623 | /* ... and right shift by 32 to obtain upper 224 bits */ |
613 | nist_set_224(buf.bn, c_d, 14, 13, 12, 11, 10, 9, 8); | 624 | nist_set_224(bnbuf, c_d, 14, 13, 12, 11, 10, 9, 8); |
614 | /* truncate lower part to 224 bits too */ | 625 | /* truncate lower part to 224 bits too */ |
615 | r_d[BN_NIST_224_TOP - 1] &= BN_MASK2l; | 626 | r_d[BN_NIST_224_TOP - 1] &= BN_MASK2l; |
616 | #else | 627 | #else |
617 | nist_cp_bn_0(buf.bn, a_d + BN_NIST_224_TOP, | 628 | nist_cp_bn_0(bnbuf, a_d + BN_NIST_224_TOP, |
618 | top - BN_NIST_224_TOP, BN_NIST_224_TOP); | 629 | top - BN_NIST_224_TOP, BN_NIST_224_TOP); |
619 | #endif | 630 | #endif |
620 | 631 | ||
621 | #if defined(NIST_INT64) && BN_BITS2!=64 | 632 | #if defined(NIST_INT64) && BN_BITS2!=64 |
622 | { | 633 | { |
623 | NIST_INT64 acc; /* accumulator */ | 634 | NIST_INT64 acc; /* accumulator */ |
624 | unsigned int *rp = (unsigned int *)r_d; | 635 | unsigned int bbuf[BN_NIST_224_TOP * |
625 | const unsigned int *bp = (const unsigned int *)buf.ui; | 636 | sizeof(BN_ULONG) / sizeof(unsigned int)]; |
637 | unsigned int rbuf[BN_NIST_224_TOP * | ||
638 | sizeof(BN_ULONG) / sizeof(unsigned int)]; | ||
639 | const unsigned int *bp = bbuf; | ||
640 | unsigned int *rp = rbuf; | ||
641 | |||
642 | CTASSERT(sizeof(bbuf) == sizeof(bnbuf)); | ||
643 | CTASSERT(sizeof(rbuf) == sizeof(bnbuf)); | ||
644 | |||
645 | /* | ||
646 | * Avoid strict aliasing violations by copying from an unsigned | ||
647 | * long array to an unsigned int array, then copying back the | ||
648 | * result. Any sensible compiler will omit the copies, while | ||
649 | * avoiding undefined behaviour that would result from unsafe | ||
650 | * type punning via pointer type casting. | ||
651 | */ | ||
652 | memcpy(bbuf, bnbuf, sizeof(bbuf)); | ||
653 | memcpy(rbuf, r_d, sizeof(rbuf)); | ||
626 | 654 | ||
627 | acc = rp[0]; | 655 | acc = rp[0]; |
628 | acc -= bp[7 - 7]; | 656 | acc -= bp[7 - 7]; |
@@ -668,6 +696,8 @@ BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
668 | acc -= bp[13 - 7]; | 696 | acc -= bp[13 - 7]; |
669 | rp[6] = (unsigned int)acc; | 697 | rp[6] = (unsigned int)acc; |
670 | 698 | ||
699 | memcpy(r_d, rbuf, sizeof(rbuf)); | ||
700 | |||
671 | carry = (int)(acc >> 32); | 701 | carry = (int)(acc >> 32); |
672 | # if BN_BITS2==64 | 702 | # if BN_BITS2==64 |
673 | rp[7] = carry; | 703 | rp[7] = carry; |
@@ -677,13 +707,13 @@ BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
677 | { | 707 | { |
678 | BN_ULONG t_d[BN_NIST_224_TOP] = {0}; | 708 | BN_ULONG t_d[BN_NIST_224_TOP] = {0}; |
679 | 709 | ||
680 | nist_set_224(t_d, buf.bn, 10, 9, 8, 7, 0, 0, 0); | 710 | nist_set_224(t_d, bnbuf, 10, 9, 8, 7, 0, 0, 0); |
681 | carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP); | 711 | carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP); |
682 | nist_set_224(t_d, buf.bn, 0, 13, 12, 11, 0, 0, 0); | 712 | nist_set_224(t_d, bnbuf, 0, 13, 12, 11, 0, 0, 0); |
683 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP); | 713 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP); |
684 | nist_set_224(t_d, buf.bn, 13, 12, 11, 10, 9, 8, 7); | 714 | nist_set_224(t_d, bnbuf, 13, 12, 11, 10, 9, 8, 7); |
685 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP); | 715 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP); |
686 | nist_set_224(t_d, buf.bn, 0, 0, 0, 0, 13, 12, 11); | 716 | nist_set_224(t_d, bnbuf, 0, 0, 0, 0, 13, 12, 11); |
687 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP); | 717 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP); |
688 | 718 | ||
689 | #if BN_BITS2==64 | 719 | #if BN_BITS2==64 |
@@ -691,7 +721,7 @@ BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
691 | #endif | 721 | #endif |
692 | } | 722 | } |
693 | #endif | 723 | #endif |
694 | u.f = bn_sub_words; | 724 | addsubf = bn_sub_words; |
695 | if (carry > 0) { | 725 | if (carry > 0) { |
696 | carry = (int)bn_sub_words(r_d, r_d, _nist_p_224[carry - 1], | 726 | carry = (int)bn_sub_words(r_d, r_d, _nist_p_224[carry - 1], |
697 | BN_NIST_224_TOP); | 727 | BN_NIST_224_TOP); |
@@ -707,14 +737,13 @@ BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
707 | * adjusted by *subtracting* the latter. */ | 737 | * adjusted by *subtracting* the latter. */ |
708 | carry = (int)bn_add_words(r_d, r_d, _nist_p_224[-carry - 1], | 738 | carry = (int)bn_add_words(r_d, r_d, _nist_p_224[-carry - 1], |
709 | BN_NIST_224_TOP); | 739 | BN_NIST_224_TOP); |
710 | mask = 0 - (uintptr_t)carry; | 740 | if (carry == 0) |
711 | u.p = ((uintptr_t)bn_sub_words & mask) | | 741 | addsubf = bn_add_words; |
712 | ((uintptr_t)bn_add_words & ~mask); | ||
713 | } else | 742 | } else |
714 | carry = 1; | 743 | carry = 1; |
715 | 744 | ||
716 | /* otherwise it's effectively same as in BN_nist_mod_192... */ | 745 | /* otherwise it's effectively same as in BN_nist_mod_192... */ |
717 | mask = 0 - (uintptr_t)(*u.f)(c_d, r_d, _nist_p_224[0], BN_NIST_224_TOP); | 746 | mask = 0 - (uintptr_t)(*addsubf)(c_d, r_d, _nist_p_224[0], BN_NIST_224_TOP); |
718 | mask &= 0 - (uintptr_t)carry; | 747 | mask &= 0 - (uintptr_t)carry; |
719 | res = c_d; | 748 | res = c_d; |
720 | res = (BN_ULONG *)(((uintptr_t)res & ~mask) | ((uintptr_t)r_d & mask)); | 749 | res = (BN_ULONG *)(((uintptr_t)res & ~mask) | ((uintptr_t)r_d & mask)); |
@@ -743,17 +772,10 @@ BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
743 | int i, top = a->top; | 772 | int i, top = a->top; |
744 | int carry = 0; | 773 | int carry = 0; |
745 | BN_ULONG *a_d = a->d, *r_d; | 774 | BN_ULONG *a_d = a->d, *r_d; |
746 | union { | 775 | BN_ULONG bnbuf[BN_NIST_256_TOP] = { 0 }; |
747 | BN_ULONG bn[BN_NIST_256_TOP]; | ||
748 | unsigned int ui[BN_NIST_256_TOP * | ||
749 | sizeof(BN_ULONG) / sizeof(unsigned int)]; | ||
750 | } buf; | ||
751 | BN_ULONG c_d[BN_NIST_256_TOP] = {0}, *res; | 776 | BN_ULONG c_d[BN_NIST_256_TOP] = {0}, *res; |
752 | uintptr_t mask; | 777 | uintptr_t mask; |
753 | union { | 778 | bn_addsub_f addsubf; |
754 | bn_addsub_f f; | ||
755 | uintptr_t p; | ||
756 | } u; | ||
757 | static const BIGNUM _bignum_nist_p_256_sqr = { | 779 | static const BIGNUM _bignum_nist_p_256_sqr = { |
758 | (BN_ULONG *)_nist_p_256_sqr, | 780 | (BN_ULONG *)_nist_p_256_sqr, |
759 | sizeof(_nist_p_256_sqr) / sizeof(_nist_p_256_sqr[0]), | 781 | sizeof(_nist_p_256_sqr) / sizeof(_nist_p_256_sqr[0]), |
@@ -782,14 +804,31 @@ BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
782 | } else | 804 | } else |
783 | r_d = a_d; | 805 | r_d = a_d; |
784 | 806 | ||
785 | nist_cp_bn_0(buf.bn, a_d + BN_NIST_256_TOP, | 807 | nist_cp_bn_0(bnbuf, a_d + BN_NIST_256_TOP, |
786 | top - BN_NIST_256_TOP, BN_NIST_256_TOP); | 808 | top - BN_NIST_256_TOP, BN_NIST_256_TOP); |
787 | 809 | ||
788 | #if defined(NIST_INT64) | 810 | #if defined(NIST_INT64) |
789 | { | 811 | { |
790 | NIST_INT64 acc; /* accumulator */ | 812 | NIST_INT64 acc; /* accumulator */ |
791 | unsigned int *rp = (unsigned int *)r_d; | 813 | unsigned int bbuf[BN_NIST_256_TOP * |
792 | const unsigned int *bp = (const unsigned int *)buf.ui; | 814 | sizeof(BN_ULONG) / sizeof(unsigned int)]; |
815 | unsigned int rbuf[BN_NIST_256_TOP * | ||
816 | sizeof(BN_ULONG) / sizeof(unsigned int)]; | ||
817 | const unsigned int *bp = bbuf; | ||
818 | unsigned int *rp = rbuf; | ||
819 | |||
820 | CTASSERT(sizeof(bbuf) == sizeof(bnbuf)); | ||
821 | CTASSERT(sizeof(rbuf) == sizeof(bnbuf)); | ||
822 | |||
823 | /* | ||
824 | * Avoid strict aliasing violations by copying from an unsigned | ||
825 | * long array to an unsigned int array, then copying back the | ||
826 | * result. Any sensible compiler will omit the copies, while | ||
827 | * avoiding undefined behaviour that would result from unsafe | ||
828 | * type punning via pointer type casting. | ||
829 | */ | ||
830 | memcpy(bbuf, bnbuf, sizeof(bbuf)); | ||
831 | memcpy(rbuf, r_d, sizeof(rbuf)); | ||
793 | 832 | ||
794 | acc = rp[0]; | 833 | acc = rp[0]; |
795 | acc += bp[8 - 8]; | 834 | acc += bp[8 - 8]; |
@@ -877,6 +916,8 @@ BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
877 | acc -= bp[13 - 8]; | 916 | acc -= bp[13 - 8]; |
878 | rp[7] = (unsigned int)acc; | 917 | rp[7] = (unsigned int)acc; |
879 | 918 | ||
919 | memcpy(r_d, rbuf, sizeof(rbuf)); | ||
920 | |||
880 | carry = (int)(acc >> 32); | 921 | carry = (int)(acc >> 32); |
881 | } | 922 | } |
882 | #else | 923 | #else |
@@ -884,9 +925,9 @@ BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
884 | BN_ULONG t_d[BN_NIST_256_TOP] = {0}; | 925 | BN_ULONG t_d[BN_NIST_256_TOP] = {0}; |
885 | 926 | ||
886 | /*S1*/ | 927 | /*S1*/ |
887 | nist_set_256(t_d, buf.bn, 15, 14, 13, 12, 11, 0, 0, 0); | 928 | nist_set_256(t_d, bnbuf, 15, 14, 13, 12, 11, 0, 0, 0); |
888 | /*S2*/ | 929 | /*S2*/ |
889 | nist_set_256(c_d, buf.bn, 0, 15, 14, 13, 12, 0, 0, 0); | 930 | nist_set_256(c_d, bnbuf, 0, 15, 14, 13, 12, 0, 0, 0); |
890 | carry = (int)bn_add_words(t_d, t_d, c_d, BN_NIST_256_TOP); | 931 | carry = (int)bn_add_words(t_d, t_d, c_d, BN_NIST_256_TOP); |
891 | /* left shift */ | 932 | /* left shift */ |
892 | { | 933 | { |
@@ -903,41 +944,40 @@ BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
903 | } | 944 | } |
904 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP); | 945 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP); |
905 | /*S3*/ | 946 | /*S3*/ |
906 | nist_set_256(t_d, buf.bn, 15, 14, 0, 0, 0, 10, 9, 8); | 947 | nist_set_256(t_d, bnbuf, 15, 14, 0, 0, 0, 10, 9, 8); |
907 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP); | 948 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP); |
908 | /*S4*/ | 949 | /*S4*/ |
909 | nist_set_256(t_d, buf.bn, 8, 13, 15, 14, 13, 11, 10, 9); | 950 | nist_set_256(t_d, bnbuf, 8, 13, 15, 14, 13, 11, 10, 9); |
910 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP); | 951 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP); |
911 | /*D1*/ | 952 | /*D1*/ |
912 | nist_set_256(t_d, buf.bn, 10, 8, 0, 0, 0, 13, 12, 11); | 953 | nist_set_256(t_d, bnbuf, 10, 8, 0, 0, 0, 13, 12, 11); |
913 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP); | 954 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP); |
914 | /*D2*/ | 955 | /*D2*/ |
915 | nist_set_256(t_d, buf.bn, 11, 9, 0, 0, 15, 14, 13, 12); | 956 | nist_set_256(t_d, bnbuf, 11, 9, 0, 0, 15, 14, 13, 12); |
916 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP); | 957 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP); |
917 | /*D3*/ | 958 | /*D3*/ |
918 | nist_set_256(t_d, buf.bn, 12, 0, 10, 9, 8, 15, 14, 13); | 959 | nist_set_256(t_d, bnbuf, 12, 0, 10, 9, 8, 15, 14, 13); |
919 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP); | 960 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP); |
920 | /*D4*/ | 961 | /*D4*/ |
921 | nist_set_256(t_d, buf.bn, 13, 0, 11, 10, 9, 0, 15, 14); | 962 | nist_set_256(t_d, bnbuf, 13, 0, 11, 10, 9, 0, 15, 14); |
922 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP); | 963 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP); |
923 | 964 | ||
924 | } | 965 | } |
925 | #endif | 966 | #endif |
926 | /* see BN_nist_mod_224 for explanation */ | 967 | /* see BN_nist_mod_224 for explanation */ |
927 | u.f = bn_sub_words; | 968 | addsubf = bn_sub_words; |
928 | if (carry > 0) | 969 | if (carry > 0) |
929 | carry = (int)bn_sub_words(r_d, r_d, _nist_p_256[carry - 1], | 970 | carry = (int)bn_sub_words(r_d, r_d, _nist_p_256[carry - 1], |
930 | BN_NIST_256_TOP); | 971 | BN_NIST_256_TOP); |
931 | else if (carry < 0) { | 972 | else if (carry < 0) { |
932 | carry = (int)bn_add_words(r_d, r_d, _nist_p_256[-carry - 1], | 973 | carry = (int)bn_add_words(r_d, r_d, _nist_p_256[-carry - 1], |
933 | BN_NIST_256_TOP); | 974 | BN_NIST_256_TOP); |
934 | mask = 0 - (uintptr_t)carry; | 975 | if (carry == 0) |
935 | u.p = ((uintptr_t)bn_sub_words & mask) | | 976 | addsubf = bn_add_words; |
936 | ((uintptr_t)bn_add_words & ~mask); | ||
937 | } else | 977 | } else |
938 | carry = 1; | 978 | carry = 1; |
939 | 979 | ||
940 | mask = 0 - (uintptr_t)(*u.f)(c_d, r_d, _nist_p_256[0], BN_NIST_256_TOP); | 980 | mask = 0 - (uintptr_t)(*addsubf)(c_d, r_d, _nist_p_256[0], BN_NIST_256_TOP); |
941 | mask &= 0 - (uintptr_t)carry; | 981 | mask &= 0 - (uintptr_t)carry; |
942 | res = c_d; | 982 | res = c_d; |
943 | res = (BN_ULONG *)(((uintptr_t)res & ~mask) | ((uintptr_t)r_d & mask)); | 983 | res = (BN_ULONG *)(((uintptr_t)res & ~mask) | ((uintptr_t)r_d & mask)); |
@@ -970,17 +1010,10 @@ BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
970 | int i, top = a->top; | 1010 | int i, top = a->top; |
971 | int carry = 0; | 1011 | int carry = 0; |
972 | BN_ULONG *r_d, *a_d = a->d; | 1012 | BN_ULONG *r_d, *a_d = a->d; |
973 | union { | 1013 | BN_ULONG bnbuf[BN_NIST_384_TOP] = { 0 }; |
974 | BN_ULONG bn[BN_NIST_384_TOP]; | ||
975 | unsigned int ui[BN_NIST_384_TOP * | ||
976 | sizeof(BN_ULONG) / sizeof(unsigned int)]; | ||
977 | } buf; | ||
978 | BN_ULONG c_d[BN_NIST_384_TOP], *res; | 1014 | BN_ULONG c_d[BN_NIST_384_TOP], *res; |
979 | uintptr_t mask; | 1015 | uintptr_t mask; |
980 | union { | 1016 | bn_addsub_f addsubf; |
981 | bn_addsub_f f; | ||
982 | uintptr_t p; | ||
983 | } u; | ||
984 | static const BIGNUM _bignum_nist_p_384_sqr = { | 1017 | static const BIGNUM _bignum_nist_p_384_sqr = { |
985 | (BN_ULONG *)_nist_p_384_sqr, | 1018 | (BN_ULONG *)_nist_p_384_sqr, |
986 | sizeof(_nist_p_384_sqr) / sizeof(_nist_p_384_sqr[0]), | 1019 | sizeof(_nist_p_384_sqr) / sizeof(_nist_p_384_sqr[0]), |
@@ -1009,14 +1042,31 @@ BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
1009 | } else | 1042 | } else |
1010 | r_d = a_d; | 1043 | r_d = a_d; |
1011 | 1044 | ||
1012 | nist_cp_bn_0(buf.bn, a_d + BN_NIST_384_TOP, | 1045 | nist_cp_bn_0(bnbuf, a_d + BN_NIST_384_TOP, |
1013 | top - BN_NIST_384_TOP, BN_NIST_384_TOP); | 1046 | top - BN_NIST_384_TOP, BN_NIST_384_TOP); |
1014 | 1047 | ||
1015 | #if defined(NIST_INT64) | 1048 | #if defined(NIST_INT64) |
1016 | { | 1049 | { |
1017 | NIST_INT64 acc; /* accumulator */ | 1050 | NIST_INT64 acc; /* accumulator */ |
1018 | unsigned int *rp = (unsigned int *)r_d; | 1051 | unsigned int bbuf[BN_NIST_384_TOP * |
1019 | const unsigned int *bp = (const unsigned int *)buf.ui; | 1052 | sizeof(BN_ULONG) / sizeof(unsigned int)]; |
1053 | unsigned int rbuf[BN_NIST_384_TOP * | ||
1054 | sizeof(BN_ULONG) / sizeof(unsigned int)]; | ||
1055 | const unsigned int *bp = bbuf; | ||
1056 | unsigned int *rp = rbuf; | ||
1057 | |||
1058 | CTASSERT(sizeof(bbuf) == sizeof(bnbuf)); | ||
1059 | CTASSERT(sizeof(rbuf) == sizeof(bnbuf)); | ||
1060 | |||
1061 | /* | ||
1062 | * Avoid strict aliasing violations by copying from an unsigned | ||
1063 | * long array to an unsigned int array, then copying back the | ||
1064 | * result. Any sensible compiler will omit the copies, while | ||
1065 | * avoiding undefined behaviour that would result from unsafe | ||
1066 | * type punning via pointer type casting. | ||
1067 | */ | ||
1068 | memcpy(bbuf, bnbuf, sizeof(bbuf)); | ||
1069 | memcpy(rbuf, r_d, sizeof(rbuf)); | ||
1020 | 1070 | ||
1021 | acc = rp[0]; | 1071 | acc = rp[0]; |
1022 | acc += bp[12 - 12]; | 1072 | acc += bp[12 - 12]; |
@@ -1131,6 +1181,8 @@ BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
1131 | acc -= bp[22 - 12]; | 1181 | acc -= bp[22 - 12]; |
1132 | rp[11] = (unsigned int)acc; | 1182 | rp[11] = (unsigned int)acc; |
1133 | 1183 | ||
1184 | memcpy(r_d, rbuf, sizeof(rbuf)); | ||
1185 | |||
1134 | carry = (int)(acc >> 32); | 1186 | carry = (int)(acc >> 32); |
1135 | } | 1187 | } |
1136 | #else | 1188 | #else |
@@ -1138,7 +1190,7 @@ BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
1138 | BN_ULONG t_d[BN_NIST_384_TOP] = {0}; | 1190 | BN_ULONG t_d[BN_NIST_384_TOP] = {0}; |
1139 | 1191 | ||
1140 | /*S1*/ | 1192 | /*S1*/ |
1141 | nist_set_256(t_d, buf.bn, 0, 0, 0, 0, 0, 23 - 4, 22 - 4, | 1193 | nist_set_256(t_d, bnbuf, 0, 0, 0, 0, 0, 23 - 4, 22 - 4, |
1142 | 21 - 4); | 1194 | 21 - 4); |
1143 | /* left shift */ | 1195 | /* left shift */ |
1144 | { | 1196 | { |
@@ -1155,49 +1207,48 @@ BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) | |||
1155 | carry = (int)bn_add_words(r_d + (128 / BN_BITS2), | 1207 | carry = (int)bn_add_words(r_d + (128 / BN_BITS2), |
1156 | r_d + (128 / BN_BITS2), t_d, BN_NIST_256_TOP); | 1208 | r_d + (128 / BN_BITS2), t_d, BN_NIST_256_TOP); |
1157 | /*S2 */ | 1209 | /*S2 */ |
1158 | carry += (int)bn_add_words(r_d, r_d, buf.bn, BN_NIST_384_TOP); | 1210 | carry += (int)bn_add_words(r_d, r_d, bnbuf, BN_NIST_384_TOP); |
1159 | /*S3*/ | 1211 | /*S3*/ |
1160 | nist_set_384(t_d, buf.bn, 20, 19, 18, 17, 16, 15, 14, 13, 12, | 1212 | nist_set_384(t_d, bnbuf, 20, 19, 18, 17, 16, 15, 14, 13, 12, |
1161 | 23, 22, 21); | 1213 | 23, 22, 21); |
1162 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP); | 1214 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP); |
1163 | /*S4*/ | 1215 | /*S4*/ |
1164 | nist_set_384(t_d, buf.bn, 19, 18, 17, 16, 15, 14, 13, 12, 20, | 1216 | nist_set_384(t_d, bnbuf, 19, 18, 17, 16, 15, 14, 13, 12, 20, |
1165 | 0, 23, 0); | 1217 | 0, 23, 0); |
1166 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP); | 1218 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP); |
1167 | /*S5*/ | 1219 | /*S5*/ |
1168 | nist_set_384(t_d, buf.bn, 0,0, 0,0, 23, 22, 21, 20, 0,0, 0, 0); | 1220 | nist_set_384(t_d, bnbuf, 0,0, 0,0, 23, 22, 21, 20, 0,0, 0, 0); |
1169 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP); | 1221 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP); |
1170 | /*S6*/ | 1222 | /*S6*/ |
1171 | nist_set_384(t_d, buf.bn, 0,0, 0,0, 0,0, 23, 22, 21, 0,0, 20); | 1223 | nist_set_384(t_d, bnbuf, 0,0, 0,0, 0,0, 23, 22, 21, 0,0, 20); |
1172 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP); | 1224 | carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP); |
1173 | /*D1*/ | 1225 | /*D1*/ |
1174 | nist_set_384(t_d, buf.bn, 22, 21, 20, 19, 18, 17, 16, 15, 14, | 1226 | nist_set_384(t_d, bnbuf, 22, 21, 20, 19, 18, 17, 16, 15, 14, |
1175 | 13, 12, 23); | 1227 | 13, 12, 23); |
1176 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP); | 1228 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP); |
1177 | /*D2*/ | 1229 | /*D2*/ |
1178 | nist_set_384(t_d, buf.bn, 0,0, 0,0, 0,0, 0,23, 22, 21, 20, 0); | 1230 | nist_set_384(t_d, bnbuf, 0,0, 0,0, 0,0, 0,23, 22, 21, 20, 0); |
1179 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP); | 1231 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP); |
1180 | /*D3*/ | 1232 | /*D3*/ |
1181 | nist_set_384(t_d, buf.bn, 0,0, 0,0, 0,0, 0,23, 23, 0,0, 0); | 1233 | nist_set_384(t_d, bnbuf, 0,0, 0,0, 0,0, 0,23, 23, 0,0, 0); |
1182 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP); | 1234 | carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP); |
1183 | 1235 | ||
1184 | } | 1236 | } |
1185 | #endif | 1237 | #endif |
1186 | /* see BN_nist_mod_224 for explanation */ | 1238 | /* see BN_nist_mod_224 for explanation */ |
1187 | u.f = bn_sub_words; | 1239 | addsubf = bn_sub_words; |
1188 | if (carry > 0) | 1240 | if (carry > 0) |
1189 | carry = (int)bn_sub_words(r_d, r_d, _nist_p_384[carry - 1], | 1241 | carry = (int)bn_sub_words(r_d, r_d, _nist_p_384[carry - 1], |
1190 | BN_NIST_384_TOP); | 1242 | BN_NIST_384_TOP); |
1191 | else if (carry < 0) { | 1243 | else if (carry < 0) { |
1192 | carry = (int)bn_add_words(r_d, r_d, _nist_p_384[-carry - 1], | 1244 | carry = (int)bn_add_words(r_d, r_d, _nist_p_384[-carry - 1], |
1193 | BN_NIST_384_TOP); | 1245 | BN_NIST_384_TOP); |
1194 | mask = 0 - (uintptr_t)carry; | 1246 | if (carry == 0) |
1195 | u.p = ((uintptr_t)bn_sub_words & mask) | | 1247 | addsubf = bn_add_words; |
1196 | ((uintptr_t)bn_add_words & ~mask); | ||
1197 | } else | 1248 | } else |
1198 | carry = 1; | 1249 | carry = 1; |
1199 | 1250 | ||
1200 | mask = 0 - (uintptr_t)(*u.f)(c_d, r_d, _nist_p_384[0], BN_NIST_384_TOP); | 1251 | mask = 0 - (uintptr_t)(*addsubf)(c_d, r_d, _nist_p_384[0], BN_NIST_384_TOP); |
1201 | mask &= 0 - (uintptr_t)carry; | 1252 | mask &= 0 - (uintptr_t)carry; |
1202 | res = c_d; | 1253 | res = c_d; |
1203 | res = (BN_ULONG *)(((uintptr_t)res & ~mask) | ((uintptr_t)r_d & mask)); | 1254 | res = (BN_ULONG *)(((uintptr_t)res & ~mask) | ((uintptr_t)r_d & mask)); |