X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/47a6b94c2389f0e2a4f42706818a12369746b713..3980e64ffbb86a37d6810b004a04a21f338a408b:/sshdss.c diff --git a/sshdss.c b/sshdss.c index fa3ac384..532c13f2 100644 --- a/sshdss.c +++ b/sshdss.c @@ -1,3 +1,7 @@ +/* + * Digital Signature Standard implementation for PuTTY. + */ + #include #include #include @@ -5,18 +9,6 @@ #include "ssh.h" #include "misc.h" -#define GET_32BIT(cp) \ - (((unsigned long)(unsigned char)(cp)[0] << 24) | \ - ((unsigned long)(unsigned char)(cp)[1] << 16) | \ - ((unsigned long)(unsigned char)(cp)[2] << 8) | \ - ((unsigned long)(unsigned char)(cp)[3])) - -#define PUT_32BIT(cp, value) { \ - (cp)[0] = (unsigned char)((value) >> 24); \ - (cp)[1] = (unsigned char)((value) >> 16); \ - (cp)[2] = (unsigned char)((value) >> 8); \ - (cp)[3] = (unsigned char)(value); } - static void sha_mpint(SHA_State * s, Bignum b) { unsigned char lenbuf[4]; @@ -28,7 +20,7 @@ static void sha_mpint(SHA_State * s, Bignum b) lenbuf[0] = bignum_byte(b, len); SHA_Bytes(s, lenbuf, 1); } - memset(lenbuf, 0, sizeof(lenbuf)); + smemclr(lenbuf, sizeof(lenbuf)); } static void sha512_mpint(SHA512_State * s, Bignum b) @@ -42,7 +34,7 @@ static void sha512_mpint(SHA512_State * s, Bignum b) lenbuf[0] = bignum_byte(b, len); SHA512_Bytes(s, lenbuf, 1); } - memset(lenbuf, 0, sizeof(lenbuf)); + smemclr(lenbuf, sizeof(lenbuf)); } static void getstring(char **data, int *datalen, char **p, int *length) @@ -50,7 +42,9 @@ static void getstring(char **data, int *datalen, char **p, int *length) *p = NULL; if (*datalen < 4) return; - *length = GET_32BIT(*data); + *length = toint(GET_32BIT(*data)); + if (*length < 0) + return; *datalen -= 4; *data += 4; if (*datalen < *length) @@ -106,7 +100,7 @@ static void *dss_newkey(char *data, int len) } #endif - if (!p || memcmp(p, "ssh-dss", 7)) { + if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) { sfree(dss); return NULL; } @@ -239,14 +233,14 @@ static int dss_verifysig(void *key, char *sig, int siglen, #endif /* * Commercial SSH (2.0.13) and OpenSSH disagree over the format - * of a DSA signature. OpenSSH is in line with the IETF drafts: + * of a DSA signature. OpenSSH is in line with RFC 4253: * it uses a string "ssh-dss", followed by a 40-byte string * containing two 160-bit integers end-to-end. Commercial SSH * can't be bothered with the header bit, and considers a DSA * signature blob to be _just_ the 40-byte string containing * the two 160-bit integers. We tell them apart by measuring * the length: length 40 means the commercial-SSH bug, anything - * else is assumed to be IETF-compliant. + * else is assumed to be RFC-compliant. */ if (siglen != 40) { /* bug not present; read admin fields */ getstring(&sig, &siglen, &p, &slen); @@ -295,6 +289,8 @@ static int dss_verifysig(void *key, char *sig, int siglen, freebn(w); freebn(sha); + freebn(u1); + freebn(u2); freebn(gu1p); freebn(yu2p); freebn(gu1yu2p); @@ -410,6 +406,7 @@ static void *dss_createkey(unsigned char *pub_blob, int pub_len, ytest = modpow(dss->g, dss->x, dss->p); if (0 != bignum_cmp(ytest, dss->y)) { dss_freekey(dss); + freebn(ytest); return NULL; } freebn(ytest); @@ -583,7 +580,7 @@ static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen) SHA512_Bytes(&ss, digest, sizeof(digest)); SHA512_Final(&ss, digest512); - memset(&ss, 0, sizeof(ss)); + smemclr(&ss, sizeof(ss)); /* * Now convert the result into a bignum, and reduce it mod q. @@ -592,7 +589,7 @@ static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen) k = bigmod(proto_k, dss->q); freebn(proto_k); - memset(digest512, 0, sizeof(digest512)); + smemclr(digest512, sizeof(digest512)); /* * Now we have k, so just go ahead and compute the signature.