1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-06-30 19:12:48 -05:00

mpint: add mp_[lr]shift_safe_into functions.

There was previously no safe left shift at all, which is an omission.
And rshift_safe_into was an odd thing to be missing, so while I'm
here, I've added it on the basis that it will probably be useful
sooner or later.
This commit is contained in:
Simon Tatham
2020-02-18 18:55:56 +00:00
parent dec79cf152
commit 18678ba9bc
4 changed files with 71 additions and 4 deletions

54
mpint.c
View File

@ -1132,13 +1132,11 @@ mp_int *mp_rshift_fixed(mp_int *x, size_t bits)
* by a power of 2 words, using the usual bit twiddling to make the
* whole shift conditional on the appropriate bit of n.
*/
mp_int *mp_rshift_safe(mp_int *x, size_t bits)
static void mp_rshift_safe_in_place(mp_int *r, size_t bits)
{
size_t wordshift = bits / BIGNUM_INT_BITS;
size_t bitshift = bits % BIGNUM_INT_BITS;
mp_int *r = mp_copy(x);
unsigned clear = (r->nw - wordshift) >> (CHAR_BIT * sizeof(size_t) - 1);
mp_cond_clear(r, clear);
@ -1163,10 +1161,60 @@ mp_int *mp_rshift_safe(mp_int *x, size_t bits)
r->w[i] ^= (r->w[i] ^ w) & mask;
}
}
}
mp_int *mp_rshift_safe(mp_int *x, size_t bits)
{
mp_int *r = mp_copy(x);
mp_rshift_safe_in_place(r, bits);
return r;
}
void mp_rshift_safe_into(mp_int *r, mp_int *x, size_t bits)
{
mp_copy_into(r, x);
mp_rshift_safe_in_place(r, bits);
}
static void mp_lshift_safe_in_place(mp_int *r, size_t bits)
{
size_t wordshift = bits / BIGNUM_INT_BITS;
size_t bitshift = bits % BIGNUM_INT_BITS;
/*
* Same strategy as mp_rshift_safe_in_place, but of course the
* other way up.
*/
unsigned clear = (r->nw - wordshift) >> (CHAR_BIT * sizeof(size_t) - 1);
mp_cond_clear(r, clear);
for (unsigned bit = 0; r->nw >> bit; bit++) {
size_t word_offset = 1 << bit;
BignumInt mask = -(BignumInt)((wordshift >> bit) & 1);
for (size_t i = r->nw; i-- > 0 ;) {
BignumInt w = mp_word(r, i - word_offset);
r->w[i] ^= (r->w[i] ^ w) & mask;
}
}
size_t downshift = BIGNUM_INT_BITS - bitshift;
size_t no_shift = (downshift >> BIGNUM_INT_BITS_BITS);
downshift &= ~-(size_t)no_shift;
BignumInt downshifted_mask = ~-(BignumInt)no_shift;
for (size_t i = r->nw; i-- > 0 ;) {
r->w[i] = (r->w[i] << bitshift) |
((mp_word(r, i-1) >> downshift) & downshifted_mask);
}
}
void mp_lshift_safe_into(mp_int *r, mp_int *x, size_t bits)
{
mp_copy_into(r, x);
mp_lshift_safe_in_place(r, bits);
}
void mp_reduce_mod_2to(mp_int *x, size_t p)
{
size_t word = p / BIGNUM_INT_BITS;