Commit d462a169 authored by Niels Möller's avatar Niels Möller

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
parent cb961e3a
...@@ -29,6 +29,8 @@ static void do_handle_dh_reply(struct packet_handler *c, ...@@ -29,6 +29,8 @@ static void do_handle_dh_reply(struct packet_handler *c,
{ {
struct dh_client *closure = (struct dh_client *) c; struct dh_client *closure = (struct dh_client *) c;
struct verifier *v; struct verifier *v;
struct hash_instance *hash;;
struct lsh_string *s;
if (!dh_process_server_msg(&closure->dh, packet)) if (!dh_process_server_msg(&closure->dh, packet))
return send_disconnect(connection, "Bad dh-reply\r\n"); return send_disconnect(connection, "Bad dh-reply\r\n");
...@@ -45,10 +47,24 @@ static void do_handle_dh_reply(struct packet_handler *c, ...@@ -45,10 +47,24 @@ static void do_handle_dh_reply(struct packet_handler *c,
/* FIXME: Same here */ /* FIXME: Same here */
return send_disconnect(connection, "Bad server host key\r\n"); 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, static void do_init_dh(struct keyexchange_algorithm *c,
...@@ -62,8 +78,7 @@ 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; dh->super.handler = do_handle_dh_reply;
init_diffie_hellman_instance(closure->dh, &dh->dh, connection); init_diffie_hellman_instance(closure->dh, &dh->dh, connection);
dh->hash = MAKE_HASH(closure->hash); dh->verifier = closure->verifier;
dh->signature_algorithm = closure->signature_algorithm;
/* Send client's message */ /* Send client's message */
A_WRITE(connection->write, dh_make_client_msg(&dh->dh)); A_WRITE(connection->write, dh_make_client_msg(&dh->dh));
...@@ -78,3 +93,22 @@ static void do_init_dh(struct keyexchange_algorithm *c, ...@@ -78,3 +93,22 @@ static void do_init_dh(struct keyexchange_algorithm *c,
return WRITE_OK; 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);
...@@ -45,7 +45,6 @@ struct dh_algorithm_client ...@@ -45,7 +45,6 @@ struct dh_algorithm_client
{ {
struct keyexchange_algorithm super; struct keyexchange_algorithm super;
struct diffie_hellman_method dh; struct diffie_hellman_method dh;
struct hash_algorithm *hash;
struct lookup_verifier *verifier; struct lookup_verifier *verifier;
}; };
...@@ -54,7 +53,6 @@ struct dh_client ...@@ -54,7 +53,6 @@ struct dh_client
{ {
struct packet_handler super; struct packet_handler super;
struct diffie_hellman_instance dh; struct diffie_hellman_instance dh;
struct hash_instance *hash;
struct lookup_verifier *verifier; struct lookup_verifier *verifier;
struct packet_handler *saved_kexinit_handler; struct packet_handler *saved_kexinit_handler;
}; };
......
...@@ -29,7 +29,14 @@ struct packet_handler ...@@ -29,7 +29,14 @@ struct packet_handler
struct ssh_connection struct ssh_connection
{ {
#if 0
struct abstract_write super; 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 */ int type; /* CONNECTION_SERVER or CONNECTION_CLIENT */
...@@ -38,6 +45,11 @@ struct ssh_connection ...@@ -38,6 +45,11 @@ struct ssh_connection
struct lsh_string *server_version; struct lsh_string *server_version;
struct lsh_string *session_id; 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 *raw; /* Socket connected to the other end */
struct abstract_write *write; /* Where to send packets through the struct abstract_write *write; /* Where to send packets through the
...@@ -54,11 +66,12 @@ struct ssh_connection ...@@ -54,11 +66,12 @@ struct ssh_connection
UINT32 max_packet; UINT32 max_packet;
/* Key exchange */ /* Key exchange */
int kex_state; /* int kex_state; */
/* First element is the kexinit sent by the server */ /* First element is the kexinit sent by the server */
struct kexinit *kexinits[2]; struct kexinit *kexinits[2];
struct lsh_string *literal_kexinits[2]; struct lsh_string *literal_kexinits[2];
struct newkeys_info *newkeys; /* Negotiated algorithms */
int ignore_one_packet; int ignore_one_packet;
......
...@@ -268,6 +268,87 @@ static int do_handle_kexinit(struct packet_hander *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, static int do_handle_newkeys(struct packet_handler *c,
struct ssh_connection *connection, struct ssh_connection *connection,
struct lsh_string *packet) struct lsh_string *packet)
......
...@@ -87,17 +87,19 @@ struct handle_keyexinit ...@@ -87,17 +87,19 @@ struct handle_keyexinit
struct alist *algorithms; struct alist *algorithms;
}; };
struct handle_newkeys struct newkeys_info
{ {
struct packet_handler super; struct crypto_algorithm *encryption_client_to_server;
/* Algorithms for transmission */ struct crypto_algorithm *encryption_server_to_client;
struct crypto_algorithm *crypto; struct mac_algorithm *mac_client_to_server;
struct mac_algorithm *mac; struct mac_algorithm *mac_server_to_client;
#if 0 #if 0
struct compression_algorithm *compressor; struct compression_algorithm *compression_client_to_server;
struct compression_algorithm *compression_server_to_client;
#endif #endif
}; };
struct packet_handler *make_kexinit_handler(); struct packet_handler *make_kexinit_handler();
struct packet_handler *make_newkeys_handler(); struct packet_handler *make_newkeys_handler();
......
...@@ -400,6 +400,8 @@ void init_diffie_hellman_instance(struct diffie_hellman_method *m, ...@@ -400,6 +400,8 @@ void init_diffie_hellman_instance(struct diffie_hellman_method *m,
self->method = m; self->method = m;
self->hash = MAKE_HASH(m->H); self->hash = MAKE_HASH(m->H);
self->exchange_hash = NULL;
HASH_UPDATE(self->hash, HASH_UPDATE(self->hash,
c->client_version->length, c->client_version->length,
c->client_version->data); c->client_version->data);
...@@ -524,17 +526,20 @@ void dh_hash_digest(struct diffie_hellman_instance *self, UINT8 *digest) ...@@ -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 lsh_string *dh_make_server_msg(struct diffie_hellman_instance *self,
struct signer *s) struct signer *s)
{ {
UINT8 *digest; struct lsh_string *msg;
dh_generate_secret(self, self->f); dh_generate_secret(self, self->f);
digest = alloca(self->hash->hash_size); self->exchange_hash = lsh_string_alloc(self->hash->hash_size);
dh_hash_digest(self, digest);
dh_hash_digest(self, exchange_hash->data);
return ssh_format("%c%S%n%fS", return ssh_format("%c%S%n%fS",
SSH_MSG_KEXDH_REPLY, SSH_MSG_KEXDH_REPLY,
self->server_key, 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, int dh_process_server_msg(struct diffie_hellman_instance *self,
......
...@@ -71,6 +71,7 @@ struct diffie_hellman_instance ...@@ -71,6 +71,7 @@ struct diffie_hellman_instance
mpz_t secret; /* This side's secret exponent */ mpz_t secret; /* This side's secret exponent */
mpz_t lsh_string *K; mpz_t lsh_string *K;
struct hash_instance *hash; struct hash_instance *hash;
struct lsh_string *exchange_hash;
}; };
/* Creates client message */ /* Creates client message */
......
...@@ -184,7 +184,7 @@ int do_read_packet(struct read_handler **h, ...@@ -184,7 +184,7 @@ int do_read_packet(struct read_handler **h,
return 0; return 0;
} }
if (!memcpy(mac, if (!memcmp(mac,
closure->computed_mac + closure->pos, closure->computed_mac + closure->pos,
n)) n))
/* FIXME: Free resources */ /* FIXME: Free resources */
......
...@@ -28,14 +28,18 @@ ...@@ -28,14 +28,18 @@
#include "abstract_io.h" #include "abstract_io.h"
#include "abstract_crypto.h" #include "abstract_crypto.h"
#include "newkeys.h"
struct read_packet struct read_packet
{ {
struct read_handler super; /* Super type */ struct read_handler super; /* Super type */
int state; int state;
UINT32 max_packet;
#if 0
UINT32 max_packet;
#endif
UINT32 sequence_number; /* Attached to read packets */ UINT32 sequence_number; /* Attached to read packets */
/* Buffer partial headers and packets. */ /* Buffer partial headers and packets. */
...@@ -43,15 +47,15 @@ struct read_packet ...@@ -43,15 +47,15 @@ struct read_packet
struct lsh_string *buffer; struct lsh_string *buffer;
UINT32 crypt_pos; 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 */ UINT8 *computed_mac; /* Must point to an area large enough to hold a mac */
#if 0
struct abstract_write *handler; struct abstract_write *handler;
#endif
struct ssh_connection *connection;
}; };
struct read_handler *make_read_packet(struct abstract_write *handler, struct read_handler *make_read_packet(struct abstract_write *handler,
UINT32 max_packet); struct ssh_connection *connection);
#endif /* LSH_READ_PACKET_H_INCLUDED */ #endif /* LSH_READ_PACKET_H_INCLUDED */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment