mirror of
https://github.com/clearml/dropbear
synced 2025-05-03 03:33:02 +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_ */
|
||||||
|
34
cli-kex.c
34
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 (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) {
|
if (buf_getmpint(ses.payload, &dh_f) != DROPBEAR_SUCCESS) {
|
||||||
TRACE(("failed getting mpint"))
|
TRACE(("failed getting mpint"))
|
||||||
dropbear_exit("Bad KEX packet");
|
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}
|
||||||
|
39
common-kex.c
39
common-kex.c
@ -549,7 +549,7 @@ 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);
|
||||||
@ -557,7 +557,8 @@ void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) {
|
|||||||
|
|
||||||
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 */
|
||||||
|
46
svr-kex.c
46
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_NORMAL_DH(ses.newkeys->algo_kex)) {
|
||||||
m_mp_init(&dh_e);
|
m_mp_init(&dh_e);
|
||||||
if (buf_getmpint(ses.payload, &dh_e) != DROPBEAR_SUCCESS) {
|
if (buf_getmpint(ses.payload, &dh_e) != DROPBEAR_SUCCESS) {
|
||||||
dropbear_exit("Failed to get kex value");
|
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);
|
||||||
|
|
||||||
|
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 */
|
/* put f */
|
||||||
buf_putmpint(ses.writepayload, &dh_f);
|
buf_putmpint(ses.writepayload, &dh_param->pub);
|
||||||
mp_clear(&dh_f);
|
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