diff options
Diffstat (limited to 'plugins/MirOTR/Libgcrypt/mpi/mpiutil.c')
-rw-r--r-- | plugins/MirOTR/Libgcrypt/mpi/mpiutil.c | 363 |
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]; +} |