From 754c0df9e163ff5c244239a201026858f4381e73 Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 12 Mar 2006 19:24:05 +0000 Subject: [PATCH] Dimitry Andric spotted that DH gex with SHA-256 was overflowing a buffer. Fixed, and added paranoia so that this shouldn't happen again. git-svn-id: svn://svn.tartarus.org/sgt/putty@6606 cda61777-01e9-0310-a592-d414129be87e --- ssh.c | 29 ++++++++++++++++++++++++----- ssh.h | 3 +++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/ssh.c b/ssh.c index ba3dfad6..1a7880cc 100644 --- a/ssh.c +++ b/ssh.c @@ -708,7 +708,7 @@ struct ssh_tag { void *cs_comp_ctx, *sc_comp_ctx; const struct ssh_kex *kex; const struct ssh_signkey *hostkey; - unsigned char v2_session_id[32]; + unsigned char v2_session_id[SSH2_KEX_MAX_HASH_LEN]; int v2_session_id_len; void *kex_ctx; @@ -4964,7 +4964,10 @@ static int first_in_commasep_string(char *needle, char *haystack, int haylen) /* * SSH-2 key creation method. + * (Currently assumes 2 lots of any hash are sufficient to generate + * keys/IVs for any cipher/MAC. SSH2_MKKEY_ITERS documents this assumption.) */ +#define SSH2_MKKEY_ITERS (2) static void ssh2_mkkey(Ssh ssh, Bignum K, unsigned char *H, char chr, unsigned char *keyspace) { @@ -5011,7 +5014,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen, char *hostkeydata, *sigdata, *keystr, *fingerprint; int hostkeylen, siglen; void *hkey; /* actual host key */ - unsigned char exchange_hash[32]; + unsigned char exchange_hash[SSH2_KEX_MAX_HASH_LEN]; int n_preferred_kex; const struct ssh_kexes *preferred_kex[KEX_MAX]; int n_preferred_ciphers; @@ -5064,7 +5067,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen, s->preferred_kex[s->n_preferred_kex++] = &ssh_diffiehellman_group1; break; - case CIPHER_WARN: + case KEX_WARN: /* Flag for later. Don't bother if it's the last in * the list. */ if (i < KEX_MAX - 1) { @@ -5662,13 +5665,21 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen, * hash from the _first_ key exchange. */ { - unsigned char keyspace[40]; + unsigned char keyspace[SSH2_KEX_MAX_HASH_LEN * SSH2_MKKEY_ITERS]; + assert(sizeof(keyspace) >= ssh->kex->hash->hlen * SSH2_MKKEY_ITERS); ssh2_mkkey(ssh,s->K,s->exchange_hash,'C',keyspace); + assert((ssh->cscipher->keylen+7) / 8 <= + ssh->kex->hash->hlen * SSH2_MKKEY_ITERS); ssh->cscipher->setkey(ssh->cs_cipher_ctx, keyspace); ssh2_mkkey(ssh,s->K,s->exchange_hash,'A',keyspace); + assert(ssh->cscipher->blksize <= + ssh->kex->hash->hlen * SSH2_MKKEY_ITERS); ssh->cscipher->setiv(ssh->cs_cipher_ctx, keyspace); ssh2_mkkey(ssh,s->K,s->exchange_hash,'E',keyspace); + assert(ssh->csmac->len <= + ssh->kex->hash->hlen * SSH2_MKKEY_ITERS); ssh->csmac->setkey(ssh->cs_mac_ctx, keyspace); + memset(keyspace, 0, sizeof(keyspace)); } logeventf(ssh, "Initialised %.200s client->server encryption", @@ -5720,13 +5731,21 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen, * hash from the _first_ key exchange. */ { - unsigned char keyspace[40]; + unsigned char keyspace[SSH2_KEX_MAX_HASH_LEN * SSH2_MKKEY_ITERS]; + assert(sizeof(keyspace) >= ssh->kex->hash->hlen * SSH2_MKKEY_ITERS); ssh2_mkkey(ssh,s->K,s->exchange_hash,'D',keyspace); + assert((ssh->sccipher->keylen+7) / 8 <= + ssh->kex->hash->hlen * SSH2_MKKEY_ITERS); ssh->sccipher->setkey(ssh->sc_cipher_ctx, keyspace); ssh2_mkkey(ssh,s->K,s->exchange_hash,'B',keyspace); + assert(ssh->sccipher->blksize <= + ssh->kex->hash->hlen * SSH2_MKKEY_ITERS); ssh->sccipher->setiv(ssh->sc_cipher_ctx, keyspace); ssh2_mkkey(ssh,s->K,s->exchange_hash,'F',keyspace); + assert(ssh->scmac->len <= + ssh->kex->hash->hlen * SSH2_MKKEY_ITERS); ssh->scmac->setkey(ssh->sc_mac_ctx, keyspace); + memset(keyspace, 0, sizeof(keyspace)); } logeventf(ssh, "Initialised %.200s server->client encryption", ssh->sccipher->text_name); diff --git a/ssh.h b/ssh.h index cca3ec07..e45c653f 100644 --- a/ssh.h +++ b/ssh.h @@ -252,6 +252,9 @@ struct ssh2_userkey { char *comment; /* the key comment */ }; +/* The maximum length of any hash algorithm used in kex. (bytes) */ +#define SSH2_KEX_MAX_HASH_LEN (32) /* SHA-256 */ + extern const struct ssh_cipher ssh_3des; extern const struct ssh_cipher ssh_des; extern const struct ssh_cipher ssh_blowfish_ssh1; -- 2.11.0