diff options
Diffstat (limited to 'libraries/integer-gmp/cbits/wrappers.c')
-rw-r--r-- | libraries/integer-gmp/cbits/wrappers.c | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/libraries/integer-gmp/cbits/wrappers.c b/libraries/integer-gmp/cbits/wrappers.c index 446a681388..8f147ad0c1 100644 --- a/libraries/integer-gmp/cbits/wrappers.c +++ b/libraries/integer-gmp/cbits/wrappers.c @@ -11,6 +11,7 @@ #include "HsFFI.h" #include "MachDeps.h" +#include "HsIntegerGmp.h" #include <assert.h> #include <stdbool.h> @@ -626,7 +627,7 @@ integer_gmp_powm(mp_limb_t rp[], // result } const mpz_t b = CONST_MPZ_INIT(bp, mp_limb_zero_p(bp,bn) ? 0 : bn); - const mpz_t e = CONST_MPZ_INIT(ep, mp_limb_zero_p(ep,en) ? 0 : en); + const mpz_t e = CONST_MPZ_INIT(ep, en); const mpz_t m = CONST_MPZ_INIT(mp, mn); mpz_t r; @@ -687,6 +688,64 @@ integer_gmp_powm_word(const mp_limb_t b0, // base return integer_gmp_powm1(&b0, !!b0, &e0, !!e0, m0); } +/* version of integer_gmp_powm() based on mpz_powm_sec + * + * With GMP 5.0 or later execution time depends on size of arguments + * and size of result. + * + * 'M' must be odd and 'E' non-negative. + */ +mp_size_t +integer_gmp_powm_sec(mp_limb_t rp[], // result + const mp_limb_t bp[], const mp_size_t bn, // base + const mp_limb_t ep[], const mp_size_t en, // exponent + const mp_limb_t mp[], const mp_size_t mn) // mod +{ + assert(!mp_limb_zero_p(mp,mn)); + assert(mp[0] & 1); + + if ((mn == 1 || mn == -1) && mp[0] == 1) { + rp[0] = 0; + return 1; + } + + if (mp_limb_zero_p(ep,en)) { + rp[0] = 1; + return 1; + } + + assert(en > 0); + + const mpz_t b = CONST_MPZ_INIT(bp, mp_limb_zero_p(bp,bn) ? 0 : bn); + const mpz_t e = CONST_MPZ_INIT(ep, en); + const mpz_t m = CONST_MPZ_INIT(mp, mn); + + mpz_t r; + mpz_init (r); + +#if HAVE_SECURE_POWM == 0 + mpz_powm(r, b, e, m); +#else + mpz_powm_sec(r, b, e, m); +#endif + + const mp_size_t rn = r[0]._mp_size; + + if (rn) { + assert(0 < rn && rn <= mn); + memcpy(rp, r[0]._mp_d, rn*sizeof(mp_limb_t)); + } + + mpz_clear (r); + + if (!rn) { + rp[0] = 0; + return 1; + } + + return rn; +} + /* wrapper around mpz_invert() * |