|
Lines 56-62
Link Here
|
| 56 |
* [including the GNU Public Licence.] |
56 |
* [including the GNU Public Licence.] |
| 57 |
*/ |
57 |
*/ |
| 58 |
/* ==================================================================== |
58 |
/* ==================================================================== |
| 59 |
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. |
59 |
* Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. |
| 60 |
* |
60 |
* |
| 61 |
* Redistribution and use in source and binary forms, with or without |
61 |
* Redistribution and use in source and binary forms, with or without |
| 62 |
* modification, are permitted provided that the following conditions |
62 |
* modification, are permitted provided that the following conditions |
|
Lines 113-118
Link Here
|
| 113 |
#include "cryptlib.h" |
113 |
#include "cryptlib.h" |
| 114 |
#include "bn_lcl.h" |
114 |
#include "bn_lcl.h" |
| 115 |
|
115 |
|
|
|
116 |
/* maximum precomputation table size for *variable* sliding windows */ |
| 116 |
#define TABLE_SIZE 32 |
117 |
#define TABLE_SIZE 32 |
| 117 |
|
118 |
|
| 118 |
/* this one works - simple but works */ |
119 |
/* this one works - simple but works */ |
|
Lines 121-126
Link Here
|
| 121 |
int i,bits,ret=0; |
122 |
int i,bits,ret=0; |
| 122 |
BIGNUM *v,*rr; |
123 |
BIGNUM *v,*rr; |
| 123 |
|
124 |
|
|
|
125 |
if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0) |
| 126 |
{ |
| 127 |
/* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */ |
| 128 |
BNerr(BN_F_BN_EXP,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
| 129 |
return -1; |
| 130 |
} |
| 131 |
|
| 124 |
BN_CTX_start(ctx); |
132 |
BN_CTX_start(ctx); |
| 125 |
if ((r == a) || (r == p)) |
133 |
if ((r == a) || (r == p)) |
| 126 |
rr = BN_CTX_get(ctx); |
134 |
rr = BN_CTX_get(ctx); |
|
Lines 204-210
Link Here
|
| 204 |
if (BN_is_odd(m)) |
212 |
if (BN_is_odd(m)) |
| 205 |
{ |
213 |
{ |
| 206 |
# ifdef MONT_EXP_WORD |
214 |
# ifdef MONT_EXP_WORD |
| 207 |
if (a->top == 1 && !a->neg) |
215 |
if (a->top == 1 && !a->neg && (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) == 0)) |
| 208 |
{ |
216 |
{ |
| 209 |
BN_ULONG A = a->d[0]; |
217 |
BN_ULONG A = a->d[0]; |
| 210 |
ret=BN_mod_exp_mont_word(r,A,p,m,ctx,NULL); |
218 |
ret=BN_mod_exp_mont_word(r,A,p,m,ctx,NULL); |
|
Lines 234-239
Link Here
|
| 234 |
BIGNUM val[TABLE_SIZE]; |
242 |
BIGNUM val[TABLE_SIZE]; |
| 235 |
BN_RECP_CTX recp; |
243 |
BN_RECP_CTX recp; |
| 236 |
|
244 |
|
|
|
245 |
if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0) |
| 246 |
{ |
| 247 |
/* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */ |
| 248 |
BNerr(BN_F_BN_MOD_EXP_RECP,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
| 249 |
return -1; |
| 250 |
} |
| 251 |
|
| 237 |
bits=BN_num_bits(p); |
252 |
bits=BN_num_bits(p); |
| 238 |
|
253 |
|
| 239 |
if (bits == 0) |
254 |
if (bits == 0) |
|
Lines 361-366
Link Here
|
| 361 |
BIGNUM val[TABLE_SIZE]; |
376 |
BIGNUM val[TABLE_SIZE]; |
| 362 |
BN_MONT_CTX *mont=NULL; |
377 |
BN_MONT_CTX *mont=NULL; |
| 363 |
|
378 |
|
|
|
379 |
if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0) |
| 380 |
{ |
| 381 |
return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont); |
| 382 |
} |
| 383 |
|
| 364 |
bn_check_top(a); |
384 |
bn_check_top(a); |
| 365 |
bn_check_top(p); |
385 |
bn_check_top(p); |
| 366 |
bn_check_top(m); |
386 |
bn_check_top(m); |
|
Lines 493-498
Link Here
|
| 493 |
return(ret); |
513 |
return(ret); |
| 494 |
} |
514 |
} |
| 495 |
|
515 |
|
|
|
516 |
|
| 517 |
/* BN_mod_exp_mont_consttime() stores the precomputed powers in a specific layout |
| 518 |
* so that accessing any of these table values shows the same access pattern as far |
| 519 |
* as cache lines are concerned. The following functions are used to transfer a BIGNUM |
| 520 |
* from/to that table. */ |
| 521 |
|
| 522 |
static int MOD_EXP_CTIME_COPY_TO_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx, int width) |
| 523 |
{ |
| 524 |
size_t i, j; |
| 525 |
|
| 526 |
if (bn_wexpand(b, top) == NULL) |
| 527 |
return 0; |
| 528 |
while (b->top < top) |
| 529 |
{ |
| 530 |
b->d[b->top++] = 0; |
| 531 |
} |
| 532 |
|
| 533 |
for (i = 0, j=idx; i < top * sizeof b->d[0]; i++, j+=width) |
| 534 |
{ |
| 535 |
buf[j] = ((unsigned char*)b->d)[i]; |
| 536 |
} |
| 537 |
|
| 538 |
bn_fix_top(b); |
| 539 |
return 1; |
| 540 |
} |
| 541 |
|
| 542 |
static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx, int width) |
| 543 |
{ |
| 544 |
size_t i, j; |
| 545 |
|
| 546 |
if (bn_wexpand(b, top) == NULL) |
| 547 |
return 0; |
| 548 |
|
| 549 |
for (i=0, j=idx; i < top * sizeof b->d[0]; i++, j+=width) |
| 550 |
{ |
| 551 |
((unsigned char*)b->d)[i] = buf[j]; |
| 552 |
} |
| 553 |
|
| 554 |
b->top = top; |
| 555 |
bn_fix_top(b); |
| 556 |
return 1; |
| 557 |
} |
| 558 |
|
| 559 |
/* Given a pointer value, compute the next address that is a cache line multiple. */ |
| 560 |
#define MOD_EXP_CTIME_ALIGN(x_) \ |
| 561 |
((unsigned char*)(x_) + (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - (((BN_ULONG)(x_)) & (MOD_EXP_CTIME_MIN_CACHE_LINE_MASK)))) |
| 562 |
|
| 563 |
/* This variant of BN_mod_exp_mont() uses fixed windows and the special |
| 564 |
* precomputation memory layout to limit data-dependency to a minimum |
| 565 |
* to protect secret exponents (cf. the hyper-threading timing attacks |
| 566 |
* pointed out by Colin Percival, |
| 567 |
* http://www.daemonology.net/hyperthreading-considered-harmful/) |
| 568 |
*/ |
| 569 |
int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, |
| 570 |
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) |
| 571 |
{ |
| 572 |
int i,bits,ret=0,idx,window,wvalue; |
| 573 |
int top; |
| 574 |
BIGNUM *r; |
| 575 |
const BIGNUM *aa; |
| 576 |
BN_MONT_CTX *mont=NULL; |
| 577 |
|
| 578 |
int numPowers; |
| 579 |
unsigned char *powerbufFree=NULL; |
| 580 |
int powerbufLen = 0; |
| 581 |
unsigned char *powerbuf=NULL; |
| 582 |
BIGNUM *computeTemp=NULL, *am=NULL; |
| 583 |
|
| 584 |
bn_check_top(a); |
| 585 |
bn_check_top(p); |
| 586 |
bn_check_top(m); |
| 587 |
|
| 588 |
top = m->top; |
| 589 |
|
| 590 |
if (!(m->d[0] & 1)) |
| 591 |
{ |
| 592 |
BNerr(BN_F_BN_MOD_EXP_MONT_CONSTTIME,BN_R_CALLED_WITH_EVEN_MODULUS); |
| 593 |
return(0); |
| 594 |
} |
| 595 |
bits=BN_num_bits(p); |
| 596 |
if (bits == 0) |
| 597 |
{ |
| 598 |
ret = BN_one(rr); |
| 599 |
return ret; |
| 600 |
} |
| 601 |
|
| 602 |
/* Initialize BIGNUM context and allocate intermediate result */ |
| 603 |
BN_CTX_start(ctx); |
| 604 |
r = BN_CTX_get(ctx); |
| 605 |
if (r == NULL) goto err; |
| 606 |
|
| 607 |
/* Allocate a montgomery context if it was not supplied by the caller. |
| 608 |
* If this is not done, things will break in the montgomery part. |
| 609 |
*/ |
| 610 |
if (in_mont != NULL) |
| 611 |
mont=in_mont; |
| 612 |
else |
| 613 |
{ |
| 614 |
if ((mont=BN_MONT_CTX_new()) == NULL) goto err; |
| 615 |
if (!BN_MONT_CTX_set(mont,m,ctx)) goto err; |
| 616 |
} |
| 617 |
|
| 618 |
/* Get the window size to use with size of p. */ |
| 619 |
window = BN_window_bits_for_ctime_exponent_size(bits); |
| 620 |
|
| 621 |
/* Allocate a buffer large enough to hold all of the pre-computed |
| 622 |
* powers of a. |
| 623 |
*/ |
| 624 |
numPowers = 1 << window; |
| 625 |
powerbufLen = sizeof(m->d[0])*top*numPowers; |
| 626 |
if ((powerbufFree=(unsigned char*)OPENSSL_malloc(powerbufLen+MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL) |
| 627 |
goto err; |
| 628 |
|
| 629 |
powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree); |
| 630 |
memset(powerbuf, 0, powerbufLen); |
| 631 |
|
| 632 |
/* Initialize the intermediate result. Do this early to save double conversion, |
| 633 |
* once each for a^0 and intermediate result. |
| 634 |
*/ |
| 635 |
if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err; |
| 636 |
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(r, top, powerbuf, 0, numPowers)) goto err; |
| 637 |
|
| 638 |
/* Initialize computeTemp as a^1 with montgomery precalcs */ |
| 639 |
computeTemp = BN_CTX_get(ctx); |
| 640 |
am = BN_CTX_get(ctx); |
| 641 |
if (computeTemp==NULL || am==NULL) goto err; |
| 642 |
|
| 643 |
if (a->neg || BN_ucmp(a,m) >= 0) |
| 644 |
{ |
| 645 |
if (!BN_mod(am,a,m,ctx)) |
| 646 |
goto err; |
| 647 |
aa= am; |
| 648 |
} |
| 649 |
else |
| 650 |
aa=a; |
| 651 |
if (!BN_to_montgomery(am,aa,mont,ctx)) goto err; |
| 652 |
if (!BN_copy(computeTemp, am)) goto err; |
| 653 |
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(am, top, powerbuf, 1, numPowers)) goto err; |
| 654 |
|
| 655 |
/* If the window size is greater than 1, then calculate |
| 656 |
* val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1) |
| 657 |
* (even powers could instead be computed as (a^(i/2))^2 |
| 658 |
* to use the slight performance advantage of sqr over mul). |
| 659 |
*/ |
| 660 |
if (window > 1) |
| 661 |
{ |
| 662 |
for (i=2; i<numPowers; i++) |
| 663 |
{ |
| 664 |
/* Calculate a^i = a^(i-1) * a */ |
| 665 |
if (!BN_mod_mul_montgomery(computeTemp,am,computeTemp,mont,ctx)) |
| 666 |
goto err; |
| 667 |
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(computeTemp, top, powerbuf, i, numPowers)) goto err; |
| 668 |
} |
| 669 |
} |
| 670 |
|
| 671 |
/* Adjust the number of bits up to a multiple of the window size. |
| 672 |
* If the exponent length is not a multiple of the window size, then |
| 673 |
* this pads the most significant bits with zeros to normalize the |
| 674 |
* scanning loop to there's no special cases. |
| 675 |
* |
| 676 |
* * NOTE: Making the window size a power of two less than the native |
| 677 |
* * word size ensures that the padded bits won't go past the last |
| 678 |
* * word in the internal BIGNUM structure. Going past the end will |
| 679 |
* * still produce the correct result, but causes a different branch |
| 680 |
* * to be taken in the BN_is_bit_set function. |
| 681 |
*/ |
| 682 |
bits = ((bits+window-1)/window)*window; |
| 683 |
idx=bits-1; /* The top bit of the window */ |
| 684 |
|
| 685 |
/* Scan the exponent one window at a time starting from the most |
| 686 |
* significant bits. |
| 687 |
*/ |
| 688 |
while (idx >= 0) |
| 689 |
{ |
| 690 |
wvalue=0; /* The 'value' of the window */ |
| 691 |
|
| 692 |
/* Scan the window, squaring the result as we go */ |
| 693 |
for (i=0; i<window; i++,idx--) |
| 694 |
{ |
| 695 |
if (!BN_mod_mul_montgomery(r,r,r,mont,ctx)) goto err; |
| 696 |
wvalue = (wvalue<<1)+BN_is_bit_set(p,idx); |
| 697 |
} |
| 698 |
|
| 699 |
/* Fetch the appropriate pre-computed value from the pre-buf */ |
| 700 |
if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(computeTemp, top, powerbuf, wvalue, numPowers)) goto err; |
| 701 |
|
| 702 |
/* Multiply the result into the intermediate result */ |
| 703 |
if (!BN_mod_mul_montgomery(r,r,computeTemp,mont,ctx)) goto err; |
| 704 |
} |
| 705 |
|
| 706 |
/* Convert the final result from montgomery to standard format */ |
| 707 |
if (!BN_from_montgomery(rr,r,mont,ctx)) goto err; |
| 708 |
ret=1; |
| 709 |
err: |
| 710 |
if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont); |
| 711 |
if (powerbuf!=NULL) |
| 712 |
{ |
| 713 |
OPENSSL_cleanse(powerbuf,powerbufLen); |
| 714 |
OPENSSL_free(powerbufFree); |
| 715 |
} |
| 716 |
if (am!=NULL) BN_clear(am); |
| 717 |
if (computeTemp!=NULL) BN_clear(computeTemp); |
| 718 |
BN_CTX_end(ctx); |
| 719 |
return(ret); |
| 720 |
} |
| 721 |
|
| 496 |
int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p, |
722 |
int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p, |
| 497 |
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) |
723 |
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) |
| 498 |
{ |
724 |
{ |
|
Lines 517-522
Link Here
|
| 517 |
#define BN_TO_MONTGOMERY_WORD(r, w, mont) \ |
743 |
#define BN_TO_MONTGOMERY_WORD(r, w, mont) \ |
| 518 |
(BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx)) |
744 |
(BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx)) |
| 519 |
|
745 |
|
|
|
746 |
if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0) |
| 747 |
{ |
| 748 |
/* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */ |
| 749 |
BNerr(BN_F_BN_MOD_EXP_MONT_WORD,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
| 750 |
return -1; |
| 751 |
} |
| 752 |
|
| 520 |
bn_check_top(p); |
753 |
bn_check_top(p); |
| 521 |
bn_check_top(m); |
754 |
bn_check_top(m); |
| 522 |
|
755 |
|
|
Lines 644-649
Link Here
|
| 644 |
BIGNUM *d; |
877 |
BIGNUM *d; |
| 645 |
BIGNUM val[TABLE_SIZE]; |
878 |
BIGNUM val[TABLE_SIZE]; |
| 646 |
|
879 |
|
|
|
880 |
if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0) |
| 881 |
{ |
| 882 |
/* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */ |
| 883 |
BNerr(BN_F_BN_MOD_EXP_SIMPLE,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
| 884 |
return -1; |
| 885 |
} |
| 886 |
|
| 647 |
bits=BN_num_bits(p); |
887 |
bits=BN_num_bits(p); |
| 648 |
|
888 |
|
| 649 |
if (bits == 0) |
889 |
if (bits == 0) |