mirror of
				https://github.com/clearml/dropbear
				synced 2025-06-26 18:17:32 +00:00 
			
		
		
		
	refactor kexdh code a bit, start working on ecdh etc
--HG-- branch : ecc
This commit is contained in:
		
							parent
							
								
									9be0d6b53d
								
							
						
					
					
						commit
						73e22c115c
					
				| @ -26,7 +26,7 @@ COMMONOBJS=dbutil.o buffer.o \ | ||||
| 		dss.o bignum.o \
 | ||||
| 		signkey.o rsa.o random.o \
 | ||||
| 		queue.o \
 | ||||
| 		atomicio.o compat.o  fake-rfc2553.o  | ||||
| 		atomicio.o compat.o  fake-rfc2553.o ltc_prng.o ecc.o | ||||
| 
 | ||||
| SVROBJS=svr-kex.o svr-algo.o svr-auth.o sshpty.o \
 | ||||
| 		svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \
 | ||||
|  | ||||
							
								
								
									
										18
									
								
								algo.h
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								algo.h
									
									
									
									
									
								
							| @ -94,5 +94,23 @@ int check_user_algos(const char* user_algo_list, algo_type * algos, | ||||
| char * algolist_string(algo_type algos[]); | ||||
| #endif | ||||
| 
 | ||||
| enum { | ||||
| 	DROPBEAR_KEX_DH_GROUP1, | ||||
| 	DROPBEAR_KEX_DH_GROUP14, | ||||
| 	DROPBEAR_KEX_ECDH_SECP256R1, | ||||
| }; | ||||
| 
 | ||||
| #ifdef DROPBEAR_ECDH | ||||
| #define IS_NORMAL_DH(algo) ((algo) == DROPBEAR_KEX_DH_GROUP1 || (algo) == DROPBEAR_KEX_DH_GROUP14) | ||||
| #else | ||||
| #define IS_NORMAL_DH(algo) 1 | ||||
| #endif | ||||
| 
 | ||||
| enum { | ||||
| 	DROPBEAR_COMP_NONE, | ||||
| 	DROPBEAR_COMP_ZLIB, | ||||
| 	DROPBEAR_COMP_ZLIB_DELAY, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #endif /* _ALGO_H_ */ | ||||
|  | ||||
							
								
								
									
										34
									
								
								cli-kex.c
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								cli-kex.c
									
									
									
									
									
								
							| @ -42,16 +42,16 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen); | ||||
| #define MAX_KNOWNHOSTS_LINE 4500 | ||||
| 
 | ||||
| void send_msg_kexdh_init() { | ||||
| 
 | ||||
| 	cli_ses.dh_e = (mp_int*)m_malloc(sizeof(mp_int)); | ||||
| 	cli_ses.dh_x = (mp_int*)m_malloc(sizeof(mp_int)); | ||||
| 	m_mp_init_multi(cli_ses.dh_e, cli_ses.dh_x, NULL); | ||||
| 
 | ||||
| 	gen_kexdh_vals(cli_ses.dh_e, cli_ses.dh_x); | ||||
| 
 | ||||
| 	CHECKCLEARTOWRITE(); | ||||
| 	buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT); | ||||
| 	buf_putmpint(ses.writepayload, cli_ses.dh_e); | ||||
| 	if (IS_NORMAL_DH(ses.newkeys->algo_kex)) { | ||||
| 		cli_ses.dh_param = gen_kexdh_param(); | ||||
| 		buf_putmpint(ses.writepayload, &cli_ses.dh_param->pub); | ||||
| 	} else { | ||||
| #ifdef DROPBEAR_ECDH | ||||
| 		cli_ses.ecdh_param =  | ||||
| #endif | ||||
| 	} | ||||
| 	encrypt_packet(); | ||||
| 	ses.requirenext = SSH_MSG_KEXDH_REPLY; | ||||
| } | ||||
| @ -59,18 +59,15 @@ void send_msg_kexdh_init() { | ||||
| /* Handle a diffie-hellman key exchange reply. */ | ||||
| void recv_msg_kexdh_reply() { | ||||
| 
 | ||||
| 	DEF_MP_INT(dh_f); | ||||
| 	sign_key *hostkey = NULL; | ||||
| 	unsigned int type, keybloblen; | ||||
| 	unsigned char* keyblob = NULL; | ||||
| 
 | ||||
| 
 | ||||
| 	TRACE(("enter recv_msg_kexdh_reply")) | ||||
| 
 | ||||
| 	if (cli_ses.kex_state != KEXDH_INIT_SENT) { | ||||
| 		dropbear_exit("Received out-of-order kexdhreply"); | ||||
| 	} | ||||
| 	m_mp_init(&dh_f); | ||||
| 	type = ses.newkeys->algo_hostkey; | ||||
| 	TRACE(("type is %d", type)) | ||||
| 
 | ||||
| @ -88,16 +85,23 @@ void recv_msg_kexdh_reply() { | ||||
| 		dropbear_exit("Bad KEX packet"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (IS_NORMAL_DH(ses.newkeys->algo_kex)) { | ||||
| 		// Normal diffie-hellman
 | ||||
| 		DEF_MP_INT(dh_f); | ||||
| 		m_mp_init(&dh_f); | ||||
| 		if (buf_getmpint(ses.payload, &dh_f) != DROPBEAR_SUCCESS) { | ||||
| 			TRACE(("failed getting mpint")) | ||||
| 			dropbear_exit("Bad KEX packet"); | ||||
| 		} | ||||
| 
 | ||||
| 	kexdh_comb_key(cli_ses.dh_e, cli_ses.dh_x, &dh_f, hostkey); | ||||
| 		kexdh_comb_key(cli_ses.dh_param, &dh_f, hostkey); | ||||
| 		mp_clear(&dh_f); | ||||
| 	mp_clear_multi(cli_ses.dh_e, cli_ses.dh_x, NULL); | ||||
| 	m_free(cli_ses.dh_e); | ||||
| 	m_free(cli_ses.dh_x); | ||||
| 		free_kexdh_param(cli_ses.dh_param); | ||||
| 		cli_ses.dh_param = NULL; | ||||
| 	} else { | ||||
| #ifdef DROPBEAR_ECDH | ||||
| #endif | ||||
| 	} | ||||
| 
 | ||||
| 	if (buf_verify(ses.payload, hostkey, ses.hash, SHA1_HASH_SIZE)  | ||||
| 			!= DROPBEAR_SUCCESS) { | ||||
|  | ||||
| @ -213,6 +213,7 @@ algo_type sshhostkey[] = { | ||||
| }; | ||||
| 
 | ||||
| algo_type sshkex[] = { | ||||
| //	{"ecdh-sha2-secp256r1", DROPBEAR_KEX_ECDH_SECP256R1, NULL, 1, NULL},
 | ||||
| 	{"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1, NULL}, | ||||
| 	{"diffie-hellman-group14-sha1", DROPBEAR_KEX_DH_GROUP14, NULL, 1, NULL}, | ||||
| 	{NULL, 0, NULL, 0, NULL} | ||||
|  | ||||
							
								
								
									
										39
									
								
								common-kex.c
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								common-kex.c
									
									
									
									
									
								
							| @ -549,7 +549,7 @@ static void load_dh_p(mp_int * dh_p) | ||||
| /* Initialises and generate one side of the diffie-hellman key exchange values.
 | ||||
|  * See the transport rfc 4253 section 8 for details */ | ||||
| /* dh_pub and dh_priv MUST be already initialised */ | ||||
| void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) { | ||||
| struct kex_dh_param *gen_kexdh_param() { | ||||
| 
 | ||||
| 	DEF_MP_INT(dh_p); | ||||
| 	DEF_MP_INT(dh_q); | ||||
| @ -557,7 +557,8 @@ void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) { | ||||
| 
 | ||||
| 	TRACE(("enter send_msg_kexdh_reply")) | ||||
| 
 | ||||
| 	m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL); | ||||
| 	struct kex_dh_param *param = m_malloc(sizeof(*param)); | ||||
| 	m_mp_init_multi(¶m->pub, ¶m->priv, NULL); | ||||
| 
 | ||||
| 	/* read the prime and generator*/ | ||||
| 	load_dh_p(&dh_p); | ||||
| @ -568,32 +569,40 @@ void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) { | ||||
| 
 | ||||
| 	/* calculate q = (p-1)/2 */ | ||||
| 	/* dh_priv is just a temp var here */ | ||||
| 	if (mp_sub_d(&dh_p, 1, dh_priv) != MP_OKAY) {  | ||||
| 	if (mp_sub_d(&dh_p, 1, ¶m->priv) != MP_OKAY) {  | ||||
| 		dropbear_exit("Diffie-Hellman error"); | ||||
| 	} | ||||
| 	if (mp_div_2(dh_priv, &dh_q) != MP_OKAY) { | ||||
| 	if (mp_div_2(¶m->priv, &dh_q) != MP_OKAY) { | ||||
| 		dropbear_exit("Diffie-Hellman error"); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Generate a private portion 0 < dh_priv < dh_q */ | ||||
| 	gen_random_mpint(&dh_q, dh_priv); | ||||
| 	gen_random_mpint(&dh_q, ¶m->priv); | ||||
| 
 | ||||
| 	/* f = g^y mod p */ | ||||
| 	if (mp_exptmod(&dh_g, dh_priv, &dh_p, dh_pub) != MP_OKAY) { | ||||
| 	if (mp_exptmod(&dh_g, ¶m->priv, &dh_p, ¶m->pub) != MP_OKAY) { | ||||
| 		dropbear_exit("Diffie-Hellman error"); | ||||
| 	} | ||||
| 	mp_clear_multi(&dh_g, &dh_p, &dh_q, NULL); | ||||
| 	return param; | ||||
| } | ||||
| 
 | ||||
| void free_kexdh_param(struct kex_dh_param *param) | ||||
| { | ||||
| 	mp_clear_multi(¶m->pub, ¶m->priv, NULL); | ||||
| 	m_free(param); | ||||
| } | ||||
| 
 | ||||
| /* This function is fairly common between client/server, with some substitution
 | ||||
|  * of dh_e/dh_f etc. Hence these arguments: | ||||
|  * dh_pub_us is 'e' for the client, 'f' for the server. dh_pub_them is  | ||||
|  * vice-versa. dh_priv is the x/y value corresponding to dh_pub_us */ | ||||
| void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them, | ||||
| void kexdh_comb_key(struct kex_dh_param *param, mp_int *dh_pub_them, | ||||
| 		sign_key *hostkey) { | ||||
| 
 | ||||
| 	mp_int dh_p; | ||||
| 	mp_int *dh_e = NULL, *dh_f = NULL; | ||||
| 
 | ||||
| 	hash_state hs; | ||||
| 
 | ||||
| 	/* read the prime and generator*/ | ||||
| @ -609,7 +618,7 @@ void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them, | ||||
| 	/* K = e^y mod p = f^x mod p */ | ||||
| 	ses.dh_K = (mp_int*)m_malloc(sizeof(mp_int)); | ||||
| 	m_mp_init(ses.dh_K); | ||||
| 	if (mp_exptmod(dh_pub_them, dh_priv, &dh_p, ses.dh_K) != MP_OKAY) { | ||||
| 	if (mp_exptmod(dh_pub_them, ¶m->priv, &dh_p, ses.dh_K) != MP_OKAY) { | ||||
| 		dropbear_exit("Diffie-Hellman error"); | ||||
| 	} | ||||
| 
 | ||||
| @ -619,11 +628,11 @@ void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them, | ||||
| 	/* From here on, the code needs to work with the _same_ vars on each side,
 | ||||
| 	 * not vice-versaing for client/server */ | ||||
| 	if (IS_DROPBEAR_CLIENT) { | ||||
| 		dh_e = dh_pub_us; | ||||
| 		dh_e = ¶m->pub; | ||||
| 		dh_f = dh_pub_them; | ||||
| 	} else { | ||||
| 		dh_e = dh_pub_them; | ||||
| 		dh_f = dh_pub_us; | ||||
| 		dh_f = ¶m->pub; | ||||
| 	}  | ||||
| 
 | ||||
| 	/* Create the remainder of the hash buffer, to generate the exchange hash */ | ||||
| @ -655,6 +664,16 @@ void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #ifdef DROPBEAR_ECDH | ||||
| struct kex_ecdh_param *gen_kexecdh_param() { | ||||
| 	struct kex_ecdh_param *param = m_malloc(sizeof(*param)); | ||||
| 	if (ecc_make_key_ex(NULL, dropbear_ltc_prng, ¶m->key | ||||
| } | ||||
| void free_kexecdh_param(struct kex_ecdh_param *param); | ||||
| void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them, | ||||
| 		sign_key *hostkey); | ||||
| #endif | ||||
| 
 | ||||
| /* read the other side's algo list. buf_match_algo is a callback to match
 | ||||
|  * algos for the client or server. */ | ||||
| static void read_kex_algos() { | ||||
|  | ||||
| @ -685,7 +685,7 @@ AS_MKDIR_P(libtomcrypt/src/pk/dsa) | ||||
| AS_MKDIR_P(libtomcrypt/src/pk/ecc) | ||||
| AS_MKDIR_P(libtomcrypt/src/pk/pkcs1) | ||||
| AS_MKDIR_P(libtomcrypt/src/pk/rsa) | ||||
| AS_MKDIR_P(libtomcrypt/src/prng) | ||||
| AS_MKDIR_P(libtomcrypt/src/prngs) | ||||
| AC_CONFIG_HEADER(config.h) | ||||
| AC_OUTPUT(Makefile) | ||||
| AC_OUTPUT(libtomcrypt/Makefile) | ||||
|  | ||||
							
								
								
									
										17
									
								
								ecc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								ecc.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| #ifdef DROPBEAR_ECC | ||||
| 
 | ||||
| void buf_put_ecc_key_string(buffer *buf, ecc_key *key) { | ||||
| 	int len = key->dp->size*2 + 1; | ||||
| 	buf_putint(len); | ||||
| 	int err = ecc_ansi_x963_export(key, buf_getwriteptr(buf, len), &len); | ||||
| 	if (err != CRYPT_OK) { | ||||
| 		dropbear_exit("ECC error"); | ||||
| 	} | ||||
| 	buf_incrwritepos(buf, len); | ||||
| } | ||||
| 
 | ||||
| int buf_get_ecc_key_string(buffer *buf, ecc_key *key) { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										24
									
								
								kex.h
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								kex.h
									
									
									
									
									
								
							| @ -33,10 +33,19 @@ void recv_msg_kexinit(); | ||||
| void send_msg_newkeys(); | ||||
| void recv_msg_newkeys(); | ||||
| void kexfirstinitialise(); | ||||
| void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv); | ||||
| void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them, | ||||
| 
 | ||||
| struct kex_dh_param *gen_kexdh_param(); | ||||
| void free_kexdh_param(struct kex_dh_param *param); | ||||
| void kexdh_comb_key(struct kex_dh_param *param, mp_int *dh_pub_them, | ||||
| 		sign_key *hostkey); | ||||
| 
 | ||||
| #ifdef DROPBEAR_ECDH | ||||
| struct kex_ecdh_param *gen_kexecdh_param(); | ||||
| void free_kexecdh_param(struct kex_ecdh_param *param); | ||||
| void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them, | ||||
| 		sign_key *hostkey); | ||||
| #endif | ||||
| 
 | ||||
| #ifndef DISABLE_ZLIB | ||||
| int is_compress_trans(); | ||||
| int is_compress_recv(); | ||||
| @ -64,6 +73,17 @@ struct KEXState { | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| struct kex_dh_param { | ||||
| 	mp_int pub; | ||||
| 	mp_int priv; | ||||
| }; | ||||
| 
 | ||||
| #ifdef DROPBEAR_ECDH | ||||
| struct kex_ecdh_param { | ||||
| 	ecc_key key; | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| #define MAX_KEXHASHBUF 2000 | ||||
| 
 | ||||
| #endif /* _KEX_H_ */ | ||||
|  | ||||
| @ -134,6 +134,13 @@ | ||||
| 
 | ||||
| #define LTC_HMAC | ||||
| 
 | ||||
| #ifdef DROPBEAR_ECDH | ||||
| #define MECC | ||||
| #define ECC256 | ||||
| #define ECC384 | ||||
| #define ECC521 | ||||
| #endif | ||||
| 
 | ||||
| /* Various tidbits of modern neatoness */ | ||||
| #define BASE64 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										136
									
								
								ltc_prng.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								ltc_prng.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,136 @@ | ||||
| /* Copied from libtomcrypt/src/prngs/sprng.c and modified to
 | ||||
|  * use Dropbear's genrandom(). */ | ||||
| 
 | ||||
| /* LibTomCrypt, modular cryptographic library -- Tom St Denis
 | ||||
|  * | ||||
|  * LibTomCrypt is a library that provides various cryptographic | ||||
|  * algorithms in a highly modular and flexible manner. | ||||
|  * | ||||
|  * The library is free for all purposes without any express | ||||
|  * guarantee it works. | ||||
|  * | ||||
|  * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
 | ||||
|  */ | ||||
| #include "options.h" | ||||
| #include "includes.h" | ||||
| #include "random.h" | ||||
| 
 | ||||
| /**
 | ||||
|    @file sprng.c | ||||
|    Secure PRNG, Tom St Denis | ||||
| */ | ||||
|     | ||||
| /* A secure PRNG using the RNG functions.  Basically this is a
 | ||||
|  * wrapper that allows you to use a secure RNG as a PRNG | ||||
|  * in the various other functions. | ||||
|  */ | ||||
| 
 | ||||
| #ifdef DROPBEAR_LTC_PRNG | ||||
| 
 | ||||
| /**
 | ||||
|   Start the PRNG | ||||
|   @param prng     [out] The PRNG state to initialize | ||||
|   @return CRYPT_OK if successful | ||||
| */   | ||||
| int dropbear_prng_start(prng_state *prng) | ||||
| { | ||||
|    return CRYPT_OK;   | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|   Add entropy to the PRNG state | ||||
|   @param in       The data to add | ||||
|   @param inlen    Length of the data to add | ||||
|   @param prng     PRNG state to update | ||||
|   @return CRYPT_OK if successful | ||||
| */   | ||||
| int dropbear_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) | ||||
| { | ||||
|    return CRYPT_OK; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|   Make the PRNG ready to read from | ||||
|   @param prng   The PRNG to make active | ||||
|   @return CRYPT_OK if successful | ||||
| */   | ||||
| int dropbear_prng_ready(prng_state *prng) | ||||
| { | ||||
|    return CRYPT_OK; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|   Read from the PRNG | ||||
|   @param out      Destination | ||||
|   @param outlen   Length of output | ||||
|   @param prng     The active PRNG to read from | ||||
|   @return Number of octets read | ||||
| */   | ||||
| unsigned long dropbear_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng) | ||||
| { | ||||
|    LTC_ARGCHK(out != NULL); | ||||
|    genrandom(out, outlen); | ||||
|    return CRYPT_OK; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|   Terminate the PRNG | ||||
|   @param prng   The PRNG to terminate | ||||
|   @return CRYPT_OK if successful | ||||
| */   | ||||
| int dropbear_prng_done(prng_state *prng) | ||||
| { | ||||
|    return CRYPT_OK; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|   Export the PRNG state | ||||
|   @param out       [out] Destination | ||||
|   @param outlen    [in/out] Max size and resulting size of the state | ||||
|   @param prng      The PRNG to export | ||||
|   @return CRYPT_OK if successful | ||||
| */   | ||||
| int dropbear_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) | ||||
| { | ||||
|    LTC_ARGCHK(outlen != NULL); | ||||
| 
 | ||||
|    *outlen = 0; | ||||
|    return CRYPT_OK; | ||||
| } | ||||
|   | ||||
| /**
 | ||||
|   Import a PRNG state | ||||
|   @param in       The PRNG state | ||||
|   @param inlen    Size of the state | ||||
|   @param prng     The PRNG to import | ||||
|   @return CRYPT_OK if successful | ||||
| */   | ||||
| int dropbear_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) | ||||
| { | ||||
|    return CRYPT_OK; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|   PRNG self-test | ||||
|   @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled | ||||
| */   | ||||
| int dropbear_prng_test(void) | ||||
| { | ||||
|    return CRYPT_OK; | ||||
| } | ||||
| 
 | ||||
| const struct ltc_prng_descriptor dropbear_prng_desc = | ||||
| { | ||||
|     "dropbear_prng", 0, | ||||
|     &dropbear_prng_start, | ||||
|     &dropbear_prng_add_entropy, | ||||
|     &dropbear_prng_ready, | ||||
|     &dropbear_prng_read, | ||||
|     &dropbear_prng_done, | ||||
|     &dropbear_prng_export, | ||||
|     &dropbear_prng_import, | ||||
|     &dropbear_prng_test | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #endif // DROPBEAR_LTC_PRNG
 | ||||
| @ -136,6 +136,8 @@ much traffic. */ | ||||
| #define DROPBEAR_RSA | ||||
| #define DROPBEAR_DSS | ||||
| 
 | ||||
| #define DROPBEAR_ECDH | ||||
| 
 | ||||
| /* RSA can be vulnerable to timing attacks which use the time required for
 | ||||
|  * signing to guess the private key. Blinding avoids this attack, though makes | ||||
|  * signing operations slightly slower. */ | ||||
|  | ||||
							
								
								
									
										9
									
								
								random.c
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								random.c
									
									
									
									
									
								
							| @ -36,6 +36,8 @@ static uint32_t counter = 0; | ||||
| static unsigned char hashpool[SHA1_HASH_SIZE] = {0}; | ||||
| static int donerandinit = 0; | ||||
| 
 | ||||
| int dropbear_ltc_prng = -1; | ||||
| 
 | ||||
| #define INIT_SEED_SIZE 32 /* 256 bits */ | ||||
| 
 | ||||
| /* The basic setup is we read some data from /dev/(u)random or prngd and hash it
 | ||||
| @ -231,6 +233,13 @@ void seedrandom() { | ||||
| 
 | ||||
| 	sha1_done(&hs, hashpool); | ||||
| 
 | ||||
| #ifdef DROPBEAR_LTC_PRNG | ||||
| 	if (dropbear_ltc_prng == -1) { | ||||
| 		dropbear_ltc_prng = register_prng(&dropbear_prng_desc); | ||||
| 		dropbear_assert(dropbear_ltc_prng != -1); | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	counter = 0; | ||||
| 	donerandinit = 1; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										2
									
								
								random.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								random.h
									
									
									
									
									
								
							| @ -32,4 +32,6 @@ void genrandom(unsigned char* buf, unsigned int len); | ||||
| void addrandom(char * buf, unsigned int len); | ||||
| void gen_random_mpint(mp_int *max, mp_int *rand); | ||||
| 
 | ||||
| extern int dropbear_ltc_prng; | ||||
| 
 | ||||
| #endif /* _RANDOM_H_ */ | ||||
|  | ||||
							
								
								
									
										10
									
								
								session.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								session.h
									
									
									
									
									
								
							| @ -67,7 +67,7 @@ struct key_context_directional { | ||||
| 	const struct dropbear_cipher_mode *crypt_mode; | ||||
| 	const struct dropbear_hash *algo_mac; | ||||
| 	int hash_index; /* lookup for libtomcrypt */ | ||||
| 	char algo_comp; /* compression */ | ||||
| 	int algo_comp; /* compression */ | ||||
| #ifndef DISABLE_ZLIB | ||||
| 	z_streamp zstream; | ||||
| #endif | ||||
| @ -86,8 +86,8 @@ struct key_context { | ||||
| 	struct key_context_directional recv; | ||||
| 	struct key_context_directional trans; | ||||
| 
 | ||||
| 	char algo_kex; | ||||
| 	char algo_hostkey; | ||||
| 	int algo_kex; | ||||
| 	int algo_hostkey; | ||||
| 
 | ||||
| 	int allow_compress; /* whether compression has started (useful in 
 | ||||
| 							zlib@openssh.com delayed compression case) */ | ||||
| @ -244,8 +244,8 @@ typedef enum { | ||||
| } cli_state; | ||||
| 
 | ||||
| struct clientsession { | ||||
| 
 | ||||
| 	mp_int *dh_e, *dh_x; /* Used during KEX */ | ||||
| 	struct kex_dh_param *dh_param; | ||||
| 	struct kex_ecdh_param *ecdh_param; | ||||
| 	cli_kex_state kex_state; /* Used for progressing KEX */ | ||||
| 	cli_state state; /* Used to progress auth/channelsession etc */ | ||||
| 	unsigned donefirstkex : 1; /* Set when we set sentnewkeys, never reset */ | ||||
|  | ||||
							
								
								
									
										46
									
								
								svr-kex.c
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								svr-kex.c
									
									
									
									
									
								
							| @ -36,7 +36,7 @@ | ||||
| #include "runopts.h" | ||||
| 
 | ||||
| 
 | ||||
| static void send_msg_kexdh_reply(mp_int *dh_e); | ||||
| static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs); | ||||
| 
 | ||||
| /* Handle a diffie-hellman key exchange initialisation. This involves
 | ||||
|  * calculating a session key reply value, and corresponding hash. These | ||||
| @ -45,20 +45,29 @@ static void send_msg_kexdh_reply(mp_int *dh_e); | ||||
| void recv_msg_kexdh_init() { | ||||
| 
 | ||||
| 	DEF_MP_INT(dh_e); | ||||
| 	buffer *ecdh_qs = NULL; | ||||
| 
 | ||||
| 	TRACE(("enter recv_msg_kexdh_init")) | ||||
| 	if (!ses.kexstate.recvkexinit) { | ||||
| 		dropbear_exit("Premature kexdh_init message received"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (IS_NORMAL_DH(ses.newkeys->algo_kex)) { | ||||
| 		m_mp_init(&dh_e); | ||||
| 		if (buf_getmpint(ses.payload, &dh_e) != DROPBEAR_SUCCESS) { | ||||
| 			dropbear_exit("Failed to get kex value"); | ||||
| 		} | ||||
| 	} else { | ||||
| #ifdef DROPBEAR_ECDH | ||||
| #endif | ||||
| 	} | ||||
| 
 | ||||
| 	send_msg_kexdh_reply(&dh_e); | ||||
| 	send_msg_kexdh_reply(&dh_e, ecdh_qs); | ||||
| 
 | ||||
| 	mp_clear(&dh_e); | ||||
| 	if (ecdh_qs) { | ||||
| 		buf_free(ecdh_qs); | ||||
| 	} | ||||
| 
 | ||||
| 	send_msg_newkeys(); | ||||
| 	ses.requirenext = SSH_MSG_NEWKEYS; | ||||
| @ -70,19 +79,10 @@ void recv_msg_kexdh_init() { | ||||
|  * that, the session hash is calculated, and signed with RSA or DSS. The | ||||
|  * result is sent to the client.  | ||||
|  * | ||||
|  * See the transport rfc 4253 section 8 for details */ | ||||
| static void send_msg_kexdh_reply(mp_int *dh_e) { | ||||
| 
 | ||||
| 	DEF_MP_INT(dh_y); | ||||
| 	DEF_MP_INT(dh_f); | ||||
| 
 | ||||
|  * See the transport RFC4253 section 8 for details | ||||
|  * or RFC5656 section 4 for elliptic curve variant. */ | ||||
| static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs) { | ||||
| 	TRACE(("enter send_msg_kexdh_reply")) | ||||
| 	m_mp_init_multi(&dh_y, &dh_f, NULL); | ||||
| 	 | ||||
| 	gen_kexdh_vals(&dh_f, &dh_y); | ||||
| 
 | ||||
| 	kexdh_comb_key(&dh_f, &dh_y, dh_e, svr_opts.hostkey); | ||||
| 	mp_clear(&dh_y); | ||||
| 
 | ||||
| 	/* we can start creating the kexdh_reply packet */ | ||||
| 	CHECKCLEARTOWRITE(); | ||||
| @ -90,9 +90,23 @@ static void send_msg_kexdh_reply(mp_int *dh_e) { | ||||
| 	buf_put_pub_key(ses.writepayload, svr_opts.hostkey, | ||||
| 			ses.newkeys->algo_hostkey); | ||||
| 
 | ||||
| 	if (IS_NORMAL_DH(ses.newkeys->algo_kex)) { | ||||
| 		// Normal diffie-hellman
 | ||||
| 		struct kex_dh_param * dh_param = gen_kexdh_param(); | ||||
| 		kexdh_comb_key(dh_param, dh_e, svr_opts.hostkey); | ||||
| 
 | ||||
| 		/* put f */ | ||||
| 	buf_putmpint(ses.writepayload, &dh_f); | ||||
| 	mp_clear(&dh_f); | ||||
| 		buf_putmpint(ses.writepayload, &dh_param->pub); | ||||
| 		free_kexdh_param(dh_param); | ||||
| 	} else { | ||||
| #ifdef DROPBEAR_ECDH | ||||
| 		struct kex_ecdh_param *ecdh_param = gen_kexecdh_param(); | ||||
| 		kexecdh_comb_key(ecdh_param, ecdh_qs, svr_opts.hostkey); | ||||
| 
 | ||||
| 		buf_put_ecc_pub(ses.writepayload, &ecdh_param->key); | ||||
| 		free_kexecdh_param(ecdh_param); | ||||
| #endif | ||||
| 	} | ||||
| 
 | ||||
| 	/* calc the signature */ | ||||
| 	buf_put_sign(ses.writepayload, svr_opts.hostkey,  | ||||
|  | ||||
							
								
								
									
										19
									
								
								sysoptions.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								sysoptions.h
									
									
									
									
									
								
							| @ -60,24 +60,20 @@ | ||||
| #define DROPBEAR_SUCCESS 0 | ||||
| #define DROPBEAR_FAILURE -1 | ||||
| 
 | ||||
| /* various algorithm identifiers */ | ||||
| #define DROPBEAR_KEX_DH_GROUP1 0 | ||||
| #define DROPBEAR_KEX_DH_GROUP14 1 | ||||
| 
 | ||||
| #define DROPBEAR_SIGNKEY_ANY 0 | ||||
| #define DROPBEAR_SIGNKEY_RSA 1 | ||||
| #define DROPBEAR_SIGNKEY_DSS 2 | ||||
| #define DROPBEAR_SIGNKEY_NONE 3 | ||||
| 
 | ||||
| #define DROPBEAR_COMP_NONE 0 | ||||
| #define DROPBEAR_COMP_ZLIB 1 | ||||
| #define DROPBEAR_COMP_ZLIB_DELAY 2 | ||||
| 
 | ||||
| /* Required for pubkey auth */ | ||||
| #if defined(ENABLE_SVR_PUBKEY_AUTH) || defined(DROPBEAR_CLIENT) | ||||
| #define DROPBEAR_SIGNKEY_VERIFY | ||||
| #endif | ||||
| 
 | ||||
| #ifdef DROPBEAR_ECDH | ||||
| #define DROPBEAR_LTC_PRNG | ||||
| #endif | ||||
| 
 | ||||
| #define SHA1_HASH_SIZE 20 | ||||
| #define MD5_HASH_SIZE 16 | ||||
| 
 | ||||
| @ -93,6 +89,13 @@ | ||||
| #define MAX_MAC_LEN 20 | ||||
| #endif | ||||
| 
 | ||||
| #if defined(DROPBEAR_ECDH) || defined (DROPBEAR_ECDSA) | ||||
| #define DROPBEAR_ECC | ||||
| #endif | ||||
| 
 | ||||
| // roughly 2x 521 bits
 | ||||
| #define MAX_ECC_SIZE 140 | ||||
| 
 | ||||
| #define MAX_NAME_LEN 64 /* maximum length of a protocol name, isn't | ||||
| 						   explicitly specified for all protocols (just | ||||
| 						   for algos) but seems valid */ | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user