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