some more text for TPMs
[gnutls.git] / lib / gnutls_mpi.c
blob688f399c7394d7421f68c1fee39694d8dd62675b
1 /*
2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS 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 3 of
11 * the License, or (at your option) any later version.
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.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 /* Here lie everything that has to do with large numbers, libgcrypt and
24 * other stuff that didn't fit anywhere else.
27 #include <gnutls_int.h>
28 #include <libtasn1.h>
29 #include <gnutls_errors.h>
30 #include <gnutls_num.h>
31 #include <gnutls_mpi.h>
32 #include <random.h>
33 #include <x509/x509_int.h>
35 /* Functions that refer to the mpi library.
38 #define clearbit(v,n) ((unsigned char)(v) & ~( (unsigned char)(1) << (unsigned)(n)))
40 bigint_t
41 _gnutls_mpi_randomize (bigint_t r, unsigned int bits,
42 gnutls_rnd_level_t level)
44 size_t size = 1 + (bits / 8);
45 int ret;
46 int rem, i;
47 bigint_t tmp;
48 uint8_t tmpbuf[512];
49 uint8_t *buf;
50 int buf_release = 0;
52 if (size < sizeof (tmpbuf))
54 buf = tmpbuf;
56 else
58 buf = gnutls_malloc (size);
59 if (buf == NULL)
61 gnutls_assert ();
62 goto cleanup;
64 buf_release = 1;
68 ret = _gnutls_rnd (level, buf, size);
69 if (ret < 0)
71 gnutls_assert ();
72 goto cleanup;
75 /* mask the bits that weren't requested */
76 rem = bits % 8;
78 if (rem == 0)
80 buf[0] = 0;
82 else
84 for (i = 8; i >= rem; i--)
85 buf[0] = clearbit (buf[0], i);
88 ret = _gnutls_mpi_scan (&tmp, buf, size);
89 if (ret < 0)
91 gnutls_assert ();
92 goto cleanup;
95 if (buf_release != 0)
97 gnutls_free (buf);
98 buf = NULL;
101 if (r != NULL)
103 _gnutls_mpi_set (r, tmp);
104 _gnutls_mpi_release (&tmp);
105 return r;
108 return tmp;
110 cleanup:
111 if (buf_release != 0)
112 gnutls_free (buf);
113 return NULL;
116 void
117 _gnutls_mpi_release (bigint_t * x)
119 if (*x == NULL)
120 return;
122 _gnutls_mpi_ops.bigint_release (*x);
123 *x = NULL;
126 /* returns %GNUTLS_E_SUCCESS (0) on success
129 _gnutls_mpi_scan (bigint_t * ret_mpi, const void *buffer, size_t nbytes)
131 *ret_mpi =
132 _gnutls_mpi_ops.bigint_scan (buffer, nbytes, GNUTLS_MPI_FORMAT_USG);
133 if (*ret_mpi == NULL)
135 gnutls_assert ();
136 return GNUTLS_E_MPI_SCAN_FAILED;
139 return 0;
142 /* returns %GNUTLS_E_SUCCESS (0) on success. Fails if the number is zero.
145 _gnutls_mpi_scan_nz (bigint_t * ret_mpi, const void *buffer, size_t nbytes)
147 int ret;
149 ret = _gnutls_mpi_scan (ret_mpi, buffer, nbytes);
150 if (ret < 0)
151 return ret;
153 /* MPIs with 0 bits are illegal
155 if (_gnutls_mpi_cmp_ui (*ret_mpi, 0) == 0)
157 _gnutls_mpi_release (ret_mpi);
158 return GNUTLS_E_MPI_SCAN_FAILED;
161 return 0;
165 _gnutls_mpi_scan_pgp (bigint_t * ret_mpi, const void *buffer, size_t nbytes)
167 *ret_mpi =
168 _gnutls_mpi_ops.bigint_scan (buffer, nbytes, GNUTLS_MPI_FORMAT_PGP);
169 if (*ret_mpi == NULL)
171 gnutls_assert ();
172 return GNUTLS_E_MPI_SCAN_FAILED;
175 return 0;
178 /* Always has the first bit zero */
180 _gnutls_mpi_dprint_lz (const bigint_t a, gnutls_datum_t * dest)
182 int ret;
183 uint8_t *buf = NULL;
184 size_t bytes = 0;
186 if (dest == NULL || a == NULL)
187 return GNUTLS_E_INVALID_REQUEST;
189 _gnutls_mpi_print_lz (a, NULL, &bytes);
191 if (bytes != 0)
192 buf = gnutls_malloc (bytes);
193 if (buf == NULL)
194 return GNUTLS_E_MEMORY_ERROR;
196 ret = _gnutls_mpi_print_lz (a, buf, &bytes);
197 if (ret < 0)
199 gnutls_free (buf);
200 return ret;
203 dest->data = buf;
204 dest->size = bytes;
205 return 0;
209 _gnutls_mpi_dprint (const bigint_t a, gnutls_datum_t * dest)
211 int ret;
212 uint8_t *buf = NULL;
213 size_t bytes = 0;
215 if (dest == NULL || a == NULL)
216 return GNUTLS_E_INVALID_REQUEST;
218 _gnutls_mpi_print (a, NULL, &bytes);
219 if (bytes != 0)
220 buf = gnutls_malloc (bytes);
221 if (buf == NULL)
222 return GNUTLS_E_MEMORY_ERROR;
224 ret = _gnutls_mpi_print (a, buf, &bytes);
225 if (ret < 0)
227 gnutls_free (buf);
228 return ret;
231 dest->data = buf;
232 dest->size = bytes;
233 return 0;
236 /* This function will copy the mpi data into a datum,
237 * but will set minimum size to 'size'. That means that
238 * the output value is left padded with zeros.
241 _gnutls_mpi_dprint_size (const bigint_t a, gnutls_datum_t * dest, size_t size)
243 int ret;
244 uint8_t *buf = NULL;
245 size_t bytes = 0;
246 unsigned int i;
248 if (dest == NULL || a == NULL)
249 return GNUTLS_E_INVALID_REQUEST;
251 _gnutls_mpi_print (a, NULL, &bytes);
252 if (bytes != 0)
253 buf = gnutls_malloc (MAX (size, bytes));
254 if (buf == NULL)
255 return GNUTLS_E_MEMORY_ERROR;
257 if (bytes <= size)
259 size_t diff = size - bytes;
260 for (i = 0; i < diff; i++)
261 buf[i] = 0;
262 ret = _gnutls_mpi_print (a, &buf[diff], &bytes);
264 else
266 ret = _gnutls_mpi_print (a, buf, &bytes);
269 if (ret < 0)
271 gnutls_free (buf);
272 return ret;
275 dest->data = buf;
276 dest->size = MAX (size, bytes);
277 return 0;
280 /* this function reads an integer
281 * from asn1 structs. Combines the read and mpi_scan
282 * steps.
285 _gnutls_x509_read_int (ASN1_TYPE node, const char *value, bigint_t * ret_mpi)
287 int result;
288 uint8_t *tmpstr = NULL;
289 int tmpstr_size;
291 tmpstr_size = 0;
292 result = asn1_read_value (node, value, NULL, &tmpstr_size);
293 if (result != ASN1_MEM_ERROR)
295 gnutls_assert ();
296 return _gnutls_asn2err (result);
299 tmpstr = gnutls_malloc (tmpstr_size);
300 if (tmpstr == NULL)
302 gnutls_assert ();
303 return GNUTLS_E_MEMORY_ERROR;
306 result = asn1_read_value (node, value, tmpstr, &tmpstr_size);
307 if (result != ASN1_SUCCESS)
309 gnutls_assert ();
310 gnutls_free (tmpstr);
311 return _gnutls_asn2err (result);
314 result = _gnutls_mpi_scan (ret_mpi, tmpstr, tmpstr_size);
315 gnutls_free (tmpstr);
317 if (result < 0)
319 gnutls_assert ();
320 return result;
323 return 0;
326 /* Writes the specified integer into the specified node.
329 _gnutls_x509_write_int (ASN1_TYPE node, const char *value, bigint_t mpi,
330 int lz)
332 uint8_t *tmpstr;
333 size_t s_len;
334 int result;
336 s_len = 0;
337 if (lz)
338 result = _gnutls_mpi_print_lz (mpi, NULL, &s_len);
339 else
340 result = _gnutls_mpi_print (mpi, NULL, &s_len);
342 if (result != GNUTLS_E_SHORT_MEMORY_BUFFER)
344 gnutls_assert ();
345 return result;
348 tmpstr = gnutls_malloc (s_len);
349 if (tmpstr == NULL)
351 gnutls_assert ();
352 return GNUTLS_E_MEMORY_ERROR;
355 if (lz)
356 result = _gnutls_mpi_print_lz (mpi, tmpstr, &s_len);
357 else
358 result = _gnutls_mpi_print (mpi, tmpstr, &s_len);
360 if (result != 0)
362 gnutls_assert ();
363 gnutls_free (tmpstr);
364 return GNUTLS_E_MPI_PRINT_FAILED;
367 result = asn1_write_value (node, value, tmpstr, s_len);
369 gnutls_free (tmpstr);
371 if (result != ASN1_SUCCESS)
373 gnutls_assert ();
374 return _gnutls_asn2err (result);
377 return 0;