diff options
Diffstat (limited to 'src/lib/libcrypto/bn/bn_exp.c')
| -rw-r--r-- | src/lib/libcrypto/bn/bn_exp.c | 240 |
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 | ||
| 537 | static int MOD_EXP_CTIME_COPY_TO_PREBUF(const BIGNUM *b, int top, unsigned char *buf, int idx, int width) | 525 | static 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 | |||
| 578 | int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, | 572 | int 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; |
| 821 | err: | 712 | err: |
| 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 | |||
