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 \
 | 		dss.o bignum.o \
 | ||||||
| 		signkey.o rsa.o random.o \
 | 		signkey.o rsa.o random.o \
 | ||||||
| 		queue.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 \
 | 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 \
 | 		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[]); | char * algolist_string(algo_type algos[]); | ||||||
| #endif | #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_ */ | #endif /* _ALGO_H_ */ | ||||||
|  | |||||||
							
								
								
									
										44
									
								
								cli-kex.c
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								cli-kex.c
									
									
									
									
									
								
							| @ -42,16 +42,16 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen); | |||||||
| #define MAX_KNOWNHOSTS_LINE 4500 | #define MAX_KNOWNHOSTS_LINE 4500 | ||||||
| 
 | 
 | ||||||
| void send_msg_kexdh_init() { | 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(); | 	CHECKCLEARTOWRITE(); | ||||||
| 	buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT); | 	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(); | 	encrypt_packet(); | ||||||
| 	ses.requirenext = SSH_MSG_KEXDH_REPLY; | 	ses.requirenext = SSH_MSG_KEXDH_REPLY; | ||||||
| } | } | ||||||
| @ -59,18 +59,15 @@ void send_msg_kexdh_init() { | |||||||
| /* Handle a diffie-hellman key exchange reply. */ | /* Handle a diffie-hellman key exchange reply. */ | ||||||
| void recv_msg_kexdh_reply() { | void recv_msg_kexdh_reply() { | ||||||
| 
 | 
 | ||||||
| 	DEF_MP_INT(dh_f); |  | ||||||
| 	sign_key *hostkey = NULL; | 	sign_key *hostkey = NULL; | ||||||
| 	unsigned int type, keybloblen; | 	unsigned int type, keybloblen; | ||||||
| 	unsigned char* keyblob = NULL; | 	unsigned char* keyblob = NULL; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	TRACE(("enter recv_msg_kexdh_reply")) | 	TRACE(("enter recv_msg_kexdh_reply")) | ||||||
| 
 | 
 | ||||||
| 	if (cli_ses.kex_state != KEXDH_INIT_SENT) { | 	if (cli_ses.kex_state != KEXDH_INIT_SENT) { | ||||||
| 		dropbear_exit("Received out-of-order kexdhreply"); | 		dropbear_exit("Received out-of-order kexdhreply"); | ||||||
| 	} | 	} | ||||||
| 	m_mp_init(&dh_f); |  | ||||||
| 	type = ses.newkeys->algo_hostkey; | 	type = ses.newkeys->algo_hostkey; | ||||||
| 	TRACE(("type is %d", type)) | 	TRACE(("type is %d", type)) | ||||||
| 
 | 
 | ||||||
| @ -88,16 +85,23 @@ void recv_msg_kexdh_reply() { | |||||||
| 		dropbear_exit("Bad KEX packet"); | 		dropbear_exit("Bad KEX packet"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (buf_getmpint(ses.payload, &dh_f) != DROPBEAR_SUCCESS) { | 	if (IS_NORMAL_DH(ses.newkeys->algo_kex)) { | ||||||
| 		TRACE(("failed getting mpint")) | 		// Normal diffie-hellman
 | ||||||
| 		dropbear_exit("Bad KEX packet"); | 		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(&dh_f); | ||||||
| 	mp_clear_multi(cli_ses.dh_e, cli_ses.dh_x, NULL); | 		free_kexdh_param(cli_ses.dh_param); | ||||||
| 	m_free(cli_ses.dh_e); | 		cli_ses.dh_param = NULL; | ||||||
| 	m_free(cli_ses.dh_x); | 	} else { | ||||||
|  | #ifdef DROPBEAR_ECDH | ||||||
|  | #endif | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if (buf_verify(ses.payload, hostkey, ses.hash, SHA1_HASH_SIZE)  | 	if (buf_verify(ses.payload, hostkey, ses.hash, SHA1_HASH_SIZE)  | ||||||
| 			!= DROPBEAR_SUCCESS) { | 			!= DROPBEAR_SUCCESS) { | ||||||
|  | |||||||
| @ -213,6 +213,7 @@ algo_type sshhostkey[] = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| algo_type sshkex[] = { | 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-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1, NULL}, | ||||||
| 	{"diffie-hellman-group14-sha1", DROPBEAR_KEX_DH_GROUP14, NULL, 1, NULL}, | 	{"diffie-hellman-group14-sha1", DROPBEAR_KEX_DH_GROUP14, NULL, 1, NULL}, | ||||||
| 	{NULL, 0, NULL, 0, NULL} | 	{NULL, 0, NULL, 0, NULL} | ||||||
|  | |||||||
							
								
								
									
										41
									
								
								common-kex.c
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								common-kex.c
									
									
									
									
									
								
							| @ -549,15 +549,16 @@ static void load_dh_p(mp_int * dh_p) | |||||||
| /* Initialises and generate one side of the diffie-hellman key exchange values.
 | /* Initialises and generate one side of the diffie-hellman key exchange values.
 | ||||||
|  * See the transport rfc 4253 section 8 for details */ |  * See the transport rfc 4253 section 8 for details */ | ||||||
| /* dh_pub and dh_priv MUST be already initialised */ | /* 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_p); | ||||||
| 	DEF_MP_INT(dh_q); | 	DEF_MP_INT(dh_q); | ||||||
| 	DEF_MP_INT(dh_g); | 	DEF_MP_INT(dh_g); | ||||||
| 
 | 
 | ||||||
| 	TRACE(("enter send_msg_kexdh_reply")) | 	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*/ | 	/* read the prime and generator*/ | ||||||
| 	load_dh_p(&dh_p); | 	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 */ | 	/* calculate q = (p-1)/2 */ | ||||||
| 	/* dh_priv is just a temp var here */ | 	/* 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"); | 		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"); | 		dropbear_exit("Diffie-Hellman error"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Generate a private portion 0 < dh_priv < dh_q */ | 	/* 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 */ | 	/* 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"); | 		dropbear_exit("Diffie-Hellman error"); | ||||||
| 	} | 	} | ||||||
| 	mp_clear_multi(&dh_g, &dh_p, &dh_q, NULL); | 	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
 | /* This function is fairly common between client/server, with some substitution
 | ||||||
|  * of dh_e/dh_f etc. Hence these arguments: |  * 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  |  * 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 */ |  * 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) { | 		sign_key *hostkey) { | ||||||
| 
 | 
 | ||||||
| 	mp_int dh_p; | 	mp_int dh_p; | ||||||
| 	mp_int *dh_e = NULL, *dh_f = NULL; | 	mp_int *dh_e = NULL, *dh_f = NULL; | ||||||
|  | 
 | ||||||
| 	hash_state hs; | 	hash_state hs; | ||||||
| 
 | 
 | ||||||
| 	/* read the prime and generator*/ | 	/* 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 */ | 	/* K = e^y mod p = f^x mod p */ | ||||||
| 	ses.dh_K = (mp_int*)m_malloc(sizeof(mp_int)); | 	ses.dh_K = (mp_int*)m_malloc(sizeof(mp_int)); | ||||||
| 	m_mp_init(ses.dh_K); | 	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"); | 		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,
 | 	/* From here on, the code needs to work with the _same_ vars on each side,
 | ||||||
| 	 * not vice-versaing for client/server */ | 	 * not vice-versaing for client/server */ | ||||||
| 	if (IS_DROPBEAR_CLIENT) { | 	if (IS_DROPBEAR_CLIENT) { | ||||||
| 		dh_e = dh_pub_us; | 		dh_e = ¶m->pub; | ||||||
| 		dh_f = dh_pub_them; | 		dh_f = dh_pub_them; | ||||||
| 	} else { | 	} else { | ||||||
| 		dh_e = dh_pub_them; | 		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 */ | 	/* 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
 | /* read the other side's algo list. buf_match_algo is a callback to match
 | ||||||
|  * algos for the client or server. */ |  * algos for the client or server. */ | ||||||
| static void read_kex_algos() { | 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/ecc) | ||||||
| AS_MKDIR_P(libtomcrypt/src/pk/pkcs1) | AS_MKDIR_P(libtomcrypt/src/pk/pkcs1) | ||||||
| AS_MKDIR_P(libtomcrypt/src/pk/rsa) | 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_CONFIG_HEADER(config.h) | ||||||
| AC_OUTPUT(Makefile) | AC_OUTPUT(Makefile) | ||||||
| AC_OUTPUT(libtomcrypt/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 send_msg_newkeys(); | ||||||
| void recv_msg_newkeys(); | void recv_msg_newkeys(); | ||||||
| void kexfirstinitialise(); | 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); | 		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 | #ifndef DISABLE_ZLIB | ||||||
| int is_compress_trans(); | int is_compress_trans(); | ||||||
| int is_compress_recv(); | 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 | #define MAX_KEXHASHBUF 2000 | ||||||
| 
 | 
 | ||||||
| #endif /* _KEX_H_ */ | #endif /* _KEX_H_ */ | ||||||
|  | |||||||
| @ -134,6 +134,13 @@ | |||||||
| 
 | 
 | ||||||
| #define LTC_HMAC | #define LTC_HMAC | ||||||
| 
 | 
 | ||||||
|  | #ifdef DROPBEAR_ECDH | ||||||
|  | #define MECC | ||||||
|  | #define ECC256 | ||||||
|  | #define ECC384 | ||||||
|  | #define ECC521 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| /* Various tidbits of modern neatoness */ | /* Various tidbits of modern neatoness */ | ||||||
| #define BASE64 | #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_RSA | ||||||
| #define DROPBEAR_DSS | #define DROPBEAR_DSS | ||||||
| 
 | 
 | ||||||
|  | #define DROPBEAR_ECDH | ||||||
|  | 
 | ||||||
| /* RSA can be vulnerable to timing attacks which use the time required for
 | /* 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 to guess the private key. Blinding avoids this attack, though makes | ||||||
|  * signing operations slightly slower. */ |  * 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 unsigned char hashpool[SHA1_HASH_SIZE] = {0}; | ||||||
| static int donerandinit = 0; | static int donerandinit = 0; | ||||||
| 
 | 
 | ||||||
|  | int dropbear_ltc_prng = -1; | ||||||
|  | 
 | ||||||
| #define INIT_SEED_SIZE 32 /* 256 bits */ | #define INIT_SEED_SIZE 32 /* 256 bits */ | ||||||
| 
 | 
 | ||||||
| /* The basic setup is we read some data from /dev/(u)random or prngd and hash it
 | /* 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); | 	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; | 	counter = 0; | ||||||
| 	donerandinit = 1; | 	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 addrandom(char * buf, unsigned int len); | ||||||
| void gen_random_mpint(mp_int *max, mp_int *rand); | void gen_random_mpint(mp_int *max, mp_int *rand); | ||||||
| 
 | 
 | ||||||
|  | extern int dropbear_ltc_prng; | ||||||
|  | 
 | ||||||
| #endif /* _RANDOM_H_ */ | #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_cipher_mode *crypt_mode; | ||||||
| 	const struct dropbear_hash *algo_mac; | 	const struct dropbear_hash *algo_mac; | ||||||
| 	int hash_index; /* lookup for libtomcrypt */ | 	int hash_index; /* lookup for libtomcrypt */ | ||||||
| 	char algo_comp; /* compression */ | 	int algo_comp; /* compression */ | ||||||
| #ifndef DISABLE_ZLIB | #ifndef DISABLE_ZLIB | ||||||
| 	z_streamp zstream; | 	z_streamp zstream; | ||||||
| #endif | #endif | ||||||
| @ -86,8 +86,8 @@ struct key_context { | |||||||
| 	struct key_context_directional recv; | 	struct key_context_directional recv; | ||||||
| 	struct key_context_directional trans; | 	struct key_context_directional trans; | ||||||
| 
 | 
 | ||||||
| 	char algo_kex; | 	int algo_kex; | ||||||
| 	char algo_hostkey; | 	int algo_hostkey; | ||||||
| 
 | 
 | ||||||
| 	int allow_compress; /* whether compression has started (useful in 
 | 	int allow_compress; /* whether compression has started (useful in 
 | ||||||
| 							zlib@openssh.com delayed compression case) */ | 							zlib@openssh.com delayed compression case) */ | ||||||
| @ -244,8 +244,8 @@ typedef enum { | |||||||
| } cli_state; | } cli_state; | ||||||
| 
 | 
 | ||||||
| struct clientsession { | struct clientsession { | ||||||
| 
 | 	struct kex_dh_param *dh_param; | ||||||
| 	mp_int *dh_e, *dh_x; /* Used during KEX */ | 	struct kex_ecdh_param *ecdh_param; | ||||||
| 	cli_kex_state kex_state; /* Used for progressing KEX */ | 	cli_kex_state kex_state; /* Used for progressing KEX */ | ||||||
| 	cli_state state; /* Used to progress auth/channelsession etc */ | 	cli_state state; /* Used to progress auth/channelsession etc */ | ||||||
| 	unsigned donefirstkex : 1; /* Set when we set sentnewkeys, never reset */ | 	unsigned donefirstkex : 1; /* Set when we set sentnewkeys, never reset */ | ||||||
|  | |||||||
							
								
								
									
										54
									
								
								svr-kex.c
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								svr-kex.c
									
									
									
									
									
								
							| @ -36,7 +36,7 @@ | |||||||
| #include "runopts.h" | #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
 | /* Handle a diffie-hellman key exchange initialisation. This involves
 | ||||||
|  * calculating a session key reply value, and corresponding hash. These |  * 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() { | void recv_msg_kexdh_init() { | ||||||
| 
 | 
 | ||||||
| 	DEF_MP_INT(dh_e); | 	DEF_MP_INT(dh_e); | ||||||
|  | 	buffer *ecdh_qs = NULL; | ||||||
| 
 | 
 | ||||||
| 	TRACE(("enter recv_msg_kexdh_init")) | 	TRACE(("enter recv_msg_kexdh_init")) | ||||||
| 	if (!ses.kexstate.recvkexinit) { | 	if (!ses.kexstate.recvkexinit) { | ||||||
| 		dropbear_exit("Premature kexdh_init message received"); | 		dropbear_exit("Premature kexdh_init message received"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	m_mp_init(&dh_e); | 	if (IS_NORMAL_DH(ses.newkeys->algo_kex)) { | ||||||
| 	if (buf_getmpint(ses.payload, &dh_e) != DROPBEAR_SUCCESS) { | 		m_mp_init(&dh_e); | ||||||
| 		dropbear_exit("Failed to get kex value"); | 		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); | 	mp_clear(&dh_e); | ||||||
|  | 	if (ecdh_qs) { | ||||||
|  | 		buf_free(ecdh_qs); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	send_msg_newkeys(); | 	send_msg_newkeys(); | ||||||
| 	ses.requirenext = SSH_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 |  * that, the session hash is calculated, and signed with RSA or DSS. The | ||||||
|  * result is sent to the client.  |  * result is sent to the client.  | ||||||
|  * |  * | ||||||
|  * See the transport rfc 4253 section 8 for details */ |  * See the transport RFC4253 section 8 for details | ||||||
| static void send_msg_kexdh_reply(mp_int *dh_e) { |  * or RFC5656 section 4 for elliptic curve variant. */ | ||||||
| 
 | static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs) { | ||||||
| 	DEF_MP_INT(dh_y); |  | ||||||
| 	DEF_MP_INT(dh_f); |  | ||||||
| 
 |  | ||||||
| 	TRACE(("enter send_msg_kexdh_reply")) | 	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 */ | 	/* we can start creating the kexdh_reply packet */ | ||||||
| 	CHECKCLEARTOWRITE(); | 	CHECKCLEARTOWRITE(); | ||||||
| @ -90,9 +90,23 @@ static void send_msg_kexdh_reply(mp_int *dh_e) { | |||||||
| 	buf_put_pub_key(ses.writepayload, svr_opts.hostkey, | 	buf_put_pub_key(ses.writepayload, svr_opts.hostkey, | ||||||
| 			ses.newkeys->algo_hostkey); | 			ses.newkeys->algo_hostkey); | ||||||
| 
 | 
 | ||||||
| 	/* put f */ | 	if (IS_NORMAL_DH(ses.newkeys->algo_kex)) { | ||||||
| 	buf_putmpint(ses.writepayload, &dh_f); | 		// Normal diffie-hellman
 | ||||||
| 	mp_clear(&dh_f); | 		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_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 */ | 	/* calc the signature */ | ||||||
| 	buf_put_sign(ses.writepayload, svr_opts.hostkey,  | 	buf_put_sign(ses.writepayload, svr_opts.hostkey,  | ||||||
|  | |||||||
							
								
								
									
										19
									
								
								sysoptions.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								sysoptions.h
									
									
									
									
									
								
							| @ -60,24 +60,20 @@ | |||||||
| #define DROPBEAR_SUCCESS 0 | #define DROPBEAR_SUCCESS 0 | ||||||
| #define DROPBEAR_FAILURE -1 | #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_ANY 0 | ||||||
| #define DROPBEAR_SIGNKEY_RSA 1 | #define DROPBEAR_SIGNKEY_RSA 1 | ||||||
| #define DROPBEAR_SIGNKEY_DSS 2 | #define DROPBEAR_SIGNKEY_DSS 2 | ||||||
| #define DROPBEAR_SIGNKEY_NONE 3 | #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 */ | /* Required for pubkey auth */ | ||||||
| #if defined(ENABLE_SVR_PUBKEY_AUTH) || defined(DROPBEAR_CLIENT) | #if defined(ENABLE_SVR_PUBKEY_AUTH) || defined(DROPBEAR_CLIENT) | ||||||
| #define DROPBEAR_SIGNKEY_VERIFY | #define DROPBEAR_SIGNKEY_VERIFY | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef DROPBEAR_ECDH | ||||||
|  | #define DROPBEAR_LTC_PRNG | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #define SHA1_HASH_SIZE 20 | #define SHA1_HASH_SIZE 20 | ||||||
| #define MD5_HASH_SIZE 16 | #define MD5_HASH_SIZE 16 | ||||||
| 
 | 
 | ||||||
| @ -93,6 +89,13 @@ | |||||||
| #define MAX_MAC_LEN 20 | #define MAX_MAC_LEN 20 | ||||||
| #endif | #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 | #define MAX_NAME_LEN 64 /* maximum length of a protocol name, isn't | ||||||
| 						   explicitly specified for all protocols (just | 						   explicitly specified for all protocols (just | ||||||
| 						   for algos) but seems valid */ | 						   for algos) but seems valid */ | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user