summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2013-03-26 01:35:22 +0800
committerMatt Johnston <matt@ucc.asn.au>2013-03-26 01:35:22 +0800
commitb50dd9f0f8dd451095401901f441dfe1ff1d8bf4 (patch)
tree3c1be68d7fc5e0a76314efc76b6c1b60604236d6
parent97c2588e7f15ecbd92d08d7c29e65bad76aef344 (diff)
downloaddropbear-b50dd9f0f8dd451095401901f441dfe1ff1d8bf4.tar.gz
refactor kexdh code a bit, start working on ecdh etc
-rw-r--r--Makefile.in2
-rw-r--r--algo.h18
-rw-r--r--cli-kex.c44
-rw-r--r--common-algo.c1
-rw-r--r--common-kex.c41
-rw-r--r--configure.ac2
-rw-r--r--ecc.c17
-rw-r--r--kex.h24
-rw-r--r--libtomcrypt/src/headers/tomcrypt_custom.h7
-rw-r--r--ltc_prng.c136
-rw-r--r--options.h2
-rw-r--r--random.c9
-rw-r--r--random.h2
-rw-r--r--session.h10
-rw-r--r--svr-kex.c54
-rw-r--r--sysoptions.h19
16 files changed, 320 insertions, 68 deletions
diff --git a/Makefile.in b/Makefile.in
index cec35f1..4eabd20 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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 \
diff --git a/algo.h b/algo.h
index ad57037..89d05e3 100644
--- a/algo.h
+++ b/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_ */
diff --git a/cli-kex.c b/cli-kex.c
index 9dadb3c..ddd2efc 100644
--- a/cli-kex.c
+++ b/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 (buf_getmpint(ses.payload, &dh_f) != DROPBEAR_SUCCESS) {
- TRACE(("failed getting mpint"))
- 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);
- 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);
+ kexdh_comb_key(cli_ses.dh_param, &dh_f, hostkey);
+ mp_clear(&dh_f);
+ 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) {
diff --git a/common-algo.c b/common-algo.c
index 4a14651..91d27b2 100644
--- a/common-algo.c
+++ b/common-algo.c
@@ -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}
diff --git a/common-kex.c b/common-kex.c
index 56b206d..c153c8f 100644
--- a/common-kex.c
+++ b/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.
* 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);
DEF_MP_INT(dh_g);
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(&param->pub, &param->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, &param->priv) != MP_OKAY) {
dropbear_exit("Diffie-Hellman error");
}
- if (mp_div_2(dh_priv, &dh_q) != MP_OKAY) {
+ if (mp_div_2(&param->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, &param->priv);
/* f = g^y mod p */
- if (mp_exptmod(&dh_g, dh_priv, &dh_p, dh_pub) != MP_OKAY) {
+ if (mp_exptmod(&dh_g, &param->priv, &dh_p, &param->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(&param->pub, &param->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, &param->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 = &param->pub;
dh_f = dh_pub_them;
} else {
dh_e = dh_pub_them;
- dh_f = dh_pub_us;
+ dh_f = &param->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, &param->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() {
diff --git a/configure.ac b/configure.ac
index 3b82bb7..d3d30b4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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)
diff --git a/ecc.c b/ecc.c
new file mode 100644
index 0000000..cf67ec0
--- /dev/null
+++ b/ecc.c
@@ -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
diff --git a/kex.h b/kex.h
index c89b0a3..f9d70b8 100644
--- a/kex.h
+++ b/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_ */
diff --git a/libtomcrypt/src/headers/tomcrypt_custom.h b/libtomcrypt/src/headers/tomcrypt_custom.h
index acc149a..1304ce7 100644
--- a/libtomcrypt/src/headers/tomcrypt_custom.h
+++ b/libtomcrypt/src/headers/tomcrypt_custom.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
diff --git a/ltc_prng.c b/ltc_prng.c
new file mode 100644
index 0000000..cfd98fc
--- /dev/null
+++ b/ltc_prng.c
@@ -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
diff --git a/options.h b/options.h
index c52d6c2..4c42c02 100644
--- a/options.h
+++ b/options.h
@@ -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. */
diff --git a/random.c b/random.c
index 0378e9a..20095aa 100644
--- a/random.c
+++ b/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;
diff --git a/random.h b/random.h
index 544e77e..4042757 100644
--- a/random.h
+++ b/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_ */
diff --git a/session.h b/session.h
index 0719e34..145f695 100644
--- a/session.h
+++ b/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 */
diff --git a/svr-kex.c b/svr-kex.c
index abd7986..e30a2d4 100644
--- a/svr-kex.c
+++ b/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");
}
- m_mp_init(&dh_e);
- if (buf_getmpint(ses.payload, &dh_e) != DROPBEAR_SUCCESS) {
- dropbear_exit("Failed to get kex value");
+ 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);
- /* put f */
- buf_putmpint(ses.writepayload, &dh_f);
- mp_clear(&dh_f);
+ 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_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,
diff --git a/sysoptions.h b/sysoptions.h
index 8c591ea..20c2e57 100644
--- a/sysoptions.h
+++ b/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 */