From b492c4d75bec08565e126e548888d40ba921e9a5 Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 27 Apr 2003 09:45:35 +0000 Subject: [PATCH] Take the random number generator back out of Pageant: the `random' numbers needed for RSA blinding are now done deterministically by hashes of the private key, much the same way we do it for DSA. git-svn-id: svn://svn.tartarus.org/sgt/putty@3149 cda61777-01e9-0310-a592-d414129be87e --- Recipe | 2 +- pageant.c | 23 ++++++++++++++++++----- sshrsa.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/Recipe b/Recipe index 475a80d9..3c9b65ad 100644 --- a/Recipe +++ b/Recipe @@ -146,7 +146,7 @@ psftp : [C] psftp console WINSSH be_none SFTP WINMISC scp.res LIBS1 pageant : [G] pageant sshrsa sshpubk sshdes sshbn sshmd5 version tree234 + misc sshaes sshsha pageantc sshdss sshsh512 winutils winmisc - + sshrand noise winstore pageant.res LIBS + + pageant.res LIBS puttygen : [G] puttygen sshrsag sshdssg sshprime sshdes sshbn sshmd5 version + sshrand noise sshsha winstore misc winctrls sshrsa sshdss winmisc diff --git a/pageant.c b/pageant.c index 41ae837e..c401ea55 100644 --- a/pageant.c +++ b/pageant.c @@ -128,6 +128,24 @@ static void *get_keylist1(void); static void *get_keylist2(void); /* + * We need this to link with the RSA code, because rsaencrypt() + * pads its data with random bytes. Since we only use rsadecrypt() + * and the signing functions, which are deterministic, this should + * never be called. + * + * If it _is_ called, there is a _serious_ problem, because it + * won't generate true random numbers. So we must scream, panic, + * and exit immediately if that should happen. + */ +int random_byte(void) +{ + MessageBox(main_hwnd, "Internal Error", APPNAME, MB_OK | MB_ICONERROR); + exit(0); + /* this line can't be reached but it placates MSVC's warnings :-) */ + return 0; +} + +/* * Blob structure for passing to the asymmetric SSH2 key compare * function, prototyped here. */ @@ -1930,11 +1948,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) } /* - * Initialise the random number generator. - */ - random_init(); - - /* * Initialise storage for short-term passphrase cache. */ passphrases = newtree234(NULL); diff --git a/sshrsa.c b/sshrsa.c index c97dce05..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--; -- 2.11.0