kex.c revision 255767
1255767Sdes/* $OpenBSD: kex.c,v 1.91 2013/05/17 00:13:13 djm Exp $ */ 2224638Sbrooks/* $FreeBSD: head/crypto/openssh/kex.c 255767 2013-09-21 21:36:09Z des $ */ 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" 2860573Skris 29162852Sdes#include <sys/param.h> 30162852Sdes 31162852Sdes#include <signal.h> 32162852Sdes#include <stdarg.h> 33162852Sdes#include <stdio.h> 34162852Sdes#include <stdlib.h> 35162852Sdes#include <string.h> 36162852Sdes 3776259Sgreen#include <openssl/crypto.h> 3876259Sgreen 39162852Sdes#include "xmalloc.h" 4060573Skris#include "ssh2.h" 4160573Skris#include "buffer.h" 4261209Skris#include "packet.h" 4360573Skris#include "compat.h" 4476259Sgreen#include "cipher.h" 45162852Sdes#include "key.h" 4660573Skris#include "kex.h" 4776259Sgreen#include "log.h" 4876259Sgreen#include "mac.h" 4976259Sgreen#include "match.h" 5076259Sgreen#include "dispatch.h" 5198675Sdes#include "monitor.h" 52204917Sdes#include "roaming.h" 5360573Skris 54162852Sdes#if OPENSSL_VERSION_NUMBER >= 0x00907000L 55162852Sdes# if defined(HAVE_EVP_SHA256) 56162852Sdes# define evp_ssh_sha256 EVP_sha256 57162852Sdes# else 58162852Sdesextern const EVP_MD *evp_ssh_sha256(void); 59162852Sdes# endif 60162852Sdes#endif 61162852Sdes 6292555Sdes/* prototype */ 6392555Sdesstatic void kex_kexinit_finish(Kex *); 6492555Sdesstatic void kex_choose_conf(Kex *); 6576259Sgreen 66255767Sdesstruct kexalg { 67255767Sdes char *name; 68255767Sdes int type; 69255767Sdes int ec_nid; 70255767Sdes const EVP_MD *(*mdfunc)(void); 71255767Sdes}; 72255767Sdesstatic const struct kexalg kexalgs[] = { 73255767Sdes { KEX_DH1, KEX_DH_GRP1_SHA1, 0, EVP_sha1 }, 74255767Sdes { KEX_DH14, KEX_DH_GRP14_SHA1, 0, EVP_sha1 }, 75255767Sdes { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, EVP_sha1 }, 76255767Sdes#ifdef HAVE_EVP_SHA256 77255767Sdes { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, EVP_sha256 }, 78255767Sdes#endif 79255767Sdes#ifdef OPENSSL_HAS_ECC 80255767Sdes { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, NID_X9_62_prime256v1, EVP_sha256 }, 81255767Sdes { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, EVP_sha384 }, 82255767Sdes { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, EVP_sha512 }, 83255767Sdes#endif 84255767Sdes { NULL, -1, -1, NULL}, 85255767Sdes}; 86255767Sdes 87255767Sdeschar * 88255767Sdeskex_alg_list(void) 89255767Sdes{ 90255767Sdes char *ret = NULL; 91255767Sdes size_t nlen, rlen = 0; 92255767Sdes const struct kexalg *k; 93255767Sdes 94255767Sdes for (k = kexalgs; k->name != NULL; k++) { 95255767Sdes if (ret != NULL) 96255767Sdes ret[rlen++] = '\n'; 97255767Sdes nlen = strlen(k->name); 98255767Sdes ret = xrealloc(ret, 1, rlen + nlen + 2); 99255767Sdes memcpy(ret + rlen, k->name, nlen + 1); 100255767Sdes rlen += nlen; 101255767Sdes } 102255767Sdes return ret; 103255767Sdes} 104255767Sdes 105255767Sdesstatic const struct kexalg * 106255767Sdeskex_alg_by_name(const char *name) 107255767Sdes{ 108255767Sdes const struct kexalg *k; 109255767Sdes 110255767Sdes for (k = kexalgs; k->name != NULL; k++) { 111255767Sdes if (strcmp(k->name, name) == 0) 112255767Sdes return k; 113255767Sdes } 114255767Sdes return NULL; 115255767Sdes} 116255767Sdes 117221420Sdes/* Validate KEX method name list */ 118221420Sdesint 119221420Sdeskex_names_valid(const char *names) 120221420Sdes{ 121221420Sdes char *s, *cp, *p; 122221420Sdes 123221420Sdes if (names == NULL || strcmp(names, "") == 0) 124221420Sdes return 0; 125221420Sdes s = cp = xstrdup(names); 126221420Sdes for ((p = strsep(&cp, ",")); p && *p != '\0'; 127221420Sdes (p = strsep(&cp, ","))) { 128255767Sdes if (kex_alg_by_name(p) == NULL) { 129221420Sdes error("Unsupported KEX algorithm \"%.100s\"", p); 130255767Sdes free(s); 131221420Sdes return 0; 132221420Sdes } 133221420Sdes } 134221420Sdes debug3("kex names ok: [%s]", names); 135255767Sdes free(s); 136221420Sdes return 1; 137221420Sdes} 138221420Sdes 139240075Sdes/* put algorithm proposal into buffer. */ 140224638Sbrooks#ifndef NONE_CIPHER_ENABLED 14192555Sdesstatic void 142224638Sbrooks#else 143224638Sbrooks/* Also used in sshconnect2.c. */ 144224638Sbrooksvoid 145224638Sbrooks#endif 14676259Sgreenkex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) 14760573Skris{ 148149749Sdes u_int i; 14976259Sgreen 15076259Sgreen buffer_clear(b); 15198675Sdes /* 15298675Sdes * add a dummy cookie, the cookie will be overwritten by 15398675Sdes * kex_send_kexinit(), each time a kexinit is set 15498675Sdes */ 15598675Sdes for (i = 0; i < KEX_COOKIE_LEN; i++) 15698675Sdes buffer_put_char(b, 0); 15760573Skris for (i = 0; i < PROPOSAL_MAX; i++) 15876259Sgreen buffer_put_cstring(b, proposal[i]); 15976259Sgreen buffer_put_char(b, 0); /* first_kex_packet_follows */ 16076259Sgreen buffer_put_int(b, 0); /* uint32 reserved */ 16160573Skris} 16260573Skris 16376259Sgreen/* parse buffer and return algorithm proposal */ 16492555Sdesstatic char ** 165113908Sdeskex_buf2prop(Buffer *raw, int *first_kex_follows) 16661209Skris{ 16776259Sgreen Buffer b; 168181111Sdes u_int i; 16976259Sgreen char **proposal; 17061209Skris 171162852Sdes proposal = xcalloc(PROPOSAL_MAX, sizeof(char *)); 17261209Skris 17376259Sgreen buffer_init(&b); 17476259Sgreen buffer_append(&b, buffer_ptr(raw), buffer_len(raw)); 17561209Skris /* skip cookie */ 17661209Skris for (i = 0; i < KEX_COOKIE_LEN; i++) 17776259Sgreen buffer_get_char(&b); 17861209Skris /* extract kex init proposal strings */ 17961209Skris for (i = 0; i < PROPOSAL_MAX; i++) { 180221420Sdes proposal[i] = buffer_get_cstring(&b,NULL); 18176259Sgreen debug2("kex_parse_kexinit: %s", proposal[i]); 18261209Skris } 18376259Sgreen /* first kex follows / reserved */ 18476259Sgreen i = buffer_get_char(&b); 185113908Sdes if (first_kex_follows != NULL) 186113908Sdes *first_kex_follows = i; 18776259Sgreen debug2("kex_parse_kexinit: first_kex_follows %d ", i); 18876259Sgreen i = buffer_get_int(&b); 189181111Sdes debug2("kex_parse_kexinit: reserved %u ", i); 19076259Sgreen buffer_free(&b); 19176259Sgreen return proposal; 19261209Skris} 19361209Skris 19492555Sdesstatic void 19576259Sgreenkex_prop_free(char **proposal) 19660573Skris{ 197149749Sdes u_int i; 19860573Skris 19976259Sgreen for (i = 0; i < PROPOSAL_MAX; i++) 200255767Sdes free(proposal[i]); 201255767Sdes free(proposal); 20260573Skris} 20360573Skris 204181111Sdes/* ARGSUSED */ 20592555Sdesstatic void 20692555Sdeskex_protocol_error(int type, u_int32_t seq, void *ctxt) 20760573Skris{ 20892555Sdes error("Hm, kex protocol error: type %d seq %u", type, seq); 20960573Skris} 21060573Skris 21192555Sdesstatic void 21292555Sdeskex_reset_dispatch(void) 21369587Sgreen{ 21492555Sdes dispatch_range(SSH2_MSG_TRANSPORT_MIN, 21592555Sdes SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); 21692555Sdes dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); 21769587Sgreen} 21869587Sgreen 21976259Sgreenvoid 22076259Sgreenkex_finish(Kex *kex) 22169587Sgreen{ 22292555Sdes kex_reset_dispatch(); 22369587Sgreen 22476259Sgreen packet_start(SSH2_MSG_NEWKEYS); 22576259Sgreen packet_send(); 22676259Sgreen /* packet_write_wait(); */ 22776259Sgreen debug("SSH2_MSG_NEWKEYS sent"); 22869587Sgreen 229113908Sdes debug("expecting SSH2_MSG_NEWKEYS"); 23092555Sdes packet_read_expect(SSH2_MSG_NEWKEYS); 23192555Sdes packet_check_eom(); 23276259Sgreen debug("SSH2_MSG_NEWKEYS received"); 23369587Sgreen 23476259Sgreen kex->done = 1; 23576259Sgreen buffer_clear(&kex->peer); 23676259Sgreen /* buffer_clear(&kex->my); */ 23776259Sgreen kex->flags &= ~KEX_INIT_SENT; 238255767Sdes free(kex->name); 23976259Sgreen kex->name = NULL; 24069587Sgreen} 24169587Sgreen 24260573Skrisvoid 24376259Sgreenkex_send_kexinit(Kex *kex) 24460573Skris{ 245137015Sdes u_int32_t rnd = 0; 24698675Sdes u_char *cookie; 247149749Sdes u_int i; 24898675Sdes 24976259Sgreen if (kex == NULL) { 25076259Sgreen error("kex_send_kexinit: no kex, cannot rekey"); 25176259Sgreen return; 25260573Skris } 25376259Sgreen if (kex->flags & KEX_INIT_SENT) { 25476259Sgreen debug("KEX_INIT_SENT"); 25576259Sgreen return; 25676259Sgreen } 25776259Sgreen kex->done = 0; 25898675Sdes 25998675Sdes /* generate a random cookie */ 26098675Sdes if (buffer_len(&kex->my) < KEX_COOKIE_LEN) 26198675Sdes fatal("kex_send_kexinit: kex proposal too short"); 26298675Sdes cookie = buffer_ptr(&kex->my); 26398675Sdes for (i = 0; i < KEX_COOKIE_LEN; i++) { 26498675Sdes if (i % 4 == 0) 265137015Sdes rnd = arc4random(); 266137015Sdes cookie[i] = rnd; 267137015Sdes rnd >>= 8; 26898675Sdes } 26976259Sgreen packet_start(SSH2_MSG_KEXINIT); 27076259Sgreen packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); 27176259Sgreen packet_send(); 27276259Sgreen debug("SSH2_MSG_KEXINIT sent"); 27376259Sgreen kex->flags |= KEX_INIT_SENT; 27460573Skris} 27560573Skris 276181111Sdes/* ARGSUSED */ 27776259Sgreenvoid 27892555Sdeskex_input_kexinit(int type, u_int32_t seq, void *ctxt) 27960573Skris{ 28076259Sgreen char *ptr; 281149749Sdes u_int i, dlen; 28276259Sgreen Kex *kex = (Kex *)ctxt; 28360573Skris 28476259Sgreen debug("SSH2_MSG_KEXINIT received"); 28576259Sgreen if (kex == NULL) 28676259Sgreen fatal("kex_input_kexinit: no kex, cannot rekey"); 28760573Skris 28876259Sgreen ptr = packet_get_raw(&dlen); 28976259Sgreen buffer_append(&kex->peer, ptr, dlen); 29060573Skris 29176259Sgreen /* discard packet */ 29276259Sgreen for (i = 0; i < KEX_COOKIE_LEN; i++) 29376259Sgreen packet_get_char(); 29476259Sgreen for (i = 0; i < PROPOSAL_MAX; i++) 295255767Sdes free(packet_get_string(NULL)); 296248619Sdes /* 297248619Sdes * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported 298248619Sdes * KEX method has the server move first, but a server might be using 299248619Sdes * a custom method or one that we otherwise don't support. We should 300248619Sdes * be prepared to remember first_kex_follows here so we can eat a 301248619Sdes * packet later. 302248619Sdes * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means 303248619Sdes * for cases where the server *doesn't* go first. I guess we should 304248619Sdes * ignore it when it is set for these cases, which is what we do now. 305248619Sdes */ 306248619Sdes (void) packet_get_char(); /* first_kex_follows */ 307248619Sdes (void) packet_get_int(); /* reserved */ 30892555Sdes packet_check_eom(); 30960573Skris 31076259Sgreen kex_kexinit_finish(kex); 31160573Skris} 31260573Skris 31376259SgreenKex * 31476259Sgreenkex_setup(char *proposal[PROPOSAL_MAX]) 31569587Sgreen{ 31676259Sgreen Kex *kex; 31769587Sgreen 318162852Sdes kex = xcalloc(1, sizeof(*kex)); 31976259Sgreen buffer_init(&kex->peer); 32076259Sgreen buffer_init(&kex->my); 32176259Sgreen kex_prop2buf(&kex->my, proposal); 32276259Sgreen kex->done = 0; 32369587Sgreen 32476259Sgreen kex_send_kexinit(kex); /* we start */ 32592555Sdes kex_reset_dispatch(); 32669587Sgreen 32776259Sgreen return kex; 32869587Sgreen} 32969587Sgreen 33092555Sdesstatic void 33176259Sgreenkex_kexinit_finish(Kex *kex) 33260573Skris{ 33376259Sgreen if (!(kex->flags & KEX_INIT_SENT)) 33476259Sgreen kex_send_kexinit(kex); 33560573Skris 33676259Sgreen kex_choose_conf(kex); 33760573Skris 338113908Sdes if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX && 339113908Sdes kex->kex[kex->kex_type] != NULL) { 340113908Sdes (kex->kex[kex->kex_type])(kex); 341113908Sdes } else { 34276259Sgreen fatal("Unsupported key exchange %d", kex->kex_type); 34360573Skris } 34460573Skris} 34560573Skris 34692555Sdesstatic void 34760573Skrischoose_enc(Enc *enc, char *client, char *server) 34860573Skris{ 34976259Sgreen char *name = match_list(client, server, NULL); 35060573Skris if (name == NULL) 351181111Sdes fatal("no matching cipher found: client %s server %s", 352181111Sdes client, server); 35392555Sdes if ((enc->cipher = cipher_by_name(name)) == NULL) 35469587Sgreen fatal("matching cipher is not supported: %s", name); 35560573Skris enc->name = name; 35660573Skris enc->enabled = 0; 35760573Skris enc->iv = NULL; 358248619Sdes enc->iv_len = cipher_ivlen(enc->cipher); 35960573Skris enc->key = NULL; 36092555Sdes enc->key_len = cipher_keylen(enc->cipher); 36192555Sdes enc->block_size = cipher_blocksize(enc->cipher); 36260573Skris} 363162852Sdes 36492555Sdesstatic void 36560573Skrischoose_mac(Mac *mac, char *client, char *server) 36660573Skris{ 36776259Sgreen char *name = match_list(client, server, NULL); 36860573Skris if (name == NULL) 369181111Sdes fatal("no matching mac found: client %s server %s", 370181111Sdes client, server); 371181111Sdes if (mac_setup(mac, name) < 0) 37260573Skris fatal("unsupported mac %s", name); 37376259Sgreen /* truncate the key */ 37476259Sgreen if (datafellows & SSH_BUG_HMAC) 37576259Sgreen mac->key_len = 16; 37660573Skris mac->name = name; 37760573Skris mac->key = NULL; 37860573Skris mac->enabled = 0; 37960573Skris} 380162852Sdes 38192555Sdesstatic void 38260573Skrischoose_comp(Comp *comp, char *client, char *server) 38360573Skris{ 38476259Sgreen char *name = match_list(client, server, NULL); 38560573Skris if (name == NULL) 38660573Skris fatal("no matching comp found: client %s server %s", client, server); 387149749Sdes if (strcmp(name, "zlib@openssh.com") == 0) { 388149749Sdes comp->type = COMP_DELAYED; 389149749Sdes } else if (strcmp(name, "zlib") == 0) { 390149749Sdes comp->type = COMP_ZLIB; 39160573Skris } else if (strcmp(name, "none") == 0) { 392149749Sdes comp->type = COMP_NONE; 39360573Skris } else { 39460573Skris fatal("unsupported comp %s", name); 39560573Skris } 39660573Skris comp->name = name; 39760573Skris} 398162852Sdes 39992555Sdesstatic void 40060573Skrischoose_kex(Kex *k, char *client, char *server) 40160573Skris{ 402255767Sdes const struct kexalg *kexalg; 403255767Sdes 40476259Sgreen k->name = match_list(client, server, NULL); 40560573Skris if (k->name == NULL) 406181111Sdes fatal("Unable to negotiate a key exchange method"); 407255767Sdes if ((kexalg = kex_alg_by_name(k->name)) == NULL) 408255767Sdes fatal("unsupported kex alg %s", k->name); 409255767Sdes k->kex_type = kexalg->type; 410255767Sdes k->evp_md = kexalg->mdfunc(); 411255767Sdes k->ec_nid = kexalg->ec_nid; 41260573Skris} 413157016Sdes 41492555Sdesstatic void 41560573Skrischoose_hostkeyalg(Kex *k, char *client, char *server) 41660573Skris{ 41776259Sgreen char *hostkeyalg = match_list(client, server, NULL); 41876259Sgreen if (hostkeyalg == NULL) 41960573Skris fatal("no hostkey alg"); 42076259Sgreen k->hostkey_type = key_type_from_name(hostkeyalg); 42176259Sgreen if (k->hostkey_type == KEY_UNSPEC) 42276259Sgreen fatal("bad hostkey alg '%s'", hostkeyalg); 423255767Sdes free(hostkeyalg); 42460573Skris} 42560573Skris 426126274Sdesstatic int 427113908Sdesproposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX]) 428113908Sdes{ 429113908Sdes static int check[] = { 430113908Sdes PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1 431113908Sdes }; 432113908Sdes int *idx; 433113908Sdes char *p; 434113908Sdes 435113908Sdes for (idx = &check[0]; *idx != -1; idx++) { 436113908Sdes if ((p = strchr(my[*idx], ',')) != NULL) 437113908Sdes *p = '\0'; 438113908Sdes if ((p = strchr(peer[*idx], ',')) != NULL) 439113908Sdes *p = '\0'; 440113908Sdes if (strcmp(my[*idx], peer[*idx]) != 0) { 441113908Sdes debug2("proposal mismatch: my %s peer %s", 442113908Sdes my[*idx], peer[*idx]); 443113908Sdes return (0); 444113908Sdes } 445113908Sdes } 446113908Sdes debug2("proposals match"); 447113908Sdes return (1); 448113908Sdes} 449113908Sdes 45092555Sdesstatic void 45176259Sgreenkex_choose_conf(Kex *kex) 45260573Skris{ 45376259Sgreen Newkeys *newkeys; 45476259Sgreen char **my, **peer; 45576259Sgreen char **cprop, **sprop; 45676259Sgreen int nenc, nmac, ncomp; 457248619Sdes u_int mode, ctos, need, authlen; 458113908Sdes int first_kex_follows, type; 459224638Sbrooks#ifdef NONE_CIPHER_ENABLED 460224638Sbrooks int auth_flag; 461224638Sbrooks#endif 46260573Skris 463113908Sdes my = kex_buf2prop(&kex->my, NULL); 464113908Sdes peer = kex_buf2prop(&kex->peer, &first_kex_follows); 46560573Skris 46676259Sgreen if (kex->server) { 46776259Sgreen cprop=peer; 46876259Sgreen sprop=my; 46976259Sgreen } else { 47076259Sgreen cprop=my; 47176259Sgreen sprop=peer; 47276259Sgreen } 47376259Sgreen 474204917Sdes /* Check whether server offers roaming */ 475204917Sdes if (!kex->server) { 476204917Sdes char *roaming; 477204917Sdes roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL); 478204917Sdes if (roaming) { 479204917Sdes kex->roaming = 1; 480255767Sdes free(roaming); 481204917Sdes } 482204917Sdes } 483204917Sdes 48476259Sgreen /* Algorithm Negotiation */ 485224638Sbrooks#ifdef NONE_CIPHER_ENABLED 486224638Sbrooks auth_flag = packet_get_authentication_state(); 487224638Sbrooks debug ("AUTH STATE is %d", auth_flag); 488224638Sbrooks#endif 48960573Skris for (mode = 0; mode < MODE_MAX; mode++) { 490162852Sdes newkeys = xcalloc(1, sizeof(*newkeys)); 49176259Sgreen kex->newkeys[mode] = newkeys; 492181111Sdes ctos = (!kex->server && mode == MODE_OUT) || 493181111Sdes (kex->server && mode == MODE_IN); 49460573Skris nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; 49560573Skris nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; 49660573Skris ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; 497248619Sdes choose_enc(&newkeys->enc, cprop[nenc], sprop[nenc]); 498248619Sdes /* ignore mac for authenticated encryption */ 499248619Sdes authlen = cipher_authlen(newkeys->enc.cipher); 500248619Sdes if (authlen == 0) 501248619Sdes choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]); 50276259Sgreen choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); 503224638Sbrooks#ifdef NONE_CIPHER_ENABLED 504224638Sbrooks debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name); 505224638Sbrooks if (strcmp(newkeys->enc.name, "none") == 0) { 506231584Sed debug("Requesting NONE. Authflag is %d", auth_flag); 507224638Sbrooks if (auth_flag == 1) 508224638Sbrooks debug("None requested post authentication."); 509224638Sbrooks else 510224638Sbrooks fatal("Pre-authentication none cipher requests " 511224638Sbrooks "are not allowed."); 512231584Sed } 513224638Sbrooks#endif 51460573Skris debug("kex: %s %s %s %s", 51560573Skris ctos ? "client->server" : "server->client", 51676259Sgreen newkeys->enc.name, 517248619Sdes authlen == 0 ? newkeys->mac.name : "<implicit>", 51876259Sgreen newkeys->comp.name); 51960573Skris } 52076259Sgreen choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); 52176259Sgreen choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], 52260573Skris sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); 52360573Skris need = 0; 52460573Skris for (mode = 0; mode < MODE_MAX; mode++) { 52576259Sgreen newkeys = kex->newkeys[mode]; 52692555Sdes if (need < newkeys->enc.key_len) 52792555Sdes need = newkeys->enc.key_len; 52892555Sdes if (need < newkeys->enc.block_size) 52992555Sdes need = newkeys->enc.block_size; 530248619Sdes if (need < newkeys->enc.iv_len) 531248619Sdes need = newkeys->enc.iv_len; 53276259Sgreen if (need < newkeys->mac.key_len) 53376259Sgreen need = newkeys->mac.key_len; 53460573Skris } 53561209Skris /* XXX need runden? */ 53676259Sgreen kex->we_need = need; 53776259Sgreen 538113908Sdes /* ignore the next message if the proposals do not match */ 539126274Sdes if (first_kex_follows && !proposals_match(my, peer) && 540149749Sdes !(datafellows & SSH_BUG_FIRSTKEX)) { 541113908Sdes type = packet_read(); 542113908Sdes debug2("skipping next packet (type %u)", type); 543113908Sdes } 544113908Sdes 54576259Sgreen kex_prop_free(my); 54676259Sgreen kex_prop_free(peer); 54760573Skris} 54860573Skris 54992555Sdesstatic u_char * 550157016Sdesderive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, 551157016Sdes BIGNUM *shared_secret) 55260573Skris{ 55376259Sgreen Buffer b; 55476259Sgreen EVP_MD_CTX md; 55576259Sgreen char c = id; 556149749Sdes u_int have; 557157016Sdes int mdsz; 558149749Sdes u_char *digest; 55960573Skris 560157016Sdes if ((mdsz = EVP_MD_size(kex->evp_md)) <= 0) 561157016Sdes fatal("bad kex md size %d", mdsz); 562162852Sdes digest = xmalloc(roundup(need, mdsz)); 563149749Sdes 56476259Sgreen buffer_init(&b); 56576259Sgreen buffer_put_bignum2(&b, shared_secret); 56676259Sgreen 56776259Sgreen /* K1 = HASH(K || H || "A" || session_id) */ 568157016Sdes EVP_DigestInit(&md, kex->evp_md); 56992555Sdes if (!(datafellows & SSH_BUG_DERIVEKEY)) 57092555Sdes EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); 571157016Sdes EVP_DigestUpdate(&md, hash, hashlen); 57276259Sgreen EVP_DigestUpdate(&md, &c, 1); 57376259Sgreen EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); 57476259Sgreen EVP_DigestFinal(&md, digest, NULL); 57576259Sgreen 57676259Sgreen /* 57776259Sgreen * expand key: 57876259Sgreen * Kn = HASH(K || H || K1 || K2 || ... || Kn-1) 57976259Sgreen * Key = K1 || K2 || ... || Kn 58076259Sgreen */ 58176259Sgreen for (have = mdsz; need > have; have += mdsz) { 582157016Sdes EVP_DigestInit(&md, kex->evp_md); 58392555Sdes if (!(datafellows & SSH_BUG_DERIVEKEY)) 58492555Sdes EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); 585157016Sdes EVP_DigestUpdate(&md, hash, hashlen); 58676259Sgreen EVP_DigestUpdate(&md, digest, have); 58776259Sgreen EVP_DigestFinal(&md, digest + have, NULL); 58876259Sgreen } 58976259Sgreen buffer_free(&b); 59076259Sgreen#ifdef DEBUG_KEX 59176259Sgreen fprintf(stderr, "key '%c'== ", c); 59276259Sgreen dump_digest("key", digest, need); 59376259Sgreen#endif 59476259Sgreen return digest; 59576259Sgreen} 59676259Sgreen 59776259SgreenNewkeys *current_keys[MODE_MAX]; 59876259Sgreen 59976259Sgreen#define NKEYS 6 60076259Sgreenvoid 601157016Sdeskex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, BIGNUM *shared_secret) 60276259Sgreen{ 60376259Sgreen u_char *keys[NKEYS]; 604149749Sdes u_int i, mode, ctos; 60576259Sgreen 606157016Sdes for (i = 0; i < NKEYS; i++) { 607157016Sdes keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, hashlen, 608157016Sdes shared_secret); 609157016Sdes } 61060573Skris 611113908Sdes debug2("kex_derive_keys"); 61260573Skris for (mode = 0; mode < MODE_MAX; mode++) { 61376259Sgreen current_keys[mode] = kex->newkeys[mode]; 61476259Sgreen kex->newkeys[mode] = NULL; 615162852Sdes ctos = (!kex->server && mode == MODE_OUT) || 616162852Sdes (kex->server && mode == MODE_IN); 61776259Sgreen current_keys[mode]->enc.iv = keys[ctos ? 0 : 1]; 61876259Sgreen current_keys[mode]->enc.key = keys[ctos ? 2 : 3]; 61976259Sgreen current_keys[mode]->mac.key = keys[ctos ? 4 : 5]; 62060573Skris } 62160573Skris} 62276259Sgreen 62376259SgreenNewkeys * 62476259Sgreenkex_get_newkeys(int mode) 62576259Sgreen{ 62676259Sgreen Newkeys *ret; 62776259Sgreen 62876259Sgreen ret = current_keys[mode]; 62976259Sgreen current_keys[mode] = NULL; 63076259Sgreen return ret; 63176259Sgreen} 63276259Sgreen 633137015Sdesvoid 634137015Sdesderive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, 635137015Sdes u_int8_t cookie[8], u_int8_t id[16]) 636137015Sdes{ 637137015Sdes const EVP_MD *evp_md = EVP_md5(); 638137015Sdes EVP_MD_CTX md; 639137015Sdes u_int8_t nbuf[2048], obuf[EVP_MAX_MD_SIZE]; 640137015Sdes int len; 641137015Sdes 642137015Sdes EVP_DigestInit(&md, evp_md); 643137015Sdes 644137015Sdes len = BN_num_bytes(host_modulus); 645149749Sdes if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) 646137015Sdes fatal("%s: bad host modulus (len %d)", __func__, len); 647137015Sdes BN_bn2bin(host_modulus, nbuf); 648137015Sdes EVP_DigestUpdate(&md, nbuf, len); 649137015Sdes 650137015Sdes len = BN_num_bytes(server_modulus); 651149749Sdes if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) 652137015Sdes fatal("%s: bad server modulus (len %d)", __func__, len); 653137015Sdes BN_bn2bin(server_modulus, nbuf); 654137015Sdes EVP_DigestUpdate(&md, nbuf, len); 655137015Sdes 656137015Sdes EVP_DigestUpdate(&md, cookie, 8); 657137015Sdes 658137015Sdes EVP_DigestFinal(&md, obuf, NULL); 659137015Sdes memcpy(id, obuf, 16); 660137015Sdes 661137015Sdes memset(nbuf, 0, sizeof(nbuf)); 662137015Sdes memset(obuf, 0, sizeof(obuf)); 663137015Sdes memset(&md, 0, sizeof(md)); 664137015Sdes} 665137015Sdes 666221420Sdes#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) 66776259Sgreenvoid 66876259Sgreendump_digest(char *msg, u_char *digest, int len) 66976259Sgreen{ 670221420Sdes int i; 67176259Sgreen 67276259Sgreen fprintf(stderr, "%s\n", msg); 673181111Sdes for (i = 0; i < len; i++) { 67476259Sgreen fprintf(stderr, "%02x", digest[i]); 67576259Sgreen if (i%32 == 31) 67676259Sgreen fprintf(stderr, "\n"); 67776259Sgreen else if (i%8 == 7) 67876259Sgreen fprintf(stderr, " "); 67976259Sgreen } 68076259Sgreen fprintf(stderr, "\n"); 68176259Sgreen} 68276259Sgreen#endif 683