Home | History | Annotate | Download | only in dropbear
      1 /*
      2  * Dropbear SSH
      3  *
      4  * Copyright (c) 2002-2004 Matt Johnston
      5  * Portions Copyright (c) 2004 by Mihnea Stoenescu
      6  * All rights reserved.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a copy
      9  * of this software and associated documentation files (the "Software"), to deal
     10  * in the Software without restriction, including without limitation the rights
     11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     12  * copies of the Software, and to permit persons to whom the Software is
     13  * furnished to do so, subject to the following conditions:
     14  *
     15  * The above copyright notice and this permission notice shall be included in
     16  * all copies or substantial portions of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     24  * SOFTWARE. */
     25 
     26 #include "includes.h"
     27 #include "dbutil.h"
     28 #include "algo.h"
     29 #include "buffer.h"
     30 #include "session.h"
     31 #include "kex.h"
     32 #include "ssh.h"
     33 #include "packet.h"
     34 #include "bignum.h"
     35 #include "random.h"
     36 
     37 /* diffie-hellman-group1-sha1 value for p */
     38 static const unsigned char dh_p_val[] = {
     39 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
     40     0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
     41 	0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
     42 	0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
     43 	0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
     44 	0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
     45 	0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
     46 	0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
     47 	0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
     48 	0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
     49 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
     50 #define DH_P_LEN sizeof(dh_p_val)
     51 
     52 static const int DH_G_VAL = 2;
     53 
     54 static void kexinitialise();
     55 void gen_new_keys();
     56 #ifndef DISABLE_ZLIB
     57 static void gen_new_zstreams();
     58 #endif
     59 static void read_kex_algos();
     60 /* helper function for gen_new_keys */
     61 static void hashkeys(unsigned char *out, int outlen,
     62 		const hash_state * hs, unsigned const char X);
     63 
     64 
     65 /* Send our list of algorithms we can use */
     66 void send_msg_kexinit() {
     67 
     68 	CHECKCLEARTOWRITE();
     69 	buf_putbyte(ses.writepayload, SSH_MSG_KEXINIT);
     70 
     71 	/* cookie */
     72 	genrandom(buf_getwriteptr(ses.writepayload, 16), 16);
     73 	buf_incrwritepos(ses.writepayload, 16);
     74 
     75 	/* kex algos */
     76 	buf_put_algolist(ses.writepayload, sshkex);
     77 
     78 	/* server_host_key_algorithms */
     79 	buf_put_algolist(ses.writepayload, sshhostkey);
     80 
     81 	/* encryption_algorithms_client_to_server */
     82 	buf_put_algolist(ses.writepayload, sshciphers);
     83 
     84 	/* encryption_algorithms_server_to_client */
     85 	buf_put_algolist(ses.writepayload, sshciphers);
     86 
     87 	/* mac_algorithms_client_to_server */
     88 	buf_put_algolist(ses.writepayload, sshhashes);
     89 
     90 	/* mac_algorithms_server_to_client */
     91 	buf_put_algolist(ses.writepayload, sshhashes);
     92 
     93 	/* compression_algorithms_client_to_server */
     94 	buf_put_algolist(ses.writepayload, sshcompress);
     95 
     96 	/* compression_algorithms_server_to_client */
     97 	buf_put_algolist(ses.writepayload, sshcompress);
     98 
     99 	/* languages_client_to_server */
    100 	buf_putstring(ses.writepayload, "", 0);
    101 
    102 	/* languages_server_to_client */
    103 	buf_putstring(ses.writepayload, "", 0);
    104 
    105 	/* first_kex_packet_follows - unimplemented for now */
    106 	buf_putbyte(ses.writepayload, 0x00);
    107 
    108 	/* reserved unit32 */
    109 	buf_putint(ses.writepayload, 0);
    110 
    111 	/* set up transmitted kex packet buffer for hashing.
    112 	 * This is freed after the end of the kex */
    113 	ses.transkexinit = buf_newcopy(ses.writepayload);
    114 
    115 	encrypt_packet();
    116 	ses.dataallowed = 0; /* don't send other packets during kex */
    117 
    118 	TRACE(("DATAALLOWED=0"))
    119 	TRACE(("-> KEXINIT"))
    120 	ses.kexstate.sentkexinit = 1;
    121 }
    122 
    123 /* *** NOTE regarding (send|recv)_msg_newkeys ***
    124  * Changed by mihnea from the original kex.c to set dataallowed after a
    125  * completed key exchange, no matter the order in which it was performed.
    126  * This enables client mode without affecting server functionality.
    127  */
    128 
    129 /* Bring new keys into use after a key exchange, and let the client know*/
    130 void send_msg_newkeys() {
    131 
    132 	TRACE(("enter send_msg_newkeys"))
    133 
    134 	/* generate the kexinit request */
    135 	CHECKCLEARTOWRITE();
    136 	buf_putbyte(ses.writepayload, SSH_MSG_NEWKEYS);
    137 	encrypt_packet();
    138 
    139 
    140 	/* set up our state */
    141 	if (ses.kexstate.recvnewkeys) {
    142 		TRACE(("while RECVNEWKEYS=1"))
    143 		gen_new_keys();
    144 		kexinitialise(); /* we've finished with this kex */
    145 		TRACE((" -> DATAALLOWED=1"))
    146 		ses.dataallowed = 1; /* we can send other packets again now */
    147 		ses.kexstate.donefirstkex = 1;
    148 	} else {
    149 		ses.kexstate.sentnewkeys = 1;
    150 		TRACE(("SENTNEWKEYS=1"))
    151 	}
    152 
    153 	TRACE(("-> MSG_NEWKEYS"))
    154 	TRACE(("leave send_msg_newkeys"))
    155 }
    156 
    157 /* Bring the new keys into use after a key exchange */
    158 void recv_msg_newkeys() {
    159 
    160 	TRACE(("<- MSG_NEWKEYS"))
    161 	TRACE(("enter recv_msg_newkeys"))
    162 
    163 	/* simply check if we've sent SSH_MSG_NEWKEYS, and if so,
    164 	 * switch to the new keys */
    165 	if (ses.kexstate.sentnewkeys) {
    166 		TRACE(("while SENTNEWKEYS=1"))
    167 		gen_new_keys();
    168 		kexinitialise(); /* we've finished with this kex */
    169 	    TRACE((" -> DATAALLOWED=1"))
    170 	    ses.dataallowed = 1; /* we can send other packets again now */
    171 		ses.kexstate.donefirstkex = 1;
    172 	} else {
    173 		TRACE(("RECVNEWKEYS=1"))
    174 		ses.kexstate.recvnewkeys = 1;
    175 	}
    176 
    177 	TRACE(("leave recv_msg_newkeys"))
    178 }
    179 
    180 
    181 /* Set up the kex for the first time */
    182 void kexfirstinitialise() {
    183 
    184 	ses.kexstate.donefirstkex = 0;
    185 	kexinitialise();
    186 }
    187 
    188 /* Reset the kex state, ready for a new negotiation */
    189 static void kexinitialise() {
    190 
    191 	struct timeval tv;
    192 
    193 	TRACE(("kexinitialise()"))
    194 
    195 	/* sent/recv'd MSG_KEXINIT */
    196 	ses.kexstate.sentkexinit = 0;
    197 	ses.kexstate.recvkexinit = 0;
    198 
    199 	/* sent/recv'd MSG_NEWKEYS */
    200 	ses.kexstate.recvnewkeys = 0;
    201 	ses.kexstate.sentnewkeys = 0;
    202 
    203 	/* first_packet_follows */
    204 	ses.kexstate.firstfollows = 0;
    205 
    206 	ses.kexstate.datatrans = 0;
    207 	ses.kexstate.datarecv = 0;
    208 
    209 	if (gettimeofday(&tv, 0) < 0) {
    210 		dropbear_exit("Error getting time");
    211 	}
    212 	ses.kexstate.lastkextime = tv.tv_sec;
    213 
    214 }
    215 
    216 /* Helper function for gen_new_keys, creates a hash. It makes a copy of the
    217  * already initialised hash_state hs, which should already have processed
    218  * the dh_K and hash, since these are common. X is the letter 'A', 'B' etc.
    219  * out must have at least min(SHA1_HASH_SIZE, outlen) bytes allocated.
    220  * The output will only be expanded once, as we are assured that
    221  * outlen <= 2*SHA1_HASH_SIZE for all known hashes.
    222  *
    223  * See Section 7.2 of rfc4253 (ssh transport) for details */
    224 static void hashkeys(unsigned char *out, int outlen,
    225 		const hash_state * hs, const unsigned char X) {
    226 
    227 	hash_state hs2;
    228 	unsigned char k2[SHA1_HASH_SIZE]; /* used to extending */
    229 
    230 	memcpy(&hs2, hs, sizeof(hash_state));
    231 	sha1_process(&hs2, &X, 1);
    232 	sha1_process(&hs2, ses.session_id, SHA1_HASH_SIZE);
    233 	sha1_done(&hs2, out);
    234 	if (SHA1_HASH_SIZE < outlen) {
    235 		/* need to extend */
    236 		memcpy(&hs2, hs, sizeof(hash_state));
    237 		sha1_process(&hs2, out, SHA1_HASH_SIZE);
    238 		sha1_done(&hs2, k2);
    239 		memcpy(&out[SHA1_HASH_SIZE], k2, outlen - SHA1_HASH_SIZE);
    240 	}
    241 }
    242 
    243 /* Generate the actual encryption/integrity keys, using the results of the
    244  * key exchange, as specified in section 5.2 of the IETF secsh-transport
    245  * draft. This occurs after the DH key-exchange.
    246  *
    247  * ses.newkeys is the new set of keys which are generated, these are only
    248  * taken into use after both sides have sent a newkeys message */
    249 
    250 /* Originally from kex.c, generalized for cli/svr mode --mihnea */
    251 void gen_new_keys() {
    252 
    253 	unsigned char C2S_IV[MAX_IV_LEN];
    254 	unsigned char C2S_key[MAX_KEY_LEN];
    255 	unsigned char S2C_IV[MAX_IV_LEN];
    256 	unsigned char S2C_key[MAX_KEY_LEN];
    257 	/* unsigned char key[MAX_KEY_LEN]; */
    258 	unsigned char *trans_IV, *trans_key, *recv_IV, *recv_key;
    259 
    260 	hash_state hs;
    261 	unsigned int C2S_keysize, S2C_keysize;
    262 	char mactransletter, macrecvletter; /* Client or server specific */
    263 	int recv_cipher = 0, trans_cipher = 0;
    264 
    265 	TRACE(("enter gen_new_keys"))
    266 	/* the dh_K and hash are the start of all hashes, we make use of that */
    267 
    268 	sha1_init(&hs);
    269 	sha1_process_mp(&hs, ses.dh_K);
    270 	mp_clear(ses.dh_K);
    271 	m_free(ses.dh_K);
    272 	sha1_process(&hs, ses.hash, SHA1_HASH_SIZE);
    273 	m_burn(ses.hash, SHA1_HASH_SIZE);
    274 
    275 	if (IS_DROPBEAR_CLIENT) {
    276 	    trans_IV	= C2S_IV;
    277 	    recv_IV		= S2C_IV;
    278 	    trans_key	= C2S_key;
    279 	    recv_key	= S2C_key;
    280 	    C2S_keysize = ses.newkeys->trans_algo_crypt->keysize;
    281 	    S2C_keysize = ses.newkeys->recv_algo_crypt->keysize;
    282 		mactransletter = 'E';
    283 		macrecvletter = 'F';
    284 	} else {
    285 	    trans_IV	= S2C_IV;
    286 	    recv_IV		= C2S_IV;
    287 	    trans_key	= S2C_key;
    288 	    recv_key	= C2S_key;
    289 	    C2S_keysize = ses.newkeys->recv_algo_crypt->keysize;
    290 	    S2C_keysize = ses.newkeys->trans_algo_crypt->keysize;
    291 		mactransletter = 'F';
    292 		macrecvletter = 'E';
    293 	}
    294 
    295 	hashkeys(C2S_IV, SHA1_HASH_SIZE, &hs, 'A');
    296 	hashkeys(S2C_IV, SHA1_HASH_SIZE, &hs, 'B');
    297 	hashkeys(C2S_key, C2S_keysize, &hs, 'C');
    298 	hashkeys(S2C_key, S2C_keysize, &hs, 'D');
    299 
    300 	recv_cipher = find_cipher(ses.newkeys->recv_algo_crypt->cipherdesc->name);
    301 	if (recv_cipher < 0)
    302 	    dropbear_exit("crypto error");
    303 
    304 	if (cbc_start(recv_cipher, recv_IV, recv_key,
    305 			ses.newkeys->recv_algo_crypt->keysize, 0,
    306 			&ses.newkeys->recv_symmetric_struct) != CRYPT_OK) {
    307 		dropbear_exit("crypto error");
    308 	}
    309 	trans_cipher = find_cipher(ses.newkeys->trans_algo_crypt->cipherdesc->name);
    310 	if (trans_cipher < 0)
    311 	    dropbear_exit("crypto error");
    312 
    313 	if (cbc_start(trans_cipher, trans_IV, trans_key,
    314 			ses.newkeys->trans_algo_crypt->keysize, 0,
    315 			&ses.newkeys->trans_symmetric_struct) != CRYPT_OK) {
    316 		dropbear_exit("crypto error");
    317 	}
    318 
    319 	/* MAC keys */
    320 	hashkeys(ses.newkeys->transmackey,
    321 			ses.newkeys->trans_algo_mac->keysize, &hs, mactransletter);
    322 	hashkeys(ses.newkeys->recvmackey,
    323 			ses.newkeys->recv_algo_mac->keysize, &hs, macrecvletter);
    324 
    325 #ifndef DISABLE_ZLIB
    326 	gen_new_zstreams();
    327 #endif
    328 
    329 	/* Switch over to the new keys */
    330 	m_burn(ses.keys, sizeof(struct key_context));
    331 	m_free(ses.keys);
    332 	ses.keys = ses.newkeys;
    333 	ses.newkeys = NULL;
    334 
    335 	TRACE(("leave gen_new_keys"))
    336 }
    337 
    338 #ifndef DISABLE_ZLIB
    339 /* Set up new zlib compression streams, close the old ones. Only
    340  * called from gen_new_keys() */
    341 static void gen_new_zstreams() {
    342 
    343 	/* create new zstreams */
    344 	if (ses.newkeys->recv_algo_comp == DROPBEAR_COMP_ZLIB) {
    345 		ses.newkeys->recv_zstream = (z_streamp)m_malloc(sizeof(z_stream));
    346 		ses.newkeys->recv_zstream->zalloc = Z_NULL;
    347 		ses.newkeys->recv_zstream->zfree = Z_NULL;
    348 
    349 		if (inflateInit(ses.newkeys->recv_zstream) != Z_OK) {
    350 			dropbear_exit("zlib error");
    351 		}
    352 	} else {
    353 		ses.newkeys->recv_zstream = NULL;
    354 	}
    355 
    356 	if (ses.newkeys->trans_algo_comp == DROPBEAR_COMP_ZLIB) {
    357 		ses.newkeys->trans_zstream = (z_streamp)m_malloc(sizeof(z_stream));
    358 		ses.newkeys->trans_zstream->zalloc = Z_NULL;
    359 		ses.newkeys->trans_zstream->zfree = Z_NULL;
    360 
    361 		if (deflateInit(ses.newkeys->trans_zstream, Z_DEFAULT_COMPRESSION)
    362 				!= Z_OK) {
    363 			dropbear_exit("zlib error");
    364 		}
    365 	} else {
    366 		ses.newkeys->trans_zstream = NULL;
    367 	}
    368 
    369 	/* clean up old keys */
    370 	if (ses.keys->recv_zstream != NULL) {
    371 		if (inflateEnd(ses.keys->recv_zstream) == Z_STREAM_ERROR) {
    372 			/* Z_DATA_ERROR is ok, just means that stream isn't ended */
    373 			dropbear_exit("crypto error");
    374 		}
    375 		m_free(ses.keys->recv_zstream);
    376 	}
    377 	if (ses.keys->trans_zstream != NULL) {
    378 		if (deflateEnd(ses.keys->trans_zstream) == Z_STREAM_ERROR) {
    379 			/* Z_DATA_ERROR is ok, just means that stream isn't ended */
    380 			dropbear_exit("crypto error");
    381 		}
    382 		m_free(ses.keys->trans_zstream);
    383 	}
    384 }
    385 #endif
    386 
    387 
    388 /* Executed upon receiving a kexinit message from the client to initiate
    389  * key exchange. If we haven't already done so, we send the list of our
    390  * preferred algorithms. The client's requested algorithms are processed,
    391  * and we calculate the first portion of the key-exchange-hash for used
    392  * later in the key exchange. No response is sent, as the client should
    393  * initiate the diffie-hellman key exchange */
    394 
    395 /* Originally from kex.c, generalized for cli/svr mode --mihnea  */
    396 /* Belongs in common_kex.c where it should be moved after review */
    397 void recv_msg_kexinit() {
    398 
    399 	unsigned int kexhashbuf_len = 0;
    400 	unsigned int remote_ident_len = 0;
    401 	unsigned int local_ident_len = 0;
    402 
    403 	TRACE(("<- KEXINIT"))
    404 	TRACE(("enter recv_msg_kexinit"))
    405 
    406 	if (!ses.kexstate.sentkexinit) {
    407 		/* we need to send a kex packet */
    408 		send_msg_kexinit();
    409 		TRACE(("continue recv_msg_kexinit: sent kexinit"))
    410 	}
    411 
    412 	/* start the kex hash */
    413 	local_ident_len = strlen(LOCAL_IDENT);
    414 	remote_ident_len = strlen((char*)ses.remoteident);
    415 
    416 	kexhashbuf_len = local_ident_len + remote_ident_len
    417 		+ ses.transkexinit->len + ses.payload->len
    418 		+ KEXHASHBUF_MAX_INTS;
    419 
    420 	ses.kexhashbuf = buf_new(kexhashbuf_len);
    421 
    422 	if (IS_DROPBEAR_CLIENT) {
    423 
    424 		/* read the peer's choice of algos */
    425 		read_kex_algos();
    426 
    427 		/* V_C, the client's version string (CR and NL excluded) */
    428 	    buf_putstring(ses.kexhashbuf,
    429 			(unsigned char*)LOCAL_IDENT, local_ident_len);
    430 		/* V_S, the server's version string (CR and NL excluded) */
    431 	    buf_putstring(ses.kexhashbuf, ses.remoteident, remote_ident_len);
    432 
    433 		/* I_C, the payload of the client's SSH_MSG_KEXINIT */
    434 	    buf_putstring(ses.kexhashbuf,
    435 			ses.transkexinit->data, ses.transkexinit->len);
    436 		/* I_S, the payload of the server's SSH_MSG_KEXINIT */
    437 	    buf_setpos(ses.payload, 0);
    438 	    buf_putstring(ses.kexhashbuf, ses.payload->data, ses.payload->len);
    439 
    440 	} else {
    441 		/* SERVER */
    442 
    443 		/* read the peer's choice of algos */
    444 		read_kex_algos();
    445 		/* V_C, the client's version string (CR and NL excluded) */
    446 	    buf_putstring(ses.kexhashbuf, ses.remoteident, remote_ident_len);
    447 		/* V_S, the server's version string (CR and NL excluded) */
    448 	    buf_putstring(ses.kexhashbuf,
    449 				(unsigned char*)LOCAL_IDENT, local_ident_len);
    450 
    451 		/* I_C, the payload of the client's SSH_MSG_KEXINIT */
    452 	    buf_setpos(ses.payload, 0);
    453 	    buf_putstring(ses.kexhashbuf, ses.payload->data, ses.payload->len);
    454 
    455 		/* I_S, the payload of the server's SSH_MSG_KEXINIT */
    456 	    buf_putstring(ses.kexhashbuf,
    457 			ses.transkexinit->data, ses.transkexinit->len);
    458 
    459 		ses.requirenext = SSH_MSG_KEXDH_INIT;
    460 	}
    461 
    462 	buf_free(ses.transkexinit);
    463 	ses.transkexinit = NULL;
    464 	/* the rest of ses.kexhashbuf will be done after DH exchange */
    465 
    466 	ses.kexstate.recvkexinit = 1;
    467 
    468 	TRACE(("leave recv_msg_kexinit"))
    469 }
    470 
    471 /* Initialises and generate one side of the diffie-hellman key exchange values.
    472  * See the ietf-secsh-transport draft, section 6, for details */
    473 /* dh_pub and dh_priv MUST be already initialised */
    474 void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) {
    475 
    476 	DEF_MP_INT(dh_p);
    477 	DEF_MP_INT(dh_q);
    478 	DEF_MP_INT(dh_g);
    479 
    480 	TRACE(("enter send_msg_kexdh_reply"))
    481 
    482 	m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL);
    483 
    484 	/* read the prime and generator*/
    485 	bytes_to_mp(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN);
    486 
    487 	if (mp_set_int(&dh_g, DH_G_VAL) != MP_OKAY) {
    488 		dropbear_exit("Diffie-Hellman error");
    489 	}
    490 
    491 	/* calculate q = (p-1)/2 */
    492 	/* dh_priv is just a temp var here */
    493 	if (mp_sub_d(&dh_p, 1, dh_priv) != MP_OKAY) {
    494 		dropbear_exit("Diffie-Hellman error");
    495 	}
    496 	if (mp_div_2(dh_priv, &dh_q) != MP_OKAY) {
    497 		dropbear_exit("Diffie-Hellman error");
    498 	}
    499 
    500 	/* Generate a private portion 0 < dh_priv < dh_q */
    501 	gen_random_mpint(&dh_q, dh_priv);
    502 
    503 	/* f = g^y mod p */
    504 	if (mp_exptmod(&dh_g, dh_priv, &dh_p, dh_pub) != MP_OKAY) {
    505 		dropbear_exit("Diffie-Hellman error");
    506 	}
    507 	mp_clear_multi(&dh_g, &dh_p, &dh_q, NULL);
    508 }
    509 
    510 /* This function is fairly common between client/server, with some substitution
    511  * of dh_e/dh_f etc. Hence these arguments:
    512  * dh_pub_us is 'e' for the client, 'f' for the server. dh_pub_them is
    513  * vice-versa. dh_priv is the x/y value corresponding to dh_pub_us */
    514 void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them,
    515 		sign_key *hostkey) {
    516 
    517 	mp_int dh_p;
    518 	mp_int *dh_e = NULL, *dh_f = NULL;
    519 	hash_state hs;
    520 
    521 	/* read the prime and generator*/
    522 	m_mp_init(&dh_p);
    523 	bytes_to_mp(&dh_p, dh_p_val, DH_P_LEN);
    524 
    525 	/* Check that dh_pub_them (dh_e or dh_f) is in the range [1, p-1] */
    526 	if (mp_cmp(dh_pub_them, &dh_p) != MP_LT
    527 			|| mp_cmp_d(dh_pub_them, 0) != MP_GT) {
    528 		dropbear_exit("Diffie-Hellman error");
    529 	}
    530 
    531 	/* K = e^y mod p = f^x mod p */
    532 	ses.dh_K = (mp_int*)m_malloc(sizeof(mp_int));
    533 	m_mp_init(ses.dh_K);
    534 	if (mp_exptmod(dh_pub_them, dh_priv, &dh_p, ses.dh_K) != MP_OKAY) {
    535 		dropbear_exit("Diffie-Hellman error");
    536 	}
    537 
    538 	/* clear no longer needed vars */
    539 	mp_clear_multi(&dh_p, NULL);
    540 
    541 	/* From here on, the code needs to work with the _same_ vars on each side,
    542 	 * not vice-versaing for client/server */
    543 	if (IS_DROPBEAR_CLIENT) {
    544 		dh_e = dh_pub_us;
    545 		dh_f = dh_pub_them;
    546 	} else {
    547 		dh_e = dh_pub_them;
    548 		dh_f = dh_pub_us;
    549 	}
    550 
    551 	/* Create the remainder of the hash buffer, to generate the exchange hash */
    552 	/* K_S, the host key */
    553 	buf_put_pub_key(ses.kexhashbuf, hostkey, ses.newkeys->algo_hostkey);
    554 	/* e, exchange value sent by the client */
    555 	buf_putmpint(ses.kexhashbuf, dh_e);
    556 	/* f, exchange value sent by the server */
    557 	buf_putmpint(ses.kexhashbuf, dh_f);
    558 	/* K, the shared secret */
    559 	buf_putmpint(ses.kexhashbuf, ses.dh_K);
    560 
    561 	/* calculate the hash H to sign */
    562 	sha1_init(&hs);
    563 	buf_setpos(ses.kexhashbuf, 0);
    564 	sha1_process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len),
    565 			ses.kexhashbuf->len);
    566 	sha1_done(&hs, ses.hash);
    567 
    568 	buf_burn(ses.kexhashbuf);
    569 	buf_free(ses.kexhashbuf);
    570 	ses.kexhashbuf = NULL;
    571 
    572 	/* first time around, we set the session_id to H */
    573 	if (ses.session_id == NULL) {
    574 		/* create the session_id, this never needs freeing */
    575 		ses.session_id = (unsigned char*)m_malloc(SHA1_HASH_SIZE);
    576 		memcpy(ses.session_id, ses.hash, SHA1_HASH_SIZE);
    577 	}
    578 }
    579 
    580 /* read the other side's algo list. buf_match_algo is a callback to match
    581  * algos for the client or server. */
    582 static void read_kex_algos() {
    583 
    584 	/* for asymmetry */
    585 	algo_type * c2s_hash_algo = NULL;
    586 	algo_type * s2c_hash_algo = NULL;
    587 	algo_type * c2s_cipher_algo = NULL;
    588 	algo_type * s2c_cipher_algo = NULL;
    589 	algo_type * c2s_comp_algo = NULL;
    590 	algo_type * s2c_comp_algo = NULL;
    591 	/* the generic one */
    592 	algo_type * algo = NULL;
    593 
    594 	/* which algo couldn't match */
    595 	char * erralgo = NULL;
    596 
    597 	int goodguess = 0;
    598 	int allgood = 1; /* we AND this with each goodguess and see if its still
    599 						true after */
    600 
    601 	buf_incrpos(ses.payload, 16); /* start after the cookie */
    602 
    603 	ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
    604 
    605 	/* kex_algorithms */
    606 	algo = ses.buf_match_algo(ses.payload, sshkex, &goodguess);
    607 	allgood &= goodguess;
    608 	if (algo == NULL) {
    609 		erralgo = "kex";
    610 		goto error;
    611 	}
    612 	TRACE(("kex algo %s", algo->name))
    613 	ses.newkeys->algo_kex = algo->val;
    614 
    615 	/* server_host_key_algorithms */
    616 	algo = ses.buf_match_algo(ses.payload, sshhostkey, &goodguess);
    617 	allgood &= goodguess;
    618 	if (algo == NULL) {
    619 		erralgo = "hostkey";
    620 		goto error;
    621 	}
    622 	TRACE(("hostkey algo %s", algo->name))
    623 	ses.newkeys->algo_hostkey = algo->val;
    624 
    625 	/* encryption_algorithms_client_to_server */
    626 	c2s_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess);
    627 	if (c2s_cipher_algo == NULL) {
    628 		erralgo = "enc c->s";
    629 		goto error;
    630 	}
    631 	TRACE(("enc c2s is  %s", c2s_cipher_algo->name))
    632 
    633 	/* encryption_algorithms_server_to_client */
    634 	s2c_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess);
    635 	if (s2c_cipher_algo == NULL) {
    636 		erralgo = "enc s->c";
    637 		goto error;
    638 	}
    639 	TRACE(("enc s2c is  %s", s2c_cipher_algo->name))
    640 
    641 	/* mac_algorithms_client_to_server */
    642 	c2s_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess);
    643 	if (c2s_hash_algo == NULL) {
    644 		erralgo = "mac c->s";
    645 		goto error;
    646 	}
    647 	TRACE(("hash c2s is  %s", c2s_hash_algo->name))
    648 
    649 	/* mac_algorithms_server_to_client */
    650 	s2c_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess);
    651 	if (s2c_hash_algo == NULL) {
    652 		erralgo = "mac s->c";
    653 		goto error;
    654 	}
    655 	TRACE(("hash s2c is  %s", s2c_hash_algo->name))
    656 
    657 	/* compression_algorithms_client_to_server */
    658 	c2s_comp_algo = ses.buf_match_algo(ses.payload, sshcompress, &goodguess);
    659 	if (c2s_comp_algo == NULL) {
    660 		erralgo = "comp c->s";
    661 		goto error;
    662 	}
    663 	TRACE(("hash c2s is  %s", c2s_comp_algo->name))
    664 
    665 	/* compression_algorithms_server_to_client */
    666 	s2c_comp_algo = ses.buf_match_algo(ses.payload, sshcompress, &goodguess);
    667 	if (s2c_comp_algo == NULL) {
    668 		erralgo = "comp s->c";
    669 		goto error;
    670 	}
    671 	TRACE(("hash s2c is  %s", s2c_comp_algo->name))
    672 
    673 	/* languages_client_to_server */
    674 	buf_eatstring(ses.payload);
    675 
    676 	/* languages_server_to_client */
    677 	buf_eatstring(ses.payload);
    678 
    679 	/* first_kex_packet_follows */
    680 	if (buf_getbool(ses.payload)) {
    681 		ses.kexstate.firstfollows = 1;
    682 		/* if the guess wasn't good, we ignore the packet sent */
    683 		if (!allgood) {
    684 			ses.ignorenext = 1;
    685 		}
    686 	}
    687 
    688 	/* Handle the asymmetry */
    689 	if (IS_DROPBEAR_CLIENT) {
    690 		ses.newkeys->recv_algo_crypt =
    691 			(struct dropbear_cipher*)s2c_cipher_algo->data;
    692 		ses.newkeys->trans_algo_crypt =
    693 			(struct dropbear_cipher*)c2s_cipher_algo->data;
    694 		ses.newkeys->recv_algo_mac =
    695 			(struct dropbear_hash*)s2c_hash_algo->data;
    696 		ses.newkeys->trans_algo_mac =
    697 			(struct dropbear_hash*)c2s_hash_algo->data;
    698 		ses.newkeys->recv_algo_comp = s2c_comp_algo->val;
    699 		ses.newkeys->trans_algo_comp = c2s_comp_algo->val;
    700 	} else {
    701 		/* SERVER */
    702 		ses.newkeys->recv_algo_crypt =
    703 			(struct dropbear_cipher*)c2s_cipher_algo->data;
    704 		ses.newkeys->trans_algo_crypt =
    705 			(struct dropbear_cipher*)s2c_cipher_algo->data;
    706 		ses.newkeys->recv_algo_mac =
    707 			(struct dropbear_hash*)c2s_hash_algo->data;
    708 		ses.newkeys->trans_algo_mac =
    709 			(struct dropbear_hash*)s2c_hash_algo->data;
    710 		ses.newkeys->recv_algo_comp = c2s_comp_algo->val;
    711 		ses.newkeys->trans_algo_comp = s2c_comp_algo->val;
    712 	}
    713 
    714 	/* reserved for future extensions */
    715 	buf_getint(ses.payload);
    716 	return;
    717 
    718 error:
    719 	dropbear_exit("no matching algo %s", erralgo);
    720 }
    721