summaryrefslogtreecommitdiff
path: root/plugins/MirOTR/Libgcrypt/mpi/mpiutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/MirOTR/Libgcrypt/mpi/mpiutil.c')
-rw-r--r--plugins/MirOTR/Libgcrypt/mpi/mpiutil.c363
1 files changed, 298 insertions, 65 deletions
diff --git a/plugins/MirOTR/Libgcrypt/mpi/mpiutil.c b/plugins/MirOTR/Libgcrypt/mpi/mpiutil.c
index 4dc5211360..6bef2a8821 100644
--- a/plugins/MirOTR/Libgcrypt/mpi/mpiutil.c
+++ b/plugins/MirOTR/Libgcrypt/mpi/mpiutil.c
@@ -1,6 +1,7 @@
/* 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.
*
@@ -25,9 +26,12 @@
#include "g10lib.h"
#include "mpi-internal.h"
-#include "memory.h"
#include "mod-source-info.h"
+/* Constants allocated right away at startup. */
+static gcry_mpi_t constants[MPI_NUMBER_OF_CONSTANTS];
+
+
const char *
_gcry_mpi_get_hw_config (void)
@@ -36,6 +40,34 @@ _gcry_mpi_get_hw_config (void)
}
+/* 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
@@ -49,7 +81,7 @@ _gcry_mpi_alloc( unsigned nlimbs )
{
gcry_mpi_t a;
- a = gcry_xmalloc( sizeof *a );
+ a = xmalloc( sizeof *a );
a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL;
a->alloced = nlimbs;
a->nlimbs = 0;
@@ -70,7 +102,7 @@ _gcry_mpi_alloc_secure( unsigned nlimbs )
{
gcry_mpi_t a;
- a = gcry_xmalloc( sizeof *a );
+ a = xmalloc( sizeof *a );
a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL;
a->alloced = nlimbs;
a->flags = 1;
@@ -88,7 +120,7 @@ _gcry_mpi_alloc_limb_space( unsigned int nlimbs, int secure )
size_t len;
len = (nlimbs ? nlimbs : 1) * sizeof (mpi_limb_t);
- p = secure ? gcry_xmalloc_secure (len) : gcry_xmalloc (len);
+ p = secure ? xmalloc_secure (len) : xmalloc (len);
if (! nlimbs)
*p = 0;
@@ -101,14 +133,14 @@ _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);
- gcry_free(a);
+ xfree(a);
}
}
@@ -138,13 +170,13 @@ _gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
limb space is already of the correct size. */
for (i=a->nlimbs; i < a->alloced; i++)
a->d[i] = 0;
- return;
+ return;
}
/* Actually resize the limb space. */
if (a->d)
{
- a->d = gcry_xrealloc (a->d, nlimbs * sizeof (mpi_limb_t));
+ a->d = xrealloc (a->d, nlimbs * sizeof (mpi_limb_t));
for (i=a->alloced; i < nlimbs; i++)
a->d[i] = 0;
}
@@ -152,10 +184,10 @@ _gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
{
if (a->flags & 1)
/* Secure memory is wanted. */
- a->d = gcry_xcalloc_secure (nlimbs , sizeof (mpi_limb_t));
+ a->d = xcalloc_secure (nlimbs , sizeof (mpi_limb_t));
else
/* Standard memory. */
- a->d = gcry_xcalloc (nlimbs , sizeof (mpi_limb_t));
+ a->d = xcalloc (nlimbs , sizeof (mpi_limb_t));
}
a->alloced = nlimbs;
}
@@ -163,8 +195,13 @@ _gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
void
_gcry_mpi_clear( gcry_mpi_t a )
{
- a->nlimbs = 0;
- a->flags = 0;
+ if (mpi_is_immutable (a))
+ {
+ mpi_immutable_failed ();
+ return;
+ }
+ a->nlimbs = 0;
+ a->flags = 0;
}
@@ -173,17 +210,33 @@ _gcry_mpi_free( gcry_mpi_t a )
{
if (!a )
return;
+ if ((a->flags & 32))
+ return; /* Never release a constant. */
if ((a->flags & 4))
- gcry_free( a->d );
+ xfree( a->d );
else
{
_gcry_mpi_free_limb_space(a->d, a->alloced);
}
- if ((a->flags & ~7))
- log_bug("invalid flag value in mpi\n");
- gcry_free(a);
+ /* 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 )
{
@@ -206,27 +259,51 @@ mpi_set_secure( gcry_mpi_t a )
gcry_mpi_t
-gcry_mpi_set_opaque( gcry_mpi_t a, void *p, unsigned int nbits )
+_gcry_mpi_set_opaque (gcry_mpi_t a, void *p, unsigned int nbits)
{
- if (!a)
+ if (!a)
a = mpi_alloc(0);
-
+
+ if (mpi_is_immutable (a))
+ {
+ mpi_immutable_failed ();
+ return a;
+ }
+
if( a->flags & 4 )
- gcry_free( a->d );
- else
+ 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 = 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 )
+_gcry_mpi_get_opaque (gcry_mpi_t a, unsigned int *nbits)
{
if( !(a->flags & 4) )
log_bug("mpi_get_opaque on normal mpi\n");
@@ -236,21 +313,39 @@ gcry_mpi_get_opaque( gcry_mpi_t a, unsigned int *nbits )
}
+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 )
+_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)? gcry_xmalloc_secure( (a->sign+7)/8 )
- : gcry_xmalloc( (a->sign+7)/8 );
+ 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 = gcry_mpi_set_opaque( NULL, p, a->sign );
+ 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 )
@@ -258,6 +353,7 @@ gcry_mpi_copy( gcry_mpi_t a )
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];
}
@@ -267,6 +363,47 @@ gcry_mpi_copy( gcry_mpi_t a )
}
+/* 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
@@ -279,10 +416,10 @@ _gcry_mpi_alloc_like( gcry_mpi_t a )
if( a && (a->flags & 4) ) {
int n = (a->sign+7)/8;
- void *p = gcry_is_secure(a->d)? gcry_malloc_secure( n )
- : gcry_malloc( n );
+ void *p = _gcry_is_secure(a->d)? xtrymalloc_secure (n)
+ : xtrymalloc (n);
memcpy( p, a->d, n );
- b = gcry_mpi_set_opaque( NULL, p, a->sign );
+ b = mpi_set_opaque( NULL, p, a->sign );
}
else if( a ) {
b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
@@ -297,33 +434,92 @@ _gcry_mpi_alloc_like( gcry_mpi_t a )
}
+/* 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)
+_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_cond (gcry_mpi_t w, const gcry_mpi_t u, unsigned long set)
+{
+ mpi_size_t i;
+ mpi_size_t nlimbs = u->alloced;
+ mpi_limb_t mask = ((mpi_limb_t)0) - !!set;
+ mpi_limb_t x;
+
+ if (w->alloced != u->alloced)
+ log_bug ("mpi_set_cond: different sizes\n");
+
+ for (i = 0; i < nlimbs; i++)
+ {
+ x = mask & (w->d[i] ^ u->d[i]);
+ w->d[i] = w->d[i] ^ x;
+ }
+
+ x = mask & (w->nlimbs ^ u->nlimbs);
+ w->nlimbs = w->nlimbs ^ x;
+
+ x = mask & (w->sign ^ u->sign);
+ w->sign = w->sign ^ x;
+ return w;
+}
+
gcry_mpi_t
-gcry_mpi_set_ui( gcry_mpi_t w, unsigned long u)
+_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;
@@ -347,19 +543,10 @@ _gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
if (! err)
*u = x;
-
+
return err;
}
-gcry_error_t
-gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
-
- err = _gcry_mpi_get_ui (w, u);
-
- return gcry_error (err);
-}
gcry_mpi_t
_gcry_mpi_alloc_set_ui( unsigned long u)
@@ -372,7 +559,7 @@ _gcry_mpi_alloc_set_ui( unsigned long u)
}
void
-gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b)
+_gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b)
{
struct gcry_mpi tmp;
@@ -381,7 +568,7 @@ gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b)
gcry_mpi_t
-gcry_mpi_new( unsigned int nbits )
+_gcry_mpi_new (unsigned int nbits)
{
return _gcry_mpi_alloc ( (nbits+BITS_PER_MPI_LIMB-1)
/ BITS_PER_MPI_LIMB );
@@ -389,58 +576,85 @@ gcry_mpi_new( unsigned int nbits )
gcry_mpi_t
-gcry_mpi_snew( unsigned int nbits )
+_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_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 )
+_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) ? gcry_xmalloc_secure (nbytes)
- : gcry_xmalloc (nbytes);
- gcry_create_nonce (p, nbytes);
+ 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);
+ p = mpi_is_secure(w) ? _gcry_random_bytes_secure (nbytes, level)
+ : _gcry_random_bytes (nbytes, level);
}
_gcry_mpi_set_buffer( w, p, nbytes, 0 );
- gcry_free (p);
+ xfree (p);
}
void
-gcry_mpi_set_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
+_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_OPAQUE:
- default: log_bug("invalid flag value\n");
+ 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 )
+_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");
@@ -448,15 +662,34 @@ gcry_mpi_clear_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
}
int
-gcry_mpi_get_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
+_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_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];
+}