+/*
+ * SSH backend.
+ */
+
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
+#include <limits.h>
#include "putty.h"
#include "tree234.h"
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;
/*
* 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)
{
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;
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) {
ssh->kex->groupname);
}
- logevent("Doing Diffie-Hellman key exchange");
+ logeventf(ssh, "Doing Diffie-Hellman key exchange with hash %s",
+ ssh->kex->hash->text_name);
/*
* Now generate and send e for Diffie-Hellman.
*/
* 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",
* 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);
s->nkeys = 0;
s->agent_response = NULL;
s->pkblob_in_agent = NULL;
- if (ssh->cfg.tryagent && agent_exists() && ssh->cfg.tryagent) {
+ if (ssh->cfg.tryagent && agent_exists()) {
void *r;
}
}
-static Socket ssh_socket(void *handle)
+static int ssh_connected(void *handle)
{
Ssh ssh = (Ssh) handle;
- return ssh->s;
+ return ssh->s != NULL;
}
static int ssh_sendok(void *handle)
if (ssh->s != NULL)
return -1;
else
- return (ssh->exitcode >= 0 ? ssh->exitcode : 0);
+ return (ssh->exitcode >= 0 ? ssh->exitcode : INT_MAX);
}
/*
ssh_size,
ssh_special,
ssh_get_specials,
- ssh_socket,
+ ssh_connected,
ssh_return_exitcode,
ssh_sendok,
ssh_ldisc,