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);
|
void freebn(Bignum b);
|
||||||
Bignum modpow(Bignum base, Bignum exp, Bignum mod);
|
Bignum modpow(Bignum base, Bignum exp, Bignum mod);
|
||||||
Bignum modmul(Bignum a, Bignum b, 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);
|
void decbn(Bignum n);
|
||||||
extern Bignum Zero, One;
|
extern Bignum Zero, One;
|
||||||
Bignum bignum_from_bytes(const unsigned char *data, int nbytes);
|
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 ssh1_read_bignum(const unsigned char *data, int len, Bignum * result);
|
||||||
int bignum_bitcount(Bignum bn);
|
int bignum_bitcount(Bignum bn);
|
||||||
int ssh1_bignum_length(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 modinv(Bignum number, Bignum modulus);
|
||||||
Bignum bignum_bitmask(Bignum number);
|
Bignum bignum_bitmask(Bignum number);
|
||||||
Bignum bignum_rshift(Bignum number, int shift);
|
Bignum bignum_rshift(Bignum number, int shift);
|
||||||
|
Bignum bignum_lshift(Bignum number, int shift);
|
||||||
int bignum_cmp(Bignum a, Bignum b);
|
int bignum_cmp(Bignum a, Bignum b);
|
||||||
char *bignum_decimal(Bignum x);
|
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;
|
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.
|
* Compute p % mod.
|
||||||
* The most significant word of mod MUST be non-zero.
|
* 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;
|
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
|
* Read an SSH-1-format bignum from a data buffer. Return the number
|
||||||
* of bytes consumed, or -1 if there wasn't enough data.
|
* of bytes consumed, or -1 if there wasn't enough data.
|
||||||
@ -1375,6 +1438,45 @@ Bignum bignum_rshift(Bignum a, int shift)
|
|||||||
return ret;
|
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.
|
* Non-modular multiplication and addition.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user