1263970Sdes/* $OpenBSD: kex.c,v 1.98 2014/02/02 03:44:31 djm Exp $ */ 2224638Sbrooks/* $FreeBSD$ */ 360573Skris/* 492555Sdes * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 560573Skris * 660573Skris * Redistribution and use in source and binary forms, with or without 760573Skris * modification, are permitted provided that the following conditions 860573Skris * are met: 960573Skris * 1. Redistributions of source code must retain the above copyright 1060573Skris * notice, this list of conditions and the following disclaimer. 1160573Skris * 2. Redistributions in binary form must reproduce the above copyright 1260573Skris * notice, this list of conditions and the following disclaimer in the 1360573Skris * documentation and/or other materials provided with the distribution. 1460573Skris * 1560573Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1660573Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1760573Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1860573Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1960573Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2060573Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2160573Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2260573Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2360573Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2460573Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2560573Skris */ 2660573Skris 2760573Skris#include "includes.h" 28263970Sdes__RCSID("$FreeBSD$"); 2960573Skris 30162852Sdes#include <sys/param.h> 31162852Sdes 32162852Sdes#include <signal.h> 33162852Sdes#include <stdarg.h> 34162852Sdes#include <stdio.h> 35162852Sdes#include <stdlib.h> 36162852Sdes#include <string.h> 37162852Sdes 3876259Sgreen#include <openssl/crypto.h> 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" 54263970Sdes#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 68263970Sdesstruct kexalg { 69263970Sdes char *name; 70263970Sdes int type; 71263970Sdes int ec_nid; 72263970Sdes int hash_alg; 73263970Sdes}; 74263970Sdesstatic const struct kexalg kexalgs[] = { 75263970Sdes { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, 76263970Sdes { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, 77263970Sdes { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, 78263970Sdes#ifdef HAVE_EVP_SHA256 79263970Sdes { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, 80263970Sdes#endif 81263970Sdes#ifdef OPENSSL_HAS_ECC 82263970Sdes { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, 83263970Sdes NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, 84263970Sdes { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, 85263970Sdes SSH_DIGEST_SHA384 }, 86263970Sdes# ifdef OPENSSL_HAS_NISTP521 87263970Sdes { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, 88263970Sdes SSH_DIGEST_SHA512 }, 89263970Sdes# endif 90263970Sdes#endif 91263970Sdes { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, 92263970Sdes#ifdef HAVE_EVP_SHA256 93263970Sdes { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, 94263970Sdes#endif 95263970Sdes { NULL, -1, -1, -1}, 96263970Sdes}; 97263970Sdes 98263970Sdeschar * 99263970Sdeskex_alg_list(char sep) 100263970Sdes{ 101263970Sdes char *ret = NULL; 102263970Sdes size_t nlen, rlen = 0; 103263970Sdes const struct kexalg *k; 104263970Sdes 105263970Sdes for (k = kexalgs; k->name != NULL; k++) { 106263970Sdes if (ret != NULL) 107263970Sdes ret[rlen++] = sep; 108263970Sdes nlen = strlen(k->name); 109263970Sdes ret = xrealloc(ret, 1, rlen + nlen + 2); 110263970Sdes memcpy(ret + rlen, k->name, nlen + 1); 111263970Sdes rlen += nlen; 112263970Sdes } 113263970Sdes return ret; 114263970Sdes} 115263970Sdes 116263970Sdesstatic const struct kexalg * 117263970Sdeskex_alg_by_name(const char *name) 118263970Sdes{ 119263970Sdes const struct kexalg *k; 120263970Sdes 121263970Sdes for (k = kexalgs; k->name != NULL; k++) { 122263970Sdes if (strcmp(k->name, name) == 0) 123263970Sdes return k; 124263970Sdes } 125263970Sdes return NULL; 126263970Sdes} 127263970Sdes 128221420Sdes/* Validate KEX method name list */ 129221420Sdesint 130221420Sdeskex_names_valid(const char *names) 131221420Sdes{ 132221420Sdes char *s, *cp, *p; 133221420Sdes 134221420Sdes if (names == NULL || strcmp(names, "") == 0) 135221420Sdes return 0; 136221420Sdes s = cp = xstrdup(names); 137221420Sdes for ((p = strsep(&cp, ",")); p && *p != '\0'; 138221420Sdes (p = strsep(&cp, ","))) { 139263970Sdes if (kex_alg_by_name(p) == NULL) { 140221420Sdes error("Unsupported KEX algorithm \"%.100s\"", p); 141263970Sdes free(s); 142221420Sdes return 0; 143221420Sdes } 144221420Sdes } 145221420Sdes debug3("kex names ok: [%s]", names); 146263970Sdes free(s); 147221420Sdes return 1; 148221420Sdes} 149221420Sdes 150247485Sdes/* put algorithm proposal into buffer. */ 151224638Sbrooks#ifndef NONE_CIPHER_ENABLED 15292555Sdesstatic void 153224638Sbrooks#else 154224638Sbrooks/* Also used in sshconnect2.c. */ 155224638Sbrooksvoid 156224638Sbrooks#endif 15776259Sgreenkex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) 15860573Skris{ 159149749Sdes u_int i; 16076259Sgreen 16176259Sgreen buffer_clear(b); 16298675Sdes /* 16398675Sdes * add a dummy cookie, the cookie will be overwritten by 16498675Sdes * kex_send_kexinit(), each time a kexinit is set 16598675Sdes */ 16698675Sdes for (i = 0; i < KEX_COOKIE_LEN; i++) 16798675Sdes buffer_put_char(b, 0); 16860573Skris for (i = 0; i < PROPOSAL_MAX; i++) 16976259Sgreen buffer_put_cstring(b, proposal[i]); 17076259Sgreen buffer_put_char(b, 0); /* first_kex_packet_follows */ 17176259Sgreen buffer_put_int(b, 0); /* uint32 reserved */ 17260573Skris} 17360573Skris 17476259Sgreen/* parse buffer and return algorithm proposal */ 17592555Sdesstatic char ** 176113908Sdeskex_buf2prop(Buffer *raw, int *first_kex_follows) 17761209Skris{ 17876259Sgreen Buffer b; 179181111Sdes u_int i; 18076259Sgreen char **proposal; 18161209Skris 182162852Sdes proposal = xcalloc(PROPOSAL_MAX, sizeof(char *)); 18361209Skris 18476259Sgreen buffer_init(&b); 18576259Sgreen buffer_append(&b, buffer_ptr(raw), buffer_len(raw)); 18661209Skris /* skip cookie */ 18761209Skris for (i = 0; i < KEX_COOKIE_LEN; i++) 18876259Sgreen buffer_get_char(&b); 18961209Skris /* extract kex init proposal strings */ 19061209Skris for (i = 0; i < PROPOSAL_MAX; i++) { 191221420Sdes proposal[i] = buffer_get_cstring(&b,NULL); 19276259Sgreen debug2("kex_parse_kexinit: %s", proposal[i]); 19361209Skris } 19476259Sgreen /* first kex follows / reserved */ 19576259Sgreen i = buffer_get_char(&b); 196113908Sdes if (first_kex_follows != NULL) 197113908Sdes *first_kex_follows = i; 19876259Sgreen debug2("kex_parse_kexinit: first_kex_follows %d ", i); 19976259Sgreen i = buffer_get_int(&b); 200181111Sdes debug2("kex_parse_kexinit: reserved %u ", i); 20176259Sgreen buffer_free(&b); 20276259Sgreen return proposal; 20361209Skris} 20461209Skris 20592555Sdesstatic void 20676259Sgreenkex_prop_free(char **proposal) 20760573Skris{ 208149749Sdes u_int i; 20960573Skris 21076259Sgreen for (i = 0; i < PROPOSAL_MAX; i++) 211263970Sdes free(proposal[i]); 212263970Sdes free(proposal); 21360573Skris} 21460573Skris 215181111Sdes/* ARGSUSED */ 21692555Sdesstatic void 21792555Sdeskex_protocol_error(int type, u_int32_t seq, void *ctxt) 21860573Skris{ 21992555Sdes error("Hm, kex protocol error: type %d seq %u", type, seq); 22060573Skris} 22160573Skris 22292555Sdesstatic void 22392555Sdeskex_reset_dispatch(void) 22469587Sgreen{ 22592555Sdes dispatch_range(SSH2_MSG_TRANSPORT_MIN, 22692555Sdes SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); 22792555Sdes dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); 22869587Sgreen} 22969587Sgreen 23076259Sgreenvoid 23176259Sgreenkex_finish(Kex *kex) 23269587Sgreen{ 23392555Sdes kex_reset_dispatch(); 23469587Sgreen 23576259Sgreen packet_start(SSH2_MSG_NEWKEYS); 23676259Sgreen packet_send(); 23776259Sgreen /* packet_write_wait(); */ 23876259Sgreen debug("SSH2_MSG_NEWKEYS sent"); 23969587Sgreen 240113908Sdes debug("expecting SSH2_MSG_NEWKEYS"); 24192555Sdes packet_read_expect(SSH2_MSG_NEWKEYS); 24292555Sdes packet_check_eom(); 24376259Sgreen debug("SSH2_MSG_NEWKEYS received"); 24469587Sgreen 24576259Sgreen kex->done = 1; 24676259Sgreen buffer_clear(&kex->peer); 24776259Sgreen /* buffer_clear(&kex->my); */ 24876259Sgreen kex->flags &= ~KEX_INIT_SENT; 249263970Sdes free(kex->name); 25076259Sgreen kex->name = NULL; 25169587Sgreen} 25269587Sgreen 25360573Skrisvoid 25476259Sgreenkex_send_kexinit(Kex *kex) 25560573Skris{ 256137015Sdes u_int32_t rnd = 0; 25798675Sdes u_char *cookie; 258149749Sdes u_int i; 25998675Sdes 26076259Sgreen if (kex == NULL) { 26176259Sgreen error("kex_send_kexinit: no kex, cannot rekey"); 26276259Sgreen return; 26360573Skris } 26476259Sgreen if (kex->flags & KEX_INIT_SENT) { 26576259Sgreen debug("KEX_INIT_SENT"); 26676259Sgreen return; 26776259Sgreen } 26876259Sgreen kex->done = 0; 26998675Sdes 27098675Sdes /* generate a random cookie */ 27198675Sdes if (buffer_len(&kex->my) < KEX_COOKIE_LEN) 27298675Sdes fatal("kex_send_kexinit: kex proposal too short"); 27398675Sdes cookie = buffer_ptr(&kex->my); 27498675Sdes for (i = 0; i < KEX_COOKIE_LEN; i++) { 27598675Sdes if (i % 4 == 0) 276137015Sdes rnd = arc4random(); 277137015Sdes cookie[i] = rnd; 278137015Sdes rnd >>= 8; 27998675Sdes } 28076259Sgreen packet_start(SSH2_MSG_KEXINIT); 28176259Sgreen packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); 28276259Sgreen packet_send(); 28376259Sgreen debug("SSH2_MSG_KEXINIT sent"); 28476259Sgreen kex->flags |= KEX_INIT_SENT; 28560573Skris} 28660573Skris 287181111Sdes/* ARGSUSED */ 28876259Sgreenvoid 28992555Sdeskex_input_kexinit(int type, u_int32_t seq, void *ctxt) 29060573Skris{ 29176259Sgreen char *ptr; 292149749Sdes u_int i, dlen; 29376259Sgreen Kex *kex = (Kex *)ctxt; 29460573Skris 29576259Sgreen debug("SSH2_MSG_KEXINIT received"); 29676259Sgreen if (kex == NULL) 29776259Sgreen fatal("kex_input_kexinit: no kex, cannot rekey"); 29860573Skris 29976259Sgreen ptr = packet_get_raw(&dlen); 30076259Sgreen buffer_append(&kex->peer, ptr, dlen); 30160573Skris 30276259Sgreen /* discard packet */ 30376259Sgreen for (i = 0; i < KEX_COOKIE_LEN; i++) 30476259Sgreen packet_get_char(); 30576259Sgreen for (i = 0; i < PROPOSAL_MAX; i++) 306263970Sdes free(packet_get_string(NULL)); 307251135Sdes /* 308251135Sdes * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported 309251135Sdes * KEX method has the server move first, but a server might be using 310251135Sdes * a custom method or one that we otherwise don't support. We should 311251135Sdes * be prepared to remember first_kex_follows here so we can eat a 312251135Sdes * packet later. 313251135Sdes * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means 314251135Sdes * for cases where the server *doesn't* go first. I guess we should 315251135Sdes * ignore it when it is set for these cases, which is what we do now. 316251135Sdes */ 317251135Sdes (void) packet_get_char(); /* first_kex_follows */ 318251135Sdes (void) packet_get_int(); /* reserved */ 31992555Sdes packet_check_eom(); 32060573Skris 32176259Sgreen kex_kexinit_finish(kex); 32260573Skris} 32360573Skris 32476259SgreenKex * 32576259Sgreenkex_setup(char *proposal[PROPOSAL_MAX]) 32669587Sgreen{ 32776259Sgreen Kex *kex; 32869587Sgreen 329162852Sdes kex = xcalloc(1, sizeof(*kex)); 33076259Sgreen buffer_init(&kex->peer); 33176259Sgreen buffer_init(&kex->my); 33276259Sgreen kex_prop2buf(&kex->my, proposal); 33376259Sgreen kex->done = 0; 33469587Sgreen 33576259Sgreen kex_send_kexinit(kex); /* we start */ 33692555Sdes kex_reset_dispatch(); 33769587Sgreen 33876259Sgreen return kex; 33969587Sgreen} 34069587Sgreen 34192555Sdesstatic void 34276259Sgreenkex_kexinit_finish(Kex *kex) 34360573Skris{ 34476259Sgreen if (!(kex->flags & KEX_INIT_SENT)) 34576259Sgreen kex_send_kexinit(kex); 34660573Skris 34776259Sgreen kex_choose_conf(kex); 34860573Skris 349113908Sdes if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX && 350113908Sdes kex->kex[kex->kex_type] != NULL) { 351113908Sdes (kex->kex[kex->kex_type])(kex); 352113908Sdes } else { 35376259Sgreen fatal("Unsupported key exchange %d", kex->kex_type); 35460573Skris } 35560573Skris} 35660573Skris 35792555Sdesstatic void 35860573Skrischoose_enc(Enc *enc, char *client, char *server) 35960573Skris{ 36076259Sgreen char *name = match_list(client, server, NULL); 36160573Skris if (name == NULL) 362181111Sdes fatal("no matching cipher found: client %s server %s", 363181111Sdes client, server); 36492555Sdes if ((enc->cipher = cipher_by_name(name)) == NULL) 36569587Sgreen fatal("matching cipher is not supported: %s", name); 36660573Skris enc->name = name; 36760573Skris enc->enabled = 0; 36860573Skris enc->iv = NULL; 369251135Sdes enc->iv_len = cipher_ivlen(enc->cipher); 37060573Skris enc->key = NULL; 37192555Sdes enc->key_len = cipher_keylen(enc->cipher); 37292555Sdes enc->block_size = cipher_blocksize(enc->cipher); 37360573Skris} 374162852Sdes 37592555Sdesstatic void 37660573Skrischoose_mac(Mac *mac, char *client, char *server) 37760573Skris{ 37876259Sgreen char *name = match_list(client, server, NULL); 37960573Skris if (name == NULL) 380181111Sdes fatal("no matching mac found: client %s server %s", 381181111Sdes client, server); 382181111Sdes if (mac_setup(mac, name) < 0) 38360573Skris fatal("unsupported mac %s", name); 38476259Sgreen /* truncate the key */ 38576259Sgreen if (datafellows & SSH_BUG_HMAC) 38676259Sgreen mac->key_len = 16; 38760573Skris mac->name = name; 38860573Skris mac->key = NULL; 38960573Skris mac->enabled = 0; 39060573Skris} 391162852Sdes 39292555Sdesstatic void 39360573Skrischoose_comp(Comp *comp, char *client, char *server) 39460573Skris{ 39576259Sgreen char *name = match_list(client, server, NULL); 39660573Skris if (name == NULL) 39760573Skris fatal("no matching comp found: client %s server %s", client, server); 398149749Sdes if (strcmp(name, "zlib@openssh.com") == 0) { 399149749Sdes comp->type = COMP_DELAYED; 400149749Sdes } else if (strcmp(name, "zlib") == 0) { 401149749Sdes comp->type = COMP_ZLIB; 40260573Skris } else if (strcmp(name, "none") == 0) { 403149749Sdes comp->type = COMP_NONE; 40460573Skris } else { 40560573Skris fatal("unsupported comp %s", name); 40660573Skris } 40760573Skris comp->name = name; 40860573Skris} 409162852Sdes 41092555Sdesstatic void 41160573Skrischoose_kex(Kex *k, char *client, char *server) 41260573Skris{ 413263970Sdes const struct kexalg *kexalg; 414263970Sdes 41576259Sgreen k->name = match_list(client, server, NULL); 41660573Skris if (k->name == NULL) 417181111Sdes fatal("Unable to negotiate a key exchange method"); 418263970Sdes if ((kexalg = kex_alg_by_name(k->name)) == NULL) 419263970Sdes fatal("unsupported kex alg %s", k->name); 420263970Sdes k->kex_type = kexalg->type; 421263970Sdes k->hash_alg = kexalg->hash_alg; 422263970Sdes k->ec_nid = kexalg->ec_nid; 42360573Skris} 424157016Sdes 42592555Sdesstatic void 42660573Skrischoose_hostkeyalg(Kex *k, char *client, char *server) 42760573Skris{ 42876259Sgreen char *hostkeyalg = match_list(client, server, NULL); 42976259Sgreen if (hostkeyalg == NULL) 43060573Skris fatal("no hostkey alg"); 43176259Sgreen k->hostkey_type = key_type_from_name(hostkeyalg); 43276259Sgreen if (k->hostkey_type == KEY_UNSPEC) 43376259Sgreen fatal("bad hostkey alg '%s'", hostkeyalg); 434263970Sdes free(hostkeyalg); 43560573Skris} 43660573Skris 437126274Sdesstatic int 438113908Sdesproposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX]) 439113908Sdes{ 440113908Sdes static int check[] = { 441113908Sdes PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1 442113908Sdes }; 443113908Sdes int *idx; 444113908Sdes char *p; 445113908Sdes 446113908Sdes for (idx = &check[0]; *idx != -1; idx++) { 447113908Sdes if ((p = strchr(my[*idx], ',')) != NULL) 448113908Sdes *p = '\0'; 449113908Sdes if ((p = strchr(peer[*idx], ',')) != NULL) 450113908Sdes *p = '\0'; 451113908Sdes if (strcmp(my[*idx], peer[*idx]) != 0) { 452113908Sdes debug2("proposal mismatch: my %s peer %s", 453113908Sdes my[*idx], peer[*idx]); 454113908Sdes return (0); 455113908Sdes } 456113908Sdes } 457113908Sdes debug2("proposals match"); 458113908Sdes return (1); 459113908Sdes} 460113908Sdes 46192555Sdesstatic void 46276259Sgreenkex_choose_conf(Kex *kex) 46360573Skris{ 46476259Sgreen Newkeys *newkeys; 46576259Sgreen char **my, **peer; 46676259Sgreen char **cprop, **sprop; 46776259Sgreen int nenc, nmac, ncomp; 468263970Sdes u_int mode, ctos, need, dh_need, authlen; 469113908Sdes int first_kex_follows, type; 470224638Sbrooks#ifdef NONE_CIPHER_ENABLED 471224638Sbrooks int auth_flag; 472224638Sbrooks#endif 47360573Skris 474113908Sdes my = kex_buf2prop(&kex->my, NULL); 475113908Sdes peer = kex_buf2prop(&kex->peer, &first_kex_follows); 47660573Skris 47776259Sgreen if (kex->server) { 47876259Sgreen cprop=peer; 47976259Sgreen sprop=my; 48076259Sgreen } else { 48176259Sgreen cprop=my; 48276259Sgreen sprop=peer; 48376259Sgreen } 48476259Sgreen 485204917Sdes /* Check whether server offers roaming */ 486204917Sdes if (!kex->server) { 487204917Sdes char *roaming; 488204917Sdes roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL); 489204917Sdes if (roaming) { 490204917Sdes kex->roaming = 1; 491263970Sdes free(roaming); 492204917Sdes } 493204917Sdes } 494204917Sdes 49576259Sgreen /* Algorithm Negotiation */ 496224638Sbrooks#ifdef NONE_CIPHER_ENABLED 497224638Sbrooks auth_flag = packet_get_authentication_state(); 498224638Sbrooks debug ("AUTH STATE is %d", auth_flag); 499224638Sbrooks#endif 50060573Skris for (mode = 0; mode < MODE_MAX; mode++) { 501162852Sdes newkeys = xcalloc(1, sizeof(*newkeys)); 50276259Sgreen kex->newkeys[mode] = newkeys; 503181111Sdes ctos = (!kex->server && mode == MODE_OUT) || 504181111Sdes (kex->server && mode == MODE_IN); 50560573Skris nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; 50660573Skris nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; 50760573Skris ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; 508251135Sdes choose_enc(&newkeys->enc, cprop[nenc], sprop[nenc]); 509251135Sdes /* ignore mac for authenticated encryption */ 510251135Sdes authlen = cipher_authlen(newkeys->enc.cipher); 511251135Sdes if (authlen == 0) 512251135Sdes choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]); 51376259Sgreen choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); 514224638Sbrooks#ifdef NONE_CIPHER_ENABLED 515224638Sbrooks debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name); 516224638Sbrooks if (strcmp(newkeys->enc.name, "none") == 0) { 517247485Sdes debug("Requesting NONE. Authflag is %d", auth_flag); 518224638Sbrooks if (auth_flag == 1) 519224638Sbrooks debug("None requested post authentication."); 520224638Sbrooks else 521224638Sbrooks fatal("Pre-authentication none cipher requests " 522224638Sbrooks "are not allowed."); 523247485Sdes } 524224638Sbrooks#endif 52560573Skris debug("kex: %s %s %s %s", 52660573Skris ctos ? "client->server" : "server->client", 52776259Sgreen newkeys->enc.name, 528251135Sdes authlen == 0 ? newkeys->mac.name : "<implicit>", 52976259Sgreen newkeys->comp.name); 53060573Skris } 53176259Sgreen choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); 53276259Sgreen choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], 53360573Skris sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); 534263970Sdes need = dh_need = 0; 53560573Skris for (mode = 0; mode < MODE_MAX; mode++) { 53676259Sgreen newkeys = kex->newkeys[mode]; 537263970Sdes need = MAX(need, newkeys->enc.key_len); 538263970Sdes need = MAX(need, newkeys->enc.block_size); 539263970Sdes need = MAX(need, newkeys->enc.iv_len); 540263970Sdes need = MAX(need, newkeys->mac.key_len); 541263970Sdes dh_need = MAX(dh_need, cipher_seclen(newkeys->enc.cipher)); 542263970Sdes dh_need = MAX(dh_need, newkeys->enc.block_size); 543263970Sdes dh_need = MAX(dh_need, newkeys->enc.iv_len); 544263970Sdes dh_need = MAX(dh_need, newkeys->mac.key_len); 54560573Skris } 54661209Skris /* XXX need runden? */ 54776259Sgreen kex->we_need = need; 548263970Sdes kex->dh_need = dh_need; 54976259Sgreen 550113908Sdes /* ignore the next message if the proposals do not match */ 551126274Sdes if (first_kex_follows && !proposals_match(my, peer) && 552149749Sdes !(datafellows & SSH_BUG_FIRSTKEX)) { 553113908Sdes type = packet_read(); 554113908Sdes debug2("skipping next packet (type %u)", type); 555113908Sdes } 556113908Sdes 55776259Sgreen kex_prop_free(my); 55876259Sgreen kex_prop_free(peer); 55960573Skris} 56060573Skris 56192555Sdesstatic u_char * 562157016Sdesderive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, 563263970Sdes const u_char *shared_secret, u_int slen) 56460573Skris{ 56576259Sgreen Buffer b; 566263970Sdes struct ssh_digest_ctx *hashctx; 56776259Sgreen char c = id; 568149749Sdes u_int have; 569263970Sdes size_t mdsz; 570149749Sdes u_char *digest; 57160573Skris 572263970Sdes if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0) 573263970Sdes fatal("bad kex md size %zu", mdsz); 574162852Sdes digest = xmalloc(roundup(need, mdsz)); 575149749Sdes 57676259Sgreen buffer_init(&b); 577263970Sdes buffer_append(&b, shared_secret, slen); 57876259Sgreen 57976259Sgreen /* K1 = HASH(K || H || "A" || session_id) */ 580263970Sdes if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) 581263970Sdes fatal("%s: ssh_digest_start failed", __func__); 582263970Sdes if (ssh_digest_update_buffer(hashctx, &b) != 0 || 583263970Sdes ssh_digest_update(hashctx, hash, hashlen) != 0 || 584263970Sdes ssh_digest_update(hashctx, &c, 1) != 0 || 585263970Sdes ssh_digest_update(hashctx, kex->session_id, 586263970Sdes kex->session_id_len) != 0) 587263970Sdes fatal("%s: ssh_digest_update failed", __func__); 588263970Sdes if (ssh_digest_final(hashctx, digest, mdsz) != 0) 589263970Sdes fatal("%s: ssh_digest_final failed", __func__); 590263970Sdes ssh_digest_free(hashctx); 59176259Sgreen 59276259Sgreen /* 59376259Sgreen * expand key: 59476259Sgreen * Kn = HASH(K || H || K1 || K2 || ... || Kn-1) 59576259Sgreen * Key = K1 || K2 || ... || Kn 59676259Sgreen */ 59776259Sgreen for (have = mdsz; need > have; have += mdsz) { 598263970Sdes if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) 599263970Sdes fatal("%s: ssh_digest_start failed", __func__); 600263970Sdes if (ssh_digest_update_buffer(hashctx, &b) != 0 || 601263970Sdes ssh_digest_update(hashctx, hash, hashlen) != 0 || 602263970Sdes ssh_digest_update(hashctx, digest, have) != 0) 603263970Sdes fatal("%s: ssh_digest_update failed", __func__); 604263970Sdes if (ssh_digest_final(hashctx, digest + have, mdsz) != 0) 605263970Sdes fatal("%s: ssh_digest_final failed", __func__); 606263970Sdes ssh_digest_free(hashctx); 60776259Sgreen } 60876259Sgreen buffer_free(&b); 60976259Sgreen#ifdef DEBUG_KEX 61076259Sgreen fprintf(stderr, "key '%c'== ", c); 61176259Sgreen dump_digest("key", digest, need); 61276259Sgreen#endif 61376259Sgreen return digest; 61476259Sgreen} 61576259Sgreen 61676259SgreenNewkeys *current_keys[MODE_MAX]; 61776259Sgreen 61876259Sgreen#define NKEYS 6 61976259Sgreenvoid 620263970Sdeskex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, 621263970Sdes const u_char *shared_secret, u_int slen) 62276259Sgreen{ 62376259Sgreen u_char *keys[NKEYS]; 624149749Sdes u_int i, mode, ctos; 62576259Sgreen 626157016Sdes for (i = 0; i < NKEYS; i++) { 627157016Sdes keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, hashlen, 628263970Sdes shared_secret, slen); 629157016Sdes } 63060573Skris 631113908Sdes debug2("kex_derive_keys"); 63260573Skris for (mode = 0; mode < MODE_MAX; mode++) { 63376259Sgreen current_keys[mode] = kex->newkeys[mode]; 63476259Sgreen kex->newkeys[mode] = NULL; 635162852Sdes ctos = (!kex->server && mode == MODE_OUT) || 636162852Sdes (kex->server && mode == MODE_IN); 63776259Sgreen current_keys[mode]->enc.iv = keys[ctos ? 0 : 1]; 63876259Sgreen current_keys[mode]->enc.key = keys[ctos ? 2 : 3]; 63976259Sgreen current_keys[mode]->mac.key = keys[ctos ? 4 : 5]; 64060573Skris } 64160573Skris} 64276259Sgreen 643263970Sdesvoid 644263970Sdeskex_derive_keys_bn(Kex *kex, u_char *hash, u_int hashlen, const BIGNUM *secret) 645263970Sdes{ 646263970Sdes Buffer shared_secret; 647263970Sdes 648263970Sdes buffer_init(&shared_secret); 649263970Sdes buffer_put_bignum2(&shared_secret, secret); 650263970Sdes kex_derive_keys(kex, hash, hashlen, 651263970Sdes buffer_ptr(&shared_secret), buffer_len(&shared_secret)); 652263970Sdes buffer_free(&shared_secret); 653263970Sdes} 654263970Sdes 65576259SgreenNewkeys * 65676259Sgreenkex_get_newkeys(int mode) 65776259Sgreen{ 65876259Sgreen Newkeys *ret; 65976259Sgreen 66076259Sgreen ret = current_keys[mode]; 66176259Sgreen current_keys[mode] = NULL; 66276259Sgreen return ret; 66376259Sgreen} 66476259Sgreen 665137015Sdesvoid 666137015Sdesderive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, 667137015Sdes u_int8_t cookie[8], u_int8_t id[16]) 668137015Sdes{ 669263970Sdes u_int8_t nbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH]; 670137015Sdes int len; 671263970Sdes struct ssh_digest_ctx *hashctx; 672137015Sdes 673263970Sdes if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL) 674263970Sdes fatal("%s: ssh_digest_start", __func__); 675137015Sdes 676137015Sdes len = BN_num_bytes(host_modulus); 677149749Sdes if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) 678137015Sdes fatal("%s: bad host modulus (len %d)", __func__, len); 679137015Sdes BN_bn2bin(host_modulus, nbuf); 680263970Sdes if (ssh_digest_update(hashctx, nbuf, len) != 0) 681263970Sdes fatal("%s: ssh_digest_update failed", __func__); 682137015Sdes 683137015Sdes len = BN_num_bytes(server_modulus); 684149749Sdes if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) 685137015Sdes fatal("%s: bad server modulus (len %d)", __func__, len); 686137015Sdes BN_bn2bin(server_modulus, nbuf); 687263970Sdes if (ssh_digest_update(hashctx, nbuf, len) != 0 || 688263970Sdes ssh_digest_update(hashctx, cookie, 8) != 0) 689263970Sdes fatal("%s: ssh_digest_update failed", __func__); 690263970Sdes if (ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) 691263970Sdes fatal("%s: ssh_digest_final failed", __func__); 692263970Sdes memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5)); 693137015Sdes 694263970Sdes explicit_bzero(nbuf, sizeof(nbuf)); 695263970Sdes explicit_bzero(obuf, sizeof(obuf)); 696137015Sdes} 697137015Sdes 698221420Sdes#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) 69976259Sgreenvoid 70076259Sgreendump_digest(char *msg, u_char *digest, int len) 70176259Sgreen{ 702221420Sdes int i; 70376259Sgreen 70476259Sgreen fprintf(stderr, "%s\n", msg); 705181111Sdes for (i = 0; i < len; i++) { 70676259Sgreen fprintf(stderr, "%02x", digest[i]); 70776259Sgreen if (i%32 == 31) 70876259Sgreen fprintf(stderr, "\n"); 70976259Sgreen else if (i%8 == 7) 71076259Sgreen fprintf(stderr, " "); 71176259Sgreen } 71276259Sgreen fprintf(stderr, "\n"); 71376259Sgreen} 71476259Sgreen#endif 715