From c6e42e7ec3d1046969d783c443c13aad7cb61bb8 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 17 Oct 2017 15:00:08 +0200 Subject: 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 --- NEWS | 5 +++++ doc/gcrypt.texi | 14 +++++++++++++- mpi/mpiutil.c | 43 +++++++++++++++++++++++++++++++------------ src/gcrypt-int.h | 4 ++-- src/gcrypt.h.in | 4 ++++ src/libgcrypt.def | 2 +- src/libgcrypt.vers | 1 + src/visibility.c | 2 +- src/visibility.h | 2 ++ tests/mpitests.c | 30 ++++++++++++++++++++++++++++++ 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); + } -- cgit v1.2.1