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