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.c244
1 files changed, 242 insertions, 2 deletions
diff --git a/src/lib/libcrypto/bn/bn_exp.c b/src/lib/libcrypto/bn/bn_exp.c
index afdfd580fb..9e1e88abe8 100644
--- a/src/lib/libcrypto/bn/bn_exp.c
+++ b/src/lib/libcrypto/bn/bn_exp.c
@@ -56,7 +56,7 @@
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
@@ -113,6 +113,7 @@
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 */
@@ -121,6 +122,13 @@ int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
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);
@@ -204,7 +212,7 @@ int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
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);
@@ -234,6 +242,13 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
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)
@@ -361,6 +376,11 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
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);
@@ -493,6 +513,212 @@ err:
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
522static 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
542static 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 */
569int 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;
709err:
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
496int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p, 722int 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 {
@@ -517,6 +743,13 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
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
@@ -644,6 +877,13 @@ int BN_mod_exp_simple(BIGNUM *r,
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)