diff options
author | markus@openbsd.org <markus@openbsd.org> | 2015-01-19 19:52:16 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2015-01-20 09:13:01 +1100 |
commit | 091c302829210c41e7f57c3f094c7b9c054306f0 (patch) | |
tree | 800de5dc85b877a85d1f269ae5bb09b0dc3fa7a7 /kex.c | |
parent | 4e62cc68ce4ba20245d208b252e74e91d3785b74 (diff) |
upstream commit
update packet.c & isolate, introduce struct ssh a) switch
packet.c to buffer api and isolate per-connection info into struct ssh b)
(de)serialization of the state is moved from monitor to packet.c c) the old
packet.c API is implemented in opacket.[ch] d) compress.c/h is removed and
integrated into packet.c with and ok djm@
Diffstat (limited to 'kex.c')
-rw-r--r-- | kex.c | 87 |
1 files changed, 54 insertions, 33 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.c,v 1.99 2014/04/29 18:01:49 markus Exp $ */ | 1 | /* $OpenBSD: kex.c,v 1.100 2015/01/19 19:52:16 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -239,8 +239,8 @@ kex_finish(Kex *kex) | |||
239 | debug("SSH2_MSG_NEWKEYS received"); | 239 | debug("SSH2_MSG_NEWKEYS received"); |
240 | 240 | ||
241 | kex->done = 1; | 241 | kex->done = 1; |
242 | buffer_clear(&kex->peer); | 242 | buffer_clear(kex->peer); |
243 | /* buffer_clear(&kex->my); */ | 243 | /* buffer_clear(kex->my); */ |
244 | kex->flags &= ~KEX_INIT_SENT; | 244 | kex->flags &= ~KEX_INIT_SENT; |
245 | free(kex->name); | 245 | free(kex->name); |
246 | kex->name = NULL; | 246 | kex->name = NULL; |
@@ -264,9 +264,9 @@ kex_send_kexinit(Kex *kex) | |||
264 | kex->done = 0; | 264 | kex->done = 0; |
265 | 265 | ||
266 | /* generate a random cookie */ | 266 | /* generate a random cookie */ |
267 | if (buffer_len(&kex->my) < KEX_COOKIE_LEN) | 267 | if (buffer_len(kex->my) < KEX_COOKIE_LEN) |
268 | fatal("kex_send_kexinit: kex proposal too short"); | 268 | fatal("kex_send_kexinit: kex proposal too short"); |
269 | cookie = buffer_ptr(&kex->my); | 269 | cookie = buffer_ptr(kex->my); |
270 | for (i = 0; i < KEX_COOKIE_LEN; i++) { | 270 | for (i = 0; i < KEX_COOKIE_LEN; i++) { |
271 | if (i % 4 == 0) | 271 | if (i % 4 == 0) |
272 | rnd = arc4random(); | 272 | rnd = arc4random(); |
@@ -274,7 +274,7 @@ kex_send_kexinit(Kex *kex) | |||
274 | rnd >>= 8; | 274 | rnd >>= 8; |
275 | } | 275 | } |
276 | packet_start(SSH2_MSG_KEXINIT); | 276 | packet_start(SSH2_MSG_KEXINIT); |
277 | packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); | 277 | packet_put_raw(buffer_ptr(kex->my), buffer_len(kex->my)); |
278 | packet_send(); | 278 | packet_send(); |
279 | debug("SSH2_MSG_KEXINIT sent"); | 279 | debug("SSH2_MSG_KEXINIT sent"); |
280 | kex->flags |= KEX_INIT_SENT; | 280 | kex->flags |= KEX_INIT_SENT; |
@@ -284,8 +284,9 @@ kex_send_kexinit(Kex *kex) | |||
284 | void | 284 | void |
285 | kex_input_kexinit(int type, u_int32_t seq, void *ctxt) | 285 | kex_input_kexinit(int type, u_int32_t seq, void *ctxt) |
286 | { | 286 | { |
287 | char *ptr; | 287 | const char *ptr; |
288 | u_int i, dlen; | 288 | u_int i; |
289 | size_t dlen; | ||
289 | Kex *kex = (Kex *)ctxt; | 290 | Kex *kex = (Kex *)ctxt; |
290 | 291 | ||
291 | debug("SSH2_MSG_KEXINIT received"); | 292 | debug("SSH2_MSG_KEXINIT received"); |
@@ -293,7 +294,7 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt) | |||
293 | fatal("kex_input_kexinit: no kex, cannot rekey"); | 294 | fatal("kex_input_kexinit: no kex, cannot rekey"); |
294 | 295 | ||
295 | ptr = packet_get_raw(&dlen); | 296 | ptr = packet_get_raw(&dlen); |
296 | buffer_append(&kex->peer, ptr, dlen); | 297 | buffer_append(kex->peer, ptr, dlen); |
297 | 298 | ||
298 | /* discard packet */ | 299 | /* discard packet */ |
299 | for (i = 0; i < KEX_COOKIE_LEN; i++) | 300 | for (i = 0; i < KEX_COOKIE_LEN; i++) |
@@ -317,15 +318,49 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt) | |||
317 | kex_kexinit_finish(kex); | 318 | kex_kexinit_finish(kex); |
318 | } | 319 | } |
319 | 320 | ||
321 | void | ||
322 | kex_free_newkeys(struct newkeys *newkeys) | ||
323 | { | ||
324 | if (newkeys == NULL) | ||
325 | return; | ||
326 | if (newkeys->enc.key) { | ||
327 | explicit_bzero(newkeys->enc.key, newkeys->enc.key_len); | ||
328 | free(newkeys->enc.key); | ||
329 | newkeys->enc.key = NULL; | ||
330 | } | ||
331 | if (newkeys->enc.iv) { | ||
332 | explicit_bzero(newkeys->enc.iv, newkeys->enc.block_size); | ||
333 | free(newkeys->enc.iv); | ||
334 | newkeys->enc.iv = NULL; | ||
335 | } | ||
336 | free(newkeys->enc.name); | ||
337 | explicit_bzero(&newkeys->enc, sizeof(newkeys->enc)); | ||
338 | free(newkeys->comp.name); | ||
339 | explicit_bzero(&newkeys->comp, sizeof(newkeys->comp)); | ||
340 | mac_clear(&newkeys->mac); | ||
341 | if (newkeys->mac.key) { | ||
342 | explicit_bzero(newkeys->mac.key, newkeys->mac.key_len); | ||
343 | free(newkeys->mac.key); | ||
344 | newkeys->mac.key = NULL; | ||
345 | } | ||
346 | free(newkeys->mac.name); | ||
347 | explicit_bzero(&newkeys->mac, sizeof(newkeys->mac)); | ||
348 | explicit_bzero(newkeys, sizeof(*newkeys)); | ||
349 | free(newkeys); | ||
350 | } | ||
351 | |||
320 | Kex * | 352 | Kex * |
321 | kex_setup(char *proposal[PROPOSAL_MAX]) | 353 | kex_setup(char *proposal[PROPOSAL_MAX]) |
322 | { | 354 | { |
323 | Kex *kex; | 355 | struct kex *kex; |
324 | 356 | ||
325 | kex = xcalloc(1, sizeof(*kex)); | 357 | if ((kex = calloc(1, sizeof(*kex))) == NULL) |
326 | buffer_init(&kex->peer); | 358 | fatal("%s: calloc", __func__); |
327 | buffer_init(&kex->my); | 359 | if ((kex->peer = sshbuf_new()) == NULL || |
328 | kex_prop2buf(&kex->my, proposal); | 360 | (kex->my = sshbuf_new()) == NULL) { |
361 | fatal("%s: sshbuf_new", __func__); | ||
362 | } | ||
363 | kex_prop2buf(kex->my, proposal); | ||
329 | kex->done = 0; | 364 | kex->done = 0; |
330 | 365 | ||
331 | kex_send_kexinit(kex); /* we start */ | 366 | kex_send_kexinit(kex); /* we start */ |
@@ -464,8 +499,8 @@ kex_choose_conf(Kex *kex) | |||
464 | u_int mode, ctos, need, dh_need, authlen; | 499 | u_int mode, ctos, need, dh_need, authlen; |
465 | int first_kex_follows, type; | 500 | int first_kex_follows, type; |
466 | 501 | ||
467 | my = kex_buf2prop(&kex->my, NULL); | 502 | my = kex_buf2prop(kex->my, NULL); |
468 | peer = kex_buf2prop(&kex->peer, &first_kex_follows); | 503 | peer = kex_buf2prop(kex->peer, &first_kex_follows); |
469 | 504 | ||
470 | if (kex->server) { | 505 | if (kex->server) { |
471 | cprop=peer; | 506 | cprop=peer; |
@@ -591,8 +626,6 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, | |||
591 | return digest; | 626 | return digest; |
592 | } | 627 | } |
593 | 628 | ||
594 | Newkeys *current_keys[MODE_MAX]; | ||
595 | |||
596 | #define NKEYS 6 | 629 | #define NKEYS 6 |
597 | void | 630 | void |
598 | kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, | 631 | kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, |
@@ -608,13 +641,11 @@ kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, | |||
608 | 641 | ||
609 | debug2("kex_derive_keys"); | 642 | debug2("kex_derive_keys"); |
610 | for (mode = 0; mode < MODE_MAX; mode++) { | 643 | for (mode = 0; mode < MODE_MAX; mode++) { |
611 | current_keys[mode] = kex->newkeys[mode]; | ||
612 | kex->newkeys[mode] = NULL; | ||
613 | ctos = (!kex->server && mode == MODE_OUT) || | 644 | ctos = (!kex->server && mode == MODE_OUT) || |
614 | (kex->server && mode == MODE_IN); | 645 | (kex->server && mode == MODE_IN); |
615 | current_keys[mode]->enc.iv = keys[ctos ? 0 : 1]; | 646 | kex->newkeys[mode]->enc.iv = keys[ctos ? 0 : 1]; |
616 | current_keys[mode]->enc.key = keys[ctos ? 2 : 3]; | 647 | kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3]; |
617 | current_keys[mode]->mac.key = keys[ctos ? 4 : 5]; | 648 | kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5]; |
618 | } | 649 | } |
619 | } | 650 | } |
620 | 651 | ||
@@ -632,16 +663,6 @@ kex_derive_keys_bn(Kex *kex, u_char *hash, u_int hashlen, const BIGNUM *secret) | |||
632 | } | 663 | } |
633 | #endif | 664 | #endif |
634 | 665 | ||
635 | Newkeys * | ||
636 | kex_get_newkeys(int mode) | ||
637 | { | ||
638 | Newkeys *ret; | ||
639 | |||
640 | ret = current_keys[mode]; | ||
641 | current_keys[mode] = NULL; | ||
642 | return ret; | ||
643 | } | ||
644 | |||
645 | #ifdef WITH_SSH1 | 666 | #ifdef WITH_SSH1 |
646 | void | 667 | void |
647 | derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, | 668 | derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, |