kex.c revision 294328
1294328Sdes/* $OpenBSD: kex.c,v 1.99 2014/04/29 18:01:49 markus Exp $ */ 260573Skris/* 392555Sdes * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 460573Skris * 560573Skris * Redistribution and use in source and binary forms, with or without 660573Skris * modification, are permitted provided that the following conditions 760573Skris * are met: 860573Skris * 1. Redistributions of source code must retain the above copyright 960573Skris * notice, this list of conditions and the following disclaimer. 1060573Skris * 2. Redistributions in binary form must reproduce the above copyright 1160573Skris * notice, this list of conditions and the following disclaimer in the 1260573Skris * documentation and/or other materials provided with the distribution. 1360573Skris * 1460573Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1560573Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1660573Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1760573Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1860573Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1960573Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2060573Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2160573Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2260573Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2360573Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2460573Skris */ 2560573Skris 2660573Skris#include "includes.h" 2760573Skris 28162852Sdes#include <sys/param.h> 29162852Sdes 30162852Sdes#include <signal.h> 31162852Sdes#include <stdarg.h> 32162852Sdes#include <stdio.h> 33162852Sdes#include <stdlib.h> 34162852Sdes#include <string.h> 35162852Sdes 36294328Sdes#ifdef WITH_OPENSSL 3776259Sgreen#include <openssl/crypto.h> 38294328Sdes#endif 3976259Sgreen 40162852Sdes#include "xmalloc.h" 4160573Skris#include "ssh2.h" 4260573Skris#include "buffer.h" 4361209Skris#include "packet.h" 4460573Skris#include "compat.h" 4576259Sgreen#include "cipher.h" 46162852Sdes#include "key.h" 4760573Skris#include "kex.h" 4876259Sgreen#include "log.h" 4976259Sgreen#include "mac.h" 5076259Sgreen#include "match.h" 5176259Sgreen#include "dispatch.h" 5298675Sdes#include "monitor.h" 53204917Sdes#include "roaming.h" 54261320Sdes#include "digest.h" 5560573Skris 56162852Sdes#if OPENSSL_VERSION_NUMBER >= 0x00907000L 57162852Sdes# if defined(HAVE_EVP_SHA256) 58162852Sdes# define evp_ssh_sha256 EVP_sha256 59162852Sdes# else 60162852Sdesextern const EVP_MD *evp_ssh_sha256(void); 61162852Sdes# endif 62162852Sdes#endif 63162852Sdes 6492555Sdes/* prototype */ 6592555Sdesstatic void kex_kexinit_finish(Kex *); 6692555Sdesstatic void kex_choose_conf(Kex *); 6776259Sgreen 68255767Sdesstruct kexalg { 69255767Sdes char *name; 70255767Sdes int type; 71255767Sdes int ec_nid; 72261320Sdes int hash_alg; 73255767Sdes}; 74255767Sdesstatic const struct kexalg kexalgs[] = { 75294328Sdes#ifdef WITH_OPENSSL 76261320Sdes { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, 77261320Sdes { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, 78261320Sdes { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, 79255767Sdes#ifdef HAVE_EVP_SHA256 80261320Sdes { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, 81294328Sdes#endif /* HAVE_EVP_SHA256 */ 82255767Sdes#ifdef OPENSSL_HAS_ECC 83261320Sdes { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, 84261320Sdes NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, 85261320Sdes { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, 86261320Sdes SSH_DIGEST_SHA384 }, 87261320Sdes# ifdef OPENSSL_HAS_NISTP521 88261320Sdes { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, 89261320Sdes SSH_DIGEST_SHA512 }, 90294328Sdes# endif /* OPENSSL_HAS_NISTP521 */ 91294328Sdes#endif /* OPENSSL_HAS_ECC */ 92261320Sdes { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, 93294328Sdes#endif /* WITH_OPENSSL */ 94261320Sdes#ifdef HAVE_EVP_SHA256 95261320Sdes { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, 96294328Sdes#endif /* HAVE_EVP_SHA256 */ 97261320Sdes { NULL, -1, -1, -1}, 98255767Sdes}; 99255767Sdes 100255767Sdeschar * 101261320Sdeskex_alg_list(char sep) 102255767Sdes{ 103255767Sdes char *ret = NULL; 104255767Sdes size_t nlen, rlen = 0; 105255767Sdes const struct kexalg *k; 106255767Sdes 107255767Sdes for (k = kexalgs; k->name != NULL; k++) { 108255767Sdes if (ret != NULL) 109261320Sdes ret[rlen++] = sep; 110255767Sdes nlen = strlen(k->name); 111255767Sdes ret = xrealloc(ret, 1, rlen + nlen + 2); 112255767Sdes memcpy(ret + rlen, k->name, nlen + 1); 113255767Sdes rlen += nlen; 114255767Sdes } 115255767Sdes return ret; 116255767Sdes} 117255767Sdes 118255767Sdesstatic const struct kexalg * 119255767Sdeskex_alg_by_name(const char *name) 120255767Sdes{ 121255767Sdes const struct kexalg *k; 122255767Sdes 123255767Sdes for (k = kexalgs; k->name != NULL; k++) { 124255767Sdes if (strcmp(k->name, name) == 0) 125255767Sdes return k; 126255767Sdes } 127255767Sdes return NULL; 128255767Sdes} 129255767Sdes 130221420Sdes/* Validate KEX method name list */ 131221420Sdesint 132221420Sdeskex_names_valid(const char *names) 133221420Sdes{ 134221420Sdes char *s, *cp, *p; 135221420Sdes 136221420Sdes if (names == NULL || strcmp(names, "") == 0) 137221420Sdes return 0; 138221420Sdes s = cp = xstrdup(names); 139221420Sdes for ((p = strsep(&cp, ",")); p && *p != '\0'; 140221420Sdes (p = strsep(&cp, ","))) { 141255767Sdes if (kex_alg_by_name(p) == NULL) { 142221420Sdes error("Unsupported KEX algorithm \"%.100s\"", p); 143255767Sdes free(s); 144221420Sdes return 0; 145221420Sdes } 146221420Sdes } 147221420Sdes debug3("kex names ok: [%s]", names); 148255767Sdes free(s); 149221420Sdes return 1; 150221420Sdes} 151221420Sdes 152291198Sdes/* put algorithm proposal into buffer */ 15392555Sdesstatic void 15476259Sgreenkex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) 15560573Skris{ 156149749Sdes u_int i; 15776259Sgreen 15876259Sgreen buffer_clear(b); 15998675Sdes /* 16098675Sdes * add a dummy cookie, the cookie will be overwritten by 16198675Sdes * kex_send_kexinit(), each time a kexinit is set 16298675Sdes */ 16398675Sdes for (i = 0; i < KEX_COOKIE_LEN; i++) 16498675Sdes buffer_put_char(b, 0); 16560573Skris for (i = 0; i < PROPOSAL_MAX; i++) 16676259Sgreen buffer_put_cstring(b, proposal[i]); 16776259Sgreen buffer_put_char(b, 0); /* first_kex_packet_follows */ 16876259Sgreen buffer_put_int(b, 0); /* uint32 reserved */ 16960573Skris} 17060573Skris 17176259Sgreen/* parse buffer and return algorithm proposal */ 17292555Sdesstatic char ** 173113908Sdeskex_buf2prop(Buffer *raw, int *first_kex_follows) 17461209Skris{ 17576259Sgreen Buffer b; 176181111Sdes u_int i; 17776259Sgreen char **proposal; 17861209Skris 179162852Sdes proposal = xcalloc(PROPOSAL_MAX, sizeof(char *)); 18061209Skris 18176259Sgreen buffer_init(&b); 18276259Sgreen buffer_append(&b, buffer_ptr(raw), buffer_len(raw)); 18361209Skris /* skip cookie */ 18461209Skris for (i = 0; i < KEX_COOKIE_LEN; i++) 18576259Sgreen buffer_get_char(&b); 18661209Skris /* extract kex init proposal strings */ 18761209Skris for (i = 0; i < PROPOSAL_MAX; i++) { 188221420Sdes proposal[i] = buffer_get_cstring(&b,NULL); 18976259Sgreen debug2("kex_parse_kexinit: %s", proposal[i]); 19061209Skris } 19176259Sgreen /* first kex follows / reserved */ 19276259Sgreen i = buffer_get_char(&b); 193113908Sdes if (first_kex_follows != NULL) 194113908Sdes *first_kex_follows = i; 19576259Sgreen debug2("kex_parse_kexinit: first_kex_follows %d ", i); 19676259Sgreen i = buffer_get_int(&b); 197181111Sdes debug2("kex_parse_kexinit: reserved %u ", i); 19876259Sgreen buffer_free(&b); 19976259Sgreen return proposal; 20061209Skris} 20161209Skris 20292555Sdesstatic void 20376259Sgreenkex_prop_free(char **proposal) 20460573Skris{ 205149749Sdes u_int i; 20660573Skris 20776259Sgreen for (i = 0; i < PROPOSAL_MAX; i++) 208255767Sdes free(proposal[i]); 209255767Sdes free(proposal); 21060573Skris} 21160573Skris 212181111Sdes/* ARGSUSED */ 21392555Sdesstatic void 21492555Sdeskex_protocol_error(int type, u_int32_t seq, void *ctxt) 21560573Skris{ 21692555Sdes error("Hm, kex protocol error: type %d seq %u", type, seq); 21760573Skris} 21860573Skris 21992555Sdesstatic void 22092555Sdeskex_reset_dispatch(void) 22169587Sgreen{ 22292555Sdes dispatch_range(SSH2_MSG_TRANSPORT_MIN, 22392555Sdes SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); 22492555Sdes dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); 22569587Sgreen} 22669587Sgreen 22776259Sgreenvoid 22876259Sgreenkex_finish(Kex *kex) 22969587Sgreen{ 23092555Sdes kex_reset_dispatch(); 23169587Sgreen 23276259Sgreen packet_start(SSH2_MSG_NEWKEYS); 23376259Sgreen packet_send(); 23476259Sgreen /* packet_write_wait(); */ 23576259Sgreen debug("SSH2_MSG_NEWKEYS sent"); 23669587Sgreen 237113908Sdes debug("expecting SSH2_MSG_NEWKEYS"); 23892555Sdes packet_read_expect(SSH2_MSG_NEWKEYS); 23992555Sdes packet_check_eom(); 24076259Sgreen debug("SSH2_MSG_NEWKEYS received"); 24169587Sgreen 24276259Sgreen kex->done = 1; 24376259Sgreen buffer_clear(&kex->peer); 24476259Sgreen /* buffer_clear(&kex->my); */ 24576259Sgreen kex->flags &= ~KEX_INIT_SENT; 246255767Sdes free(kex->name); 24776259Sgreen kex->name = NULL; 24869587Sgreen} 24969587Sgreen 25060573Skrisvoid 25176259Sgreenkex_send_kexinit(Kex *kex) 25260573Skris{ 253137015Sdes u_int32_t rnd = 0; 25498675Sdes u_char *cookie; 255149749Sdes u_int i; 25698675Sdes 25776259Sgreen if (kex == NULL) { 25876259Sgreen error("kex_send_kexinit: no kex, cannot rekey"); 25976259Sgreen return; 26060573Skris } 26176259Sgreen if (kex->flags & KEX_INIT_SENT) { 26276259Sgreen debug("KEX_INIT_SENT"); 26376259Sgreen return; 26476259Sgreen } 26576259Sgreen kex->done = 0; 26698675Sdes 26798675Sdes /* generate a random cookie */ 26898675Sdes if (buffer_len(&kex->my) < KEX_COOKIE_LEN) 26998675Sdes fatal("kex_send_kexinit: kex proposal too short"); 27098675Sdes cookie = buffer_ptr(&kex->my); 27198675Sdes for (i = 0; i < KEX_COOKIE_LEN; i++) { 27298675Sdes if (i % 4 == 0) 273137015Sdes rnd = arc4random(); 274137015Sdes cookie[i] = rnd; 275137015Sdes rnd >>= 8; 27698675Sdes } 27776259Sgreen packet_start(SSH2_MSG_KEXINIT); 27876259Sgreen packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); 27976259Sgreen packet_send(); 28076259Sgreen debug("SSH2_MSG_KEXINIT sent"); 28176259Sgreen kex->flags |= KEX_INIT_SENT; 28260573Skris} 28360573Skris 284181111Sdes/* ARGSUSED */ 28576259Sgreenvoid 28692555Sdeskex_input_kexinit(int type, u_int32_t seq, void *ctxt) 28760573Skris{ 28876259Sgreen char *ptr; 289149749Sdes u_int i, dlen; 29076259Sgreen Kex *kex = (Kex *)ctxt; 29160573Skris 29276259Sgreen debug("SSH2_MSG_KEXINIT received"); 29376259Sgreen if (kex == NULL) 29476259Sgreen fatal("kex_input_kexinit: no kex, cannot rekey"); 29560573Skris 29676259Sgreen ptr = packet_get_raw(&dlen); 29776259Sgreen buffer_append(&kex->peer, ptr, dlen); 29860573Skris 29976259Sgreen /* discard packet */ 30076259Sgreen for (i = 0; i < KEX_COOKIE_LEN; i++) 30176259Sgreen packet_get_char(); 30276259Sgreen for (i = 0; i < PROPOSAL_MAX; i++) 303255767Sdes free(packet_get_string(NULL)); 304248619Sdes /* 305248619Sdes * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported 306248619Sdes * KEX method has the server move first, but a server might be using 307248619Sdes * a custom method or one that we otherwise don't support. We should 308248619Sdes * be prepared to remember first_kex_follows here so we can eat a 309248619Sdes * packet later. 310248619Sdes * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means 311248619Sdes * for cases where the server *doesn't* go first. I guess we should 312248619Sdes * ignore it when it is set for these cases, which is what we do now. 313248619Sdes */ 314248619Sdes (void) packet_get_char(); /* first_kex_follows */ 315248619Sdes (void) packet_get_int(); /* reserved */ 31692555Sdes packet_check_eom(); 31760573Skris 31876259Sgreen kex_kexinit_finish(kex); 31960573Skris} 32060573Skris 32176259SgreenKex * 32276259Sgreenkex_setup(char *proposal[PROPOSAL_MAX]) 32369587Sgreen{ 32476259Sgreen Kex *kex; 32569587Sgreen 326162852Sdes kex = xcalloc(1, sizeof(*kex)); 32776259Sgreen buffer_init(&kex->peer); 32876259Sgreen buffer_init(&kex->my); 32976259Sgreen kex_prop2buf(&kex->my, proposal); 33076259Sgreen kex->done = 0; 33169587Sgreen 33276259Sgreen kex_send_kexinit(kex); /* we start */ 33392555Sdes kex_reset_dispatch(); 33469587Sgreen 33576259Sgreen return kex; 33669587Sgreen} 33769587Sgreen 33892555Sdesstatic void 33976259Sgreenkex_kexinit_finish(Kex *kex) 34060573Skris{ 34176259Sgreen if (!(kex->flags & KEX_INIT_SENT)) 34276259Sgreen kex_send_kexinit(kex); 34360573Skris 34476259Sgreen kex_choose_conf(kex); 34560573Skris 346113908Sdes if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX && 347113908Sdes kex->kex[kex->kex_type] != NULL) { 348113908Sdes (kex->kex[kex->kex_type])(kex); 349113908Sdes } else { 35076259Sgreen fatal("Unsupported key exchange %d", kex->kex_type); 35160573Skris } 35260573Skris} 35360573Skris 35492555Sdesstatic void 35560573Skrischoose_enc(Enc *enc, char *client, char *server) 35660573Skris{ 35776259Sgreen char *name = match_list(client, server, NULL); 35860573Skris if (name == NULL) 359181111Sdes fatal("no matching cipher found: client %s server %s", 360181111Sdes client, server); 36192555Sdes if ((enc->cipher = cipher_by_name(name)) == NULL) 36269587Sgreen fatal("matching cipher is not supported: %s", name); 36360573Skris enc->name = name; 36460573Skris enc->enabled = 0; 36560573Skris enc->iv = NULL; 366248619Sdes enc->iv_len = cipher_ivlen(enc->cipher); 36760573Skris enc->key = NULL; 36892555Sdes enc->key_len = cipher_keylen(enc->cipher); 36992555Sdes enc->block_size = cipher_blocksize(enc->cipher); 37060573Skris} 371162852Sdes 37292555Sdesstatic void 37360573Skrischoose_mac(Mac *mac, char *client, char *server) 37460573Skris{ 37576259Sgreen char *name = match_list(client, server, NULL); 37660573Skris if (name == NULL) 377181111Sdes fatal("no matching mac found: client %s server %s", 378181111Sdes client, server); 379181111Sdes if (mac_setup(mac, name) < 0) 38060573Skris fatal("unsupported mac %s", name); 38176259Sgreen /* truncate the key */ 38276259Sgreen if (datafellows & SSH_BUG_HMAC) 38376259Sgreen mac->key_len = 16; 38460573Skris mac->name = name; 38560573Skris mac->key = NULL; 38660573Skris mac->enabled = 0; 38760573Skris} 388162852Sdes 38992555Sdesstatic void 39060573Skrischoose_comp(Comp *comp, char *client, char *server) 39160573Skris{ 39276259Sgreen char *name = match_list(client, server, NULL); 39360573Skris if (name == NULL) 39460573Skris fatal("no matching comp found: client %s server %s", client, server); 395149749Sdes if (strcmp(name, "zlib@openssh.com") == 0) { 396149749Sdes comp->type = COMP_DELAYED; 397149749Sdes } else if (strcmp(name, "zlib") == 0) { 398149749Sdes comp->type = COMP_ZLIB; 39960573Skris } else if (strcmp(name, "none") == 0) { 400149749Sdes comp->type = COMP_NONE; 40160573Skris } else { 40260573Skris fatal("unsupported comp %s", name); 40360573Skris } 40460573Skris comp->name = name; 40560573Skris} 406162852Sdes 40792555Sdesstatic void 40860573Skrischoose_kex(Kex *k, char *client, char *server) 40960573Skris{ 410255767Sdes const struct kexalg *kexalg; 411255767Sdes 41276259Sgreen k->name = match_list(client, server, NULL); 41360573Skris if (k->name == NULL) 414181111Sdes fatal("Unable to negotiate a key exchange method"); 415255767Sdes if ((kexalg = kex_alg_by_name(k->name)) == NULL) 416255767Sdes fatal("unsupported kex alg %s", k->name); 417255767Sdes k->kex_type = kexalg->type; 418261320Sdes k->hash_alg = kexalg->hash_alg; 419255767Sdes k->ec_nid = kexalg->ec_nid; 42060573Skris} 421157016Sdes 42292555Sdesstatic void 42360573Skrischoose_hostkeyalg(Kex *k, char *client, char *server) 42460573Skris{ 42576259Sgreen char *hostkeyalg = match_list(client, server, NULL); 42676259Sgreen if (hostkeyalg == NULL) 42760573Skris fatal("no hostkey alg"); 42876259Sgreen k->hostkey_type = key_type_from_name(hostkeyalg); 42976259Sgreen if (k->hostkey_type == KEY_UNSPEC) 43076259Sgreen fatal("bad hostkey alg '%s'", hostkeyalg); 431255767Sdes free(hostkeyalg); 43260573Skris} 43360573Skris 434126274Sdesstatic int 435113908Sdesproposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX]) 436113908Sdes{ 437113908Sdes static int check[] = { 438113908Sdes PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1 439113908Sdes }; 440113908Sdes int *idx; 441113908Sdes char *p; 442113908Sdes 443113908Sdes for (idx = &check[0]; *idx != -1; idx++) { 444113908Sdes if ((p = strchr(my[*idx], ',')) != NULL) 445113908Sdes *p = '\0'; 446113908Sdes if ((p = strchr(peer[*idx], ',')) != NULL) 447113908Sdes *p = '\0'; 448113908Sdes if (strcmp(my[*idx], peer[*idx]) != 0) { 449113908Sdes debug2("proposal mismatch: my %s peer %s", 450113908Sdes my[*idx], peer[*idx]); 451113908Sdes return (0); 452113908Sdes } 453113908Sdes } 454113908Sdes debug2("proposals match"); 455113908Sdes return (1); 456113908Sdes} 457113908Sdes 45892555Sdesstatic void 45976259Sgreenkex_choose_conf(Kex *kex) 46060573Skris{ 46176259Sgreen Newkeys *newkeys; 46276259Sgreen char **my, **peer; 46376259Sgreen char **cprop, **sprop; 46476259Sgreen int nenc, nmac, ncomp; 465261320Sdes u_int mode, ctos, need, dh_need, authlen; 466113908Sdes int first_kex_follows, type; 46760573Skris 468113908Sdes my = kex_buf2prop(&kex->my, NULL); 469113908Sdes peer = kex_buf2prop(&kex->peer, &first_kex_follows); 47060573Skris 47176259Sgreen if (kex->server) { 47276259Sgreen cprop=peer; 47376259Sgreen sprop=my; 47476259Sgreen } else { 47576259Sgreen cprop=my; 47676259Sgreen sprop=peer; 47776259Sgreen } 47876259Sgreen 479204917Sdes /* Check whether server offers roaming */ 480204917Sdes if (!kex->server) { 481204917Sdes char *roaming; 482204917Sdes roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL); 483204917Sdes if (roaming) { 484204917Sdes kex->roaming = 1; 485255767Sdes free(roaming); 486204917Sdes } 487204917Sdes } 488204917Sdes 48976259Sgreen /* Algorithm Negotiation */ 49060573Skris for (mode = 0; mode < MODE_MAX; mode++) { 491162852Sdes newkeys = xcalloc(1, sizeof(*newkeys)); 49276259Sgreen kex->newkeys[mode] = newkeys; 493181111Sdes ctos = (!kex->server && mode == MODE_OUT) || 494181111Sdes (kex->server && mode == MODE_IN); 49560573Skris nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; 49660573Skris nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; 49760573Skris ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; 498248619Sdes choose_enc(&newkeys->enc, cprop[nenc], sprop[nenc]); 499248619Sdes /* ignore mac for authenticated encryption */ 500248619Sdes authlen = cipher_authlen(newkeys->enc.cipher); 501248619Sdes if (authlen == 0) 502248619Sdes choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]); 50376259Sgreen choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); 50460573Skris debug("kex: %s %s %s %s", 50560573Skris ctos ? "client->server" : "server->client", 50676259Sgreen newkeys->enc.name, 507248619Sdes authlen == 0 ? newkeys->mac.name : "<implicit>", 50876259Sgreen newkeys->comp.name); 50960573Skris } 51076259Sgreen choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); 51176259Sgreen choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], 51260573Skris sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); 513261320Sdes need = dh_need = 0; 51460573Skris for (mode = 0; mode < MODE_MAX; mode++) { 51576259Sgreen newkeys = kex->newkeys[mode]; 516261320Sdes need = MAX(need, newkeys->enc.key_len); 517261320Sdes need = MAX(need, newkeys->enc.block_size); 518261320Sdes need = MAX(need, newkeys->enc.iv_len); 519261320Sdes need = MAX(need, newkeys->mac.key_len); 520261320Sdes dh_need = MAX(dh_need, cipher_seclen(newkeys->enc.cipher)); 521261320Sdes dh_need = MAX(dh_need, newkeys->enc.block_size); 522261320Sdes dh_need = MAX(dh_need, newkeys->enc.iv_len); 523261320Sdes dh_need = MAX(dh_need, newkeys->mac.key_len); 52460573Skris } 52561209Skris /* XXX need runden? */ 52676259Sgreen kex->we_need = need; 527261320Sdes kex->dh_need = dh_need; 52876259Sgreen 529113908Sdes /* ignore the next message if the proposals do not match */ 530126274Sdes if (first_kex_follows && !proposals_match(my, peer) && 531149749Sdes !(datafellows & SSH_BUG_FIRSTKEX)) { 532113908Sdes type = packet_read(); 533113908Sdes debug2("skipping next packet (type %u)", type); 534113908Sdes } 535113908Sdes 53676259Sgreen kex_prop_free(my); 53776259Sgreen kex_prop_free(peer); 53860573Skris} 53960573Skris 54092555Sdesstatic u_char * 541157016Sdesderive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, 542261320Sdes const u_char *shared_secret, u_int slen) 54360573Skris{ 54476259Sgreen Buffer b; 545261320Sdes struct ssh_digest_ctx *hashctx; 54676259Sgreen char c = id; 547149749Sdes u_int have; 548261320Sdes size_t mdsz; 549149749Sdes u_char *digest; 55060573Skris 551261320Sdes if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0) 552261320Sdes fatal("bad kex md size %zu", mdsz); 553162852Sdes digest = xmalloc(roundup(need, mdsz)); 554149749Sdes 55576259Sgreen buffer_init(&b); 556261320Sdes buffer_append(&b, shared_secret, slen); 55776259Sgreen 55876259Sgreen /* K1 = HASH(K || H || "A" || session_id) */ 559261320Sdes if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) 560261320Sdes fatal("%s: ssh_digest_start failed", __func__); 561261320Sdes if (ssh_digest_update_buffer(hashctx, &b) != 0 || 562261320Sdes ssh_digest_update(hashctx, hash, hashlen) != 0 || 563261320Sdes ssh_digest_update(hashctx, &c, 1) != 0 || 564261320Sdes ssh_digest_update(hashctx, kex->session_id, 565261320Sdes kex->session_id_len) != 0) 566261320Sdes fatal("%s: ssh_digest_update failed", __func__); 567261320Sdes if (ssh_digest_final(hashctx, digest, mdsz) != 0) 568261320Sdes fatal("%s: ssh_digest_final failed", __func__); 569261320Sdes ssh_digest_free(hashctx); 57076259Sgreen 57176259Sgreen /* 57276259Sgreen * expand key: 57376259Sgreen * Kn = HASH(K || H || K1 || K2 || ... || Kn-1) 57476259Sgreen * Key = K1 || K2 || ... || Kn 57576259Sgreen */ 57676259Sgreen for (have = mdsz; need > have; have += mdsz) { 577261320Sdes if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) 578261320Sdes fatal("%s: ssh_digest_start failed", __func__); 579261320Sdes if (ssh_digest_update_buffer(hashctx, &b) != 0 || 580261320Sdes ssh_digest_update(hashctx, hash, hashlen) != 0 || 581261320Sdes ssh_digest_update(hashctx, digest, have) != 0) 582261320Sdes fatal("%s: ssh_digest_update failed", __func__); 583261320Sdes if (ssh_digest_final(hashctx, digest + have, mdsz) != 0) 584261320Sdes fatal("%s: ssh_digest_final failed", __func__); 585261320Sdes ssh_digest_free(hashctx); 58676259Sgreen } 58776259Sgreen buffer_free(&b); 58876259Sgreen#ifdef DEBUG_KEX 58976259Sgreen fprintf(stderr, "key '%c'== ", c); 59076259Sgreen dump_digest("key", digest, need); 59176259Sgreen#endif 59276259Sgreen return digest; 59376259Sgreen} 59476259Sgreen 59576259SgreenNewkeys *current_keys[MODE_MAX]; 59676259Sgreen 59776259Sgreen#define NKEYS 6 59876259Sgreenvoid 599261320Sdeskex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, 600261320Sdes const u_char *shared_secret, u_int slen) 60176259Sgreen{ 60276259Sgreen u_char *keys[NKEYS]; 603149749Sdes u_int i, mode, ctos; 60476259Sgreen 605157016Sdes for (i = 0; i < NKEYS; i++) { 606157016Sdes keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, hashlen, 607261320Sdes shared_secret, slen); 608157016Sdes } 60960573Skris 610113908Sdes debug2("kex_derive_keys"); 61160573Skris for (mode = 0; mode < MODE_MAX; mode++) { 61276259Sgreen current_keys[mode] = kex->newkeys[mode]; 61376259Sgreen kex->newkeys[mode] = NULL; 614162852Sdes ctos = (!kex->server && mode == MODE_OUT) || 615162852Sdes (kex->server && mode == MODE_IN); 61676259Sgreen current_keys[mode]->enc.iv = keys[ctos ? 0 : 1]; 61776259Sgreen current_keys[mode]->enc.key = keys[ctos ? 2 : 3]; 61876259Sgreen current_keys[mode]->mac.key = keys[ctos ? 4 : 5]; 61960573Skris } 62060573Skris} 62176259Sgreen 622294328Sdes#ifdef WITH_OPENSSL 623261320Sdesvoid 624261320Sdeskex_derive_keys_bn(Kex *kex, u_char *hash, u_int hashlen, const BIGNUM *secret) 625261320Sdes{ 626261320Sdes Buffer shared_secret; 627261320Sdes 628261320Sdes buffer_init(&shared_secret); 629261320Sdes buffer_put_bignum2(&shared_secret, secret); 630261320Sdes kex_derive_keys(kex, hash, hashlen, 631261320Sdes buffer_ptr(&shared_secret), buffer_len(&shared_secret)); 632261320Sdes buffer_free(&shared_secret); 633261320Sdes} 634294328Sdes#endif 635261320Sdes 63676259SgreenNewkeys * 63776259Sgreenkex_get_newkeys(int mode) 63876259Sgreen{ 63976259Sgreen Newkeys *ret; 64076259Sgreen 64176259Sgreen ret = current_keys[mode]; 64276259Sgreen current_keys[mode] = NULL; 64376259Sgreen return ret; 64476259Sgreen} 64576259Sgreen 646294328Sdes#ifdef WITH_SSH1 647137015Sdesvoid 648137015Sdesderive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, 649137015Sdes u_int8_t cookie[8], u_int8_t id[16]) 650137015Sdes{ 651261320Sdes u_int8_t nbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH]; 652137015Sdes int len; 653261320Sdes struct ssh_digest_ctx *hashctx; 654137015Sdes 655261320Sdes if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL) 656261320Sdes fatal("%s: ssh_digest_start", __func__); 657137015Sdes 658137015Sdes len = BN_num_bytes(host_modulus); 659149749Sdes if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) 660137015Sdes fatal("%s: bad host modulus (len %d)", __func__, len); 661137015Sdes BN_bn2bin(host_modulus, nbuf); 662261320Sdes if (ssh_digest_update(hashctx, nbuf, len) != 0) 663261320Sdes fatal("%s: ssh_digest_update failed", __func__); 664137015Sdes 665137015Sdes len = BN_num_bytes(server_modulus); 666149749Sdes if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) 667137015Sdes fatal("%s: bad server modulus (len %d)", __func__, len); 668137015Sdes BN_bn2bin(server_modulus, nbuf); 669261320Sdes if (ssh_digest_update(hashctx, nbuf, len) != 0 || 670261320Sdes ssh_digest_update(hashctx, cookie, 8) != 0) 671261320Sdes fatal("%s: ssh_digest_update failed", __func__); 672261320Sdes if (ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) 673261320Sdes fatal("%s: ssh_digest_final failed", __func__); 674261320Sdes memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5)); 675137015Sdes 676263712Sdes explicit_bzero(nbuf, sizeof(nbuf)); 677263712Sdes explicit_bzero(obuf, sizeof(obuf)); 678137015Sdes} 679294328Sdes#endif 680137015Sdes 681221420Sdes#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) 68276259Sgreenvoid 68376259Sgreendump_digest(char *msg, u_char *digest, int len) 68476259Sgreen{ 685221420Sdes int i; 68676259Sgreen 68776259Sgreen fprintf(stderr, "%s\n", msg); 688181111Sdes for (i = 0; i < len; i++) { 68976259Sgreen fprintf(stderr, "%02x", digest[i]); 69076259Sgreen if (i%32 == 31) 69176259Sgreen fprintf(stderr, "\n"); 69276259Sgreen else if (i%8 == 7) 69376259Sgreen fprintf(stderr, " "); 69476259Sgreen } 69576259Sgreen fprintf(stderr, "\n"); 69676259Sgreen} 69776259Sgreen#endif 698