Coverage Report

Created: 2025-06-24 07:00

/src/boringssl/crypto/bn/convert.cc
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 <ctype.h>
19
#include <limits.h>
20
#include <stdio.h>
21
22
#include <algorithm>
23
24
#include <openssl/bio.h>
25
#include <openssl/bytestring.h>
26
#include <openssl/err.h>
27
#include <openssl/mem.h>
28
29
#include "../fipsmodule/bn/internal.h"
30
31
32
22.7k
int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
33
22.7k
  uint8_t *ptr;
34
22.7k
  return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in);
35
22.7k
}
36
37
static const char hextable[] = "0123456789abcdef";
38
39
933
char *BN_bn2hex(const BIGNUM *bn) {
40
933
  int width = bn_minimal_width(bn);
41
933
  char *buf = reinterpret_cast<char *>(
42
933
      OPENSSL_malloc(1 /* leading '-' */ + 1 /* zero is non-empty */ +
43
933
                     width * BN_BYTES * 2 + 1 /* trailing NUL */));
44
933
  if (buf == NULL) {
45
0
    return NULL;
46
0
  }
47
48
933
  char *p = buf;
49
933
  if (bn->neg) {
50
531
    *(p++) = '-';
51
531
  }
52
53
933
  if (BN_is_zero(bn)) {
54
0
    *(p++) = '0';
55
0
  }
56
57
933
  int z = 0;
58
7.17k
  for (int i = width - 1; i >= 0; i--) {
59
56.1k
    for (int j = BN_BITS2 - 8; j >= 0; j -= 8) {
60
      // strip leading zeros
61
49.9k
      int v = ((int)(bn->d[i] >> (long)j)) & 0xff;
62
49.9k
      if (z || v != 0) {
63
46.9k
        *(p++) = hextable[v >> 4];
64
46.9k
        *(p++) = hextable[v & 0x0f];
65
46.9k
        z = 1;
66
46.9k
      }
67
49.9k
    }
68
6.24k
  }
69
933
  *p = '\0';
70
71
933
  return buf;
72
933
}
73
74
// decode_hex decodes |in_len| bytes of hex data from |in| and updates |bn|.
75
2.36k
static int decode_hex(BIGNUM *bn, const char *in, int in_len) {
76
2.36k
  if (in_len > INT_MAX / 4) {
77
0
    OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
78
0
    return 0;
79
0
  }
80
  // |in_len| is the number of hex digits.
81
2.36k
  if (!bn_expand(bn, in_len * 4)) {
82
0
    return 0;
83
0
  }
84
85
2.36k
  int i = 0;
86
10.9k
  while (in_len > 0) {
87
    // Decode one |BN_ULONG| at a time.
88
8.58k
    int todo = BN_BYTES * 2;
89
8.58k
    if (todo > in_len) {
90
1.71k
      todo = in_len;
91
1.71k
    }
92
93
8.58k
    BN_ULONG word = 0;
94
8.58k
    int j;
95
124k
    for (j = todo; j > 0; j--) {
96
116k
      uint8_t hex = 0;
97
116k
      if (!OPENSSL_fromxdigit(&hex, in[in_len - j])) {
98
        // This shouldn't happen. The caller checks |OPENSSL_isxdigit|.
99
0
        assert(0);
100
0
      }
101
116k
      word = (word << 4) | hex;
102
116k
    }
103
104
8.58k
    bn->d[i++] = word;
105
8.58k
    in_len -= todo;
106
8.58k
  }
107
2.36k
  assert(i <= bn->dmax);
108
2.36k
  bn->width = i;
109
2.36k
  return 1;
110
2.36k
}
111
112
// decode_dec decodes |in_len| bytes of decimal data from |in| and updates |bn|.
113
11.3k
static int decode_dec(BIGNUM *bn, const char *in, int in_len) {
114
11.3k
  int i, j;
115
11.3k
  BN_ULONG l = 0;
116
117
  // Decode |BN_DEC_NUM| digits at a time.
118
11.3k
  j = BN_DEC_NUM - (in_len % BN_DEC_NUM);
119
11.3k
  if (j == BN_DEC_NUM) {
120
750
    j = 0;
121
750
  }
122
11.3k
  l = 0;
123
184k
  for (i = 0; i < in_len; i++) {
124
173k
    l *= 10;
125
173k
    l += in[i] - '0';
126
173k
    if (++j == BN_DEC_NUM) {
127
18.6k
      if (!BN_mul_word(bn, BN_DEC_CONV) || !BN_add_word(bn, l)) {
128
0
        return 0;
129
0
      }
130
18.6k
      l = 0;
131
18.6k
      j = 0;
132
18.6k
    }
133
173k
  }
134
11.3k
  return 1;
135
11.3k
}
136
137
typedef int (*decode_func)(BIGNUM *bn, const char *in, int in_len);
138
typedef int (*char_test_func)(int c);
139
140
static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode,
141
13.7k
                   char_test_func want_char) {
142
13.7k
  BIGNUM *ret = NULL;
143
13.7k
  int neg = 0, i;
144
13.7k
  int num;
145
146
13.7k
  if (in == NULL || *in == 0) {
147
29
    return 0;
148
29
  }
149
150
13.6k
  if (*in == '-') {
151
1.41k
    neg = 1;
152
1.41k
    in++;
153
1.41k
  }
154
155
303k
  for (i = 0; want_char((unsigned char)in[i]) && i + neg < INT_MAX; i++) {
156
289k
  }
157
158
13.6k
  num = i + neg;
159
13.6k
  if (outp == NULL) {
160
0
    return num;
161
0
  }
162
163
  // in is the start of the hex digits, and it is 'i' long
164
13.6k
  if (*outp == NULL) {
165
0
    ret = BN_new();
166
0
    if (ret == NULL) {
167
0
      return 0;
168
0
    }
169
13.6k
  } else {
170
13.6k
    ret = *outp;
171
13.6k
    BN_zero(ret);
172
13.6k
  }
173
174
13.6k
  if (!decode(ret, in, i)) {
175
0
    goto err;
176
0
  }
177
178
13.6k
  bn_set_minimal_width(ret);
179
13.6k
  if (!BN_is_zero(ret)) {
180
9.59k
    ret->neg = neg;
181
9.59k
  }
182
183
13.6k
  *outp = ret;
184
13.6k
  return num;
185
186
0
err:
187
0
  if (*outp == NULL) {
188
0
    BN_free(ret);
189
0
  }
190
191
0
  return 0;
192
13.6k
}
193
194
2.38k
int BN_hex2bn(BIGNUM **outp, const char *in) {
195
2.38k
  return bn_x2bn(outp, in, decode_hex, OPENSSL_isxdigit);
196
2.38k
}
197
198
1.24k
char *BN_bn2dec(const BIGNUM *a) {
199
  // It is easier to print strings little-endian, so we assemble it in reverse
200
  // and fix at the end.
201
1.24k
  bssl::ScopedCBB cbb;
202
1.24k
  if (!CBB_init(cbb.get(), 16) || //
203
1.24k
      !CBB_add_u8(cbb.get(), 0 /* trailing NUL */)) {
204
0
    return nullptr;
205
0
  }
206
207
1.24k
  if (BN_is_zero(a)) {
208
33
    if (!CBB_add_u8(cbb.get(), '0')) {
209
0
      return nullptr;
210
0
    }
211
1.20k
  } else {
212
1.20k
    bssl::UniquePtr<BIGNUM> copy(BN_dup(a));
213
1.20k
    if (copy == nullptr) {
214
0
      return nullptr;
215
0
    }
216
217
2.41k
    while (!BN_is_zero(copy.get())) {
218
1.20k
      BN_ULONG word = BN_div_word(copy.get(), BN_DEC_CONV);
219
1.20k
      if (word == (BN_ULONG)-1) {
220
0
        return nullptr;
221
0
      }
222
223
1.20k
      const int add_leading_zeros = !BN_is_zero(copy.get());
224
6.18k
      for (int i = 0; i < BN_DEC_NUM && (add_leading_zeros || word != 0); i++) {
225
4.97k
        if (!CBB_add_u8(cbb.get(), '0' + word % 10)) {
226
0
          return nullptr;
227
0
        }
228
4.97k
        word /= 10;
229
4.97k
      }
230
1.20k
      assert(word == 0);
231
1.20k
    }
232
1.20k
  }
233
234
1.24k
  if (BN_is_negative(a) && //
235
1.24k
      !CBB_add_u8(cbb.get(), '-')) {
236
0
    return nullptr;
237
0
  }
238
239
1.24k
  uint8_t *data;
240
1.24k
  size_t len;
241
1.24k
  if (!CBB_finish(cbb.get(), &data, &len)) {
242
0
    return nullptr;
243
0
  }
244
245
1.24k
  std::reverse(data, data + len);
246
1.24k
  return reinterpret_cast<char *>(data);
247
1.24k
}
248
249
11.3k
int BN_dec2bn(BIGNUM **outp, const char *in) {
250
11.3k
  return bn_x2bn(outp, in, decode_dec, OPENSSL_isdigit);
251
11.3k
}
252
253
0
int BN_asc2bn(BIGNUM **outp, const char *in) {
254
0
  const char *const orig_in = in;
255
0
  if (*in == '-') {
256
0
    in++;
257
0
  }
258
259
0
  if (in[0] == '0' && (in[1] == 'X' || in[1] == 'x')) {
260
0
    if (!BN_hex2bn(outp, in + 2)) {
261
0
      return 0;
262
0
    }
263
0
  } else {
264
0
    if (!BN_dec2bn(outp, in)) {
265
0
      return 0;
266
0
    }
267
0
  }
268
269
0
  if (*orig_in == '-' && !BN_is_zero(*outp)) {
270
0
    (*outp)->neg = 1;
271
0
  }
272
273
0
  return 1;
274
0
}
275
276
0
int BN_print(BIO *bp, const BIGNUM *a) {
277
0
  if (a->neg && BIO_write(bp, "-", 1) != 1) {
278
0
    return 0;
279
0
  }
280
281
0
  if (BN_is_zero(a) && BIO_write(bp, "0", 1) != 1) {
282
0
    return 0;
283
0
  }
284
285
0
  int z = 0;
286
0
  for (int i = bn_minimal_width(a) - 1; i >= 0; i--) {
287
0
    for (int j = BN_BITS2 - 4; j >= 0; j -= 4) {
288
      // strip leading zeros
289
0
      int v = ((int)(a->d[i] >> (long)j)) & 0x0f;
290
0
      if (z || v != 0) {
291
0
        if (BIO_write(bp, &hextable[v], 1) != 1) {
292
0
          return 0;
293
0
        }
294
0
        z = 1;
295
0
      }
296
0
    }
297
0
  }
298
0
  return 1;
299
0
}
300
301
0
int BN_print_fp(FILE *fp, const BIGNUM *a) {
302
0
  BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
303
0
  if (b == NULL) {
304
0
    return 0;
305
0
  }
306
307
0
  int ret = BN_print(b, a);
308
0
  BIO_free(b);
309
0
  return ret;
310
0
}
311
312
313
0
size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) {
314
0
  const size_t bits = BN_num_bits(in);
315
0
  const size_t bytes = (bits + 7) / 8;
316
  // If the number of bits is a multiple of 8, i.e. if the MSB is set,
317
  // prefix with a zero byte.
318
0
  int extend = 0;
319
0
  if (bytes != 0 && (bits & 0x07) == 0) {
320
0
    extend = 1;
321
0
  }
322
323
0
  const size_t len = bytes + extend;
324
0
  if (len < bytes || 4 + len < len || (len & 0xffffffff) != len) {
325
    // If we cannot represent the number then we emit zero as the interface
326
    // doesn't allow an error to be signalled.
327
0
    if (out) {
328
0
      OPENSSL_memset(out, 0, 4);
329
0
    }
330
0
    return 4;
331
0
  }
332
333
0
  if (out == NULL) {
334
0
    return 4 + len;
335
0
  }
336
337
0
  out[0] = len >> 24;
338
0
  out[1] = len >> 16;
339
0
  out[2] = len >> 8;
340
0
  out[3] = len;
341
0
  if (extend) {
342
0
    out[4] = 0;
343
0
  }
344
0
  BN_bn2bin(in, out + 4 + extend);
345
0
  if (in->neg && len > 0) {
346
0
    out[4] |= 0x80;
347
0
  }
348
0
  return len + 4;
349
0
}
350
351
0
BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) {
352
0
  if (len < 4) {
353
0
    OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
354
0
    return NULL;
355
0
  }
356
0
  const size_t in_len = ((size_t)in[0] << 24) | //
357
0
                        ((size_t)in[1] << 16) | //
358
0
                        ((size_t)in[2] << 8) | //
359
0
                        ((size_t)in[3]);
360
0
  if (in_len != len - 4) {
361
0
    OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
362
0
    return NULL;
363
0
  }
364
365
0
  int out_is_alloced = 0;
366
0
  if (out == NULL) {
367
0
    out = BN_new();
368
0
    if (out == NULL) {
369
0
      return NULL;
370
0
    }
371
0
    out_is_alloced = 1;
372
0
  }
373
374
0
  if (in_len == 0) {
375
0
    BN_zero(out);
376
0
    return out;
377
0
  }
378
379
0
  in += 4;
380
0
  if (BN_bin2bn(in, in_len, out) == NULL) {
381
0
    if (out_is_alloced) {
382
0
      BN_free(out);
383
0
    }
384
0
    return NULL;
385
0
  }
386
0
  out->neg = ((*in) & 0x80) != 0;
387
0
  if (out->neg) {
388
0
    BN_clear_bit(out, BN_num_bits(out) - 1);
389
0
  }
390
0
  return out;
391
0
}
392
393
0
int BN_bn2binpad(const BIGNUM *in, uint8_t *out, int len) {
394
0
  if (len < 0 || //
395
0
      !BN_bn2bin_padded(out, (size_t)len, in)) {
396
0
    return -1;
397
0
  }
398
0
  return len;
399
0
}
400
401
0
int BN_bn2lebinpad(const BIGNUM *in, uint8_t *out, int len) {
402
0
  if (len < 0 || //
403
0
      !BN_bn2le_padded(out, (size_t)len, in)) {
404
0
    return -1;
405
0
  }
406
0
  return len;
407
0
}