move kex-specific states to struct kex and release states in kex_free()

This commit is contained in:
Markus Friedl
2012-01-13 10:32:24 +01:00
parent 0e69e20693
commit 585db2baab
7 changed files with 87 additions and 166 deletions

View File

@@ -270,6 +270,10 @@ kex_free(Kex *kex)
{
buffer_free(&kex->peer);
buffer_free(&kex->my);
if (kex->dh)
DH_free(kex->dh);
if (kex->ec_client_key)
EC_KEY_free(kex->ec_client_key);
xfree(kex);
}

View File

@@ -136,7 +136,11 @@ struct Kex {
struct sshkey *(*load_host_private_key)(int, struct ssh *);
int (*host_key_index)(struct sshkey *);
void (*kex[KEX_MAX])(struct ssh *);
void *state;
/* kex specific state */
DH *dh; /* DH */
int min, max, nbits; /* GEX */
EC_KEY *ec_client_key; /* EC<45>H */
const EC_GROUP *ec_group; /* EC<45>H */
};
int kex_names_valid(const char *);

View File

@@ -44,48 +44,38 @@
#include "compat.h"
#include "err.h"
struct kexdhc_state {
DH *dh;
};
static int input_kex_dh(int, u_int32_t, struct ssh *);
void
kexdh_client(struct ssh *ssh)
{
Kex *kex = ssh->kex;
struct kexdhc_state *kexdhc_state;
DH *dh;
/* generate and send 'e', client DH public key */
switch (kex->kex_type) {
case KEX_DH_GRP1_SHA1:
dh = dh_new_group1();
kex->dh = dh_new_group1();
break;
case KEX_DH_GRP14_SHA1:
dh = dh_new_group14();
kex->dh = dh_new_group14();
break;
default:
fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
}
dh_gen_key(dh, kex->we_need * 8);
dh_gen_key(kex->dh, kex->we_need * 8);
ssh_packet_start(ssh, SSH2_MSG_KEXDH_INIT);
ssh_packet_put_bignum2(ssh, dh->pub_key);
ssh_packet_put_bignum2(ssh, kex->dh->pub_key);
ssh_packet_send(ssh);
debug("sending SSH2_MSG_KEXDH_INIT");
#ifdef DEBUG_KEXDH
DHparams_print_fp(stderr, dh);
DHparams_print_fp(stderr, kex->dh);
fprintf(stderr, "pub= ");
BN_print_fp(stderr, dh->pub_key);
BN_print_fp(stderr, kex->dh->pub_key);
fprintf(stderr, "\n");
#endif
debug("expecting SSH2_MSG_KEXDH_REPLY");
kexdhc_state = xcalloc(1, sizeof(*kexdhc_state));
kexdhc_state->dh = dh;
kex->state = kexdhc_state;
ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_REPLY, &input_kex_dh);
}
@@ -93,7 +83,6 @@ static int
input_kex_dh(int type, u_int32_t seq, struct ssh *ssh)
{
Kex *kex = ssh->kex;
struct kexdhc_state *kexdhc_state = kex->state;
BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
struct sshkey *server_host_key;
u_char *server_host_key_blob = NULL, *signature = NULL;
@@ -129,13 +118,13 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh)
signature = ssh_packet_get_string(ssh, &slen);
ssh_packet_check_eom(ssh);
if (!dh_pub_is_valid(kexdhc_state->dh, dh_server_pub))
if (!dh_pub_is_valid(kex->dh, dh_server_pub))
ssh_packet_disconnect(ssh,
"bad server public DH value");
klen = DH_size(kexdhc_state->dh);
klen = DH_size(kex->dh);
kbuf = xmalloc(klen);
if ((kout = DH_compute_key(kbuf, dh_server_pub, kexdhc_state->dh)) < 0)
if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0)
fatal("DH_compute_key: failed");
#ifdef DEBUG_KEXDH
dump_digest("shared secret", kbuf, kout);
@@ -154,14 +143,15 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh)
buffer_ptr(&kex->my), buffer_len(&kex->my),
buffer_ptr(&kex->peer), buffer_len(&kex->peer),
server_host_key_blob, sbloblen,
kexdhc_state->dh->pub_key,
kex->dh->pub_key,
dh_server_pub,
shared_secret,
&hash, &hashlen
);
xfree(server_host_key_blob);
BN_clear_free(dh_server_pub);
DH_free(kexdhc_state->dh);
DH_free(kex->dh);
kex->dh = NULL;
if (sshkey_verify(server_host_key, signature, slen, hash, hashlen,
datafellows) != 0)
@@ -178,8 +168,6 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh)
kex_derive_keys(ssh, hash, hashlen, shared_secret);
BN_clear_free(shared_secret);
xfree(kex->state);
kex->state = NULL;
kex_finish(ssh);
return 0;
}

View File

@@ -47,35 +47,25 @@
#include "compat.h"
#include "err.h"
struct kexdhs_state {
DH *dh;
};
static int input_kex_dh_init(int, u_int32_t, struct ssh *);
void
kexdh_server(struct ssh *ssh)
{
Kex *kex = ssh->kex;
DH *dh;
struct kexdhs_state *kexdhs_state;
/* generate server DH public key */
switch (kex->kex_type) {
case KEX_DH_GRP1_SHA1:
dh = dh_new_group1();
kex->dh = dh_new_group1();
break;
case KEX_DH_GRP14_SHA1:
dh = dh_new_group14();
kex->dh = dh_new_group14();
break;
default:
fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
}
dh_gen_key(dh, kex->we_need * 8);
kexdhs_state = xcalloc(1, sizeof(*kexdhs_state));
kexdhs_state->dh = dh;
kex->state = kexdhs_state;
dh_gen_key(kex->dh, kex->we_need * 8);
debug("expecting SSH2_MSG_KEXDH_INIT");
ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_INIT, &input_kex_dh_init);
@@ -85,16 +75,12 @@ static int
input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh)
{
Kex *kex = ssh->kex;
struct kexdhs_state *kexdhs_state = kex->state;
BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
DH *dh;
struct sshkey *server_host_public, *server_host_private;
u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
u_int sbloblen, klen, hashlen, slen;
int kout, r;
dh = kexdhs_state->dh;
if (kex->load_host_public_key == NULL ||
kex->load_host_private_key == NULL)
fatal("Cannot load hostkey");
@@ -120,18 +106,18 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh)
#endif
#ifdef DEBUG_KEXDH
DHparams_print_fp(stderr, dh);
DHparams_print_fp(stderr, kex->dh);
fprintf(stderr, "pub= ");
BN_print_fp(stderr, dh->pub_key);
BN_print_fp(stderr, kex->dh->pub_key);
fprintf(stderr, "\n");
#endif
if (!dh_pub_is_valid(dh, dh_client_pub))
if (!dh_pub_is_valid(kex->dh, dh_client_pub))
ssh_packet_disconnect(ssh,
"bad client public DH value");
klen = DH_size(dh);
klen = DH_size(kex->dh);
kbuf = xmalloc(klen);
if ((kout = DH_compute_key(kbuf, dh_client_pub, dh)) < 0)
if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0)
fatal("DH_compute_key: failed");
#ifdef DEBUG_KEXDH
dump_digest("shared secret", kbuf, kout);
@@ -155,7 +141,7 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh)
buffer_ptr(&kex->my), buffer_len(&kex->my),
server_host_key_blob, sbloblen,
dh_client_pub,
dh->pub_key,
kex->dh->pub_key,
shared_secret,
&hash, &hashlen
);
@@ -178,19 +164,18 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh)
/* send server hostkey, DH pubkey 'f' and singed H */
ssh_packet_start(ssh, SSH2_MSG_KEXDH_REPLY);
ssh_packet_put_string(ssh, server_host_key_blob, sbloblen);
ssh_packet_put_bignum2(ssh, dh->pub_key); /* f */
ssh_packet_put_bignum2(ssh, kex->dh->pub_key); /* f */
ssh_packet_put_string(ssh, signature, slen);
ssh_packet_send(ssh);
xfree(signature);
xfree(server_host_key_blob);
/* have keys, free DH */
DH_free(dh);
DH_free(kex->dh);
kex->dh = NULL;
kex_derive_keys(ssh, hash, hashlen, shared_secret);
BN_clear_free(shared_secret);
xfree(kex->state);
kex->state = NULL;
kex_finish(ssh);
return 0;
}

View File

@@ -45,11 +45,6 @@
#include "compat.h"
#include "err.h"
struct kexecdhc_state {
EC_KEY *client_key;
const EC_GROUP *group;
};
static int input_kex_ecdh_reply(int, u_int32_t, struct ssh *);
void
@@ -59,7 +54,6 @@ kexecdh_client(struct ssh *ssh)
EC_KEY *client_key;
const EC_GROUP *group;
int curve_nid;
struct kexecdhc_state *kexecdhc_state;
if ((curve_nid = kex_ecdh_name_to_nid(kex->name)) == -1)
fatal("%s: unsupported ECDH curve \"%s\"", __func__, kex->name);
@@ -79,10 +73,8 @@ kexecdh_client(struct ssh *ssh)
sshkey_dump_ec_key(client_key);
#endif
kexecdhc_state = xcalloc(1, sizeof(*kexecdhc_state));
kexecdhc_state->client_key = client_key;
kexecdhc_state->group = group;
kex->state = kexecdhc_state;
kex->ec_client_key = client_key;
kex->ec_group = group;
debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_ecdh_reply);
@@ -92,7 +84,6 @@ static int
input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh)
{
Kex *kex = ssh->kex;
struct kexecdhc_state *kexecdhc_state = kex->state;
const EC_GROUP *group;
EC_POINT *server_public;
EC_KEY *client_key;
@@ -103,8 +94,8 @@ input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh)
u_int klen, slen, sbloblen, hashlen;
int r;
group = kexecdhc_state->group;
client_key = kexecdhc_state->client_key;
group = kex->ec_group;
client_key = kex->ec_client_key;
/* hostkey */
server_host_key_blob = ssh_packet_get_string(ssh, &sbloblen);
@@ -170,7 +161,8 @@ input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh)
);
xfree(server_host_key_blob);
EC_POINT_clear_free(server_public);
EC_KEY_free(client_key);
EC_KEY_free(kex->ec_client_key);
kex->ec_client_key = NULL;
if ((r = sshkey_verify(server_host_key, signature, slen, hash,
hashlen, datafellows)) != 0)
@@ -187,8 +179,6 @@ input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh)
kex_derive_keys(ssh, hash, hashlen, shared_secret);
BN_clear_free(shared_secret);
xfree(kex->state);
kex->state = NULL;
kex_finish(ssh);
return 0;
}

View File

@@ -45,11 +45,6 @@
#include "dispatch.h"
#include "err.h"
struct kexgexc_state {
int min, max, nbits;
DH *dh;
};
static int input_kex_dh_gex_group(int, u_int32_t, struct ssh *);
static int input_kex_dh_gex_reply(int, u_int32_t, struct ssh *);
@@ -58,7 +53,6 @@ kexgex_client(struct ssh *ssh)
{
Kex *kex = ssh->kex;
int min, max, nbits;
struct kexgexc_state *kexgexc_state;
nbits = dh_estimate(kex->we_need * 8);
@@ -88,12 +82,9 @@ kexgex_client(struct ssh *ssh)
#endif
ssh_packet_send(ssh);
kexgexc_state = xcalloc(1, sizeof(*kexgexc_state));
kexgexc_state->min = min;
kexgexc_state->max = max;
kexgexc_state->nbits = nbits;
kex->state = kexgexc_state;
kex->min = min;
kex->max = max;
kex->nbits = nbits;
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, &input_kex_dh_gex_group);
}
@@ -101,14 +92,7 @@ static int
input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh)
{
Kex *kex = ssh->kex;
struct kexgexc_state *kexgexc_state = kex->state;
int min, max, nbits;
BIGNUM *p = NULL, *g = NULL;
DH *dh;
min = kexgexc_state->min;
max = kexgexc_state->max;
nbits = kexgexc_state->nbits;
debug("got SSH2_MSG_KEX_DH_GEX_GROUP");
@@ -120,27 +104,26 @@ input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh)
ssh_packet_get_bignum2(ssh, g);
ssh_packet_check_eom(ssh);
if (BN_num_bits(p) < min || BN_num_bits(p) > max)
if (BN_num_bits(p) < kex->min || BN_num_bits(p) > kex->max)
fatal("DH_GEX group out of range: %d !< %d !< %d",
min, BN_num_bits(p), max);
kex->min, BN_num_bits(p), kex->max);
dh = dh_new_group(g, p);
dh_gen_key(dh, kex->we_need * 8);
kex->dh = dh_new_group(g, p);
dh_gen_key(kex->dh, kex->we_need * 8);
#ifdef DEBUG_KEXDH
DHparams_print_fp(stderr, dh);
DHparams_print_fp(stderr, kex->dh);
fprintf(stderr, "pub= ");
BN_print_fp(stderr, dh->pub_key);
BN_print_fp(stderr, kex->dh->pub_key);
fprintf(stderr, "\n");
#endif
debug("SSH2_MSG_KEX_DH_GEX_INIT sent");
/* generate and send 'e', client DH public key */
ssh_packet_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT);
ssh_packet_put_bignum2(ssh, dh->pub_key);
ssh_packet_put_bignum2(ssh, kex->dh->pub_key);
ssh_packet_send(ssh);
kexgexc_state->dh = dh;
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, NULL);
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &input_kex_dh_gex_reply);
return 0;
@@ -150,19 +133,11 @@ static int
input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
{
Kex *kex = ssh->kex;
struct kexgexc_state *kexgexc_state = kex->state;
BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
struct sshkey *server_host_key;
u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
u_int klen, slen, sbloblen, hashlen;
int kout, min, max, nbits, r;
DH *dh;
debug("%s %p %p", __func__, kex, kexgexc_state);
dh = kexgexc_state->dh;
min = kexgexc_state->min;
max = kexgexc_state->max;
nbits = kexgexc_state->nbits;
int kout, r;
debug("got SSH2_MSG_KEX_DH_GEX_REPLY");
@@ -194,13 +169,13 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
signature = ssh_packet_get_string(ssh, &slen);
ssh_packet_check_eom(ssh);
if (!dh_pub_is_valid(dh, dh_server_pub))
if (!dh_pub_is_valid(kex->dh, dh_server_pub))
ssh_packet_disconnect(ssh,
"bad server public DH value");
klen = DH_size(dh);
klen = DH_size(kex->dh);
kbuf = xmalloc(klen);
if ((kout = DH_compute_key(kbuf, dh_server_pub, dh)) < 0)
if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0)
fatal("DH_compute_key: failed");
#ifdef DEBUG_KEXDH
dump_digest("shared secret", kbuf, kout);
@@ -213,7 +188,7 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
xfree(kbuf);
if (ssh->datafellows & SSH_OLD_DHGEX)
min = max = -1;
kex->min = kex->max = -1;
/* calc and verify H */
kexgex_hash(
@@ -223,16 +198,17 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
buffer_ptr(&kex->my), buffer_len(&kex->my),
buffer_ptr(&kex->peer), buffer_len(&kex->peer),
server_host_key_blob, sbloblen,
min, nbits, max,
dh->p, dh->g,
dh->pub_key,
kex->min, kex->nbits, kex->max,
kex->dh->p, kex->dh->g,
kex->dh->pub_key,
dh_server_pub,
shared_secret,
&hash, &hashlen
);
/* have keys, free DH */
DH_free(dh);
DH_free(kex->dh);
kex->dh = NULL;
xfree(server_host_key_blob);
BN_clear_free(dh_server_pub);
@@ -252,8 +228,6 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
BN_clear_free(shared_secret);
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, NULL);
xfree(kex->state);
kex->state = NULL;
kex_finish(ssh);
return 0;
}

View File

@@ -49,29 +49,24 @@
#include "dispatch.h"
#include "err.h"
struct kexgexs_state {
int omin, min, omax, max, onbits;
DH *dh;
};
static int input_kex_dh_gex_init(int, u_int32_t, struct ssh *);
void
kexgex_server(struct ssh *ssh)
{
Kex *kex = ssh->kex;
DH *dh;
int omin = -1, min = -1, omax = -1, max = -1, onbits = -1, nbits = -1;
int min = -1, max = -1, nbits = -1;
int type;
struct kexgexs_state *kexgexs_state;
kex->min = kex->nbits = kex->max = -1;
type = ssh_packet_read(ssh);
switch (type) {
case SSH2_MSG_KEX_DH_GEX_REQUEST:
debug("SSH2_MSG_KEX_DH_GEX_REQUEST received");
omin = min = ssh_packet_get_int(ssh);
onbits = nbits = ssh_packet_get_int(ssh);
omax = max = ssh_packet_get_int(ssh);
kex->min = min = ssh_packet_get_int(ssh);
kex->nbits = nbits = ssh_packet_get_int(ssh);
kex->max = max = ssh_packet_get_int(ssh);
min = MAX(DH_GRP_MIN, min);
max = MIN(DH_GRP_MAX, max);
nbits = MAX(DH_GRP_MIN, nbits);
@@ -79,46 +74,37 @@ kexgex_server(struct ssh *ssh)
break;
case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD:
debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received");
onbits = nbits = ssh_packet_get_int(ssh);
kex->nbits = nbits = ssh_packet_get_int(ssh);
/* unused for old GEX */
omin = min = DH_GRP_MIN;
omax = max = DH_GRP_MAX;
kex->min = min = DH_GRP_MIN;
kex->max = max = DH_GRP_MAX;
break;
default:
fatal("protocol error during kex, no DH_GEX_REQUEST: %d", type);
}
ssh_packet_check_eom(ssh);
if (omax < omin || onbits < omin || omax < onbits)
if (kex->max < kex->min || kex->nbits < kex->min || kex->max < kex->nbits)
fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d",
omin, onbits, omax);
kex->min, kex->nbits, kex->max);
/* Contact privileged parent */
dh = PRIVSEP(choose_dh(min, nbits, max));
if (dh == NULL)
kex->dh = PRIVSEP(choose_dh(min, nbits, max));
if (kex->dh == NULL)
ssh_packet_disconnect(ssh,
"Protocol error: no matching DH grp found");
debug("SSH2_MSG_KEX_DH_GEX_GROUP sent");
ssh_packet_start(ssh, SSH2_MSG_KEX_DH_GEX_GROUP);
ssh_packet_put_bignum2(ssh, dh->p);
ssh_packet_put_bignum2(ssh, dh->g);
ssh_packet_put_bignum2(ssh, kex->dh->p);
ssh_packet_put_bignum2(ssh, kex->dh->g);
ssh_packet_send(ssh);
/* flush */
ssh_packet_write_wait(ssh);
/* Compute our exchange value in parallel with the client */
dh_gen_key(dh, kex->we_need * 8);
kexgexs_state = xcalloc(1, sizeof(*kexgexs_state));
kexgexs_state->omin = omin;
kexgexs_state->omax = omax;
kexgexs_state->min = min;
kexgexs_state->max = max;
kexgexs_state->onbits = onbits;
kexgexs_state->dh = dh;
kex->state = kexgexs_state;
dh_gen_key(kex->dh, kex->we_need * 8);
debug("expecting SSH2_MSG_KEX_DH_GEX_INIT");
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &input_kex_dh_gex_init);
@@ -128,20 +114,11 @@ static int
input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
{
Kex *kex = ssh->kex;
struct kexgexs_state *kexgexs_state = kex->state;
BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
struct sshkey *server_host_public, *server_host_private;
DH *dh;
u_int sbloblen, klen, slen, hashlen;
u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
int omin, min, omax, max, onbits, kout, r;
dh = kexgexs_state->dh;
omin = kexgexs_state->omin;
min = kexgexs_state->min;
omax = kexgexs_state->omax;
max = kexgexs_state->max;
onbits = kexgexs_state->onbits;
int kout, r;
if (kex->load_host_public_key == NULL ||
kex->load_host_private_key == NULL)
@@ -168,18 +145,18 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
#endif
#ifdef DEBUG_KEXDH
DHparams_print_fp(stderr, dh);
DHparams_print_fp(stderr, kex->dh);
fprintf(stderr, "pub= ");
BN_print_fp(stderr, dh->pub_key);
fprintf(stderr, "\n");
#endif
if (!dh_pub_is_valid(dh, dh_client_pub))
if (!dh_pub_is_valid(kex->dh, dh_client_pub))
ssh_packet_disconnect(ssh,
"bad client public DH value");
klen = DH_size(dh);
klen = DH_size(kex->dh);
kbuf = xmalloc(klen);
if ((kout = DH_compute_key(kbuf, dh_client_pub, dh)) < 0)
if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0)
fatal("DH_compute_key: failed");
#ifdef DEBUG_KEXDH
dump_digest("shared secret", kbuf, kout);
@@ -196,7 +173,7 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
fatal("%s: sshkey_to_blob failed: %s", __func__, ssh_err(r));
if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD)
omin = min = omax = max = -1;
kex->min = kex->max = -1;
/* calc H */
kexgex_hash(
@@ -206,10 +183,10 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
buffer_ptr(&kex->peer), buffer_len(&kex->peer),
buffer_ptr(&kex->my), buffer_len(&kex->my),
server_host_key_blob, sbloblen,
omin, onbits, omax,
dh->p, dh->g,
kex->min, kex->nbits, kex->max,
kex->dh->p, kex->dh->g,
dh_client_pub,
dh->pub_key,
kex->dh->pub_key,
shared_secret,
&hash, &hashlen
);
@@ -233,20 +210,19 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
debug("SSH2_MSG_KEX_DH_GEX_REPLY sent");
ssh_packet_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY);
ssh_packet_put_string(ssh, server_host_key_blob, sbloblen);
ssh_packet_put_bignum2(ssh, dh->pub_key); /* f */
ssh_packet_put_bignum2(ssh, kex->dh->pub_key); /* f */
ssh_packet_put_string(ssh, signature, slen);
ssh_packet_send(ssh);
xfree(signature);
xfree(server_host_key_blob);
/* have keys, free DH */
DH_free(dh);
DH_free(kex->dh);
kex->dh = NULL;
kex_derive_keys(ssh, hash, hashlen, shared_secret);
BN_clear_free(shared_secret);
xfree(kex->state);
kex->state = NULL;
kex_finish(ssh);
return 0;
}