Sync with TP.
[gnutls.git] / lib / gnutls_mpi.c
blob76a93a0bbeb7cd3c8a0009ae44cbbb3392554dbe
1 /*
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008, 2010 Free Software
3 * Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GNUTLS.
9 * The GNUTLS library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 * USA
26 /* Here lie everything that has to do with large numbers, libgcrypt and
27 * other stuff that didn't fit anywhere else.
30 #include <gnutls_int.h>
31 #include <libtasn1.h>
32 #include <gnutls_errors.h>
33 #include <gnutls_num.h>
34 #include <gnutls_mpi.h>
35 #include <random.h>
37 /* Functions that refer to the mpi library.
40 #define clearbit(v,n) ((unsigned char)(v) & ~( (unsigned char)(1) << (unsigned)(n)))
42 bigint_t
43 _gnutls_mpi_randomize (bigint_t r, unsigned int bits,
44 gnutls_rnd_level_t level)
46 size_t size = 1 + (bits / 8);
47 int ret;
48 int rem, i;
49 bigint_t tmp;
50 char tmpbuf[512];
51 opaque *buf;
52 int buf_release = 0;
54 if (size < sizeof (tmpbuf))
56 buf = tmpbuf;
58 else
60 buf = gnutls_malloc (size);
61 if (buf == NULL)
63 gnutls_assert ();
64 goto cleanup;
66 buf_release = 1;
70 ret = _gnutls_rnd (level, buf, size);
71 if (ret < 0)
73 gnutls_assert ();
74 goto cleanup;
77 /* mask the bits that weren't requested */
78 rem = bits % 8;
80 if (rem == 0)
82 buf[0] = 0;
84 else
86 for (i = 8; i >= rem; i--)
87 buf[0] = clearbit (buf[0], i);
90 ret = _gnutls_mpi_scan (&tmp, buf, size);
91 if (ret < 0)
93 gnutls_assert ();
94 goto cleanup;
97 if (buf_release != 0)
99 gnutls_free (buf);
100 buf = NULL;
103 if (r != NULL)
105 _gnutls_mpi_set (r, tmp);
106 _gnutls_mpi_release (&tmp);
107 return r;
110 return tmp;
112 cleanup:
113 if (buf_release != 0)
114 gnutls_free (buf);
115 return NULL;
118 void
119 _gnutls_mpi_release (bigint_t * x)
121 if (*x == NULL)
122 return;
124 _gnutls_mpi_ops.bigint_release (*x);
125 *x = NULL;
128 /* returns zero on success
131 _gnutls_mpi_scan (bigint_t * ret_mpi, const void *buffer, size_t nbytes)
133 *ret_mpi =
134 _gnutls_mpi_ops.bigint_scan (buffer, nbytes, GNUTLS_MPI_FORMAT_USG);
135 if (*ret_mpi == NULL)
137 gnutls_assert ();
138 return GNUTLS_E_MPI_SCAN_FAILED;
141 return 0;
144 /* returns zero on success. Fails if the number is zero.
147 _gnutls_mpi_scan_nz (bigint_t * ret_mpi, const void *buffer, size_t nbytes)
149 int ret;
151 ret = _gnutls_mpi_scan (ret_mpi, buffer, nbytes);
152 if (ret < 0)
153 return ret;
155 /* MPIs with 0 bits are illegal
157 if (_gnutls_mpi_get_nbits (*ret_mpi) == 0)
159 _gnutls_mpi_release (ret_mpi);
160 return GNUTLS_E_MPI_SCAN_FAILED;
163 return 0;
167 _gnutls_mpi_scan_pgp (bigint_t * ret_mpi, const void *buffer, size_t nbytes)
169 *ret_mpi =
170 _gnutls_mpi_ops.bigint_scan (buffer, nbytes, GNUTLS_MPI_FORMAT_PGP);
171 if (*ret_mpi == NULL)
173 gnutls_assert ();
174 return GNUTLS_E_MPI_SCAN_FAILED;
177 return 0;
180 /* Always has the first bit zero */
182 _gnutls_mpi_dprint_lz (const bigint_t a, gnutls_datum_t * dest)
184 int ret;
185 opaque *buf = NULL;
186 size_t bytes = 0;
188 if (dest == NULL || a == NULL)
189 return GNUTLS_E_INVALID_REQUEST;
191 _gnutls_mpi_print_lz (a, NULL, &bytes);
193 if (bytes != 0)
194 buf = gnutls_malloc (bytes);
195 if (buf == NULL)
196 return GNUTLS_E_MEMORY_ERROR;
198 ret = _gnutls_mpi_print_lz (a, buf, &bytes);
199 if (ret < 0)
201 gnutls_free (buf);
202 return ret;
205 dest->data = buf;
206 dest->size = bytes;
207 return 0;
211 _gnutls_mpi_dprint (const bigint_t a, gnutls_datum_t * dest)
213 int ret;
214 opaque *buf = NULL;
215 size_t bytes = 0;
217 if (dest == NULL || a == NULL)
218 return GNUTLS_E_INVALID_REQUEST;
220 _gnutls_mpi_print (a, NULL, &bytes);
221 if (bytes != 0)
222 buf = gnutls_malloc (bytes);
223 if (buf == NULL)
224 return GNUTLS_E_MEMORY_ERROR;
226 ret = _gnutls_mpi_print (a, buf, &bytes);
227 if (ret < 0)
229 gnutls_free (buf);
230 return ret;
233 dest->data = buf;
234 dest->size = bytes;
235 return 0;
238 /* This function will copy the mpi data into a datum,
239 * but will set minimum size to 'size'. That means that
240 * the output value is left padded with zeros.
243 _gnutls_mpi_dprint_size (const bigint_t a, gnutls_datum_t * dest, size_t size)
245 int ret;
246 opaque *buf = NULL;
247 size_t bytes = 0;
248 unsigned int i;
250 if (dest == NULL || a == NULL)
251 return GNUTLS_E_INVALID_REQUEST;
253 _gnutls_mpi_print (a, NULL, &bytes);
254 if (bytes != 0)
255 buf = gnutls_malloc (MAX (size, bytes));
256 if (buf == NULL)
257 return GNUTLS_E_MEMORY_ERROR;
259 dest->size = MAX (size, bytes);
261 if (bytes <= size)
263 size_t diff = size - bytes;
264 for (i = 0; i < diff; i++)
265 buf[i] = 0;
266 ret = _gnutls_mpi_print (a, &buf[diff], &bytes);
268 else
270 ret = _gnutls_mpi_print (a, buf, &bytes);
273 if (ret < 0)
275 gnutls_free (buf);
276 return ret;
279 dest->data = buf;
280 dest->size = MAX (size, bytes);
281 return 0;
284 /* this function reads an integer
285 * from asn1 structs. Combines the read and mpi_scan
286 * steps.
289 _gnutls_x509_read_int (ASN1_TYPE node, const char *value, bigint_t * ret_mpi)
291 int result;
292 opaque *tmpstr = NULL;
293 int tmpstr_size;
295 tmpstr_size = 0;
296 result = asn1_read_value (node, value, NULL, &tmpstr_size);
297 if (result != ASN1_MEM_ERROR)
299 gnutls_assert ();
300 return _gnutls_asn2err (result);
303 tmpstr = gnutls_malloc (tmpstr_size);
304 if (tmpstr == NULL)
306 gnutls_assert ();
307 return GNUTLS_E_MEMORY_ERROR;
310 result = asn1_read_value (node, value, tmpstr, &tmpstr_size);
311 if (result != ASN1_SUCCESS)
313 gnutls_assert ();
314 gnutls_free (tmpstr);
315 return _gnutls_asn2err (result);
318 result = _gnutls_mpi_scan (ret_mpi, tmpstr, tmpstr_size);
319 gnutls_free (tmpstr);
321 if (result < 0)
323 gnutls_assert ();
324 return result;
327 return 0;
330 /* Writes the specified integer into the specified node.
333 _gnutls_x509_write_int (ASN1_TYPE node, const char *value, bigint_t mpi,
334 int lz)
336 opaque *tmpstr;
337 size_t s_len;
338 int result;
340 s_len = 0;
341 if (lz)
342 result = _gnutls_mpi_print_lz (mpi, NULL, &s_len);
343 else
344 result = _gnutls_mpi_print (mpi, NULL, &s_len);
346 if (result != 0)
348 gnutls_assert ();
349 return result;
352 tmpstr = gnutls_malloc (s_len);
353 if (tmpstr == NULL)
355 gnutls_assert ();
356 return GNUTLS_E_MEMORY_ERROR;
359 if (lz)
360 result = _gnutls_mpi_print_lz (mpi, tmpstr, &s_len);
361 else
362 result = _gnutls_mpi_print (mpi, tmpstr, &s_len);
364 if (result != 0)
366 gnutls_assert ();
367 gnutls_free (tmpstr);
368 return GNUTLS_E_MPI_PRINT_FAILED;
371 result = asn1_write_value (node, value, tmpstr, s_len);
373 gnutls_free (tmpstr);
375 if (result != ASN1_SUCCESS)
377 gnutls_assert ();
378 return _gnutls_asn2err (result);
381 return 0;