From d462a1690453f4610077424c2c2c1c9fe2184b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20M=C3=B6ller?= Date: Sat, 12 Sep 1998 00:53:05 +0200 Subject: [PATCH] Random hacking. connection objects should no longer be considered write handlers, instead the read_packet-handler has a reference directly to the connection object. Session key generation halfway written. Rev: src/client_keyexchange.c:1.3 Rev: src/client_keyexchange.h:1.2 Rev: src/connection.h:1.11 Rev: src/keyexchange.c:1.8 Rev: src/keyexchange.h:1.9 Rev: src/publickey_crypto.c:1.7 Rev: src/publickey_crypto.h:1.6 Rev: src/read_packet.c:1.8 Rev: src/read_packet.h:1.5 --- src/client_keyexchange.c | 42 +++++++++++++++++++-- src/client_keyexchange.h | 2 - src/connection.h | 15 +++++++- src/keyexchange.c | 81 ++++++++++++++++++++++++++++++++++++++++ src/keyexchange.h | 14 ++++--- src/publickey_crypto.c | 13 +++++-- src/publickey_crypto.h | 1 + src/read_packet.c | 2 +- src/read_packet.h | 16 +++++--- 9 files changed, 162 insertions(+), 24 deletions(-) diff --git a/src/client_keyexchange.c b/src/client_keyexchange.c index 53aa5546..3de82ec3 100644 --- a/src/client_keyexchange.c +++ b/src/client_keyexchange.c @@ -29,6 +29,8 @@ static void do_handle_dh_reply(struct packet_handler *c, { struct dh_client *closure = (struct dh_client *) c; struct verifier *v; + struct hash_instance *hash;; + struct lsh_string *s; if (!dh_process_server_msg(&closure->dh, packet)) return send_disconnect(connection, "Bad dh-reply\r\n"); @@ -45,10 +47,24 @@ static void do_handle_dh_reply(struct packet_handler *c, /* FIXME: Same here */ return send_disconnect(connection, "Bad server host key\r\n"); - /* Key exchange successful! */ - + /* Key exchange successful! Send a newkeys message, and install a + * handler for recieving the newkeys message. */ + + /* Record session id */ + if (!connection->session_id) + connection->session_id = closure->dh.exchange_hash; + /* A hash instance initialized with the key, to be used for key generation */ + hash = MAKE_HASH(closure->dh->method->hash); + s = ssh_format("%n", closure->dh->K); + HASH_UPDATE(hash, s->length, s->data); + lsh_string_free(s); + + res = prepare_keys(connection, hash); + lsh_free(hash); + + return res; } static void do_init_dh(struct keyexchange_algorithm *c, @@ -62,8 +78,7 @@ static void do_init_dh(struct keyexchange_algorithm *c, dh->super.handler = do_handle_dh_reply; init_diffie_hellman_instance(closure->dh, &dh->dh, connection); - dh->hash = MAKE_HASH(closure->hash); - dh->signature_algorithm = closure->signature_algorithm; + dh->verifier = closure->verifier; /* Send client's message */ A_WRITE(connection->write, dh_make_client_msg(&dh->dh)); @@ -78,3 +93,22 @@ static void do_init_dh(struct keyexchange_algorithm *c, return WRITE_OK; } +int prepare_keys_client(struct hash_instance *secret, + struct ssh_connection *connection) +{ + /* FIXME: For DES, instantiating a crypto may fail, if the key + * happens to be weak. */ + /* FIXME: No IV:s */ + + struct crypto_instance *crypt_client_to_server + = kex_make_encrypt(secret, KEX_ENCRYPTION_CLIENT_TO_SERVER, connection); + struct crypto_instance *crypt_server_to_client + = kex_make_decrypt(secret, KEX_ENCRYPTION_SERVER_TO_CLIENT, connection); + + struct mac_instance *mac_client_to_server + = kex_make_mac(secret, KEX_MAC_CLIENT_TO_SERVER, connection); + struct mac_instance *mac_server_to_client + = kex_make_mac(secret, KEX_MAC_SERVER_TO_CLIENT, connection); + + + diff --git a/src/client_keyexchange.h b/src/client_keyexchange.h index 3631e686..199f5f1a 100644 --- a/src/client_keyexchange.h +++ b/src/client_keyexchange.h @@ -45,7 +45,6 @@ struct dh_algorithm_client { struct keyexchange_algorithm super; struct diffie_hellman_method dh; - struct hash_algorithm *hash; struct lookup_verifier *verifier; }; @@ -54,7 +53,6 @@ struct dh_client { struct packet_handler super; struct diffie_hellman_instance dh; - struct hash_instance *hash; struct lookup_verifier *verifier; struct packet_handler *saved_kexinit_handler; }; diff --git a/src/connection.h b/src/connection.h index eb1d5476..b21741ce 100644 --- a/src/connection.h +++ b/src/connection.h @@ -29,7 +29,14 @@ struct packet_handler struct ssh_connection { +#if 0 struct abstract_write super; + + struct read_packet *reader; /* Needed for changing the decryption + * algorithms. Is there a better way? + * Perhaps one can keep this pointer + * inside the newkeys-handler? */ +#endif int type; /* CONNECTION_SERVER or CONNECTION_CLIENT */ @@ -38,6 +45,11 @@ struct ssh_connection struct lsh_string *server_version; struct lsh_string *session_id; + + /* Reading */ + struct mac_instance *mac; + struct crypto_instance *crypto; + struct abstract_write *raw; /* Socket connected to the other end */ struct abstract_write *write; /* Where to send packets through the @@ -54,11 +66,12 @@ struct ssh_connection UINT32 max_packet; /* Key exchange */ - int kex_state; + /* int kex_state; */ /* First element is the kexinit sent by the server */ struct kexinit *kexinits[2]; struct lsh_string *literal_kexinits[2]; + struct newkeys_info *newkeys; /* Negotiated algorithms */ int ignore_one_packet; diff --git a/src/keyexchange.c b/src/keyexchange.c index c917d2af..2cece481 100644 --- a/src/keyexchange.c +++ b/src/keyexchange.c @@ -268,6 +268,87 @@ static int do_handle_kexinit(struct packet_hander *c, } } +/* FIXME: THis function can't handle IV:s at all */ +struct lsh_string *kex_make_key(struct hash_instance *secret, + UINT32 key_length, + int type, + strut lsh_string *session_id) +{ + /* Indexed by the KEX_* values */ + static const char *tags = "CDEF"; + + struct lsh_string *key; + struct hash_instance *hash; + UINT8 *digest; + + key = lsh_string_alloc(key_length); + + if (!key_length) + return key; + + hash = HASH_COPY(secret); + digest = alloca(hash->digest_size); + + HASH_UPDATE(hash, tags + type, 1); + HASH_UPDATE(hash, session_id->length, session_id->data); + HASH_DIGEST(hash, digest); + + if (key_length < hash->digest_size) + fatal("Not implemmented\n"); + + memcpy(key->data, digest, key_length); + lsh_free(hash); + return key; +} + +struct crypto_instance *kex_make_encrypt(struct hash_instance *secret, + struct crypto_algorithm *algorithm, + int type, + struct ssh_connection *connection) +{ + struct lsh_string *key = kex_make_key(secret, algorithm->key_size, + type, connection->session_id); + /* FIXME: No IV. Note that for DES, instantiating the crypto can + * fail, if the key happens to be weak. */ + struct crypto_instance *crypt + = MAKE_ENCRYPT(algorithm, key->data); + + lsh_string_free(key); + return crypt; +} + +struct crypto_instance *kex_make_decrypt(struct hash_instance *secret, + struct crypto_algorithm *algorithm, + int type, + struct ssh_connection *connection) +{ + struct lsh_string *key = kex_make_key(secret, algorithm->key_size, + type, connection->session_id); + /* FIXME: No IV. Note that for DES, instantiating the crypto can + * fail, if the key happens to be weak. */ + struct crypto_instance *crypt + = MAKE_DECRYPT(algorithm, key->data); + + lsh_string_free(key); + return crypt; +} + +struct mac_instance *kex_make_mac(struct hash_instance *secret, + struct mac_algorithm *algorithm, + int type, + struct ssh_connection *connection) +{ + struct lsh_string *key = kex_make_key(secret, algorithm->key_size, + type, connection->session_id); + + struct mac_instance *mac + = MAKE_MAC(algorithm, key->data); + + lsh_string_free(key); + return mac; +} + + static int do_handle_newkeys(struct packet_handler *c, struct ssh_connection *connection, struct lsh_string *packet) diff --git a/src/keyexchange.h b/src/keyexchange.h index 5109d207..ecfc5905 100644 --- a/src/keyexchange.h +++ b/src/keyexchange.h @@ -87,17 +87,19 @@ struct handle_keyexinit struct alist *algorithms; }; -struct handle_newkeys +struct newkeys_info { - struct packet_handler super; - /* Algorithms for transmission */ - struct crypto_algorithm *crypto; - struct mac_algorithm *mac; + struct crypto_algorithm *encryption_client_to_server; + struct crypto_algorithm *encryption_server_to_client; + struct mac_algorithm *mac_client_to_server; + struct mac_algorithm *mac_server_to_client; #if 0 - struct compression_algorithm *compressor; + struct compression_algorithm *compression_client_to_server; + struct compression_algorithm *compression_server_to_client; #endif }; + struct packet_handler *make_kexinit_handler(); struct packet_handler *make_newkeys_handler(); diff --git a/src/publickey_crypto.c b/src/publickey_crypto.c index 93c70eb5..2c0eb1db 100644 --- a/src/publickey_crypto.c +++ b/src/publickey_crypto.c @@ -400,6 +400,8 @@ void init_diffie_hellman_instance(struct diffie_hellman_method *m, self->method = m; self->hash = MAKE_HASH(m->H); + self->exchange_hash = NULL; + HASH_UPDATE(self->hash, c->client_version->length, c->client_version->data); @@ -524,17 +526,20 @@ void dh_hash_digest(struct diffie_hellman_instance *self, UINT8 *digest) struct lsh_string *dh_make_server_msg(struct diffie_hellman_instance *self, struct signer *s) { - UINT8 *digest; + struct lsh_string *msg; dh_generate_secret(self, self->f); - digest = alloca(self->hash->hash_size); - dh_hash_digest(self, digest); + self->exchange_hash = lsh_string_alloc(self->hash->hash_size); + + dh_hash_digest(self, exchange_hash->data); return ssh_format("%c%S%n%fS", SSH_MSG_KEXDH_REPLY, self->server_key, - self->f, SIGN(s, self->hash->hash_size, digest)); + self->f, SIGN(s, + self->exchange_hash->length, + self->exchange_hash->data)); } int dh_process_server_msg(struct diffie_hellman_instance *self, diff --git a/src/publickey_crypto.h b/src/publickey_crypto.h index 0f726e7a..acc97ec9 100644 --- a/src/publickey_crypto.h +++ b/src/publickey_crypto.h @@ -71,6 +71,7 @@ struct diffie_hellman_instance mpz_t secret; /* This side's secret exponent */ mpz_t lsh_string *K; struct hash_instance *hash; + struct lsh_string *exchange_hash; }; /* Creates client message */ diff --git a/src/read_packet.c b/src/read_packet.c index e2518edc..3dccdceb 100644 --- a/src/read_packet.c +++ b/src/read_packet.c @@ -184,7 +184,7 @@ int do_read_packet(struct read_handler **h, return 0; } - if (!memcpy(mac, + if (!memcmp(mac, closure->computed_mac + closure->pos, n)) /* FIXME: Free resources */ diff --git a/src/read_packet.h b/src/read_packet.h index 0901b3e8..14f441fe 100644 --- a/src/read_packet.h +++ b/src/read_packet.h @@ -28,14 +28,18 @@ #include "abstract_io.h" #include "abstract_crypto.h" +#include "newkeys.h" struct read_packet { struct read_handler super; /* Super type */ int state; - UINT32 max_packet; +#if 0 + UINT32 max_packet; +#endif + UINT32 sequence_number; /* Attached to read packets */ /* Buffer partial headers and packets. */ @@ -43,15 +47,15 @@ struct read_packet struct lsh_string *buffer; UINT32 crypt_pos; - struct mac_instance *mac; - struct crypto_instance *crypto; - UINT8 *computed_mac; /* Must point to an area large enough to hold a mac */ - + +#if 0 struct abstract_write *handler; +#endif + struct ssh_connection *connection; }; struct read_handler *make_read_packet(struct abstract_write *handler, - UINT32 max_packet); + struct ssh_connection *connection); #endif /* LSH_READ_PACKET_H_INCLUDED */ -- GitLab