From d39f364a883ab4a791939320caa50761cd1e068f Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 5 Sep 2000 16:23:36 +0000 Subject: [PATCH] Second attempt. Can successfully decrypt the _first block_ of a packet. git-svn-id: svn://svn.tartarus.org/sgt/putty@570 cda61777-01e9-0310-a592-d414129be87e --- ssh.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- ssh.h | 9 +++++-- sshblowf.c | 26 ++++++++++++++++++++ sshdes.c | 50 +++++++++++++++++++++++++++++--------- sshsha.c | 35 ++++++++++++++++++--------- 5 files changed, 167 insertions(+), 35 deletions(-) diff --git a/ssh.c b/ssh.c index ae41a80e..8a483f8b 100644 --- a/ssh.c +++ b/ssh.c @@ -104,11 +104,11 @@ extern struct ssh_mac ssh_sha1; SHA_State exhash; -static void nullmac_sesskey(unsigned char *key, int len) { } +static void nullmac_key(unsigned char *key) { } static void nullmac_generate(unsigned char *blk, int len, unsigned long seq) { } static int nullmac_verify(unsigned char *blk, int len, unsigned long seq) { return 1; } struct ssh_mac ssh_mac_none = { - nullmac_sesskey, nullmac_generate, nullmac_verify, "none", 0 + nullmac_key, nullmac_key, nullmac_generate, nullmac_verify, "none", 0 }; struct ssh_mac *macs[] = { &ssh_sha1, &ssh_mac_none }; @@ -346,8 +346,16 @@ next_packet: /* FIXME */ } #endif + debug(("Got initblk:")); + for (i = 0; i < cipherblk; i++) + debug((" %02x", (unsigned char)pktin.data[i])); + debug(("\r\n")); if (sccipher) sccipher->decrypt(pktin.data, cipherblk); + debug(("Decrypted initblk:")); + for (i = 0; i < cipherblk; i++) + debug((" %02x", (unsigned char)pktin.data[i])); + debug(("\r\n")); /* * Now get the length and padding figures. @@ -392,6 +400,11 @@ next_packet: if (sccipher) sccipher->decrypt(pktin.data + cipherblk, packetlen - cipherblk); + debug(("Got packet len=%d pad=%d\r\n", len, pad)); + for (i = 0; i < packetlen; i++) + debug((" %02x", (unsigned char)pktin.data[i])); + debug(("\r\n")); + /* * Check the MAC. */ @@ -400,12 +413,6 @@ next_packet: pktin.savedpos = 6; pktin.type = pktin.data[5]; -#if 0 - debug(("Got packet len=%d pad=%d\r\n", len, pad)); - for (i = 0; i < payload; i++) - debug((" %02x", (unsigned char)pktin.data[i])); - debug(("\r\n")); -#endif /* * FIXME: handle IGNORE and DEBUG messages. @@ -1311,6 +1318,26 @@ int in_commasep_string(char *needle, char *haystack, int haylen) { } /* + * SSH2 key creation method. + */ +void ssh2_mkkey(Bignum K, char *H, char chr, char *keyspace) { + SHA_State s; + /* First 20 bytes. */ + SHA_Init(&s); + sha_mpint(&s, K); + SHA_Bytes(&s, H, 20); + SHA_Bytes(&s, &chr, 1); + SHA_Bytes(&s, H, 20); + SHA_Final(&s, keyspace); + /* Next 20 bytes. */ + SHA_Init(&s); + sha_mpint(&s, K); + SHA_Bytes(&s, H, 20); + SHA_Bytes(&s, keyspace, 20); + SHA_Final(&s, keyspace+20); +} + +/* * Handle the SSH2 key exchange phase. */ static int do_ssh2_kex(unsigned char *in, int inlen, int ispkt) @@ -1327,6 +1354,7 @@ static int do_ssh2_kex(unsigned char *in, int inlen, int ispkt) static char *hostkeydata, *sigdata; static int hostkeylen, siglen; static unsigned char exchange_hash[20]; + static unsigned char keyspace[40]; crBegin; @@ -1519,9 +1547,43 @@ static int do_ssh2_kex(unsigned char *in, int inlen, int ispkt) debug(("\r\n")); /* - * FIXME: verify hostkeydata and sigdata. + * FIXME: verify host key. This bit will be moderately + * unpleasant, because of having to rewrite it to work + * alongside the old scheme. */ - + + /* + * FIXME: verify signature of exchange hash. + */ + + /* + * Send SSH2_MSG_NEWKEYS. Expect it from server. + */ + ssh2_pkt_init(SSH2_MSG_NEWKEYS); + ssh2_pkt_send(); + crWaitUntil(ispkt); + if (pktin.type != SSH2_MSG_NEWKEYS) + fatalbox("expected new-keys packet from server"); + + /* + * Create and initialise session keys. + */ + cscipher = cscipher_tobe; + sccipher = sccipher_tobe; + csmac = csmac_tobe; + scmac = scmac_tobe; + cscomp = cscomp_tobe; + sccomp = sccomp_tobe; + /* + * Set IVs after keys. + */ + ssh2_mkkey(K, exchange_hash, 'C', keyspace); cscipher->setcskey(keyspace); + ssh2_mkkey(K, exchange_hash, 'D', keyspace); cscipher->setsckey(keyspace); + ssh2_mkkey(K, exchange_hash, 'A', keyspace); cscipher->setcsiv(keyspace); + ssh2_mkkey(K, exchange_hash, 'B', keyspace); sccipher->setsciv(keyspace); + ssh2_mkkey(K, exchange_hash, 'E', keyspace); csmac->setcskey(keyspace); + ssh2_mkkey(K, exchange_hash, 'F', keyspace); scmac->setsckey(keyspace); + crWaitUntil(0); crFinish(1); diff --git a/ssh.h b/ssh.h index e7be138c..84e3c205 100644 --- a/ssh.h +++ b/ssh.h @@ -73,7 +73,11 @@ void SHA_Bytes(SHA_State *s, void *p, int len); void SHA_Final(SHA_State *s, unsigned char *output); struct ssh_cipher { - void (*sesskey)(unsigned char *key); + void (*sesskey)(unsigned char *key); /* for ssh 1 */ + void (*setcsiv)(unsigned char *key); /* for ssh 2 */ + void (*setcskey)(unsigned char *key); /* for ssh 2 */ + void (*setsciv)(unsigned char *key); /* for ssh 2 */ + void (*setsckey)(unsigned char *key); /* for ssh 2 */ void (*encrypt)(unsigned char *blk, int len); void (*decrypt)(unsigned char *blk, int len); char *name; @@ -81,7 +85,8 @@ struct ssh_cipher { }; struct ssh_mac { - void (*sesskey)(unsigned char *key, int len); + 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); char *name; diff --git a/sshblowf.c b/sshblowf.c index 364067a1..d6e6731f 100644 --- a/sshblowf.c +++ b/sshblowf.c @@ -392,6 +392,30 @@ static void blowfish_setkey(BlowfishContext *ctx, #define SSH_SESSION_KEY_LENGTH 32 static BlowfishContext ectx, dctx; +static void blowfish_cskey(unsigned char *key) +{ + blowfish_setkey(&ectx, key, 16); + logevent("Initialised Blowfish client->server encryption"); +} + +static void blowfish_sckey(unsigned char *key) +{ + blowfish_setkey(&dctx, key, 16); + logevent("Initialised Blowfish server->client encryption"); +} + +static void blowfish_csiv(unsigned char *key) +{ + ectx.iv0 = GET_32BIT_LSB_FIRST(key); + ectx.iv1 = GET_32BIT_LSB_FIRST(key+4); +} + +static void blowfish_sciv(unsigned char *key) +{ + dctx.iv0 = GET_32BIT_LSB_FIRST(key); + dctx.iv1 = GET_32BIT_LSB_FIRST(key+4); +} + static void blowfish_sesskey(unsigned char *key) { blowfish_setkey(&ectx, key, SSH_SESSION_KEY_LENGTH); @@ -413,6 +437,8 @@ static void blowfish_decrypt_blk(unsigned char *blk, int len) struct ssh_cipher ssh_blowfish = { blowfish_sesskey, + blowfish_csiv, blowfish_cskey, + blowfish_sciv, blowfish_sckey, blowfish_encrypt_blk, blowfish_decrypt_blk, "blowfish-cbc", diff --git a/sshdes.c b/sshdes.c index 0e90e644..1c351576 100644 --- a/sshdes.c +++ b/sshdes.c @@ -662,28 +662,55 @@ static void des_3cbc_decrypt(unsigned char *dest, const unsigned char *src, des_cbc_decrypt(dest, src, len, &scheds[0]); } -static DESContext keys[3]; +static DESContext cskeys[3], sckeys[3]; -static void des3_sesskey(unsigned char *key) { +static void des3_cskey(unsigned char *key) { des_key_setup(GET_32BIT_MSB_FIRST(key), - GET_32BIT_MSB_FIRST(key+4), &keys[0]); + GET_32BIT_MSB_FIRST(key+4), &cskeys[0]); des_key_setup(GET_32BIT_MSB_FIRST(key+8), - GET_32BIT_MSB_FIRST(key+12), &keys[1]); + GET_32BIT_MSB_FIRST(key+12), &cskeys[1]); des_key_setup(GET_32BIT_MSB_FIRST(key+16), - GET_32BIT_MSB_FIRST(key+20), &keys[2]); - logevent("Initialised triple-DES encryption"); + GET_32BIT_MSB_FIRST(key+20), &cskeys[2]); + logevent("Initialised triple-DES client->server encryption"); +} + +static void des3_csiv(unsigned char *key) { + cskeys[0].eiv0 = GET_32BIT_MSB_FIRST(key); + cskeys[0].eiv1 = GET_32BIT_MSB_FIRST(key+4); +} + +static void des3_sciv(unsigned char *key) { + sckeys[0].div0 = GET_32BIT_MSB_FIRST(key); + sckeys[0].div1 = GET_32BIT_MSB_FIRST(key+4); +} + +static void des3_sckey(unsigned char *key) { + des_key_setup(GET_32BIT_MSB_FIRST(key), + GET_32BIT_MSB_FIRST(key+4), &sckeys[0]); + des_key_setup(GET_32BIT_MSB_FIRST(key+8), + GET_32BIT_MSB_FIRST(key+12), &sckeys[1]); + des_key_setup(GET_32BIT_MSB_FIRST(key+16), + GET_32BIT_MSB_FIRST(key+20), &sckeys[2]); + logevent("Initialised triple-DES server->client encryption"); +} + +static void des3_sesskey(unsigned char *key) { + des3_cskey(key); + des3_sckey(key); } static void des3_encrypt_blk(unsigned char *blk, int len) { - des_3cbc_encrypt(blk, blk, len, keys); + des_3cbc_encrypt(blk, blk, len, cskeys); } static void des3_decrypt_blk(unsigned char *blk, int len) { - des_3cbc_decrypt(blk, blk, len, keys); + des_3cbc_decrypt(blk, blk, len, sckeys); } struct ssh_cipher ssh_3des = { des3_sesskey, + des3_csiv, des3_cskey, + des3_sciv, des3_sckey, des3_encrypt_blk, des3_decrypt_blk, "3des-cbc", @@ -692,20 +719,21 @@ struct ssh_cipher ssh_3des = { static void des_sesskey(unsigned char *key) { des_key_setup(GET_32BIT_MSB_FIRST(key), - GET_32BIT_MSB_FIRST(key+4), &keys[0]); + GET_32BIT_MSB_FIRST(key+4), &cskeys[0]); logevent("Initialised single-DES encryption"); } static void des_encrypt_blk(unsigned char *blk, int len) { - des_cbc_encrypt(blk, blk, len, keys); + des_cbc_encrypt(blk, blk, len, cskeys); } static void des_decrypt_blk(unsigned char *blk, int len) { - des_cbc_decrypt(blk, blk, len, keys); + des_cbc_decrypt(blk, blk, len, cskeys); } struct ssh_cipher ssh_des = { des_sesskey, + NULL, NULL, NULL, NULL, /* SSH 2 bits - unused */ des_encrypt_blk, des_decrypt_blk, "des-cbc", /* should never be used - not a valid cipher in ssh2 */ diff --git a/sshsha.c b/sshsha.c index 487d1733..d47b1be9 100644 --- a/sshsha.c +++ b/sshsha.c @@ -170,28 +170,39 @@ void SHA_Simple(void *p, int len, unsigned char *output) { * HMAC wrapper on it. */ -static SHA_State sha1_mac_s1, sha1_mac_s2; +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_sesskey(unsigned char *key, int len) { +static void sha1_key(SHA_State *s1, SHA_State *s2, + unsigned char *key, int len) { unsigned char foo[64]; int i; memset(foo, 0x36, 64); for (i = 0; i < len && i < 64; i++) foo[i] ^= key[i]; - SHA_Init(&sha1_mac_s1); - SHA_Bytes(&sha1_mac_s1, foo, 64); + SHA_Init(s1); + SHA_Bytes(s1, foo, 64); memset(foo, 0x5C, 64); for (i = 0; i < len && i < 64; i++) foo[i] ^= key[i]; - SHA_Init(&sha1_mac_s2); - SHA_Bytes(&sha1_mac_s2, foo, 64); + SHA_Init(s2); + SHA_Bytes(s2, foo, 64); memset(foo, 0, 64); /* burn the evidence */ } -static void sha1_do_hmac(unsigned char *blk, int len, unsigned long seq, +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_do_hmac(SHA_State *s1, SHA_State *s2, + unsigned char *blk, int len, unsigned long seq, unsigned char *hmac) { SHA_State s; unsigned char intermediate[20]; @@ -201,27 +212,27 @@ static void sha1_do_hmac(unsigned char *blk, int len, unsigned long seq, intermediate[2] = (unsigned char)((seq >> 8) & 0xFF); intermediate[3] = (unsigned char)((seq ) & 0xFF); - s = sha1_mac_s1; /* structure copy */ + s = *s1; /* structure copy */ SHA_Bytes(&s, intermediate, 4); SHA_Bytes(&s, blk, len); SHA_Final(&s, intermediate); - s = sha1_mac_s2; /* structure copy */ + s = *s2; /* structure copy */ SHA_Bytes(&s, intermediate, 20); SHA_Final(&s, hmac); } static void sha1_generate(unsigned char *blk, int len, unsigned long seq) { - sha1_do_hmac(blk, len, seq, blk+len); + sha1_do_hmac(&sha1_cs_mac_s1, &sha1_cs_mac_s2, blk, len, seq, blk+len); } static int sha1_verify(unsigned char *blk, int len, unsigned long seq) { unsigned char correct[20]; - sha1_do_hmac(blk, len, seq, correct); + sha1_do_hmac(&sha1_sc_mac_s1, &sha1_sc_mac_s2, blk, len, seq, correct); return !memcmp(correct, blk+len, 20); } struct ssh_mac ssh_sha1 = { - sha1_sesskey, + sha1_cskey, sha1_sckey, sha1_generate, sha1_verify, "hmac-sha1", -- 2.11.0