1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 01:02:24 +00:00

Fix construction of the output bignum in Curve25519 kex.

We were doing an endianness flip on the output elliptic-curve point.
Endianness flips of bignums, of course, have to specify how many bytes
they're imagining the value to have (that's how you decide whether to
convert 0xA1A2 into 0xA2A1 or 0xA2A10000 or 0xA2A1000000000000 etc),
and we had chosen our byte count based on the highest set bit in the
_output value_ - but in fact we should have chosen it based on the
size of the curve's modulus, leading to a failure about 1/256 of the
time when the MSB happened to come out zero so the two byte counts
differed.

(Also added a missing smemclr, while I was there.)
This commit is contained in:
Simon Tatham 2015-05-19 09:54:17 +01:00
parent a209b9044e
commit 686ce91905

View File

@ -2690,15 +2690,30 @@ static Bignum ecdh_calculate(const Bignum private,
p->x = NULL;
if (p->curve->type == EC_MONTGOMERY) {
/* Do conversion in network byte order */
/*
* Endianness-swap. The Curve25519 algorithm definition
* assumes you were doing your computation in arrays of 32
* little-endian bytes, and now specifies that you take your
* final one of those and convert it into a bignum in
* _network_ byte order, i.e. big-endian.
*
* In particular, the spec says, you convert the _whole_ 32
* bytes into a bignum. That is, on the rare occasions that
* p->x has come out with the most significant 8 bits zero, we
* have to imagine that being represented by a 32-byte string
* with the last byte being zero, so that has to be converted
* into an SSH-2 bignum with the _low_ byte zero, i.e. a
* multiple of 256.
*/
int i;
int bytes = (bignum_bitcount(ret)+7) / 8;
int bytes = (p->curve->fieldBits+7) / 8;
unsigned char *byteorder = snewn(bytes, unsigned char);
for (i = 0; i < bytes; ++i) {
byteorder[i] = bignum_byte(ret, i);
}
freebn(ret);
ret = bignum_from_bytes(byteorder, bytes);
smemclr(byteorder, bytes);
sfree(byteorder);
}