1
/* mpiutil.ac - Utility functions for MPI
2
* Copyright (C) 1998, 2000, 2001, 2002, 2003,
3
* 2007 Free Software Foundation, Inc.
5
* This file is part of Libgcrypt.
7
* Libgcrypt is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU Lesser General Public License as
9
* published by the Free Software Foundation; either version 2.1 of
10
* the License, or (at your option) any later version.
12
* Libgcrypt is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
27
#include "mpi-internal.h"
28
#include "mod-source-info.h"
32
_gcry_mpi_get_hw_config (void)
34
return mod_source_info + 1;
39
* Note: It was a bad idea to use the number of limbs to allocate
40
* because on a alpha the limbs are large but we normally need
41
* integers of n bits - So we should change this to bits (or bytes).
43
* But mpi_alloc is used in a lot of places :-(. New code
47
_gcry_mpi_alloc( unsigned nlimbs )
51
a = gcry_xmalloc( sizeof *a );
52
a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL;
61
_gcry_mpi_m_check( gcry_mpi_t a )
64
_gcry_check_heap(a->d);
68
_gcry_mpi_alloc_secure( unsigned nlimbs )
72
a = gcry_xmalloc( sizeof *a );
73
a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL;
84
_gcry_mpi_alloc_limb_space( unsigned int nlimbs, int secure )
89
len = (nlimbs ? nlimbs : 1) * sizeof (mpi_limb_t);
90
p = secure ? gcry_xmalloc_secure (len) : gcry_xmalloc (len);
98
_gcry_mpi_free_limb_space( mpi_ptr_t a, unsigned int nlimbs)
102
size_t len = nlimbs * sizeof(mpi_limb_t);
104
/* If we have information on the number of allocated limbs, we
105
better wipe that space out. This is a failsafe feature if
106
secure memory has been disabled or was not properly
107
implemented in user provided allocation functions. */
116
_gcry_mpi_assign_limb_space( gcry_mpi_t a, mpi_ptr_t ap, unsigned int nlimbs )
118
_gcry_mpi_free_limb_space (a->d, a->alloced);
126
* Resize the array of A to NLIMBS. The additional space is cleared
130
_gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
134
if (nlimbs <= a->alloced)
136
/* We only need to clear the new space (this is a nop if the
137
limb space is already of the correct size. */
138
for (i=a->nlimbs; i < a->alloced; i++)
143
/* Actually resize the limb space. */
146
a->d = gcry_xrealloc (a->d, nlimbs * sizeof (mpi_limb_t));
147
for (i=a->alloced; i < nlimbs; i++)
153
/* Secure memory is wanted. */
154
a->d = gcry_xcalloc_secure (nlimbs , sizeof (mpi_limb_t));
156
/* Standard memory. */
157
a->d = gcry_xcalloc (nlimbs , sizeof (mpi_limb_t));
163
_gcry_mpi_clear( gcry_mpi_t a )
171
_gcry_mpi_free( gcry_mpi_t a )
179
_gcry_mpi_free_limb_space(a->d, a->alloced);
182
log_bug("invalid flag value in mpi\n");
187
mpi_set_secure( gcry_mpi_t a )
191
if ( (a->flags & 1) )
200
bp = mpi_alloc_limb_space (a->nlimbs, 1);
201
MPN_COPY( bp, ap, a->nlimbs );
203
_gcry_mpi_free_limb_space (ap, a->alloced);
208
gcry_mpi_set_opaque( gcry_mpi_t a, void *p, unsigned int nbits )
216
_gcry_mpi_free_limb_space (a->d, a->alloced);
228
gcry_mpi_get_opaque( gcry_mpi_t a, unsigned int *nbits )
230
if( !(a->flags & 4) )
231
log_bug("mpi_get_opaque on normal mpi\n");
239
* Note: This copy function should not interpret the MPI
240
* but copy it transparently.
243
gcry_mpi_copy( gcry_mpi_t a )
248
if( a && (a->flags & 4) ) {
249
void *p = gcry_is_secure(a->d)? gcry_xmalloc_secure( (a->sign+7)/8 )
250
: gcry_xmalloc( (a->sign+7)/8 );
251
memcpy( p, a->d, (a->sign+7)/8 );
252
b = gcry_mpi_set_opaque( NULL, p, a->sign );
255
b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
256
: mpi_alloc( a->nlimbs );
257
b->nlimbs = a->nlimbs;
260
for(i=0; i < b->nlimbs; i++ )
270
* This function allocates an MPI which is optimized to hold
271
* a value as large as the one given in the argument and allocates it
272
* with the same flags as A.
275
_gcry_mpi_alloc_like( gcry_mpi_t a )
279
if( a && (a->flags & 4) ) {
280
int n = (a->sign+7)/8;
281
void *p = gcry_is_secure(a->d)? gcry_malloc_secure( n )
283
memcpy( p, a->d, n );
284
b = gcry_mpi_set_opaque( NULL, p, a->sign );
287
b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
288
: mpi_alloc( a->nlimbs );
300
gcry_mpi_set( gcry_mpi_t w, gcry_mpi_t u)
303
mpi_size_t usize = u->nlimbs;
307
w = _gcry_mpi_alloc( mpi_get_nlimbs(u) );
308
RESIZE_IF_NEEDED(w, usize);
311
MPN_COPY( wp, up, usize );
320
gcry_mpi_set_ui( gcry_mpi_t w, unsigned long u)
323
w = _gcry_mpi_alloc (1);
324
/* FIXME: If U is 0 we have no need to resize and thus possible
325
allocating the the limbs. */
326
RESIZE_IF_NEEDED(w, 1);
335
_gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
337
gcry_err_code_t err = GPG_ERR_NO_ERROR;
341
err = GPG_ERR_TOO_LARGE;
342
else if (w->nlimbs == 1)
354
gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
356
gcry_err_code_t err = GPG_ERR_NO_ERROR;
358
err = _gcry_mpi_get_ui (w, u);
360
return gcry_error (err);
364
_gcry_mpi_alloc_set_ui( unsigned long u)
366
gcry_mpi_t w = mpi_alloc(1);
374
gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b)
378
tmp = *a; *a = *b; *b = tmp;
383
gcry_mpi_new( unsigned int nbits )
385
return _gcry_mpi_alloc ( (nbits+BITS_PER_MPI_LIMB-1)
386
/ BITS_PER_MPI_LIMB );
391
gcry_mpi_snew( unsigned int nbits )
393
return _gcry_mpi_alloc_secure ( (nbits+BITS_PER_MPI_LIMB-1)
394
/ BITS_PER_MPI_LIMB );
398
gcry_mpi_release( gcry_mpi_t a )
404
gcry_mpi_randomize( gcry_mpi_t w,
405
unsigned int nbits, enum gcry_random_level level )
408
size_t nbytes = (nbits+7)/8;
410
if (level == GCRY_WEAK_RANDOM)
412
p = mpi_is_secure(w) ? gcry_xmalloc_secure (nbytes)
413
: gcry_xmalloc (nbytes);
414
gcry_create_nonce (p, nbytes);
418
p = mpi_is_secure(w) ? gcry_random_bytes_secure (nbytes, level)
419
: gcry_random_bytes (nbytes, level);
421
_gcry_mpi_set_buffer( w, p, nbytes, 0 );
427
gcry_mpi_set_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
430
case GCRYMPI_FLAG_SECURE: mpi_set_secure(a); break;
431
case GCRYMPI_FLAG_OPAQUE:
432
default: log_bug("invalid flag value\n");
437
gcry_mpi_clear_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
439
(void)a; /* Not yet used. */
443
case GCRYMPI_FLAG_SECURE:
444
case GCRYMPI_FLAG_OPAQUE:
445
default: log_bug("invalid flag value\n");
450
gcry_mpi_get_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
454
case GCRYMPI_FLAG_SECURE: return (a->flags & 1);
455
case GCRYMPI_FLAG_OPAQUE: return (a->flags & 4);
456
default: log_bug("invalid flag value\n");