mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-05-28 15:24:49 -05:00
Some extra bignum functions: modsub, lshift, random_in_range.
This commit is contained in:
parent
66970c4258
commit
7d1c30cd50
3
ssh.h
3
ssh.h
@ -515,9 +515,11 @@ Bignum bignum_from_long(unsigned long n);
|
||||
void freebn(Bignum b);
|
||||
Bignum modpow(Bignum base, Bignum exp, Bignum mod);
|
||||
Bignum modmul(Bignum a, Bignum b, Bignum mod);
|
||||
Bignum modsub(const Bignum a, const Bignum b, const Bignum n);
|
||||
void decbn(Bignum n);
|
||||
extern Bignum Zero, One;
|
||||
Bignum bignum_from_bytes(const unsigned char *data, int nbytes);
|
||||
Bignum bignum_random_in_range(const Bignum lower, const Bignum upper);
|
||||
int ssh1_read_bignum(const unsigned char *data, int len, Bignum * result);
|
||||
int bignum_bitcount(Bignum bn);
|
||||
int ssh1_bignum_length(Bignum bn);
|
||||
@ -538,6 +540,7 @@ Bignum bigmod(Bignum a, Bignum b);
|
||||
Bignum modinv(Bignum number, Bignum modulus);
|
||||
Bignum bignum_bitmask(Bignum number);
|
||||
Bignum bignum_rshift(Bignum number, int shift);
|
||||
Bignum bignum_lshift(Bignum number, int shift);
|
||||
int bignum_cmp(Bignum a, Bignum b);
|
||||
char *bignum_decimal(Bignum x);
|
||||
|
||||
|
102
sshbn.c
102
sshbn.c
@ -1092,6 +1092,38 @@ Bignum modmul(Bignum p, Bignum q, Bignum mod)
|
||||
return result;
|
||||
}
|
||||
|
||||
Bignum modsub(const Bignum a, const Bignum b, const Bignum n)
|
||||
{
|
||||
Bignum a1, b1, ret;
|
||||
|
||||
if (bignum_cmp(a, n) >= 0) a1 = bigmod(a, n);
|
||||
else a1 = a;
|
||||
if (bignum_cmp(b, n) >= 0) b1 = bigmod(b, n);
|
||||
else b1 = b;
|
||||
|
||||
if (bignum_cmp(a1, b1) >= 0) /* a >= b */
|
||||
{
|
||||
ret = bigsub(a1, b1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Handle going round the corner of the modulus without having
|
||||
* negative support in Bignum */
|
||||
Bignum tmp = bigsub(n, b1);
|
||||
if (tmp) {
|
||||
ret = bigadd(tmp, a1);
|
||||
freebn(tmp);
|
||||
} else {
|
||||
ret = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (a != a1) freebn(a1);
|
||||
if (b != b1) freebn(b1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute p % mod.
|
||||
* The most significant word of mod MUST be non-zero.
|
||||
@ -1201,6 +1233,37 @@ Bignum bignum_from_bytes(const unsigned char *data, int nbytes)
|
||||
return result;
|
||||
}
|
||||
|
||||
Bignum bignum_random_in_range(const Bignum lower, const Bignum upper)
|
||||
{
|
||||
Bignum ret = NULL;
|
||||
int upper_len = bignum_bitcount(upper);
|
||||
int upper_bytes = upper_len / 8;
|
||||
int upper_bits = upper_len % 8;
|
||||
if (upper_bits) ++upper_bytes;
|
||||
|
||||
do {
|
||||
unsigned char *bytes;
|
||||
int i;
|
||||
|
||||
if (ret) freebn(ret);
|
||||
|
||||
bytes = snewn(upper_bytes, unsigned char);
|
||||
for (i = 0; i < upper_bytes; ++i)
|
||||
{
|
||||
bytes[i] = (unsigned char)random_byte();
|
||||
}
|
||||
/* Mask the top to reduce failure rate to 50/50 */
|
||||
if (upper_bits)
|
||||
{
|
||||
bytes[i - 1] &= 0xFF >> (8 - upper_bits);
|
||||
}
|
||||
|
||||
ret = bignum_from_bytes(bytes, upper_bytes);
|
||||
} while (bignum_cmp(ret, lower) < 0 || bignum_cmp(ret, upper) > 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read an SSH-1-format bignum from a data buffer. Return the number
|
||||
* of bytes consumed, or -1 if there wasn't enough data.
|
||||
@ -1375,6 +1438,45 @@ Bignum bignum_rshift(Bignum a, int shift)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Left-shift one bignum to form another.
|
||||
*/
|
||||
Bignum bignum_lshift(Bignum a, int shift)
|
||||
{
|
||||
Bignum ret;
|
||||
int bits, shiftWords, shiftBits;
|
||||
|
||||
assert(shift >= 0);
|
||||
|
||||
bits = bignum_bitcount(a) + shift;
|
||||
ret = newbn((bits + BIGNUM_INT_BITS - 1) / BIGNUM_INT_BITS);
|
||||
if (!ret) return NULL;
|
||||
|
||||
shiftWords = shift / BIGNUM_INT_BITS;
|
||||
shiftBits = shift % BIGNUM_INT_BITS;
|
||||
|
||||
if (shiftBits == 0)
|
||||
{
|
||||
memcpy(&ret[1 + shiftWords], &a[1], sizeof(BignumInt) * a[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
BignumInt carry = 0;
|
||||
|
||||
/* Remember that Bignum[0] is length, so add 1 */
|
||||
for (i = shiftWords + 1; i < ((int)a[0]) + shiftWords + 1; ++i)
|
||||
{
|
||||
BignumInt from = a[i - shiftWords];
|
||||
ret[i] = (from << shiftBits) | carry;
|
||||
carry = from >> (BIGNUM_INT_BITS - shiftBits);
|
||||
}
|
||||
if (carry) ret[i] = carry;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-modular multiplication and addition.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user