Coverage Report

Created: 2025-03-06 06:58

/src/gnutls/lib/nettle/mpi.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
3
 *
4
 * Author: Nikos Mavrogiannopoulos
5
 *
6
 * This file is part of GNUTLS.
7
 *
8
 * The GNUTLS library 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, gmp.
24
 */
25
26
#include "gnutls_int.h"
27
#include "errors.h"
28
#include "algorithms.h"
29
#include "num.h"
30
#include "mpi.h"
31
#include <nettle/bignum.h> /* includes gmp.h */
32
#if ENABLE_GOST
33
#include "gost/bignum-le.h"
34
#endif
35
#include "gnettle.h"
36
#include "random.h"
37
38
static int wrap_nettle_mpi_print(const bigint_t a, void *buffer, size_t *nbytes,
39
         gnutls_bigint_format_t format)
40
0
{
41
0
  unsigned int size;
42
0
  mpz_t *p = (void *)a;
43
44
0
  if (format == GNUTLS_MPI_FORMAT_USG) {
45
0
    size = nettle_mpz_sizeinbase_256_u(*p);
46
0
  } else if (format == GNUTLS_MPI_FORMAT_STD) {
47
0
    size = nettle_mpz_sizeinbase_256_s(*p);
48
0
#if ENABLE_GOST
49
0
  } else if (format == GNUTLS_MPI_FORMAT_ULE) {
50
0
    size = nettle_mpz_sizeinbase_256_u_le(*p);
51
0
#endif
52
0
  } else {
53
0
    gnutls_assert();
54
0
    return GNUTLS_E_INVALID_REQUEST;
55
0
  }
56
57
0
  if (buffer == NULL || size > *nbytes) {
58
0
    *nbytes = size;
59
0
    gnutls_assert();
60
0
    return GNUTLS_E_SHORT_MEMORY_BUFFER;
61
0
  }
62
63
0
#if ENABLE_GOST
64
0
  if (format == GNUTLS_MPI_FORMAT_ULE)
65
0
    nettle_mpz_get_str_256_u_le(size, buffer, *p);
66
0
  else
67
0
#endif
68
0
    nettle_mpz_get_str_256(size, buffer, *p);
69
0
  *nbytes = size;
70
71
0
  return 0;
72
0
}
73
74
static int wrap_nettle_mpi_init(bigint_t *w)
75
0
{
76
0
  bigint_t r;
77
78
0
  r = gnutls_malloc(SIZEOF_MPZT);
79
0
  if (r == NULL) {
80
0
    gnutls_assert();
81
0
    return GNUTLS_E_MEMORY_ERROR;
82
0
  }
83
84
0
  mpz_init(TOMPZ(r));
85
0
  *w = r;
86
87
0
  return 0;
88
0
}
89
90
static int wrap_nettle_mpi_init_multi(bigint_t *w, ...)
91
0
{
92
0
  va_list args;
93
0
  bigint_t *next;
94
0
  int ret;
95
0
  bigint_t *last_failed = NULL;
96
97
0
  ret = wrap_nettle_mpi_init(w);
98
0
  if (ret < 0) {
99
0
    gnutls_assert();
100
0
    return ret;
101
0
  }
102
103
0
  va_start(args, w);
104
105
0
  do {
106
0
    next = va_arg(args, bigint_t *);
107
0
    if (next != NULL) {
108
0
      ret = wrap_nettle_mpi_init(next);
109
0
      if (ret < 0) {
110
0
        gnutls_assert();
111
0
        va_end(args);
112
0
        last_failed = next;
113
0
        goto fail;
114
0
      }
115
0
    }
116
0
  } while (next != 0);
117
118
0
  va_end(args);
119
120
0
  return 0;
121
0
fail:
122
0
  mpz_clear(TOMPZ(*w));
123
0
  gnutls_free(*w);
124
125
0
  va_start(args, w);
126
127
0
  do {
128
0
    next = va_arg(args, bigint_t *);
129
0
    if (next != last_failed) {
130
0
      mpz_clear(TOMPZ(*next));
131
0
      gnutls_free(*next);
132
0
    }
133
0
  } while (next != last_failed);
134
135
0
  va_end(args);
136
137
0
  return GNUTLS_E_MEMORY_ERROR;
138
0
}
139
140
static int wrap_nettle_mpi_scan(bigint_t r, const void *buffer, size_t nbytes,
141
        gnutls_bigint_format_t format)
142
0
{
143
0
  if (format == GNUTLS_MPI_FORMAT_USG) {
144
0
    nettle_mpz_set_str_256_u(TOMPZ(r), nbytes, buffer);
145
0
  } else if (format == GNUTLS_MPI_FORMAT_STD) {
146
0
    nettle_mpz_set_str_256_s(TOMPZ(r), nbytes, buffer);
147
0
#if ENABLE_GOST
148
0
  } else if (format == GNUTLS_MPI_FORMAT_ULE) {
149
0
    nettle_mpz_set_str_256_u_le(TOMPZ(r), nbytes, buffer);
150
0
#endif
151
0
  } else {
152
0
    gnutls_assert();
153
0
    goto fail;
154
0
  }
155
156
0
  return 0;
157
0
fail:
158
0
  return GNUTLS_E_MPI_SCAN_FAILED;
159
0
}
160
161
static int wrap_nettle_mpi_cmp(const bigint_t u, const bigint_t v)
162
0
{
163
0
  mpz_t *i1 = u, *i2 = v;
164
165
0
  return mpz_cmp(*i1, *i2);
166
0
}
167
168
static int wrap_nettle_mpi_cmp_ui(const bigint_t u, unsigned long v)
169
0
{
170
0
  mpz_t *i1 = u;
171
172
0
  return mpz_cmp_ui(*i1, v);
173
0
}
174
175
static int wrap_nettle_mpi_set(bigint_t w, const bigint_t u)
176
0
{
177
0
  mpz_set(TOMPZ(w), TOMPZ(u));
178
179
0
  return 0;
180
0
}
181
182
static bigint_t wrap_nettle_mpi_copy(const bigint_t u)
183
0
{
184
0
  int ret;
185
0
  bigint_t w;
186
187
0
  ret = wrap_nettle_mpi_init(&w);
188
0
  if (ret < 0)
189
0
    return NULL;
190
191
0
  mpz_set(TOMPZ(w), u);
192
193
0
  return w;
194
0
}
195
196
static int wrap_nettle_mpi_set_ui(bigint_t w, unsigned long u)
197
0
{
198
0
  mpz_set_ui(TOMPZ(w), u);
199
200
0
  return 0;
201
0
}
202
203
static unsigned int wrap_nettle_mpi_get_nbits(bigint_t a)
204
0
{
205
0
  return mpz_sizeinbase(TOMPZ(a), 2);
206
0
}
207
208
static void wrap_nettle_mpi_release(bigint_t a)
209
0
{
210
0
  mpz_clear(TOMPZ(a));
211
0
  gnutls_free(a);
212
0
}
213
214
static void wrap_nettle_mpi_clear(bigint_t a)
215
0
{
216
0
  zeroize_key(TOMPZ(a)[0]._mp_d,
217
0
        TOMPZ(a)[0]._mp_alloc * sizeof(mp_limb_t));
218
0
}
219
220
static int wrap_nettle_mpi_modm(bigint_t r, const bigint_t a, const bigint_t b)
221
0
{
222
0
  if (mpz_cmp_ui(TOMPZ(b), 0) == 0)
223
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
224
225
0
  mpz_mod(TOMPZ(r), TOMPZ(a), TOMPZ(b));
226
227
0
  return 0;
228
0
}
229
230
static int wrap_nettle_mpi_powm(bigint_t w, const bigint_t b, const bigint_t e,
231
        const bigint_t m)
232
0
{
233
0
  mpz_powm(TOMPZ(w), TOMPZ(b), TOMPZ(e), TOMPZ(m));
234
235
0
  return 0;
236
0
}
237
238
static int wrap_nettle_mpi_addm(bigint_t w, const bigint_t a, const bigint_t b,
239
        const bigint_t m)
240
0
{
241
0
  mpz_add(TOMPZ(w), TOMPZ(b), TOMPZ(a));
242
0
  mpz_fdiv_r(TOMPZ(w), TOMPZ(w), TOMPZ(m));
243
244
0
  return 0;
245
0
}
246
247
static int wrap_nettle_mpi_subm(bigint_t w, const bigint_t a, const bigint_t b,
248
        const bigint_t m)
249
0
{
250
0
  mpz_sub(TOMPZ(w), TOMPZ(a), TOMPZ(b));
251
0
  mpz_fdiv_r(TOMPZ(w), TOMPZ(w), TOMPZ(m));
252
253
0
  return 0;
254
0
}
255
256
static int wrap_nettle_mpi_mulm(bigint_t w, const bigint_t a, const bigint_t b,
257
        const bigint_t m)
258
0
{
259
0
  mpz_mul(TOMPZ(w), TOMPZ(a), TOMPZ(b));
260
0
  mpz_fdiv_r(TOMPZ(w), TOMPZ(w), TOMPZ(m));
261
262
0
  return 0;
263
0
}
264
265
static int wrap_nettle_mpi_add(bigint_t w, const bigint_t a, const bigint_t b)
266
0
{
267
0
  mpz_add(TOMPZ(w), TOMPZ(a), TOMPZ(b));
268
269
0
  return 0;
270
0
}
271
272
static int wrap_nettle_mpi_sub(bigint_t w, const bigint_t a, const bigint_t b)
273
0
{
274
0
  mpz_sub(TOMPZ(w), TOMPZ(a), TOMPZ(b));
275
276
0
  return 0;
277
0
}
278
279
static int wrap_nettle_mpi_mul(bigint_t w, const bigint_t a, const bigint_t b)
280
0
{
281
0
  mpz_mul(TOMPZ(w), TOMPZ(a), TOMPZ(b));
282
283
0
  return 0;
284
0
}
285
286
/* q = a / b */
287
static int wrap_nettle_mpi_div(bigint_t q, const bigint_t a, const bigint_t b)
288
0
{
289
0
  mpz_cdiv_q(TOMPZ(q), TOMPZ(a), TOMPZ(b));
290
291
0
  return 0;
292
0
}
293
294
static int wrap_nettle_mpi_add_ui(bigint_t w, const bigint_t a, unsigned long b)
295
0
{
296
0
  mpz_add_ui(TOMPZ(w), TOMPZ(a), b);
297
298
0
  return 0;
299
0
}
300
301
static int wrap_nettle_mpi_sub_ui(bigint_t w, const bigint_t a, unsigned long b)
302
0
{
303
0
  mpz_sub_ui(TOMPZ(w), TOMPZ(a), b);
304
305
0
  return 0;
306
0
}
307
308
static int wrap_nettle_mpi_mul_ui(bigint_t w, const bigint_t a, unsigned long b)
309
0
{
310
0
  mpz_mul_ui(TOMPZ(w), TOMPZ(a), b);
311
312
0
  return 0;
313
0
}
314
315
static int wrap_nettle_prime_check(bigint_t pp)
316
0
{
317
0
  int ret;
318
319
0
  ret = mpz_probab_prime_p(TOMPZ(pp), PRIME_CHECK_PARAM);
320
0
  if (ret > 0) {
321
0
    return 0;
322
0
  }
323
324
0
  return GNUTLS_E_INTERNAL_ERROR; /* ignored */
325
0
}
326
327
int crypto_bigint_prio = INT_MAX;
328
329
gnutls_crypto_bigint_st _gnutls_mpi_ops = {
330
  .bigint_init = wrap_nettle_mpi_init,
331
  .bigint_init_multi = wrap_nettle_mpi_init_multi,
332
  .bigint_cmp = wrap_nettle_mpi_cmp,
333
  .bigint_cmp_ui = wrap_nettle_mpi_cmp_ui,
334
  .bigint_modm = wrap_nettle_mpi_modm,
335
  .bigint_copy = wrap_nettle_mpi_copy,
336
  .bigint_set = wrap_nettle_mpi_set,
337
  .bigint_set_ui = wrap_nettle_mpi_set_ui,
338
  .bigint_get_nbits = wrap_nettle_mpi_get_nbits,
339
  .bigint_powm = wrap_nettle_mpi_powm,
340
  .bigint_addm = wrap_nettle_mpi_addm,
341
  .bigint_subm = wrap_nettle_mpi_subm,
342
  .bigint_add = wrap_nettle_mpi_add,
343
  .bigint_sub = wrap_nettle_mpi_sub,
344
  .bigint_add_ui = wrap_nettle_mpi_add_ui,
345
  .bigint_sub_ui = wrap_nettle_mpi_sub_ui,
346
  .bigint_mul = wrap_nettle_mpi_mul,
347
  .bigint_mulm = wrap_nettle_mpi_mulm,
348
  .bigint_mul_ui = wrap_nettle_mpi_mul_ui,
349
  .bigint_div = wrap_nettle_mpi_div,
350
  .bigint_prime_check = wrap_nettle_prime_check,
351
  .bigint_release = wrap_nettle_mpi_release,
352
  .bigint_clear = wrap_nettle_mpi_clear,
353
  .bigint_print = wrap_nettle_mpi_print,
354
  .bigint_scan = wrap_nettle_mpi_scan,
355
};