diff options
author | Werner Koch <wk@gnupg.org> | 2008-12-02 12:39:01 +0000 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2008-12-02 12:39:01 +0000 |
commit | 80e3857a2ca8f2577c40c6902adfa08bfb937ad9 (patch) | |
tree | 1de6eba999788013f8f502b3b4a2339ce92cd6dc /mpi/mpi-pow.c | |
parent | 1542e469807398149e2cab3b8f9856121493637b (diff) | |
download | libgcrypt-80e3857a2ca8f2577c40c6902adfa08bfb937ad9.tar.gz |
Fix bug 977.
Diffstat (limited to 'mpi/mpi-pow.c')
-rw-r--r-- | mpi/mpi-pow.c | 88 |
1 files changed, 38 insertions, 50 deletions
diff --git a/mpi/mpi-pow.c b/mpi/mpi-pow.c index dc75df52..24865543 100644 --- a/mpi/mpi-pow.c +++ b/mpi/mpi-pow.c @@ -40,11 +40,15 @@ void gcry_mpi_powm (gcry_mpi_t res, gcry_mpi_t base, gcry_mpi_t expo, gcry_mpi_t mod) { + /* Pointer to the limbs of the arguments, their size and signs. */ mpi_ptr_t rp, ep, mp, bp; mpi_size_t esize, msize, bsize, rsize; int msign, bsign, rsign; - int esec, msec, bsec, rsec; + /* Flags telling the secure allocation status of the arguments. */ + int esec, msec, bsec, rsec; + /* Size of the result including space for temporary values. */ mpi_size_t size; + /* Helper. */ int mod_shift_cnt; int negative_result; mpi_ptr_t mp_marker = NULL; @@ -55,7 +59,6 @@ gcry_mpi_powm (gcry_mpi_t res, unsigned int bp_nlimbs = 0; unsigned int ep_nlimbs = 0; unsigned int xp_nlimbs = 0; - int assign_rp = 0; mpi_ptr_t tspace = NULL; mpi_size_t tsize = 0; @@ -127,54 +130,43 @@ gcry_mpi_powm (gcry_mpi_t res, goto leave; } - if (res->alloced < size) + + /* Make BASE, EXPO and MOD not overlap with RES. */ + if ( rp == bp ) { - /* We have to allocate more space for RES. If any of the input - parameters are identical to RES, defer deallocation of the - old space. */ - if ( rp == ep || rp == mp || rp == bp ) - { - rp = mpi_alloc_limb_space( size, rsec ); - assign_rp = 1; - } - else - { - mpi_resize( res, size ); - rp = res->d; - } + /* RES and BASE are identical. Allocate temp. space for BASE. */ + gcry_assert (!bp_marker); + bp_nlimbs = bsec? bsize:0; + bp = bp_marker = mpi_alloc_limb_space( bsize, bsec ); + MPN_COPY(bp, rp, bsize); } - else - { - /* Make BASE, EXPO and MOD not overlap with RES. */ - if ( rp == bp ) - { - /* RES and BASE are identical. Allocate temp. space for BASE. */ - gcry_assert (!bp_marker); - bp_nlimbs = bsec? bsize:0; - bp = bp_marker = mpi_alloc_limb_space( bsize, bsec ); - MPN_COPY(bp, rp, bsize); - } - if ( rp == ep ) - { - /* RES and EXPO are identical. Allocate temp. space for EXPO. */ - ep_nlimbs = esec? esize:0; - ep = ep_marker = mpi_alloc_limb_space( esize, esec ); - MPN_COPY(ep, rp, esize); - } - if ( rp == mp ) - { - /* RES and MOD are identical. Allocate temporary space for MOD.*/ - gcry_assert (!mp_marker); - mp_nlimbs = msec?msize:0; - mp = mp_marker = mpi_alloc_limb_space( msize, msec ); - MPN_COPY(mp, rp, msize); - } + if ( rp == ep ) + { + /* RES and EXPO are identical. Allocate temp. space for EXPO. */ + ep_nlimbs = esec? esize:0; + ep = ep_marker = mpi_alloc_limb_space( esize, esec ); + MPN_COPY(ep, rp, esize); + } + if ( rp == mp ) + { + /* RES and MOD are identical. Allocate temporary space for MOD.*/ + gcry_assert (!mp_marker); + mp_nlimbs = msec?msize:0; + mp = mp_marker = mpi_alloc_limb_space( msize, msec ); + MPN_COPY(mp, rp, msize); + } + + /* Copy base to the result. */ + if (res->alloced < size) + { + mpi_resize (res, size); + rp = res->d; } - MPN_COPY ( rp, bp, bsize ); rsize = bsize; rsign = bsign; + /* Main processing. */ { mpi_size_t i; mpi_ptr_t xp; @@ -285,12 +277,8 @@ gcry_mpi_powm (gcry_mpi_t res, rsize++; } } - else - { - MPN_COPY( res->d, rp, rsize); - rp = res->d; - } + gcry_assert (res->d == rp); if ( rsize >= msize ) { _gcry_mpih_divrem(rp + msize, 0, rp, rsize, mp, msize); @@ -305,6 +293,7 @@ gcry_mpi_powm (gcry_mpi_t res, _gcry_mpih_release_karatsuba_ctx (&karactx ); } + /* Fixup for negative results. */ if ( negative_result && rsize ) { if ( mod_shift_cnt ) @@ -314,12 +303,11 @@ gcry_mpi_powm (gcry_mpi_t res, rsign = msign; MPN_NORMALIZE(rp, rsize); } + gcry_assert (res->d == rp); res->nlimbs = rsize; res->sign = rsign; leave: - if (assign_rp) - _gcry_mpi_assign_limb_space( res, rp, size ); if (mp_marker) _gcry_mpi_free_limb_space( mp_marker, mp_nlimbs ); if (bp_marker) |