From e0e1a00d471c4970f88b2a87f7f54d6c2c97c7f4 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 25 Oct 2002 12:51:28 +0000 Subject: [PATCH] SSH2 MACs now use dynamically allocated contexts. git-svn-id: svn://svn.tartarus.org/sgt/putty@2131 cda61777-01e9-0310-a592-d414129be87e --- ssh.c | 39 +++++++++++++++++++++++------- ssh.h | 9 +++---- sshmd5.c | 57 ++++++++++++++++++++++--------------------- sshsha.c | 84 +++++++++++++++++++++++++++++++--------------------------------- 4 files changed, 106 insertions(+), 83 deletions(-) diff --git a/ssh.c b/ssh.c index c8ba298d..9689fd24 100644 --- a/ssh.c +++ b/ssh.c @@ -371,19 +371,28 @@ const static struct ssh_kex *kex_algs[] = { const static struct ssh_signkey *hostkey_algs[] = { &ssh_rsa, &ssh_dss }; -static void nullmac_key(unsigned char *key) +static void *nullmac_make_context(void) +{ + return NULL; +} +static void nullmac_free_context(void *handle) +{ +} +static void nullmac_key(void *handle, unsigned char *key) { } -static void nullmac_generate(unsigned char *blk, int len, +static void nullmac_generate(void *handle, unsigned char *blk, int len, unsigned long seq) { } -static int nullmac_verify(unsigned char *blk, int len, unsigned long seq) +static int nullmac_verify(void *handle, unsigned char *blk, int len, + unsigned long seq) { return 1; } const static struct ssh_mac ssh_mac_none = { - nullmac_key, nullmac_key, nullmac_generate, nullmac_verify, "none", 0 + nullmac_make_context, nullmac_free_context, nullmac_key, + nullmac_generate, nullmac_verify, "none", 0 }; const static struct ssh_mac *macs[] = { &ssh_sha1, &ssh_md5, &ssh_mac_none @@ -554,6 +563,7 @@ struct ssh_tag { const struct ssh2_cipher *cscipher, *sccipher; void *cs_cipher_ctx, *sc_cipher_ctx; const struct ssh_mac *csmac, *scmac; + void *cs_mac_ctx, *sc_mac_ctx; const struct ssh_compress *cscomp, *sccomp; const struct ssh_kex *kex; const struct ssh_signkey *hostkey; @@ -979,7 +989,7 @@ static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen) * Check the MAC. */ if (ssh->scmac - && !ssh->scmac->verify(ssh->pktin.data, st->len + 4, + && !ssh->scmac->verify(ssh->sc_mac_ctx, ssh->pktin.data, st->len + 4, st->incoming_sequence)) { bombout(("Incorrect MAC received on packet")); crReturn(0); @@ -1468,7 +1478,8 @@ static int ssh2_pkt_construct(Ssh ssh) ssh->pktout.data[ssh->pktout.length + i] = random_byte(); PUT_32BIT(ssh->pktout.data, ssh->pktout.length + padding - 4); if (ssh->csmac) - ssh->csmac->generate(ssh->pktout.data, ssh->pktout.length + padding, + ssh->csmac->generate(ssh->cs_mac_ctx, ssh->pktout.data, + ssh->pktout.length + padding, ssh->v2_outgoing_sequence); ssh->v2_outgoing_sequence++; /* whether or not we MACed */ @@ -4031,12 +4042,22 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) ssh->cscipher->free_context(ssh->cs_cipher_ctx); ssh->cscipher = s->cscipher_tobe; ssh->cs_cipher_ctx = ssh->cscipher->make_context(); + if (ssh->sc_cipher_ctx) ssh->sccipher->free_context(ssh->sc_cipher_ctx); ssh->sccipher = s->sccipher_tobe; ssh->sc_cipher_ctx = ssh->sccipher->make_context(); + + if (ssh->cs_mac_ctx) + ssh->csmac->free_context(ssh->cs_mac_ctx); ssh->csmac = s->csmac_tobe; + ssh->cs_mac_ctx = ssh->csmac->make_context(); + + if (ssh->sc_mac_ctx) + ssh->scmac->free_context(ssh->sc_mac_ctx); ssh->scmac = s->scmac_tobe; + ssh->sc_mac_ctx = ssh->scmac->make_context(); + ssh->cscomp = s->cscomp_tobe; ssh->sccomp = s->sccomp_tobe; ssh->cscomp->compress_init(); @@ -4059,9 +4080,9 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'B',keyspace); ssh->sccipher->setiv(ssh->sc_cipher_ctx, keyspace); ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'E',keyspace); - ssh->csmac->setcskey(keyspace); + ssh->csmac->setkey(ssh->cs_mac_ctx, keyspace); ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'F',keyspace); - ssh->scmac->setsckey(keyspace); + ssh->scmac->setkey(ssh->sc_mac_ctx, keyspace); } { char buf[256]; @@ -5785,7 +5806,9 @@ static char *ssh_init(void *frontend_handle, void **backend_handle, ssh->sccipher = NULL; ssh->sc_cipher_ctx = NULL; ssh->csmac = NULL; + ssh->sc_mac_ctx = NULL; ssh->scmac = NULL; + ssh->sc_mac_ctx = NULL; ssh->cscomp = NULL; ssh->sccomp = NULL; ssh->kex = NULL; diff --git a/ssh.h b/ssh.h index a99b6336..28dd6dd1 100644 --- a/ssh.h +++ b/ssh.h @@ -151,10 +151,11 @@ struct ssh2_ciphers { }; struct ssh_mac { - void (*setcskey) (unsigned char *key); - void (*setsckey) (unsigned char *key); - void (*generate) (unsigned char *blk, int len, unsigned long seq); - int (*verify) (unsigned char *blk, int len, unsigned long seq); + void *(*make_context)(void); + void (*free_context)(void *); + void (*setkey) (void *, unsigned char *key); + void (*generate) (void *, unsigned char *blk, int len, unsigned long seq); + int (*verify) (void *, unsigned char *blk, int len, unsigned long seq); char *name; int len; }; diff --git a/sshmd5.c b/sshmd5.c index 0625f768..22c3e650 100644 --- a/sshmd5.c +++ b/sshmd5.c @@ -208,44 +208,46 @@ void MD5Final(unsigned char output[16], struct MD5Context *s) * HMAC wrapper on it. */ -static struct MD5Context md5_cs_mac_s1, md5_cs_mac_s2; -static struct MD5Context md5_sc_mac_s1, md5_sc_mac_s2; +static void *md5_make_context(void) +{ + return smalloc(2*sizeof(struct MD5Context)); +} + +static void md5_free_context(void *handle) +{ + sfree(handle); +} -static void md5_key(struct MD5Context *s1, struct MD5Context *s2, - unsigned char *key, int len) +static void md5_key_internal(void *handle, unsigned char *key, int len) { + struct MD5Context *keys = (struct MD5Context *)handle; unsigned char foo[64]; int i; memset(foo, 0x36, 64); for (i = 0; i < len && i < 64; i++) foo[i] ^= key[i]; - MD5Init(s1); - MD5Update(s1, foo, 64); + MD5Init(&keys[0]); + MD5Update(&keys[0], foo, 64); memset(foo, 0x5C, 64); for (i = 0; i < len && i < 64; i++) foo[i] ^= key[i]; - MD5Init(s2); - MD5Update(s2, foo, 64); + MD5Init(&keys[0]); + MD5Update(&keys[0], foo, 64); memset(foo, 0, 64); /* burn the evidence */ } -static void md5_cskey(unsigned char *key) -{ - md5_key(&md5_cs_mac_s1, &md5_cs_mac_s2, key, 16); -} - -static void md5_sckey(unsigned char *key) +static void md5_key(void *handle, unsigned char *key) { - md5_key(&md5_sc_mac_s1, &md5_sc_mac_s2, key, 16); + md5_key_internal(handle, key, 16); } -static void md5_do_hmac(struct MD5Context *s1, struct MD5Context *s2, - unsigned char *blk, int len, unsigned long seq, - unsigned char *hmac) +static void md5_do_hmac(void *handle, unsigned char *blk, int len, + unsigned long seq, unsigned char *hmac) { + struct MD5Context *keys = (struct MD5Context *)handle; struct MD5Context s; unsigned char intermediate[16]; @@ -254,31 +256,32 @@ static void md5_do_hmac(struct MD5Context *s1, struct MD5Context *s2, intermediate[2] = (unsigned char) ((seq >> 8) & 0xFF); intermediate[3] = (unsigned char) ((seq) & 0xFF); - s = *s1; /* structure copy */ + s = keys[0]; /* structure copy */ MD5Update(&s, intermediate, 4); MD5Update(&s, blk, len); MD5Final(intermediate, &s); - s = *s2; /* structure copy */ + s = keys[1]; /* structure copy */ MD5Update(&s, intermediate, 16); MD5Final(hmac, &s); } -static void md5_generate(unsigned char *blk, int len, unsigned long seq) +static void md5_generate(void *handle, unsigned char *blk, int len, + unsigned long seq) { - md5_do_hmac(&md5_cs_mac_s1, &md5_cs_mac_s2, blk, len, seq, blk + len); + md5_do_hmac(handle, blk, len, seq, blk + len); } -static int md5_verify(unsigned char *blk, int len, unsigned long seq) +static int md5_verify(void *handle, unsigned char *blk, int len, + unsigned long seq) { unsigned char correct[16]; - md5_do_hmac(&md5_sc_mac_s1, &md5_sc_mac_s2, blk, len, seq, correct); + md5_do_hmac(handle, blk, len, seq, correct); return !memcmp(correct, blk + len, 16); } const struct ssh_mac ssh_md5 = { - md5_cskey, md5_sckey, - md5_generate, - md5_verify, + md5_make_context, md5_free_context, md5_key, + md5_generate, md5_verify, "hmac-md5", 16 }; diff --git a/sshsha.c b/sshsha.c index 5b50d7ec..4bac4fdc 100644 --- a/sshsha.c +++ b/sshsha.c @@ -193,54 +193,51 @@ void SHA_Simple(void *p, int len, unsigned char *output) * HMAC wrapper on it. */ -static SHA_State sha1_cs_mac_s1, sha1_cs_mac_s2; -static SHA_State sha1_sc_mac_s1, sha1_sc_mac_s2; +static void *sha1_make_context(void) +{ + return smalloc(2*sizeof(SHA_State)); +} + +static void sha1_free_context(void *handle) +{ + sfree(handle); +} -static void sha1_key(SHA_State * s1, SHA_State * s2, - unsigned char *key, int len) +static void sha1_key_internal(void *handle, unsigned char *key, int len) { + SHA_State *keys = (SHA_State *)handle; unsigned char foo[64]; int i; memset(foo, 0x36, 64); for (i = 0; i < len && i < 64; i++) foo[i] ^= key[i]; - SHA_Init(s1); - SHA_Bytes(s1, foo, 64); + SHA_Init(&keys[0]); + SHA_Bytes(&keys[0], foo, 64); memset(foo, 0x5C, 64); for (i = 0; i < len && i < 64; i++) foo[i] ^= key[i]; - SHA_Init(s2); - SHA_Bytes(s2, foo, 64); + SHA_Init(&keys[1]); + SHA_Bytes(&keys[1], foo, 64); memset(foo, 0, 64); /* burn the evidence */ } -static void sha1_cskey(unsigned char *key) -{ - sha1_key(&sha1_cs_mac_s1, &sha1_cs_mac_s2, key, 20); -} - -static void sha1_sckey(unsigned char *key) -{ - sha1_key(&sha1_sc_mac_s1, &sha1_sc_mac_s2, key, 20); -} - -static void sha1_cskey_buggy(unsigned char *key) +static void sha1_key(void *handle, unsigned char *key) { - sha1_key(&sha1_cs_mac_s1, &sha1_cs_mac_s2, key, 16); + sha1_key_internal(handle, key, 20); } -static void sha1_sckey_buggy(unsigned char *key) +static void sha1_key_buggy(void *handle, unsigned char *key) { - sha1_key(&sha1_sc_mac_s1, &sha1_sc_mac_s2, key, 16); + sha1_key_internal(handle, key, 16); } -static void sha1_do_hmac(SHA_State * s1, SHA_State * s2, - unsigned char *blk, int len, unsigned long seq, - unsigned char *hmac) +static void sha1_do_hmac(void *handle, unsigned char *blk, int len, + unsigned long seq, unsigned char *hmac) { + SHA_State *keys = (SHA_State *)handle; SHA_State s; unsigned char intermediate[20]; @@ -249,53 +246,52 @@ static void sha1_do_hmac(SHA_State * s1, SHA_State * s2, intermediate[2] = (unsigned char) ((seq >> 8) & 0xFF); intermediate[3] = (unsigned char) ((seq) & 0xFF); - s = *s1; /* structure copy */ + s = keys[0]; /* structure copy */ SHA_Bytes(&s, intermediate, 4); SHA_Bytes(&s, blk, len); SHA_Final(&s, intermediate); - s = *s2; /* structure copy */ + s = keys[1]; /* structure copy */ SHA_Bytes(&s, intermediate, 20); SHA_Final(&s, hmac); } -static void sha1_generate(unsigned char *blk, int len, unsigned long seq) +static void sha1_generate(void *handle, unsigned char *blk, int len, + unsigned long seq) { - sha1_do_hmac(&sha1_cs_mac_s1, &sha1_cs_mac_s2, blk, len, seq, - blk + len); + sha1_do_hmac(handle, blk, len, seq, blk + len); } -static int sha1_verify(unsigned char *blk, int len, unsigned long seq) +static int sha1_verify(void *handle, unsigned char *blk, int len, + unsigned long seq) { unsigned char correct[20]; - sha1_do_hmac(&sha1_sc_mac_s1, &sha1_sc_mac_s2, blk, len, seq, correct); + sha1_do_hmac(handle, blk, len, seq, correct); return !memcmp(correct, blk + len, 20); } void hmac_sha1_simple(void *key, int keylen, void *data, int datalen, unsigned char *output) { - SHA_State s1, s2; + SHA_State states[2]; unsigned char intermediate[20]; - sha1_key(&s1, &s2, key, keylen); - SHA_Bytes(&s1, data, datalen); - SHA_Final(&s1, intermediate); + sha1_key_internal(states, key, keylen); + SHA_Bytes(&states[0], data, datalen); + SHA_Final(&states[0], intermediate); - SHA_Bytes(&s2, intermediate, 20); - SHA_Final(&s2, output); + SHA_Bytes(&states[1], intermediate, 20); + SHA_Final(&states[1], output); } const struct ssh_mac ssh_sha1 = { - sha1_cskey, sha1_sckey, - sha1_generate, - sha1_verify, + sha1_make_context, sha1_free_context, sha1_key, + sha1_generate, sha1_verify, "hmac-sha1", 20 }; const struct ssh_mac ssh_sha1_buggy = { - sha1_cskey_buggy, sha1_sckey_buggy, - sha1_generate, - sha1_verify, + sha1_make_context, sha1_free_context, sha1_key_buggy, + sha1_generate, sha1_verify, "hmac-sha1", 20 }; -- 2.11.0