version 1.99, 2014/04/29 18:01:49 |
version 1.100, 2015/01/19 19:52:16 |
|
|
debug("SSH2_MSG_NEWKEYS received"); |
debug("SSH2_MSG_NEWKEYS received"); |
|
|
kex->done = 1; |
kex->done = 1; |
buffer_clear(&kex->peer); |
buffer_clear(kex->peer); |
/* buffer_clear(&kex->my); */ |
/* buffer_clear(kex->my); */ |
kex->flags &= ~KEX_INIT_SENT; |
kex->flags &= ~KEX_INIT_SENT; |
free(kex->name); |
free(kex->name); |
kex->name = NULL; |
kex->name = NULL; |
|
|
kex->done = 0; |
kex->done = 0; |
|
|
/* generate a random cookie */ |
/* generate a random cookie */ |
if (buffer_len(&kex->my) < KEX_COOKIE_LEN) |
if (buffer_len(kex->my) < KEX_COOKIE_LEN) |
fatal("kex_send_kexinit: kex proposal too short"); |
fatal("kex_send_kexinit: kex proposal too short"); |
cookie = buffer_ptr(&kex->my); |
cookie = buffer_ptr(kex->my); |
for (i = 0; i < KEX_COOKIE_LEN; i++) { |
for (i = 0; i < KEX_COOKIE_LEN; i++) { |
if (i % 4 == 0) |
if (i % 4 == 0) |
rnd = arc4random(); |
rnd = arc4random(); |
|
|
rnd >>= 8; |
rnd >>= 8; |
} |
} |
packet_start(SSH2_MSG_KEXINIT); |
packet_start(SSH2_MSG_KEXINIT); |
packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); |
packet_put_raw(buffer_ptr(kex->my), buffer_len(kex->my)); |
packet_send(); |
packet_send(); |
debug("SSH2_MSG_KEXINIT sent"); |
debug("SSH2_MSG_KEXINIT sent"); |
kex->flags |= KEX_INIT_SENT; |
kex->flags |= KEX_INIT_SENT; |
|
|
void |
void |
kex_input_kexinit(int type, u_int32_t seq, void *ctxt) |
kex_input_kexinit(int type, u_int32_t seq, void *ctxt) |
{ |
{ |
char *ptr; |
const char *ptr; |
u_int i, dlen; |
u_int i; |
|
size_t dlen; |
Kex *kex = (Kex *)ctxt; |
Kex *kex = (Kex *)ctxt; |
|
|
debug("SSH2_MSG_KEXINIT received"); |
debug("SSH2_MSG_KEXINIT received"); |
|
|
fatal("kex_input_kexinit: no kex, cannot rekey"); |
fatal("kex_input_kexinit: no kex, cannot rekey"); |
|
|
ptr = packet_get_raw(&dlen); |
ptr = packet_get_raw(&dlen); |
buffer_append(&kex->peer, ptr, dlen); |
buffer_append(kex->peer, ptr, dlen); |
|
|
/* discard packet */ |
/* discard packet */ |
for (i = 0; i < KEX_COOKIE_LEN; i++) |
for (i = 0; i < KEX_COOKIE_LEN; i++) |
|
|
kex_kexinit_finish(kex); |
kex_kexinit_finish(kex); |
} |
} |
|
|
|
void |
|
kex_free_newkeys(struct newkeys *newkeys) |
|
{ |
|
if (newkeys == NULL) |
|
return; |
|
if (newkeys->enc.key) { |
|
explicit_bzero(newkeys->enc.key, newkeys->enc.key_len); |
|
free(newkeys->enc.key); |
|
newkeys->enc.key = NULL; |
|
} |
|
if (newkeys->enc.iv) { |
|
explicit_bzero(newkeys->enc.iv, newkeys->enc.block_size); |
|
free(newkeys->enc.iv); |
|
newkeys->enc.iv = NULL; |
|
} |
|
free(newkeys->enc.name); |
|
explicit_bzero(&newkeys->enc, sizeof(newkeys->enc)); |
|
free(newkeys->comp.name); |
|
explicit_bzero(&newkeys->comp, sizeof(newkeys->comp)); |
|
mac_clear(&newkeys->mac); |
|
if (newkeys->mac.key) { |
|
explicit_bzero(newkeys->mac.key, newkeys->mac.key_len); |
|
free(newkeys->mac.key); |
|
newkeys->mac.key = NULL; |
|
} |
|
free(newkeys->mac.name); |
|
explicit_bzero(&newkeys->mac, sizeof(newkeys->mac)); |
|
explicit_bzero(newkeys, sizeof(*newkeys)); |
|
free(newkeys); |
|
} |
|
|
Kex * |
Kex * |
kex_setup(char *proposal[PROPOSAL_MAX]) |
kex_setup(char *proposal[PROPOSAL_MAX]) |
{ |
{ |
Kex *kex; |
struct kex *kex; |
|
|
kex = xcalloc(1, sizeof(*kex)); |
if ((kex = calloc(1, sizeof(*kex))) == NULL) |
buffer_init(&kex->peer); |
fatal("%s: calloc", __func__); |
buffer_init(&kex->my); |
if ((kex->peer = sshbuf_new()) == NULL || |
kex_prop2buf(&kex->my, proposal); |
(kex->my = sshbuf_new()) == NULL) { |
|
fatal("%s: sshbuf_new", __func__); |
|
} |
|
kex_prop2buf(kex->my, proposal); |
kex->done = 0; |
kex->done = 0; |
|
|
kex_send_kexinit(kex); /* we start */ |
kex_send_kexinit(kex); /* we start */ |
|
|
u_int mode, ctos, need, dh_need, authlen; |
u_int mode, ctos, need, dh_need, authlen; |
int first_kex_follows, type; |
int first_kex_follows, type; |
|
|
my = kex_buf2prop(&kex->my, NULL); |
my = kex_buf2prop(kex->my, NULL); |
peer = kex_buf2prop(&kex->peer, &first_kex_follows); |
peer = kex_buf2prop(kex->peer, &first_kex_follows); |
|
|
if (kex->server) { |
if (kex->server) { |
cprop=peer; |
cprop=peer; |
|
|
return digest; |
return digest; |
} |
} |
|
|
Newkeys *current_keys[MODE_MAX]; |
|
|
|
#define NKEYS 6 |
#define NKEYS 6 |
void |
void |
kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, |
kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, |
|
|
|
|
debug2("kex_derive_keys"); |
debug2("kex_derive_keys"); |
for (mode = 0; mode < MODE_MAX; mode++) { |
for (mode = 0; mode < MODE_MAX; mode++) { |
current_keys[mode] = kex->newkeys[mode]; |
|
kex->newkeys[mode] = NULL; |
|
ctos = (!kex->server && mode == MODE_OUT) || |
ctos = (!kex->server && mode == MODE_OUT) || |
(kex->server && mode == MODE_IN); |
(kex->server && mode == MODE_IN); |
current_keys[mode]->enc.iv = keys[ctos ? 0 : 1]; |
kex->newkeys[mode]->enc.iv = keys[ctos ? 0 : 1]; |
current_keys[mode]->enc.key = keys[ctos ? 2 : 3]; |
kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3]; |
current_keys[mode]->mac.key = keys[ctos ? 4 : 5]; |
kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5]; |
} |
} |
} |
} |
|
|
|
|
buffer_free(&shared_secret); |
buffer_free(&shared_secret); |
} |
} |
#endif |
#endif |
|
|
Newkeys * |
|
kex_get_newkeys(int mode) |
|
{ |
|
Newkeys *ret; |
|
|
|
ret = current_keys[mode]; |
|
current_keys[mode] = NULL; |
|
return ret; |
|
} |
|
|
|
#ifdef WITH_SSH1 |
#ifdef WITH_SSH1 |
void |
void |