mirror of
https://github.com/clearml/dropbear
synced 2025-03-09 13:30:45 +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 \
|
||||
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 \
|
||||
|
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[]);
|
||||
#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_ */
|
||||
|
44
cli-kex.c
44
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) {
|
||||
|
@ -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}
|
||||
|
41
common-kex.c
41
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(¶m->pub, ¶m->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, ¶m->priv) != MP_OKAY) {
|
||||
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");
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
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");
|
||||
}
|
||||
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
|
||||
* 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, ¶m->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 = ¶m->pub;
|
||||
dh_f = dh_pub_them;
|
||||
} else {
|
||||
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 */
|
||||
@ -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
|
||||
* algos for the client or server. */
|
||||
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/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)
|
||||
|
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 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_ */
|
||||
|
@ -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
|
||||
|
||||
|
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_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. */
|
||||
|
9
random.c
9
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;
|
||||
|
||||
|
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 gen_random_mpint(mp_int *max, mp_int *rand);
|
||||
|
||||
extern int dropbear_ltc_prng;
|
||||
|
||||
#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_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 */
|
||||
|
54
svr-kex.c
54
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,
|
||||
|
19
sysoptions.h
19
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user