diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | doc/gcrypt.texi | 16 | ||||
-rw-r--r-- | mpi/ec.c | 65 | ||||
-rw-r--r-- | mpi/mpiutil.c | 89 | ||||
-rw-r--r-- | src/g10lib.h | 1 | ||||
-rw-r--r-- | src/gcrypt.h.in | 3 | ||||
-rw-r--r-- | src/global.c | 3 | ||||
-rw-r--r-- | src/mpi.h | 22 | ||||
-rw-r--r-- | tests/mpitests.c | 62 |
9 files changed, 202 insertions, 60 deletions
@@ -51,6 +51,7 @@ Noteworthy changes in version 1.6.0 (unreleased) gcry_mpi_ec_add NEW. gcry_mpi_ec_mul NEW. GCRYMPI_FLAG_IMMUTABLE NEW. + GCRYMPI_FLAG_CONST NEW. Noteworthy changes in version 1.5.0 (2011-06-29) diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index bfc825d6..a56d5278 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -3571,7 +3571,8 @@ confidential data like private key parameters. @deftypefun gcry_mpi_t gcry_mpi_copy (@w{const gcry_mpi_t @var{a}}) -Create a new MPI as the exact copy of @var{a}. +Create a new MPI as the exact copy of @var{a} but with the constant +and immutable flags cleared. @end deftypefun @@ -4008,20 +4009,29 @@ cleared. If this flag is set, the MPI is marked as immutable. Setting or changing the value of that MPI is ignored and an error message is logged. The flag is sometimes useful for debugging. +@item GCRYMPI_FLAG_CONST +If this flag is set, the MPI is marked as a constant and as immutable +Setting or changing the value of that MPI is ignored and an error +message is logged. Such an MPI will never be deallocated and may thus +be used without copying. Note that using gcry_mpi_copy will return a +copy of that constant with this and the immutable flag cleared. @end table @deftypefun void gcry_mpi_set_flag (@w{gcry_mpi_t @var{a}}, @ @w{enum gcry_mpi_flag @var{flag}}) Set the @var{flag} for the MPI @var{a}. The only allowed flags are -@code{GCRYMPI_FLAG_SECURE} and @code{GCRYMPI_FLAG_IMMUTABLE}. +@code{GCRYMPI_FLAG_SECURE}, @code{GCRYMPI_FLAG_IMMUTABLE}, and +@code{GCRYMPI_FLAG_CONST}. @end deftypefun @deftypefun void gcry_mpi_clear_flag (@w{gcry_mpi_t @var{a}}, @ @w{enum gcry_mpi_flag @var{flag}}) Clear @var{flag} for the multi-precision-integers @var{a}. The only -allowed flag is @code{GCRYMPI_FLAG_IMMUTABLE}. +allowed flag is @code{GCRYMPI_FLAG_IMMUTABLE} but only if +@code{GCRYMPI_FLAG_CONST} is not set. If @code{GCRYMPI_FLAG_CONST} is +set, clearing @code{GCRYMPI_FLAG_IMMUTABLE} will simply be ignored. @end deftypefun o @deftypefun int gcry_mpi_get_flag (@w{gcry_mpi_t @var{a}}, @ @@ -45,12 +45,6 @@ struct mpi_ec_ctx_s int a_is_pminus3; /* True if A = P - 3. */ - /* Some often used constants. */ - gcry_mpi_t one; - gcry_mpi_t two; - gcry_mpi_t three; - gcry_mpi_t four; - gcry_mpi_t eight; gcry_mpi_t two_inv_p; /* Scratch variables. */ @@ -374,15 +368,8 @@ ec_p_init (mpi_ec_t ctx, gcry_mpi_t p, gcry_mpi_t a) ctx->a_is_pminus3 = !mpi_cmp (ctx->a, tmp); mpi_free (tmp); - - /* Allocate constants. */ - ctx->one = mpi_alloc_set_ui (1); - ctx->two = mpi_alloc_set_ui (2); - ctx->three = mpi_alloc_set_ui (3); - ctx->four = mpi_alloc_set_ui (4); - ctx->eight = mpi_alloc_set_ui (8); ctx->two_inv_p = mpi_alloc (0); - ec_invm (ctx->two_inv_p, ctx->two, ctx); + ec_invm (ctx->two_inv_p, mpi_const (MPI_C_TWO), ctx); /* Allocate scratch variables. */ for (i=0; i< DIM(ctx->scratch); i++) @@ -417,12 +404,6 @@ ec_deinit (void *opaque) mpi_free (ctx->p); mpi_free (ctx->a); - mpi_free (ctx->one); - mpi_free (ctx->two); - mpi_free (ctx->three); - mpi_free (ctx->four); - mpi_free (ctx->eight); - mpi_free (ctx->two_inv_p); for (i=0; i< DIM(ctx->scratch); i++) @@ -563,9 +544,9 @@ _gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) /* L1 = 3(X - Z^2)(X + Z^2) */ /* T1: used for Z^2. */ /* T2: used for the right term. */ - ec_powm (t1, point->z, ctx->two, ctx); + ec_powm (t1, point->z, mpi_const (MPI_C_TWO), ctx); ec_subm (l1, point->x, t1, ctx); - ec_mulm (l1, l1, ctx->three, ctx); + ec_mulm (l1, l1, mpi_const (MPI_C_THREE), ctx); ec_addm (t2, point->x, t1, ctx); ec_mulm (l1, l1, t2, ctx); } @@ -573,32 +554,32 @@ _gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) { /* L1 = 3X^2 + aZ^4 */ /* T1: used for aZ^4. */ - ec_powm (l1, point->x, ctx->two, ctx); - ec_mulm (l1, l1, ctx->three, ctx); - ec_powm (t1, point->z, ctx->four, ctx); + ec_powm (l1, point->x, mpi_const (MPI_C_TWO), ctx); + ec_mulm (l1, l1, mpi_const (MPI_C_THREE), ctx); + ec_powm (t1, point->z, mpi_const (MPI_C_FOUR), ctx); ec_mulm (t1, t1, ctx->a, ctx); ec_addm (l1, l1, t1, ctx); } /* Z3 = 2YZ */ ec_mulm (z3, point->y, point->z, ctx); - ec_mulm (z3, z3, ctx->two, ctx); + ec_mulm (z3, z3, mpi_const (MPI_C_TWO), ctx); /* L2 = 4XY^2 */ /* T2: used for Y2; required later. */ - ec_powm (t2, point->y, ctx->two, ctx); + ec_powm (t2, point->y, mpi_const (MPI_C_TWO), ctx); ec_mulm (l2, t2, point->x, ctx); - ec_mulm (l2, l2, ctx->four, ctx); + ec_mulm (l2, l2, mpi_const (MPI_C_FOUR), ctx); /* X3 = L1^2 - 2L2 */ /* T1: used for L2^2. */ - ec_powm (x3, l1, ctx->two, ctx); - ec_mulm (t1, l2, ctx->two, ctx); + ec_powm (x3, l1, mpi_const (MPI_C_TWO), ctx); + ec_mulm (t1, l2, mpi_const (MPI_C_TWO), ctx); ec_subm (x3, x3, t1, ctx); /* L3 = 8Y^4 */ /* T2: taken from above. */ - ec_powm (t2, t2, ctx->two, ctx); - ec_mulm (l3, t2, ctx->eight, ctx); + ec_powm (t2, t2, mpi_const (MPI_C_TWO), ctx); + ec_mulm (l3, t2, mpi_const (MPI_C_EIGHT), ctx); /* Y3 = L1(L2 - X3) - L3 */ ec_subm (y3, l2, x3, ctx); @@ -676,23 +657,23 @@ _gcry_mpi_ec_add_points (mpi_point_t result, mpi_set (l1, x1); else { - ec_powm (l1, z2, ctx->two, ctx); + ec_powm (l1, z2, mpi_const (MPI_C_TWO), ctx); ec_mulm (l1, l1, x1, ctx); } if (z1_is_one) mpi_set (l2, x1); else { - ec_powm (l2, z1, ctx->two, ctx); + ec_powm (l2, z1, mpi_const (MPI_C_TWO), ctx); ec_mulm (l2, l2, x2, ctx); } /* l3 = l1 - l2 */ ec_subm (l3, l1, l2, ctx); /* l4 = y1 z2^3 */ - ec_powm (l4, z2, ctx->three, ctx); + ec_powm (l4, z2, mpi_const (MPI_C_THREE), ctx); ec_mulm (l4, l4, y1, ctx); /* l5 = y2 z1^3 */ - ec_powm (l5, z1, ctx->three, ctx); + ec_powm (l5, z1, mpi_const (MPI_C_THREE), ctx); ec_mulm (l5, l5, y2, ctx); /* l6 = l4 - l5 */ ec_subm (l6, l4, l5, ctx); @@ -722,16 +703,16 @@ _gcry_mpi_ec_add_points (mpi_point_t result, ec_mulm (z3, z1, z2, ctx); ec_mulm (z3, z3, l3, ctx); /* x3 = l6^2 - l7 l3^2 */ - ec_powm (t1, l6, ctx->two, ctx); - ec_powm (t2, l3, ctx->two, ctx); + ec_powm (t1, l6, mpi_const (MPI_C_TWO), ctx); + ec_powm (t2, l3, mpi_const (MPI_C_TWO), ctx); ec_mulm (t2, t2, l7, ctx); ec_subm (x3, t1, t2, ctx); /* l9 = l7 l3^2 - 2 x3 */ - ec_mulm (t1, x3, ctx->two, ctx); + ec_mulm (t1, x3, mpi_const (MPI_C_TWO), ctx); ec_subm (l9, t2, t1, ctx); /* y3 = (l9 l6 - l8 l3^3)/2 */ ec_mulm (l9, l9, l6, ctx); - ec_powm (t1, l3, ctx->three, ctx); /* fixme: Use saved value*/ + ec_powm (t1, l3, mpi_const (MPI_C_THREE), ctx); /* fixme: Use saved value*/ ec_mulm (t1, t1, l8, ctx); ec_subm (y3, l9, t1, ctx); ec_mulm (y3, y3, ctx->two_inv_p, ctx); @@ -824,9 +805,9 @@ _gcry_mpi_ec_mul_point (mpi_point_t result, mpi_free (z2); mpi_free (z3); } - z1 = mpi_copy (ctx->one); + z1 = mpi_copy (mpi_const (MPI_C_ONE)); - mpi_mul (h, k, ctx->three); /* h = 3k */ + mpi_mul (h, k, mpi_const (MPI_C_THREE)); /* h = 3k */ loops = mpi_get_nbits (h); mpi_set (result->x, point->x); diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c index 64a2f7e1..cff15b74 100644 --- a/mpi/mpiutil.c +++ b/mpi/mpiutil.c @@ -28,6 +28,10 @@ #include "mpi-internal.h" #include "mod-source-info.h" +/* Constatns allocated right away at strtartup. */ +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 @@ -178,6 +210,8 @@ _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 ); else @@ -195,7 +229,7 @@ _gcry_mpi_free( gcry_mpi_t a ) void _gcry_mpi_immutable_failed (void) { - log_info ("Warning: trying to change immutable MPI\n"); + log_info ("Warning: trying to change an immutable MPI\n"); } @@ -226,6 +260,12 @@ 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 ) gcry_free( a->d ); else @@ -266,6 +306,7 @@ gcry_mpi_copy( gcry_mpi_t a ) : gcry_xmalloc( (a->sign+7)/8 ); memcpy( p, a->d, (a->sign+7)/8 ); b = gcry_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 ) @@ -273,6 +314,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]; } @@ -478,24 +520,30 @@ gcry_mpi_randomize( gcry_mpi_t w, 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_IMMUTABLE: a->flags |= 16; 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_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: a->flags &= ~16; break; + case GCRYMPI_FLAG_IMMUTABLE: + if (!(a->flags & 32)) + a->flags &= ~16; + break; + case GCRYMPI_FLAG_CONST: case GCRYMPI_FLAG_SECURE: case GCRYMPI_FLAG_OPAQUE: default: log_bug("invalid flag value\n"); @@ -503,15 +551,30 @@ 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_IMMUTABLE: return (a->flags & 16); + 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); 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]; +} diff --git a/src/g10lib.h b/src/g10lib.h index da76c7b8..3caa2beb 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -348,6 +348,7 @@ gcry_err_code_t _gcry_cipher_init (void); gcry_err_code_t _gcry_md_init (void); gcry_err_code_t _gcry_pk_init (void); gcry_err_code_t _gcry_secmem_module_init (void); +gcry_err_code_t _gcry_mpi_init (void); gcry_err_code_t _gcry_pk_module_lookup (int id, gcry_module_t *module); void _gcry_pk_module_release (gcry_module_t module); diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 9f6438ce..eb9a11db 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -457,7 +457,8 @@ enum gcry_mpi_flag GCRYMPI_FLAG_OPAQUE = 2, /* The number is not a real one but just a way to store some bytes. This is useful for encrypted big integers. */ - GCRYMPI_FLAG_IMMUTABLE = 4 /* Mark the MPI as immutable. */ + GCRYMPI_FLAG_IMMUTABLE = 4, /* Mark the MPI as immutable. */ + GCRYMPI_FLAG_CONST = 8 /* Mark the MPI as a constant. */ }; diff --git a/src/global.c b/src/global.c index a1a83e9b..0c6fbbdd 100644 --- a/src/global.c +++ b/src/global.c @@ -140,6 +140,9 @@ global_init (void) err = _gcry_secmem_module_init (); if (err) goto fail; + err = _gcry_mpi_init (); + if (err) + goto fail; return; @@ -70,7 +70,8 @@ struct gcry_mpi for opaque MPIs to store the length. */ unsigned int flags; /* Bit 0: Array to be allocated in secure memory space.*/ /* Bit 2: The limb is a pointer to some m_alloced data.*/ - /* Bit 4: Const MPI - the MPI may not be modified. */ + /* Bit 4: Immutable MPI - the MPI may not be modified. */ + /* Bit 5: Constant MPI - the MPI will not be freed. */ mpi_limb_t *d; /* Array with the limbs */ }; @@ -108,6 +109,7 @@ struct gcry_mpi void _gcry_mpi_immutable_failed (void); #define mpi_immutable_failed() _gcry_mpi_immutable_failed () +#define mpi_is_const(a) ((a) && ((a)->flags&32)) #define mpi_is_immutable(a) ((a) && ((a)->flags&16)) #define mpi_is_opaque(a) ((a) && ((a)->flags&4)) #define mpi_is_secure(a) ((a) && ((a)->flags&1)) @@ -122,6 +124,7 @@ void _gcry_mpi_immutable_failed (void); #define mpi_swap(a,b) _gcry_mpi_swap ((a),(b)) #define mpi_new(n) _gcry_mpi_new ((n)) #define mpi_snew(n) _gcry_mpi_snew ((n)) +#define mpi_const(n) _gcry_mpi_const ((n)) void _gcry_mpi_clear( gcry_mpi_t a ); gcry_mpi_t _gcry_mpi_alloc_like( gcry_mpi_t a ); @@ -132,6 +135,23 @@ void _gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b); gcry_mpi_t _gcry_mpi_new (unsigned int nbits); gcry_mpi_t _gcry_mpi_snew (unsigned int nbits); +/* Constants used to return constant MPIs. See _gcry_mpi_init if you + want to add more constants. */ +#define MPI_NUMBER_OF_CONSTANTS 6 +enum gcry_mpi_constants + { + MPI_C_ZERO, + MPI_C_ONE, + MPI_C_TWO, + MPI_C_THREE, + MPI_C_FOUR, + MPI_C_EIGHT + }; + + +gcry_mpi_t _gcry_mpi_const (enum gcry_mpi_constants no); + + /*-- mpicoder.c --*/ void _gcry_log_mpidump( const char *text, gcry_mpi_t a ); u32 _gcry_mpi_get_keyid( gcry_mpi_t a, u32 *keyid ); diff --git a/tests/mpitests.c b/tests/mpitests.c index cf828425..3b75ea79 100644 --- a/tests/mpitests.c +++ b/tests/mpitests.c @@ -88,6 +88,67 @@ unsigned char manyff[] = { }; +static int +test_const_and_immutable (void) +{ + gcry_mpi_t one, second_one; + + one = gcry_mpi_set_ui (NULL, 1); + if (gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE) + || gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST)) + die ("immutable or const flag initially set\n"); + + second_one = gcry_mpi_copy (one); + if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_IMMUTABLE)) + die ("immutable flag set after copy\n"); + if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_CONST)) + die ("const flag set after copy\n"); + gcry_mpi_release (second_one); + + gcry_mpi_set_flag (one, GCRYMPI_FLAG_IMMUTABLE); + if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE)) + die ("failed to set immutable flag\n"); + if (gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST)) + die ("const flag unexpectly set\n"); + + second_one = gcry_mpi_copy (one); + if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_IMMUTABLE)) + die ("immutable flag not cleared after copy\n"); + if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_CONST)) + die ("const flag unexpectly set after copy\n"); + gcry_mpi_release (second_one); + + gcry_mpi_clear_flag (one, GCRYMPI_FLAG_IMMUTABLE); + if (gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE)) + die ("failed to clear immutable flag\n"); + if (gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST)) + die ("const flag unexpectly set\n"); + + gcry_mpi_set_flag (one, GCRYMPI_FLAG_CONST); + if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST)) + die ("failed to set const flag\n"); + if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE)) + die ("failed to set immutable flag with const flag\n"); + + second_one = gcry_mpi_copy (one); + if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_IMMUTABLE)) + die ("immutable flag not cleared after copy\n"); + if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_CONST)) + die ("const flag not cleared after copy\n"); + gcry_mpi_release (second_one); + + gcry_mpi_clear_flag (one, GCRYMPI_FLAG_IMMUTABLE); + if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE)) + die ("clearing immutable flag not ignored for a constant MPI\n"); + if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST)) + die ("const flag unexpectly cleared\n"); + + /* Due to the the constant flag the release below should be a NOP + and will leak memory. */ + gcry_mpi_release (one); + return 1; +} + static int test_add (void) @@ -292,6 +353,7 @@ main (int argc, char* argv[]) } gcry_control(GCRYCTL_DISABLE_SECMEM); + test_const_and_immutable (); test_add (); test_sub (); test_mul (); |