From cf7a271f90c2cc6970a02264a6dca9799984d3c6 Mon Sep 17 00:00:00 2001
From: Matt Johnston <matt@ucc.asn.au>
Date: Wed, 27 Mar 2013 23:50:52 +0800
Subject: [PATCH] ecc key import function

--HG--
branch : ecc
---
 common-kex.c |  7 +++--
 ecc.c        | 79 ++++++++++++++++++++++++++++++++++++++++++++--------
 ecc.h        |  2 +-
 3 files changed, 73 insertions(+), 15 deletions(-)

diff --git a/common-kex.c b/common-kex.c
index 5d46f793..aa4c3a42 100644
--- a/common-kex.c
+++ b/common-kex.c
@@ -678,10 +678,11 @@ void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them,
 	// public keys from client and server
 	ecc_key *Q_C, *Q_S, *Q_them;
 
-	// XXX load Q_them
+oj	// XXX load Q_them
+	Q_them = buf_get_ecc_key_string()
+
+	ses.dh_K = dropbear_ecc_shared_secret();
 
-	ses.dh_K = dropbear_ecc_shared_secret()
-	
 	/* Check that dh_pub_them (dh_e or dh_f) is in the range [1, p-1] */
 	if (mp_cmp(dh_pub_them, &dh_p) != MP_LT 
 			|| mp_cmp_d(dh_pub_them, 0) != MP_GT) {
diff --git a/ecc.c b/ecc.c
index 873a92ac..0172516c 100644
--- a/ecc.c
+++ b/ecc.c
@@ -4,9 +4,11 @@
 
 #ifdef DROPBEAR_ECC
 
+// TODO: use raw bytes for the dp rather than the hex strings in libtomcrypt's ecc.c
+
 #ifdef DROPBEAR_ECC_256
-const struct ecc_curve_secp256r1 {
-	.ltc_set = &ltc_ecc_sets[0],
+const struct dropbear_ecc_curve ecc_curve_secp256r1 {
+	.dp = &ltc_ecc_sets[0],
 	.hash_desc = sha256_desc,
 	.name = "secp256r1"
 };
@@ -14,23 +16,23 @@ const struct ecc_curve_secp256r1 {
 
 
 #ifdef DROPBEAR_ECC_384
-const struct ecc_curve_secp384r1 {
-	.ltc_set = &ltc_ecc_sets[1],
+const struct dropbear_ecc_curve ecc_curve_secp384r1 {
+	.dp = &ltc_ecc_sets[1],
 	.hash_desc = sha384_desc,
 	.name = "secp384r1"
 };
 #endif
 
-#ifdef DROPBEAR_ECC_256
-const struct ecc_curve_secp256r1 {
-	.ltc_set = &ltc_ecc_sets[0],
-	.hash_desc = sha256_desc,
-	.name = "secp256r1"
+#ifdef DROPBEAR_ECC_521
+const struct dropbear_ecc_curve ecc_curve_secp521r1 {
+	.dp = &ltc_ecc_sets[2],
+	.hash_desc = sha521_desc,
+	.name = "secp521r1"
 };
 #endif
 
 
-void buf_put_ecc_key_string(buffer *buf, ecc_key *key) {
+void buf_put_ecc_pubkey_string(buffer *buf, ecc_key *key) {
 	// XXX point compression
 	int len = key->dp->size*2 + 1;
 	buf_putint(len);
@@ -41,7 +43,62 @@ void buf_put_ecc_key_string(buffer *buf, ecc_key *key) {
 	buf_incrwritepos(buf, len);
 }
 
-int buf_get_ecc_key_string(buffer *buf, ecc_key *key) {
+ecc_key * buf_get_ecc_key_string(buffer *buf, const struct dropbear_ecc_curve *curve) {
+   ecc_key *key = NULL;
+   int ret = DROPBEAR_FAILURE;
+   const int size = curve->dp->size;
+   unsigned int len = buf_get_string(buf);
+   unsigned char first = buf_get_char(buf);
+   if (first == 2 || first == 3) {
+      dropbear_log("Dropbear doesn't support ECC point compression");
+      return NULL;
+   }
+   if (first != 4 || len != 1+2*size) {
+      return NULL;
+   }
+
+   key = m_malloc(sizeof(*key));
+   m_mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL);
+
+   if (mp_read_unsigned_bin(&key->pubkey.x, buf_getptr(buf, size), size) != MP_OKAY) {
+      goto out;
+   }
+   buf_incrpos(buf, size);
+
+   if (mp_read_unsigned_bin(&key->pubkey.y, buf_getptr(buf, size), size) != MP_OKAY) {
+      goto out;
+   }
+   buf_incrpos(buf, size);
+
+   if (mp_set(key->pubkey.z, 1) != MP_OKAY) {
+      goto out;
+   }
+
+   if (is_point(key) != CRYPT_OK) {
+      goto out;
+   }
+
+   // SEC1 3.2.3.1 Check that Q != 0
+   if (mp_cmp_d(key->pubkey.x, 0) == LTC_MP_EQ) {
+      goto out;
+   }
+   if (mp_cmp_d(key->pubkey.y, 0) == LTC_MP_EQ) {
+      goto out;
+   }
+
+   ret = DROPBEAR_SUCCESS;
+
+out:
+   if (ret == DROPBEAR_FAILURE) {
+      if (key) {
+         mp_free_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL);
+         m_free(key);
+         key = NULL;
+      }
+   }
+
+   return key;
+
 }
 
 // a modified version of libtomcrypt's "ecc_shared_secret" to output
diff --git a/ecc.h b/ecc.h
index 426f698d..019282d9 100644
--- a/ecc.h
+++ b/ecc.h
@@ -9,7 +9,7 @@
 #ifdef DROPBEAR_ECC
 
 struct dropbear_ecc_curve {
-	const ltc_ecc_set_type* ltc_set;
+	const ltc_ecc_set_type *dp; // curve domain parameters
 	const struct ltc_hash_descriptor *hash_desc;
 	const char *name;
 };
-- 
GitLab