Coverage Report

Created: 2026-02-09 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/mpi.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
3
 *
4
 * Author: Nikos Mavrogiannopoulos
5
 *
6
 * This file is part of GnuTLS.
7
 *
8
 * The GnuTLS is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public License
10
 * as published by the Free Software Foundation; either version 2.1 of
11
 * the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
20
 *
21
 */
22
23
/* Here lie everything that has to do with large numbers, libgcrypt and
24
 * other stuff that didn't fit anywhere else.
25
 */
26
27
#include "gnutls_int.h"
28
#include <libtasn1.h>
29
#include "errors.h"
30
#include "num.h"
31
#include "mpi.h"
32
#include "random.h"
33
#include "x509/x509_int.h"
34
35
/* Functions that refer to the mpi library.
36
 */
37
38
/* Returns a random number r, 0 < r < p */
39
bigint_t _gnutls_mpi_random_modp(bigint_t r, bigint_t p,
40
         gnutls_rnd_level_t level)
41
0
{
42
0
  size_t size;
43
0
  int ret;
44
0
  bigint_t tmp;
45
0
  uint8_t tmpbuf[512];
46
0
  uint8_t *buf;
47
0
  int buf_release = 0;
48
49
0
  size = ((_gnutls_mpi_get_nbits(p) + 64) / 8) + 1;
50
51
0
  if (size < sizeof(tmpbuf)) {
52
0
    buf = tmpbuf;
53
0
  } else {
54
0
    buf = gnutls_malloc(size);
55
0
    if (buf == NULL) {
56
0
      gnutls_assert();
57
0
      goto cleanup;
58
0
    }
59
0
    buf_release = 1;
60
0
  }
61
62
0
  ret = gnutls_rnd(level, buf, size);
63
0
  if (ret < 0) {
64
0
    gnutls_assert();
65
0
    goto cleanup;
66
0
  }
67
68
0
  ret = _gnutls_mpi_init_scan(&tmp, buf, size);
69
0
  if (ret < 0) {
70
0
    gnutls_assert();
71
0
    goto cleanup;
72
0
  }
73
74
0
  ret = _gnutls_mpi_modm(tmp, tmp, p);
75
0
  if (ret < 0) {
76
0
    gnutls_assert();
77
0
    goto cleanup;
78
0
  }
79
80
0
  if (_gnutls_mpi_cmp_ui(tmp, 0) == 0) {
81
0
    ret = _gnutls_mpi_add_ui(tmp, tmp, 1);
82
0
    if (ret < 0) {
83
0
      gnutls_assert();
84
0
      goto cleanup;
85
0
    }
86
0
  }
87
88
0
  if (buf_release != 0) {
89
0
    gnutls_free(buf);
90
0
  }
91
92
0
  if (r != NULL) {
93
0
    ret = _gnutls_mpi_set(r, tmp);
94
0
    if (ret < 0)
95
0
      goto cleanup;
96
97
0
    _gnutls_mpi_release(&tmp);
98
0
    return r;
99
0
  }
100
101
0
  return tmp;
102
103
0
cleanup:
104
0
  if (buf_release != 0)
105
0
    gnutls_free(buf);
106
0
  return NULL;
107
0
}
108
109
/* returns %GNUTLS_E_SUCCESS (0) on success
110
 */
111
int _gnutls_mpi_init_scan(bigint_t *ret_mpi, const void *buffer, size_t nbytes)
112
600k
{
113
600k
  bigint_t r;
114
600k
  int ret;
115
116
600k
  ret = _gnutls_mpi_init(&r);
117
600k
  if (ret < 0)
118
0
    return gnutls_assert_val(ret);
119
120
600k
  ret = _gnutls_mpi_scan(r, buffer, nbytes);
121
600k
  if (ret < 0) {
122
0
    gnutls_assert();
123
0
    _gnutls_mpi_release(&r);
124
0
    return ret;
125
0
  }
126
127
600k
  *ret_mpi = r;
128
129
600k
  return 0;
130
600k
}
131
132
/* returns %GNUTLS_E_SUCCESS (0) on success. Fails if the number is zero.
133
 */
134
int _gnutls_mpi_init_scan_nz(bigint_t *ret_mpi, const void *buffer,
135
           size_t nbytes)
136
49.7k
{
137
49.7k
  int ret;
138
139
49.7k
  ret = _gnutls_mpi_init_scan(ret_mpi, buffer, nbytes);
140
49.7k
  if (ret < 0)
141
0
    return ret;
142
143
  /* MPIs with 0 bits are illegal
144
   */
145
49.7k
  if (_gnutls_mpi_cmp_ui(*ret_mpi, 0) == 0) {
146
98
    _gnutls_mpi_release(ret_mpi);
147
98
    return GNUTLS_E_MPI_SCAN_FAILED;
148
98
  }
149
150
49.6k
  return 0;
151
49.7k
}
152
153
int _gnutls_mpi_init_scan_le(bigint_t *ret_mpi, const void *buffer,
154
           size_t nbytes)
155
2.35k
{
156
2.35k
  bigint_t r;
157
2.35k
  int ret;
158
159
2.35k
  ret = _gnutls_mpi_init(&r);
160
2.35k
  if (ret < 0)
161
0
    return gnutls_assert_val(ret);
162
163
2.35k
  ret = _gnutls_mpi_scan_le(r, buffer, nbytes);
164
2.35k
  if (ret < 0) {
165
0
    gnutls_assert();
166
0
    _gnutls_mpi_release(&r);
167
0
    return ret;
168
0
  }
169
170
2.35k
  *ret_mpi = r;
171
172
2.35k
  return 0;
173
2.35k
}
174
175
int _gnutls_mpi_dprint_le(const bigint_t a, gnutls_datum_t *dest)
176
282
{
177
282
  int ret;
178
282
  uint8_t *buf = NULL;
179
282
  size_t bytes = 0;
180
181
282
  if (dest == NULL || a == NULL)
182
0
    return GNUTLS_E_INVALID_REQUEST;
183
184
282
  _gnutls_mpi_print_le(a, NULL, &bytes);
185
282
  if (bytes != 0)
186
282
    buf = gnutls_malloc(bytes);
187
282
  if (buf == NULL)
188
0
    return GNUTLS_E_MEMORY_ERROR;
189
190
282
  ret = _gnutls_mpi_print_le(a, buf, &bytes);
191
282
  if (ret < 0) {
192
0
    gnutls_free(buf);
193
0
    return ret;
194
0
  }
195
196
282
  dest->data = buf;
197
282
  dest->size = bytes;
198
282
  return 0;
199
282
}
200
201
/* Always has the first bit zero */
202
int _gnutls_mpi_dprint_lz(const bigint_t a, gnutls_datum_t *dest)
203
18.1k
{
204
18.1k
  int ret;
205
18.1k
  uint8_t *buf = NULL;
206
18.1k
  size_t bytes = 0;
207
208
18.1k
  if (dest == NULL || a == NULL)
209
0
    return GNUTLS_E_INVALID_REQUEST;
210
211
18.1k
  _gnutls_mpi_print_lz(a, NULL, &bytes);
212
213
18.1k
  if (bytes != 0)
214
18.1k
    buf = gnutls_malloc(bytes);
215
18.1k
  if (buf == NULL)
216
0
    return GNUTLS_E_MEMORY_ERROR;
217
218
18.1k
  ret = _gnutls_mpi_print_lz(a, buf, &bytes);
219
18.1k
  if (ret < 0) {
220
0
    gnutls_free(buf);
221
0
    return ret;
222
0
  }
223
224
18.1k
  dest->data = buf;
225
18.1k
  dest->size = bytes;
226
18.1k
  return 0;
227
18.1k
}
228
229
int _gnutls_mpi_dprint(const bigint_t a, gnutls_datum_t *dest)
230
20.0k
{
231
20.0k
  int ret;
232
20.0k
  uint8_t *buf = NULL;
233
20.0k
  size_t bytes = 0;
234
235
20.0k
  if (dest == NULL || a == NULL)
236
0
    return GNUTLS_E_INVALID_REQUEST;
237
238
20.0k
  _gnutls_mpi_print(a, NULL, &bytes);
239
20.0k
  if (bytes != 0)
240
20.0k
    buf = gnutls_malloc(bytes);
241
20.0k
  if (buf == NULL)
242
0
    return GNUTLS_E_MEMORY_ERROR;
243
244
20.0k
  ret = _gnutls_mpi_print(a, buf, &bytes);
245
20.0k
  if (ret < 0) {
246
0
    gnutls_free(buf);
247
0
    return ret;
248
0
  }
249
250
20.0k
  dest->data = buf;
251
20.0k
  dest->size = bytes;
252
20.0k
  return 0;
253
20.0k
}
254
255
/* This function will copy the mpi data into a datum,
256
 * but will set minimum size to 'size'. That means that
257
 * the output value is left padded with zeros.
258
 */
259
int _gnutls_mpi_dprint_size(const bigint_t a, gnutls_datum_t *dest, size_t size)
260
23.2k
{
261
23.2k
  int ret;
262
23.2k
  uint8_t *buf = NULL;
263
23.2k
  size_t bytes = 0;
264
23.2k
  unsigned int i;
265
266
23.2k
  if (dest == NULL || a == NULL)
267
0
    return GNUTLS_E_INVALID_REQUEST;
268
269
23.2k
  _gnutls_mpi_print(a, NULL, &bytes);
270
23.2k
  if (bytes != 0)
271
23.2k
    buf = gnutls_malloc(MAX(size, bytes));
272
23.2k
  if (buf == NULL)
273
0
    return GNUTLS_E_MEMORY_ERROR;
274
275
23.2k
  if (bytes <= size) {
276
23.2k
    size_t diff = size - bytes;
277
23.3k
    for (i = 0; i < diff; i++)
278
85
      buf[i] = 0;
279
23.2k
    ret = _gnutls_mpi_print(a, &buf[diff], &bytes);
280
23.2k
  } else {
281
0
    ret = _gnutls_mpi_print(a, buf, &bytes);
282
0
  }
283
284
23.2k
  if (ret < 0) {
285
0
    gnutls_free(buf);
286
0
    return ret;
287
0
  }
288
289
23.2k
  dest->data = buf;
290
23.2k
  dest->size = MAX(size, bytes);
291
23.2k
  return 0;
292
23.2k
}
293
294
/* like _gnutls_mpi_dprint_size, but prints into preallocated byte buffer */
295
int _gnutls_mpi_bprint_size(const bigint_t a, uint8_t *buf, size_t size)
296
1.33k
{
297
1.33k
  int result;
298
1.33k
  size_t bytes = 0;
299
300
1.33k
  result = _gnutls_mpi_print(a, NULL, &bytes);
301
1.33k
  if (result != GNUTLS_E_SHORT_MEMORY_BUFFER)
302
0
    return gnutls_assert_val(result);
303
304
1.33k
  if (bytes <= size) {
305
1.33k
    unsigned i;
306
1.33k
    size_t diff = size - bytes;
307
308
2.84k
    for (i = 0; i < diff; i++)
309
1.50k
      buf[i] = 0;
310
1.33k
    result = _gnutls_mpi_print(a, &buf[diff], &bytes);
311
1.33k
  } else {
312
0
    result = _gnutls_mpi_print(a, buf, &bytes);
313
0
  }
314
315
1.33k
  return result;
316
1.33k
}
317
318
/* Flags for __gnutls_x509_read_int() and __gnutls_x509_write_int */
319
720k
#define GNUTLS_X509_INT_OVERWRITE (1 << 0)
320
450k
#define GNUTLS_X509_INT_LE (1 << 1)
321
139k
#define GNUTLS_X509_INT_LZ (1 << 2) /* write only */
322
323
/* this function reads an integer
324
 * from asn1 structs. Combines the read and mpi_scan
325
 * steps.
326
 */
327
static int __gnutls_x509_read_int(asn1_node node, const char *value,
328
          bigint_t *ret_mpi, unsigned int flags)
329
450k
{
330
450k
  int result;
331
450k
  uint8_t *tmpstr = NULL;
332
450k
  int tmpstr_size;
333
334
450k
  tmpstr_size = 0;
335
450k
  result = asn1_read_value(node, value, NULL, &tmpstr_size);
336
450k
  if (result != ASN1_MEM_ERROR) {
337
240
    gnutls_assert();
338
240
    return _gnutls_asn2err(result);
339
240
  }
340
341
449k
  tmpstr = gnutls_malloc(tmpstr_size);
342
449k
  if (tmpstr == NULL) {
343
0
    gnutls_assert();
344
0
    return GNUTLS_E_MEMORY_ERROR;
345
0
  }
346
347
449k
  result = asn1_read_value(node, value, tmpstr, &tmpstr_size);
348
449k
  if (result != ASN1_SUCCESS) {
349
0
    gnutls_assert();
350
0
    gnutls_free(tmpstr);
351
0
    return _gnutls_asn2err(result);
352
0
  }
353
354
449k
  if (flags & GNUTLS_X509_INT_LE)
355
188
    result = _gnutls_mpi_init_scan_le(ret_mpi, tmpstr, tmpstr_size);
356
449k
  else
357
449k
    result = _gnutls_mpi_init_scan(ret_mpi, tmpstr, tmpstr_size);
358
359
449k
  if (flags & GNUTLS_X509_INT_OVERWRITE)
360
219k
    zeroize_key(tmpstr, tmpstr_size);
361
449k
  gnutls_free(tmpstr);
362
363
449k
  if (result < 0) {
364
0
    gnutls_assert();
365
0
    return result;
366
0
  }
367
368
449k
  return 0;
369
449k
}
370
371
int _gnutls_x509_read_int(asn1_node node, const char *value, bigint_t *ret_mpi)
372
230k
{
373
230k
  return __gnutls_x509_read_int(node, value, ret_mpi, 0);
374
230k
}
375
376
int _gnutls_x509_read_key_int(asn1_node node, const char *value,
377
            bigint_t *ret_mpi)
378
219k
{
379
219k
  return __gnutls_x509_read_int(node, value, ret_mpi,
380
219k
              GNUTLS_X509_INT_OVERWRITE);
381
219k
}
382
383
int _gnutls_x509_read_key_int_le(asn1_node node, const char *value,
384
         bigint_t *ret_mpi)
385
188
{
386
188
  return __gnutls_x509_read_int(node, value, ret_mpi,
387
188
              GNUTLS_X509_INT_OVERWRITE |
388
188
                GNUTLS_X509_INT_LE);
389
188
}
390
391
/* Writes the specified integer into the specified node.
392
 */
393
static int __gnutls_x509_write_int(asn1_node node, const char *value,
394
           bigint_t mpi, unsigned int flags)
395
46.5k
{
396
46.5k
  uint8_t *tmpstr;
397
46.5k
  size_t s_len;
398
46.5k
  int result;
399
400
46.5k
  s_len = 0;
401
46.5k
  if (flags & GNUTLS_X509_INT_LZ)
402
46.5k
    result = _gnutls_mpi_print_lz(mpi, NULL, &s_len);
403
0
  else if (flags & GNUTLS_X509_INT_LE)
404
0
    result = _gnutls_mpi_print_le(mpi, NULL, &s_len);
405
0
  else
406
0
    result = _gnutls_mpi_print(mpi, NULL, &s_len);
407
408
46.5k
  if (result != GNUTLS_E_SHORT_MEMORY_BUFFER) {
409
0
    gnutls_assert();
410
0
    return result;
411
0
  }
412
413
46.5k
  tmpstr = gnutls_malloc(s_len);
414
46.5k
  if (tmpstr == NULL) {
415
0
    gnutls_assert();
416
0
    return GNUTLS_E_MEMORY_ERROR;
417
0
  }
418
419
46.5k
  if (flags & GNUTLS_X509_INT_LZ)
420
46.5k
    result = _gnutls_mpi_print_lz(mpi, tmpstr, &s_len);
421
0
  else if (flags & GNUTLS_X509_INT_LE)
422
0
    result = _gnutls_mpi_print_le(mpi, tmpstr, &s_len);
423
0
  else
424
0
    result = _gnutls_mpi_print(mpi, tmpstr, &s_len);
425
426
46.5k
  if (result != 0) {
427
0
    gnutls_assert();
428
0
    gnutls_free(tmpstr);
429
0
    return GNUTLS_E_MPI_PRINT_FAILED;
430
0
  }
431
432
46.5k
  result = asn1_write_value(node, value, tmpstr, s_len);
433
434
46.5k
  if (flags & GNUTLS_X509_INT_OVERWRITE)
435
4.10k
    zeroize_key(tmpstr, s_len);
436
437
46.5k
  gnutls_free(tmpstr);
438
439
46.5k
  if (result != ASN1_SUCCESS) {
440
0
    gnutls_assert();
441
0
    return _gnutls_asn2err(result);
442
0
  }
443
444
46.5k
  return 0;
445
46.5k
}
446
447
int _gnutls_x509_write_int(asn1_node node, const char *value, bigint_t mpi,
448
         int lz)
449
42.4k
{
450
42.4k
  return __gnutls_x509_write_int(node, value, mpi,
451
42.4k
               lz ? GNUTLS_X509_INT_LZ : 0);
452
42.4k
}
453
454
int _gnutls_x509_write_key_int(asn1_node node, const char *value, bigint_t mpi,
455
             int lz)
456
4.10k
{
457
4.10k
  return __gnutls_x509_write_int(node, value, mpi,
458
4.10k
               (lz ? GNUTLS_X509_INT_LZ : 0) |
459
4.10k
                 GNUTLS_X509_INT_OVERWRITE);
460
4.10k
}
461
462
int _gnutls_x509_write_key_int_le(asn1_node node, const char *value,
463
          bigint_t mpi)
464
0
{
465
0
  return __gnutls_x509_write_int(node, value, mpi,
466
0
               GNUTLS_X509_INT_OVERWRITE |
467
0
                 GNUTLS_X509_INT_LE);
468
0
}