Tizen 2.0 Release
[external/libgnutls26.git] / lib / gnutls_mpi.c
1 /*
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008, 2010 Free Software
3  * Foundation, Inc.
4  *
5  * Author: Nikos Mavrogiannopoulos
6  *
7  * This file is part of GnuTLS.
8  *
9  * The GnuTLS 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.
13  *
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.
18  *
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
23  *
24  */
25
26 /* Here lie everything that has to do with large numbers, libgcrypt and
27  * other stuff that didn't fit anywhere else.
28  */
29
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>
36
37 /* Functions that refer to the mpi library.
38  */
39
40 #define clearbit(v,n)    ((unsigned char)(v) & ~( (unsigned char)(1) << (unsigned)(n)))
41
42 bigint_t
43 _gnutls_mpi_randomize (bigint_t r, unsigned int bits,
44                        gnutls_rnd_level_t level)
45 {
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;
53
54   if (size < sizeof (tmpbuf))
55     {
56       buf = tmpbuf;
57     }
58   else
59     {
60       buf = gnutls_malloc (size);
61       if (buf == NULL)
62         {
63           gnutls_assert ();
64           goto cleanup;
65         }
66       buf_release = 1;
67     }
68
69
70   ret = _gnutls_rnd (level, buf, size);
71   if (ret < 0)
72     {
73       gnutls_assert ();
74       goto cleanup;
75     }
76
77   /* mask the bits that weren't requested */
78   rem = bits % 8;
79
80   if (rem == 0)
81     {
82       buf[0] = 0;
83     }
84   else
85     {
86       for (i = 8; i >= rem; i--)
87         buf[0] = clearbit (buf[0], i);
88     }
89
90   ret = _gnutls_mpi_scan (&tmp, buf, size);
91   if (ret < 0)
92     {
93       gnutls_assert ();
94       goto cleanup;
95     }
96
97   if (buf_release != 0)
98     {
99       gnutls_free (buf);
100       buf = NULL;
101     }
102
103   if (r != NULL)
104     {
105       _gnutls_mpi_set (r, tmp);
106       _gnutls_mpi_release (&tmp);
107       return r;
108     }
109
110   return tmp;
111
112 cleanup:
113   if (buf_release != 0)
114     gnutls_free (buf);
115   return NULL;
116 }
117
118 void
119 _gnutls_mpi_release (bigint_t * x)
120 {
121   if (*x == NULL)
122     return;
123
124   _gnutls_mpi_ops.bigint_release (*x);
125   *x = NULL;
126 }
127
128 /* returns zero on success
129  */
130 int
131 _gnutls_mpi_scan (bigint_t * ret_mpi, const void *buffer, size_t nbytes)
132 {
133   *ret_mpi =
134     _gnutls_mpi_ops.bigint_scan (buffer, nbytes, GNUTLS_MPI_FORMAT_USG);
135   if (*ret_mpi == NULL)
136     {
137       gnutls_assert ();
138       return GNUTLS_E_MPI_SCAN_FAILED;
139     }
140
141   return 0;
142 }
143
144 /* returns zero on success. Fails if the number is zero.
145  */
146 int
147 _gnutls_mpi_scan_nz (bigint_t * ret_mpi, const void *buffer, size_t nbytes)
148 {
149   int ret;
150
151   ret = _gnutls_mpi_scan (ret_mpi, buffer, nbytes);
152   if (ret < 0)
153     return ret;
154
155   /* MPIs with 0 bits are illegal
156    */
157   if (_gnutls_mpi_cmp_ui (*ret_mpi, 0) == 0)
158     {
159       _gnutls_mpi_release (ret_mpi);
160       return GNUTLS_E_MPI_SCAN_FAILED;
161     }
162
163   return 0;
164 }
165
166 int
167 _gnutls_mpi_scan_pgp (bigint_t * ret_mpi, const void *buffer, size_t nbytes)
168 {
169   *ret_mpi =
170     _gnutls_mpi_ops.bigint_scan (buffer, nbytes, GNUTLS_MPI_FORMAT_PGP);
171   if (*ret_mpi == NULL)
172     {
173       gnutls_assert ();
174       return GNUTLS_E_MPI_SCAN_FAILED;
175     }
176
177   return 0;
178 }
179
180 /* Always has the first bit zero */
181 int
182 _gnutls_mpi_dprint_lz (const bigint_t a, gnutls_datum_t * dest)
183 {
184   int ret;
185   opaque *buf = NULL;
186   size_t bytes = 0;
187
188   if (dest == NULL || a == NULL)
189     return GNUTLS_E_INVALID_REQUEST;
190
191   _gnutls_mpi_print_lz (a, NULL, &bytes);
192
193   if (bytes != 0)
194     buf = gnutls_malloc (bytes);
195   if (buf == NULL)
196     return GNUTLS_E_MEMORY_ERROR;
197
198   ret = _gnutls_mpi_print_lz (a, buf, &bytes);
199   if (ret < 0)
200     {
201       gnutls_free (buf);
202       return ret;
203     }
204
205   dest->data = buf;
206   dest->size = bytes;
207   return 0;
208 }
209
210 int
211 _gnutls_mpi_dprint (const bigint_t a, gnutls_datum_t * dest)
212 {
213   int ret;
214   opaque *buf = NULL;
215   size_t bytes = 0;
216
217   if (dest == NULL || a == NULL)
218     return GNUTLS_E_INVALID_REQUEST;
219
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;
225
226   ret = _gnutls_mpi_print (a, buf, &bytes);
227   if (ret < 0)
228     {
229       gnutls_free (buf);
230       return ret;
231     }
232
233   dest->data = buf;
234   dest->size = bytes;
235   return 0;
236 }
237
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.
241  */
242 int
243 _gnutls_mpi_dprint_size (const bigint_t a, gnutls_datum_t * dest, size_t size)
244 {
245   int ret;
246   opaque *buf = NULL;
247   size_t bytes = 0;
248   unsigned int i;
249
250   if (dest == NULL || a == NULL)
251     return GNUTLS_E_INVALID_REQUEST;
252
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;
258
259   if (bytes <= size)
260     {
261       size_t diff = size - bytes;
262       for (i = 0; i < diff; i++)
263         buf[i] = 0;
264       ret = _gnutls_mpi_print (a, &buf[diff], &bytes);
265     }
266   else
267     {
268       ret = _gnutls_mpi_print (a, buf, &bytes);
269     }
270
271   if (ret < 0)
272     {
273       gnutls_free (buf);
274       return ret;
275     }
276
277   dest->data = buf;
278   dest->size = MAX (size, bytes);
279   return 0;
280 }
281
282 /* this function reads an integer
283  * from asn1 structs. Combines the read and mpi_scan
284  * steps.
285  */
286 int
287 _gnutls_x509_read_int (ASN1_TYPE node, const char *value, bigint_t * ret_mpi)
288 {
289   int result;
290   opaque *tmpstr = NULL;
291   int tmpstr_size;
292
293   tmpstr_size = 0;
294   result = asn1_read_value (node, value, NULL, &tmpstr_size);
295   if (result != ASN1_MEM_ERROR)
296     {
297       gnutls_assert ();
298       return _gnutls_asn2err (result);
299     }
300
301   tmpstr = gnutls_malloc (tmpstr_size);
302   if (tmpstr == NULL)
303     {
304       gnutls_assert ();
305       return GNUTLS_E_MEMORY_ERROR;
306     }
307
308   result = asn1_read_value (node, value, tmpstr, &tmpstr_size);
309   if (result != ASN1_SUCCESS)
310     {
311       gnutls_assert ();
312       gnutls_free (tmpstr);
313       return _gnutls_asn2err (result);
314     }
315
316   result = _gnutls_mpi_scan (ret_mpi, tmpstr, tmpstr_size);
317   gnutls_free (tmpstr);
318
319   if (result < 0)
320     {
321       gnutls_assert ();
322       return result;
323     }
324
325   return 0;
326 }
327
328 /* Writes the specified integer into the specified node.
329  */
330 int
331 _gnutls_x509_write_int (ASN1_TYPE node, const char *value, bigint_t mpi,
332                         int lz)
333 {
334   opaque *tmpstr;
335   size_t s_len;
336   int result;
337
338   s_len = 0;
339   if (lz)
340     result = _gnutls_mpi_print_lz (mpi, NULL, &s_len);
341   else
342     result = _gnutls_mpi_print (mpi, NULL, &s_len);
343
344   if (result != GNUTLS_E_SHORT_MEMORY_BUFFER)
345     {
346       gnutls_assert ();
347       return result;
348     }
349
350   tmpstr = gnutls_malloc (s_len);
351   if (tmpstr == NULL)
352     {
353       gnutls_assert ();
354       return GNUTLS_E_MEMORY_ERROR;
355     }
356
357   if (lz)
358     result = _gnutls_mpi_print_lz (mpi, tmpstr, &s_len);
359   else
360     result = _gnutls_mpi_print (mpi, tmpstr, &s_len);
361
362   if (result != 0)
363     {
364       gnutls_assert ();
365       gnutls_free (tmpstr);
366       return GNUTLS_E_MPI_PRINT_FAILED;
367     }
368
369   result = asn1_write_value (node, value, tmpstr, s_len);
370
371   gnutls_free (tmpstr);
372
373   if (result != ASN1_SUCCESS)
374     {
375       gnutls_assert ();
376       return _gnutls_asn2err (result);
377     }
378
379   return 0;
380 }