summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bn/bn_exp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/bn/bn_exp.c')
-rw-r--r--src/lib/libcrypto/bn/bn_exp.c240
1 files changed, 67 insertions, 173 deletions
diff --git a/src/lib/libcrypto/bn/bn_exp.c b/src/lib/libcrypto/bn/bn_exp.c
index 2abf6fd678..d9b6c737fc 100644
--- a/src/lib/libcrypto/bn/bn_exp.c
+++ b/src/lib/libcrypto/bn/bn_exp.c
@@ -113,18 +113,6 @@
113#include "cryptlib.h" 113#include "cryptlib.h"
114#include "bn_lcl.h" 114#include "bn_lcl.h"
115 115
116#include <stdlib.h>
117#ifdef _WIN32
118# include <malloc.h>
119# ifndef alloca
120# define alloca _alloca
121# endif
122#elif defined(__GNUC__)
123# ifndef alloca
124# define alloca(s) __builtin_alloca((s))
125# endif
126#endif
127
128/* maximum precomputation table size for *variable* sliding windows */ 116/* maximum precomputation table size for *variable* sliding windows */
129#define TABLE_SIZE 32 117#define TABLE_SIZE 32
130 118
@@ -534,17 +522,23 @@ err:
534 * as cache lines are concerned. The following functions are used to transfer a BIGNUM 522 * as cache lines are concerned. The following functions are used to transfer a BIGNUM
535 * from/to that table. */ 523 * from/to that table. */
536 524
537static int MOD_EXP_CTIME_COPY_TO_PREBUF(const BIGNUM *b, int top, unsigned char *buf, int idx, int width) 525static int MOD_EXP_CTIME_COPY_TO_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx, int width)
538 { 526 {
539 size_t i, j; 527 size_t i, j;
540 528
541 if (top > b->top) 529 if (bn_wexpand(b, top) == NULL)
542 top = b->top; /* this works because 'buf' is explicitly zeroed */ 530 return 0;
531 while (b->top < top)
532 {
533 b->d[b->top++] = 0;
534 }
535
543 for (i = 0, j=idx; i < top * sizeof b->d[0]; i++, j+=width) 536 for (i = 0, j=idx; i < top * sizeof b->d[0]; i++, j+=width)
544 { 537 {
545 buf[j] = ((unsigned char*)b->d)[i]; 538 buf[j] = ((unsigned char*)b->d)[i];
546 } 539 }
547 540
541 bn_correct_top(b);
548 return 1; 542 return 1;
549 } 543 }
550 544
@@ -567,7 +561,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, unsigned char *buf
567 561
568/* Given a pointer value, compute the next address that is a cache line multiple. */ 562/* Given a pointer value, compute the next address that is a cache line multiple. */
569#define MOD_EXP_CTIME_ALIGN(x_) \ 563#define MOD_EXP_CTIME_ALIGN(x_) \
570 ((unsigned char*)(x_) + (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - (((size_t)(x_)) & (MOD_EXP_CTIME_MIN_CACHE_LINE_MASK)))) 564 ((unsigned char*)(x_) + (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - (((BN_ULONG)(x_)) & (MOD_EXP_CTIME_MIN_CACHE_LINE_MASK))))
571 565
572/* This variant of BN_mod_exp_mont() uses fixed windows and the special 566/* This variant of BN_mod_exp_mont() uses fixed windows and the special
573 * precomputation memory layout to limit data-dependency to a minimum 567 * precomputation memory layout to limit data-dependency to a minimum
@@ -578,15 +572,17 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, unsigned char *buf
578int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, 572int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
579 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) 573 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
580 { 574 {
581 int i,bits,ret=0,window,wvalue; 575 int i,bits,ret=0,idx,window,wvalue;
582 int top; 576 int top;
577 BIGNUM *r;
578 const BIGNUM *aa;
583 BN_MONT_CTX *mont=NULL; 579 BN_MONT_CTX *mont=NULL;
584 580
585 int numPowers; 581 int numPowers;
586 unsigned char *powerbufFree=NULL; 582 unsigned char *powerbufFree=NULL;
587 int powerbufLen = 0; 583 int powerbufLen = 0;
588 unsigned char *powerbuf=NULL; 584 unsigned char *powerbuf=NULL;
589 BIGNUM tmp, am; 585 BIGNUM *computeTemp=NULL, *am=NULL;
590 586
591 bn_check_top(a); 587 bn_check_top(a);
592 bn_check_top(p); 588 bn_check_top(p);
@@ -606,7 +602,10 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
606 return ret; 602 return ret;
607 } 603 }
608 604
605 /* Initialize BIGNUM context and allocate intermediate result */
609 BN_CTX_start(ctx); 606 BN_CTX_start(ctx);
607 r = BN_CTX_get(ctx);
608 if (r == NULL) goto err;
610 609
611 /* Allocate a montgomery context if it was not supplied by the caller. 610 /* Allocate a montgomery context if it was not supplied by the caller.
612 * If this is not done, things will break in the montgomery part. 611 * If this is not done, things will break in the montgomery part.
@@ -621,154 +620,40 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
621 620
622 /* Get the window size to use with size of p. */ 621 /* Get the window size to use with size of p. */
623 window = BN_window_bits_for_ctime_exponent_size(bits); 622 window = BN_window_bits_for_ctime_exponent_size(bits);
624#if defined(OPENSSL_BN_ASM_MONT5)
625 if (window==6 && bits<=1024) window=5; /* ~5% improvement of 2048-bit RSA sign */
626#endif
627 623
628 /* Allocate a buffer large enough to hold all of the pre-computed 624 /* Allocate a buffer large enough to hold all of the pre-computed
629 * powers of am, am itself and tmp. 625 * powers of a.
630 */ 626 */
631 numPowers = 1 << window; 627 numPowers = 1 << window;
632 powerbufLen = sizeof(m->d[0])*(top*numPowers + 628 powerbufLen = sizeof(m->d[0])*top*numPowers;
633 ((2*top)>numPowers?(2*top):numPowers));
634#ifdef alloca
635 if (powerbufLen < 3072)
636 powerbufFree = alloca(powerbufLen+MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH);
637 else
638#endif
639 if ((powerbufFree=(unsigned char*)OPENSSL_malloc(powerbufLen+MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL) 629 if ((powerbufFree=(unsigned char*)OPENSSL_malloc(powerbufLen+MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL)
640 goto err; 630 goto err;
641 631
642 powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree); 632 powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree);
643 memset(powerbuf, 0, powerbufLen); 633 memset(powerbuf, 0, powerbufLen);
644 634
645#ifdef alloca 635 /* Initialize the intermediate result. Do this early to save double conversion,
646 if (powerbufLen < 3072) 636 * once each for a^0 and intermediate result.
647 powerbufFree = NULL; 637 */
648#endif 638 if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err;
639 if (!MOD_EXP_CTIME_COPY_TO_PREBUF(r, top, powerbuf, 0, numPowers)) goto err;
649 640
650 /* lay down tmp and am right after powers table */ 641 /* Initialize computeTemp as a^1 with montgomery precalcs */
651 tmp.d = (BN_ULONG *)(powerbuf + sizeof(m->d[0])*top*numPowers); 642 computeTemp = BN_CTX_get(ctx);
652 am.d = tmp.d + top; 643 am = BN_CTX_get(ctx);
653 tmp.top = am.top = 0; 644 if (computeTemp==NULL || am==NULL) goto err;
654 tmp.dmax = am.dmax = top;
655 tmp.neg = am.neg = 0;
656 tmp.flags = am.flags = BN_FLG_STATIC_DATA;
657
658 /* prepare a^0 in Montgomery domain */
659#if 1
660 if (!BN_to_montgomery(&tmp,BN_value_one(),mont,ctx)) goto err;
661#else
662 tmp.d[0] = (0-m->d[0])&BN_MASK2; /* 2^(top*BN_BITS2) - m */
663 for (i=1;i<top;i++)
664 tmp.d[i] = (~m->d[i])&BN_MASK2;
665 tmp.top = top;
666#endif
667 645
668 /* prepare a^1 in Montgomery domain */
669 if (a->neg || BN_ucmp(a,m) >= 0) 646 if (a->neg || BN_ucmp(a,m) >= 0)
670 { 647 {
671 if (!BN_mod(&am,a,m,ctx)) goto err; 648 if (!BN_mod(am,a,m,ctx))
672 if (!BN_to_montgomery(&am,&am,mont,ctx)) goto err; 649 goto err;
673 } 650 aa= am;
674 else if (!BN_to_montgomery(&am,a,mont,ctx)) goto err;
675
676#if defined(OPENSSL_BN_ASM_MONT5)
677 /* This optimization uses ideas from http://eprint.iacr.org/2011/239,
678 * specifically optimization of cache-timing attack countermeasures
679 * and pre-computation optimization. */
680
681 /* Dedicated window==4 case improves 512-bit RSA sign by ~15%, but as
682 * 512-bit RSA is hardly relevant, we omit it to spare size... */
683 if (window==5)
684 {
685 void bn_mul_mont_gather5(BN_ULONG *rp,const BN_ULONG *ap,
686 const void *table,const BN_ULONG *np,
687 const BN_ULONG *n0,int num,int power);
688 void bn_scatter5(const BN_ULONG *inp,size_t num,
689 void *table,size_t power);
690 void bn_gather5(BN_ULONG *out,size_t num,
691 void *table,size_t power);
692
693 BN_ULONG *np=mont->N.d, *n0=mont->n0;
694
695 /* BN_to_montgomery can contaminate words above .top
696 * [in BN_DEBUG[_DEBUG] build]... */
697 for (i=am.top; i<top; i++) am.d[i]=0;
698 for (i=tmp.top; i<top; i++) tmp.d[i]=0;
699
700 bn_scatter5(tmp.d,top,powerbuf,0);
701 bn_scatter5(am.d,am.top,powerbuf,1);
702 bn_mul_mont(tmp.d,am.d,am.d,np,n0,top);
703 bn_scatter5(tmp.d,top,powerbuf,2);
704
705#if 0
706 for (i=3; i<32; i++)
707 {
708 /* Calculate a^i = a^(i-1) * a */
709 bn_mul_mont_gather5(tmp.d,am.d,powerbuf,np,n0,top,i-1);
710 bn_scatter5(tmp.d,top,powerbuf,i);
711 }
712#else
713 /* same as above, but uses squaring for 1/2 of operations */
714 for (i=4; i<32; i*=2)
715 {
716 bn_mul_mont(tmp.d,tmp.d,tmp.d,np,n0,top);
717 bn_scatter5(tmp.d,top,powerbuf,i);
718 }
719 for (i=3; i<8; i+=2)
720 {
721 int j;
722 bn_mul_mont_gather5(tmp.d,am.d,powerbuf,np,n0,top,i-1);
723 bn_scatter5(tmp.d,top,powerbuf,i);
724 for (j=2*i; j<32; j*=2)
725 {
726 bn_mul_mont(tmp.d,tmp.d,tmp.d,np,n0,top);
727 bn_scatter5(tmp.d,top,powerbuf,j);
728 }
729 }
730 for (; i<16; i+=2)
731 {
732 bn_mul_mont_gather5(tmp.d,am.d,powerbuf,np,n0,top,i-1);
733 bn_scatter5(tmp.d,top,powerbuf,i);
734 bn_mul_mont(tmp.d,tmp.d,tmp.d,np,n0,top);
735 bn_scatter5(tmp.d,top,powerbuf,2*i);
736 }
737 for (; i<32; i+=2)
738 {
739 bn_mul_mont_gather5(tmp.d,am.d,powerbuf,np,n0,top,i-1);
740 bn_scatter5(tmp.d,top,powerbuf,i);
741 }
742#endif
743 bits--;
744 for (wvalue=0, i=bits%5; i>=0; i--,bits--)
745 wvalue = (wvalue<<1)+BN_is_bit_set(p,bits);
746 bn_gather5(tmp.d,top,powerbuf,wvalue);
747
748 /* Scan the exponent one window at a time starting from the most
749 * significant bits.
750 */
751 while (bits >= 0)
752 {
753 for (wvalue=0, i=0; i<5; i++,bits--)
754 wvalue = (wvalue<<1)+BN_is_bit_set(p,bits);
755
756 bn_mul_mont(tmp.d,tmp.d,tmp.d,np,n0,top);
757 bn_mul_mont(tmp.d,tmp.d,tmp.d,np,n0,top);
758 bn_mul_mont(tmp.d,tmp.d,tmp.d,np,n0,top);
759 bn_mul_mont(tmp.d,tmp.d,tmp.d,np,n0,top);
760 bn_mul_mont(tmp.d,tmp.d,tmp.d,np,n0,top);
761 bn_mul_mont_gather5(tmp.d,tmp.d,powerbuf,np,n0,top,wvalue);
762 } 651 }
763 652 else
764 tmp.top=top; 653 aa=a;
765 bn_correct_top(&tmp); 654 if (!BN_to_montgomery(am,aa,mont,ctx)) goto err;
766 } 655 if (!BN_copy(computeTemp, am)) goto err;
767 else 656 if (!MOD_EXP_CTIME_COPY_TO_PREBUF(am, top, powerbuf, 1, numPowers)) goto err;
768#endif
769 {
770 if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 0, numPowers)) goto err;
771 if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&am, top, powerbuf, 1, numPowers)) goto err;
772 657
773 /* If the window size is greater than 1, then calculate 658 /* If the window size is greater than 1, then calculate
774 * val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1) 659 * val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1)
@@ -777,54 +662,62 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
777 */ 662 */
778 if (window > 1) 663 if (window > 1)
779 { 664 {
780 if (!BN_mod_mul_montgomery(&tmp,&am,&am,mont,ctx)) goto err; 665 for (i=2; i<numPowers; i++)
781 if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 2, numPowers)) goto err;
782 for (i=3; i<numPowers; i++)
783 { 666 {
784 /* Calculate a^i = a^(i-1) * a */ 667 /* Calculate a^i = a^(i-1) * a */
785 if (!BN_mod_mul_montgomery(&tmp,&am,&tmp,mont,ctx)) 668 if (!BN_mod_mul_montgomery(computeTemp,am,computeTemp,mont,ctx))
786 goto err; 669 goto err;
787 if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, i, numPowers)) goto err; 670 if (!MOD_EXP_CTIME_COPY_TO_PREBUF(computeTemp, top, powerbuf, i, numPowers)) goto err;
788 } 671 }
789 } 672 }
790 673
791 bits--; 674 /* Adjust the number of bits up to a multiple of the window size.
792 for (wvalue=0, i=bits%window; i>=0; i--,bits--) 675 * If the exponent length is not a multiple of the window size, then
793 wvalue = (wvalue<<1)+BN_is_bit_set(p,bits); 676 * this pads the most significant bits with zeros to normalize the
794 if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&tmp,top,powerbuf,wvalue,numPowers)) goto err; 677 * scanning loop to there's no special cases.
795 678 *
796 /* Scan the exponent one window at a time starting from the most 679 * * NOTE: Making the window size a power of two less than the native
797 * significant bits. 680 * * word size ensures that the padded bits won't go past the last
798 */ 681 * * word in the internal BIGNUM structure. Going past the end will
799 while (bits >= 0) 682 * * still produce the correct result, but causes a different branch
683 * * to be taken in the BN_is_bit_set function.
684 */
685 bits = ((bits+window-1)/window)*window;
686 idx=bits-1; /* The top bit of the window */
687
688 /* Scan the exponent one window at a time starting from the most
689 * significant bits.
690 */
691 while (idx >= 0)
800 { 692 {
801 wvalue=0; /* The 'value' of the window */ 693 wvalue=0; /* The 'value' of the window */
802 694
803 /* Scan the window, squaring the result as we go */ 695 /* Scan the window, squaring the result as we go */
804 for (i=0; i<window; i++,bits--) 696 for (i=0; i<window; i++,idx--)
805 { 697 {
806 if (!BN_mod_mul_montgomery(&tmp,&tmp,&tmp,mont,ctx)) goto err; 698 if (!BN_mod_mul_montgomery(r,r,r,mont,ctx)) goto err;
807 wvalue = (wvalue<<1)+BN_is_bit_set(p,bits); 699 wvalue = (wvalue<<1)+BN_is_bit_set(p,idx);
808 } 700 }
809 701
810 /* Fetch the appropriate pre-computed value from the pre-buf */ 702 /* Fetch the appropriate pre-computed value from the pre-buf */
811 if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&am, top, powerbuf, wvalue, numPowers)) goto err; 703 if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(computeTemp, top, powerbuf, wvalue, numPowers)) goto err;
812 704
813 /* Multiply the result into the intermediate result */ 705 /* Multiply the result into the intermediate result */
814 if (!BN_mod_mul_montgomery(&tmp,&tmp,&am,mont,ctx)) goto err; 706 if (!BN_mod_mul_montgomery(r,r,computeTemp,mont,ctx)) goto err;
815 } 707 }
816 }
817 708
818 /* Convert the final result from montgomery to standard format */ 709 /* Convert the final result from montgomery to standard format */
819 if (!BN_from_montgomery(rr,&tmp,mont,ctx)) goto err; 710 if (!BN_from_montgomery(rr,r,mont,ctx)) goto err;
820 ret=1; 711 ret=1;
821err: 712err:
822 if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont); 713 if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
823 if (powerbuf!=NULL) 714 if (powerbuf!=NULL)
824 { 715 {
825 OPENSSL_cleanse(powerbuf,powerbufLen); 716 OPENSSL_cleanse(powerbuf,powerbufLen);
826 if (powerbufFree) OPENSSL_free(powerbufFree); 717 OPENSSL_free(powerbufFree);
827 } 718 }
719 if (am!=NULL) BN_clear(am);
720 if (computeTemp!=NULL) BN_clear(computeTemp);
828 BN_CTX_end(ctx); 721 BN_CTX_end(ctx);
829 return(ret); 722 return(ret);
830 } 723 }
@@ -1095,3 +988,4 @@ err:
1095 bn_check_top(r); 988 bn_check_top(r);
1096 return(ret); 989 return(ret);
1097 } 990 }
991