changeset 807:75509065db53 ecc

have separate ecdsa keys for each size fix crash from the mp_alloc_init_multi change in RSA
author Matt Johnston <matt@ucc.asn.au>
date Sat, 25 May 2013 00:54:19 +0800
parents 71e7d31f7671
children 4095b6d7c9fc d7d9f1612d51
files dropbearkey.c keyimport.c rsa.c signkey.c signkey.h svr-runopts.c
diffstat 6 files changed, 120 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/dropbearkey.c	Thu May 23 22:18:33 2013 +0800
+++ b/dropbearkey.c	Sat May 25 00:54:19 2013 +0800
@@ -266,8 +266,11 @@
 #endif
 #ifdef DROPBEAR_ECDSA
 		case DROPBEAR_SIGNKEY_ECDSA_KEYGEN:
-			key->ecckey = gen_ecdsa_priv_key(bits);
-			keytype = ecdsa_signkey_type(key->ecckey);
+			{
+				ecc_key *ecckey = gen_ecdsa_priv_key(bits);
+				keytype = ecdsa_signkey_type(ecckey);
+				*signkey_ecc_key_ptr(key, keytype) = ecckey;
+			}
 			break;
 #endif
 		default:
--- a/keyimport.c	Thu May 23 22:18:33 2013 +0800
+++ b/keyimport.c	Sat May 25 00:54:19 2013 +0800
@@ -680,7 +680,7 @@
 		int private_key_len = 0;
 		unsigned char* public_key_bytes = NULL;
 		int public_key_len = 0;
-		ecc_key *ecc;
+		ecc_key *ecc = NULL;
 		const struct dropbear_ecc_curve *curve = NULL;
 
 		// See SEC1 v2, Appendix C.4
@@ -774,7 +774,7 @@
 			goto error;
 		}
 
-		retkey->ecckey = ecc;
+		*signkey_ecc_key_ptr(retkey, retkey->type) = ecc;
 	}
 #endif // DROPBEAR_ECDSA
 
--- a/rsa.c	Thu May 23 22:18:33 2013 +0800
+++ b/rsa.c	Sat May 25 00:54:19 2013 +0800
@@ -96,7 +96,7 @@
 	key->p = NULL;
 	key->q = NULL;
 
-	m_mp_alloc_init_multi(&key->d);
+	m_mp_alloc_init_multi(&key->d, NULL);
 	if (buf_getmpint(buf, key->d) == DROPBEAR_FAILURE) {
 		TRACE(("leave buf_get_rsa_priv_key: d: ret == DROPBEAR_FAILURE"))
 	    goto out;
--- a/signkey.c	Thu May 23 22:18:33 2013 +0800
+++ b/signkey.c	Sat May 25 00:54:19 2013 +0800
@@ -103,6 +103,22 @@
 	return DROPBEAR_SIGNKEY_NONE;
 }
 
+#ifdef DROPBEAR_ECDSA
+ecc_key **
+signkey_ecc_key_ptr(sign_key *key, enum signkey_type ecc_type) {
+	switch (ecc_type) {
+		case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
+			return &key->ecckey256;
+		case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
+			return &key->ecckey384;
+		case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
+			return &key->ecckey521;
+		default:
+			return NULL;
+	}
+}
+#endif
+
 /* returns DROPBEAR_SUCCESS on success, DROPBEAR_FAILURE on fail.
  * type should be set by the caller to specify the type to read, and
  * on return is set to the type read (useful when type = _ANY) */
@@ -152,13 +168,17 @@
 	}
 #endif
 #ifdef DROPBEAR_ECDSA
-	if (IS_ECDSA_KEY(keytype)) {
-		if (key->ecckey) {
-			ecc_free(key->ecckey);
-		}
-		key->ecckey = buf_get_ecdsa_pub_key(buf);
-		if (key->ecckey) {
-			ret = DROPBEAR_SUCCESS;
+	{
+		ecc_key **eck = signkey_ecc_key_ptr(key, keytype);
+		if (eck) {
+			if (*eck) {
+				ecc_free(*eck);
+				*eck = NULL;
+			}
+			*eck = buf_get_ecdsa_pub_key(buf);
+			if (*eck) {
+				ret = DROPBEAR_SUCCESS;
+			}
 		}
 	}
 #endif
@@ -216,13 +236,17 @@
 	}
 #endif
 #ifdef DROPBEAR_ECDSA
-	if (IS_ECDSA_KEY(keytype)) {
-		if (key->ecckey) {
-			ecc_free(key->ecckey);
-		}
-		key->ecckey = buf_get_ecdsa_priv_key(buf);
-		if (key->ecckey) {
-			ret = DROPBEAR_SUCCESS;
+	{
+		ecc_key **eck = signkey_ecc_key_ptr(key, keytype);
+		if (eck) {
+			if (*eck) {
+				ecc_free(*eck);
+				*eck = NULL;
+			}
+			*eck = buf_get_ecdsa_priv_key(buf);
+			if (*eck) {
+				ret = DROPBEAR_SUCCESS;
+			}
 		}
 	}
 #endif
@@ -252,8 +276,11 @@
 	}
 #endif
 #ifdef DROPBEAR_ECDSA
-	if (IS_ECDSA_KEY(type)) {
-		buf_put_ecdsa_pub_key(pubkeys, key->ecckey);
+	{
+		ecc_key **eck = signkey_ecc_key_ptr(key, type);
+		if (eck) {
+			buf_put_ecdsa_pub_key(pubkeys, *eck);
+		}
 	}
 #endif
 	if (pubkeys->len == 0) {
@@ -286,9 +313,13 @@
 	}
 #endif
 #ifdef DROPBEAR_ECDSA
-	if (IS_ECDSA_KEY(type)) {
-		buf_put_ecdsa_priv_key(buf, key->ecckey);
-		return;
+	{
+		ecc_key **eck = signkey_ecc_key_ptr(key, type);
+		if (eck) {
+			buf_put_ecdsa_priv_key(buf, *eck);
+			TRACE(("leave buf_put_priv_key: ecdsa done"))
+			return;
+		}
 	}
 #endif
 	dropbear_exit("Bad key types in put pub key");
@@ -307,9 +338,17 @@
 	key->rsakey = NULL;
 #endif
 #ifdef DROPBEAR_ECDSA
-	if (key->ecckey) {
-		ecc_free(key->ecckey);
-		key->ecckey = NULL;
+	if (key->ecckey256) {
+		ecc_free(key->ecckey256);
+		key->ecckey256 = NULL;
+	}
+	if (key->ecckey384) {
+		ecc_free(key->ecckey384);
+		key->ecckey384 = NULL;
+	}
+	if (key->ecckey521) {
+		ecc_free(key->ecckey521);
+		key->ecckey521 = NULL;
 	}
 #endif
 
@@ -429,8 +468,11 @@
 	}
 #endif
 #ifdef DROPBEAR_ECDSA
-	if (IS_ECDSA_KEY(type)) {
-		buf_put_ecdsa_sign(sigblob, key->ecckey, data_buf);
+	{
+		ecc_key **eck = signkey_ecc_key_ptr(key, type);
+		if (eck) {
+			buf_put_ecdsa_sign(sigblob, *eck, data_buf);
+		}
 	}
 #endif
 	if (sigblob->len == 0) {
@@ -477,8 +519,11 @@
 	}
 #endif
 #ifdef DROPBEAR_ECDSA
-	if (IS_ECDSA_KEY(type)) {
-		return buf_ecdsa_verify(buf, key->ecckey, data_buf);
+	{
+		ecc_key **eck = signkey_ecc_key_ptr(key, type);
+		if (eck) {
+			return buf_ecdsa_verify(buf, *eck, data_buf);
+		}
 	}
 #endif
 
--- a/signkey.h	Thu May 23 22:18:33 2013 +0800
+++ b/signkey.h	Sat May 25 00:54:19 2013 +0800
@@ -68,7 +68,15 @@
 	dropbear_rsa_key * rsakey;
 #endif
 #ifdef DROPBEAR_ECDSA
-	ecc_key * ecckey;
+#ifdef DROPBEAR_ECC_256
+	ecc_key * ecckey256;
+#endif
+#ifdef DROPBEAR_ECC_384
+	ecc_key * ecckey384;
+#endif
+#ifdef DROPBEAR_ECC_521
+	ecc_key * ecckey521;
+#endif
 #endif
 };
 
@@ -92,11 +100,7 @@
 					buffer * line, char ** fingerprint);
 
 #ifdef DROPBEAR_ECDSA
-#define IS_ECDSA_KEY(type) \
-	((type) == DROPBEAR_SIGNKEY_ECDSA_NISTP256 \
-		|| (type) == DROPBEAR_SIGNKEY_ECDSA_NISTP384 \
-		|| (type) == DROPBEAR_SIGNKEY_ECDSA_NISTP521 \
-		|| (type) == DROPBEAR_SIGNKEY_ECDSA_KEYGEN)
+ecc_key ** signkey_ecc_key_ptr(sign_key *key, enum signkey_type ecc_type);
 #endif
 
 #endif /* _SIGNKEY_H_ */
--- a/svr-runopts.c	Thu May 23 22:18:33 2013 +0800
+++ b/svr-runopts.c	Sat May 25 00:54:19 2013 +0800
@@ -375,6 +375,18 @@
 	}
 }
 
+static void loadhostkey_helper(const char *name, void** src, void** dst, int fatal_duplicate) {
+	if (*dst) {
+		if (fatal_duplicate) {
+			dropbear_exit("Only one %s key can be specified", name);
+		}
+	} else {
+		*dst = *src;
+		*src = NULL;
+	}
+
+}
+
 /* Must be called after syslog/etc is working */
 static void loadhostkey(const char *keyfile, int fatal_duplicate) {
 	sign_key * read_key = new_sign_key();
@@ -385,42 +397,33 @@
 
 #ifdef DROPBEAR_RSA
 	if (type == DROPBEAR_SIGNKEY_RSA) {
-		if (svr_opts.hostkey->rsakey) {
-			if (fatal_duplicate) {
-				dropbear_exit("Only one RSA key can be specified");
-			}
-		} else {
-			svr_opts.hostkey->rsakey = read_key->rsakey;
-			read_key->rsakey = NULL;
-		}
+		loadhostkey_helper("RSA", &read_key->rsakey, &svr_opts.hostkey->rsakey, fatal_duplicate);
 	}
 #endif
 
 #ifdef DROPBEAR_DSS
 	if (type == DROPBEAR_SIGNKEY_DSS) {
-		if (svr_opts.hostkey->dsskey) {
-			if (fatal_duplicate) {
-				dropbear_exit("Only one DSS key can be specified");
-			}
-		} else {
-			svr_opts.hostkey->dsskey = read_key->dsskey;
-			read_key->dsskey = NULL;
-		}
+		loadhostkey_helper("DSS", &read_key->dsskey, &svr_opts.hostkey->dsskey, fatal_duplicate);
 	}
 #endif
 
 #ifdef DROPBEAR_ECDSA
-	if (IS_ECDSA_KEY(type)) {
-		if (svr_opts.hostkey->ecckey) {
-			if (fatal_duplicate) {
-				dropbear_exit("Only one ECDSA key can be specified");
-			}
-		} else {
-			svr_opts.hostkey->ecckey = read_key->ecckey;
-			read_key->ecckey = NULL;
-		}
+#ifdef DROPBEAR_ECC_256
+	if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP256) {
+		loadhostkey_helper("ECDSA256", &read_key->ecckey256, &svr_opts.hostkey->ecckey256, fatal_duplicate);
 	}
 #endif
+#ifdef DROPBEAR_ECC_384
+	if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP384) {
+		loadhostkey_helper("ECDSA384", &read_key->ecckey384, &svr_opts.hostkey->ecckey384, fatal_duplicate);
+	}
+#endif
+#ifdef DROPBEAR_ECC_521
+	if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP521) {
+		loadhostkey_helper("ECDSA521", &read_key->ecckey521, &svr_opts.hostkey->ecckey521, fatal_duplicate);
+	}
+#endif
+#endif // DROPBEAR_ECDSA
 	sign_key_free(read_key);
 	TRACE(("leave loadhostkey"))
 }
@@ -468,20 +471,17 @@
 #endif
 #ifdef DROPBEAR_ECDSA
 #ifdef DROPBEAR_ECC_256
-	if (!svr_opts.hostkey->ecckey 
-		|| ecdsa_signkey_type(svr_opts.hostkey->ecckey) != DROPBEAR_SIGNKEY_ECDSA_NISTP256) {
+	if (!svr_opts.hostkey->ecckey256) {
 		disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP256);
 	}
 #endif
 #ifdef DROPBEAR_ECC_384
-	if (!svr_opts.hostkey->ecckey 
-		|| ecdsa_signkey_type(svr_opts.hostkey->ecckey) != DROPBEAR_SIGNKEY_ECDSA_NISTP384) {
+	if (!svr_opts.hostkey->ecckey384) {
 		disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP384);
 	}
 #endif
 #ifdef DROPBEAR_ECC_521
-	if (!svr_opts.hostkey->ecckey 
-		|| ecdsa_signkey_type(svr_opts.hostkey->ecckey) != DROPBEAR_SIGNKEY_ECDSA_NISTP521) {
+	if (!svr_opts.hostkey->ecckey521) {
 		disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP521);
 	}
 #endif