X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/5c72ca6161da0e7976245222c412d62ebae2e386..6f1e7b78af0f9c4c502609392f62771cf2528d8f:/sshdss.c diff --git a/sshdss.c b/sshdss.c index b2179a83..ce56d3c5 100644 --- a/sshdss.c +++ b/sshdss.c @@ -19,7 +19,6 @@ static void sha_mpint(SHA_State * s, Bignum b) { - unsigned char *p; unsigned char lenbuf[4]; int len; len = (bignum_bitcount(b) + 8) / 8; @@ -34,7 +33,6 @@ static void sha_mpint(SHA_State * s, Bignum b) static void sha512_mpint(SHA512_State * s, Bignum b) { - unsigned char *p; unsigned char lenbuf[4]; int len; len = (bignum_bitcount(b) + 8) / 8; @@ -357,31 +355,19 @@ static unsigned char *dss_private_blob(void *key, int *len) int xlen, bloblen; int i; unsigned char *blob, *p; - SHA_State s; - unsigned char digest[20]; xlen = (bignum_bitcount(dss->x) + 8) / 8; /* - * mpint x, string[20] the SHA of p||q||g. Total 28 + xlen. - * (two length fields and twenty bytes, 20+8=28). + * mpint x, string[20] the SHA of p||q||g. Total 4 + xlen. */ - bloblen = 28 + xlen; + bloblen = 4 + xlen; blob = smalloc(bloblen); p = blob; PUT_32BIT(p, xlen); p += 4; for (i = xlen; i--;) *p++ = bignum_byte(dss->x, i); - PUT_32BIT(p, 20); - SHA_Init(&s); - sha_mpint(&s, dss->p); - sha_mpint(&s, dss->q); - sha_mpint(&s, dss->g); - SHA_Final(&s, digest); - p += 4; - for (i = 0; i < 20; i++) - *p++ = digest[i]; assert(p == blob + bloblen); *len = bloblen; return blob; @@ -400,24 +386,22 @@ static void *dss_createkey(unsigned char *pub_blob, int pub_len, dss = dss_newkey((char *) pub_blob, pub_len); dss->x = getmp(&pb, &priv_len); - getstring(&pb, &priv_len, &hash, &hashlen); /* - * Verify details of the key. First check that the hash is - * indeed a hash of p||q||g. + * Check the obsolete hash in the old DSS key format. */ - if (hashlen != 20) { - dss_freekey(dss); - return NULL; - } - SHA_Init(&s); - sha_mpint(&s, dss->p); - sha_mpint(&s, dss->q); - sha_mpint(&s, dss->g); - SHA_Final(&s, digest); - if (0 != memcmp(hash, digest, 20)) { - dss_freekey(dss); - return NULL; + hashlen = -1; + getstring(&pb, &priv_len, &hash, &hashlen); + if (hashlen == 20) { + SHA_Init(&s); + sha_mpint(&s, dss->p); + sha_mpint(&s, dss->q); + sha_mpint(&s, dss->g); + SHA_Final(&s, digest); + if (0 != memcmp(hash, digest, 20)) { + dss_freekey(dss); + return NULL; + } } /* @@ -546,9 +530,16 @@ unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen) * signing the same hash twice with the same key yields the * same signature. * - * (It doesn't, _per se_, protect against reuse of k. Reuse of - * k is left to chance; all it does is prevent _excessively - * high_ chances of reuse of k due to entropy problems.) + * Despite this determinism, it's still not predictable to an + * attacker, because in order to repeat the SHA-512 + * construction that created it, the attacker would have to + * know the private key value x - and by assumption he doesn't, + * because if he knew that he wouldn't be attacking k! + * + * (This trick doesn't, _per se_, protect against reuse of k. + * Reuse of k is left to chance; all it does is prevent + * _excessively high_ chances of reuse of k due to entropy + * problems.) * * Thanks to Colin Plumb for the general idea of using x to * ensure k is hard to guess, and to the Cambridge University