Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F36623161
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
14 KB
Subscribers
None
View Options
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index 1f1754a2..fdce578e 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -1,670 +1,670 @@
/* mpiutil.ac - Utility functions for MPI
* Copyright (C) 1998, 2000, 2001, 2002, 2003,
* 2007 Free Software Foundation, Inc.
* Copyright (C) 2013 g10 Code GmbH
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "g10lib.h"
#include "mpi-internal.h"
#include "mod-source-info.h"
-/* Constatns allocated right away at strtartup. */
+/* Constants allocated right away at startup. */
static gcry_mpi_t constants[MPI_NUMBER_OF_CONSTANTS];
const char *
_gcry_mpi_get_hw_config (void)
{
return mod_source_info + 1;
}
/* Initialize the MPI subsystem. This is called early and allows to
do some initialization without taking care of threading issues. */
gcry_err_code_t
_gcry_mpi_init (void)
{
int idx;
unsigned long value;
for (idx=0; idx < MPI_NUMBER_OF_CONSTANTS; idx++)
{
switch (idx)
{
case MPI_C_ZERO: value = 0; break;
case MPI_C_ONE: value = 1; break;
case MPI_C_TWO: value = 2; break;
case MPI_C_THREE: value = 3; break;
case MPI_C_FOUR: value = 4; break;
case MPI_C_EIGHT: value = 8; break;
default: log_bug ("invalid mpi_const selector %d\n", idx);
}
constants[idx] = mpi_alloc_set_ui (value);
constants[idx]->flags = (16|32);
}
return 0;
}
/****************
* Note: It was a bad idea to use the number of limbs to allocate
* because on a alpha the limbs are large but we normally need
* integers of n bits - So we should change this to bits (or bytes).
*
* But mpi_alloc is used in a lot of places :-(. New code
* should use mpi_new.
*/
gcry_mpi_t
_gcry_mpi_alloc( unsigned nlimbs )
{
gcry_mpi_t a;
a = xmalloc( sizeof *a );
a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL;
a->alloced = nlimbs;
a->nlimbs = 0;
a->sign = 0;
a->flags = 0;
return a;
}
void
_gcry_mpi_m_check( gcry_mpi_t a )
{
_gcry_check_heap(a);
_gcry_check_heap(a->d);
}
gcry_mpi_t
_gcry_mpi_alloc_secure( unsigned nlimbs )
{
gcry_mpi_t a;
a = xmalloc( sizeof *a );
a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL;
a->alloced = nlimbs;
a->flags = 1;
a->nlimbs = 0;
a->sign = 0;
return a;
}
mpi_ptr_t
_gcry_mpi_alloc_limb_space( unsigned int nlimbs, int secure )
{
mpi_ptr_t p;
size_t len;
len = (nlimbs ? nlimbs : 1) * sizeof (mpi_limb_t);
p = secure ? xmalloc_secure (len) : xmalloc (len);
if (! nlimbs)
*p = 0;
return p;
}
void
_gcry_mpi_free_limb_space( mpi_ptr_t a, unsigned int nlimbs)
{
if (a)
{
size_t len = nlimbs * sizeof(mpi_limb_t);
/* If we have information on the number of allocated limbs, we
better wipe that space out. This is a failsafe feature if
secure memory has been disabled or was not properly
implemented in user provided allocation functions. */
if (len)
wipememory (a, len);
xfree(a);
}
}
void
_gcry_mpi_assign_limb_space( gcry_mpi_t a, mpi_ptr_t ap, unsigned int nlimbs )
{
_gcry_mpi_free_limb_space (a->d, a->alloced);
a->d = ap;
a->alloced = nlimbs;
}
/****************
* Resize the array of A to NLIMBS. The additional space is cleared
* (set to 0).
*/
void
_gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
{
size_t i;
if (nlimbs <= a->alloced)
{
/* We only need to clear the new space (this is a nop if the
limb space is already of the correct size. */
for (i=a->nlimbs; i < a->alloced; i++)
a->d[i] = 0;
return;
}
/* Actually resize the limb space. */
if (a->d)
{
a->d = xrealloc (a->d, nlimbs * sizeof (mpi_limb_t));
for (i=a->alloced; i < nlimbs; i++)
a->d[i] = 0;
}
else
{
if (a->flags & 1)
/* Secure memory is wanted. */
a->d = xcalloc_secure (nlimbs , sizeof (mpi_limb_t));
else
/* Standard memory. */
a->d = xcalloc (nlimbs , sizeof (mpi_limb_t));
}
a->alloced = nlimbs;
}
void
_gcry_mpi_clear( gcry_mpi_t a )
{
if (mpi_is_immutable (a))
{
mpi_immutable_failed ();
return;
}
a->nlimbs = 0;
a->flags = 0;
}
void
_gcry_mpi_free( gcry_mpi_t a )
{
if (!a )
return;
if ((a->flags & 32))
return; /* Never release a constant. */
if ((a->flags & 4))
xfree( a->d );
else
{
_gcry_mpi_free_limb_space(a->d, a->alloced);
}
/* Check that the flags makes sense. We better allow for bit 1
(value 2) for backward ABI compatibility. */
if ((a->flags & ~(1|2|4|16
|GCRYMPI_FLAG_USER1
|GCRYMPI_FLAG_USER2
|GCRYMPI_FLAG_USER3
|GCRYMPI_FLAG_USER4)))
log_bug("invalid flag value in mpi_free\n");
xfree (a);
}
void
_gcry_mpi_immutable_failed (void)
{
log_info ("Warning: trying to change an immutable MPI\n");
}
static void
mpi_set_secure( gcry_mpi_t a )
{
mpi_ptr_t ap, bp;
if ( (a->flags & 1) )
return;
a->flags |= 1;
ap = a->d;
if (!a->nlimbs)
{
gcry_assert (!ap);
return;
}
bp = mpi_alloc_limb_space (a->nlimbs, 1);
MPN_COPY( bp, ap, a->nlimbs );
a->d = bp;
_gcry_mpi_free_limb_space (ap, a->alloced);
}
gcry_mpi_t
_gcry_mpi_set_opaque (gcry_mpi_t a, void *p, unsigned int nbits)
{
if (!a)
a = mpi_alloc(0);
if (mpi_is_immutable (a))
{
mpi_immutable_failed ();
return a;
}
if( a->flags & 4 )
xfree (a->d);
else
_gcry_mpi_free_limb_space (a->d, a->alloced);
a->d = p;
a->alloced = 0;
a->nlimbs = 0;
a->sign = nbits;
a->flags = 4 | (a->flags & (GCRYMPI_FLAG_USER1|GCRYMPI_FLAG_USER2
|GCRYMPI_FLAG_USER3|GCRYMPI_FLAG_USER4));
if (_gcry_is_secure (a->d))
a->flags |= 1;
return a;
}
gcry_mpi_t
_gcry_mpi_set_opaque_copy (gcry_mpi_t a, const void *p, unsigned int nbits)
{
void *d;
unsigned int n;
n = (nbits+7)/8;
d = _gcry_is_secure (p)? xtrymalloc_secure (n) : xtrymalloc (n);
if (!d)
return NULL;
memcpy (d, p, n);
return mpi_set_opaque (a, d, nbits);
}
void *
_gcry_mpi_get_opaque (gcry_mpi_t a, unsigned int *nbits)
{
if( !(a->flags & 4) )
log_bug("mpi_get_opaque on normal mpi\n");
if( nbits )
*nbits = a->sign;
return a->d;
}
void *
_gcry_mpi_get_opaque_copy (gcry_mpi_t a, unsigned int *nbits)
{
const void *s;
void *d;
unsigned int n;
s = mpi_get_opaque (a, nbits);
if (!s && nbits)
return NULL;
n = (*nbits+7)/8;
d = _gcry_is_secure (s)? xtrymalloc_secure (n) : xtrymalloc (n);
if (d)
memcpy (d, s, n);
return d;
}
/****************
* Note: This copy function should not interpret the MPI
* but copy it transparently.
*/
gcry_mpi_t
_gcry_mpi_copy (gcry_mpi_t a)
{
int i;
gcry_mpi_t b;
if( a && (a->flags & 4) ) {
void *p = _gcry_is_secure(a->d)? xmalloc_secure ((a->sign+7)/8)
: xmalloc ((a->sign+7)/8);
memcpy( p, a->d, (a->sign+7)/8 );
b = mpi_set_opaque( NULL, p, a->sign );
b->flags &= ~(16|32); /* Reset the immutable and constant flags. */
}
else if( a ) {
b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
: mpi_alloc( a->nlimbs );
b->nlimbs = a->nlimbs;
b->sign = a->sign;
b->flags = a->flags;
b->flags &= ~(16|32); /* Reset the immutable and constant flags. */
for(i=0; i < b->nlimbs; i++ )
b->d[i] = a->d[i];
}
else
b = NULL;
return b;
}
/* Return true if A is negative. */
int
_gcry_mpi_is_neg (gcry_mpi_t a)
{
if (a->sign && _gcry_mpi_cmp_ui (a, 0))
return 1;
else
return 0;
}
/* W = - U */
void
_gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u)
{
if (w != u)
mpi_set (w, u);
else if (mpi_is_immutable (w))
{
mpi_immutable_failed ();
return;
}
w->sign = !u->sign;
}
/* W = [W] */
void
_gcry_mpi_abs (gcry_mpi_t w)
{
if (mpi_is_immutable (w))
{
mpi_immutable_failed ();
return;
}
w->sign = 0;
}
/****************
* This function allocates an MPI which is optimized to hold
* a value as large as the one given in the argument and allocates it
* with the same flags as A.
*/
gcry_mpi_t
_gcry_mpi_alloc_like( gcry_mpi_t a )
{
gcry_mpi_t b;
if( a && (a->flags & 4) ) {
int n = (a->sign+7)/8;
void *p = _gcry_is_secure(a->d)? xtrymalloc_secure (n)
: xtrymalloc (n);
memcpy( p, a->d, n );
b = mpi_set_opaque( NULL, p, a->sign );
}
else if( a ) {
b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
: mpi_alloc( a->nlimbs );
b->nlimbs = 0;
b->sign = 0;
b->flags = a->flags;
}
else
b = NULL;
return b;
}
/* Set U into W and release U. If W is NULL only U will be released. */
void
_gcry_mpi_snatch (gcry_mpi_t w, gcry_mpi_t u)
{
if (w)
{
if (mpi_is_immutable (w))
{
mpi_immutable_failed ();
return;
}
_gcry_mpi_assign_limb_space (w, u->d, u->alloced);
w->nlimbs = u->nlimbs;
w->sign = u->sign;
w->flags = u->flags;
u->alloced = 0;
u->nlimbs = 0;
u->d = NULL;
}
_gcry_mpi_free (u);
}
gcry_mpi_t
_gcry_mpi_set (gcry_mpi_t w, gcry_mpi_t u)
{
mpi_ptr_t wp, up;
mpi_size_t usize = u->nlimbs;
int usign = u->sign;
if (!w)
w = _gcry_mpi_alloc( mpi_get_nlimbs(u) );
if (mpi_is_immutable (w))
{
mpi_immutable_failed ();
return w;
}
RESIZE_IF_NEEDED(w, usize);
wp = w->d;
up = u->d;
MPN_COPY( wp, up, usize );
w->nlimbs = usize;
w->flags = u->flags;
w->flags &= ~(16|32); /* Reset the immutable and constant flags. */
w->sign = usign;
return w;
}
gcry_mpi_t
_gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u)
{
if (!w)
w = _gcry_mpi_alloc (1);
/* FIXME: If U is 0 we have no need to resize and thus possible
allocating the the limbs. */
if (mpi_is_immutable (w))
{
mpi_immutable_failed ();
return w;
}
RESIZE_IF_NEEDED(w, 1);
w->d[0] = u;
w->nlimbs = u? 1:0;
w->sign = 0;
w->flags = 0;
return w;
}
gcry_err_code_t
_gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
{
gcry_err_code_t err = GPG_ERR_NO_ERROR;
unsigned long x = 0;
if (w->nlimbs > 1)
err = GPG_ERR_TOO_LARGE;
else if (w->nlimbs == 1)
x = w->d[0];
else
x = 0;
if (! err)
*u = x;
return err;
}
gcry_mpi_t
_gcry_mpi_alloc_set_ui( unsigned long u)
{
gcry_mpi_t w = mpi_alloc(1);
w->d[0] = u;
w->nlimbs = u? 1:0;
w->sign = 0;
return w;
}
void
_gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b)
{
struct gcry_mpi tmp;
tmp = *a; *a = *b; *b = tmp;
}
gcry_mpi_t
_gcry_mpi_new (unsigned int nbits)
{
return _gcry_mpi_alloc ( (nbits+BITS_PER_MPI_LIMB-1)
/ BITS_PER_MPI_LIMB );
}
gcry_mpi_t
_gcry_mpi_snew (unsigned int nbits)
{
return _gcry_mpi_alloc_secure ( (nbits+BITS_PER_MPI_LIMB-1)
/ BITS_PER_MPI_LIMB );
}
void
_gcry_mpi_release( gcry_mpi_t a )
{
_gcry_mpi_free( a );
}
void
_gcry_mpi_randomize (gcry_mpi_t w,
unsigned int nbits, enum gcry_random_level level)
{
unsigned char *p;
size_t nbytes = (nbits+7)/8;
if (mpi_is_immutable (w))
{
mpi_immutable_failed ();
return;
}
if (level == GCRY_WEAK_RANDOM)
{
p = mpi_is_secure(w) ? xmalloc_secure (nbytes)
: xmalloc (nbytes);
_gcry_create_nonce (p, nbytes);
}
else
{
p = mpi_is_secure(w) ? _gcry_random_bytes_secure (nbytes, level)
: _gcry_random_bytes (nbytes, level);
}
_gcry_mpi_set_buffer( w, p, nbytes, 0 );
xfree (p);
}
void
_gcry_mpi_set_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
{
switch (flag)
{
case GCRYMPI_FLAG_SECURE: mpi_set_secure(a); break;
case GCRYMPI_FLAG_CONST: a->flags |= (16|32); break;
case GCRYMPI_FLAG_IMMUTABLE: a->flags |= 16; break;
case GCRYMPI_FLAG_USER1:
case GCRYMPI_FLAG_USER2:
case GCRYMPI_FLAG_USER3:
case GCRYMPI_FLAG_USER4: a->flags |= flag; break;
case GCRYMPI_FLAG_OPAQUE:
default: log_bug("invalid flag value\n");
}
}
void
_gcry_mpi_clear_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
{
(void)a; /* Not yet used. */
switch (flag)
{
case GCRYMPI_FLAG_IMMUTABLE:
if (!(a->flags & 32))
a->flags &= ~16;
break;
case GCRYMPI_FLAG_USER1:
case GCRYMPI_FLAG_USER2:
case GCRYMPI_FLAG_USER3:
case GCRYMPI_FLAG_USER4:
a->flags &= ~flag;
break;
case GCRYMPI_FLAG_CONST:
case GCRYMPI_FLAG_SECURE:
case GCRYMPI_FLAG_OPAQUE:
default: log_bug("invalid flag value\n");
}
}
int
_gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
{
switch (flag)
{
case GCRYMPI_FLAG_SECURE: return !!(a->flags & 1);
case GCRYMPI_FLAG_OPAQUE: return !!(a->flags & 4);
case GCRYMPI_FLAG_IMMUTABLE: return !!(a->flags & 16);
case GCRYMPI_FLAG_CONST: return !!(a->flags & 32);
case GCRYMPI_FLAG_USER1:
case GCRYMPI_FLAG_USER2:
case GCRYMPI_FLAG_USER3:
case GCRYMPI_FLAG_USER4: return !!(a->flags & flag);
default: log_bug("invalid flag value\n");
}
/*NOTREACHED*/
return 0;
}
/* Return a constant MPI descripbed by NO which is one of the
MPI_C_xxx macros. There is no need to copy this returned value; it
may be used directly. */
gcry_mpi_t
_gcry_mpi_const (enum gcry_mpi_constants no)
{
if ((int)no < 0 || no > MPI_NUMBER_OF_CONSTANTS)
log_bug("invalid mpi_const selector %d\n", no);
if (!constants[no])
log_bug("MPI subsystem not initialized\n");
return constants[no];
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Feb 26, 6:41 PM (4 h, 39 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
82/0c/d00a51ecbfdaf493ef404851aa87
Attached To
rC libgcrypt
Event Timeline
Log In to Comment