mirror of
				https://github.com/clearml/dropbear
				synced 2025-06-26 18:17:32 +00:00 
			
		
		
		
	A bit of work on ecdsa for host/auth keys
--HG-- branch : ecc
This commit is contained in:
		
							parent
							
								
									f842712551
								
							
						
					
					
						commit
						5c87c6a435
					
				
							
								
								
									
										6
									
								
								algo.h
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								algo.h
									
									
									
									
									
								
							| @ -74,8 +74,10 @@ struct dropbear_cipher_mode { | ||||
| }; | ||||
| 
 | ||||
| struct dropbear_hash { | ||||
| 	const struct ltc_hash_descriptor *hashdesc; | ||||
| 	const struct ltc_hash_descriptor *hash_desc; | ||||
| 	const unsigned long keysize; | ||||
| 	// hashsize may be truncated from the size returned by hash_desc,
 | ||||
| 	// eg sha1-96
 | ||||
| 	const unsigned char hashsize; | ||||
| }; | ||||
| 
 | ||||
| @ -90,7 +92,7 @@ struct dropbear_kex { | ||||
| #endif | ||||
| 
 | ||||
| 	// both
 | ||||
| 	const struct ltc_hash_descriptor *hashdesc; | ||||
| 	const struct ltc_hash_descriptor *hash_desc; | ||||
| }; | ||||
| 
 | ||||
| int have_algo(char* algo, size_t algolen, algo_type algos[]); | ||||
|  | ||||
							
								
								
									
										50
									
								
								common-kex.c
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								common-kex.c
									
									
									
									
									
								
							| @ -255,25 +255,25 @@ static void kexinitialise() { | ||||
| static void hashkeys(unsigned char *out, unsigned int outlen,  | ||||
| 		const hash_state * hs, const unsigned char X) { | ||||
| 
 | ||||
| 	const struct ltc_hash_descriptor *hashdesc = ses.newkeys->algo_kex->hashdesc; | ||||
| 	const struct ltc_hash_descriptor *hash_desc = ses.newkeys->algo_kex->hash_desc; | ||||
| 	hash_state hs2; | ||||
| 	unsigned int offset; | ||||
| 	unsigned char tmpout[hashdesc->hashsize]; | ||||
| 	unsigned char tmpout[hash_desc->hashsize]; | ||||
| 
 | ||||
| 	memcpy(&hs2, hs, sizeof(hash_state)); | ||||
| 	hashdesc->process(&hs2, &X, 1); | ||||
| 	hashdesc->process(&hs2, ses.session_id->data, ses.session_id->len); | ||||
| 	hashdesc->done(&hs2, tmpout); | ||||
| 	memcpy(out, tmpout, MIN(hashdesc->hashsize, outlen)); | ||||
| 	for (offset = hashdesc->hashsize;  | ||||
| 	hash_desc->process(&hs2, &X, 1); | ||||
| 	hash_desc->process(&hs2, ses.session_id->data, ses.session_id->len); | ||||
| 	hash_desc->done(&hs2, tmpout); | ||||
| 	memcpy(out, tmpout, MIN(hash_desc->hashsize, outlen)); | ||||
| 	for (offset = hash_desc->hashsize;  | ||||
| 			offset < outlen;  | ||||
| 			offset += hashdesc->hashsize) | ||||
| 			offset += hash_desc->hashsize) | ||||
| 	{ | ||||
| 		/* need to extend */ | ||||
| 		memcpy(&hs2, hs, sizeof(hash_state)); | ||||
| 		hashdesc->process(&hs2, out, offset); | ||||
| 		hashdesc->done(&hs2, tmpout); | ||||
| 		memcpy(&out[offset], tmpout, MIN(outlen - offset, hashdesc->hashsize)); | ||||
| 		hash_desc->process(&hs2, out, offset); | ||||
| 		hash_desc->done(&hs2, tmpout); | ||||
| 		memcpy(&out[offset], tmpout, MIN(outlen - offset, hash_desc->hashsize)); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -295,17 +295,17 @@ void gen_new_keys() { | ||||
| 	unsigned char *trans_IV, *trans_key, *recv_IV, *recv_key; | ||||
| 
 | ||||
| 	hash_state hs; | ||||
| 	const struct ltc_hash_descriptor *hashdesc = ses.newkeys->algo_kex->hashdesc; | ||||
| 	const struct ltc_hash_descriptor *hash_desc = ses.newkeys->algo_kex->hash_desc; | ||||
| 	char mactransletter, macrecvletter; /* Client or server specific */ | ||||
| 
 | ||||
| 	TRACE(("enter gen_new_keys")) | ||||
| 	/* the dh_K and hash are the start of all hashes, we make use of that */ | ||||
| 
 | ||||
| 	hashdesc->init(&hs); | ||||
| 	hash_process_mp(hashdesc, &hs, ses.dh_K); | ||||
| 	hash_desc->init(&hs); | ||||
| 	hash_process_mp(hash_desc, &hs, ses.dh_K); | ||||
| 	mp_clear(ses.dh_K); | ||||
| 	m_free(ses.dh_K); | ||||
| 	hashdesc->process(&hs, ses.hash->data, ses.hash->len); | ||||
| 	hash_desc->process(&hs, ses.hash->data, ses.hash->len); | ||||
| 	buf_burn(ses.hash); | ||||
| 	buf_free(ses.hash); | ||||
| 	ses.hash = NULL; | ||||
| @ -355,16 +355,16 @@ void gen_new_keys() { | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (ses.newkeys->trans.algo_mac->hashdesc != NULL) { | ||||
| 	if (ses.newkeys->trans.algo_mac->hash_desc != NULL) { | ||||
| 		hashkeys(ses.newkeys->trans.mackey,  | ||||
| 				ses.newkeys->trans.algo_mac->keysize, &hs, mactransletter); | ||||
| 		ses.newkeys->trans.hash_index = find_hash(ses.newkeys->trans.algo_mac->hashdesc->name); | ||||
| 		ses.newkeys->trans.hash_index = find_hash(ses.newkeys->trans.algo_mac->hash_desc->name); | ||||
| 	} | ||||
| 
 | ||||
| 	if (ses.newkeys->recv.algo_mac->hashdesc != NULL) { | ||||
| 	if (ses.newkeys->recv.algo_mac->hash_desc != NULL) { | ||||
| 		hashkeys(ses.newkeys->recv.mackey,  | ||||
| 				ses.newkeys->recv.algo_mac->keysize, &hs, macrecvletter); | ||||
| 		ses.newkeys->recv.hash_index = find_hash(ses.newkeys->recv.algo_mac->hashdesc->name); | ||||
| 		ses.newkeys->recv.hash_index = find_hash(ses.newkeys->recv.algo_mac->hash_desc->name); | ||||
| 	} | ||||
| 
 | ||||
| #ifndef DISABLE_ZLIB | ||||
| @ -694,15 +694,15 @@ void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them, | ||||
| 
 | ||||
| static void finish_kexhashbuf(void) { | ||||
| 	hash_state hs; | ||||
| 	const struct ltc_hash_descriptor *hashdesc = ses.newkeys->algo_kex->hashdesc; | ||||
| 	const struct ltc_hash_descriptor *hash_desc = ses.newkeys->algo_kex->hash_desc; | ||||
| 
 | ||||
| 	hashdesc->init(&hs); | ||||
| 	hash_desc->init(&hs); | ||||
| 	buf_setpos(ses.kexhashbuf, 0); | ||||
| 	hashdesc->process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len), | ||||
| 	hash_desc->process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len), | ||||
| 			ses.kexhashbuf->len); | ||||
| 	ses.hash = buf_new(hashdesc->hashsize); | ||||
| 	hashdesc->done(&hs, buf_getwriteptr(ses.hash, hashdesc->hashsize)); | ||||
| 	buf_setlen(ses.hash, hashdesc->hashsize); | ||||
| 	ses.hash = buf_new(hash_desc->hashsize); | ||||
| 	hash_desc->done(&hs, buf_getwriteptr(ses.hash, hash_desc->hashsize)); | ||||
| 	buf_setlen(ses.hash, hash_desc->hashsize); | ||||
| 
 | ||||
| 	buf_burn(ses.kexhashbuf); | ||||
| 	buf_free(ses.kexhashbuf); | ||||
|  | ||||
							
								
								
									
										17
									
								
								ecc.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								ecc.c
									
									
									
									
									
								
							| @ -10,21 +10,21 @@ | ||||
| #ifdef DROPBEAR_ECC_256 | ||||
| struct dropbear_ecc_curve ecc_curve_nistp256 = { | ||||
| 	.ltc_size = 32, | ||||
| 	.hashdesc = &sha256_desc, | ||||
| 	.hash_desc = &sha256_desc, | ||||
| 	.name = "nistp256" | ||||
| }; | ||||
| #endif | ||||
| #ifdef DROPBEAR_ECC_384 | ||||
| struct dropbear_ecc_curve ecc_curve_nistp384 = { | ||||
| 	.ltc_size = 48, | ||||
| 	.hashdesc = &sha384_desc, | ||||
| 	.hash_desc = &sha384_desc, | ||||
| 	.name = "nistp384" | ||||
| }; | ||||
| #endif | ||||
| #ifdef DROPBEAR_ECC_521 | ||||
| struct dropbear_ecc_curve ecc_curve_nistp521 = { | ||||
| 	.ltc_size = 66, | ||||
| 	.hashdesc = &sha512_desc, | ||||
| 	.hash_desc = &sha512_desc, | ||||
| 	.name = "nistp521" | ||||
| }; | ||||
| #endif | ||||
| @ -59,6 +59,17 @@ void dropbear_ecc_fill_dp() { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| struct dropbear_ecc_curve* curve_for_dp(const ltc_ecc_set_type *dp) { | ||||
| 	struct dropbear_ecc_curve **curve = NULL; | ||||
| 	for (curve = dropbear_ecc_curves; *curve; curve++) { | ||||
| 		if ((*curve)->dp == dp) { | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	assert(*curve); | ||||
| 	return *curve; | ||||
| } | ||||
| 
 | ||||
| ecc_key * new_ecc_key(void) { | ||||
| 	ecc_key *key = m_malloc(sizeof(*key)); | ||||
| 	key->pubkey.x = m_malloc(sizeof(mp_int)); | ||||
|  | ||||
							
								
								
									
										5
									
								
								ecc.h
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								ecc.h
									
									
									
									
									
								
							| @ -11,8 +11,8 @@ | ||||
| struct dropbear_ecc_curve { | ||||
| 	int ltc_size; // to match the byte sizes in ltc_ecc_sets[]
 | ||||
| 	const ltc_ecc_set_type *dp; // curve domain parameters
 | ||||
| 	const struct ltc_hash_descriptor *hashdesc; | ||||
| 	const char *name; | ||||
| 	const struct ltc_hash_descriptor *hash_desc; | ||||
| 	const unsigned char *name; | ||||
| }; | ||||
| 
 | ||||
| extern struct dropbear_ecc_curve ecc_curve_nistp256; | ||||
| @ -21,6 +21,7 @@ extern struct dropbear_ecc_curve ecc_curve_nistp521; | ||||
| extern struct dropbear_ecc_curve *dropbear_ecc_curves[]; | ||||
| 
 | ||||
| void dropbear_ecc_fill_dp(); | ||||
| struct dropbear_ecc_curve* curve_for_dp(const ltc_ecc_set_type *dp); | ||||
| 
 | ||||
| // "pubkey" refers to a point, but LTC uses ecc_key structure for both public
 | ||||
| // and private keys
 | ||||
|  | ||||
							
								
								
									
										320
									
								
								ecdsa.c
									
									
									
									
									
								
							
							
						
						
									
										320
									
								
								ecdsa.c
									
									
									
									
									
								
							| @ -2,6 +2,7 @@ | ||||
| #include "dbutil.h" | ||||
| #include "crypto_desc.h" | ||||
| #include "ecc.h" | ||||
| #include "ecdsa.h" | ||||
| 
 | ||||
| #ifdef DROPBEAR_ECDSA | ||||
| 
 | ||||
| @ -55,7 +56,7 @@ ecc_key *buf_get_ecdsa_pub_key(buffer* buf) { | ||||
| 
 | ||||
| 	// string   "ecdsa-sha2-[identifier]"
 | ||||
| 	key_ident = buf_getstring(buf, &key_ident_len); | ||||
| 	// string   "ecdsa-sha2-[identifier]"
 | ||||
| 	// string   "[identifier]"
 | ||||
| 	identifier = buf_getstring(buf, &identifier_len); | ||||
| 
 | ||||
| 	if (key_ident_len != identifier_len + strlen("ecdsa-sha2-")) { | ||||
| @ -68,7 +69,7 @@ ecc_key *buf_get_ecdsa_pub_key(buffer* buf) { | ||||
| 	} | ||||
| 
 | ||||
| 	for (curve = dropbear_ecc_curves; *curve; curve++) { | ||||
| 		if (memcmp(identifier, (*curve)->name, strlen((*curve)->name)) == 0) { | ||||
| 		if (memcmp(identifier, (char*)(*curve)->name, strlen((char*)(*curve)->name)) == 0) { | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| @ -82,12 +83,8 @@ ecc_key *buf_get_ecdsa_pub_key(buffer* buf) { | ||||
| 	new_key = buf_get_ecc_raw_pubkey(q_buf, *curve); | ||||
| 
 | ||||
| out: | ||||
| 	if (key_ident) { | ||||
| 		m_free(key_ident); | ||||
| 	} | ||||
| 	if (identifier) { | ||||
| 		m_free(identifier); | ||||
| 	} | ||||
| 	m_free(key_ident); | ||||
| 	m_free(identifier); | ||||
| 	if (q_buf) { | ||||
| 		buf_free(q_buf); | ||||
| 		q_buf = NULL; | ||||
| @ -96,5 +93,312 @@ out: | ||||
| 	return new_key; | ||||
| } | ||||
| 
 | ||||
| ecc_key *buf_get_ecdsa_priv_key(buffer *buf) { | ||||
| 	ecc_key *new_key = NULL; | ||||
| 	TRACE(("enter buf_get_ecdsa_priv_key")) | ||||
| 	new_key = buf_get_ecdsa_pub_key(buf); | ||||
| 	if (!new_key) { | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (buf_getmpint(buf, new_key->k) != DROPBEAR_SUCCESS) { | ||||
| 		ecc_free(new_key); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	return new_key; | ||||
| } | ||||
| 
 | ||||
| void buf_put_ecdsa_pub_key(buffer *buf, ecc_key *key) { | ||||
| 	struct dropbear_ecc_curve *curve = NULL; | ||||
| 	unsigned char key_ident[30]; | ||||
| 
 | ||||
| 	curve = curve_for_dp(key->dp); | ||||
| 	snprintf((char*)key_ident, sizeof(key_ident), "ecdsa-sha2-%s", curve->name); | ||||
| 	buf_putstring(buf, key_ident, strlen(key_ident)); | ||||
| 	buf_putstring(buf, curve->name, strlen(curve->name)); | ||||
| 	buf_put_ecc_raw_pubkey_string(buf, key); | ||||
| } | ||||
| 
 | ||||
| void buf_put_ecdsa_priv_key(buffer *buf, ecc_key *key) { | ||||
| 	buf_put_ecdsa_pub_key(buf, key); | ||||
| 	buf_putmpint(buf, key->k); | ||||
| } | ||||
| 
 | ||||
| void buf_put_ecdsa_sign(buffer *buf, ecc_key *key, buffer *data_buf) { | ||||
| 	/* Based on libtomcrypt's ecc_sign_hash but without the asn1 */ | ||||
| 	int err = DROPBEAR_FAILURE; | ||||
| 	struct dropbear_ecc_curve *curve = NULL; | ||||
| 	hash_state hs; | ||||
| 	unsigned char hash[64]; | ||||
| 	void *e = NULL, *p = NULL, *s = NULL, *r; | ||||
| 	unsigned char key_ident[30]; | ||||
| 	buffer *sigbuf = NULL; | ||||
| 
 | ||||
| 	TRACE(("buf_put_ecdsa_sign")) | ||||
| 	curve = curve_for_dp(key->dp); | ||||
| 
 | ||||
| 	if (ltc_init_multi(&r, &s, &p, &e, NULL) != CRYPT_OK) {  | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	curve->hash_desc->init(&hs); | ||||
| 	curve->hash_desc->process(&hs, data_buf->data, data_buf->len); | ||||
| 	curve->hash_desc->done(&hs, hash); | ||||
| 
 | ||||
| 	if (ltc_mp.unsigned_read(e, hash, curve->hash_desc->hashsize) != CRYPT_OK) { | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ltc_mp.read_radix(p, (char *)key->dp->order, 16) != CRYPT_OK) {  | ||||
| 		goto out;  | ||||
| 	} | ||||
| 
 | ||||
| 	for (;;) { | ||||
| 		ecc_key R_key; // ephemeral key
 | ||||
| 		if (ecc_make_key_ex(NULL, dropbear_ltc_prng, &R_key, key->dp) != CRYPT_OK) { | ||||
| 			goto out; | ||||
| 		} | ||||
| 		if (ltc_mp.mpdiv(R_key.pubkey.x, p, NULL, r) != CRYPT_OK) { | ||||
| 			goto out; | ||||
| 		} | ||||
| 		if (ltc_mp.compare_d(r, 0) == LTC_MP_EQ) { | ||||
| 			// try again
 | ||||
| 			ecc_free(&R_key); | ||||
| 			continue; | ||||
| 		} | ||||
| 		/* k = 1/k */ | ||||
| 		if (ltc_mp.invmod(R_key.k, p, R_key.k) != CRYPT_OK) { | ||||
| 			goto out; | ||||
| 		} | ||||
| 		/* s = xr */ | ||||
| 		if (ltc_mp.mulmod(key->k, r, p, s) != CRYPT_OK) { | ||||
| 			goto out; | ||||
| 		} | ||||
| 		/* s = e +  xr */ | ||||
| 		if (ltc_mp.add(e, s, s) != CRYPT_OK) { | ||||
| 			goto out; | ||||
| 		} | ||||
| 		if (ltc_mp.mpdiv(s, p, NULL, s) != CRYPT_OK) { | ||||
| 			goto out; | ||||
| 		} | ||||
| 		/* s = (e + xr)/k */ | ||||
| 		if (ltc_mp.mulmod(s, R_key.k, p, s) != CRYPT_OK) { | ||||
| 			goto out; | ||||
| 		} | ||||
| 		ecc_free(&R_key); | ||||
| 
 | ||||
| 		if (ltc_mp.compare_d(s, 0) != LTC_MP_EQ) { | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	snprintf((char*)key_ident, sizeof(key_ident), "ecdsa-sha2-%s", curve->name); | ||||
| 	buf_putstring(buf, key_ident, strlen(key_ident)); | ||||
| 	// enough for nistp521
 | ||||
| 	sigbuf = buf_new(200); | ||||
| 	buf_putmpint(sigbuf, (mp_int*)r); | ||||
| 	buf_putmpint(sigbuf, (mp_int*)s); | ||||
| 	buf_putbufstring(buf, sigbuf); | ||||
| 
 | ||||
| 	err = DROPBEAR_SUCCESS; | ||||
| 
 | ||||
| out: | ||||
| 	if (r && s && p && e) { | ||||
| 		ltc_deinit_multi(r, s, p, e, NULL); | ||||
| 	} | ||||
| 
 | ||||
| 	if (sigbuf) { | ||||
| 		buf_free(sigbuf); | ||||
| 	} | ||||
| 
 | ||||
| 	if (err == DROPBEAR_FAILURE) { | ||||
| 		dropbear_exit("ECC error"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // returns values in s and r
 | ||||
| // returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE
 | ||||
| static int buf_get_ecdsa_verify_params(buffer *buf, struct dropbear_ecc_curve *curve, | ||||
| 	void *r, void* s) { | ||||
| 	int ret = DROPBEAR_FAILURE; | ||||
| 	unsigned char* ident = NULL; | ||||
| 	unsigned int ident_len; | ||||
| 	unsigned int sig_len; | ||||
| 	unsigned int sig_pos; | ||||
| 	unsigned char key_ident[30]; | ||||
| 
 | ||||
| 	ident = buf_getstring(buf, &ident_len); | ||||
| 	snprintf((char*)key_ident, sizeof(key_ident), "ecdsa-sha2-%s", curve->name); | ||||
| 	if (strlen((char*)key_ident) != ident_len) { | ||||
| 		goto out; | ||||
| 	} | ||||
| 	if (memcmp(key_ident, ident, ident_len) != 0) { | ||||
| 		goto out; | ||||
| 	} | ||||
| 	sig_len = buf_getint(buf); | ||||
| 	sig_pos = buf->pos; | ||||
| 	if (buf_getmpint(buf, r) != DROPBEAR_SUCCESS) { | ||||
| 		goto out; | ||||
| 	} | ||||
| 	if (buf_getmpint(buf, s) != DROPBEAR_SUCCESS) { | ||||
| 		goto out; | ||||
| 	} | ||||
| 	if (buf->pos - sig_pos != sig_len) { | ||||
| 		goto out; | ||||
| 	} | ||||
| 	ret = DROPBEAR_SUCCESS; | ||||
| 
 | ||||
| out: | ||||
| 	m_free(ident); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int buf_ecdsa_verify(buffer *buf, ecc_key *key, buffer *data_buf) { | ||||
| 	/* Based on libtomcrypt's ecc_verify_hash but without the asn1 */ | ||||
| 	int ret = DROPBEAR_FAILURE; | ||||
| 	hash_state hs; | ||||
| 	struct dropbear_ecc_curve *curve = NULL; | ||||
| 	unsigned char hash[64]; | ||||
| 	ecc_point *mG = NULL, *mQ = NULL; | ||||
| 	void *r = NULL, *s = NULL, *v = NULL, *w = NULL, *u1 = NULL, *u2 = NULL,  | ||||
| 		*e = NULL, *p = NULL, *m = NULL; | ||||
| 	void *mp = NULL; | ||||
| 
 | ||||
| 	/* verify 
 | ||||
| 	 * | ||||
| 	 * w  = s^-1 mod n | ||||
| 	 * u1 = xw  | ||||
| 	 * u2 = rw | ||||
| 	 * X = u1*G + u2*Q | ||||
| 	 * v = X_x1 mod n | ||||
| 	 * accept if v == r | ||||
| 	 */ | ||||
| 
 | ||||
| 	TRACE(("buf_ecdsa_verify")) | ||||
| 	curve = curve_for_dp(key->dp); | ||||
| 
 | ||||
| 	mG = ltc_ecc_new_point(); | ||||
| 	mQ = ltc_ecc_new_point(); | ||||
| 	if (ltc_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL) != CRYPT_OK | ||||
| 		|| !mG | ||||
| 		|| !mQ) { | ||||
| 		dropbear_exit("ECC error"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (buf_get_ecdsa_verify_params(buf, curve, r, s) != DROPBEAR_SUCCESS) { | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	curve->hash_desc->init(&hs); | ||||
| 	curve->hash_desc->process(&hs, data_buf->data, data_buf->len); | ||||
| 	curve->hash_desc->done(&hs, hash); | ||||
| 
 | ||||
| 	if (ltc_mp.unsigned_read(e, hash, curve->hash_desc->hashsize) != CRYPT_OK) { | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
|    /* get the order */ | ||||
| 	if (ltc_mp.read_radix(p, (char *)key->dp->order, 16) != CRYPT_OK) {  | ||||
| 		goto out;  | ||||
| 	} | ||||
| 
 | ||||
|    /* get the modulus */ | ||||
| 	if (ltc_mp.read_radix(m, (char *)key->dp->prime, 16) != CRYPT_OK) {  | ||||
| 		goto out;  | ||||
| 	} | ||||
| 
 | ||||
|    /* check for zero */ | ||||
| 	if (ltc_mp.compare_d(r, 0) == LTC_MP_EQ  | ||||
| 		|| ltc_mp.compare_d(s, 0) == LTC_MP_EQ  | ||||
| 		|| ltc_mp.compare(r, p) != LTC_MP_LT  | ||||
| 		|| ltc_mp.compare(s, p) != LTC_MP_LT) { | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
|    /*  w  = s^-1 mod n */ | ||||
| 	if (ltc_mp.invmod(s, p, w) != CRYPT_OK) {  | ||||
| 		goto out;  | ||||
| 	} | ||||
| 
 | ||||
|    /* u1 = ew */ | ||||
| 	if (ltc_mp.mulmod(e, w, p, u1) != CRYPT_OK) {  | ||||
| 		goto out;  | ||||
| 	} | ||||
| 
 | ||||
|    /* u2 = rw */ | ||||
| 	if (ltc_mp.mulmod(r, w, p, u2) != CRYPT_OK) {  | ||||
| 		goto out;  | ||||
| 	} | ||||
| 
 | ||||
|    /* find mG and mQ */ | ||||
| 	if (ltc_mp.read_radix(mG->x, (char *)key->dp->Gx, 16) != CRYPT_OK) {  | ||||
| 		goto out;  | ||||
| 	} | ||||
| 	if (ltc_mp.read_radix(mG->y, (char *)key->dp->Gy, 16) != CRYPT_OK) {  | ||||
| 		goto out;  | ||||
| 	} | ||||
| 	if (ltc_mp.set_int(mG->z, 1) != CRYPT_OK) {  | ||||
| 		goto out;  | ||||
| 	} | ||||
| 
 | ||||
| 	if (ltc_mp.copy(key->pubkey.x, mQ->x) != CRYPT_OK | ||||
| 		|| ltc_mp.copy(key->pubkey.y, mQ->y) != CRYPT_OK | ||||
| 		|| ltc_mp.copy(key->pubkey.z, mQ->z) != CRYPT_OK) {  | ||||
| 		goto out;  | ||||
| 	} | ||||
| 
 | ||||
|    /* compute u1*mG + u2*mQ = mG */ | ||||
| 	if (ltc_mp.ecc_mul2add == NULL) { | ||||
| 		if (ltc_mp.ecc_ptmul(u1, mG, mG, m, 0) != CRYPT_OK) {  | ||||
| 			goto out;  | ||||
| 		} | ||||
| 		if (ltc_mp.ecc_ptmul(u2, mQ, mQ, m, 0) != CRYPT_OK) { | ||||
| 			goto out;  | ||||
| 		} | ||||
| 
 | ||||
| 		/* find the montgomery mp */ | ||||
| 		if (ltc_mp.montgomery_setup(m, &mp) != CRYPT_OK) {  | ||||
| 			goto out;  | ||||
| 		} | ||||
| 
 | ||||
| 		/* add them */ | ||||
| 		if (ltc_mp.ecc_ptadd(mQ, mG, mG, m, mp) != CRYPT_OK) {  | ||||
| 			goto out;  | ||||
| 		} | ||||
| 
 | ||||
|     	/* reduce */ | ||||
| 		if (ltc_mp.ecc_map(mG, m, mp) != CRYPT_OK) {  | ||||
| 			goto out;  | ||||
| 		} | ||||
| 	} else { | ||||
|       /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */ | ||||
| 		if (ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, m) != CRYPT_OK) {  | ||||
| 			goto out;  | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|    /* v = X_x1 mod n */ | ||||
| 	if (ltc_mp.mpdiv(mG->x, p, NULL, v) != CRYPT_OK) {  | ||||
| 		goto out;  | ||||
| 	} | ||||
| 
 | ||||
|    /* does v == r */ | ||||
| 	if (ltc_mp.compare(v, r) == LTC_MP_EQ) { | ||||
| 		ret = DROPBEAR_SUCCESS; | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	ltc_ecc_del_point(mG); | ||||
| 	ltc_ecc_del_point(mQ); | ||||
| 	mp_clear_multi(r, s, v, w, u1, u2, p, e, m, NULL); | ||||
| 	if (mp != NULL) {  | ||||
| 		ltc_mp.montgomery_deinit(mp); | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #endif // DROPBEAR_ECDSA
 | ||||
|  | ||||
							
								
								
									
										16
									
								
								ecdsa.h
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								ecdsa.h
									
									
									
									
									
								
							| @ -0,0 +1,16 @@ | ||||
| #ifndef _ECDSA_H_ | ||||
| #define _ECDSA_H_ | ||||
| 
 | ||||
| #include "includes.h" | ||||
| #include "buffer.h" | ||||
| 
 | ||||
| ecc_key *gen_ecdsa_priv_key(unsigned int bit_size); | ||||
| ecc_key *buf_get_ecdsa_pub_key(buffer* buf); | ||||
| ecc_key *buf_get_ecdsa_priv_key(buffer *buf); | ||||
| void buf_put_ecdsa_pub_key(buffer *buf, ecc_key *key); | ||||
| void buf_put_ecdsa_priv_key(buffer *buf, ecc_key *key); | ||||
| 
 | ||||
| void buf_put_ecdsa_sign(buffer *buf, ecc_key *key, buffer *data_buf); | ||||
| int buf_ecdsa_verify(buffer *buf, ecc_key *key, buffer *data_buf); | ||||
| 
 | ||||
| #endif // _ECDSA_H_
 | ||||
| @ -349,7 +349,7 @@ struct mpint_pos { void *start; int bytes; }; | ||||
|  * Code to read and write OpenSSH private keys. | ||||
|  */ | ||||
| 
 | ||||
| enum { OSSH_DSA, OSSH_RSA }; | ||||
| enum { OSSH_DSA, OSSH_RSA, OSSH_EC }; | ||||
| struct openssh_key { | ||||
| 	int type; | ||||
| 	int encrypted; | ||||
| @ -392,6 +392,8 @@ static struct openssh_key *load_openssh_key(const char *filename) | ||||
| 		ret->type = OSSH_RSA; | ||||
| 	else if (!strcmp(buffer, "-----BEGIN DSA PRIVATE KEY-----\n")) | ||||
| 		ret->type = OSSH_DSA; | ||||
| 	else if (!strcmp(buffer, "-----BEGIN EC PRIVATE KEY-----\n")) | ||||
| 		ret->type = OSSH_EC; | ||||
| 	else { | ||||
| 		errmsg = "Unrecognised key type"; | ||||
| 		goto error; | ||||
|  | ||||
| @ -138,6 +138,8 @@ | ||||
| 
 | ||||
| #ifdef DROPBEAR_ECC | ||||
| #define MECC | ||||
| #define LTC_ECC_SHAMIR | ||||
| #define LTC_ECC_TIMING_RESISTANT | ||||
| #define MPI | ||||
| #define LTM_DESC | ||||
| #ifdef DROPBEAR_ECC_256 | ||||
|  | ||||
| @ -34,13 +34,6 @@ sign_key * new_sign_key() { | ||||
| 	sign_key * ret; | ||||
| 
 | ||||
| 	ret = (sign_key*)m_malloc(sizeof(sign_key)); | ||||
| #ifdef DROPBEAR_DSS | ||||
| 	ret->dsskey = NULL; | ||||
| #endif | ||||
| #ifdef DROPBEAR_RSA | ||||
| 	ret->rsakey = NULL; | ||||
| #endif | ||||
| 	ret->filename = NULL; | ||||
| 	ret->type = DROPBEAR_SIGNKEY_NONE; | ||||
| 	ret->source = SIGNKEY_SOURCE_INVALID; | ||||
| 	return ret; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user