X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/f85d818695cf93284f79dcb79263927a4b8b01d6..7961438be4add9289b13b3471e4cd7943399f5ae:/sshbn.c diff --git a/sshbn.c b/sshbn.c index 7c6b13a1..580dd6f6 100644 --- a/sshbn.c +++ b/sshbn.c @@ -1385,6 +1385,78 @@ Bignum bigsub(Bignum a, Bignum b) } /* + * Return a bignum which is the result of shifting another left by N bits. + * If N is negative then you get a right shift instead. + */ +Bignum biglsl(Bignum x, int n) +{ + Bignum d; + unsigned o, i; + + if (!n || !x[0]) + return copybn(x); + else if (n < 0) + return biglsr(x, -n); + + o = n/BIGNUM_INT_BITS; + n %= BIGNUM_INT_BITS; + d = newbn(x[0] + o + !!n); + + for (i = 1; i <= o; i++) + d[i] = 0; + + if (!n) { + for (i = 1; i <= x[0]; i++) + d[o + i] = x[i]; + } else { + d[o + 1] = x[1] << n; + for (i = 2; i <= x[0]; i--) + d[o + i] = (x[i] << n) | (x[i - 1] >> (BIGNUM_INT_BITS - n)); + d[o + x[0] + 1] = x[x[0]] >> (BIGNUM_INT_BITS - n); + } + + bn_restore_invariant(d); + return d; +} + +/* + * Return a bignum which is the result of shifting another right by N bits + * (discarding the least significant N bits, and shifting zeroes in at the + * most significant end). If N is negative then you get a left shift + * instead. + */ +Bignum biglsr(Bignum x, int n) +{ + Bignum d; + unsigned o, i; + + if (!n || !x[0]) + return copybn(x); + else if (n < 0) + return biglsl(x, -n); + + o = n/BIGNUM_INT_BITS; + n %= BIGNUM_INT_BITS; + d = newbn(x[0]); + + if (!n) { + for (i = o + 1; i <= x[0]; i++) + d[i - o] = x[i]; + } else { + d[1] = x[o + 1] >> n; + for (i = o + 2; i < x[0]; i++) + d[i - o] = x[ + d[o + x[0] + 1] = x[x[0]] >> (BIGNUM_INT_BITS - n); + for (i = x[0]; i > 1; i--) + d[o + i] = (x[i] << n) | (x[i - 1] >> (BIGNUM_INT_BITS - n)); + d[o + 1] = x[1] << n; + } + + bn_restore_invariant(d); + return d; +} + +/* * Create a bignum which is the bitmask covering another one. That * is, the smallest integer which is >= N and is also one less than * a power of two.