api: New function gcry_mpi_get_ui.
authorWerner Koch <wk@gnupg.org>
Tue, 17 Oct 2017 13:00:08 +0000 (15:00 +0200)
committerWerner Koch <wk@gnupg.org>
Tue, 17 Oct 2017 13:02:33 +0000 (15:02 +0200)
* 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>
NEWS
doc/gcrypt.texi
mpi/mpiutil.c
src/gcrypt-int.h
src/gcrypt.h.in
src/libgcrypt.def
src/libgcrypt.vers
src/visibility.c
src/visibility.h
tests/mpitests.c

diff --git a/NEWS b/NEWS
index 3e07a94..3b49350 100644 (file)
--- 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]
 ------------------------------------------------
 
index 2bf23a5..a684134 100644 (file)
@@ -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
index 3ae84c3..9dde37f 100644 (file)
 #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;
 }
 
 
index ad719be..e88f868 100644 (file)
@@ -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) )
index 89b1303..76d9b1d 100644 (file)
@@ -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) )
index a76b377..6239a95 100644 (file)
@@ -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
index 1aa830f..edf8a76 100644 (file)
@@ -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;
index 104c70d..44972a1 100644 (file)
@@ -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));
 }
index df2caf6..9c9fa87 100644 (file)
@@ -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
index 18156d1..9b4a66c 100644 (file)
@@ -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);
+
 }