2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008, 2010 Free Software
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
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 3 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 License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>
24 /* Here lie everything that has to do with large numbers, libgcrypt and
25 * other stuff that didn't fit anywhere else.
28 #include <gnutls_int.h>
30 #include <gnutls_errors.h>
31 #include <gnutls_num.h>
32 #include <gnutls_mpi.h>
34 #include <x509/x509_int.h>
36 /* Functions that refer to the mpi library.
39 #define clearbit(v,n) ((unsigned char)(v) & ~( (unsigned char)(1) << (unsigned)(n)))
42 _gnutls_mpi_randomize (bigint_t r
, unsigned int bits
,
43 gnutls_rnd_level_t level
)
45 size_t size
= 1 + (bits
/ 8);
53 if (size
< sizeof (tmpbuf
))
59 buf
= gnutls_malloc (size
);
69 ret
= gnutls_rnd (level
, buf
, size
);
76 /* mask the bits that weren't requested */
85 for (i
= 8; i
>= rem
; i
--)
86 buf
[0] = clearbit (buf
[0], i
);
89 ret
= _gnutls_mpi_scan (&tmp
, buf
, size
);
104 _gnutls_mpi_set (r
, tmp
);
105 _gnutls_mpi_release (&tmp
);
112 if (buf_release
!= 0)
118 _gnutls_mpi_release (bigint_t
* x
)
123 _gnutls_mpi_ops
.bigint_release (*x
);
127 /* returns %GNUTLS_E_SUCCESS (0) on success
130 _gnutls_mpi_scan (bigint_t
* ret_mpi
, const void *buffer
, size_t nbytes
)
133 _gnutls_mpi_ops
.bigint_scan (buffer
, nbytes
, GNUTLS_MPI_FORMAT_USG
);
134 if (*ret_mpi
== NULL
)
137 return GNUTLS_E_MPI_SCAN_FAILED
;
143 /* returns %GNUTLS_E_SUCCESS (0) on success. Fails if the number is zero.
146 _gnutls_mpi_scan_nz (bigint_t
* ret_mpi
, const void *buffer
, size_t nbytes
)
150 ret
= _gnutls_mpi_scan (ret_mpi
, buffer
, nbytes
);
154 /* MPIs with 0 bits are illegal
156 if (_gnutls_mpi_get_nbits (*ret_mpi
) == 0)
158 _gnutls_mpi_release (ret_mpi
);
159 return GNUTLS_E_MPI_SCAN_FAILED
;
166 _gnutls_mpi_scan_pgp (bigint_t
* ret_mpi
, const void *buffer
, size_t nbytes
)
169 _gnutls_mpi_ops
.bigint_scan (buffer
, nbytes
, GNUTLS_MPI_FORMAT_PGP
);
170 if (*ret_mpi
== NULL
)
173 return GNUTLS_E_MPI_SCAN_FAILED
;
179 /* Always has the first bit zero */
181 _gnutls_mpi_dprint_lz (const bigint_t a
, gnutls_datum_t
* dest
)
187 if (dest
== NULL
|| a
== NULL
)
188 return GNUTLS_E_INVALID_REQUEST
;
190 _gnutls_mpi_print_lz (a
, NULL
, &bytes
);
193 buf
= gnutls_malloc (bytes
);
195 return GNUTLS_E_MEMORY_ERROR
;
197 ret
= _gnutls_mpi_print_lz (a
, buf
, &bytes
);
210 _gnutls_mpi_dprint (const bigint_t a
, gnutls_datum_t
* dest
)
216 if (dest
== NULL
|| a
== NULL
)
217 return GNUTLS_E_INVALID_REQUEST
;
219 _gnutls_mpi_print (a
, NULL
, &bytes
);
221 buf
= gnutls_malloc (bytes
);
223 return GNUTLS_E_MEMORY_ERROR
;
225 ret
= _gnutls_mpi_print (a
, buf
, &bytes
);
237 /* This function will copy the mpi data into a datum,
238 * but will set minimum size to 'size'. That means that
239 * the output value is left padded with zeros.
242 _gnutls_mpi_dprint_size (const bigint_t a
, gnutls_datum_t
* dest
, size_t size
)
249 if (dest
== NULL
|| a
== NULL
)
250 return GNUTLS_E_INVALID_REQUEST
;
252 _gnutls_mpi_print (a
, NULL
, &bytes
);
254 buf
= gnutls_malloc (MAX (size
, bytes
));
256 return GNUTLS_E_MEMORY_ERROR
;
260 size_t diff
= size
- bytes
;
261 for (i
= 0; i
< diff
; i
++)
263 ret
= _gnutls_mpi_print (a
, &buf
[diff
], &bytes
);
267 ret
= _gnutls_mpi_print (a
, buf
, &bytes
);
277 dest
->size
= MAX (size
, bytes
);
281 /* this function reads an integer
282 * from asn1 structs. Combines the read and mpi_scan
286 _gnutls_x509_read_int (ASN1_TYPE node
, const char *value
, bigint_t
* ret_mpi
)
289 opaque
*tmpstr
= NULL
;
293 result
= asn1_read_value (node
, value
, NULL
, &tmpstr_size
);
294 if (result
!= ASN1_MEM_ERROR
)
297 return _gnutls_asn2err (result
);
300 tmpstr
= gnutls_malloc (tmpstr_size
);
304 return GNUTLS_E_MEMORY_ERROR
;
307 result
= asn1_read_value (node
, value
, tmpstr
, &tmpstr_size
);
308 if (result
!= ASN1_SUCCESS
)
311 gnutls_free (tmpstr
);
312 return _gnutls_asn2err (result
);
315 result
= _gnutls_mpi_scan (ret_mpi
, tmpstr
, tmpstr_size
);
316 gnutls_free (tmpstr
);
327 /* Writes the specified integer into the specified node.
330 _gnutls_x509_write_int (ASN1_TYPE node
, const char *value
, bigint_t mpi
,
339 result
= _gnutls_mpi_print_lz (mpi
, NULL
, &s_len
);
341 result
= _gnutls_mpi_print (mpi
, NULL
, &s_len
);
343 if (result
!= GNUTLS_E_SHORT_MEMORY_BUFFER
)
349 tmpstr
= gnutls_malloc (s_len
);
353 return GNUTLS_E_MEMORY_ERROR
;
357 result
= _gnutls_mpi_print_lz (mpi
, tmpstr
, &s_len
);
359 result
= _gnutls_mpi_print (mpi
, tmpstr
, &s_len
);
364 gnutls_free (tmpstr
);
365 return GNUTLS_E_MPI_PRINT_FAILED
;
368 result
= asn1_write_value (node
, value
, tmpstr
, s_len
);
370 gnutls_free (tmpstr
);
372 if (result
!= ASN1_SUCCESS
)
375 return _gnutls_asn2err (result
);