summaryrefslogtreecommitdiff
path: root/mpi
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2013-03-13 15:08:33 +0100
committerWerner Koch <wk@gnupg.org>2013-03-13 15:08:33 +0100
commite005629bd7bebb3e13945645c6e1230b44ab16a2 (patch)
tree46dc8a478d794e103ee4e70ec5c0832902d1bcba /mpi
parent1fecae98ee7e0fa49b29f98efa6817ca121ed98a (diff)
downloadlibgcrypt-e005629bd7bebb3e13945645c6e1230b44ab16a2.tar.gz
Add GCRYMPI_FLAG_CONST and make use constants.
* src/gcrypt.h.in (GCRYMPI_FLAG_CONST): New. * src/mpi.h (mpi_is_const, mpi_const): New. (enum gcry_mpi_constants, MPI_NUMBER_OF_CONSTANTS): New. * mpi/mpiutil.c (_gcry_mpi_init): New. (constants): New. (_gcry_mpi_free): Do not release a constant flagged MPI. (gcry_mpi_copy): Clear the const and immutable flags. (gcry_mpi_set_flag, gcry_mpi_clear_flag, gcry_mpi_get_flag): Support GCRYMPI_FLAG_CONST. (_gcry_mpi_const): New. * src/global.c (global_init): Call _gcry_mpi_init. * mpi/ec.c (mpi_ec_ctx_s): Remove fields one, two, three, four, and eight. Change all users to call mpi_const() instead. * src/mpiutils.c (gcry_mpi_set_opaque): Check the immutable flag. -- Allocating the trivial constants newly for every EC context is a waste of memory and cpu cycles. We instead provide a simple mechanism to internally support such constants. Using a new flag in THE API also allows to mark an arbitrary MPI as constant. The drawback of the constants is the their memory will never be deallocated. However, that is what constants are about.
Diffstat (limited to 'mpi')
-rw-r--r--mpi/ec.c65
-rw-r--r--mpi/mpiutil.c89
2 files changed, 99 insertions, 55 deletions
diff --git a/mpi/ec.c b/mpi/ec.c
index e85ec04d..7f310eac 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -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];
+}