Coverage Report

Created: 2025-09-05 06:13

/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
}