mirror of
https://github.com/openssh/libopenssh
synced 2026-04-16 17:56:33 +00:00
move kex-specific states to struct kex and release states in kex_free()
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
36
ssh/kexdhc.c
36
ssh/kexdhc.c
@@ -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;
|
||||
}
|
||||
|
||||
39
ssh/kexdhs.c
39
ssh/kexdhs.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user