Coverage Report

Created: 2023-03-26 07:33

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