mirror of
https://github.com/clearml/dropbear
synced 2025-04-08 06:34:23 +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 \
|
||||
queue.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 \
|
||||
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 \
|
||||
common-runopts.o circbuffer.o curve25519-donna.o
|
||||
|
||||
KEYOBJS=dropbearkey.o gendss.o genrsa.o
|
||||
KEYOBJS=dropbearkey.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"))
|
||||
}
|
||||
|
||||
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;
|
||||
FILE *tty = NULL;
|
||||
@ -192,14 +193,16 @@ static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
|
||||
fp = sign_key_fingerprint(keyblob, keybloblen);
|
||||
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,
|
||||
algoname,
|
||||
fp);
|
||||
m_free(fp);
|
||||
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,
|
||||
algoname,
|
||||
fp);
|
||||
m_free(fp);
|
||||
|
||||
@ -294,16 +297,17 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
return;
|
||||
}
|
||||
|
||||
algoname = signkey_name_from_type(ses.newkeys->algo_hostkey, &algolen);
|
||||
|
||||
hostsfile = open_known_hosts_file(&readonly);
|
||||
if (!hostsfile) {
|
||||
ask_to_confirm(keyblob, keybloblen);
|
||||
ask_to_confirm(keyblob, keybloblen, algoname);
|
||||
/* ask_to_confirm will exit upon failure */
|
||||
return;
|
||||
}
|
||||
|
||||
line = buf_new(MAX_KNOWNHOSTS_LINE);
|
||||
hostlen = strlen(cli_opts.remotehost);
|
||||
algoname = signkey_name_from_type(ses.newkeys->algo_hostkey, &algolen);
|
||||
|
||||
do {
|
||||
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 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"
|
||||
"Expected %s\n"
|
||||
"If you know that the host key is correct you can\nremove the bad entry from ~/.ssh/known_hosts",
|
||||
algoname,
|
||||
cli_opts.remotehost,
|
||||
sign_key_fingerprint(keyblob, keybloblen),
|
||||
fingerprint ? fingerprint : "UNKNOWN");
|
||||
} while (1); /* keep going 'til something happens */
|
||||
|
||||
/* Key doesn't exist yet */
|
||||
ask_to_confirm(keyblob, keybloblen);
|
||||
ask_to_confirm(keyblob, keybloblen, algoname);
|
||||
|
||||
/* 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.
|
||||
You will need to pass "-F" as well. */
|
||||
/* #define DEBUG_NOFORK */
|
||||
#define DEBUG_NOFORK
|
||||
|
||||
|
||||
|
172
dropbearkey.c
172
dropbearkey.c
@ -54,15 +54,13 @@
|
||||
#include "ecdsa.h"
|
||||
#include "crypto_desc.h"
|
||||
#include "random.h"
|
||||
#include "gensignkey.h"
|
||||
|
||||
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 justprintpub(const char* filename);
|
||||
static int printpubfile(const char* filename);
|
||||
|
||||
/* Print a help message */
|
||||
static void printhelp(char * progname) {
|
||||
@ -103,6 +101,30 @@ static void printhelp(char * 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)
|
||||
int dropbearkey_main(int argc, char ** argv) {
|
||||
@ -112,13 +134,11 @@ int main(int argc, char ** argv) {
|
||||
|
||||
int i;
|
||||
char ** next = 0;
|
||||
sign_key *key = NULL;
|
||||
buffer *buf = NULL;
|
||||
char * filename = NULL;
|
||||
enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE;
|
||||
char * typetext = NULL;
|
||||
char * sizetext = NULL;
|
||||
unsigned int bits;
|
||||
unsigned int bits = 0;
|
||||
int printpub = 0;
|
||||
|
||||
crypto_init();
|
||||
@ -174,8 +194,8 @@ int main(int argc, char ** argv) {
|
||||
}
|
||||
|
||||
if (printpub) {
|
||||
justprintpub(filename);
|
||||
/* Not reached */
|
||||
int ret = printpubfile(filename);
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
/* check/parse args */
|
||||
@ -216,106 +236,22 @@ int main(int argc, char ** argv) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// TODO: put RSA and DSS size checks into genrsa.c etc
|
||||
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 */
|
||||
}
|
||||
check_signkey_bits(keytype, bits);;
|
||||
}
|
||||
|
||||
} 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");
|
||||
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:
|
||||
{
|
||||
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);
|
||||
}
|
||||
if (signkey_generate(keytype, bits, filename) == DROPBEAR_FAILURE)
|
||||
{
|
||||
dropbear_exit("Failed to generate key.\n");
|
||||
}
|
||||
|
||||
buf = buf_new(MAX_PRIVKEY_SIZE);
|
||||
|
||||
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);
|
||||
printpubfile(filename);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void justprintpub(const char* filename) {
|
||||
static int printpubfile(const char* filename) {
|
||||
|
||||
buffer *buf = NULL;
|
||||
sign_key *key = NULL;
|
||||
@ -353,7 +289,7 @@ out:
|
||||
sign_key_free(key);
|
||||
key = NULL;
|
||||
}
|
||||
exit(err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void printpubkey(sign_key * key, int keytype) {
|
||||
@ -402,35 +338,3 @@ static void printpubkey(sign_key * key, int keytype) {
|
||||
m_free(fp);
|
||||
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
|
||||
|
||||
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) {
|
||||
#ifdef DROPBEAR_ECC_256
|
||||
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);
|
||||
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
|
||||
|
||||
|
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;
|
||||
sign_key *ret = NULL;
|
||||
int type;
|
||||
enum signkey_type type;
|
||||
|
||||
buf = buf_new(MAX_PRIVKEY_SIZE);
|
||||
if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) {
|
||||
@ -501,7 +501,7 @@ static int openssh_encrypted(const char *filename)
|
||||
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;
|
||||
unsigned char *p;
|
||||
@ -511,7 +511,7 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
|
||||
char *errmsg;
|
||||
char *modptr = NULL;
|
||||
int modlen = -9999;
|
||||
int type;
|
||||
enum signkey_type type;
|
||||
|
||||
sign_key *retkey;
|
||||
buffer * blobbuf = NULL;
|
||||
@ -709,19 +709,29 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
|
||||
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) {
|
||||
retkey->type = DROPBEAR_SIGNKEY_ECDSA_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) {
|
||||
retkey->type = DROPBEAR_SIGNKEY_ECDSA_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) {
|
||||
retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP521;
|
||||
curve = &ecc_curve_nistp521;
|
||||
} else {
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
errmsg = "Unknown ECC key type";
|
||||
goto error;
|
||||
}
|
||||
@ -1019,7 +1029,7 @@ static int openssh_write(const char *filename, sign_key *key,
|
||||
*/
|
||||
buffer *seq_buf = buf_new(400);
|
||||
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;
|
||||
const void* curve_oid = NULL;
|
||||
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"
|
||||
* 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
|
||||
#define DROPBEAR_DEFPORT "22"
|
||||
@ -129,7 +129,7 @@ much traffic. */
|
||||
|
||||
/* 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
|
||||
* 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 */
|
||||
|
||||
/* Hostkey/public key algorithms - at least one required, these are used
|
||||
@ -138,10 +138,14 @@ much traffic. */
|
||||
* SSH2 RFC Draft requires dss, recommends rsa */
|
||||
#define DROPBEAR_RSA
|
||||
#define DROPBEAR_DSS
|
||||
|
||||
#define DROPBEAR_ECDH
|
||||
#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
|
||||
|
||||
/* RSA can be vulnerable to timing attacks which use the time required for
|
||||
@ -149,6 +153,9 @@ much traffic. */
|
||||
* signing operations slightly slower. */
|
||||
#define RSA_BLINDING
|
||||
|
||||
/* Enable elliptic curve Diffie Hellman key exchange */
|
||||
#define DROPBEAR_ECDH
|
||||
|
||||
/* Control the memory/performance/compression tradeoff for zlib.
|
||||
* Set windowBits=8 for least memory usage, see your system's
|
||||
* zlib.h for full details.
|
||||
@ -184,7 +191,7 @@ much traffic. */
|
||||
|
||||
#define ENABLE_SVR_PASSWORD_AUTH
|
||||
/* PAM requires ./configure --enable-pam */
|
||||
//#define ENABLE_SVR_PAM_AUTH
|
||||
/*#define ENABLE_SVR_PAM_AUTH */
|
||||
#define ENABLE_SVR_PUBKEY_AUTH
|
||||
|
||||
/* Whether to take public key options in
|
||||
|
@ -100,6 +100,8 @@ typedef struct svr_runopts {
|
||||
|
||||
sign_key *hostkey;
|
||||
|
||||
int delay_hostkey;
|
||||
|
||||
char *hostkey_files[MAX_HOSTKEYS];
|
||||
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
|
||||
#ifdef DROPBEAR_ECDSA
|
||||
{
|
||||
if (signkey_is_ecdsa(keytype)) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
||||
if (eck) {
|
||||
if (*eck) {
|
||||
@ -249,7 +249,7 @@ int buf_get_priv_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
||||
}
|
||||
#endif
|
||||
#ifdef DROPBEAR_ECDSA
|
||||
{
|
||||
if (signkey_is_ecdsa(keytype)) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
||||
if (eck) {
|
||||
if (*eck) {
|
||||
@ -289,10 +289,7 @@ void buf_put_pub_key(buffer* buf, sign_key *key, enum signkey_type type) {
|
||||
}
|
||||
#endif
|
||||
#ifdef DROPBEAR_ECDSA
|
||||
if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP256
|
||||
|| type == DROPBEAR_SIGNKEY_ECDSA_NISTP384
|
||||
|| type == DROPBEAR_SIGNKEY_ECDSA_NISTP521)
|
||||
{
|
||||
if (signkey_is_ecdsa(type)) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
||||
if (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
|
||||
#ifdef DROPBEAR_ECDSA
|
||||
{
|
||||
if (signkey_is_ecdsa(type)) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
||||
if (eck) {
|
||||
buf_put_ecdsa_priv_key(buf, *eck);
|
||||
@ -354,18 +351,24 @@ void sign_key_free(sign_key *key) {
|
||||
key->rsakey = NULL;
|
||||
#endif
|
||||
#ifdef DROPBEAR_ECDSA
|
||||
#ifdef DROPBEAR_ECC_256
|
||||
if (key->ecckey256) {
|
||||
ecc_free(key->ecckey256);
|
||||
key->ecckey256 = NULL;
|
||||
}
|
||||
#endif
|
||||
#ifdef DROPBEAR_ECC_384
|
||||
if (key->ecckey384) {
|
||||
ecc_free(key->ecckey384);
|
||||
key->ecckey384 = NULL;
|
||||
}
|
||||
#endif
|
||||
#ifdef DROPBEAR_ECC_521
|
||||
if (key->ecckey521) {
|
||||
ecc_free(key->ecckey521);
|
||||
key->ecckey521 = NULL;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_free(key->filename);
|
||||
@ -484,7 +487,7 @@ void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type type,
|
||||
}
|
||||
#endif
|
||||
#ifdef DROPBEAR_ECDSA
|
||||
{
|
||||
if (signkey_is_ecdsa(type)) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
||||
if (eck) {
|
||||
buf_put_ecdsa_sign(sigblob, *eck, data_buf);
|
||||
@ -535,7 +538,7 @@ int buf_verify(buffer * buf, sign_key *key, buffer *data_buf) {
|
||||
}
|
||||
#endif
|
||||
#ifdef DROPBEAR_ECDSA
|
||||
{
|
||||
if (signkey_is_ecdsa(type)) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
||||
if (eck) {
|
||||
return buf_ecdsa_verify(buf, *eck, data_buf);
|
||||
|
89
svr-kex.c
89
svr-kex.c
@ -35,6 +35,7 @@
|
||||
#include "random.h"
|
||||
#include "runopts.h"
|
||||
#include "ecc.h"
|
||||
#include "gensignkey.h"
|
||||
|
||||
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;
|
||||
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
|
||||
* 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 */
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
#ifdef DROPBEAR_DELAY_HOSTKEY
|
||||
if (svr_opts.delay_hostkey)
|
||||
{
|
||||
svr_ensure_hostkey();
|
||||
}
|
||||
#endif
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY);
|
||||
buf_put_pub_key(ses.writepayload, svr_opts.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:
|
||||
#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);
|
||||
buf_putstring(ses.writepayload, param->priv, CURVE25519_LEN);
|
||||
free_kexcurve25519_param(param);
|
||||
|
@ -44,13 +44,19 @@ static void printhelp(const char * progname) {
|
||||
"-b bannerfile Display the contents of bannerfile"
|
||||
" before user login\n"
|
||||
" (default: none)\n"
|
||||
"-r keyfile Specify hostkeys (repeatable)\n"
|
||||
" defaults: \n"
|
||||
#ifdef DROPBEAR_DSS
|
||||
"-d dsskeyfile Use dsskeyfile for the DSS host key\n"
|
||||
" (default: %s)\n"
|
||||
" dss %s\n"
|
||||
#endif
|
||||
#ifdef DROPBEAR_RSA
|
||||
"-r rsakeyfile Use rsakeyfile for the RSA host key\n"
|
||||
" (default: %s)\n"
|
||||
" rsa %s\n"
|
||||
#endif
|
||||
#ifdef DROPBEAR_ECDSA
|
||||
" ecdsa %s\n"
|
||||
#endif
|
||||
#ifdef DROPBEAR_DELAY_HOSTKEY
|
||||
"-R Create hostkeys as required\n"
|
||||
#endif
|
||||
"-F Don't fork into background\n"
|
||||
#ifdef DISABLE_SYSLOG
|
||||
@ -95,6 +101,9 @@ static void printhelp(const char * progname) {
|
||||
#endif
|
||||
#ifdef DROPBEAR_RSA
|
||||
RSA_PRIV_FILENAME,
|
||||
#endif
|
||||
#ifdef DROPBEAR_ECDSA
|
||||
ECDSA_PRIV_FILENAME,
|
||||
#endif
|
||||
DROPBEAR_MAX_PORTS, DROPBEAR_DEFPORT, DROPBEAR_PIDFILE,
|
||||
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.portcount = 0;
|
||||
svr_opts.hostkey = NULL;
|
||||
svr_opts.delay_hostkey = 0;
|
||||
svr_opts.pidfile = DROPBEAR_PIDFILE;
|
||||
#ifdef ENABLE_SVR_LOCALTCPFWD
|
||||
svr_opts.nolocaltcp = 0;
|
||||
@ -180,6 +190,9 @@ void svr_getopts(int argc, char ** argv) {
|
||||
case 'r':
|
||||
next = &keyfile;
|
||||
break;
|
||||
case 'R':
|
||||
svr_opts.delay_hostkey = 1;
|
||||
break;
|
||||
case 'F':
|
||||
svr_opts.forkbg = 0;
|
||||
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 */
|
||||
static void loadhostkey(const char *keyfile, int fatal_duplicate) {
|
||||
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) {
|
||||
dropbear_log(LOG_WARNING, "Failed loading %s", keyfile);
|
||||
}
|
||||
@ -438,6 +451,7 @@ static void addhostkey(const char *keyfile) {
|
||||
|
||||
void load_all_hostkeys() {
|
||||
int i;
|
||||
int disable_unset_keys = 1;
|
||||
|
||||
svr_opts.hostkey = new_sign_key();
|
||||
|
||||
@ -459,31 +473,47 @@ void load_all_hostkeys() {
|
||||
loadhostkey(ECDSA_PRIV_FILENAME, 0);
|
||||
#endif
|
||||
|
||||
#ifdef DROPBEAR_DELAY_HOSTKEY
|
||||
if (svr_opts.delay_hostkey)
|
||||
{
|
||||
disable_unset_keys = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DROPBEAR_RSA
|
||||
if (!svr_opts.hostkey->rsakey) {
|
||||
if (disable_unset_keys && !svr_opts.hostkey->rsakey) {
|
||||
disablekey(DROPBEAR_SIGNKEY_RSA);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DROPBEAR_DSS
|
||||
if (!svr_opts.hostkey->dsskey) {
|
||||
if (disable_unset_keys && !svr_opts.hostkey->dsskey) {
|
||||
disablekey(DROPBEAR_SIGNKEY_RSA);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef DROPBEAR_ECDSA
|
||||
#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);
|
||||
}
|
||||
#endif
|
||||
|
||||
#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);
|
||||
}
|
||||
#endif
|
||||
|
||||
#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);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif /* DROPBEAR_ECDSA */
|
||||
|
||||
}
|
||||
|
@ -104,21 +104,22 @@
|
||||
#define DROPBEAR_LTC_PRNG
|
||||
#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)
|
||||
#define DROPBEAR_SHA256
|
||||
#endif
|
||||
#if defined(DROPBEAR_ECC_384)
|
||||
#define DROPBEAR_SHA384
|
||||
#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
|
||||
#endif
|
||||
#if defined(DROPBEAR_MD5_HMAC)
|
||||
#define DROPBEAR_MD5
|
||||
#endif
|
||||
|
||||
// roughly 2x 521 bits
|
||||
/* roughly 2x 521 bits */
|
||||
#define MAX_ECC_SIZE 140
|
||||
|
||||
#define MAX_NAME_LEN 64 /* maximum length of a protocol name, isn't
|
||||
|
Loading…
Reference in New Issue
Block a user