diff options
Diffstat (limited to 'kex.c')
-rw-r--r-- | kex.c | 46 |
1 files changed, 28 insertions, 18 deletions
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: kex.c,v 1.29 2001/04/04 14:34:58 markus Exp $"); | 26 | RCSID("$OpenBSD: kex.c,v 1.30 2001/04/04 20:25:37 markus Exp $"); |
27 | 27 | ||
28 | #include <openssl/crypto.h> | 28 | #include <openssl/crypto.h> |
29 | 29 | ||
@@ -136,7 +136,7 @@ kex_finish(Kex *kex) | |||
136 | debug("waiting for SSH2_MSG_NEWKEYS"); | 136 | debug("waiting for SSH2_MSG_NEWKEYS"); |
137 | packet_read_expect(&plen, SSH2_MSG_NEWKEYS); | 137 | packet_read_expect(&plen, SSH2_MSG_NEWKEYS); |
138 | debug("SSH2_MSG_NEWKEYS received"); | 138 | debug("SSH2_MSG_NEWKEYS received"); |
139 | kex->newkeys = 1; | 139 | kex->done = 1; |
140 | buffer_clear(&kex->peer); | 140 | buffer_clear(&kex->peer); |
141 | /* buffer_clear(&kex->my); */ | 141 | /* buffer_clear(&kex->my); */ |
142 | kex->flags &= ~KEX_INIT_SENT; | 142 | kex->flags &= ~KEX_INIT_SENT; |
@@ -153,6 +153,7 @@ kex_send_kexinit(Kex *kex) | |||
153 | debug("KEX_INIT_SENT"); | 153 | debug("KEX_INIT_SENT"); |
154 | return; | 154 | return; |
155 | } | 155 | } |
156 | kex->done = 0; | ||
156 | packet_start(SSH2_MSG_KEXINIT); | 157 | packet_start(SSH2_MSG_KEXINIT); |
157 | packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); | 158 | packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); |
158 | packet_send(); | 159 | packet_send(); |
@@ -187,7 +188,7 @@ kex_setup(char *proposal[PROPOSAL_MAX]) | |||
187 | buffer_init(&kex->peer); | 188 | buffer_init(&kex->peer); |
188 | buffer_init(&kex->my); | 189 | buffer_init(&kex->my); |
189 | kex_prop2buf(&kex->my, proposal); | 190 | kex_prop2buf(&kex->my, proposal); |
190 | kex->newkeys = 0; | 191 | kex->done = 0; |
191 | 192 | ||
192 | kex_send_kexinit(kex); /* we start */ | 193 | kex_send_kexinit(kex); /* we start */ |
193 | kex_clear_dispatch(); | 194 | kex_clear_dispatch(); |
@@ -307,10 +308,11 @@ kex_choose_conf(Kex *kex) | |||
307 | sprop=peer; | 308 | sprop=peer; |
308 | } | 309 | } |
309 | 310 | ||
311 | /* Algorithm Negotiation */ | ||
310 | for (mode = 0; mode < MODE_MAX; mode++) { | 312 | for (mode = 0; mode < MODE_MAX; mode++) { |
311 | newkeys = xmalloc(sizeof(*newkeys)); | 313 | newkeys = xmalloc(sizeof(*newkeys)); |
312 | memset(newkeys, 0, sizeof(*newkeys)); | 314 | memset(newkeys, 0, sizeof(*newkeys)); |
313 | kex->keys[mode] = newkeys; | 315 | kex->newkeys[mode] = newkeys; |
314 | ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); | 316 | ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); |
315 | nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; | 317 | nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; |
316 | nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; | 318 | nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; |
@@ -329,7 +331,7 @@ kex_choose_conf(Kex *kex) | |||
329 | sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); | 331 | sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); |
330 | need = 0; | 332 | need = 0; |
331 | for (mode = 0; mode < MODE_MAX; mode++) { | 333 | for (mode = 0; mode < MODE_MAX; mode++) { |
332 | newkeys = kex->keys[mode]; | 334 | newkeys = kex->newkeys[mode]; |
333 | if (need < newkeys->enc.cipher->key_len) | 335 | if (need < newkeys->enc.cipher->key_len) |
334 | need = newkeys->enc.cipher->key_len; | 336 | need = newkeys->enc.cipher->key_len; |
335 | if (need < newkeys->enc.cipher->block_size) | 337 | if (need < newkeys->enc.cipher->block_size) |
@@ -353,19 +355,24 @@ derive_key(Kex *kex, int id, int need, u_char *hash, BIGNUM *shared_secret) | |||
353 | char c = id; | 355 | char c = id; |
354 | int have; | 356 | int have; |
355 | int mdsz = evp_md->md_size; | 357 | int mdsz = evp_md->md_size; |
356 | u_char *digest = xmalloc(((need+mdsz-1)/mdsz)*mdsz); | 358 | u_char *digest = xmalloc(roundup(need, mdsz)); |
357 | 359 | ||
358 | buffer_init(&b); | 360 | buffer_init(&b); |
359 | buffer_put_bignum2(&b, shared_secret); | 361 | buffer_put_bignum2(&b, shared_secret); |
360 | 362 | ||
363 | /* K1 = HASH(K || H || "A" || session_id) */ | ||
361 | EVP_DigestInit(&md, evp_md); | 364 | EVP_DigestInit(&md, evp_md); |
362 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); /* shared_secret K */ | 365 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); |
363 | EVP_DigestUpdate(&md, hash, mdsz); /* transport-06 */ | 366 | EVP_DigestUpdate(&md, hash, mdsz); |
364 | EVP_DigestUpdate(&md, &c, 1); /* key id */ | 367 | EVP_DigestUpdate(&md, &c, 1); |
365 | EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); | 368 | EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); |
366 | EVP_DigestFinal(&md, digest, NULL); | 369 | EVP_DigestFinal(&md, digest, NULL); |
367 | 370 | ||
368 | /* expand */ | 371 | /* |
372 | * expand key: | ||
373 | * Kn = HASH(K || H || K1 || K2 || ... || Kn-1) | ||
374 | * Key = K1 || K2 || ... || Kn | ||
375 | */ | ||
369 | for (have = mdsz; need > have; have += mdsz) { | 376 | for (have = mdsz; need > have; have += mdsz) { |
370 | EVP_DigestInit(&md, evp_md); | 377 | EVP_DigestInit(&md, evp_md); |
371 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); | 378 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); |
@@ -381,13 +388,12 @@ derive_key(Kex *kex, int id, int need, u_char *hash, BIGNUM *shared_secret) | |||
381 | return digest; | 388 | return digest; |
382 | } | 389 | } |
383 | 390 | ||
384 | Newkeys *x_newkeys[MODE_MAX]; | 391 | Newkeys *current_keys[MODE_MAX]; |
385 | 392 | ||
386 | #define NKEYS 6 | 393 | #define NKEYS 6 |
387 | void | 394 | void |
388 | kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret) | 395 | kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret) |
389 | { | 396 | { |
390 | Newkeys *newkeys; | ||
391 | u_char *keys[NKEYS]; | 397 | u_char *keys[NKEYS]; |
392 | int i, mode, ctos; | 398 | int i, mode, ctos; |
393 | 399 | ||
@@ -396,19 +402,23 @@ kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret) | |||
396 | 402 | ||
397 | debug("kex_derive_keys"); | 403 | debug("kex_derive_keys"); |
398 | for (mode = 0; mode < MODE_MAX; mode++) { | 404 | for (mode = 0; mode < MODE_MAX; mode++) { |
399 | newkeys = kex->keys[mode]; | 405 | current_keys[mode] = kex->newkeys[mode]; |
406 | kex->newkeys[mode] = NULL; | ||
400 | ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); | 407 | ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); |
401 | newkeys->enc.iv = keys[ctos ? 0 : 1]; | 408 | current_keys[mode]->enc.iv = keys[ctos ? 0 : 1]; |
402 | newkeys->enc.key = keys[ctos ? 2 : 3]; | 409 | current_keys[mode]->enc.key = keys[ctos ? 2 : 3]; |
403 | newkeys->mac.key = keys[ctos ? 4 : 5]; | 410 | current_keys[mode]->mac.key = keys[ctos ? 4 : 5]; |
404 | x_newkeys[mode] = newkeys; | ||
405 | } | 411 | } |
406 | } | 412 | } |
407 | 413 | ||
408 | Newkeys * | 414 | Newkeys * |
409 | kex_get_newkeys(int mode) | 415 | kex_get_newkeys(int mode) |
410 | { | 416 | { |
411 | return x_newkeys[mode]; | 417 | Newkeys *ret; |
418 | |||
419 | ret = current_keys[mode]; | ||
420 | current_keys[mode] = NULL; | ||
421 | return ret; | ||
412 | } | 422 | } |
413 | 423 | ||
414 | #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) | 424 | #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) |