X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/033a3ded0dcac2688eddf18c2b086b2f7d7f7927..df0870fc8ceb5a8fea66a4d0fe00e7db12317e33:/sshrsa.c diff --git a/sshrsa.c b/sshrsa.c index 64676660..58755089 100644 --- a/sshrsa.c +++ b/sshrsa.c @@ -89,6 +89,20 @@ void rsaencrypt(unsigned char *data, int length, struct RSAKey *key) freebn(b2); } +static void sha512_mpint(SHA512_State * s, Bignum b) +{ + unsigned char lenbuf[4]; + int len; + len = (bignum_bitcount(b) + 8) / 8; + PUT_32BIT(lenbuf, len); + SHA512_Bytes(s, lenbuf, 4); + while (len-- > 0) { + lenbuf[0] = bignum_byte(b, len); + SHA512_Bytes(s, lenbuf, 1); + } + memset(lenbuf, 0, sizeof(lenbuf)); +} + /* * This function is a wrapper on modpow(). It has the same effect * as modpow(), but employs RSA blinding to protect against timing @@ -100,6 +114,11 @@ static Bignum rsa_privkey_op(Bignum input, struct RSAKey *key) Bignum input_blinded, ret_blinded; Bignum ret; + SHA512_State ss; + unsigned char digest512[64]; + int digestused = lenof(digest512); + int hashseq = 0; + /* * Start by inventing a random number chosen uniformly from the * range 2..modulus-1. (We do this by preparing a random number @@ -110,6 +129,10 @@ static Bignum rsa_privkey_op(Bignum input, struct RSAKey *key) * There are timing implications to the potential retries, of * course, but all they tell you is the modulus, which you * already knew.) + * + * To preserve determinism and avoid Pageant needing to share + * the random number pool, we actually generate this `random' + * number by hashing stuff with the private key. */ while (1) { int bits, byte, bitsleft, v; @@ -123,8 +146,35 @@ static Bignum rsa_privkey_op(Bignum input, struct RSAKey *key) byte = 0; bitsleft = 0; while (bits--) { - if (bitsleft <= 0) - bitsleft = 8, byte = random_byte(); + if (bitsleft <= 0) { + bitsleft = 8; + /* + * Conceptually the following few lines are equivalent to + * byte = random_byte(); + */ + if (digestused >= lenof(digest512)) { + unsigned char seqbuf[4]; + PUT_32BIT(seqbuf, hashseq); + SHA512_Init(&ss); + SHA512_Bytes(&ss, "RSA deterministic blinding", 26); + SHA512_Bytes(&ss, seqbuf, sizeof(seqbuf)); + sha512_mpint(&ss, key->private_exponent); + SHA512_Final(&ss, digest512); + hashseq++; + + /* + * Now hash that digest plus the signature + * input. + */ + SHA512_Init(&ss); + SHA512_Bytes(&ss, digest512, sizeof(digest512)); + sha512_mpint(&ss, input); + SHA512_Final(&ss, digest512); + + digestused = 0; + } + byte = digest512[digestused++]; + } v = byte & 1; byte >>= 1; bitsleft--; @@ -316,7 +366,7 @@ unsigned char *rsa_public_blob(struct RSAKey *key, int *len) length = (ssh1_bignum_length(key->modulus) + ssh1_bignum_length(key->exponent) + 4); - ret = smalloc(length); + ret = snewn(length, unsigned char); PUT_32BIT(ret, bignum_bitcount(key->modulus)); pos = 4; @@ -388,7 +438,7 @@ static void *rsa2_newkey(char *data, int len) int slen; struct RSAKey *rsa; - rsa = smalloc(sizeof(struct RSAKey)); + rsa = snew(struct RSAKey); if (!rsa) return NULL; getstring(&data, &len, &p, &slen); @@ -419,7 +469,7 @@ static char *rsa2_fmtkey(void *key) int len; len = rsastr_len(rsa); - p = smalloc(len); + p = snewn(len, char); rsastr_fmt(p, rsa); return p; } @@ -439,7 +489,7 @@ static unsigned char *rsa2_public_blob(void *key, int *len) * (three length fields, 12+7=19). */ bloblen = 19 + elen + mlen; - blob = smalloc(bloblen); + blob = snewn(bloblen, unsigned char); p = blob; PUT_32BIT(p, 7); p += 4; @@ -475,7 +525,7 @@ static unsigned char *rsa2_private_blob(void *key, int *len) * sum of lengths. */ bloblen = 16 + dlen + plen + qlen + ulen; - blob = smalloc(bloblen); + blob = snewn(bloblen, unsigned char); p = blob; PUT_32BIT(p, dlen); p += 4; @@ -523,7 +573,7 @@ static void *rsa2_openssh_createkey(unsigned char **blob, int *len) char **b = (char **) blob; struct RSAKey *rsa; - rsa = smalloc(sizeof(struct RSAKey)); + rsa = snew(struct RSAKey); if (!rsa) return NULL; rsa->comment = NULL; @@ -608,7 +658,7 @@ static char *rsa2_fingerprint(void *key) for (i = 0; i < 16; i++) sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "", digest[i]); - ret = smalloc(strlen(buffer) + 1); + ret = snewn(strlen(buffer) + 1, char); if (ret) strcpy(ret, buffer); return ret; @@ -705,7 +755,7 @@ static unsigned char *rsa2_sign(void *key, char *data, int datalen, SHA_Simple(data, datalen, hash); nbytes = (bignum_bitcount(rsa->modulus) - 1) / 8; - bytes = smalloc(nbytes); + bytes = snewn(nbytes, unsigned char); bytes[0] = 1; for (i = 1; i < nbytes - 20 - ASN1_LEN; i++) @@ -722,7 +772,7 @@ static unsigned char *rsa2_sign(void *key, char *data, int datalen, freebn(in); nbytes = (bignum_bitcount(out) + 7) / 8; - bytes = smalloc(4 + 7 + 4 + nbytes); + bytes = snewn(4 + 7 + 4 + nbytes, unsigned char); PUT_32BIT(bytes, 7); memcpy(bytes + 4, "ssh-rsa", 7); PUT_32BIT(bytes + 4 + 7, nbytes);