mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-04-18 03:28:07 -05:00
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. [originally from svn r3149]
This commit is contained in:
parent
1f5780ad9f
commit
dca1486602
2
Recipe
2
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
|
||||
|
23
pageant.c
23
pageant.c
@ -127,6 +127,24 @@ static void *make_keylist2(int *length);
|
||||
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.
|
||||
@ -1929,11 +1947,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.
|
||||
*/
|
||||
|
54
sshrsa.c
54
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--;
|
||||
|
Loading…
x
Reference in New Issue
Block a user