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 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,
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>
32 #include <gnutls_errors.h>
33 #include <gnutls_num.h>
34 #include <gnutls_mpi.h>
37 /* Functions that refer to the mpi library.
40 #define clearbit(v,n) ((unsigned char)(v) & ~( (unsigned char)(1) << (unsigned)(n)))
43 _gnutls_mpi_randomize (bigint_t r
, unsigned int bits
,
44 gnutls_rnd_level_t level
)
46 size_t size
= 1 + (bits
/ 8);
54 if (size
< sizeof (tmpbuf
))
60 buf
= gnutls_malloc (size
);
70 ret
= _gnutls_rnd (level
, buf
, size
);
77 /* mask the bits that weren't requested */
86 for (i
= 8; i
>= rem
; i
--)
87 buf
[0] = clearbit (buf
[0], i
);
90 ret
= _gnutls_mpi_scan (&tmp
, buf
, size
);
105 _gnutls_mpi_set (r
, tmp
);
106 _gnutls_mpi_release (&tmp
);
113 if (buf_release
!= 0)
119 _gnutls_mpi_release (bigint_t
* x
)
124 _gnutls_mpi_ops
.bigint_release (*x
);
128 /* returns zero on success
131 _gnutls_mpi_scan (bigint_t
* ret_mpi
, const void *buffer
, size_t nbytes
)
134 _gnutls_mpi_ops
.bigint_scan (buffer
, nbytes
, GNUTLS_MPI_FORMAT_USG
);
135 if (*ret_mpi
== NULL
)
138 return GNUTLS_E_MPI_SCAN_FAILED
;
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
)
151 ret
= _gnutls_mpi_scan (ret_mpi
, buffer
, nbytes
);
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
;
167 _gnutls_mpi_scan_pgp (bigint_t
* ret_mpi
, const void *buffer
, size_t nbytes
)
170 _gnutls_mpi_ops
.bigint_scan (buffer
, nbytes
, GNUTLS_MPI_FORMAT_PGP
);
171 if (*ret_mpi
== NULL
)
174 return GNUTLS_E_MPI_SCAN_FAILED
;
180 /* Always has the first bit zero */
182 _gnutls_mpi_dprint_lz (const bigint_t a
, gnutls_datum_t
* dest
)
188 if (dest
== NULL
|| a
== NULL
)
189 return GNUTLS_E_INVALID_REQUEST
;
191 _gnutls_mpi_print_lz (a
, NULL
, &bytes
);
194 buf
= gnutls_malloc (bytes
);
196 return GNUTLS_E_MEMORY_ERROR
;
198 ret
= _gnutls_mpi_print_lz (a
, buf
, &bytes
);
211 _gnutls_mpi_dprint (const bigint_t a
, gnutls_datum_t
* dest
)
217 if (dest
== NULL
|| a
== NULL
)
218 return GNUTLS_E_INVALID_REQUEST
;
220 _gnutls_mpi_print (a
, NULL
, &bytes
);
222 buf
= gnutls_malloc (bytes
);
224 return GNUTLS_E_MEMORY_ERROR
;
226 ret
= _gnutls_mpi_print (a
, buf
, &bytes
);
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
)
250 if (dest
== NULL
|| a
== NULL
)
251 return GNUTLS_E_INVALID_REQUEST
;
253 _gnutls_mpi_print (a
, NULL
, &bytes
);
255 buf
= gnutls_malloc (MAX (size
, bytes
));
257 return GNUTLS_E_MEMORY_ERROR
;
259 dest
->size
= MAX (size
, bytes
);
263 size_t diff
= size
- bytes
;
264 for (i
= 0; i
< diff
; i
++)
266 ret
= _gnutls_mpi_print (a
, &buf
[diff
], &bytes
);
270 ret
= _gnutls_mpi_print (a
, buf
, &bytes
);
280 dest
->size
= MAX (size
, bytes
);
284 /* this function reads an integer
285 * from asn1 structs. Combines the read and mpi_scan
289 _gnutls_x509_read_int (ASN1_TYPE node
, const char *value
, bigint_t
* ret_mpi
)
292 opaque
*tmpstr
= NULL
;
296 result
= asn1_read_value (node
, value
, NULL
, &tmpstr_size
);
297 if (result
!= ASN1_MEM_ERROR
)
300 return _gnutls_asn2err (result
);
303 tmpstr
= gnutls_malloc (tmpstr_size
);
307 return GNUTLS_E_MEMORY_ERROR
;
310 result
= asn1_read_value (node
, value
, tmpstr
, &tmpstr_size
);
311 if (result
!= ASN1_SUCCESS
)
314 gnutls_free (tmpstr
);
315 return _gnutls_asn2err (result
);
318 result
= _gnutls_mpi_scan (ret_mpi
, tmpstr
, tmpstr_size
);
319 gnutls_free (tmpstr
);
330 /* Writes the specified integer into the specified node.
333 _gnutls_x509_write_int (ASN1_TYPE node
, const char *value
, bigint_t mpi
,
342 result
= _gnutls_mpi_print_lz (mpi
, NULL
, &s_len
);
344 result
= _gnutls_mpi_print (mpi
, NULL
, &s_len
);
352 tmpstr
= gnutls_malloc (s_len
);
356 return GNUTLS_E_MEMORY_ERROR
;
360 result
= _gnutls_mpi_print_lz (mpi
, tmpstr
, &s_len
);
362 result
= _gnutls_mpi_print (mpi
, tmpstr
, &s_len
);
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
)
378 return _gnutls_asn2err (result
);