mirror of
https://github.com/clearml/dropbear
synced 2025-06-26 18:17:32 +00:00
Merge
--HG-- branch : ecc
This commit is contained in:
commit
29b1455f36
@ -27,7 +27,8 @@ COMMONOBJS=dbutil.o buffer.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 ecdsa.o crypto_desc.o
|
ltc_prng.o ecc.o ecdsa.o crypto_desc.o \
|
||||||
|
gensignkey.o gendss.o genrsa.o
|
||||||
|
|
||||||
SVROBJS=svr-kex.o svr-auth.o sshpty.o \
|
SVROBJS=svr-kex.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 \
|
||||||
@ -44,7 +45,7 @@ CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
|
|||||||
tcp-accept.o listener.o process-packet.o \
|
tcp-accept.o listener.o process-packet.o \
|
||||||
common-runopts.o circbuffer.o curve25519-donna.o
|
common-runopts.o circbuffer.o curve25519-donna.o
|
||||||
|
|
||||||
KEYOBJS=dropbearkey.o gendss.o genrsa.o
|
KEYOBJS=dropbearkey.o
|
||||||
|
|
||||||
CONVERTOBJS=dropbearconvert.o keyimport.o
|
CONVERTOBJS=dropbearconvert.o keyimport.o
|
||||||
|
|
||||||
|
19
cli-kex.c
19
cli-kex.c
@ -184,7 +184,8 @@ void recv_msg_kexdh_reply() {
|
|||||||
TRACE(("leave recv_msg_kexdh_init"))
|
TRACE(("leave recv_msg_kexdh_init"))
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) {
|
static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen,
|
||||||
|
const char* algoname) {
|
||||||
|
|
||||||
char* fp = NULL;
|
char* fp = NULL;
|
||||||
FILE *tty = NULL;
|
FILE *tty = NULL;
|
||||||
@ -192,14 +193,16 @@ static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) {
|
|||||||
|
|
||||||
fp = sign_key_fingerprint(keyblob, keybloblen);
|
fp = sign_key_fingerprint(keyblob, keybloblen);
|
||||||
if (cli_opts.always_accept_key) {
|
if (cli_opts.always_accept_key) {
|
||||||
fprintf(stderr, "\nHost '%s' key accepted unconditionally.\n(fingerprint %s)\n",
|
fprintf(stderr, "\nHost '%s' key accepted unconditionally.\n(%s fingerprint %s)\n",
|
||||||
cli_opts.remotehost,
|
cli_opts.remotehost,
|
||||||
|
algoname,
|
||||||
fp);
|
fp);
|
||||||
m_free(fp);
|
m_free(fp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(fingerprint %s)\nDo you want to continue connecting? (y/n) ",
|
fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(%s fingerprint %s)\nDo you want to continue connecting? (y/n) ",
|
||||||
cli_opts.remotehost,
|
cli_opts.remotehost,
|
||||||
|
algoname,
|
||||||
fp);
|
fp);
|
||||||
m_free(fp);
|
m_free(fp);
|
||||||
|
|
||||||
@ -294,16 +297,17 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
algoname = signkey_name_from_type(ses.newkeys->algo_hostkey, &algolen);
|
||||||
|
|
||||||
hostsfile = open_known_hosts_file(&readonly);
|
hostsfile = open_known_hosts_file(&readonly);
|
||||||
if (!hostsfile) {
|
if (!hostsfile) {
|
||||||
ask_to_confirm(keyblob, keybloblen);
|
ask_to_confirm(keyblob, keybloblen, algoname);
|
||||||
/* ask_to_confirm will exit upon failure */
|
/* ask_to_confirm will exit upon failure */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
line = buf_new(MAX_KNOWNHOSTS_LINE);
|
line = buf_new(MAX_KNOWNHOSTS_LINE);
|
||||||
hostlen = strlen(cli_opts.remotehost);
|
hostlen = strlen(cli_opts.remotehost);
|
||||||
algoname = signkey_name_from_type(ses.newkeys->algo_hostkey, &algolen);
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (buf_getline(line, hostsfile) == DROPBEAR_FAILURE) {
|
if (buf_getline(line, hostsfile) == DROPBEAR_FAILURE) {
|
||||||
@ -356,17 +360,18 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
|
|||||||
|
|
||||||
/* The keys didn't match. eep. Note that we're "leaking"
|
/* The keys didn't match. eep. Note that we're "leaking"
|
||||||
the fingerprint strings here, but we're exiting anyway */
|
the fingerprint strings here, but we're exiting anyway */
|
||||||
dropbear_exit("\n\nHost key mismatch for %s !\n"
|
dropbear_exit("\n\n%s host key mismatch for %s !\n"
|
||||||
"Fingerprint is %s\n"
|
"Fingerprint is %s\n"
|
||||||
"Expected %s\n"
|
"Expected %s\n"
|
||||||
"If you know that the host key is correct you can\nremove the bad entry from ~/.ssh/known_hosts",
|
"If you know that the host key is correct you can\nremove the bad entry from ~/.ssh/known_hosts",
|
||||||
|
algoname,
|
||||||
cli_opts.remotehost,
|
cli_opts.remotehost,
|
||||||
sign_key_fingerprint(keyblob, keybloblen),
|
sign_key_fingerprint(keyblob, keybloblen),
|
||||||
fingerprint ? fingerprint : "UNKNOWN");
|
fingerprint ? fingerprint : "UNKNOWN");
|
||||||
} while (1); /* keep going 'til something happens */
|
} while (1); /* keep going 'til something happens */
|
||||||
|
|
||||||
/* Key doesn't exist yet */
|
/* Key doesn't exist yet */
|
||||||
ask_to_confirm(keyblob, keybloblen);
|
ask_to_confirm(keyblob, keybloblen, algoname);
|
||||||
|
|
||||||
/* If we get here, they said yes */
|
/* If we get here, they said yes */
|
||||||
|
|
||||||
|
1
debug.h
1
debug.h
@ -72,6 +72,7 @@
|
|||||||
|
|
||||||
/* To debug with GDB it is easier to run with no forking of child processes.
|
/* To debug with GDB it is easier to run with no forking of child processes.
|
||||||
You will need to pass "-F" as well. */
|
You will need to pass "-F" as well. */
|
||||||
|
/* #define DEBUG_NOFORK */
|
||||||
#define DEBUG_NOFORK
|
#define DEBUG_NOFORK
|
||||||
|
|
||||||
|
|
||||||
|
172
dropbearkey.c
172
dropbearkey.c
@ -54,15 +54,13 @@
|
|||||||
#include "ecdsa.h"
|
#include "ecdsa.h"
|
||||||
#include "crypto_desc.h"
|
#include "crypto_desc.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
|
#include "gensignkey.h"
|
||||||
|
|
||||||
static void printhelp(char * progname);
|
static void printhelp(char * progname);
|
||||||
|
|
||||||
#define RSA_DEFAULT_SIZE 2048
|
|
||||||
#define DSS_DEFAULT_SIZE 1024
|
|
||||||
|
|
||||||
static void buf_writefile(buffer * buf, const char * filename);
|
|
||||||
static void printpubkey(sign_key * key, int keytype);
|
static void printpubkey(sign_key * key, int keytype);
|
||||||
static void justprintpub(const char* filename);
|
static int printpubfile(const char* filename);
|
||||||
|
|
||||||
/* Print a help message */
|
/* Print a help message */
|
||||||
static void printhelp(char * progname) {
|
static void printhelp(char * progname) {
|
||||||
@ -103,6 +101,30 @@ static void printhelp(char * progname) {
|
|||||||
,progname);
|
,progname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fails fatally */
|
||||||
|
static void check_signkey_bits(enum signkey_type type, int bits)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
#ifdef DROPBEAR_RSA
|
||||||
|
case DROPBEAR_SIGNKEY_RSA:
|
||||||
|
if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
|
||||||
|
dropbear_exit("Bits must satisfy 512 <= bits <= 4096, and be a"
|
||||||
|
" multiple of 8\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef DROPEAR_DSS
|
||||||
|
case DROPBEAR_SIGNKEY_DSS:
|
||||||
|
if (bits != 1024) {
|
||||||
|
dropbear_exit("DSS keys have a fixed size of 1024 bits\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
(void)0; /* quiet, compiler. ecdsa handles checks itself */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(DBMULTI_dropbearkey) || !defined(DROPBEAR_MULTI)
|
#if defined(DBMULTI_dropbearkey) || !defined(DROPBEAR_MULTI)
|
||||||
#if defined(DBMULTI_dropbearkey) && defined(DROPBEAR_MULTI)
|
#if defined(DBMULTI_dropbearkey) && defined(DROPBEAR_MULTI)
|
||||||
int dropbearkey_main(int argc, char ** argv) {
|
int dropbearkey_main(int argc, char ** argv) {
|
||||||
@ -112,13 +134,11 @@ int main(int argc, char ** argv) {
|
|||||||
|
|
||||||
int i;
|
int i;
|
||||||
char ** next = 0;
|
char ** next = 0;
|
||||||
sign_key *key = NULL;
|
|
||||||
buffer *buf = NULL;
|
|
||||||
char * filename = NULL;
|
char * filename = NULL;
|
||||||
enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE;
|
enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE;
|
||||||
char * typetext = NULL;
|
char * typetext = NULL;
|
||||||
char * sizetext = NULL;
|
char * sizetext = NULL;
|
||||||
unsigned int bits;
|
unsigned int bits = 0;
|
||||||
int printpub = 0;
|
int printpub = 0;
|
||||||
|
|
||||||
crypto_init();
|
crypto_init();
|
||||||
@ -174,8 +194,8 @@ int main(int argc, char ** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (printpub) {
|
if (printpub) {
|
||||||
justprintpub(filename);
|
int ret = printpubfile(filename);
|
||||||
/* Not reached */
|
exit(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check/parse args */
|
/* check/parse args */
|
||||||
@ -216,106 +236,22 @@ int main(int argc, char ** argv) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: put RSA and DSS size checks into genrsa.c etc
|
check_signkey_bits(keytype, bits);;
|
||||||
switch (keytype) {
|
}
|
||||||
#ifdef DROPBEAR_RSA
|
|
||||||
case DROPBEAR_SIGNKEY_RSA:
|
|
||||||
if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
|
|
||||||
fprintf(stderr, "Bits must satisfy 512 <= bits <= 4096, and be a"
|
|
||||||
" multiple of 8\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef DROPEAR_DSS
|
|
||||||
case DROPBEAR_SIGNKEY_DSS:
|
|
||||||
if (bits != 1024) {
|
|
||||||
fprintf(stderr, "DSS keys have a fixed size of 1024 bits\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
(void)0; /* quiet, compiler. ecdsa handles checks itself */
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* default key size */
|
|
||||||
|
|
||||||
switch (keytype) {
|
|
||||||
#ifdef DROPBEAR_RSA
|
|
||||||
case DROPBEAR_SIGNKEY_RSA:
|
|
||||||
bits = RSA_DEFAULT_SIZE;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef DROPBEAR_DSS
|
|
||||||
case DROPBEAR_SIGNKEY_DSS:
|
|
||||||
bits = DSS_DEFAULT_SIZE;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef DROPBEAR_ECDSA
|
|
||||||
case DROPBEAR_SIGNKEY_ECDSA_KEYGEN:
|
|
||||||
bits = ECDSA_DEFAULT_SIZE;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
exit(EXIT_FAILURE); /* not reached */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(stderr, "Will output %d bit %s secret key to '%s'\n", bits,
|
|
||||||
typetext, filename);
|
|
||||||
|
|
||||||
/* don't want the file readable by others */
|
|
||||||
umask(077);
|
|
||||||
|
|
||||||
/* now we can generate the key */
|
|
||||||
key = new_sign_key();
|
|
||||||
|
|
||||||
fprintf(stderr, "Generating key, this may take a while...\n");
|
fprintf(stderr, "Generating key, this may take a while...\n");
|
||||||
switch(keytype) {
|
if (signkey_generate(keytype, bits, filename) == DROPBEAR_FAILURE)
|
||||||
#ifdef DROPBEAR_RSA
|
{
|
||||||
case DROPBEAR_SIGNKEY_RSA:
|
dropbear_exit("Failed to generate key.\n");
|
||||||
key->rsakey = gen_rsa_priv_key(bits);
|
}
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef DROPBEAR_DSS
|
|
||||||
case DROPBEAR_SIGNKEY_DSS:
|
|
||||||
key->dsskey = gen_dss_priv_key(bits);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef DROPBEAR_ECDSA
|
|
||||||
case DROPBEAR_SIGNKEY_ECDSA_KEYGEN:
|
|
||||||
{
|
|
||||||
ecc_key *ecckey = gen_ecdsa_priv_key(bits);
|
|
||||||
keytype = ecdsa_signkey_type(ecckey);
|
|
||||||
*signkey_key_ptr(key, keytype) = ecckey;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "Internal error, bad key type\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = buf_new(MAX_PRIVKEY_SIZE);
|
printpubfile(filename);
|
||||||
|
|
||||||
buf_put_priv_key(buf, key, keytype);
|
|
||||||
buf_setpos(buf, 0);
|
|
||||||
buf_writefile(buf, filename);
|
|
||||||
|
|
||||||
buf_burn(buf);
|
|
||||||
buf_free(buf);
|
|
||||||
|
|
||||||
printpubkey(key, keytype);
|
|
||||||
|
|
||||||
sign_key_free(key);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void justprintpub(const char* filename) {
|
static int printpubfile(const char* filename) {
|
||||||
|
|
||||||
buffer *buf = NULL;
|
buffer *buf = NULL;
|
||||||
sign_key *key = NULL;
|
sign_key *key = NULL;
|
||||||
@ -353,7 +289,7 @@ out:
|
|||||||
sign_key_free(key);
|
sign_key_free(key);
|
||||||
key = NULL;
|
key = NULL;
|
||||||
}
|
}
|
||||||
exit(err);
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printpubkey(sign_key * key, int keytype) {
|
static void printpubkey(sign_key * key, int keytype) {
|
||||||
@ -402,35 +338,3 @@ static void printpubkey(sign_key * key, int keytype) {
|
|||||||
m_free(fp);
|
m_free(fp);
|
||||||
buf_free(buf);
|
buf_free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a buffer to a file specified, failing if the file exists */
|
|
||||||
static void buf_writefile(buffer * buf, const char * filename) {
|
|
||||||
|
|
||||||
int fd;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
|
|
||||||
if (fd < 0) {
|
|
||||||
fprintf(stderr, "Couldn't create new file %s\n", filename);
|
|
||||||
perror("Reason");
|
|
||||||
buf_burn(buf);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* write the file now */
|
|
||||||
while (buf->pos != buf->len) {
|
|
||||||
len = write(fd, buf_getptr(buf, buf->len - buf->pos),
|
|
||||||
buf->len - buf->pos);
|
|
||||||
if (errno == EINTR) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (len <= 0) {
|
|
||||||
fprintf(stderr, "Failed writing file '%s'\n",filename);
|
|
||||||
perror("Reason");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
buf_incrpos(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
7
ecdsa.c
7
ecdsa.c
@ -8,6 +8,13 @@
|
|||||||
|
|
||||||
#ifdef DROPBEAR_ECDSA
|
#ifdef DROPBEAR_ECDSA
|
||||||
|
|
||||||
|
int signkey_is_ecdsa(enum signkey_type type)
|
||||||
|
{
|
||||||
|
return type == DROPBEAR_SIGNKEY_ECDSA_NISTP256
|
||||||
|
|| type == DROPBEAR_SIGNKEY_ECDSA_NISTP384
|
||||||
|
|| type == DROPBEAR_SIGNKEY_ECDSA_NISTP521;
|
||||||
|
}
|
||||||
|
|
||||||
enum signkey_type ecdsa_signkey_type(ecc_key * key) {
|
enum signkey_type ecdsa_signkey_type(ecc_key * key) {
|
||||||
#ifdef DROPBEAR_ECC_256
|
#ifdef DROPBEAR_ECC_256
|
||||||
if (key->dp == ecc_curve_nistp256.dp) {
|
if (key->dp == ecc_curve_nistp256.dp) {
|
||||||
|
2
ecdsa.h
2
ecdsa.h
@ -26,6 +26,8 @@ enum signkey_type ecdsa_signkey_type(ecc_key * key);
|
|||||||
|
|
||||||
void buf_put_ecdsa_sign(buffer *buf, ecc_key *key, buffer *data_buf);
|
void buf_put_ecdsa_sign(buffer *buf, ecc_key *key, buffer *data_buf);
|
||||||
int buf_ecdsa_verify(buffer *buf, ecc_key *key, buffer *data_buf);
|
int buf_ecdsa_verify(buffer *buf, ecc_key *key, buffer *data_buf);
|
||||||
|
/* Returns 1 on success */
|
||||||
|
int signkey_is_ecdsa(enum signkey_type type);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
127
gensignkey.c
Normal file
127
gensignkey.c
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#include "includes.h"
|
||||||
|
#include "dbutil.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "ecdsa.h"
|
||||||
|
#include "genrsa.h"
|
||||||
|
#include "gendss.h"
|
||||||
|
#include "signkey.h"
|
||||||
|
|
||||||
|
#define RSA_DEFAULT_SIZE 2048
|
||||||
|
#define DSS_DEFAULT_SIZE 1024
|
||||||
|
|
||||||
|
// Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE
|
||||||
|
static int buf_writefile(buffer * buf, const char * filename) {
|
||||||
|
int ret = DROPBEAR_FAILURE;
|
||||||
|
int fd = -1;
|
||||||
|
|
||||||
|
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
|
||||||
|
if (fd < 0) {
|
||||||
|
dropbear_log(LOG_ERR, "Couldn't create new file %s: %s",
|
||||||
|
filename, strerror(errno));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write the file now */
|
||||||
|
while (buf->pos != buf->len) {
|
||||||
|
int len = write(fd, buf_getptr(buf, buf->len - buf->pos),
|
||||||
|
buf->len - buf->pos);
|
||||||
|
if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (len <= 0) {
|
||||||
|
dropbear_log(LOG_ERR, "Failed writing file %s: %s",
|
||||||
|
filename, strerror(errno));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
buf_incrpos(buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = DROPBEAR_SUCCESS;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (fd >= 0) {
|
||||||
|
m_close(fd);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns 0 on failure */
|
||||||
|
static int get_default_bits(enum signkey_type keytype)
|
||||||
|
{
|
||||||
|
switch (keytype) {
|
||||||
|
#ifdef DROPBEAR_RSA
|
||||||
|
case DROPBEAR_SIGNKEY_RSA:
|
||||||
|
return RSA_DEFAULT_SIZE;
|
||||||
|
#endif
|
||||||
|
#ifdef DROPBEAR_DSS
|
||||||
|
case DROPBEAR_SIGNKEY_DSS:
|
||||||
|
return DSS_DEFAULT_SIZE;
|
||||||
|
#endif
|
||||||
|
#ifdef DROPBEAR_ECDSA
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_KEYGEN:
|
||||||
|
return ECDSA_DEFAULT_SIZE;
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
|
||||||
|
return 521;
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
|
||||||
|
return 384;
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
|
||||||
|
return 256;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int signkey_generate(enum signkey_type keytype, int bits, const char* filename)
|
||||||
|
{
|
||||||
|
sign_key * key = NULL;
|
||||||
|
buffer *buf = NULL;
|
||||||
|
int ret = DROPBEAR_FAILURE;
|
||||||
|
if (bits == 0)
|
||||||
|
{
|
||||||
|
bits = get_default_bits(keytype);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now we can generate the key */
|
||||||
|
key = new_sign_key();
|
||||||
|
|
||||||
|
switch(keytype) {
|
||||||
|
#ifdef DROPBEAR_RSA
|
||||||
|
case DROPBEAR_SIGNKEY_RSA:
|
||||||
|
key->rsakey = gen_rsa_priv_key(bits);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef DROPBEAR_DSS
|
||||||
|
case DROPBEAR_SIGNKEY_DSS:
|
||||||
|
key->dsskey = gen_dss_priv_key(bits);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef DROPBEAR_ECDSA
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_KEYGEN:
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
|
||||||
|
{
|
||||||
|
ecc_key *ecckey = gen_ecdsa_priv_key(bits);
|
||||||
|
keytype = ecdsa_signkey_type(ecckey);
|
||||||
|
*signkey_key_ptr(key, keytype) = ecckey;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
dropbear_exit("Internal error");
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = buf_new(MAX_PRIVKEY_SIZE);
|
||||||
|
|
||||||
|
buf_put_priv_key(buf, key, keytype);
|
||||||
|
sign_key_free(key);
|
||||||
|
key = NULL;
|
||||||
|
buf_setpos(buf, 0);
|
||||||
|
ret = buf_writefile(buf, filename);
|
||||||
|
|
||||||
|
buf_burn(buf);
|
||||||
|
buf_free(buf);
|
||||||
|
buf = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
8
gensignkey.h
Normal file
8
gensignkey.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef _GENSIGNKEY_H
|
||||||
|
#define _GENSIGNKEY_H
|
||||||
|
|
||||||
|
#include "signkey.h"
|
||||||
|
|
||||||
|
int signkey_generate(enum signkey_type type, int bits, const char* filename);
|
||||||
|
|
||||||
|
#endif
|
26
keyimport.c
26
keyimport.c
@ -112,7 +112,7 @@ static sign_key *dropbear_read(const char* filename) {
|
|||||||
|
|
||||||
buffer * buf = NULL;
|
buffer * buf = NULL;
|
||||||
sign_key *ret = NULL;
|
sign_key *ret = NULL;
|
||||||
int type;
|
enum signkey_type type;
|
||||||
|
|
||||||
buf = buf_new(MAX_PRIVKEY_SIZE);
|
buf = buf_new(MAX_PRIVKEY_SIZE);
|
||||||
if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) {
|
if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) {
|
||||||
@ -501,7 +501,7 @@ static int openssh_encrypted(const char *filename)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static sign_key *openssh_read(const char *filename, char *passphrase)
|
static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase))
|
||||||
{
|
{
|
||||||
struct openssh_key *key;
|
struct openssh_key *key;
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
@ -511,7 +511,7 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
|
|||||||
char *errmsg;
|
char *errmsg;
|
||||||
char *modptr = NULL;
|
char *modptr = NULL;
|
||||||
int modlen = -9999;
|
int modlen = -9999;
|
||||||
int type;
|
enum signkey_type type;
|
||||||
|
|
||||||
sign_key *retkey;
|
sign_key *retkey;
|
||||||
buffer * blobbuf = NULL;
|
buffer * blobbuf = NULL;
|
||||||
@ -709,19 +709,29 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len == sizeof(OID_SEC256R1_BLOB)
|
if (0) {}
|
||||||
|
#ifdef DROPBEAR_ECC_256
|
||||||
|
else if (len == sizeof(OID_SEC256R1_BLOB)
|
||||||
&& memcmp(p, OID_SEC256R1_BLOB, len) == 0) {
|
&& memcmp(p, OID_SEC256R1_BLOB, len) == 0) {
|
||||||
retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
|
retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
|
||||||
curve = &ecc_curve_nistp256;
|
curve = &ecc_curve_nistp256;
|
||||||
} else if (len == sizeof(OID_SEC384R1_BLOB)
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef DROPBEAR_ECC_384
|
||||||
|
else if (len == sizeof(OID_SEC384R1_BLOB)
|
||||||
&& memcmp(p, OID_SEC384R1_BLOB, len) == 0) {
|
&& memcmp(p, OID_SEC384R1_BLOB, len) == 0) {
|
||||||
retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP384;
|
retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP384;
|
||||||
curve = &ecc_curve_nistp384;
|
curve = &ecc_curve_nistp384;
|
||||||
} else if (len == sizeof(OID_SEC521R1_BLOB)
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef DROPBEAR_ECC_521
|
||||||
|
else if (len == sizeof(OID_SEC521R1_BLOB)
|
||||||
&& memcmp(p, OID_SEC521R1_BLOB, len) == 0) {
|
&& memcmp(p, OID_SEC521R1_BLOB, len) == 0) {
|
||||||
retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP521;
|
retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP521;
|
||||||
curve = &ecc_curve_nistp521;
|
curve = &ecc_curve_nistp521;
|
||||||
} else {
|
}
|
||||||
|
#endif
|
||||||
|
else {
|
||||||
errmsg = "Unknown ECC key type";
|
errmsg = "Unknown ECC key type";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -1019,7 +1029,7 @@ static int openssh_write(const char *filename, sign_key *key,
|
|||||||
*/
|
*/
|
||||||
buffer *seq_buf = buf_new(400);
|
buffer *seq_buf = buf_new(400);
|
||||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, key->type);
|
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, key->type);
|
||||||
const unsigned long curve_size = (*eck)->dp->size;
|
const long curve_size = (*eck)->dp->size;
|
||||||
int curve_oid_len = 0;
|
int curve_oid_len = 0;
|
||||||
const void* curve_oid = NULL;
|
const void* curve_oid = NULL;
|
||||||
unsigned long pubkey_size = 2*curve_size+1;
|
unsigned long pubkey_size = 2*curve_size+1;
|
||||||
|
17
options.h
17
options.h
@ -8,7 +8,7 @@
|
|||||||
/* Define compile-time options below - the "#ifndef DROPBEAR_XXX .... #endif"
|
/* Define compile-time options below - the "#ifndef DROPBEAR_XXX .... #endif"
|
||||||
* parts are to allow for commandline -DDROPBEAR_XXX options etc. */
|
* parts are to allow for commandline -DDROPBEAR_XXX options etc. */
|
||||||
|
|
||||||
/* Important: Many options will require "make clean" after changes */
|
/* IMPORTANT: Many options will require "make clean" after changes */
|
||||||
|
|
||||||
#ifndef DROPBEAR_DEFPORT
|
#ifndef DROPBEAR_DEFPORT
|
||||||
#define DROPBEAR_DEFPORT "22"
|
#define DROPBEAR_DEFPORT "22"
|
||||||
@ -129,7 +129,7 @@ much traffic. */
|
|||||||
|
|
||||||
/* You can also disable integrity. Don't bother disabling this if you're
|
/* You can also disable integrity. Don't bother disabling this if you're
|
||||||
* still using a cipher, it's relatively cheap. If you disable this it's dead
|
* still using a cipher, it's relatively cheap. If you disable this it's dead
|
||||||
* simple to run arbitrary commands on the remote host. Beware. */
|
* simple for an attacker to run arbitrary commands on the remote host. Beware. */
|
||||||
/* #define DROPBEAR_NONE_INTEGRITY */
|
/* #define DROPBEAR_NONE_INTEGRITY */
|
||||||
|
|
||||||
/* Hostkey/public key algorithms - at least one required, these are used
|
/* Hostkey/public key algorithms - at least one required, these are used
|
||||||
@ -138,10 +138,14 @@ much traffic. */
|
|||||||
* SSH2 RFC Draft requires dss, recommends rsa */
|
* SSH2 RFC Draft requires dss, recommends rsa */
|
||||||
#define DROPBEAR_RSA
|
#define DROPBEAR_RSA
|
||||||
#define DROPBEAR_DSS
|
#define DROPBEAR_DSS
|
||||||
|
|
||||||
#define DROPBEAR_ECDH
|
|
||||||
#define DROPBEAR_ECDSA
|
#define DROPBEAR_ECDSA
|
||||||
|
|
||||||
|
/* Generate hostkeys as-needed when the first connection using that key type occurs.
|
||||||
|
This avoids the need to otherwise run "dropbearkey" and avoids some problems
|
||||||
|
with badly seeded random devices when systems first boot.
|
||||||
|
This also requires a runtime flag "-R". */
|
||||||
|
#define DROPBEAR_DELAY_HOSTKEY
|
||||||
|
|
||||||
#define DROPBEAR_CURVE25519
|
#define DROPBEAR_CURVE25519
|
||||||
|
|
||||||
/* 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
|
||||||
@ -149,6 +153,9 @@ much traffic. */
|
|||||||
* signing operations slightly slower. */
|
* signing operations slightly slower. */
|
||||||
#define RSA_BLINDING
|
#define RSA_BLINDING
|
||||||
|
|
||||||
|
/* Enable elliptic curve Diffie Hellman key exchange */
|
||||||
|
#define DROPBEAR_ECDH
|
||||||
|
|
||||||
/* Control the memory/performance/compression tradeoff for zlib.
|
/* Control the memory/performance/compression tradeoff for zlib.
|
||||||
* Set windowBits=8 for least memory usage, see your system's
|
* Set windowBits=8 for least memory usage, see your system's
|
||||||
* zlib.h for full details.
|
* zlib.h for full details.
|
||||||
@ -184,7 +191,7 @@ much traffic. */
|
|||||||
|
|
||||||
#define ENABLE_SVR_PASSWORD_AUTH
|
#define ENABLE_SVR_PASSWORD_AUTH
|
||||||
/* PAM requires ./configure --enable-pam */
|
/* PAM requires ./configure --enable-pam */
|
||||||
//#define ENABLE_SVR_PAM_AUTH
|
/*#define ENABLE_SVR_PAM_AUTH */
|
||||||
#define ENABLE_SVR_PUBKEY_AUTH
|
#define ENABLE_SVR_PUBKEY_AUTH
|
||||||
|
|
||||||
/* Whether to take public key options in
|
/* Whether to take public key options in
|
||||||
|
@ -100,6 +100,8 @@ typedef struct svr_runopts {
|
|||||||
|
|
||||||
sign_key *hostkey;
|
sign_key *hostkey;
|
||||||
|
|
||||||
|
int delay_hostkey;
|
||||||
|
|
||||||
char *hostkey_files[MAX_HOSTKEYS];
|
char *hostkey_files[MAX_HOSTKEYS];
|
||||||
int num_hostkey_files;
|
int num_hostkey_files;
|
||||||
|
|
||||||
|
21
signkey.c
21
signkey.c
@ -181,7 +181,7 @@ int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef DROPBEAR_ECDSA
|
#ifdef DROPBEAR_ECDSA
|
||||||
{
|
if (signkey_is_ecdsa(keytype)) {
|
||||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
||||||
if (eck) {
|
if (eck) {
|
||||||
if (*eck) {
|
if (*eck) {
|
||||||
@ -249,7 +249,7 @@ int buf_get_priv_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef DROPBEAR_ECDSA
|
#ifdef DROPBEAR_ECDSA
|
||||||
{
|
if (signkey_is_ecdsa(keytype)) {
|
||||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
||||||
if (eck) {
|
if (eck) {
|
||||||
if (*eck) {
|
if (*eck) {
|
||||||
@ -289,10 +289,7 @@ void buf_put_pub_key(buffer* buf, sign_key *key, enum signkey_type type) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef DROPBEAR_ECDSA
|
#ifdef DROPBEAR_ECDSA
|
||||||
if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP256
|
if (signkey_is_ecdsa(type)) {
|
||||||
|| type == DROPBEAR_SIGNKEY_ECDSA_NISTP384
|
|
||||||
|| type == DROPBEAR_SIGNKEY_ECDSA_NISTP521)
|
|
||||||
{
|
|
||||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
||||||
if (eck) {
|
if (eck) {
|
||||||
buf_put_ecdsa_pub_key(pubkeys, *eck);
|
buf_put_ecdsa_pub_key(pubkeys, *eck);
|
||||||
@ -329,7 +326,7 @@ void buf_put_priv_key(buffer* buf, sign_key *key, enum signkey_type type) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef DROPBEAR_ECDSA
|
#ifdef DROPBEAR_ECDSA
|
||||||
{
|
if (signkey_is_ecdsa(type)) {
|
||||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
||||||
if (eck) {
|
if (eck) {
|
||||||
buf_put_ecdsa_priv_key(buf, *eck);
|
buf_put_ecdsa_priv_key(buf, *eck);
|
||||||
@ -354,18 +351,24 @@ void sign_key_free(sign_key *key) {
|
|||||||
key->rsakey = NULL;
|
key->rsakey = NULL;
|
||||||
#endif
|
#endif
|
||||||
#ifdef DROPBEAR_ECDSA
|
#ifdef DROPBEAR_ECDSA
|
||||||
|
#ifdef DROPBEAR_ECC_256
|
||||||
if (key->ecckey256) {
|
if (key->ecckey256) {
|
||||||
ecc_free(key->ecckey256);
|
ecc_free(key->ecckey256);
|
||||||
key->ecckey256 = NULL;
|
key->ecckey256 = NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef DROPBEAR_ECC_384
|
||||||
if (key->ecckey384) {
|
if (key->ecckey384) {
|
||||||
ecc_free(key->ecckey384);
|
ecc_free(key->ecckey384);
|
||||||
key->ecckey384 = NULL;
|
key->ecckey384 = NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef DROPBEAR_ECC_521
|
||||||
if (key->ecckey521) {
|
if (key->ecckey521) {
|
||||||
ecc_free(key->ecckey521);
|
ecc_free(key->ecckey521);
|
||||||
key->ecckey521 = NULL;
|
key->ecckey521 = NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_free(key->filename);
|
m_free(key->filename);
|
||||||
@ -484,7 +487,7 @@ void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type type,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef DROPBEAR_ECDSA
|
#ifdef DROPBEAR_ECDSA
|
||||||
{
|
if (signkey_is_ecdsa(type)) {
|
||||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
||||||
if (eck) {
|
if (eck) {
|
||||||
buf_put_ecdsa_sign(sigblob, *eck, data_buf);
|
buf_put_ecdsa_sign(sigblob, *eck, data_buf);
|
||||||
@ -535,7 +538,7 @@ int buf_verify(buffer * buf, sign_key *key, buffer *data_buf) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef DROPBEAR_ECDSA
|
#ifdef DROPBEAR_ECDSA
|
||||||
{
|
if (signkey_is_ecdsa(type)) {
|
||||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
||||||
if (eck) {
|
if (eck) {
|
||||||
return buf_ecdsa_verify(buf, *eck, data_buf);
|
return buf_ecdsa_verify(buf, *eck, data_buf);
|
||||||
|
89
svr-kex.c
89
svr-kex.c
@ -35,6 +35,7 @@
|
|||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "runopts.h"
|
#include "runopts.h"
|
||||||
#include "ecc.h"
|
#include "ecc.h"
|
||||||
|
#include "gensignkey.h"
|
||||||
|
|
||||||
static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs);
|
static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs);
|
||||||
|
|
||||||
@ -82,6 +83,84 @@ void recv_msg_kexdh_init() {
|
|||||||
ses.requirenext[1] = 0;
|
ses.requirenext[1] = 0;
|
||||||
TRACE(("leave recv_msg_kexdh_init"))
|
TRACE(("leave recv_msg_kexdh_init"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DROPBEAR_DELAY_HOSTKEY
|
||||||
|
static void svr_ensure_hostkey() {
|
||||||
|
|
||||||
|
const char* fn = NULL;
|
||||||
|
char *fn_temp = NULL;
|
||||||
|
enum signkey_type type = ses.newkeys->algo_hostkey;
|
||||||
|
void **hostkey = signkey_key_ptr(svr_opts.hostkey, type);
|
||||||
|
int ret = DROPBEAR_FAILURE;
|
||||||
|
|
||||||
|
if (hostkey && *hostkey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
#ifdef DROPBEAR_RSA
|
||||||
|
case DROPBEAR_SIGNKEY_RSA:
|
||||||
|
fn = RSA_PRIV_FILENAME;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef DROPBEAR_DSS
|
||||||
|
case DROPBEAR_SIGNKEY_DSS:
|
||||||
|
fn = DSS_PRIV_FILENAME;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef DROPBEAR_ECDSA
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
|
||||||
|
fn = ECDSA_PRIV_FILENAME;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
(void)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readhostkey(fn, svr_opts.hostkey, &type) == DROPBEAR_SUCCESS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn_temp = m_malloc(strlen(fn) + 20);
|
||||||
|
snprintf(fn_temp, strlen(fn)+20, "%s.tmp%d", fn, getpid());
|
||||||
|
|
||||||
|
if (signkey_generate(type, 0, fn_temp) == DROPBEAR_FAILURE) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (link(fn_temp, fn) < 0) {
|
||||||
|
if (errno != EEXIST) {
|
||||||
|
dropbear_log(LOG_ERR, "Failed moving key file to %s", fn);
|
||||||
|
/* XXX fallback to non-atomic copy for some filesystems? */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = readhostkey(fn, svr_opts.hostkey, &type);
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (fn_temp) {
|
||||||
|
unlink(fn_temp);
|
||||||
|
m_free(fn_temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == DROPBEAR_FAILURE)
|
||||||
|
{
|
||||||
|
dropbear_exit("Couldn't read or generate hostkey %s", fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// directory for keys.
|
||||||
|
|
||||||
|
// Create lockfile first, or wait if it exists. PID!
|
||||||
|
// Generate key
|
||||||
|
// write it, load to memory
|
||||||
|
// atomic rename, done.
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Generate our side of the diffie-hellman key exchange value (dh_f), and
|
/* Generate our side of the diffie-hellman key exchange value (dh_f), and
|
||||||
* calculate the session key using the diffie-hellman algorithm. Following
|
* calculate the session key using the diffie-hellman algorithm. Following
|
||||||
@ -95,6 +174,14 @@ static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs) {
|
|||||||
|
|
||||||
/* we can start creating the kexdh_reply packet */
|
/* we can start creating the kexdh_reply packet */
|
||||||
CHECKCLEARTOWRITE();
|
CHECKCLEARTOWRITE();
|
||||||
|
|
||||||
|
#ifdef DROPBEAR_DELAY_HOSTKEY
|
||||||
|
if (svr_opts.delay_hostkey)
|
||||||
|
{
|
||||||
|
svr_ensure_hostkey();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY);
|
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY);
|
||||||
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);
|
||||||
@ -124,7 +211,7 @@ static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs) {
|
|||||||
case DROPBEAR_KEX_CURVE25519:
|
case DROPBEAR_KEX_CURVE25519:
|
||||||
#ifdef DROPBEAR_CURVE25519
|
#ifdef DROPBEAR_CURVE25519
|
||||||
{
|
{
|
||||||
struct kex_curve25519_param *param = gen_kexecdh_param();
|
struct kex_curve25519_param *param = gen_kexcurve25519_param();
|
||||||
kexcurve25519_comb_key(param, ecdh_qs, svr_opts.hostkey);
|
kexcurve25519_comb_key(param, ecdh_qs, svr_opts.hostkey);
|
||||||
buf_putstring(ses.writepayload, param->priv, CURVE25519_LEN);
|
buf_putstring(ses.writepayload, param->priv, CURVE25519_LEN);
|
||||||
free_kexcurve25519_param(param);
|
free_kexcurve25519_param(param);
|
||||||
|
@ -44,13 +44,19 @@ static void printhelp(const char * progname) {
|
|||||||
"-b bannerfile Display the contents of bannerfile"
|
"-b bannerfile Display the contents of bannerfile"
|
||||||
" before user login\n"
|
" before user login\n"
|
||||||
" (default: none)\n"
|
" (default: none)\n"
|
||||||
|
"-r keyfile Specify hostkeys (repeatable)\n"
|
||||||
|
" defaults: \n"
|
||||||
#ifdef DROPBEAR_DSS
|
#ifdef DROPBEAR_DSS
|
||||||
"-d dsskeyfile Use dsskeyfile for the DSS host key\n"
|
" dss %s\n"
|
||||||
" (default: %s)\n"
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef DROPBEAR_RSA
|
#ifdef DROPBEAR_RSA
|
||||||
"-r rsakeyfile Use rsakeyfile for the RSA host key\n"
|
" rsa %s\n"
|
||||||
" (default: %s)\n"
|
#endif
|
||||||
|
#ifdef DROPBEAR_ECDSA
|
||||||
|
" ecdsa %s\n"
|
||||||
|
#endif
|
||||||
|
#ifdef DROPBEAR_DELAY_HOSTKEY
|
||||||
|
"-R Create hostkeys as required\n"
|
||||||
#endif
|
#endif
|
||||||
"-F Don't fork into background\n"
|
"-F Don't fork into background\n"
|
||||||
#ifdef DISABLE_SYSLOG
|
#ifdef DISABLE_SYSLOG
|
||||||
@ -95,6 +101,9 @@ static void printhelp(const char * progname) {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef DROPBEAR_RSA
|
#ifdef DROPBEAR_RSA
|
||||||
RSA_PRIV_FILENAME,
|
RSA_PRIV_FILENAME,
|
||||||
|
#endif
|
||||||
|
#ifdef DROPBEAR_ECDSA
|
||||||
|
ECDSA_PRIV_FILENAME,
|
||||||
#endif
|
#endif
|
||||||
DROPBEAR_MAX_PORTS, DROPBEAR_DEFPORT, DROPBEAR_PIDFILE,
|
DROPBEAR_MAX_PORTS, DROPBEAR_DEFPORT, DROPBEAR_PIDFILE,
|
||||||
DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT);
|
DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT);
|
||||||
@ -122,6 +131,7 @@ void svr_getopts(int argc, char ** argv) {
|
|||||||
svr_opts.inetdmode = 0;
|
svr_opts.inetdmode = 0;
|
||||||
svr_opts.portcount = 0;
|
svr_opts.portcount = 0;
|
||||||
svr_opts.hostkey = NULL;
|
svr_opts.hostkey = NULL;
|
||||||
|
svr_opts.delay_hostkey = 0;
|
||||||
svr_opts.pidfile = DROPBEAR_PIDFILE;
|
svr_opts.pidfile = DROPBEAR_PIDFILE;
|
||||||
#ifdef ENABLE_SVR_LOCALTCPFWD
|
#ifdef ENABLE_SVR_LOCALTCPFWD
|
||||||
svr_opts.nolocaltcp = 0;
|
svr_opts.nolocaltcp = 0;
|
||||||
@ -180,6 +190,9 @@ void svr_getopts(int argc, char ** argv) {
|
|||||||
case 'r':
|
case 'r':
|
||||||
next = &keyfile;
|
next = &keyfile;
|
||||||
break;
|
break;
|
||||||
|
case 'R':
|
||||||
|
svr_opts.delay_hostkey = 1;
|
||||||
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
svr_opts.forkbg = 0;
|
svr_opts.forkbg = 0;
|
||||||
break;
|
break;
|
||||||
@ -390,7 +403,7 @@ static void loadhostkey_helper(const char *name, void** src, void** dst, int fat
|
|||||||
/* Must be called after syslog/etc is working */
|
/* Must be called after syslog/etc is working */
|
||||||
static void loadhostkey(const char *keyfile, int fatal_duplicate) {
|
static void loadhostkey(const char *keyfile, int fatal_duplicate) {
|
||||||
sign_key * read_key = new_sign_key();
|
sign_key * read_key = new_sign_key();
|
||||||
int type = DROPBEAR_SIGNKEY_ANY;
|
enum signkey_type type = DROPBEAR_SIGNKEY_ANY;
|
||||||
if (readhostkey(keyfile, read_key, &type) == DROPBEAR_FAILURE) {
|
if (readhostkey(keyfile, read_key, &type) == DROPBEAR_FAILURE) {
|
||||||
dropbear_log(LOG_WARNING, "Failed loading %s", keyfile);
|
dropbear_log(LOG_WARNING, "Failed loading %s", keyfile);
|
||||||
}
|
}
|
||||||
@ -438,6 +451,7 @@ static void addhostkey(const char *keyfile) {
|
|||||||
|
|
||||||
void load_all_hostkeys() {
|
void load_all_hostkeys() {
|
||||||
int i;
|
int i;
|
||||||
|
int disable_unset_keys = 1;
|
||||||
|
|
||||||
svr_opts.hostkey = new_sign_key();
|
svr_opts.hostkey = new_sign_key();
|
||||||
|
|
||||||
@ -459,31 +473,47 @@ void load_all_hostkeys() {
|
|||||||
loadhostkey(ECDSA_PRIV_FILENAME, 0);
|
loadhostkey(ECDSA_PRIV_FILENAME, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DROPBEAR_DELAY_HOSTKEY
|
||||||
|
if (svr_opts.delay_hostkey)
|
||||||
|
{
|
||||||
|
disable_unset_keys = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DROPBEAR_RSA
|
#ifdef DROPBEAR_RSA
|
||||||
if (!svr_opts.hostkey->rsakey) {
|
if (disable_unset_keys && !svr_opts.hostkey->rsakey) {
|
||||||
disablekey(DROPBEAR_SIGNKEY_RSA);
|
disablekey(DROPBEAR_SIGNKEY_RSA);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DROPBEAR_DSS
|
#ifdef DROPBEAR_DSS
|
||||||
if (!svr_opts.hostkey->dsskey) {
|
if (disable_unset_keys && !svr_opts.hostkey->dsskey) {
|
||||||
disablekey(DROPBEAR_SIGNKEY_RSA);
|
disablekey(DROPBEAR_SIGNKEY_RSA);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef DROPBEAR_ECDSA
|
#ifdef DROPBEAR_ECDSA
|
||||||
#ifdef DROPBEAR_ECC_256
|
#ifdef DROPBEAR_ECC_256
|
||||||
if (!svr_opts.hostkey->ecckey256) {
|
if ((disable_unset_keys || ECDSA_DEFAULT_SIZE != 256)
|
||||||
|
&& !svr_opts.hostkey->ecckey256) {
|
||||||
disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP256);
|
disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP256);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DROPBEAR_ECC_384
|
#ifdef DROPBEAR_ECC_384
|
||||||
if (!svr_opts.hostkey->ecckey384) {
|
if ((disable_unset_keys || ECDSA_DEFAULT_SIZE != 384)
|
||||||
|
&& !svr_opts.hostkey->ecckey384) {
|
||||||
disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP384);
|
disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP384);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DROPBEAR_ECC_521
|
#ifdef DROPBEAR_ECC_521
|
||||||
if (!svr_opts.hostkey->ecckey521) {
|
if ((disable_unset_keys || ECDSA_DEFAULT_SIZE != 521)
|
||||||
|
&& !svr_opts.hostkey->ecckey521) {
|
||||||
disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP521);
|
disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP521);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif /* DROPBEAR_ECDSA */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -104,21 +104,22 @@
|
|||||||
#define DROPBEAR_LTC_PRNG
|
#define DROPBEAR_LTC_PRNG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// hashes which will be linked and registered
|
/* hashes which will be linked and registered */
|
||||||
#if defined(DROPBEAR_SHA2_256_HMAC) || defined(DROPBEAR_ECC_256)
|
#if defined(DROPBEAR_SHA2_256_HMAC) || defined(DROPBEAR_ECC_256)
|
||||||
#define DROPBEAR_SHA256
|
#define DROPBEAR_SHA256
|
||||||
#endif
|
#endif
|
||||||
#if defined(DROPBEAR_ECC_384)
|
#if defined(DROPBEAR_ECC_384)
|
||||||
#define DROPBEAR_SHA384
|
#define DROPBEAR_SHA384
|
||||||
#endif
|
#endif
|
||||||
#if defined(DROPBEAR_SHA2_512_HMAC) || defined(DROPBEAR_ECC_521)
|
/* LTC SHA384 depends on SHA512 */
|
||||||
|
#if defined(DROPBEAR_SHA2_512_HMAC) || defined(DROPBEAR_ECC_521) || defined(DROPBEAR_ECC_384)
|
||||||
#define DROPBEAR_SHA512
|
#define DROPBEAR_SHA512
|
||||||
#endif
|
#endif
|
||||||
#if defined(DROPBEAR_MD5_HMAC)
|
#if defined(DROPBEAR_MD5_HMAC)
|
||||||
#define DROPBEAR_MD5
|
#define DROPBEAR_MD5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// roughly 2x 521 bits
|
/* roughly 2x 521 bits */
|
||||||
#define MAX_ECC_SIZE 140
|
#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
|
||||||
|
Loading…
Reference in New Issue
Block a user