/src/boringssl/crypto/fipsmodule/bn/div.cc.inc
Line | Count | Source |
1 | | // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include <openssl/bn.h> |
16 | | |
17 | | #include <assert.h> |
18 | | #include <limits.h> |
19 | | |
20 | | #include <openssl/err.h> |
21 | | |
22 | | #include "internal.h" |
23 | | |
24 | | #if (defined(OPENSSL_X86) || defined(OPENSSL_X86_64)) && defined(_MSC_VER) && \ |
25 | | !defined(__clang__) |
26 | | #define HAVE_MSVC_DIV_INTRINSICS |
27 | | #include <immintrin.h> |
28 | | #if defined(OPENSSL_X86) |
29 | | #pragma intrinsic(_udiv64) |
30 | | #else |
31 | | #pragma intrinsic(_udiv128) |
32 | | #endif |
33 | | #endif |
34 | | |
35 | | |
36 | | using namespace bssl; |
37 | | |
38 | | // bn_div_words divides a double-width |h|,|l| by |d| and returns the result, |
39 | | // which must fit in a |BN_ULONG|, i.e. |h < d|. |
40 | | [[maybe_unused]] |
41 | 0 | static BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) { |
42 | 0 | assert(h < d); |
43 | 0 | BN_ULONG dh, dl, q, ret = 0, th, tl, t; |
44 | 0 | int i, count = 2; |
45 | 0 |
|
46 | 0 | if (d == 0) { |
47 | 0 | return BN_MASK2; |
48 | 0 | } |
49 | 0 |
|
50 | 0 | i = BN_num_bits_word(d); |
51 | 0 | assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i)); |
52 | 0 |
|
53 | 0 | i = BN_BITS2 - i; |
54 | 0 | if (h >= d) { |
55 | 0 | h -= d; |
56 | 0 | } |
57 | 0 |
|
58 | 0 | if (i) { |
59 | 0 | d <<= i; |
60 | 0 | h = (h << i) | (l >> (BN_BITS2 - i)); |
61 | 0 | l <<= i; |
62 | 0 | } |
63 | 0 | dh = (d & BN_MASK2h) >> BN_BITS4; |
64 | 0 | dl = (d & BN_MASK2l); |
65 | 0 | for (;;) { |
66 | 0 | if ((h >> BN_BITS4) == dh) { |
67 | 0 | q = BN_MASK2l; |
68 | 0 | } else { |
69 | 0 | q = h / dh; |
70 | 0 | } |
71 | 0 |
|
72 | 0 | th = q * dh; |
73 | 0 | tl = dl * q; |
74 | 0 | for (;;) { |
75 | 0 | t = h - th; |
76 | 0 | if ((t & BN_MASK2h) || |
77 | 0 | ((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4)))) { |
78 | 0 | break; |
79 | 0 | } |
80 | 0 | q--; |
81 | 0 | th -= dh; |
82 | 0 | tl -= dl; |
83 | 0 | } |
84 | 0 | t = (tl >> BN_BITS4); |
85 | 0 | tl = (tl << BN_BITS4) & BN_MASK2h; |
86 | 0 | th += t; |
87 | 0 |
|
88 | 0 | if (l < tl) { |
89 | 0 | th++; |
90 | 0 | } |
91 | 0 | l -= tl; |
92 | 0 | if (h < th) { |
93 | 0 | h += d; |
94 | 0 | q--; |
95 | 0 | } |
96 | 0 | h -= th; |
97 | 0 |
|
98 | 0 | if (--count == 0) { |
99 | 0 | break; |
100 | 0 | } |
101 | 0 |
|
102 | 0 | ret = q << BN_BITS4; |
103 | 0 | h = (h << BN_BITS4) | (l >> BN_BITS4); |
104 | 0 | l = (l & BN_MASK2l) << BN_BITS4; |
105 | 0 | } |
106 | 0 |
|
107 | 0 | ret |= q; |
108 | 0 | return ret; |
109 | 0 | } |
110 | | |
111 | | // bn_div_rem_words divides a double-width numerator (high half |nh| and low |
112 | | // half |nl|) with a single-width divisor. It sets |*quotient_out| and |
113 | | // |*rem_out| to be the quotient and numerator, respectively. The quotient must |
114 | | // fit in a |BN_ULONG|, i.e. |nh < d|. |
115 | | static void bn_div_rem_words(BN_ULONG *quotient_out, BN_ULONG *rem_out, |
116 | 31.4M | BN_ULONG nh, BN_ULONG nl, BN_ULONG d) { |
117 | 31.4M | assert(nh < d); |
118 | | // This operation is the x86 and x86_64 DIV instruction, but it is difficult |
119 | | // for the compiler to emit it. Dividing a |BN_ULLONG| by a |BN_ULONG| does |
120 | | // not work because, a priori, the quotient may not fit in |BN_ULONG| and DIV |
121 | | // will trap on overflow, not truncate. The compiler will instead emit a call |
122 | | // to a more expensive support function (e.g. |__udivdi3|). Thus we use inline |
123 | | // assembly or intrinsics to get the instruction. |
124 | | // |
125 | | // These is specific to x86 and x86_64; Arm and RISC-V do not have double-wide |
126 | | // division instructions. |
127 | | #if defined(BN_CAN_USE_INLINE_ASM) && defined(OPENSSL_X86) |
128 | | __asm__ volatile("divl %4" |
129 | | : "=a"(*quotient_out), "=d"(*rem_out) |
130 | | : "a"(nl), "d"(nh), "rm"(d) |
131 | | : "cc"); |
132 | | #elif defined(BN_CAN_USE_INLINE_ASM) && defined(OPENSSL_X86_64) |
133 | 31.4M | __asm__ volatile("divq %4" |
134 | 31.4M | : "=a"(*quotient_out), "=d"(*rem_out) |
135 | 31.4M | : "a"(nl), "d"(nh), "rm"(d) |
136 | 31.4M | : "cc"); |
137 | | #elif defined(HAVE_MSVC_DIV_INTRINSICS) && defined(OPENSSL_X86) |
138 | | BN_ULLONG n = (((BN_ULLONG)nh) << BN_BITS2) | nl; |
139 | | unsigned rem; |
140 | | *quotient_out = _udiv64(n, d, &rem); |
141 | | *rem_out = rem; |
142 | | #elif defined(HAVE_MSVC_DIV_INTRINSICS) && defined(OPENSSL_X86_64) |
143 | | unsigned __int64 rem; |
144 | | *quotient_out = _udiv128(nh, nl, d, &rem); |
145 | | *rem_out = rem; |
146 | | #else |
147 | | #if defined(BN_CAN_DIVIDE_ULLONG) |
148 | | BN_ULLONG n = (((BN_ULLONG)nh) << BN_BITS2) | nl; |
149 | | *quotient_out = (BN_ULONG)(n / d); |
150 | | #else |
151 | | *quotient_out = bn_div_words(nh, nl, d); |
152 | | #endif // BN_CAN_DIVIDE_ULLONG |
153 | | *rem_out = nl - (*quotient_out * d); |
154 | | #endif |
155 | 31.4M | } |
156 | | |
157 | | int BN_div(BIGNUM *quotient, BIGNUM *rem, const BIGNUM *numerator, |
158 | 6.26M | const BIGNUM *divisor, BN_CTX *ctx) { |
159 | | // This function implements long division, per Knuth, The Art of Computer |
160 | | // Programming, Volume 2, Chapter 4.3.1, Algorithm D. This algorithm only |
161 | | // divides non-negative integers, but we round towards zero, so we divide |
162 | | // absolute values and adjust the signs separately. |
163 | | // |
164 | | // Inputs to this function are assumed public and may be leaked by timing and |
165 | | // cache side channels. Division with secret inputs should use other |
166 | | // implementation strategies such as Montgomery reduction. |
167 | 6.26M | if (BN_is_zero(divisor)) { |
168 | 0 | OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO); |
169 | 0 | return 0; |
170 | 0 | } |
171 | | |
172 | 6.26M | BN_CTXScope scope(ctx); |
173 | 6.26M | BIGNUM *tmp = BN_CTX_get(ctx); |
174 | 6.26M | BIGNUM *snum = BN_CTX_get(ctx); |
175 | 6.26M | BIGNUM *sdiv = BN_CTX_get(ctx); |
176 | 6.26M | BIGNUM *res = quotient == nullptr ? BN_CTX_get(ctx) : quotient; |
177 | 6.26M | int norm_shift, num_n, loop, div_n; |
178 | 6.26M | BN_ULONG d0, d1; |
179 | 6.26M | if (tmp == nullptr || snum == nullptr || sdiv == nullptr || res == nullptr) { |
180 | 0 | return 0; |
181 | 0 | } |
182 | | |
183 | | // Knuth step D1: Normalise the numbers such that the divisor's MSB is set. |
184 | | // This ensures, in Knuth's terminology, that v1 >= b/2, needed for the |
185 | | // quotient estimation step. |
186 | 6.26M | norm_shift = BN_BITS2 - (BN_num_bits(divisor) % BN_BITS2); |
187 | 6.26M | if (!BN_lshift(sdiv, divisor, norm_shift) || |
188 | 6.26M | !BN_lshift(snum, numerator, norm_shift)) { |
189 | 0 | return 0; |
190 | 0 | } |
191 | | |
192 | | // This algorithm relies on |sdiv| being minimal width. We do not use this |
193 | | // function on secret inputs, so leaking this is fine. Also minimize |snum| to |
194 | | // avoid looping on leading zeros, as we're not trying to be leak-free. |
195 | 6.26M | bn_set_minimal_width(sdiv); |
196 | 6.26M | bn_set_minimal_width(snum); |
197 | 6.26M | div_n = sdiv->width; |
198 | 6.26M | d0 = sdiv->d[div_n - 1]; |
199 | 6.26M | d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2]; |
200 | 6.26M | assert(d0 & (((BN_ULONG)1) << (BN_BITS2 - 1))); |
201 | | |
202 | | // Extend |snum| with zeros to satisfy the long division invariants: |
203 | | // - |snum| must have at least |div_n| + 1 words. |
204 | | // - |snum|'s most significant word must be zero to guarantee the first loop |
205 | | // iteration works with a prefix greater than |sdiv|. (This is the extra u0 |
206 | | // digit in Knuth step D1.) |
207 | 6.26M | num_n = snum->width <= div_n ? div_n + 1 : snum->width + 1; |
208 | 6.26M | if (!bn_resize_words(snum, num_n)) { |
209 | 0 | return 0; |
210 | 0 | } |
211 | | |
212 | | // Knuth step D2: The quotient's width is the difference between numerator and |
213 | | // denominator. Also set up its sign and size a temporary for the loop. |
214 | 6.26M | loop = num_n - div_n; |
215 | 6.26M | res->neg = snum->neg ^ sdiv->neg; |
216 | 6.26M | if (!bn_wexpand(res, loop) || // |
217 | 6.26M | !bn_wexpand(tmp, div_n + 1)) { |
218 | 0 | return 0; |
219 | 0 | } |
220 | 6.26M | res->width = loop; |
221 | | |
222 | | // Knuth steps D2 through D7: Compute the quotient with a word-by-word long |
223 | | // division. Note that Knuth indexes words from most to least significant, so |
224 | | // our index is reversed. Each loop iteration computes res->d[i] of the |
225 | | // quotient and updates snum with the running remainder. Before each loop |
226 | | // iteration, the div_n words beginning at snum->d[i+1] must be less than |
227 | | // snum. |
228 | 37.8M | for (int i = loop - 1; i >= 0; i--) { |
229 | | // The next word of the quotient, q, is floor(wnum / sdiv), where wnum is |
230 | | // the div_n + 1 words beginning at snum->d[i]. i starts at |
231 | | // num_n - div_n - 1, so there are at least div_n + 1 words available. |
232 | | // |
233 | | // Knuth step D3: Compute q', an estimate of q by looking at the top words |
234 | | // of wnum and sdiv. We must estimate such that q' = q or q' = q + 1. |
235 | 31.5M | BN_ULONG q, rm = 0; |
236 | 31.5M | BN_ULONG *wnum = snum->d + i; |
237 | 31.5M | BN_ULONG n0 = wnum[div_n]; |
238 | 31.5M | BN_ULONG n1 = wnum[div_n - 1]; |
239 | 31.5M | if (n0 == d0) { |
240 | | // Estimate q' = b - 1, where b is the base. |
241 | 115k | q = BN_MASK2; |
242 | | // Knuth also runs the fixup routine in this case, but this would require |
243 | | // computing rm and is unnecessary. q' is already close enough. That is, |
244 | | // the true quotient, q is either b - 1 or b - 2. |
245 | | // |
246 | | // By the loop invariant, q <= b - 1, so we must show that q >= b - 2. We |
247 | | // do this by showing wnum / sdiv >= b - 2. Suppose wnum / sdiv < b - 2. |
248 | | // wnum and sdiv have the same most significant word, so: |
249 | | // |
250 | | // wnum >= n0 * b^div_n |
251 | | // sdiv < (n0 + 1) * b^(d_div - 1) |
252 | | // |
253 | | // Thus: |
254 | | // |
255 | | // b - 2 > wnum / sdiv |
256 | | // > (n0 * b^div_n) / (n0 + 1) * b^(div_n - 1) |
257 | | // = (n0 * b) / (n0 + 1) |
258 | | // |
259 | | // (n0 + 1) * (b - 2) > n0 * b |
260 | | // n0 * b + b - 2 * n0 - 2 > n0 * b |
261 | | // b - 2 > 2 * n0 |
262 | | // b/2 - 1 > n0 |
263 | | // |
264 | | // This contradicts the normalization condition, so q >= b - 2 and our |
265 | | // estimate is close enough. |
266 | 31.4M | } else { |
267 | | // Estimate q' = floor(n0n1 / d0). Per Theorem B, q' - 2 <= q <= q', which |
268 | | // is slightly outside of our bounds. |
269 | 31.4M | assert(n0 < d0); |
270 | 31.4M | bn_div_rem_words(&q, &rm, n0, n1, d0); |
271 | | |
272 | | // Fix the estimate by examining one more word and adjusting q' as needed. |
273 | | // This is the second half of step D3 and is sufficient per exercises 19, |
274 | | // 20, and 21. Although only one iteration is needed to correct q + 2 to |
275 | | // q + 1, Knuth uses a loop. A loop will often also correct q + 1 to q, |
276 | | // saving the slightly more expensive underflow handling below. |
277 | 31.4M | if (div_n > 1) { |
278 | 30.8M | BN_ULONG n2 = wnum[div_n - 2]; |
279 | 30.8M | #ifdef BN_ULLONG |
280 | 30.8M | BN_ULLONG t2 = (BN_ULLONG)d1 * q; |
281 | 31.0M | for (;;) { |
282 | 31.0M | if (t2 <= ((((BN_ULLONG)rm) << BN_BITS2) | n2)) { |
283 | 21.7M | break; |
284 | 21.7M | } |
285 | 9.26M | q--; |
286 | 9.26M | rm += d0; |
287 | 9.26M | if (rm < d0) { |
288 | | // If rm overflows, the true value exceeds BN_ULONG and the next |
289 | | // t2 comparison should exit the loop. |
290 | 9.02M | break; |
291 | 9.02M | } |
292 | 240k | t2 -= d1; |
293 | 240k | } |
294 | | #else // !BN_ULLONG |
295 | | BN_ULONG t2l, t2h; |
296 | | BN_UMULT_LOHI(t2l, t2h, d1, q); |
297 | | for (;;) { |
298 | | if (t2h < rm || (t2h == rm && t2l <= n2)) { |
299 | | break; |
300 | | } |
301 | | q--; |
302 | | rm += d0; |
303 | | if (rm < d0) { |
304 | | // If rm overflows, the true value exceeds BN_ULONG and the next |
305 | | // t2 comparison should exit the loop. |
306 | | break; |
307 | | } |
308 | | if (t2l < d1) { |
309 | | t2h--; |
310 | | } |
311 | | t2l -= d1; |
312 | | } |
313 | | #endif // !BN_ULLONG |
314 | 30.8M | } |
315 | 31.4M | } |
316 | | |
317 | | // Knuth step D4 through D6: Now q' = q or q' = q + 1, and |
318 | | // -sdiv < wnum - sdiv * q < sdiv. If q' = q + 1, the subtraction will |
319 | | // underflow, and we fix it up below. |
320 | 31.5M | tmp->d[div_n] = bn_mul_words(tmp->d, sdiv->d, div_n, q); |
321 | 31.5M | if (bn_sub_words(wnum, wnum, tmp->d, div_n + 1)) { |
322 | 114k | q--; |
323 | | // The final addition is expected to overflow, canceling the underflow. |
324 | 114k | wnum[div_n] += bn_add_words(wnum, wnum, sdiv->d, div_n); |
325 | 114k | } |
326 | | |
327 | | // q is now correct, and wnum has been updated to the running remainder. |
328 | 31.5M | res->d[i] = q; |
329 | 31.5M | } |
330 | | |
331 | | // Trim leading zeros and correct any negative zeros. |
332 | 6.26M | bn_set_minimal_width(snum); |
333 | 6.26M | bn_set_minimal_width(res); |
334 | | |
335 | | // Knuth step D8: Unnormalize. snum now contains the remainder. |
336 | 6.26M | if (rem != nullptr && !BN_rshift(rem, snum, norm_shift)) { |
337 | 0 | return 0; |
338 | 0 | } |
339 | | |
340 | 6.26M | return 1; |
341 | 6.26M | } |
342 | | |
343 | 5.97M | int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) { |
344 | 5.97M | if (!(BN_mod(r, m, d, ctx))) { |
345 | 0 | return 0; |
346 | 0 | } |
347 | 5.97M | if (!r->neg) { |
348 | 5.97M | return 1; |
349 | 5.97M | } |
350 | | |
351 | | // now -d < r < 0, so we have to set r := r + d. Ignoring the sign bits, this |
352 | | // is r = d - r. |
353 | 2.63k | return BN_usub(r, d, r); |
354 | 5.97M | } |
355 | | |
356 | | BN_ULONG bssl::bn_reduce_once(BN_ULONG *r, const BN_ULONG *a, BN_ULONG carry, |
357 | 564k | const BN_ULONG *m, size_t num) { |
358 | 564k | assert(r != a); |
359 | | // |r| = |a| - |m|. |bn_sub_words| performs the bulk of the subtraction, and |
360 | | // then we apply the borrow to |carry|. |
361 | 564k | carry -= bn_sub_words(r, a, m, num); |
362 | | // We know 0 <= |a| < 2*|m|, so -|m| <= |r| < |m|. |
363 | | // |
364 | | // If 0 <= |r| < |m|, |r| fits in |num| words and |carry| is zero. We then |
365 | | // wish to select |r| as the answer. Otherwise -m <= r < 0 and we wish to |
366 | | // return |r| + |m|, or |a|. |carry| must then be -1 or all ones. In both |
367 | | // cases, |carry| is a suitable input to |bn_select_words|. |
368 | | // |
369 | | // Although |carry| may be one if it was one on input and |bn_sub_words| |
370 | | // returns zero, this would give |r| > |m|, violating our input assumptions. |
371 | 564k | declassify_assert(carry + 1 <= 1); |
372 | 564k | bn_select_words(r, carry, a /* r < 0 */, r /* r >= 0 */, num); |
373 | 564k | return carry; |
374 | 564k | } |
375 | | |
376 | | BN_ULONG bssl::bn_reduce_once_in_place(BN_ULONG *r, BN_ULONG carry, |
377 | | const BN_ULONG *m, BN_ULONG *tmp, |
378 | 120M | size_t num) { |
379 | | // See |bn_reduce_once| for why this logic works. |
380 | 120M | carry -= bn_sub_words(tmp, r, m, num); |
381 | 120M | declassify_assert(carry + 1 <= 1); |
382 | 120M | bn_select_words(r, carry, r /* tmp < 0 */, tmp /* tmp >= 0 */, num); |
383 | 120M | return carry; |
384 | 120M | } |
385 | | |
386 | | void bssl::bn_mod_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, |
387 | 82.0M | const BN_ULONG *m, BN_ULONG *tmp, size_t num) { |
388 | | // r = a - b |
389 | 82.0M | BN_ULONG borrow = bn_sub_words(r, a, b, num); |
390 | | // tmp = a - b + m |
391 | 82.0M | bn_add_words(tmp, r, m, num); |
392 | 82.0M | bn_select_words(r, 0 - borrow, tmp /* r < 0 */, r /* r >= 0 */, num); |
393 | 82.0M | } |
394 | | |
395 | | void bssl::bn_mod_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, |
396 | 119M | const BN_ULONG *m, BN_ULONG *tmp, size_t num) { |
397 | 119M | BN_ULONG carry = bn_add_words(r, a, b, num); |
398 | 119M | bn_reduce_once_in_place(r, carry, m, tmp, num); |
399 | 119M | } |
400 | | |
401 | | int bssl::bn_div_consttime(BIGNUM *quotient, BIGNUM *remainder, |
402 | | const BIGNUM *numerator, const BIGNUM *divisor, |
403 | 1.10k | unsigned divisor_min_bits, BN_CTX *ctx) { |
404 | 1.10k | if (BN_is_negative(numerator) || BN_is_negative(divisor)) { |
405 | 0 | OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); |
406 | 0 | return 0; |
407 | 0 | } |
408 | 1.10k | if (BN_is_zero(divisor)) { |
409 | 0 | OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO); |
410 | 0 | return 0; |
411 | 0 | } |
412 | | |
413 | | // This function implements long division in binary. It is not very efficient, |
414 | | // but it is simple, easy to make constant-time, and performant enough for RSA |
415 | | // key generation. |
416 | | |
417 | 1.10k | BN_CTXScope scope(ctx); |
418 | 1.10k | BIGNUM *q = quotient, *r = remainder; |
419 | 1.10k | if (quotient == nullptr || quotient == numerator || quotient == divisor) { |
420 | 1.10k | q = BN_CTX_get(ctx); |
421 | 1.10k | } |
422 | 1.10k | if (remainder == nullptr || remainder == numerator || remainder == divisor) { |
423 | 715 | r = BN_CTX_get(ctx); |
424 | 715 | } |
425 | 1.10k | BIGNUM *tmp = BN_CTX_get(ctx); |
426 | 1.10k | int initial_words; |
427 | 1.10k | if (q == nullptr || r == nullptr || tmp == nullptr || |
428 | 1.10k | !bn_wexpand(q, numerator->width) || !bn_wexpand(r, divisor->width) || |
429 | 1.10k | !bn_wexpand(tmp, divisor->width)) { |
430 | 0 | return 0; |
431 | 0 | } |
432 | | |
433 | 1.10k | OPENSSL_memset(q->d, 0, numerator->width * sizeof(BN_ULONG)); |
434 | 1.10k | q->width = numerator->width; |
435 | 1.10k | q->neg = 0; |
436 | | |
437 | 1.10k | OPENSSL_memset(r->d, 0, divisor->width * sizeof(BN_ULONG)); |
438 | 1.10k | r->width = divisor->width; |
439 | 1.10k | r->neg = 0; |
440 | | |
441 | | // Incorporate |numerator| into |r|, one bit at a time, reducing after each |
442 | | // step. We maintain the invariant that |0 <= r < divisor| and |
443 | | // |q * divisor + r = n| where |n| is the portion of |numerator| incorporated |
444 | | // so far. |
445 | | // |
446 | | // First, we short-circuit the loop: if we know |divisor| has at least |
447 | | // |divisor_min_bits| bits, the top |divisor_min_bits - 1| can be incorporated |
448 | | // without reductions. This significantly speeds up |RSA_check_key|. For |
449 | | // simplicity, we round down to a whole number of words. |
450 | 1.10k | declassify_assert(divisor_min_bits <= BN_num_bits(divisor)); |
451 | 1.10k | initial_words = 0; |
452 | 1.10k | if (divisor_min_bits > 0) { |
453 | 1.10k | initial_words = (divisor_min_bits - 1) / BN_BITS2; |
454 | 1.10k | if (initial_words > numerator->width) { |
455 | 82 | initial_words = numerator->width; |
456 | 82 | } |
457 | 1.10k | OPENSSL_memcpy(r->d, numerator->d + numerator->width - initial_words, |
458 | 1.10k | initial_words * sizeof(BN_ULONG)); |
459 | 1.10k | } |
460 | | |
461 | 12.9k | for (int i = numerator->width - initial_words - 1; i >= 0; i--) { |
462 | 770k | for (int bit = BN_BITS2 - 1; bit >= 0; bit--) { |
463 | | // Incorporate the next bit of the numerator, by computing |
464 | | // r = 2*r or 2*r + 1. Note the result fits in one more word. We store the |
465 | | // extra word in |carry|. |
466 | 758k | BN_ULONG carry = bn_add_words(r->d, r->d, r->d, divisor->width); |
467 | 758k | r->d[0] |= (numerator->d[i] >> bit) & 1; |
468 | | // |r| was previously fully-reduced, so we know: |
469 | | // 2*0 <= r <= 2*(divisor-1) + 1 |
470 | | // 0 <= r <= 2*divisor - 1 < 2*divisor. |
471 | | // Thus |r| satisfies the preconditions for |bn_reduce_once_in_place|. |
472 | 758k | BN_ULONG subtracted = bn_reduce_once_in_place(r->d, carry, divisor->d, |
473 | 758k | tmp->d, divisor->width); |
474 | | // The corresponding bit of the quotient is set iff we needed to subtract. |
475 | 758k | q->d[i] |= (~subtracted & 1) << bit; |
476 | 758k | } |
477 | 11.8k | } |
478 | | |
479 | 1.10k | if ((quotient != nullptr && !BN_copy(quotient, q)) || |
480 | 1.10k | (remainder != nullptr && !BN_copy(remainder, r))) { |
481 | 0 | return 0; |
482 | 0 | } |
483 | | |
484 | 1.10k | return 1; |
485 | 1.10k | } |
486 | | |
487 | 44.7k | static BIGNUM *bn_scratch_space_from_ctx(size_t width, BN_CTX *ctx) { |
488 | 44.7k | BIGNUM *ret = BN_CTX_get(ctx); |
489 | 44.7k | if (ret == nullptr || !bn_wexpand(ret, width)) { |
490 | 0 | return nullptr; |
491 | 0 | } |
492 | 44.7k | ret->neg = 0; |
493 | 44.7k | ret->width = (int)width; |
494 | 44.7k | return ret; |
495 | 44.7k | } |
496 | | |
497 | | // bn_resized_from_ctx returns |bn| with width at least |width| or NULL on |
498 | | // error. This is so it may be used with low-level "words" functions. If |
499 | | // necessary, it allocates a new |BIGNUM| with a lifetime of the current scope |
500 | | // in |ctx|, so the caller does not need to explicitly free it. |bn| must fit in |
501 | | // |width| words. |
502 | | static const BIGNUM *bn_resized_from_ctx(const BIGNUM *bn, size_t width, |
503 | 71.5k | BN_CTX *ctx) { |
504 | 71.5k | if ((size_t)bn->width >= width) { |
505 | | // Any excess words must be zero. |
506 | 71.2k | assert(bn_fits_in_words(bn, width)); |
507 | 71.2k | return bn; |
508 | 71.2k | } |
509 | 321 | BIGNUM *ret = bn_scratch_space_from_ctx(width, ctx); |
510 | 321 | if (ret == nullptr || !BN_copy(ret, bn) || !bn_resize_words(ret, width)) { |
511 | 0 | return nullptr; |
512 | 0 | } |
513 | 321 | return ret; |
514 | 321 | } |
515 | | |
516 | | int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, |
517 | 0 | BN_CTX *ctx) { |
518 | 0 | if (!BN_add(r, a, b)) { |
519 | 0 | return 0; |
520 | 0 | } |
521 | 0 | return BN_nnmod(r, r, m, ctx); |
522 | 0 | } |
523 | | |
524 | | int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, |
525 | 0 | const BIGNUM *m) { |
526 | 0 | UniquePtr<BN_CTX> ctx(BN_CTX_new()); |
527 | 0 | return ctx != nullptr && bn_mod_add_consttime(r, a, b, m, ctx.get()); |
528 | 0 | } |
529 | | |
530 | | int bssl::bn_mod_add_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, |
531 | 11.6k | const BIGNUM *m, BN_CTX *ctx) { |
532 | 11.6k | BN_CTXScope scope(ctx); |
533 | 11.6k | a = bn_resized_from_ctx(a, m->width, ctx); |
534 | 11.6k | b = bn_resized_from_ctx(b, m->width, ctx); |
535 | 11.6k | BIGNUM *tmp = bn_scratch_space_from_ctx(m->width, ctx); |
536 | 11.6k | if (a == nullptr || b == nullptr || tmp == nullptr || |
537 | 11.6k | !bn_wexpand(r, m->width)) { |
538 | 0 | return 0; |
539 | 0 | } |
540 | 11.6k | bn_mod_add_words(r->d, a->d, b->d, m->d, tmp->d, m->width); |
541 | 11.6k | r->width = m->width; |
542 | 11.6k | r->neg = 0; |
543 | 11.6k | return 1; |
544 | 11.6k | } |
545 | | |
546 | | int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, |
547 | 0 | BN_CTX *ctx) { |
548 | 0 | if (!BN_sub(r, a, b)) { |
549 | 0 | return 0; |
550 | 0 | } |
551 | 0 | return BN_nnmod(r, r, m, ctx); |
552 | 0 | } |
553 | | |
554 | | int bssl::bn_mod_sub_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, |
555 | 24.0k | const BIGNUM *m, BN_CTX *ctx) { |
556 | 24.0k | BN_CTXScope scope(ctx); |
557 | 24.0k | a = bn_resized_from_ctx(a, m->width, ctx); |
558 | 24.0k | b = bn_resized_from_ctx(b, m->width, ctx); |
559 | 24.0k | BIGNUM *tmp = bn_scratch_space_from_ctx(m->width, ctx); |
560 | 24.0k | if (a == nullptr || b == nullptr || tmp == nullptr || |
561 | 24.0k | !bn_wexpand(r, m->width)) { |
562 | 0 | return 0; |
563 | 0 | } |
564 | 24.0k | bn_mod_sub_words(r->d, a->d, b->d, m->d, tmp->d, m->width); |
565 | 24.0k | r->width = m->width; |
566 | 24.0k | r->neg = 0; |
567 | 24.0k | return 1; |
568 | 24.0k | } |
569 | | |
570 | | int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, |
571 | 0 | const BIGNUM *m) { |
572 | 0 | UniquePtr<BN_CTX> ctx(BN_CTX_new()); |
573 | 0 | return ctx != nullptr && bn_mod_sub_consttime(r, a, b, m, ctx.get()); |
574 | 0 | } |
575 | | |
576 | | int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, |
577 | 5.60M | BN_CTX *ctx) { |
578 | 5.60M | BN_CTXScope scope(ctx); |
579 | 5.60M | BIGNUM *t = BN_CTX_get(ctx); |
580 | 5.60M | if (t == nullptr) { |
581 | 0 | return 0; |
582 | 0 | } |
583 | | |
584 | 5.60M | if (a == b) { |
585 | 5.35M | if (!BN_sqr(t, a, ctx)) { |
586 | 0 | return 0; |
587 | 0 | } |
588 | 5.35M | } else { |
589 | 250k | if (!BN_mul(t, a, b, ctx)) { |
590 | 0 | return 0; |
591 | 0 | } |
592 | 250k | } |
593 | | |
594 | 5.60M | if (!BN_nnmod(r, t, m, ctx)) { |
595 | 0 | return 0; |
596 | 0 | } |
597 | | |
598 | 5.60M | return 1; |
599 | 5.60M | } |
600 | | |
601 | 274k | int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) { |
602 | 274k | if (!BN_sqr(r, a, ctx)) { |
603 | 0 | return 0; |
604 | 0 | } |
605 | | |
606 | | // r->neg == 0, thus we don't need BN_nnmod |
607 | 274k | return BN_mod(r, r, m, ctx); |
608 | 274k | } |
609 | | |
610 | | int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, |
611 | 0 | BN_CTX *ctx) { |
612 | 0 | if (!BN_nnmod(r, a, m, ctx)) { |
613 | 0 | return 0; |
614 | 0 | } |
615 | | |
616 | 0 | UniquePtr<BIGNUM> abs_m; |
617 | 0 | if (m->neg) { |
618 | 0 | abs_m.reset(BN_dup(m)); |
619 | 0 | if (abs_m == nullptr) { |
620 | 0 | return 0; |
621 | 0 | } |
622 | 0 | abs_m->neg = 0; |
623 | 0 | } |
624 | | |
625 | 0 | return bn_mod_lshift_consttime(r, r, n, (abs_m ? abs_m.get() : m), ctx); |
626 | 0 | } |
627 | | |
628 | | int bssl::bn_mod_lshift_consttime(BIGNUM *r, const BIGNUM *a, int n, |
629 | 8.61k | const BIGNUM *m, BN_CTX *ctx) { |
630 | 8.61k | if (!BN_copy(r, a) || !bn_resize_words(r, m->width)) { |
631 | 0 | return 0; |
632 | 0 | } |
633 | | |
634 | 8.61k | BN_CTXScope scope(ctx); |
635 | 8.61k | BIGNUM *tmp = bn_scratch_space_from_ctx(m->width, ctx); |
636 | 8.61k | if (tmp == nullptr) { |
637 | 0 | return 0; |
638 | 0 | } |
639 | 311k | for (int i = 0; i < n; i++) { |
640 | 302k | bn_mod_add_words(r->d, r->d, r->d, m->d, tmp->d, m->width); |
641 | 302k | } |
642 | 8.61k | r->neg = 0; |
643 | 8.61k | return 1; |
644 | 8.61k | } |
645 | | |
646 | 0 | int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m) { |
647 | 0 | UniquePtr<BN_CTX> ctx(BN_CTX_new()); |
648 | 0 | return ctx != nullptr && bn_mod_lshift_consttime(r, a, n, m, ctx.get()); |
649 | 0 | } |
650 | | |
651 | 0 | int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) { |
652 | 0 | if (!BN_lshift1(r, a)) { |
653 | 0 | return 0; |
654 | 0 | } |
655 | | |
656 | 0 | return BN_nnmod(r, r, m, ctx); |
657 | 0 | } |
658 | | |
659 | | int bssl::bn_mod_lshift1_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, |
660 | 3.89k | BN_CTX *ctx) { |
661 | 3.89k | return bn_mod_add_consttime(r, a, a, m, ctx); |
662 | 3.89k | } |
663 | | |
664 | 0 | int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m) { |
665 | 0 | UniquePtr<BN_CTX> ctx(BN_CTX_new()); |
666 | 0 | return ctx != nullptr && bn_mod_lshift1_consttime(r, a, m, ctx.get()); |
667 | 0 | } |
668 | | |
669 | 840 | BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) { |
670 | 840 | BN_ULONG ret = 0; |
671 | 840 | int i, j; |
672 | | |
673 | 840 | if (!w) { |
674 | | // actually this an error (division by zero) |
675 | 0 | return (BN_ULONG)-1; |
676 | 0 | } |
677 | | |
678 | 840 | if (a->width == 0) { |
679 | 0 | return 0; |
680 | 0 | } |
681 | | |
682 | | // normalize input for |bn_div_rem_words|. |
683 | 840 | j = BN_BITS2 - BN_num_bits_word(w); |
684 | 840 | w <<= j; |
685 | 840 | if (!BN_lshift(a, a, j)) { |
686 | 0 | return (BN_ULONG)-1; |
687 | 0 | } |
688 | | |
689 | 1.68k | for (i = a->width - 1; i >= 0; i--) { |
690 | 840 | BN_ULONG l = a->d[i]; |
691 | 840 | BN_ULONG d; |
692 | 840 | BN_ULONG unused_rem; |
693 | 840 | bn_div_rem_words(&d, &unused_rem, ret, l, w); |
694 | 840 | ret = l - (d * w); |
695 | 840 | a->d[i] = d; |
696 | 840 | } |
697 | | |
698 | 840 | bn_set_minimal_width(a); |
699 | 840 | ret >>= j; |
700 | 840 | return ret; |
701 | 840 | } |
702 | | |
703 | 0 | BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) { |
704 | | #ifndef BN_CAN_DIVIDE_ULLONG |
705 | | BN_ULONG ret = 0; |
706 | | #else |
707 | 0 | BN_ULLONG ret = 0; |
708 | 0 | #endif |
709 | 0 | int i; |
710 | |
|
711 | 0 | if (w == 0) { |
712 | 0 | return (BN_ULONG)-1; |
713 | 0 | } |
714 | | |
715 | | #ifndef BN_CAN_DIVIDE_ULLONG |
716 | | // If |w| is too long and we don't have |BN_ULLONG| division then we need to |
717 | | // fall back to using |BN_div_word|. |
718 | | if (w > ((BN_ULONG)1 << BN_BITS4)) { |
719 | | BIGNUM *tmp = BN_dup(a); |
720 | | if (tmp == nullptr) { |
721 | | return (BN_ULONG)-1; |
722 | | } |
723 | | ret = BN_div_word(tmp, w); |
724 | | BN_free(tmp); |
725 | | return ret; |
726 | | } |
727 | | #endif |
728 | | |
729 | 0 | for (i = a->width - 1; i >= 0; i--) { |
730 | | #ifndef BN_CAN_DIVIDE_ULLONG |
731 | | ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) & BN_MASK2l)) % w; |
732 | | ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w; |
733 | | #else |
734 | 0 | ret = (BN_ULLONG)(((ret << (BN_ULLONG)BN_BITS2) | a->d[i]) % (BN_ULLONG)w); |
735 | 0 | #endif |
736 | 0 | } |
737 | 0 | return (BN_ULONG)ret; |
738 | 0 | } |