1 /* 2 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * 24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #include "includes.h" 29 RCSID("$OpenBSD: kex.c,v 1.51 2002/06/24 14:55:38 markus Exp $"); 30 31 #include <locale.h> 32 33 #include <openssl/opensslconf.h> 34 #include <openssl/crypto.h> 35 36 #include "ssh2.h" 37 #include "xmalloc.h" 38 #include "buffer.h" 39 #include "bufaux.h" 40 #include "packet.h" 41 #include "compat.h" 42 #include "cipher.h" 43 #include "kex.h" 44 #include "key.h" 45 #include "log.h" 46 #include "mac.h" 47 #include "match.h" 48 #include "dispatch.h" 49 #include "g11n.h" 50 51 #ifdef GSSAPI 52 #include "ssh-gss.h" 53 #endif 54 55 #define KEX_COOKIE_LEN 16 56 57 char *session_lang = NULL; 58 59 60 /* prototype */ 61 static void kex_do_hook(Kex *kex); 62 static void kex_kexinit_finish(Kex *); 63 static void kex_choose_conf(Kex *); 64 65 /* put algorithm proposal into buffer */ 66 static 67 void 68 kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) 69 { 70 int i; 71 72 buffer_clear(b); 73 /* 74 * add a dummy cookie, the cookie will be overwritten by 75 * kex_send_kexinit(), each time a kexinit is set 76 */ 77 for (i = 0; i < KEX_COOKIE_LEN; i++) 78 buffer_put_char(b, 0); 79 for (i = 0; i < PROPOSAL_MAX; i++) 80 buffer_put_cstring(b, proposal[i]); 81 buffer_put_char(b, 0); /* first_kex_packet_follows */ 82 buffer_put_int(b, 0); /* uint32 reserved */ 83 } 84 85 /* parse buffer and return algorithm proposal */ 86 static 87 char ** 88 kex_buf2prop(Buffer *raw, int *first_kex_follows) 89 { 90 Buffer b; 91 int i; 92 char **proposal; 93 94 proposal = xmalloc(PROPOSAL_MAX * sizeof(char *)); 95 96 buffer_init(&b); 97 buffer_append(&b, buffer_ptr(raw), buffer_len(raw)); 98 /* skip cookie */ 99 for (i = 0; i < KEX_COOKIE_LEN; i++) 100 buffer_get_char(&b); 101 /* extract kex init proposal strings */ 102 for (i = 0; i < PROPOSAL_MAX; i++) { 103 proposal[i] = buffer_get_string(&b,NULL); 104 debug2("kex_parse_kexinit: %s", proposal[i]); 105 } 106 /* first kex follows / reserved */ 107 i = buffer_get_char(&b); 108 if (first_kex_follows != NULL) 109 *first_kex_follows = i; 110 debug2("kex_parse_kexinit: first_kex_follows %d ", i); 111 i = buffer_get_int(&b); 112 debug2("kex_parse_kexinit: reserved %d ", i); 113 buffer_free(&b); 114 return proposal; 115 } 116 117 static 118 void 119 kex_prop_free(char **proposal) 120 { 121 int i; 122 123 for (i = 0; i < PROPOSAL_MAX; i++) 124 xfree(proposal[i]); 125 xfree(proposal); 126 } 127 128 static void 129 kex_protocol_error(int type, u_int32_t seq, void *ctxt) 130 { 131 error("Hm, kex protocol error: type %d seq %u", type, seq); 132 } 133 134 static void 135 kex_reset_dispatch(void) 136 { 137 #ifdef ALTPRIVSEP 138 /* unprivileged sshd has a kex packet handler that must not be reset */ 139 debug3("kex_reset_dispatch -- should we dispatch_set(KEXINIT) here? %d && !%d", 140 packet_is_server(), packet_is_monitor()); 141 if (packet_is_server() && !packet_is_monitor()) { 142 debug3("kex_reset_dispatch -- skipping dispatch_set(KEXINIT) in unpriv proc"); 143 return; 144 } 145 #endif /* ALTPRIVSEP */ 146 147 dispatch_range(SSH2_MSG_TRANSPORT_MIN, 148 SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); 149 dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); 150 } 151 152 void 153 kex_finish(Kex *kex) 154 { 155 kex_reset_dispatch(); 156 157 packet_start(SSH2_MSG_NEWKEYS); 158 packet_send(); 159 /* packet_write_wait(); */ 160 debug("SSH2_MSG_NEWKEYS sent"); 161 162 #ifdef ALTPRIVSEP 163 if (packet_is_monitor()) 164 goto skip_newkeys; 165 #endif /* ALTPRIVSEP */ 166 debug("expecting SSH2_MSG_NEWKEYS"); 167 packet_read_expect(SSH2_MSG_NEWKEYS); 168 packet_check_eom(); 169 debug("SSH2_MSG_NEWKEYS received"); 170 #ifdef ALTPRIVSEP 171 skip_newkeys: 172 #endif /* ALTPRIVSEP */ 173 174 kex->done = 1; 175 kex->initial_kex_done = 1; /* never to be cleared once set */ 176 buffer_clear(&kex->peer); 177 /* buffer_clear(&kex->my); */ 178 kex->flags &= ~KEX_INIT_SENT; 179 xfree(kex->name); 180 kex->name = NULL; 181 } 182 183 void 184 kex_send_kexinit(Kex *kex) 185 { 186 u_int32_t rand = 0; 187 u_char *cookie; 188 int i; 189 190 if (kex == NULL) { 191 error("kex_send_kexinit: no kex, cannot rekey"); 192 return; 193 } 194 if (kex->flags & KEX_INIT_SENT) { 195 debug("KEX_INIT_SENT"); 196 return; 197 } 198 kex->done = 0; 199 200 /* update my proposal -- e.g., add/remove GSS kexalgs */ 201 kex_do_hook(kex); 202 203 /* generate a random cookie */ 204 if (buffer_len(&kex->my) < KEX_COOKIE_LEN) 205 fatal("kex_send_kexinit: kex proposal too short"); 206 cookie = buffer_ptr(&kex->my); 207 for (i = 0; i < KEX_COOKIE_LEN; i++) { 208 if (i % 4 == 0) 209 rand = arc4random(); 210 cookie[i] = rand; 211 rand >>= 8; 212 } 213 packet_start(SSH2_MSG_KEXINIT); 214 packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); 215 packet_send(); 216 debug("SSH2_MSG_KEXINIT sent"); 217 kex->flags |= KEX_INIT_SENT; 218 } 219 220 void 221 kex_input_kexinit(int type, u_int32_t seq, void *ctxt) 222 { 223 char *ptr; 224 u_int dlen; 225 int i; 226 Kex *kex = (Kex *)ctxt; 227 228 debug("SSH2_MSG_KEXINIT received"); 229 if (kex == NULL) 230 fatal("kex_input_kexinit: no kex, cannot rekey"); 231 232 ptr = packet_get_raw(&dlen); 233 buffer_append(&kex->peer, ptr, dlen); 234 235 /* discard packet */ 236 for (i = 0; i < KEX_COOKIE_LEN; i++) 237 packet_get_char(); 238 for (i = 0; i < PROPOSAL_MAX; i++) 239 xfree(packet_get_string(NULL)); 240 (void) packet_get_char(); 241 (void) packet_get_int(); 242 packet_check_eom(); 243 244 kex_kexinit_finish(kex); 245 } 246 247 /* 248 * This is for GSS keyex, where actual KEX offer can change at rekey 249 * time due to credential expiration/renewal... 250 */ 251 static 252 void 253 kex_do_hook(Kex *kex) 254 { 255 char **prop; 256 257 if (kex->kex_hook == NULL) 258 return; 259 260 /* Unmarshall my proposal, let the hook modify it, remarshall it */ 261 prop = kex_buf2prop(&kex->my, NULL); 262 buffer_clear(&kex->my); 263 (kex->kex_hook)(kex, prop); 264 kex_prop2buf(&kex->my, prop); 265 kex_prop_free(prop); 266 } 267 268 /* Initiate the key exchange by sending the SSH2_MSG_KEXINIT message. */ 269 void 270 kex_start(Kex *kex) 271 { 272 kex_send_kexinit(kex); 273 kex_reset_dispatch(); 274 } 275 276 /* 277 * Allocate a key exchange structure and populate it with a proposal we are 278 * going to use. This function does not start the actual key exchange. 279 */ 280 Kex * 281 kex_setup(const char *host, char *proposal[PROPOSAL_MAX], Kex_hook_func hook) 282 { 283 Kex *kex; 284 285 kex = xmalloc(sizeof(*kex)); 286 memset(kex, 0, sizeof(*kex)); 287 buffer_init(&kex->peer); 288 buffer_init(&kex->my); 289 290 kex->kex_hook = hook; /* called by kex_send_kexinit() */ 291 292 if (host != NULL && *host != '\0') 293 kex->serverhost = xstrdup(host); 294 else 295 kex->server = 1; 296 297 kex_prop2buf(&kex->my, proposal); 298 299 return kex; 300 } 301 302 static void 303 kex_kexinit_finish(Kex *kex) 304 { 305 if (!(kex->flags & KEX_INIT_SENT)) 306 kex_send_kexinit(kex); 307 308 kex_choose_conf(kex); 309 310 if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX && 311 kex->kex[kex->kex_type] != NULL) 312 (kex->kex[kex->kex_type])(kex); 313 else 314 fatal("Unsupported key exchange %d", kex->kex_type); 315 } 316 317 static void 318 choose_lang(char **lang, char *client, char *server) 319 { 320 if (datafellows & SSH_BUG_LOCALES_NOT_LANGTAGS) 321 *lang = match_list(client, server, NULL); 322 else 323 *lang = g11n_srvr_locale_negotiate(client, NULL); 324 } 325 326 /* 327 * Make the message clear enough so that if this happens the user can figure out 328 * the workaround of changing the Ciphers option. 329 */ 330 #define CLIENT_ERR_MSG \ 331 "Client and server could not agree on a common cipher:\n" \ 332 " client: %s\n" \ 333 " server: %s\n" \ 334 "\n" \ 335 "The client cipher list can be controlled using the \"Ciphers\" option, \n" \ 336 "see ssh_config(4) for more information. The \"-o Ciphers=<cipher-list>\"\n" \ 337 "option may be used to temporarily override the ciphers the client\n" \ 338 "offers." 339 340 /* 341 * The server side message goes to syslogd and we do not want to send multiline 342 * messages there. What's more, the server side notification may be shorter 343 * since we expect that an administrator will deal with that, not the user. 344 */ 345 #define SERVER_ERR_MSG \ 346 "Client and server could not agree on a common cipher: client \"%s\", " \ 347 "server \"%s\". The server cipher list can be controlled using the " \ 348 "\"Ciphers\" option, see sshd_config(4) for more information." 349 350 static void 351 choose_enc(int is_server, Enc *enc, char *client, char *server) 352 { 353 char *name = match_list(client, server, NULL); 354 355 if (name == NULL) { 356 if (is_server == 1) 357 fatal(SERVER_ERR_MSG, client, server); 358 else 359 fatal(CLIENT_ERR_MSG, client, server); 360 } 361 362 if ((enc->cipher = cipher_by_name(name)) == NULL) 363 fatal("matching cipher is not supported: %s", name); 364 365 enc->name = name; 366 enc->enabled = 0; 367 enc->iv = NULL; 368 enc->key = NULL; 369 enc->key_len = cipher_keylen(enc->cipher); 370 enc->block_size = cipher_blocksize(enc->cipher); 371 } 372 373 static void 374 choose_mac(Mac *mac, char *client, char *server) 375 { 376 char *name = match_list(client, server, NULL); 377 if (name == NULL) 378 fatal("no matching mac found: client %s server %s", 379 client, server); 380 if (mac_setup(mac, name) < 0) 381 fatal("unsupported mac %s", name); 382 /* truncate the key */ 383 if (datafellows & SSH_BUG_HMAC) 384 mac->key_len = 16; 385 mac->name = name; 386 mac->key = NULL; 387 mac->enabled = 0; 388 } 389 390 static void 391 choose_comp(Comp *comp, char *client, char *server) 392 { 393 char *name = match_list(client, server, NULL); 394 if (name == NULL) 395 fatal("no matching comp found: client %s server %s", client, server); 396 if (strcmp(name, "zlib") == 0) { 397 comp->type = 1; 398 } else if (strcmp(name, "none") == 0) { 399 comp->type = 0; 400 } else { 401 fatal("unsupported comp %s", name); 402 } 403 comp->name = name; 404 } 405 406 static void 407 choose_kex(Kex *k, char *client, char *server) 408 { 409 k->name = match_list(client, server, NULL); 410 if (k->name == NULL) 411 fatal("no common kex alg: client '%s', server '%s'", client, 412 server); 413 /* XXX Finish 3.6/7 merge of kex stuff -- choose_kex() done */ 414 if (strcmp(k->name, KEX_DH1) == 0) { 415 k->kex_type = KEX_DH_GRP1_SHA1; 416 } else if (strcmp(k->name, KEX_DHGEX) == 0) { 417 k->kex_type = KEX_DH_GEX_SHA1; 418 #ifdef GSSAPI 419 } else if (strncmp(k->name, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1) == 0) { 420 k->kex_type = KEX_GSS_GRP1_SHA1; 421 #endif 422 } else 423 fatal("bad kex alg %s", k->name); 424 } 425 426 static void 427 choose_hostkeyalg(Kex *k, char *client, char *server) 428 { 429 char *hostkeyalg = match_list(client, server, NULL); 430 if (hostkeyalg == NULL) 431 fatal("no hostkey alg"); 432 k->hostkey_type = key_type_from_name(hostkeyalg); 433 if (k->hostkey_type == KEY_UNSPEC) 434 fatal("bad hostkey alg '%s'", hostkeyalg); 435 xfree(hostkeyalg); 436 } 437 438 static int 439 proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX]) 440 { 441 static int check[] = { 442 PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1 443 }; 444 int *idx; 445 char *p; 446 447 for (idx = &check[0]; *idx != -1; idx++) { 448 if ((p = strchr(my[*idx], ',')) != NULL) 449 *p = '\0'; 450 if ((p = strchr(peer[*idx], ',')) != NULL) 451 *p = '\0'; 452 if (strcmp(my[*idx], peer[*idx]) != 0) { 453 debug2("proposal mismatch: my %s peer %s", 454 my[*idx], peer[*idx]); 455 return (0); 456 } 457 } 458 debug2("proposals match"); 459 return (1); 460 } 461 462 static void 463 kex_choose_conf(Kex *kex) 464 { 465 Newkeys *newkeys; 466 char **my, **peer; 467 char **cprop, **sprop; 468 char *p_langs_c2s, *p_langs_s2c; /* peer's langs */ 469 char *plangs = NULL; /* peer's langs*/ 470 char *mlangs = NULL; /* my langs */ 471 int nenc, nmac, ncomp; 472 int mode; 473 int ctos; /* direction: if true client-to-server */ 474 int need; 475 int first_kex_follows, type; 476 477 my = kex_buf2prop(&kex->my, NULL); 478 peer = kex_buf2prop(&kex->peer, &first_kex_follows); 479 480 if (kex->server) { 481 cprop=peer; 482 sprop=my; 483 } else { 484 cprop=my; 485 sprop=peer; 486 } 487 488 /* Algorithm Negotiation */ 489 for (mode = 0; mode < MODE_MAX; mode++) { 490 newkeys = xmalloc(sizeof(*newkeys)); 491 memset(newkeys, 0, sizeof(*newkeys)); 492 kex->newkeys[mode] = newkeys; 493 ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); 494 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; 495 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; 496 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; 497 choose_enc(kex->server, &newkeys->enc, cprop[nenc], sprop[nenc]); 498 choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]); 499 choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); 500 debug("kex: %s %s %s %s", 501 ctos ? "client->server" : "server->client", 502 newkeys->enc.name, 503 newkeys->mac.name, 504 newkeys->comp.name); 505 } 506 choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); 507 choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], 508 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); 509 need = 0; 510 for (mode = 0; mode < MODE_MAX; mode++) { 511 newkeys = kex->newkeys[mode]; 512 if (need < newkeys->enc.key_len) 513 need = newkeys->enc.key_len; 514 if (need < newkeys->enc.block_size) 515 need = newkeys->enc.block_size; 516 if (need < newkeys->mac.key_len) 517 need = newkeys->mac.key_len; 518 } 519 /* XXX need runden? */ 520 kex->we_need = need; 521 522 /* ignore the next message if the proposals do not match */ 523 if (first_kex_follows && !proposals_match(my, peer) && 524 !(datafellows & SSH_BUG_FIRSTKEX)) { 525 type = packet_read(); 526 debug2("skipping next packet (type %u)", type); 527 } 528 529 /* Language/locale negotiation -- not worth doing on re-key */ 530 531 if (!kex->initial_kex_done) { 532 p_langs_c2s = peer[PROPOSAL_LANG_CTOS]; 533 p_langs_s2c = peer[PROPOSAL_LANG_STOC]; 534 debug("Peer sent proposed langtags, ctos: %s", p_langs_c2s); 535 debug("Peer sent proposed langtags, stoc: %s", p_langs_s2c); 536 plangs = NULL; 537 538 /* We propose the same langs for each protocol direction */ 539 mlangs = my[PROPOSAL_LANG_STOC]; 540 debug("We proposed langtags, ctos: %s", my[PROPOSAL_LANG_CTOS]); 541 debug("We proposed langtags, stoc: %s", mlangs); 542 543 /* 544 * Why oh why did they bother with negotiating langs for 545 * each protocol direction?! 546 * 547 * The semantics of this are vaguely specified, but one can 548 * imagine using one language (locale) for the whole session and 549 * a different one for message localization (e.g., 'en_US.UTF-8' 550 * overall and 'fr' for messages). Weird? Maybe. But lang 551 * tags don't include codeset info, like locales do... 552 * 553 * So, server-side we want: 554 * - setlocale(LC_ALL, c2s_locale); 555 * and 556 * - setlocale(LC_MESSAGES, s2c_locale); 557 * 558 * Client-side we don't really care. But we could do: 559 * 560 * - when very verbose, tell the use what lang the server's 561 * messages are in, if left out in the protocol 562 * - when sending messages to the server, and if applicable, we 563 * can localize them according to the language negotiated for 564 * that direction. 565 * 566 * But for now we do nothing on the client side. 567 */ 568 if ((p_langs_c2s && *p_langs_c2s) && !(p_langs_s2c && *p_langs_s2c)) 569 plangs = p_langs_c2s; 570 else if ((p_langs_s2c && *p_langs_s2c) && !(p_langs_c2s && *p_langs_c2s)) 571 plangs = p_langs_s2c; 572 else 573 plangs = p_langs_c2s; 574 575 if (kex->server) { 576 if (plangs && mlangs && *plangs && *mlangs) { 577 char *locale; 578 579 g11n_test_langtag(plangs, 1); 580 581 choose_lang(&locale, plangs, mlangs); 582 if (locale) { 583 g11n_setlocale(LC_ALL, locale); 584 debug("Negotiated main locale: %s", locale); 585 packet_send_debug("Negotiated main locale: %s", locale); 586 xfree(locale); 587 } 588 if (plangs != p_langs_s2c && 589 p_langs_s2c && *p_langs_s2c) { 590 choose_lang(&locale, p_langs_s2c, mlangs); 591 if (locale) { 592 g11n_setlocale(LC_MESSAGES, locale); 593 debug("Negotiated messages locale: %s", locale); 594 packet_send_debug("Negotiated " 595 "messages locale: %s", locale); 596 xfree(locale); 597 } 598 } 599 } 600 } 601 else { 602 if (plangs && mlangs && *plangs && *mlangs && 603 !(datafellows & SSH_BUG_LOCALES_NOT_LANGTAGS)) { 604 char *lang; 605 lang = g11n_clnt_langtag_negotiate(mlangs, plangs); 606 if (lang) { 607 session_lang = lang; 608 debug("Negotiated lang: %s", lang); 609 g11n_test_langtag(lang, 0); 610 } 611 } 612 } 613 } 614 615 kex_prop_free(my); 616 kex_prop_free(peer); 617 } 618 619 static u_char * 620 derive_key(Kex *kex, int id, int need, u_char *hash, BIGNUM *shared_secret) 621 { 622 Buffer b; 623 const EVP_MD *evp_md = EVP_sha1(); 624 EVP_MD_CTX md; 625 char c = id; 626 int have; 627 int mdsz = EVP_MD_size(evp_md); 628 u_char *digest = xmalloc(roundup(need, mdsz)); 629 630 buffer_init(&b); 631 buffer_put_bignum2(&b, shared_secret); 632 633 /* K1 = HASH(K || H || "A" || session_id) */ 634 EVP_DigestInit(&md, evp_md); 635 if (!(datafellows & SSH_BUG_DERIVEKEY)) 636 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); 637 EVP_DigestUpdate(&md, hash, mdsz); 638 EVP_DigestUpdate(&md, &c, 1); 639 EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); 640 EVP_DigestFinal(&md, digest, NULL); 641 642 /* 643 * expand key: 644 * Kn = HASH(K || H || K1 || K2 || ... || Kn-1) 645 * Key = K1 || K2 || ... || Kn 646 */ 647 for (have = mdsz; need > have; have += mdsz) { 648 EVP_DigestInit(&md, evp_md); 649 if (!(datafellows & SSH_BUG_DERIVEKEY)) 650 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); 651 EVP_DigestUpdate(&md, hash, mdsz); 652 EVP_DigestUpdate(&md, digest, have); 653 EVP_DigestFinal(&md, digest + have, NULL); 654 } 655 buffer_free(&b); 656 #ifdef DEBUG_KEX 657 fprintf(stderr, "key '%c'== ", c); 658 dump_digest("key", digest, need); 659 #endif 660 return digest; 661 } 662 663 Newkeys *current_keys[MODE_MAX]; 664 665 #define NKEYS 6 666 void 667 kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret) 668 { 669 u_char *keys[NKEYS]; 670 int i, mode, ctos; 671 672 for (i = 0; i < NKEYS; i++) 673 keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, shared_secret); 674 675 debug2("kex_derive_keys"); 676 for (mode = 0; mode < MODE_MAX; mode++) { 677 current_keys[mode] = kex->newkeys[mode]; 678 kex->newkeys[mode] = NULL; 679 ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); 680 current_keys[mode]->enc.iv = keys[ctos ? 0 : 1]; 681 current_keys[mode]->enc.key = keys[ctos ? 2 : 3]; 682 current_keys[mode]->mac.key = keys[ctos ? 4 : 5]; 683 } 684 } 685 686 Newkeys * 687 kex_get_newkeys(int mode) 688 { 689 Newkeys *ret; 690 691 ret = current_keys[mode]; 692 current_keys[mode] = NULL; 693 return ret; 694 } 695 696 #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) 697 void 698 dump_digest(char *msg, u_char *digest, int len) 699 { 700 int i; 701 702 fprintf(stderr, "%s\n", msg); 703 for (i = 0; i< len; i++) { 704 fprintf(stderr, "%02x", digest[i]); 705 if (i%32 == 31) 706 fprintf(stderr, "\n"); 707 else if (i%8 == 7) 708 fprintf(stderr, " "); 709 } 710 fprintf(stderr, "\n"); 711 } 712 #endif