Codebase list openssl / db91094
Fix timing leak in BN_from_montgomery_word. BN_from_montgomery_word doesn't have a constant memory access pattern. Replace the pointer trick with a constant-time select. There is, of course, still the bn_correct_top leak pervasive in BIGNUM itself. See also https://boringssl-review.googlesource.com/22904 from BoringSSL. Reviewed-by: Andy Polyakov <appro@openssl.org> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> (Merged from https://github.com/openssl/openssl/pull/5228) (cherry picked from commit f345b1f39d9b4e4c9ef07e7522e9b2a870c9ca09) David Benjamin authored 6 years ago Andy Polyakov committed 6 years ago
1 changed file(s) with 21 addition(s) and 38 deletion(s). Raw diff Collapse all Expand all
100100 r->top = max;
101101 n0 = mont->n0[0];
102102
103 /*
104 * Add multiples of |n| to |r| until R = 2^(nl * BN_BITS2) divides it. On
105 * input, we had |r| < |n| * R, so now |r| < 2 * |n| * R. Note that |r|
106 * includes |carry| which is stored separately.
107 */
103108 for (carry = 0, i = 0; i < nl; i++, rp++) {
104109 v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2);
105110 v = (v + carry + rp[nl]) & BN_MASK2;
114119 ret->neg = r->neg;
115120
116121 rp = ret->d;
122
123 /*
124 * Shift |nl| words to divide by R. We have |ap| < 2 * |n|. Note that |ap|
125 * includes |carry| which is stored separately.
126 */
117127 ap = &(r->d[nl]);
118128
119 # define BRANCH_FREE 1
120 # if BRANCH_FREE
121 {
122 BN_ULONG *nrp;
123 size_t m;
124
125 v = bn_sub_words(rp, ap, np, nl) - carry;
126 /*
127 * if subtraction result is real, then trick unconditional memcpy
128 * below to perform in-place "refresh" instead of actual copy.
129 */
130 m = (0 - (size_t)v);
131 nrp =
132 (BN_ULONG *)(((PTR_SIZE_INT) rp & ~m) | ((PTR_SIZE_INT) ap & m));
133
134 for (i = 0, nl -= 4; i < nl; i += 4) {
135 BN_ULONG t1, t2, t3, t4;
136
137 t1 = nrp[i + 0];
138 t2 = nrp[i + 1];
139 t3 = nrp[i + 2];
140 ap[i + 0] = 0;
141 t4 = nrp[i + 3];
142 ap[i + 1] = 0;
143 rp[i + 0] = t1;
144 ap[i + 2] = 0;
145 rp[i + 1] = t2;
146 ap[i + 3] = 0;
147 rp[i + 2] = t3;
148 rp[i + 3] = t4;
149 }
150 for (nl += 4; i < nl; i++)
151 rp[i] = nrp[i], ap[i] = 0;
152 }
153 # else
154 if (bn_sub_words(rp, ap, np, nl) - carry)
155 memcpy(rp, ap, nl * sizeof(BN_ULONG));
156 # endif
129 /*
130 * |v| is one if |ap| - |np| underflowed or zero if it did not. Note |v|
131 * cannot be -1. That would imply the subtraction did not fit in |nl| words,
132 * and we know at most one subtraction is needed.
133 */
134 v = bn_sub_words(rp, ap, np, nl) - carry;
135 v = 0 - v;
136 for (i = 0; i < nl; i++) {
137 rp[i] = (v & ap[i]) | (~v & rp[i]);
138 ap[i] = 0;
139 }
157140 bn_correct_top(r);
158141 bn_correct_top(ret);
159142 bn_check_top(ret);