diff options
author | bcook <> | 2016-09-03 17:26:29 +0000 |
---|---|---|
committer | bcook <> | 2016-09-03 17:26:29 +0000 |
commit | 05812bec7df03184841379790bd48dadca90c010 (patch) | |
tree | 5a55fa6d7a407158eb3e24dce67281670f92a99c /src | |
parent | 06907d7e2bc335e13382062e78c2e1c5aa05fbfe (diff) | |
download | openbsd-05812bec7df03184841379790bd48dadca90c010.tar.gz openbsd-05812bec7df03184841379790bd48dadca90c010.tar.bz2 openbsd-05812bec7df03184841379790bd48dadca90c010.zip |
add constant-time MOD_EXP_CTIME_COPY_FROM_PREBUF.
Patch based on OpenSSL commit d7a854c055ff22fb7da80c3b0e7cb08d248591d0
"Performance penalty varies from platform to platform, and even
key length. For rsa2048 sign it was observed to reach almost 10%."
CVE-2016-0702
ok beck@
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libcrypto/bn/bn_exp.c | 71 |
1 files changed, 55 insertions, 16 deletions
diff --git a/src/lib/libcrypto/bn/bn_exp.c b/src/lib/libcrypto/bn/bn_exp.c index 87b5775886..64c8cbf375 100644 --- a/src/lib/libcrypto/bn/bn_exp.c +++ b/src/lib/libcrypto/bn/bn_exp.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: bn_exp.c,v 1.25 2016/09/03 17:21:38 bcook Exp $ */ | 1 | /* $OpenBSD: bn_exp.c,v 1.26 2016/09/03 17:26:29 bcook Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -115,6 +115,7 @@ | |||
115 | #include <openssl/err.h> | 115 | #include <openssl/err.h> |
116 | 116 | ||
117 | #include "bn_lcl.h" | 117 | #include "bn_lcl.h" |
118 | #include "constant_time_locl.h" | ||
118 | 119 | ||
119 | /* maximum precomputation table size for *variable* sliding windows */ | 120 | /* maximum precomputation table size for *variable* sliding windows */ |
120 | #define TABLE_SIZE 32 | 121 | #define TABLE_SIZE 32 |
@@ -541,14 +542,17 @@ err: | |||
541 | 542 | ||
542 | static int | 543 | static int |
543 | MOD_EXP_CTIME_COPY_TO_PREBUF(const BIGNUM *b, int top, unsigned char *buf, | 544 | MOD_EXP_CTIME_COPY_TO_PREBUF(const BIGNUM *b, int top, unsigned char *buf, |
544 | int idx, int width) | 545 | int idx, int window) |
545 | { | 546 | { |
546 | size_t i, j; | 547 | int i, j; |
548 | int width = 1 << window; | ||
549 | BN_ULONG *table = (BN_ULONG *)buf; | ||
547 | 550 | ||
548 | if (top > b->top) | 551 | if (top > b->top) |
549 | top = b->top; /* this works because 'buf' is explicitly zeroed */ | 552 | top = b->top; /* this works because 'buf' is explicitly zeroed */ |
550 | for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) { | 553 | |
551 | buf[j] = ((unsigned char*)b->d)[i]; | 554 | for (i = 0, j = idx; i < top; i++, j += width) { |
555 | table[j] = b->d[i]; | ||
552 | } | 556 | } |
553 | 557 | ||
554 | return 1; | 558 | return 1; |
@@ -556,17 +560,52 @@ MOD_EXP_CTIME_COPY_TO_PREBUF(const BIGNUM *b, int top, unsigned char *buf, | |||
556 | 560 | ||
557 | static int | 561 | static int |
558 | MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx, | 562 | MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx, |
559 | int width) | 563 | int window) |
560 | { | 564 | { |
561 | size_t i, j; | 565 | int i, j; |
566 | int width = 1 << window; | ||
567 | volatile BN_ULONG *table = (volatile BN_ULONG *)buf; | ||
562 | 568 | ||
563 | if (bn_wexpand(b, top) == NULL) | 569 | if (bn_wexpand(b, top) == NULL) |
564 | return 0; | 570 | return 0; |
565 | 571 | ||
566 | for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) { | 572 | if (window <= 3) { |
567 | ((unsigned char*)b->d)[i] = buf[j]; | 573 | for (i = 0; i < top; i++, table += width) { |
568 | } | 574 | BN_ULONG acc = 0; |
575 | |||
576 | for (j = 0; j < width; j++) { | ||
577 | acc |= table[j] & | ||
578 | ((BN_ULONG)0 - (constant_time_eq_int(j,idx)&1)); | ||
579 | } | ||
580 | |||
581 | b->d[i] = acc; | ||
582 | } | ||
583 | } else { | ||
584 | int xstride = 1 << (window - 2); | ||
585 | BN_ULONG y0, y1, y2, y3; | ||
569 | 586 | ||
587 | i = idx >> (window - 2); /* equivalent of idx / xstride */ | ||
588 | idx &= xstride - 1; /* equivalent of idx % xstride */ | ||
589 | |||
590 | y0 = (BN_ULONG)0 - (constant_time_eq_int(i,0)&1); | ||
591 | y1 = (BN_ULONG)0 - (constant_time_eq_int(i,1)&1); | ||
592 | y2 = (BN_ULONG)0 - (constant_time_eq_int(i,2)&1); | ||
593 | y3 = (BN_ULONG)0 - (constant_time_eq_int(i,3)&1); | ||
594 | |||
595 | for (i = 0; i < top; i++, table += width) { | ||
596 | BN_ULONG acc = 0; | ||
597 | |||
598 | for (j = 0; j < xstride; j++) { | ||
599 | acc |= ( (table[j + 0 * xstride] & y0) | | ||
600 | (table[j + 1 * xstride] & y1) | | ||
601 | (table[j + 2 * xstride] & y2) | | ||
602 | (table[j + 3 * xstride] & y3) ) | ||
603 | & ((BN_ULONG)0 - (constant_time_eq_int(j,idx)&1)); | ||
604 | } | ||
605 | |||
606 | b->d[i] = acc; | ||
607 | } | ||
608 | } | ||
570 | b->top = top; | 609 | b->top = top; |
571 | bn_correct_top(b); | 610 | bn_correct_top(b); |
572 | return 1; | 611 | return 1; |
@@ -772,10 +811,10 @@ BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, | |||
772 | #endif | 811 | #endif |
773 | { | 812 | { |
774 | if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 0, | 813 | if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 0, |
775 | numPowers)) | 814 | window)) |
776 | goto err; | 815 | goto err; |
777 | if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&am, top, powerbuf, 1, | 816 | if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&am, top, powerbuf, 1, |
778 | numPowers)) | 817 | window)) |
779 | goto err; | 818 | goto err; |
780 | 819 | ||
781 | /* If the window size is greater than 1, then calculate | 820 | /* If the window size is greater than 1, then calculate |
@@ -787,7 +826,7 @@ BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, | |||
787 | if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx)) | 826 | if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx)) |
788 | goto err; | 827 | goto err; |
789 | if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, | 828 | if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, |
790 | 2, numPowers)) | 829 | 2, window)) |
791 | goto err; | 830 | goto err; |
792 | for (i = 3; i < numPowers; i++) { | 831 | for (i = 3; i < numPowers; i++) { |
793 | /* Calculate a^i = a^(i-1) * a */ | 832 | /* Calculate a^i = a^(i-1) * a */ |
@@ -795,7 +834,7 @@ BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, | |||
795 | mont, ctx)) | 834 | mont, ctx)) |
796 | goto err; | 835 | goto err; |
797 | if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, | 836 | if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, |
798 | powerbuf, i, numPowers)) | 837 | powerbuf, i, window)) |
799 | goto err; | 838 | goto err; |
800 | } | 839 | } |
801 | } | 840 | } |
@@ -804,7 +843,7 @@ BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, | |||
804 | for (wvalue = 0, i = bits % window; i >= 0; i--, bits--) | 843 | for (wvalue = 0, i = bits % window; i >= 0; i--, bits--) |
805 | wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); | 844 | wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); |
806 | if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&tmp, top, powerbuf, | 845 | if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&tmp, top, powerbuf, |
807 | wvalue, numPowers)) | 846 | wvalue, window)) |
808 | goto err; | 847 | goto err; |
809 | 848 | ||
810 | /* Scan the exponent one window at a time starting from the most | 849 | /* Scan the exponent one window at a time starting from the most |
@@ -823,7 +862,7 @@ BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, | |||
823 | 862 | ||
824 | /* Fetch the appropriate pre-computed value from the pre-buf */ | 863 | /* Fetch the appropriate pre-computed value from the pre-buf */ |
825 | if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&am, top, powerbuf, | 864 | if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&am, top, powerbuf, |
826 | wvalue, numPowers)) | 865 | wvalue, window)) |
827 | goto err; | 866 | goto err; |
828 | 867 | ||
829 | /* Multiply the result into the intermediate result */ | 868 | /* Multiply the result into the intermediate result */ |