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