summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2013-03-12 20:20:42 +0100
committerWerner Koch <wk@gnupg.org>2013-03-13 12:38:30 +0100
commit1fecae98ee7e0fa49b29f98efa6817ca121ed98a (patch)
tree02a3ba8f73f47d1ee629563d1abde0b56dc5d31d
parent5e743bc72e3fee3d550d0d7ae98596b7de6b46f8 (diff)
downloadlibgcrypt-1fecae98ee7e0fa49b29f98efa6817ca121ed98a.tar.gz
Add GCRYMPI_FLAG_IMMUTABLE to help debugging.
* src/gcrypt.h.in (GCRYMPI_FLAG_IMMUTABLE): New. * src/mpi.h (mpi_is_immutable): New macro. * mpi/mpiutil.c (gcry_mpi_set_flag, gcry_mpi_clear_flag) (gcry_mpi_get_flag): Implement new flag (_gcry_mpi_immutable_failed): New. * mpi/mpiutil.c (_gcry_mpi_clear, _gcry_mpi_free, gcry_mpi_snatch) (gcry_mpi_set, gcry_mpi_randomize): Act upon the immutable flag. * mpi/mpi-bit.c (gcry_mpi_set_bit, gcry_mpi_set_highbit) (gcry_mpi_clear_highbit, gcry_mpi_clear_bit) (_gcry_mpi_rshift_limbs, gcry_mpi_lshift): Ditto. * mpi/mpicoder.c (_gcry_mpi_set_buffer): Ditto. -- Note that this flag is currently only checked by a few MPI functions. The reason why we eventually need such a flag is to help implementing a generic way to retrieve and set ECC parameters without accidentally changing a curve parameter taken from a list of predefined curves.
-rw-r--r--NEWS1
-rw-r--r--doc/gcrypt.texi47
-rw-r--r--mpi/mpi-bit.c93
-rw-r--r--mpi/mpicoder.c6
-rw-r--r--mpi/mpiutil.c48
-rw-r--r--src/gcrypt.h.in3
-rw-r--r--src/mpi.h11
7 files changed, 164 insertions, 45 deletions
diff --git a/NEWS b/NEWS
index 733dd88e..3a4ca4c0 100644
--- a/NEWS
+++ b/NEWS
@@ -50,6 +50,7 @@ Noteworthy changes in version 1.6.0 (unreleased)
gcry_mpi_ec_dup NEW.
gcry_mpi_ec_add NEW.
gcry_mpi_ec_mul NEW.
+ GCRYMPI_FLAG_IMMUTABLE NEW.
Noteworthy changes in version 1.5.0 (2011-06-29)
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index c986ec7f..bfc825d6 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -3970,6 +3970,9 @@ Multiply the point @var{u} of the elliptic curve described by
@node Miscellaneous
@section Miscellaneous
+An MPI data type is allowed to be ``misused'' to store an arbitrary
+value. Two functions implement this kludge:
+
@deftypefun gcry_mpi_t gcry_mpi_set_opaque (@w{gcry_mpi_t @var{a}}, @w{void *@var{p}}, @w{unsigned int @var{nbits}})
Store @var{nbits} of the value @var{p} points to in @var{a} and mark
@@ -3980,7 +3983,6 @@ math calculation and is only used to store an arbitrary bit pattern in
WARNING: Never use an opaque MPI for actual math operations. The only
valid functions are gcry_mpi_get_opaque and gcry_mpi_release. Use
gcry_mpi_scan to convert a string of arbitrary bytes into an MPI.
-
@end deftypefun
@deftypefun {void *} gcry_mpi_get_opaque (@w{gcry_mpi_t @var{a}}, @w{unsigned int *@var{nbits}})
@@ -3991,23 +3993,46 @@ size in @var{nbits}. Note that the returned pointer is still owned by
MPI.
@end deftypefun
-@deftypefun void gcry_mpi_set_flag (@w{gcry_mpi_t @var{a}}, @w{enum gcry_mpi_flag @var{flag}})
+Each MPI has an associated set of flags for special purposes. The
+currently defined flags are:
-Set the @var{flag} for the MPI @var{a}. Currently only the flag
-@code{GCRYMPI_FLAG_SECURE} is allowed to convert @var{a} into an MPI
-stored in "secure memory".
-@end deftypefun
+@table @code
+@item GCRYMPI_FLAG_SECURE
+Setting this flag converts @var{a} into an MPI stored in "secure
+memory". Clearing this flag is not allowed.
+@item GCRYMPI_FLAG_OPAQUE
+This is an interanl flag, indicating the an opaque valuue and not an
+integer is stored. This is an read-only flag; it may not be set or
+cleared.
+@item GCRYMPI_FLAG_IMMUTABLE
+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.
+@end table
-@deftypefun void gcry_mpi_clear_flag (@w{gcry_mpi_t @var{a}}, @w{enum gcry_mpi_flag @var{flag}})
+@deftypefun void gcry_mpi_set_flag (@w{gcry_mpi_t @var{a}}, @
+ @w{enum gcry_mpi_flag @var{flag}})
-Clear @var{flag} for the multi-precision-integers @var{a}. Note that
-this function is currently useless as no flags are allowed.
+Set the @var{flag} for the MPI @var{a}. The only allowed flags are
+@code{GCRYMPI_FLAG_SECURE} and @code{GCRYMPI_FLAG_IMMUTABLE}.
@end deftypefun
-@deftypefun int gcry_mpi_get_flag (@w{gcry_mpi_t @var{a}}, @w{enum gcry_mpi_flag @var{flag}})
+@deftypefun void gcry_mpi_clear_flag (@w{gcry_mpi_t @var{a}}, @
+ @w{enum gcry_mpi_flag @var{flag}})
-Return true when the @var{flag} is set for @var{a}.
+Clear @var{flag} for the multi-precision-integers @var{a}. The only
+allowed flag is @code{GCRYMPI_FLAG_IMMUTABLE}.
@end deftypefun
+o
+@deftypefun int gcry_mpi_get_flag (@w{gcry_mpi_t @var{a}}, @
+ @w{enum gcry_mpi_flag @var{flag}})
+
+Return true if @var{flag} is set for @var{a}.
+@end deftypefun
+
+
+To put a random value into an MPI, the following convenience function
+may be used:
@deftypefun void gcry_mpi_randomize (@w{gcry_mpi_t @var{w}}, @w{unsigned int @var{nbits}}, @w{enum gcry_random_level @var{level}})
diff --git a/mpi/mpi-bit.c b/mpi/mpi-bit.c
index cdc6b0b3..74042e89 100644
--- a/mpi/mpi-bit.c
+++ b/mpi/mpi-bit.c
@@ -1,5 +1,6 @@
/* mpi-bit.c - MPI bit level functions
* Copyright (C) 1998, 1999, 2001, 2002, 2006 Free Software Foundation, Inc.
+ * Copyright (C) 2013 g10 Code GmbH
*
* This file is part of Libgcrypt.
*
@@ -117,6 +118,12 @@ gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n )
{
unsigned int limbno, bitno;
+ if (mpi_is_immutable (a))
+ {
+ mpi_immutable_failed ();
+ return;
+ }
+
limbno = n / BITS_PER_MPI_LIMB;
bitno = n % BITS_PER_MPI_LIMB;
@@ -136,6 +143,12 @@ gcry_mpi_set_highbit( gcry_mpi_t a, unsigned int n )
{
unsigned int limbno, bitno;
+ if (mpi_is_immutable (a))
+ {
+ mpi_immutable_failed ();
+ return;
+ }
+
limbno = n / BITS_PER_MPI_LIMB;
bitno = n % BITS_PER_MPI_LIMB;
@@ -156,18 +169,23 @@ gcry_mpi_set_highbit( gcry_mpi_t a, unsigned int n )
void
gcry_mpi_clear_highbit( gcry_mpi_t a, unsigned int n )
{
- unsigned int limbno, bitno;
+ unsigned int limbno, bitno;
- limbno = n / BITS_PER_MPI_LIMB;
- bitno = n % BITS_PER_MPI_LIMB;
+ if (mpi_is_immutable (a))
+ {
+ mpi_immutable_failed ();
+ return;
+ }
- if( limbno >= a->nlimbs )
- return; /* not allocated, therefore no need to clear bits
- :-) */
+ limbno = n / BITS_PER_MPI_LIMB;
+ bitno = n % BITS_PER_MPI_LIMB;
+
+ if( limbno >= a->nlimbs )
+ return; /* not allocated, therefore no need to clear bits :-) */
- for( ; bitno < BITS_PER_MPI_LIMB; bitno++ )
- a->d[limbno] &= ~(A_LIMB_1 << bitno);
- a->nlimbs = limbno+1;
+ for( ; bitno < BITS_PER_MPI_LIMB; bitno++ )
+ a->d[limbno] &= ~(A_LIMB_1 << bitno);
+ a->nlimbs = limbno+1;
}
/****************
@@ -176,14 +194,20 @@ gcry_mpi_clear_highbit( gcry_mpi_t a, unsigned int n )
void
gcry_mpi_clear_bit( gcry_mpi_t a, unsigned int n )
{
- unsigned int limbno, bitno;
+ unsigned int limbno, bitno;
- limbno = n / BITS_PER_MPI_LIMB;
- bitno = n % BITS_PER_MPI_LIMB;
+ if (mpi_is_immutable (a))
+ {
+ mpi_immutable_failed ();
+ return;
+ }
- if( limbno >= a->nlimbs )
- return; /* don't need to clear this bit, it's to far to left */
- a->d[limbno] &= ~(A_LIMB_1 << bitno);
+ limbno = n / BITS_PER_MPI_LIMB;
+ bitno = n % BITS_PER_MPI_LIMB;
+
+ if (limbno >= a->nlimbs)
+ return; /* Don't need to clear this bit, it's far too left. */
+ a->d[limbno] &= ~(A_LIMB_1 << bitno);
}
@@ -194,19 +218,26 @@ gcry_mpi_clear_bit( gcry_mpi_t a, unsigned int n )
void
_gcry_mpi_rshift_limbs( gcry_mpi_t a, unsigned int count )
{
- mpi_ptr_t ap = a->d;
- mpi_size_t n = a->nlimbs;
- unsigned int i;
+ mpi_ptr_t ap = a->d;
+ mpi_size_t n = a->nlimbs;
+ unsigned int i;
- if( count >= n ) {
- a->nlimbs = 0;
- return;
+ if (mpi_is_immutable (a))
+ {
+ mpi_immutable_failed ();
+ return;
}
- for( i = 0; i < n - count; i++ )
- ap[i] = ap[i+count];
- ap[i] = 0;
- a->nlimbs -= count;
+ if (count >= n)
+ {
+ a->nlimbs = 0;
+ return;
+ }
+
+ for( i = 0; i < n - count; i++ )
+ ap[i] = ap[i+count];
+ ap[i] = 0;
+ a->nlimbs -= count;
}
@@ -221,6 +252,12 @@ gcry_mpi_rshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n )
unsigned int nlimbs = (n/BITS_PER_MPI_LIMB);
unsigned int nbits = (n%BITS_PER_MPI_LIMB);
+ if (mpi_is_immutable (x))
+ {
+ mpi_immutable_failed ();
+ return;
+ }
+
if ( x == a )
{
/* In-place operation. */
@@ -328,6 +365,12 @@ gcry_mpi_lshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n )
unsigned int nlimbs = (n/BITS_PER_MPI_LIMB);
unsigned int nbits = (n%BITS_PER_MPI_LIMB);
+ if (mpi_is_immutable (x))
+ {
+ mpi_immutable_failed ();
+ return;
+ }
+
if (x == a && !n)
return; /* In-place shift with an amount of zero. */
diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c
index a3435ed1..06d5553e 100644
--- a/mpi/mpicoder.c
+++ b/mpi/mpicoder.c
@@ -305,6 +305,12 @@ _gcry_mpi_set_buffer (gcry_mpi_t a, const void *buffer_arg,
int nlimbs;
int i;
+ if (mpi_is_immutable (a))
+ {
+ mpi_immutable_failed ();
+ return;
+ }
+
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
RESIZE_IF_NEEDED(a, nlimbs);
a->sign = sign;
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index d410d90b..64a2f7e1 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -163,8 +163,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;
}
@@ -179,11 +184,21 @@ _gcry_mpi_free( gcry_mpi_t a )
{
_gcry_mpi_free_limb_space(a->d, a->alloced);
}
- if ((a->flags & ~7))
- log_bug("invalid flag value in mpi\n");
+ /* 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)))
+ log_bug("invalid flag value in mpi_free\n");
gcry_free(a);
}
+
+void
+_gcry_mpi_immutable_failed (void)
+{
+ log_info ("Warning: trying to change immutable MPI\n");
+}
+
+
static void
mpi_set_secure( gcry_mpi_t a )
{
@@ -303,6 +318,11 @@ 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;
@@ -324,6 +344,11 @@ gcry_mpi_set( gcry_mpi_t w, gcry_mpi_t u)
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;
@@ -342,6 +367,11 @@ gcry_mpi_set_ui( gcry_mpi_t w, unsigned long u)
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;
@@ -426,6 +456,11 @@ gcry_mpi_randomize( gcry_mpi_t w,
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)
@@ -446,7 +481,8 @@ 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_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");
}
@@ -459,6 +495,7 @@ gcry_mpi_clear_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
switch (flag)
{
+ case GCRYMPI_FLAG_IMMUTABLE: a->flags &= ~16; break;
case GCRYMPI_FLAG_SECURE:
case GCRYMPI_FLAG_OPAQUE:
default: log_bug("invalid flag value\n");
@@ -472,6 +509,7 @@ gcry_mpi_get_flag( gcry_mpi_t a, enum gcry_mpi_flag 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);
default: log_bug("invalid flag value\n");
}
/*NOTREACHED*/
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 57b841eb..9f6438ce 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -454,9 +454,10 @@ enum gcry_mpi_format
enum gcry_mpi_flag
{
GCRYMPI_FLAG_SECURE = 1, /* Allocate the number in "secure" memory. */
- GCRYMPI_FLAG_OPAQUE = 2 /* The number is not a real one but just
+ 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. */
};
diff --git a/src/mpi.h b/src/mpi.h
index 23afa683..93ad8897 100644
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -69,7 +69,8 @@ struct gcry_mpi
int sign; /* Indicates a negative number and is also used
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 2: The limb is a pointer to some m_alloced data.*/
+ /* Bit 4: Const MPI - the MPI may not be modified. */
mpi_limb_t *d; /* Array with the limbs */
};
@@ -104,8 +105,12 @@ struct gcry_mpi
gcry_mpi_t _gcry_mpi_copy( gcry_mpi_t a );
#endif
-#define mpi_is_opaque(a) ((a) && ((a)->flags&4))
-#define mpi_is_secure(a) ((a) && ((a)->flags&1))
+void _gcry_mpi_immutable_failed (void);
+#define mpi_immutable_failed() _gcry_mpi_immutable_failed ()
+
+#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))
#define mpi_clear(a) _gcry_mpi_clear ((a))
#define mpi_alloc_like(a) _gcry_mpi_alloc_like((a))
#define mpi_snatch(a,b) _gcry_mpi_snatch ((a),(b))