Coverage Report

Created: 2025-03-18 06:55

/src/gnutls/lib/mpi.c
Line
Count
Source (jump to first uncovered line)
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
0
{
113
0
  bigint_t r;
114
0
  int ret;
115
116
0
  ret = _gnutls_mpi_init(&r);
117
0
  if (ret < 0)
118
0
    return gnutls_assert_val(ret);
119
120
0
  ret = _gnutls_mpi_scan(r, buffer, nbytes);
121
0
  if (ret < 0) {
122
0
    gnutls_assert();
123
0
    _gnutls_mpi_release(&r);
124
0
    return ret;
125
0
  }
126
127
0
  *ret_mpi = r;
128
129
0
  return 0;
130
0
}
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
0
{
137
0
  int ret;
138
139
0
  ret = _gnutls_mpi_init_scan(ret_mpi, buffer, nbytes);
140
0
  if (ret < 0)
141
0
    return ret;
142
143
  /* MPIs with 0 bits are illegal
144
   */
145
0
  if (_gnutls_mpi_cmp_ui(*ret_mpi, 0) == 0) {
146
0
    _gnutls_mpi_release(ret_mpi);
147
0
    return GNUTLS_E_MPI_SCAN_FAILED;
148
0
  }
149
150
0
  return 0;
151
0
}
152
153
int _gnutls_mpi_init_scan_le(bigint_t *ret_mpi, const void *buffer,
154
           size_t nbytes)
155
0
{
156
0
  bigint_t r;
157
0
  int ret;
158
159
0
  ret = _gnutls_mpi_init(&r);
160
0
  if (ret < 0)
161
0
    return gnutls_assert_val(ret);
162
163
0
  ret = _gnutls_mpi_scan_le(r, buffer, nbytes);
164
0
  if (ret < 0) {
165
0
    gnutls_assert();
166
0
    _gnutls_mpi_release(&r);
167
0
    return ret;
168
0
  }
169
170
0
  *ret_mpi = r;
171
172
0
  return 0;
173
0
}
174
175
int _gnutls_mpi_dprint_le(const bigint_t a, gnutls_datum_t *dest)
176
0
{
177
0
  int ret;
178
0
  uint8_t *buf = NULL;
179
0
  size_t bytes = 0;
180
181
0
  if (dest == NULL || a == NULL)
182
0
    return GNUTLS_E_INVALID_REQUEST;
183
184
0
  _gnutls_mpi_print_le(a, NULL, &bytes);
185
0
  if (bytes != 0)
186
0
    buf = gnutls_malloc(bytes);
187
0
  if (buf == NULL)
188
0
    return GNUTLS_E_MEMORY_ERROR;
189
190
0
  ret = _gnutls_mpi_print_le(a, buf, &bytes);
191
0
  if (ret < 0) {
192
0
    gnutls_free(buf);
193
0
    return ret;
194
0
  }
195
196
0
  dest->data = buf;
197
0
  dest->size = bytes;
198
0
  return 0;
199
0
}
200
201
/* Always has the first bit zero */
202
int _gnutls_mpi_dprint_lz(const bigint_t a, gnutls_datum_t *dest)
203
0
{
204
0
  int ret;
205
0
  uint8_t *buf = NULL;
206
0
  size_t bytes = 0;
207
208
0
  if (dest == NULL || a == NULL)
209
0
    return GNUTLS_E_INVALID_REQUEST;
210
211
0
  _gnutls_mpi_print_lz(a, NULL, &bytes);
212
213
0
  if (bytes != 0)
214
0
    buf = gnutls_malloc(bytes);
215
0
  if (buf == NULL)
216
0
    return GNUTLS_E_MEMORY_ERROR;
217
218
0
  ret = _gnutls_mpi_print_lz(a, buf, &bytes);
219
0
  if (ret < 0) {
220
0
    gnutls_free(buf);
221
0
    return ret;
222
0
  }
223
224
0
  dest->data = buf;
225
0
  dest->size = bytes;
226
0
  return 0;
227
0
}
228
229
int _gnutls_mpi_dprint(const bigint_t a, gnutls_datum_t *dest)
230
0
{
231
0
  int ret;
232
0
  uint8_t *buf = NULL;
233
0
  size_t bytes = 0;
234
235
0
  if (dest == NULL || a == NULL)
236
0
    return GNUTLS_E_INVALID_REQUEST;
237
238
0
  _gnutls_mpi_print(a, NULL, &bytes);
239
0
  if (bytes != 0)
240
0
    buf = gnutls_malloc(bytes);
241
0
  if (buf == NULL)
242
0
    return GNUTLS_E_MEMORY_ERROR;
243
244
0
  ret = _gnutls_mpi_print(a, buf, &bytes);
245
0
  if (ret < 0) {
246
0
    gnutls_free(buf);
247
0
    return ret;
248
0
  }
249
250
0
  dest->data = buf;
251
0
  dest->size = bytes;
252
0
  return 0;
253
0
}
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
0
{
261
0
  int ret;
262
0
  uint8_t *buf = NULL;
263
0
  size_t bytes = 0;
264
0
  unsigned int i;
265
266
0
  if (dest == NULL || a == NULL)
267
0
    return GNUTLS_E_INVALID_REQUEST;
268
269
0
  _gnutls_mpi_print(a, NULL, &bytes);
270
0
  if (bytes != 0)
271
0
    buf = gnutls_malloc(MAX(size, bytes));
272
0
  if (buf == NULL)
273
0
    return GNUTLS_E_MEMORY_ERROR;
274
275
0
  if (bytes <= size) {
276
0
    size_t diff = size - bytes;
277
0
    for (i = 0; i < diff; i++)
278
0
      buf[i] = 0;
279
0
    ret = _gnutls_mpi_print(a, &buf[diff], &bytes);
280
0
  } else {
281
0
    ret = _gnutls_mpi_print(a, buf, &bytes);
282
0
  }
283
284
0
  if (ret < 0) {
285
0
    gnutls_free(buf);
286
0
    return ret;
287
0
  }
288
289
0
  dest->data = buf;
290
0
  dest->size = MAX(size, bytes);
291
0
  return 0;
292
0
}
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
0
{
297
0
  int result;
298
0
  size_t bytes = 0;
299
300
0
  result = _gnutls_mpi_print(a, NULL, &bytes);
301
0
  if (result != GNUTLS_E_SHORT_MEMORY_BUFFER)
302
0
    return gnutls_assert_val(result);
303
304
0
  if (bytes <= size) {
305
0
    unsigned i;
306
0
    size_t diff = size - bytes;
307
308
0
    for (i = 0; i < diff; i++)
309
0
      buf[i] = 0;
310
0
    result = _gnutls_mpi_print(a, &buf[diff], &bytes);
311
0
  } else {
312
0
    result = _gnutls_mpi_print(a, buf, &bytes);
313
0
  }
314
315
0
  return result;
316
0
}
317
318
/* Flags for __gnutls_x509_read_int() and __gnutls_x509_write_int */
319
0
#define GNUTLS_X509_INT_OVERWRITE (1 << 0)
320
0
#define GNUTLS_X509_INT_LE (1 << 1)
321
0
#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
0
{
330
0
  int result;
331
0
  uint8_t *tmpstr = NULL;
332
0
  int tmpstr_size;
333
334
0
  tmpstr_size = 0;
335
0
  result = asn1_read_value(node, value, NULL, &tmpstr_size);
336
0
  if (result != ASN1_MEM_ERROR) {
337
0
    gnutls_assert();
338
0
    return _gnutls_asn2err(result);
339
0
  }
340
341
0
  tmpstr = gnutls_malloc(tmpstr_size);
342
0
  if (tmpstr == NULL) {
343
0
    gnutls_assert();
344
0
    return GNUTLS_E_MEMORY_ERROR;
345
0
  }
346
347
0
  result = asn1_read_value(node, value, tmpstr, &tmpstr_size);
348
0
  if (result != ASN1_SUCCESS) {
349
0
    gnutls_assert();
350
0
    gnutls_free(tmpstr);
351
0
    return _gnutls_asn2err(result);
352
0
  }
353
354
0
  if (flags & GNUTLS_X509_INT_LE)
355
0
    result = _gnutls_mpi_init_scan_le(ret_mpi, tmpstr, tmpstr_size);
356
0
  else
357
0
    result = _gnutls_mpi_init_scan(ret_mpi, tmpstr, tmpstr_size);
358
359
0
  if (flags & GNUTLS_X509_INT_OVERWRITE)
360
0
    zeroize_key(tmpstr, tmpstr_size);
361
0
  gnutls_free(tmpstr);
362
363
0
  if (result < 0) {
364
0
    gnutls_assert();
365
0
    return result;
366
0
  }
367
368
0
  return 0;
369
0
}
370
371
int _gnutls_x509_read_int(asn1_node node, const char *value, bigint_t *ret_mpi)
372
0
{
373
0
  return __gnutls_x509_read_int(node, value, ret_mpi, 0);
374
0
}
375
376
int _gnutls_x509_read_key_int(asn1_node node, const char *value,
377
            bigint_t *ret_mpi)
378
0
{
379
0
  return __gnutls_x509_read_int(node, value, ret_mpi,
380
0
              GNUTLS_X509_INT_OVERWRITE);
381
0
}
382
383
int _gnutls_x509_read_key_int_le(asn1_node node, const char *value,
384
         bigint_t *ret_mpi)
385
0
{
386
0
  return __gnutls_x509_read_int(node, value, ret_mpi,
387
0
              GNUTLS_X509_INT_OVERWRITE |
388
0
                GNUTLS_X509_INT_LE);
389
0
}
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
0
{
396
0
  uint8_t *tmpstr;
397
0
  size_t s_len;
398
0
  int result;
399
400
0
  s_len = 0;
401
0
  if (flags & GNUTLS_X509_INT_LZ)
402
0
    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
0
  if (result != GNUTLS_E_SHORT_MEMORY_BUFFER) {
409
0
    gnutls_assert();
410
0
    return result;
411
0
  }
412
413
0
  tmpstr = gnutls_malloc(s_len);
414
0
  if (tmpstr == NULL) {
415
0
    gnutls_assert();
416
0
    return GNUTLS_E_MEMORY_ERROR;
417
0
  }
418
419
0
  if (flags & GNUTLS_X509_INT_LZ)
420
0
    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
0
  if (result != 0) {
427
0
    gnutls_assert();
428
0
    gnutls_free(tmpstr);
429
0
    return GNUTLS_E_MPI_PRINT_FAILED;
430
0
  }
431
432
0
  result = asn1_write_value(node, value, tmpstr, s_len);
433
434
0
  if (flags & GNUTLS_X509_INT_OVERWRITE)
435
0
    zeroize_key(tmpstr, s_len);
436
437
0
  gnutls_free(tmpstr);
438
439
0
  if (result != ASN1_SUCCESS) {
440
0
    gnutls_assert();
441
0
    return _gnutls_asn2err(result);
442
0
  }
443
444
0
  return 0;
445
0
}
446
447
int _gnutls_x509_write_int(asn1_node node, const char *value, bigint_t mpi,
448
         int lz)
449
0
{
450
0
  return __gnutls_x509_write_int(node, value, mpi,
451
0
               lz ? GNUTLS_X509_INT_LZ : 0);
452
0
}
453
454
int _gnutls_x509_write_key_int(asn1_node node, const char *value, bigint_t mpi,
455
             int lz)
456
0
{
457
0
  return __gnutls_x509_write_int(node, value, mpi,
458
0
               (lz ? GNUTLS_X509_INT_LZ : 0) |
459
0
                 GNUTLS_X509_INT_OVERWRITE);
460
0
}
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
}