/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 | 931k | #define BN_MAX_WORDS (INT_MAX / (4 * BN_BITS2)) |
35 | | |
36 | 709k | BIGNUM *BN_new() { |
37 | 709k | BIGNUM *bn = New<BIGNUM>(); |
38 | | |
39 | 709k | if (bn == nullptr) { |
40 | 0 | return nullptr; |
41 | 0 | } |
42 | | |
43 | 709k | OPENSSL_memset(bn, 0, sizeof(BIGNUM)); |
44 | 709k | bn->flags = BN_FLG_MALLOCED; |
45 | | |
46 | 709k | return bn; |
47 | 709k | } |
48 | | |
49 | 0 | BIGNUM *BN_secure_new() { return BN_new(); } |
50 | | |
51 | 52.3k | void BN_init(BIGNUM *bn) { OPENSSL_memset(bn, 0, sizeof(BIGNUM)); } |
52 | | |
53 | 761k | void BN_free(BIGNUM *bn) { |
54 | 761k | if (bn == nullptr) { |
55 | 0 | return; |
56 | 0 | } |
57 | | |
58 | 761k | if ((bn->flags & BN_FLG_STATIC_DATA) == 0) { |
59 | 761k | OPENSSL_free(bn->d); |
60 | 761k | } |
61 | | |
62 | 761k | if (bn->flags & BN_FLG_MALLOCED) { |
63 | 709k | Delete(bn); |
64 | 709k | } else { |
65 | 52.2k | bn->d = nullptr; |
66 | 52.2k | } |
67 | 761k | } |
68 | | |
69 | 0 | void BN_clear_free(BIGNUM *bn) { BN_free(bn); } |
70 | | |
71 | 3.13k | BIGNUM *BN_dup(const BIGNUM *src) { |
72 | 3.13k | BIGNUM *copy; |
73 | | |
74 | 3.13k | if (src == nullptr) { |
75 | 0 | return nullptr; |
76 | 0 | } |
77 | | |
78 | 3.13k | copy = BN_new(); |
79 | 3.13k | if (copy == nullptr) { |
80 | 0 | return nullptr; |
81 | 0 | } |
82 | | |
83 | 3.13k | if (!BN_copy(copy, src)) { |
84 | 0 | BN_free(copy); |
85 | 0 | return nullptr; |
86 | 0 | } |
87 | | |
88 | 3.13k | return copy; |
89 | 3.13k | } |
90 | | |
91 | 833k | BIGNUM *BN_copy(BIGNUM *dest, const BIGNUM *src) { |
92 | 833k | if (src == dest) { |
93 | 10.0k | return dest; |
94 | 10.0k | } |
95 | | |
96 | 823k | if (!bn_wexpand(dest, src->width)) { |
97 | 0 | return nullptr; |
98 | 0 | } |
99 | | |
100 | 823k | OPENSSL_memcpy(dest->d, src->d, sizeof(src->d[0]) * src->width); |
101 | | |
102 | 823k | dest->width = src->width; |
103 | 823k | dest->neg = src->neg; |
104 | 823k | return dest; |
105 | 823k | } |
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 | 8.35M | 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 | 8.35M | BN_ULONG x, mask; |
132 | 8.35M | int bits = (l != 0); |
133 | | |
134 | 8.35M | #if BN_BITS2 > 32 |
135 | | // Look at the upper half of |x|. |x| is at most 64 bits long. |
136 | 8.35M | 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 | 8.35M | mask = 0u - x; |
140 | 8.35M | 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 | 8.35M | bits += 32 & mask; |
144 | 8.35M | l ^= (x ^ l) & mask; // |l| is |x| if |mask| and remains |l| otherwise. |
145 | 8.35M | #endif |
146 | | |
147 | | // The remaining blocks are analogous iterations at lower powers of two. |
148 | 8.35M | x = l >> 16; |
149 | 8.35M | mask = 0u - x; |
150 | 8.35M | mask = (0u - (mask >> (BN_BITS2 - 1))); |
151 | 8.35M | bits += 16 & mask; |
152 | 8.35M | l ^= (x ^ l) & mask; |
153 | | |
154 | 8.35M | x = l >> 8; |
155 | 8.35M | mask = 0u - x; |
156 | 8.35M | mask = (0u - (mask >> (BN_BITS2 - 1))); |
157 | 8.35M | bits += 8 & mask; |
158 | 8.35M | l ^= (x ^ l) & mask; |
159 | | |
160 | 8.35M | x = l >> 4; |
161 | 8.35M | mask = 0u - x; |
162 | 8.35M | mask = (0u - (mask >> (BN_BITS2 - 1))); |
163 | 8.35M | bits += 4 & mask; |
164 | 8.35M | l ^= (x ^ l) & mask; |
165 | | |
166 | 8.35M | x = l >> 2; |
167 | 8.35M | mask = 0u - x; |
168 | 8.35M | mask = (0u - (mask >> (BN_BITS2 - 1))); |
169 | 8.35M | bits += 2 & mask; |
170 | 8.35M | l ^= (x ^ l) & mask; |
171 | | |
172 | 8.35M | x = l >> 1; |
173 | 8.35M | mask = 0u - x; |
174 | 8.35M | mask = (0u - (mask >> (BN_BITS2 - 1))); |
175 | 8.35M | bits += 1 & mask; |
176 | | |
177 | 8.35M | return bits; |
178 | 8.35M | } |
179 | | |
180 | 8.33M | unsigned BN_num_bits(const BIGNUM *bn) { |
181 | 8.33M | const int width = bn_minimal_width(bn); |
182 | 8.33M | if (width == 0) { |
183 | 3.83k | return 0; |
184 | 3.83k | } |
185 | | |
186 | 8.32M | return (width - 1) * BN_BITS2 + BN_num_bits_word(bn->d[width - 1]); |
187 | 8.33M | } |
188 | | |
189 | 713k | unsigned BN_num_bytes(const BIGNUM *bn) { return (BN_num_bits(bn) + 7) / 8; } |
190 | | |
191 | 36.5M | void BN_zero(BIGNUM *bn) { bn->width = bn->neg = 0; } |
192 | | |
193 | 2.48k | int BN_one(BIGNUM *bn) { return BN_set_word(bn, 1); } |
194 | | |
195 | 44.0k | int BN_set_word(BIGNUM *bn, BN_ULONG value) { |
196 | 44.0k | if (value == 0) { |
197 | 0 | BN_zero(bn); |
198 | 0 | return 1; |
199 | 0 | } |
200 | | |
201 | 44.0k | if (!bn_wexpand(bn, 1)) { |
202 | 0 | return 0; |
203 | 0 | } |
204 | | |
205 | 44.0k | bn->neg = 0; |
206 | 44.0k | bn->d[0] = value; |
207 | 44.0k | bn->width = 1; |
208 | 44.0k | return 1; |
209 | 44.0k | } |
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 | 7.82M | int bssl::bn_fits_in_words(const BIGNUM *bn, size_t num) { |
258 | | // All words beyond |num| must be zero. |
259 | 7.82M | BN_ULONG mask = 0; |
260 | 45.4M | for (size_t i = num; i < (size_t)bn->width; i++) { |
261 | 37.6M | mask |= bn->d[i]; |
262 | 37.6M | } |
263 | 7.82M | return mask == 0; |
264 | 7.82M | } |
265 | | |
266 | 54.5k | int bssl::bn_copy_words(BN_ULONG *out, size_t num, const BIGNUM *bn) { |
267 | 54.5k | if (bn->neg) { |
268 | 0 | OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); |
269 | 0 | return 0; |
270 | 0 | } |
271 | | |
272 | 54.5k | size_t width = (size_t)bn->width; |
273 | 54.5k | if (width > num) { |
274 | 898 | if (!bn_fits_in_words(bn, num)) { |
275 | 826 | OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); |
276 | 826 | return 0; |
277 | 826 | } |
278 | 72 | width = num; |
279 | 72 | } |
280 | | |
281 | 53.7k | OPENSSL_memset(out, 0, sizeof(BN_ULONG) * num); |
282 | 53.7k | OPENSSL_memcpy(out, bn->d, sizeof(BN_ULONG) * width); |
283 | 53.7k | return 1; |
284 | 54.5k | } |
285 | | |
286 | 554k | int BN_is_negative(const BIGNUM *bn) { return bn->neg != 0; } |
287 | | |
288 | 5.94k | void BN_set_negative(BIGNUM *bn, int sign) { |
289 | 5.94k | if (sign && !BN_is_zero(bn)) { |
290 | 3.83k | bn->neg = 1; |
291 | 3.83k | } else { |
292 | 2.11k | bn->neg = 0; |
293 | 2.11k | } |
294 | 5.94k | } |
295 | | |
296 | 55.9M | int bssl::bn_wexpand(BIGNUM *bn, size_t words) { |
297 | 55.9M | BN_ULONG *a; |
298 | | |
299 | 55.9M | if (words <= (size_t)bn->dmax) { |
300 | 54.9M | return 1; |
301 | 54.9M | } |
302 | | |
303 | 931k | if (words > BN_MAX_WORDS) { |
304 | 0 | OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); |
305 | 0 | return 0; |
306 | 0 | } |
307 | | |
308 | 931k | 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 | 931k | a = reinterpret_cast<BN_ULONG *>(OPENSSL_calloc(words, sizeof(BN_ULONG))); |
314 | 931k | if (a == nullptr) { |
315 | 0 | return 0; |
316 | 0 | } |
317 | | |
318 | 931k | OPENSSL_memcpy(a, bn->d, sizeof(BN_ULONG) * bn->width); |
319 | | |
320 | 931k | OPENSSL_free(bn->d); |
321 | 931k | bn->d = a; |
322 | 931k | bn->dmax = (int)words; |
323 | | |
324 | 931k | return 1; |
325 | 931k | } |
326 | | |
327 | 1.79k | int bssl::bn_expand(BIGNUM *bn, size_t bits) { |
328 | 1.79k | 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.79k | return bn_wexpand(bn, (bits + BN_BITS2 - 1) / BN_BITS2); |
333 | 1.79k | } |
334 | | |
335 | 7.82M | int bssl::bn_resize_words(BIGNUM *bn, size_t words) { |
336 | 7.82M | if ((size_t)bn->width <= words) { |
337 | 7.80M | if (!bn_wexpand(bn, words)) { |
338 | 0 | return 0; |
339 | 0 | } |
340 | 7.80M | OPENSSL_memset(bn->d + bn->width, 0, |
341 | 7.80M | (words - bn->width) * sizeof(BN_ULONG)); |
342 | 7.80M | bn->width = (int)words; |
343 | 7.80M | return 1; |
344 | 7.80M | } |
345 | | |
346 | | // All words beyond the new width must be zero. |
347 | 20.2k | 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 | 20.2k | bn->width = (int)words; |
352 | 20.2k | return 1; |
353 | 20.2k | } |
354 | | |
355 | | void bssl::bn_select_words(BN_ULONG *r, BN_ULONG mask, const BN_ULONG *a, |
356 | 393M | const BN_ULONG *b, size_t num) { |
357 | 2.81G | for (size_t i = 0; i < num; i++) { |
358 | 2.42G | static_assert(sizeof(BN_ULONG) <= sizeof(crypto_word_t), |
359 | 2.42G | "crypto_word_t is too small"); |
360 | 2.42G | r[i] = constant_time_select_w(mask, a[i], b[i]); |
361 | 2.42G | } |
362 | 393M | } |
363 | | |
364 | 65.8M | int bssl::bn_minimal_width(const BIGNUM *bn) { |
365 | 65.8M | int ret = bn->width; |
366 | 125M | while (ret > 0 && bn->d[ret - 1] == 0) { |
367 | 59.9M | ret--; |
368 | 59.9M | } |
369 | 65.8M | return ret; |
370 | 65.8M | } |
371 | | |
372 | 57.4M | void bssl::bn_set_minimal_width(BIGNUM *bn) { |
373 | 57.4M | bn->width = bn_minimal_width(bn); |
374 | 57.4M | if (bn->width == 0) { |
375 | 884k | bn->neg = 0; |
376 | 884k | } |
377 | 57.4M | } |