summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2017-10-17 15:00:08 +0200
committerWerner Koch <wk@gnupg.org>2017-10-17 15:02:33 +0200
commitc6e42e7ec3d1046969d783c443c13aad7cb61bb8 (patch)
tree25a50e8a5174be9244841fa96fe037185f23270f
parente4dc458b0b7dc9b8417a2177ef17822d9b9064ec (diff)
downloadlibgcrypt-c6e42e7ec3d1046969d783c443c13aad7cb61bb8.tar.gz
api: New function gcry_mpi_get_ui.
* src/gcrypt.h.in (gcry_mpi_get_ui): New. (mpi_get_ui): New macro. * src/libgcrypt.def, src/libgcrypt.vers: Add new function. * src/visibility.c (gcry_mpi_get_ui): New. * src/visibility.h: Mark that function. (gcry_mpi_get_ui): New. * mpi/mpiutil.c (MY_UINT_MAX): New macro. (_gcry_mpi_get_ui): Re-implemented. This function existed but was never imported or used. * tests/mpitests.c (test_maxsize): Add some test for this function. -- Note that in libgcrypt.def the cardinal 91 is used which was never used in the past. Signed-off-by: Werner Koch <wk@gnupg.org>
-rw-r--r--NEWS5
-rw-r--r--doc/gcrypt.texi14
-rw-r--r--mpi/mpiutil.c43
-rw-r--r--src/gcrypt-int.h4
-rw-r--r--src/gcrypt.h.in4
-rw-r--r--src/libgcrypt.def2
-rw-r--r--src/libgcrypt.vers1
-rw-r--r--src/visibility.c2
-rw-r--r--src/visibility.h2
-rw-r--r--tests/mpitests.c30
10 files changed, 90 insertions, 17 deletions
diff --git a/NEWS b/NEWS
index 3e07a941..3b49350b 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,11 @@ Noteworthy changes in version 1.9.0 (unreleased) [C22/A3/R0]
------------------------------------------------
+ * Interface changes relative to the 1.8.0 release:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ gcry_mpi_get_ui NEW function.
+
+
Noteworthy changes in version 1.8.1 (2017-08-27) [C22/A2/R1]
------------------------------------------------
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index 2bf23a55..a6841344 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -4578,6 +4578,18 @@ int} as type for @var{u} and thus it is only possible to set @var{w} to
small values (usually up to the word size of the CPU).
@end deftypefun
+@deftypefun gcry_error_t gcry_mpi_get_ui (@w{unsigned int *@var{w}}, @w{gcry_mpi_t @var{u}})
+
+If @var{u} is not negative and small enough to be stored in an
+@code{unsigned int} variable, store its value at @var{w}. If the
+value does not fit or is negative return GPG_ERR_ERANGE and do not
+change the value stored at @var{w}. Note that this function returns
+an @code{unsigned int} so that this value can immediately be used with
+the bit test functions. This is in contrast to the other "_ui"
+functions which allow for values up to an @code{unsigned long}.
+@end deftypefun
+
+
@deftypefun void gcry_mpi_swap (@w{gcry_mpi_t @var{a}}, @w{gcry_mpi_t @var{b}})
Swap the values of @var{a} and @var{b}.
@@ -5122,7 +5134,7 @@ currently defined flags are:
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
+This is an internal 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
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index 3ae84c30..9dde37fb 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -28,6 +28,21 @@
#include "mpi-internal.h"
#include "mod-source-info.h"
+
+#if SIZEOF_UNSIGNED_INT == 2
+# define MY_UINT_MAX 0xffff
+/* (visual check: 0123 ) */
+#elif SIZEOF_UNSIGNED_INT == 4
+# define MY_UINT_MAX 0xffffffff
+/* (visual check: 01234567 ) */
+#elif SIZEOF_UNSIGNED_INT == 8
+# define MY_UINT_MAX 0xffffffffffffffff
+/* (visual check: 0123456789abcdef ) */
+#else
+# error Need MY_UINT_MAX for this limb size
+#endif
+
+
/* Constants allocated right away at startup. */
static gcry_mpi_t constants[MPI_NUMBER_OF_CONSTANTS];
@@ -539,23 +554,27 @@ _gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u)
return w;
}
+/* If U is non-negative and small enough store it as an unsigned int
+ * at W. If the value does not fit into an unsigned int or is
+ * negative return GPG_ERR_ERANGE. Note that we return an unsigned
+ * int so that the value can be used with the bit test functions; in
+ * contrast the other _ui functions take an unsigned long so that on
+ * some platforms they may accept a larger value. On error the value
+ * at U is not changed. */
gcry_err_code_t
-_gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
+_gcry_mpi_get_ui (unsigned int *w, gcry_mpi_t u)
{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- unsigned long x = 0;
+ mpi_limb_t x;
- if (w->nlimbs > 1)
- err = GPG_ERR_TOO_LARGE;
- else if (w->nlimbs == 1)
- x = w->d[0];
- else
- x = 0;
+ if (u->nlimbs > 1 || u->sign)
+ return GPG_ERR_ERANGE;
- if (! err)
- *u = x;
+ x = (u->nlimbs == 1) ? u->d[0] : 0;
+ if (sizeof (x) > sizeof (unsigned int) && x > MY_UINT_MAX)
+ return GPG_ERR_ERANGE;
- return err;
+ *w = x;
+ return 0;
}
diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h
index ad719be5..e88f8685 100644
--- a/src/gcrypt-int.h
+++ b/src/gcrypt-int.h
@@ -362,7 +362,7 @@ gcry_mpi_t _gcry_mpi_copy (const gcry_mpi_t a);
void _gcry_mpi_snatch (gcry_mpi_t w, gcry_mpi_t u);
gcry_mpi_t _gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u);
gcry_mpi_t _gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u);
-gcry_err_code_t _gcry_mpi_get_ui (gcry_mpi_t w, ulong *u);
+gcry_err_code_t _gcry_mpi_get_ui (unsigned int *w, gcry_mpi_t u);
void _gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b);
int _gcry_mpi_is_neg (gcry_mpi_t a);
void _gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u);
@@ -464,7 +464,7 @@ int _gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
#define mpi_snatch( w, u) _gcry_mpi_snatch( (w), (u) )
#define mpi_set( w, u) _gcry_mpi_set( (w), (u) )
#define mpi_set_ui( w, u) _gcry_mpi_set_ui( (w), (u) )
-#define mpi_get_ui(a,b) _gcry_mpi_get_ui( (a), (b) )
+#define mpi_get_ui(w,u) _gcry_mpi_get_ui( (w), (u) )
#define mpi_swap(a,b) _gcry_mpi_swap ((a),(b))
#define mpi_abs( w ) _gcry_mpi_abs( (w) )
#define mpi_neg( w, u) _gcry_mpi_neg( (w), (u) )
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 89b13036..76d9b1d7 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -587,6 +587,9 @@ gcry_mpi_t gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u);
/* Store the unsigned integer value U in W. */
gcry_mpi_t gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u);
+/* Store U as an unsigned int at W or return GPG_ERR_ERANGE. */
+gpg_error_t gcry_mpi_get_ui (unsigned int *w, gcry_mpi_t u);
+
/* Swap the values of A and B. */
void gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b);
@@ -840,6 +843,7 @@ gcry_mpi_t _gcry_mpi_get_const (int no);
#define mpi_snatch( w, u) gcry_mpi_snatch( (w), (u) )
#define mpi_set( w, u) gcry_mpi_set( (w), (u) )
#define mpi_set_ui( w, u) gcry_mpi_set_ui( (w), (u) )
+#define mpi_get_ui( w, u) gcry_mpi_get_ui( (w), (u) )
#define mpi_abs( w ) gcry_mpi_abs( (w) )
#define mpi_neg( w, u) gcry_mpi_neg( (w), (u) )
#define mpi_cmp( u, v ) gcry_mpi_cmp( (u), (v) )
diff --git a/src/libgcrypt.def b/src/libgcrypt.def
index a76b3775..6239a958 100644
--- a/src/libgcrypt.def
+++ b/src/libgcrypt.def
@@ -118,7 +118,7 @@ EXPORTS
gcry_mpi_set_flag @88
gcry_mpi_clear_flag @89
gcry_mpi_get_flag @90
-
+ gcry_mpi_get_ui @91
gcry_cipher_open @92
gcry_cipher_close @93
diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers
index 1aa830f9..edf8a76a 100644
--- a/src/libgcrypt.vers
+++ b/src/libgcrypt.vers
@@ -108,6 +108,7 @@ GCRYPT_1.6 {
gcry_mpi_ec_dup; gcry_mpi_ec_add; gcry_mpi_ec_sub; gcry_mpi_ec_mul;
gcry_mpi_ec_curve_point; gcry_mpi_ec_decode_point;
gcry_mpi_point_copy;
+ gcry_mpi_get_ui;
gcry_log_debug;
gcry_log_debughex; gcry_log_debugmpi; gcry_log_debugpnt; gcry_log_debugsxp;
diff --git a/src/visibility.c b/src/visibility.c
index 104c70d5..44972a18 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -308,7 +308,7 @@ gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u)
}
gcry_error_t
-gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
+gcry_mpi_get_ui (unsigned int *w, gcry_mpi_t u)
{
return gpg_error (_gcry_mpi_get_ui (w, u));
}
diff --git a/src/visibility.h b/src/visibility.h
index df2caf6f..9c9fa877 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -265,6 +265,7 @@ MARK_VISIBLEX (gcry_mpi_set_highbit)
MARK_VISIBLEX (gcry_mpi_set_opaque)
MARK_VISIBLEX (gcry_mpi_set_opaque_copy)
MARK_VISIBLEX (gcry_mpi_set_ui)
+MARK_VISIBLEX (gcry_mpi_get_ui)
MARK_VISIBLEX (gcry_mpi_snew)
MARK_VISIBLEX (gcry_mpi_sub)
MARK_VISIBLEX (gcry_mpi_sub_ui)
@@ -484,6 +485,7 @@ MARK_VISIBLEX (_gcry_mpi_get_const)
#define gcry_mpi_set_highbit _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_set_opaque _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_set_ui _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_mpi_get_ui _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_snatch _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_snew _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_sub _gcry_USE_THE_UNDERSCORED_FUNCTION
diff --git a/tests/mpitests.c b/tests/mpitests.c
index 18156d1b..9b4a66c2 100644
--- a/tests/mpitests.c
+++ b/tests/mpitests.c
@@ -205,6 +205,7 @@ test_maxsize (void)
{
gpg_error_t err;
gcry_mpi_t a;
+ unsigned int val;
char buffer[2+2048]; /* For PGP: 2 length bytes and 16384 bits. */
memset (buffer, 0x55, sizeof buffer);
@@ -232,7 +233,36 @@ test_maxsize (void)
err = gcry_mpi_scan (&a, GCRYMPI_FMT_PGP, buffer, sizeof buffer, NULL);
if (err)
die ("gcry_mpi_scan did not parse a large PGP: %s\n", gpg_strerror (err));
+
+ /* Let's also test get_ui. */
+ gcry_mpi_set_ui (a, 0);
+ val = 4711;
+ err = gcry_mpi_get_ui (&val, a);
+ if (err || val != 0)
+ die ("gcry_mpi_get_ui failed at %d: %s\n", __LINE__, gpg_strerror (err));
+
+ gcry_mpi_sub_ui (a, a, 1);
+ val = 4711;
+ err = gcry_mpi_get_ui (&val, a);
+ if (gpg_err_code (err) != GPG_ERR_ERANGE || val != 4711)
+ die ("gcry_mpi_get_ui failed at %d: %s\n", __LINE__, gpg_strerror (err));
+
+ gcry_mpi_set_ui (a, 0xffffffff);
+ val = 4711;
+ err = gcry_mpi_get_ui (&val, a);
+ if (err || val != 0xffffffff)
+ die ("gcry_mpi_get_ui failed at %d: %s\n", __LINE__, gpg_strerror (err));
+
+ if (sizeof (val) == 4)
+ {
+ gcry_mpi_add_ui (a, a, 1);
+ err = gcry_mpi_get_ui (&val, a);
+ if (gpg_err_code (err) != GPG_ERR_ERANGE)
+ die ("gcry_mpi_get_ui failed at %d: %s\n", __LINE__,gpg_strerror (err));
+ }
+
gcry_mpi_release (a);
+
}