1 Patch comes from upstream: |
|
2 http://git.openssl.org/gitweb/?p=openssl.git;a=commit;h=2198be3483259de374f91e57d247d0fc667aef29 |
|
3 It will be obsoleted when openssl-1.0.0m is available. |
|
4 |
|
5 --- openssl-1.0.0l/crypto/bn/bn.h.orig Mon Jan 6 07:00:59 2014 |
|
6 +++ openssl-1.0.0l/crypto/bn/bn.h Fri Apr 18 13:03:57 2014 |
|
7 @@ -538,6 +538,8 @@ |
|
8 BIGNUM *BN_mod_sqrt(BIGNUM *ret, |
|
9 const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx); |
|
10 |
|
11 +void BN_consttime_swap(BN_ULONG swap, BIGNUM *a, BIGNUM *b, int nwords); |
|
12 + |
|
13 /* Deprecated versions */ |
|
14 #ifndef OPENSSL_NO_DEPRECATED |
|
15 BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int safe, |
|
16 @@ -759,11 +761,20 @@ |
|
17 |
|
18 #define bn_fix_top(a) bn_check_top(a) |
|
19 |
|
20 +#define bn_check_size(bn, bits) bn_wcheck_size(bn, ((bits+BN_BITS2-1))/BN_BITS2) |
|
21 +#define bn_wcheck_size(bn, words) \ |
|
22 + do { \ |
|
23 + const BIGNUM *_bnum2 = (bn); \ |
|
24 + assert(words <= (_bnum2)->dmax && words >= (_bnum2)->top); \ |
|
25 + } while(0) |
|
26 + |
|
27 #else /* !BN_DEBUG */ |
|
28 |
|
29 #define bn_pollute(a) |
|
30 #define bn_check_top(a) |
|
31 #define bn_fix_top(a) bn_correct_top(a) |
|
32 +#define bn_check_size(bn, bits) |
|
33 +#define bn_wcheck_size(bn, words) |
|
34 |
|
35 #endif |
|
36 |
|
37 --- openssl-1.0.0l/crypto/bn/bn_lib.c.orig Mon Jan 6 07:00:59 2014 |
|
38 +++ openssl-1.0.0l/crypto/bn/bn_lib.c Fri Apr 18 13:03:08 2014 |
|
39 @@ -843,3 +843,55 @@ |
|
40 } |
|
41 return bn_cmp_words(a,b,cl); |
|
42 } |
|
43 + |
|
44 +/* |
|
45 + * Constant-time conditional swap of a and b. |
|
46 + * a and b are swapped if condition is not 0. The code assumes that at most one bit of condition is set. |
|
47 + * nwords is the number of words to swap. The code assumes that at least nwords are allocated in both a and b, |
|
48 + * and that no more than nwords are used by either a or b. |
|
49 + * a and b cannot be the same number |
|
50 + */ |
|
51 +void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) |
|
52 + { |
|
53 + BN_ULONG t; |
|
54 + int i; |
|
55 + |
|
56 + bn_wcheck_size(a, nwords); |
|
57 + bn_wcheck_size(b, nwords); |
|
58 + |
|
59 + assert(a != b); |
|
60 + assert((condition & (condition - 1)) == 0); |
|
61 + assert(sizeof(BN_ULONG) >= sizeof(int)); |
|
62 + |
|
63 + condition = ((condition - 1) >> (BN_BITS2 - 1)) - 1; |
|
64 + |
|
65 + t = (a->top^b->top) & condition; |
|
66 + a->top ^= t; |
|
67 + b->top ^= t; |
|
68 + |
|
69 +#define BN_CONSTTIME_SWAP(ind) \ |
|
70 + do { \ |
|
71 + t = (a->d[ind] ^ b->d[ind]) & condition; \ |
|
72 + a->d[ind] ^= t; \ |
|
73 + b->d[ind] ^= t; \ |
|
74 + } while (0) |
|
75 + |
|
76 + |
|
77 + switch (nwords) { |
|
78 + default: |
|
79 + for (i = 10; i < nwords; i++) |
|
80 + BN_CONSTTIME_SWAP(i); |
|
81 + /* Fallthrough */ |
|
82 + case 10: BN_CONSTTIME_SWAP(9); /* Fallthrough */ |
|
83 + case 9: BN_CONSTTIME_SWAP(8); /* Fallthrough */ |
|
84 + case 8: BN_CONSTTIME_SWAP(7); /* Fallthrough */ |
|
85 + case 7: BN_CONSTTIME_SWAP(6); /* Fallthrough */ |
|
86 + case 6: BN_CONSTTIME_SWAP(5); /* Fallthrough */ |
|
87 + case 5: BN_CONSTTIME_SWAP(4); /* Fallthrough */ |
|
88 + case 4: BN_CONSTTIME_SWAP(3); /* Fallthrough */ |
|
89 + case 3: BN_CONSTTIME_SWAP(2); /* Fallthrough */ |
|
90 + case 2: BN_CONSTTIME_SWAP(1); /* Fallthrough */ |
|
91 + case 1: BN_CONSTTIME_SWAP(0); |
|
92 + } |
|
93 +#undef BN_CONSTTIME_SWAP |
|
94 +} |
|
95 --- openssl-1.0.0l/crypto/ec/ec2_mult.c.orig Mon Jan 6 07:00:59 2014 |
|
96 +++ openssl-1.0.0l/crypto/ec/ec2_mult.c Fri Apr 18 13:00:28 2014 |
|
97 @@ -206,11 +206,15 @@ |
|
98 return ret; |
|
99 } |
|
100 |
|
101 + |
|
102 /* Computes scalar*point and stores the result in r. |
|
103 * point can not equal r. |
|
104 - * Uses algorithm 2P of |
|
105 + * Uses a modified algorithm 2P of |
|
106 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over |
|
107 * GF(2^m) without precomputation" (CHES '99, LNCS 1717). |
|
108 + * |
|
109 + * To protect against side-channel attack the function uses constant time swap, |
|
110 + * avoiding conditional branches. |
|
111 */ |
|
112 static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, |
|
113 const EC_POINT *point, BN_CTX *ctx) |
|
114 @@ -244,6 +248,11 @@ |
|
115 x2 = &r->X; |
|
116 z2 = &r->Y; |
|
117 |
|
118 + bn_wexpand(x1, group->field.top); |
|
119 + bn_wexpand(z1, group->field.top); |
|
120 + bn_wexpand(x2, group->field.top); |
|
121 + bn_wexpand(z2, group->field.top); |
|
122 + |
|
123 if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */ |
|
124 if (!BN_one(z1)) goto err; /* z1 = 1 */ |
|
125 if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2 = x^2 */ |
|
126 @@ -268,16 +277,12 @@ |
|
127 word = scalar->d[i]; |
|
128 while (mask) |
|
129 { |
|
130 - if (word & mask) |
|
131 - { |
|
132 - if (!gf2m_Madd(group, &point->X, x1, z1, x2, z2, ctx)) goto err; |
|
133 - if (!gf2m_Mdouble(group, x2, z2, ctx)) goto err; |
|
134 - } |
|
135 - else |
|
136 - { |
|
137 - if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err; |
|
138 - if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err; |
|
139 - } |
|
140 + BN_consttime_swap(word & mask, x1, x2, group->field.top); |
|
141 + BN_consttime_swap(word & mask, z1, z2, group->field.top); |
|
142 + if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err; |
|
143 + if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err; |
|
144 + BN_consttime_swap(word & mask, x1, x2, group->field.top); |
|
145 + BN_consttime_swap(word & mask, z1, z2, group->field.top); |
|
146 mask >>= 1; |
|
147 } |
|
148 mask = BN_TBIT; |
|