/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  |  | };  |