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