version 1.29, 2001/04/04 14:34:58 |
version 1.30, 2001/04/04 20:25:37 |
|
|
debug("waiting for SSH2_MSG_NEWKEYS"); |
debug("waiting for SSH2_MSG_NEWKEYS"); |
packet_read_expect(&plen, SSH2_MSG_NEWKEYS); |
packet_read_expect(&plen, SSH2_MSG_NEWKEYS); |
debug("SSH2_MSG_NEWKEYS received"); |
debug("SSH2_MSG_NEWKEYS received"); |
kex->newkeys = 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; |
|
|
debug("KEX_INIT_SENT"); |
debug("KEX_INIT_SENT"); |
return; |
return; |
} |
} |
|
kex->done = 0; |
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(); |
|
|
buffer_init(&kex->peer); |
buffer_init(&kex->peer); |
buffer_init(&kex->my); |
buffer_init(&kex->my); |
kex_prop2buf(&kex->my, proposal); |
kex_prop2buf(&kex->my, proposal); |
kex->newkeys = 0; |
kex->done = 0; |
|
|
kex_send_kexinit(kex); /* we start */ |
kex_send_kexinit(kex); /* we start */ |
kex_clear_dispatch(); |
kex_clear_dispatch(); |
|
|
sprop=peer; |
sprop=peer; |
} |
} |
|
|
|
/* Algorithm Negotiation */ |
for (mode = 0; mode < MODE_MAX; mode++) { |
for (mode = 0; mode < MODE_MAX; mode++) { |
newkeys = xmalloc(sizeof(*newkeys)); |
newkeys = xmalloc(sizeof(*newkeys)); |
memset(newkeys, 0, sizeof(*newkeys)); |
memset(newkeys, 0, sizeof(*newkeys)); |
kex->keys[mode] = newkeys; |
kex->newkeys[mode] = newkeys; |
ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); |
ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); |
nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; |
nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; |
nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; |
nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; |
|
|
sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); |
sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); |
need = 0; |
need = 0; |
for (mode = 0; mode < MODE_MAX; mode++) { |
for (mode = 0; mode < MODE_MAX; mode++) { |
newkeys = kex->keys[mode]; |
newkeys = kex->newkeys[mode]; |
if (need < newkeys->enc.cipher->key_len) |
if (need < newkeys->enc.cipher->key_len) |
need = newkeys->enc.cipher->key_len; |
need = newkeys->enc.cipher->key_len; |
if (need < newkeys->enc.cipher->block_size) |
if (need < newkeys->enc.cipher->block_size) |
|
|
char c = id; |
char c = id; |
int have; |
int have; |
int mdsz = evp_md->md_size; |
int mdsz = evp_md->md_size; |
u_char *digest = xmalloc(((need+mdsz-1)/mdsz)*mdsz); |
u_char *digest = xmalloc(roundup(need, mdsz)); |
|
|
buffer_init(&b); |
buffer_init(&b); |
buffer_put_bignum2(&b, shared_secret); |
buffer_put_bignum2(&b, shared_secret); |
|
|
|
/* K1 = HASH(K || H || "A" || session_id) */ |
EVP_DigestInit(&md, evp_md); |
EVP_DigestInit(&md, evp_md); |
EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); /* shared_secret K */ |
EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); |
EVP_DigestUpdate(&md, hash, mdsz); /* transport-06 */ |
EVP_DigestUpdate(&md, hash, mdsz); |
EVP_DigestUpdate(&md, &c, 1); /* key id */ |
EVP_DigestUpdate(&md, &c, 1); |
EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); |
EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); |
EVP_DigestFinal(&md, digest, NULL); |
EVP_DigestFinal(&md, digest, NULL); |
|
|
/* expand */ |
/* |
|
* expand key: |
|
* Kn = HASH(K || H || K1 || K2 || ... || Kn-1) |
|
* Key = K1 || K2 || ... || Kn |
|
*/ |
for (have = mdsz; need > have; have += mdsz) { |
for (have = mdsz; need > have; have += mdsz) { |
EVP_DigestInit(&md, evp_md); |
EVP_DigestInit(&md, evp_md); |
EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); |
EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); |
|
|
return digest; |
return digest; |
} |
} |
|
|
Newkeys *x_newkeys[MODE_MAX]; |
Newkeys *current_keys[MODE_MAX]; |
|
|
#define NKEYS 6 |
#define NKEYS 6 |
void |
void |
kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret) |
kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret) |
{ |
{ |
Newkeys *newkeys; |
|
u_char *keys[NKEYS]; |
u_char *keys[NKEYS]; |
int i, mode, ctos; |
int i, mode, ctos; |
|
|
|
|
|
|
debug("kex_derive_keys"); |
debug("kex_derive_keys"); |
for (mode = 0; mode < MODE_MAX; mode++) { |
for (mode = 0; mode < MODE_MAX; mode++) { |
newkeys = kex->keys[mode]; |
current_keys[mode] = kex->newkeys[mode]; |
|
kex->newkeys[mode] = NULL; |
ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); |
ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); |
newkeys->enc.iv = keys[ctos ? 0 : 1]; |
current_keys[mode]->enc.iv = keys[ctos ? 0 : 1]; |
newkeys->enc.key = keys[ctos ? 2 : 3]; |
current_keys[mode]->enc.key = keys[ctos ? 2 : 3]; |
newkeys->mac.key = keys[ctos ? 4 : 5]; |
current_keys[mode]->mac.key = keys[ctos ? 4 : 5]; |
x_newkeys[mode] = newkeys; |
|
} |
} |
} |
} |
|
|
Newkeys * |
Newkeys * |
kex_get_newkeys(int mode) |
kex_get_newkeys(int mode) |
{ |
{ |
return x_newkeys[mode]; |
Newkeys *ret; |
|
|
|
ret = current_keys[mode]; |
|
current_keys[mode] = NULL; |
|
return ret; |
} |
} |
|
|
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) |
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) |