/src/boringssl/crypto/fipsmodule/bn/bn.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 | | #include <string.h> |
20 | | |
21 | | #include <openssl/err.h> |
22 | | #include <openssl/mem.h> |
23 | | |
24 | | #include "../../mem_internal.h" |
25 | | #include "../delocate.h" |
26 | | #include "internal.h" |
27 | | |
28 | | |
29 | | using namespace bssl; |
30 | | |
31 | | // BN_MAX_WORDS is the maximum number of words allowed in a |BIGNUM|. It is |
32 | | // sized so byte and bit counts of a |BIGNUM| always fit in |int|, with room to |
33 | | // spare. |
34 | 857k | #define BN_MAX_WORDS (INT_MAX / (4 * BN_BITS2)) |
35 | | |
36 | 648k | BIGNUM *BN_new() { |
37 | 648k | BIGNUM *bn = New<BIGNUM>(); |
38 | | |
39 | 648k | if (bn == nullptr) { |
40 | 0 | return nullptr; |
41 | 0 | } |
42 | | |
43 | 648k | OPENSSL_memset(bn, 0, sizeof(BIGNUM)); |
44 | 648k | bn->flags = BN_FLG_MALLOCED; |
45 | | |
46 | 648k | return bn; |
47 | 648k | } |
48 | | |
49 | 0 | BIGNUM *BN_secure_new() { return BN_new(); } |
50 | | |
51 | 47.8k | void BN_init(BIGNUM *bn) { OPENSSL_memset(bn, 0, sizeof(BIGNUM)); } |
52 | | |
53 | 1.87M | void BN_free(BIGNUM *bn) { |
54 | 1.87M | if (bn == nullptr) { |
55 | 1.18M | return; |
56 | 1.18M | } |
57 | | |
58 | 695k | if ((bn->flags & BN_FLG_STATIC_DATA) == 0) { |
59 | 695k | OPENSSL_free(bn->d); |
60 | 695k | } |
61 | | |
62 | 695k | if (bn->flags & BN_FLG_MALLOCED) { |
63 | 647k | Delete(bn); |
64 | 647k | } else { |
65 | 47.8k | bn->d = nullptr; |
66 | 47.8k | } |
67 | 695k | } |
68 | | |
69 | 34.0k | void BN_clear_free(BIGNUM *bn) { BN_free(bn); } |
70 | | |
71 | 2.73k | BIGNUM *BN_dup(const BIGNUM *src) { |
72 | 2.73k | BIGNUM *copy; |
73 | | |
74 | 2.73k | if (src == nullptr) { |
75 | 0 | return nullptr; |
76 | 0 | } |
77 | | |
78 | 2.73k | copy = BN_new(); |
79 | 2.73k | if (copy == nullptr) { |
80 | 0 | return nullptr; |
81 | 0 | } |
82 | | |
83 | 2.73k | if (!BN_copy(copy, src)) { |
84 | 0 | BN_free(copy); |
85 | 0 | return nullptr; |
86 | 0 | } |
87 | | |
88 | 2.73k | return copy; |
89 | 2.73k | } |
90 | | |
91 | 785k | BIGNUM *BN_copy(BIGNUM *dest, const BIGNUM *src) { |
92 | 785k | if (src == dest) { |
93 | 8.73k | return dest; |
94 | 8.73k | } |
95 | | |
96 | 777k | if (!bn_wexpand(dest, src->width)) { |
97 | 0 | return nullptr; |
98 | 0 | } |
99 | | |
100 | 777k | OPENSSL_memcpy(dest->d, src->d, sizeof(src->d[0]) * src->width); |
101 | | |
102 | 777k | dest->width = src->width; |
103 | 777k | dest->neg = src->neg; |
104 | 777k | return dest; |
105 | 777k | } |
106 | | |
107 | 0 | void BN_clear(BIGNUM *bn) { |
108 | 0 | if (bn->d != nullptr) { |
109 | 0 | OPENSSL_memset(bn->d, 0, bn->dmax * sizeof(bn->d[0])); |
110 | 0 | } |
111 | |
|
112 | 0 | bn->width = 0; |
113 | 0 | bn->neg = 0; |
114 | 0 | } |
115 | | |
116 | 17 | DEFINE_METHOD_FUNCTION(BIGNUM, BN_value_one) { |
117 | 17 | static const BN_ULONG kOneLimbs[1] = {1}; |
118 | 17 | out->d = (BN_ULONG *)kOneLimbs; |
119 | 17 | out->width = 1; |
120 | 17 | out->dmax = 1; |
121 | 17 | out->neg = 0; |
122 | 17 | out->flags = BN_FLG_STATIC_DATA; |
123 | 17 | } |
124 | | |
125 | | // BN_num_bits_word returns the minimum number of bits needed to represent the |
126 | | // value in |l|. |
127 | 7.16M | unsigned BN_num_bits_word(BN_ULONG l) { |
128 | | // |BN_num_bits| is often called on RSA prime factors. These have public bit |
129 | | // lengths, but all bits beyond the high bit are secret, so count bits in |
130 | | // constant time. |
131 | 7.16M | BN_ULONG x, mask; |
132 | 7.16M | int bits = (l != 0); |
133 | | |
134 | 7.16M | #if BN_BITS2 > 32 |
135 | | // Look at the upper half of |x|. |x| is at most 64 bits long. |
136 | 7.16M | x = l >> 32; |
137 | | // Set |mask| to all ones if |x| (the top 32 bits of |l|) is non-zero and all |
138 | | // all zeros otherwise. |
139 | 7.16M | mask = 0u - x; |
140 | 7.16M | mask = (0u - (mask >> (BN_BITS2 - 1))); |
141 | | // If |x| is non-zero, the lower half is included in the bit count in full, |
142 | | // and we count the upper half. Otherwise, we count the lower half. |
143 | 7.16M | bits += 32 & mask; |
144 | 7.16M | l ^= (x ^ l) & mask; // |l| is |x| if |mask| and remains |l| otherwise. |
145 | 7.16M | #endif |
146 | | |
147 | | // The remaining blocks are analogous iterations at lower powers of two. |
148 | 7.16M | x = l >> 16; |
149 | 7.16M | mask = 0u - x; |
150 | 7.16M | mask = (0u - (mask >> (BN_BITS2 - 1))); |
151 | 7.16M | bits += 16 & mask; |
152 | 7.16M | l ^= (x ^ l) & mask; |
153 | | |
154 | 7.16M | x = l >> 8; |
155 | 7.16M | mask = 0u - x; |
156 | 7.16M | mask = (0u - (mask >> (BN_BITS2 - 1))); |
157 | 7.16M | bits += 8 & mask; |
158 | 7.16M | l ^= (x ^ l) & mask; |
159 | | |
160 | 7.16M | x = l >> 4; |
161 | 7.16M | mask = 0u - x; |
162 | 7.16M | mask = (0u - (mask >> (BN_BITS2 - 1))); |
163 | 7.16M | bits += 4 & mask; |
164 | 7.16M | l ^= (x ^ l) & mask; |
165 | | |
166 | 7.16M | x = l >> 2; |
167 | 7.16M | mask = 0u - x; |
168 | 7.16M | mask = (0u - (mask >> (BN_BITS2 - 1))); |
169 | 7.16M | bits += 2 & mask; |
170 | 7.16M | l ^= (x ^ l) & mask; |
171 | | |
172 | 7.16M | x = l >> 1; |
173 | 7.16M | mask = 0u - x; |
174 | 7.16M | mask = (0u - (mask >> (BN_BITS2 - 1))); |
175 | 7.16M | bits += 1 & mask; |
176 | | |
177 | 7.16M | return bits; |
178 | 7.16M | } |
179 | | |
180 | 7.14M | unsigned BN_num_bits(const BIGNUM *bn) { |
181 | 7.14M | const int width = bn_minimal_width(bn); |
182 | 7.14M | if (width == 0) { |
183 | 3.79k | return 0; |
184 | 3.79k | } |
185 | | |
186 | 7.13M | return (width - 1) * BN_BITS2 + BN_num_bits_word(bn->d[width - 1]); |
187 | 7.14M | } |
188 | | |
189 | 674k | unsigned BN_num_bytes(const BIGNUM *bn) { return (BN_num_bits(bn) + 7) / 8; } |
190 | | |
191 | 31.0M | void BN_zero(BIGNUM *bn) { bn->width = bn->neg = 0; } |
192 | | |
193 | 2.26k | int BN_one(BIGNUM *bn) { return BN_set_word(bn, 1); } |
194 | | |
195 | 38.2k | int BN_set_word(BIGNUM *bn, BN_ULONG value) { |
196 | 38.2k | if (value == 0) { |
197 | 0 | BN_zero(bn); |
198 | 0 | return 1; |
199 | 0 | } |
200 | | |
201 | 38.2k | if (!bn_wexpand(bn, 1)) { |
202 | 0 | return 0; |
203 | 0 | } |
204 | | |
205 | 38.2k | bn->neg = 0; |
206 | 38.2k | bn->d[0] = value; |
207 | 38.2k | bn->width = 1; |
208 | 38.2k | return 1; |
209 | 38.2k | } |
210 | | |
211 | 0 | int BN_set_u64(BIGNUM *bn, uint64_t value) { |
212 | 0 | #if BN_BITS2 == 64 |
213 | 0 | return BN_set_word(bn, value); |
214 | | #elif BN_BITS2 == 32 |
215 | | if (value <= BN_MASK2) { |
216 | | return BN_set_word(bn, (BN_ULONG)value); |
217 | | } |
218 | | |
219 | | if (!bn_wexpand(bn, 2)) { |
220 | | return 0; |
221 | | } |
222 | | |
223 | | bn->neg = 0; |
224 | | bn->d[0] = (BN_ULONG)value; |
225 | | bn->d[1] = (BN_ULONG)(value >> 32); |
226 | | bn->width = 2; |
227 | | return 1; |
228 | | #else |
229 | | #error "BN_BITS2 must be 32 or 64." |
230 | | #endif |
231 | 0 | } |
232 | | |
233 | 0 | int bssl::bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) { |
234 | 0 | if (!bn_wexpand(bn, num)) { |
235 | 0 | return 0; |
236 | 0 | } |
237 | 0 | OPENSSL_memmove(bn->d, words, num * sizeof(BN_ULONG)); |
238 | | // |bn_wexpand| verified that |num| isn't too large. |
239 | 0 | bn->width = (int)num; |
240 | 0 | bn->neg = 0; |
241 | 0 | return 1; |
242 | 0 | } |
243 | | |
244 | 256 | void bssl::bn_set_static_words(BIGNUM *bn, const BN_ULONG *words, size_t num) { |
245 | 256 | if ((bn->flags & BN_FLG_STATIC_DATA) == 0) { |
246 | 256 | OPENSSL_free(bn->d); |
247 | 256 | } |
248 | 256 | bn->d = (BN_ULONG *)words; |
249 | | |
250 | 256 | assert(num <= BN_MAX_WORDS); |
251 | 256 | bn->width = (int)num; |
252 | 256 | bn->dmax = (int)num; |
253 | 256 | bn->neg = 0; |
254 | 256 | bn->flags |= BN_FLG_STATIC_DATA; |
255 | 256 | } |
256 | | |
257 | 6.70M | int bssl::bn_fits_in_words(const BIGNUM *bn, size_t num) { |
258 | | // All words beyond |num| must be zero. |
259 | 6.70M | BN_ULONG mask = 0; |
260 | 40.0M | for (size_t i = num; i < (size_t)bn->width; i++) { |
261 | 33.3M | mask |= bn->d[i]; |
262 | 33.3M | } |
263 | 6.70M | return mask == 0; |
264 | 6.70M | } |
265 | | |
266 | 55.2k | int bssl::bn_copy_words(BN_ULONG *out, size_t num, const BIGNUM *bn) { |
267 | 55.2k | if (bn->neg) { |
268 | 0 | OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); |
269 | 0 | return 0; |
270 | 0 | } |
271 | | |
272 | 55.2k | size_t width = (size_t)bn->width; |
273 | 55.2k | if (width > num) { |
274 | 786 | if (!bn_fits_in_words(bn, num)) { |
275 | 733 | OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); |
276 | 733 | return 0; |
277 | 733 | } |
278 | 53 | width = num; |
279 | 53 | } |
280 | | |
281 | 54.5k | OPENSSL_memset(out, 0, sizeof(BN_ULONG) * num); |
282 | 54.5k | OPENSSL_memcpy(out, bn->d, sizeof(BN_ULONG) * width); |
283 | 54.5k | return 1; |
284 | 55.2k | } |
285 | | |
286 | 495k | int BN_is_negative(const BIGNUM *bn) { return bn->neg != 0; } |
287 | | |
288 | 5.35k | void BN_set_negative(BIGNUM *bn, int sign) { |
289 | 5.35k | if (sign && !BN_is_zero(bn)) { |
290 | 3.52k | bn->neg = 1; |
291 | 3.52k | } else { |
292 | 1.83k | bn->neg = 0; |
293 | 1.83k | } |
294 | 5.35k | } |
295 | | |
296 | 47.7M | int bssl::bn_wexpand(BIGNUM *bn, size_t words) { |
297 | 47.7M | BN_ULONG *a; |
298 | | |
299 | 47.7M | if (words <= (size_t)bn->dmax) { |
300 | 46.9M | return 1; |
301 | 46.9M | } |
302 | | |
303 | 857k | if (words > BN_MAX_WORDS) { |
304 | 0 | OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); |
305 | 0 | return 0; |
306 | 0 | } |
307 | | |
308 | 857k | if (bn->flags & BN_FLG_STATIC_DATA) { |
309 | 0 | OPENSSL_PUT_ERROR(BN, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); |
310 | 0 | return 0; |
311 | 0 | } |
312 | | |
313 | 857k | a = reinterpret_cast<BN_ULONG *>(OPENSSL_calloc(words, sizeof(BN_ULONG))); |
314 | 857k | if (a == nullptr) { |
315 | 0 | return 0; |
316 | 0 | } |
317 | | |
318 | 857k | OPENSSL_memcpy(a, bn->d, sizeof(BN_ULONG) * bn->width); |
319 | | |
320 | 857k | OPENSSL_free(bn->d); |
321 | 857k | bn->d = a; |
322 | 857k | bn->dmax = (int)words; |
323 | | |
324 | 857k | return 1; |
325 | 857k | } |
326 | | |
327 | 1.67k | int bssl::bn_expand(BIGNUM *bn, size_t bits) { |
328 | 1.67k | if (bits + BN_BITS2 - 1 < bits) { |
329 | 0 | OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); |
330 | 0 | return 0; |
331 | 0 | } |
332 | 1.67k | return bn_wexpand(bn, (bits + BN_BITS2 - 1) / BN_BITS2); |
333 | 1.67k | } |
334 | | |
335 | 6.70M | int bssl::bn_resize_words(BIGNUM *bn, size_t words) { |
336 | 6.70M | if ((size_t)bn->width <= words) { |
337 | 6.68M | if (!bn_wexpand(bn, words)) { |
338 | 0 | return 0; |
339 | 0 | } |
340 | 6.68M | OPENSSL_memset(bn->d + bn->width, 0, |
341 | 6.68M | (words - bn->width) * sizeof(BN_ULONG)); |
342 | 6.68M | bn->width = (int)words; |
343 | 6.68M | return 1; |
344 | 6.68M | } |
345 | | |
346 | | // All words beyond the new width must be zero. |
347 | 21.1k | if (!bn_fits_in_words(bn, words)) { |
348 | 0 | OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); |
349 | 0 | return 0; |
350 | 0 | } |
351 | 21.1k | bn->width = (int)words; |
352 | 21.1k | return 1; |
353 | 21.1k | } |
354 | | |
355 | | void bssl::bn_select_words(BN_ULONG *r, BN_ULONG mask, const BN_ULONG *a, |
356 | 433M | const BN_ULONG *b, size_t num) { |
357 | 3.09G | for (size_t i = 0; i < num; i++) { |
358 | 2.66G | static_assert(sizeof(BN_ULONG) <= sizeof(crypto_word_t), |
359 | 2.66G | "crypto_word_t is too small"); |
360 | 2.66G | r[i] = constant_time_select_w(mask, a[i], b[i]); |
361 | 2.66G | } |
362 | 433M | } |
363 | | |
364 | 55.7M | int bssl::bn_minimal_width(const BIGNUM *bn) { |
365 | 55.7M | int ret = bn->width; |
366 | 106M | while (ret > 0 && bn->d[ret - 1] == 0) { |
367 | 51.2M | ret--; |
368 | 51.2M | } |
369 | 55.7M | return ret; |
370 | 55.7M | } |
371 | | |
372 | 48.5M | void bssl::bn_set_minimal_width(BIGNUM *bn) { |
373 | 48.5M | bn->width = bn_minimal_width(bn); |
374 | 48.5M | if (bn->width == 0) { |
375 | 785k | bn->neg = 0; |
376 | 785k | } |
377 | 48.5M | } |