bn.c
Go to the documentation of this file.
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to. The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  * notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  * notice, this list of conditions and the following disclaimer in the
29  * documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  * must display the following acknowledgement:
32  * "This product includes cryptographic software written by
33  * Eric Young (eay@cryptsoft.com)"
34  * The word 'cryptographic' can be left out if the rouines from the library
35  * being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  * the apps directory (application code) you must include an acknowledgement:
38  * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed. i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.] */
56 
57 #include <openssl/bn.h>
58 
59 #include <limits.h>
60 #include <string.h>
61 
62 #include <openssl/err.h>
63 #include <openssl/mem.h>
64 
65 #include "internal.h"
66 #include "../delocate.h"
67 
68 
69 BIGNUM *BN_new(void) {
70  BIGNUM *bn = OPENSSL_malloc(sizeof(BIGNUM));
71 
72  if (bn == NULL) {
74  return NULL;
75  }
76 
77  OPENSSL_memset(bn, 0, sizeof(BIGNUM));
78  bn->flags = BN_FLG_MALLOCED;
79 
80  return bn;
81 }
82 
83 void BN_init(BIGNUM *bn) {
84  OPENSSL_memset(bn, 0, sizeof(BIGNUM));
85 }
86 
87 void BN_free(BIGNUM *bn) {
88  if (bn == NULL) {
89  return;
90  }
91 
92  if ((bn->flags & BN_FLG_STATIC_DATA) == 0) {
93  OPENSSL_free(bn->d);
94  }
95 
96  if (bn->flags & BN_FLG_MALLOCED) {
97  OPENSSL_free(bn);
98  } else {
99  bn->d = NULL;
100  }
101 }
102 
104  BN_free(bn);
105 }
106 
107 BIGNUM *BN_dup(const BIGNUM *src) {
108  BIGNUM *copy;
109 
110  if (src == NULL) {
111  return NULL;
112  }
113 
114  copy = BN_new();
115  if (copy == NULL) {
116  return NULL;
117  }
118 
119  if (!BN_copy(copy, src)) {
120  BN_free(copy);
121  return NULL;
122  }
123 
124  return copy;
125 }
126 
127 BIGNUM *BN_copy(BIGNUM *dest, const BIGNUM *src) {
128  if (src == dest) {
129  return dest;
130  }
131 
132  if (!bn_wexpand(dest, src->width)) {
133  return NULL;
134  }
135 
136  OPENSSL_memcpy(dest->d, src->d, sizeof(src->d[0]) * src->width);
137 
138  dest->width = src->width;
139  dest->neg = src->neg;
140  return dest;
141 }
142 
143 void BN_clear(BIGNUM *bn) {
144  if (bn->d != NULL) {
145  OPENSSL_memset(bn->d, 0, bn->dmax * sizeof(bn->d[0]));
146  }
147 
148  bn->width = 0;
149  bn->neg = 0;
150 }
151 
153  static const BN_ULONG kOneLimbs[1] = { 1 };
154  out->d = (BN_ULONG*) kOneLimbs;
155  out->width = 1;
156  out->dmax = 1;
157  out->neg = 0;
158  out->flags = BN_FLG_STATIC_DATA;
159 }
160 
161 // BN_num_bits_word returns the minimum number of bits needed to represent the
162 // value in |l|.
163 unsigned BN_num_bits_word(BN_ULONG l) {
164  // |BN_num_bits| is often called on RSA prime factors. These have public bit
165  // lengths, but all bits beyond the high bit are secret, so count bits in
166  // constant time.
167  BN_ULONG x, mask;
168  int bits = (l != 0);
169 
170 #if BN_BITS2 > 32
171  // Look at the upper half of |x|. |x| is at most 64 bits long.
172  x = l >> 32;
173  // Set |mask| to all ones if |x| (the top 32 bits of |l|) is non-zero and all
174  // all zeros otherwise.
175  mask = 0u - x;
176  mask = (0u - (mask >> (BN_BITS2 - 1)));
177  // If |x| is non-zero, the lower half is included in the bit count in full,
178  // and we count the upper half. Otherwise, we count the lower half.
179  bits += 32 & mask;
180  l ^= (x ^ l) & mask; // |l| is |x| if |mask| and remains |l| otherwise.
181 #endif
182 
183  // The remaining blocks are analogous iterations at lower powers of two.
184  x = l >> 16;
185  mask = 0u - x;
186  mask = (0u - (mask >> (BN_BITS2 - 1)));
187  bits += 16 & mask;
188  l ^= (x ^ l) & mask;
189 
190  x = l >> 8;
191  mask = 0u - x;
192  mask = (0u - (mask >> (BN_BITS2 - 1)));
193  bits += 8 & mask;
194  l ^= (x ^ l) & mask;
195 
196  x = l >> 4;
197  mask = 0u - x;
198  mask = (0u - (mask >> (BN_BITS2 - 1)));
199  bits += 4 & mask;
200  l ^= (x ^ l) & mask;
201 
202  x = l >> 2;
203  mask = 0u - x;
204  mask = (0u - (mask >> (BN_BITS2 - 1)));
205  bits += 2 & mask;
206  l ^= (x ^ l) & mask;
207 
208  x = l >> 1;
209  mask = 0u - x;
210  mask = (0u - (mask >> (BN_BITS2 - 1)));
211  bits += 1 & mask;
212 
213  return bits;
214 }
215 
216 unsigned BN_num_bits(const BIGNUM *bn) {
217  const int width = bn_minimal_width(bn);
218  if (width == 0) {
219  return 0;
220  }
221 
222  return (width - 1) * BN_BITS2 + BN_num_bits_word(bn->d[width - 1]);
223 }
224 
225 unsigned BN_num_bytes(const BIGNUM *bn) {
226  return (BN_num_bits(bn) + 7) / 8;
227 }
228 
229 void BN_zero(BIGNUM *bn) {
230  bn->width = bn->neg = 0;
231 }
232 
233 int BN_one(BIGNUM *bn) {
234  return BN_set_word(bn, 1);
235 }
236 
237 int BN_set_word(BIGNUM *bn, BN_ULONG value) {
238  if (value == 0) {
239  BN_zero(bn);
240  return 1;
241  }
242 
243  if (!bn_wexpand(bn, 1)) {
244  return 0;
245  }
246 
247  bn->neg = 0;
248  bn->d[0] = value;
249  bn->width = 1;
250  return 1;
251 }
252 
254 #if BN_BITS2 == 64
255  return BN_set_word(bn, value);
256 #elif BN_BITS2 == 32
257  if (value <= BN_MASK2) {
258  return BN_set_word(bn, (BN_ULONG)value);
259  }
260 
261  if (!bn_wexpand(bn, 2)) {
262  return 0;
263  }
264 
265  bn->neg = 0;
266  bn->d[0] = (BN_ULONG)value;
267  bn->d[1] = (BN_ULONG)(value >> 32);
268  bn->width = 2;
269  return 1;
270 #else
271 #error "BN_BITS2 must be 32 or 64."
272 #endif
273 }
274 
275 int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) {
276  if (!bn_wexpand(bn, num)) {
277  return 0;
278  }
279  OPENSSL_memmove(bn->d, words, num * sizeof(BN_ULONG));
280  // |bn_wexpand| verified that |num| isn't too large.
281  bn->width = (int)num;
282  bn->neg = 0;
283  return 1;
284 }
285 
286 void bn_set_static_words(BIGNUM *bn, const BN_ULONG *words, size_t num) {
287  if ((bn->flags & BN_FLG_STATIC_DATA) == 0) {
288  OPENSSL_free(bn->d);
289  }
290  bn->d = (BN_ULONG *)words;
291 
292  bn->width = num;
293  bn->dmax = num;
294  bn->neg = 0;
295  bn->flags |= BN_FLG_STATIC_DATA;
296 }
297 
298 int bn_fits_in_words(const BIGNUM *bn, size_t num) {
299  // All words beyond |num| must be zero.
300  BN_ULONG mask = 0;
301  for (size_t i = num; i < (size_t)bn->width; i++) {
302  mask |= bn->d[i];
303  }
304  return mask == 0;
305 }
306 
307 int bn_copy_words(BN_ULONG *out, size_t num, const BIGNUM *bn) {
308  if (bn->neg) {
310  return 0;
311  }
312 
313  size_t width = (size_t)bn->width;
314  if (width > num) {
315  if (!bn_fits_in_words(bn, num)) {
317  return 0;
318  }
319  width = num;
320  }
321 
322  OPENSSL_memset(out, 0, sizeof(BN_ULONG) * num);
323  OPENSSL_memcpy(out, bn->d, sizeof(BN_ULONG) * width);
324  return 1;
325 }
326 
327 int BN_is_negative(const BIGNUM *bn) {
328  return bn->neg != 0;
329 }
330 
331 void BN_set_negative(BIGNUM *bn, int sign) {
332  if (sign && !BN_is_zero(bn)) {
333  bn->neg = 1;
334  } else {
335  bn->neg = 0;
336  }
337 }
338 
339 int bn_wexpand(BIGNUM *bn, size_t words) {
340  BN_ULONG *a;
341 
342  if (words <= (size_t)bn->dmax) {
343  return 1;
344  }
345 
346  if (words > (INT_MAX / (4 * BN_BITS2))) {
348  return 0;
349  }
350 
351  if (bn->flags & BN_FLG_STATIC_DATA) {
353  return 0;
354  }
355 
356  a = OPENSSL_malloc(sizeof(BN_ULONG) * words);
357  if (a == NULL) {
359  return 0;
360  }
361 
362  OPENSSL_memcpy(a, bn->d, sizeof(BN_ULONG) * bn->width);
363 
364  OPENSSL_free(bn->d);
365  bn->d = a;
366  bn->dmax = (int)words;
367 
368  return 1;
369 }
370 
371 int bn_expand(BIGNUM *bn, size_t bits) {
372  if (bits + BN_BITS2 - 1 < bits) {
374  return 0;
375  }
376  return bn_wexpand(bn, (bits+BN_BITS2-1)/BN_BITS2);
377 }
378 
379 int bn_resize_words(BIGNUM *bn, size_t words) {
380 #if defined(OPENSSL_PPC64LE)
381  // This is a workaround for a miscompilation bug in Clang 7.0.1 on POWER.
382  // The unittests catch the miscompilation, if it occurs, and it manifests
383  // as a crash in |bn_fits_in_words|.
384  //
385  // The bug only triggers if building in FIPS mode and with -O3. Clang 8.0.1
386  // has the same bug but this workaround is not effective there---I've not
387  // been able to find a workaround for 8.0.1.
388  //
389  // At the time of writing (2019-08-08), Clang git does *not* have this bug
390  // and does not need this workaroud. The current git version should go on to
391  // be Clang 10 thus, once we can depend on that, this can be removed.
392  if (value_barrier_w((size_t)bn->width == words)) {
393  return 1;
394  }
395 #endif
396 
397  if ((size_t)bn->width <= words) {
398  if (!bn_wexpand(bn, words)) {
399  return 0;
400  }
401  OPENSSL_memset(bn->d + bn->width, 0,
402  (words - bn->width) * sizeof(BN_ULONG));
403  bn->width = words;
404  return 1;
405  }
406 
407  // All words beyond the new width must be zero.
408  if (!bn_fits_in_words(bn, words)) {
410  return 0;
411  }
412  bn->width = words;
413  return 1;
414 }
415 
416 void bn_select_words(BN_ULONG *r, BN_ULONG mask, const BN_ULONG *a,
417  const BN_ULONG *b, size_t num) {
418  for (size_t i = 0; i < num; i++) {
419  OPENSSL_STATIC_ASSERT(sizeof(BN_ULONG) <= sizeof(crypto_word_t),
420  "crypto_word_t is too small");
421  r[i] = constant_time_select_w(mask, a[i], b[i]);
422  }
423 }
424 
425 int bn_minimal_width(const BIGNUM *bn) {
426  int ret = bn->width;
427  while (ret > 0 && bn->d[ret - 1] == 0) {
428  ret--;
429  }
430  return ret;
431 }
432 
434  bn->width = bn_minimal_width(bn);
435  if (bn->width == 0) {
436  bn->neg = 0;
437  }
438 }
BN_zero
void BN_zero(BIGNUM *bn)
Definition: bn.c:229
bn.h
width
int width
Definition: libuv/docs/code/tty-gravity/main.c:10
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
BN_FLG_STATIC_DATA
#define BN_FLG_STATIC_DATA
Definition: bn.h:997
BN_free
void BN_free(BIGNUM *bn)
Definition: bn.c:87
bn_set_static_words
void bn_set_static_words(BIGNUM *bn, const BN_ULONG *words, size_t num)
Definition: bn.c:286
bn_fits_in_words
int bn_fits_in_words(const BIGNUM *bn, size_t num)
Definition: bn.c:298
BN_one
int BN_one(BIGNUM *bn)
Definition: bn.c:233
bn_set_words
int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num)
Definition: bn.c:275
OPENSSL_PUT_ERROR
#define OPENSSL_PUT_ERROR(library, reason)
Definition: err.h:423
bignum_st::width
int width
Definition: bn.h:975
string.h
copy
static int copy(grpc_slice_buffer *input, grpc_slice_buffer *output)
Definition: message_compress.cc:145
BN_is_negative
int BN_is_negative(const BIGNUM *bn)
Definition: bn.c:327
bn_minimal_width
int bn_minimal_width(const BIGNUM *bn)
Definition: bn.c:425
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
words
std::vector< std::string > words
Definition: bloaty/third_party/protobuf/src/google/protobuf/repeated_field_unittest.cc:1787
BN_clear
void BN_clear(BIGNUM *bn)
Definition: bn.c:143
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
BN_R_NEGATIVE_NUMBER
#define BN_R_NEGATIVE_NUMBER
Definition: bn.h:1045
bn_set_minimal_width
void bn_set_minimal_width(BIGNUM *bn)
Definition: bn.c:433
BN_set_negative
void BN_set_negative(BIGNUM *bn, int sign)
Definition: bn.c:331
OPENSSL_memset
static void * OPENSSL_memset(void *dst, int c, size_t n)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:835
BN_copy
BIGNUM * BN_copy(BIGNUM *dest, const BIGNUM *src)
Definition: bn.c:127
BN_value_one
const OPENSSL_EXPORT BIGNUM * BN_value_one(void)
OPENSSL_malloc
#define OPENSSL_malloc
Definition: boringssl_prefix_symbols.h:1885
xds_interop_client.int
int
Definition: xds_interop_client.py:113
bn_expand
int bn_expand(BIGNUM *bn, size_t bits)
Definition: bn.c:371
bn_select_words
void bn_select_words(BN_ULONG *r, BN_ULONG mask, const BN_ULONG *a, const BN_ULONG *b, size_t num)
Definition: bn.c:416
BN_R_BIGNUM_TOO_LONG
#define BN_R_BIGNUM_TOO_LONG
Definition: bn.h:1038
BN_num_bytes
unsigned BN_num_bytes(const BIGNUM *bn)
Definition: bn.c:225
BN_clear_free
void BN_clear_free(BIGNUM *bn)
Definition: bn.c:103
BN_FLG_MALLOCED
#define BN_FLG_MALLOCED
Definition: bn.h:996
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
OPENSSL_memcpy
static void * OPENSSL_memcpy(void *dst, const void *src, size_t n)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:819
bits
OPENSSL_EXPORT ASN1_BIT_STRING * bits
Definition: x509v3.h:482
err.h
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
BN_is_zero
#define BN_is_zero
Definition: boringssl_prefix_symbols.h:940
BN_new
BIGNUM * BN_new(void)
Definition: bn.c:69
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
tests.qps.qps_worker.dest
dest
Definition: qps_worker.py:45
BN_set_u64
int BN_set_u64(BIGNUM *bn, uint64_t value)
Definition: bn.c:253
bn_copy_words
int bn_copy_words(BN_ULONG *out, size_t num, const BIGNUM *bn)
Definition: bn.c:307
value
const char * value
Definition: hpack_parser_table.cc:165
bignum_st::neg
int neg
Definition: bn.h:979
value_barrier_w
static crypto_word_t value_barrier_w(crypto_word_t a)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:288
BN_set_word
int BN_set_word(BIGNUM *bn, BN_ULONG value)
Definition: bn.c:237
bignum_st
Definition: bn.h:957
internal.h
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
fix_build_deps.r
r
Definition: fix_build_deps.py:491
bignum_st::d
BN_ULONG * d
Definition: bn.h:960
xds_manager.num
num
Definition: xds_manager.py:56
OPENSSL_memmove
static void * OPENSSL_memmove(void *dst, const void *src, size_t n)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:827
BN_dup
BIGNUM * BN_dup(const BIGNUM *src)
Definition: bn.c:107
constant_time_select_w
static crypto_word_t constant_time_select_w(crypto_word_t mask, crypto_word_t a, crypto_word_t b)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:420
BN_num_bits_word
unsigned BN_num_bits_word(BN_ULONG l)
Definition: bn.c:163
bn_resize_words
int bn_resize_words(BIGNUM *bn, size_t words)
Definition: bn.c:379
BN_init
void BN_init(BIGNUM *bn)
Definition: bn.c:83
mem.h
bignum_st::flags
int flags
Definition: bn.h:981
run_grpclb_interop_tests.l
dictionary l
Definition: run_grpclb_interop_tests.py:410
BN_R_EXPAND_ON_STATIC_BIGNUM_DATA
#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA
Definition: bn.h:1042
OPENSSL_free
#define OPENSSL_free
Definition: boringssl_prefix_symbols.h:1869
DEFINE_METHOD_FUNCTION
DEFINE_METHOD_FUNCTION(BIGNUM, BN_value_one)
Definition: bn.c:152
bn_wexpand
int bn_wexpand(BIGNUM *bn, size_t words)
Definition: bn.c:339
if
if(p->owned &&p->wrapped !=NULL)
Definition: call.c:42
bignum_st::dmax
int dmax
Definition: bn.h:977
OPENSSL_STATIC_ASSERT
#define OPENSSL_STATIC_ASSERT(cond, msg)
Definition: type_check.h:75
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
BN_num_bits
unsigned BN_num_bits(const BIGNUM *bn)
Definition: bn.c:216
ERR_R_MALLOC_FAILURE
#define ERR_R_MALLOC_FAILURE
Definition: err.h:371


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:49