# HG changeset patch # User Matt Johnston # Date 1367162263 -28800 # Node ID d386defb5376f7cc80803364b2970335218a53e6 # Parent 70625eed40c99b176b7f86ad08007bd77a9723d6 more ecdsa signkey work, not correct diff -r 70625eed40c9 -r d386defb5376 dropbearkey.c --- a/dropbearkey.c Sun Apr 14 00:50:03 2013 +0800 +++ b/dropbearkey.c Sun Apr 28 23:17:43 2013 +0800 @@ -51,11 +51,13 @@ #include "genrsa.h" #include "gendss.h" +#include "ecdsa.h" +#include "crypto_desc.h" static void printhelp(char * progname); -#define RSA_SIZE (1024/8) /* 1024 bit */ -#define DSS_SIZE (1024/8) /* 1024 bit */ +#define RSA_DEFAULT_SIZE 1024 +#define DSS_DEFAULT_SIZE 1024 static void buf_writefile(buffer * buf, const char * filename); static void printpubkey(sign_key * key, int keytype); @@ -72,9 +74,27 @@ #ifdef DROPBEAR_DSS " dss\n" #endif +#ifdef DROPBEAR_ECDSA + " ecdsa\n" +#endif "-f filename Use filename for the secret key\n" "-s bits Key size in bits, should be a multiple of 8 (optional)\n" - " (DSS has a fixed size of 1024 bits)\n" +#ifdef DROPBEAR_DSS + " DSS has a fixed size of 1024 bits\n" +#endif +#ifdef DROPBEAR_ECDSA + " ECDSA has sizes " +#ifdef DROPBEAR_ECC_256 + "256 " +#endif +#ifdef DROPBEAR_ECC_384 + "384 " +#endif +#ifdef DROPBEAR_ECC_521 + "521 " +#endif + "\n" +#endif "-y Just print the publickey and fingerprint for the\n private key in .\n" #ifdef DEBUG_TRACE "-v verbose\n" @@ -94,11 +114,10 @@ sign_key *key = NULL; buffer *buf = NULL; char * filename = NULL; - int keytype = -1; + enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE; char * typetext = NULL; char * sizetext = NULL; unsigned int bits; - unsigned int keysize; int printpub = 0; /* get the commandline options */ @@ -162,21 +181,9 @@ exit(EXIT_FAILURE); } - if (strlen(typetext) == 3) { -#ifdef DROPBEAR_RSA - if (strncmp(typetext, "rsa", 3) == 0) { - keytype = DROPBEAR_SIGNKEY_RSA; - TRACE(("type is rsa")) - } -#endif -#ifdef DROPBEAR_DSS - if (strncmp(typetext, "dss", 3) == 0) { - keytype = DROPBEAR_SIGNKEY_DSS; - TRACE(("type is dss")) - } -#endif - } - if (keytype == -1) { + keytype = signkey_type_from_name(typetext, strlen(typetext)); + + if (keytype == DROPBEAR_SIGNKEY_NONE) { fprintf(stderr, "Unknown key type '%s'\n", typetext); printhelp(argv[0]); exit(EXIT_FAILURE); @@ -197,25 +204,29 @@ " multiple of 8\n"); exit(EXIT_FAILURE); } - - keysize = bits / 8; } else { if (keytype == DROPBEAR_SIGNKEY_DSS) { - keysize = DSS_SIZE; + bits = DSS_DEFAULT_SIZE; } else if (keytype == DROPBEAR_SIGNKEY_RSA) { - keysize = RSA_SIZE; + bits = RSA_DEFAULT_SIZE; + } else if (keytype == DROPBEAR_SIGNKEY_ECDSA_KEYGEN) { + bits = ECDSA_DEFAULT_SIZE; } else { exit(EXIT_FAILURE); /* not reached */ } } - fprintf(stderr, "Will output %d bit %s secret key to '%s'\n", keysize*8, + 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); + crypto_init(); + seedrandom(); + + /* now we can generate the key */ key = new_sign_key(); @@ -223,12 +234,17 @@ switch(keytype) { #ifdef DROPBEAR_RSA case DROPBEAR_SIGNKEY_RSA: - key->rsakey = gen_rsa_priv_key(keysize); /* 128 bytes = 1024 bit */ + key->rsakey = gen_rsa_priv_key(bits); break; #endif #ifdef DROPBEAR_DSS case DROPBEAR_SIGNKEY_DSS: - key->dsskey = gen_dss_priv_key(keysize); /* 128 bytes = 1024 bit */ + key->dsskey = gen_dss_priv_key(bits); + break; +#endif +#ifdef DROPBEAR_ECDSA + case DROPBEAR_SIGNKEY_ECDSA_KEYGEN: + key->ecckey = gen_ecdsa_priv_key(bits); break; #endif default: @@ -320,7 +336,7 @@ fprintf(stderr, "base64 failed"); } - typestring = signkey_name_from_type(keytype, &err); + typestring = signkey_name_from_type(keytype, NULL); fp = sign_key_fingerprint(buf_getptr(buf, len), len); diff -r 70625eed40c9 -r d386defb5376 dss.h --- a/dss.h Sun Apr 14 00:50:03 2013 +0800 +++ b/dss.h Sun Apr 28 23:17:43 2013 +0800 @@ -30,8 +30,6 @@ #ifdef DROPBEAR_DSS -#define DSS_SIGNATURE_SIZE 4+SSH_SIGNKEY_DSS_LEN+4+2*SHA1_HASH_SIZE - typedef struct { mp_int* p; diff -r 70625eed40c9 -r d386defb5376 ecdsa.c --- a/ecdsa.c Sun Apr 14 00:50:03 2013 +0800 +++ b/ecdsa.c Sun Apr 28 23:17:43 2013 +0800 @@ -1,3 +1,4 @@ +#include "options.h" #include "includes.h" #include "dbutil.h" #include "crypto_desc.h" @@ -8,7 +9,6 @@ ecc_key *gen_ecdsa_priv_key(unsigned int bit_size) { const ltc_ecc_set_type *dp = NULL; // curve domain parameters - // TODO: use raw bytes for the dp rather than the hex strings in libtomcrypt's ecc.c switch (bit_size) { #ifdef DROPBEAR_ECC_256 case 256: diff -r 70625eed40c9 -r d386defb5376 ecdsa.h --- a/ecdsa.h Sun Apr 14 00:50:03 2013 +0800 +++ b/ecdsa.h Sun Apr 28 23:17:43 2013 +0800 @@ -4,6 +4,16 @@ #include "includes.h" #include "buffer.h" +#ifdef DROPBEAR_ECC_256 +#define ECDSA_DEFAULT_SIZE 256 +#elif DROPBEAR_ECC_384 +#define ECDSA_DEFAULT_SIZE 384 +#elif DROPBEAR_ECC_521 +#define ECDSA_DEFAULT_SIZE 521 +#else +#define ECDSA_DEFAULT_SIZE 0 +#endif + ecc_key *gen_ecdsa_priv_key(unsigned int bit_size); ecc_key *buf_get_ecdsa_pub_key(buffer* buf); ecc_key *buf_get_ecdsa_priv_key(buffer *buf); diff -r 70625eed40c9 -r d386defb5376 gendss.c --- a/gendss.c Sun Apr 14 00:50:03 2013 +0800 +++ b/gendss.c Sun Apr 28 23:17:43 2013 +0800 @@ -47,6 +47,10 @@ dropbear_dss_key *key; + if (size != 1024) { + dropbear_exit("DSS keys have a fixed size of 1024 bits"); + } + key = m_malloc(sizeof(*key)); key->p = (mp_int*)m_malloc(sizeof(mp_int)); @@ -56,10 +60,8 @@ key->x = (mp_int*)m_malloc(sizeof(mp_int)); m_mp_init_multi(key->p, key->q, key->g, key->y, key->x, NULL); - seedrandom(); - getq(key); - getp(key, size); + getp(key, size/8); getg(key); getx(key); gety(key); diff -r 70625eed40c9 -r d386defb5376 genrsa.c --- a/genrsa.c Sun Apr 14 00:50:03 2013 +0800 +++ b/genrsa.c Sun Apr 28 23:17:43 2013 +0800 @@ -34,7 +34,7 @@ #ifdef DROPBEAR_RSA static void getrsaprime(mp_int* prime, mp_int *primeminus, - mp_int* rsa_e, unsigned int size); + mp_int* rsa_e, unsigned int size_bytes); /* mostly taken from libtomcrypt's rsa key generation routine */ dropbear_rsa_key * gen_rsa_priv_key(unsigned int size) { @@ -44,6 +44,11 @@ DEF_MP_INT(qminus); DEF_MP_INT(lcm); + if (size < 512 || size > 4096 || (size % 8 != 0)) { + dropbear_exit("Bits must satisfy 512 <= bits <= 4096, and be a" + " multiple of 8"); + } + key = m_malloc(sizeof(*key)); key->e = (mp_int*)m_malloc(sizeof(mp_int)); @@ -55,15 +60,13 @@ m_mp_init_multi(key->e, key->n, key->d, key->p, key->q, &pminus, &lcm, &qminus, NULL); - seedrandom(); - if (mp_set_int(key->e, RSA_E) != MP_OKAY) { fprintf(stderr, "RSA generation failed\n"); exit(1); } - getrsaprime(key->p, &pminus, key->e, size/2); - getrsaprime(key->q, &qminus, key->e, size/2); + getrsaprime(key->p, &pminus, key->e, size/16); + getrsaprime(key->q, &qminus, key->e, size/16); if (mp_mul(key->p, key->q, key->n) != MP_OKAY) { fprintf(stderr, "RSA generation failed\n"); @@ -90,21 +93,21 @@ /* return a prime suitable for p or q */ static void getrsaprime(mp_int* prime, mp_int *primeminus, - mp_int* rsa_e, unsigned int size) { + mp_int* rsa_e, unsigned int size_bytes) { unsigned char *buf; DEF_MP_INT(temp_gcd); - buf = (unsigned char*)m_malloc(size+1); + buf = (unsigned char*)m_malloc(size_bytes+1); m_mp_init(&temp_gcd); do { /* generate a random odd number with MSB set, then find the the next prime above it */ - genrandom(buf, size+1); + genrandom(buf, size_bytes+1); buf[0] |= 0x80; /* MSB set */ - bytes_to_mp(prime, buf, size+1); + bytes_to_mp(prime, buf, size_bytes+1); /* find the next integer which is prime, 8 round of miller-rabin */ if (mp_prime_next_prime(prime, 8, 0) != MP_OKAY) { @@ -126,7 +129,7 @@ /* now we have a good value for result */ mp_clear(&temp_gcd); - m_burn(buf, size+1); + m_burn(buf, size_bytes+1); m_free(buf); } diff -r 70625eed40c9 -r d386defb5376 signkey.c --- a/signkey.c Sun Apr 14 00:50:03 2013 +0800 +++ b/signkey.c Sun Apr 28 23:17:43 2013 +0800 @@ -27,6 +27,28 @@ #include "signkey.h" #include "buffer.h" #include "ssh.h" +#include "ecdsa.h" + +static const char *signkey_names[DROPBEAR_SIGNKEY_NUM_NAMED] = { +#ifdef DROPBEAR_RSA + "ssh-rsa", +#endif +#ifdef DROPBEAR_DSS + "ssh-dss", +#endif +#ifdef DROPBEAR_ECDSA +#ifdef DROPBEAR_ECC_256 + "ecdsa-sha2-nistp256", +#endif +#ifdef DROPBEAR_ECC_384 + "ecdsa-sha2-nistp384", +#endif +#ifdef DROPBEAR_ECC_521 + "ecdsa-sha2-nistp521", +#endif + "ecdsa" // for keygen +#endif // DROPBEAR_ECDSA +}; /* malloc a new sign_key and set the dss and rsa keys to NULL */ sign_key * new_sign_key() { @@ -39,42 +61,29 @@ return ret; } -/* Returns "ssh-dss" or "ssh-rsa" corresponding to the type. Exits fatally +/* Returns key name corresponding to the type. Exits fatally * if the type is invalid */ -const char* signkey_name_from_type(int type, int *namelen) { - -#ifdef DROPBEAR_RSA - if (type == DROPBEAR_SIGNKEY_RSA) { - *namelen = SSH_SIGNKEY_RSA_LEN; - return SSH_SIGNKEY_RSA; +const char* signkey_name_from_type(enum signkey_type type, unsigned int *namelen) { + if (type >= DROPBEAR_SIGNKEY_NUM_NAMED) { + dropbear_exit("Bad key type %d", type); } -#endif -#ifdef DROPBEAR_DSS - if (type == DROPBEAR_SIGNKEY_DSS) { - *namelen = SSH_SIGNKEY_DSS_LEN; - return SSH_SIGNKEY_DSS; + + if (namelen) { + *namelen = strlen(signkey_names[type]); } -#endif - dropbear_exit("Bad key type %d", type); - return NULL; /* notreached */ + return signkey_names[type]; } -/* Returns DROPBEAR_SIGNKEY_RSA, DROPBEAR_SIGNKEY_DSS, - * or DROPBEAR_SIGNKEY_NONE */ -int signkey_type_from_name(const char* name, int namelen) { - -#ifdef DROPBEAR_RSA - if (namelen == SSH_SIGNKEY_RSA_LEN - && memcmp(name, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN) == 0) { - return DROPBEAR_SIGNKEY_RSA; +/* Returns DROPBEAR_SIGNKEY_NONE if none match */ +enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen) { + int i; + for (i = 0; i < DROPBEAR_SIGNKEY_NUM_NAMED; i++) { + const char *fixed_name = signkey_names[i]; + if (namelen == strlen(fixed_name) + && memcmp(fixed_name, name, namelen) == 0) { + return i; + } } -#endif -#ifdef DROPBEAR_DSS - if (namelen == SSH_SIGNKEY_DSS_LEN - && memcmp(name, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN) == 0) { - return DROPBEAR_SIGNKEY_DSS; - } -#endif TRACE(("signkey_type_from_name unexpected key type.")) @@ -129,6 +138,19 @@ } } #endif +#ifdef DROPBEAR_ECDSA + if (keytype == DROPBEAR_SIGNKEY_ECDSA_NISTP256 + || keytype == DROPBEAR_SIGNKEY_ECDSA_NISTP384 + || keytype == DROPBEAR_SIGNKEY_ECDSA_NISTP521) { + if (key->ecckey) { + ecc_free(key->ecckey); + } + key->ecckey = buf_get_ecdsa_pub_key(buf); + if (key->ecckey) { + ret = DROPBEAR_SUCCESS; + } + } +#endif TRACE(("leave buf_get_pub_key")) @@ -182,6 +204,19 @@ } } #endif +#ifdef DROPBEAR_ECDSA + if (keytype == DROPBEAR_SIGNKEY_ECDSA_NISTP256 + || keytype == DROPBEAR_SIGNKEY_ECDSA_NISTP384 + || keytype == DROPBEAR_SIGNKEY_ECDSA_NISTP521) { + if (key->ecckey) { + ecc_free(key->ecckey); + } + key->ecckey = buf_get_ecdsa_priv_key(buf); + if (key->ecckey) { + ret = DROPBEAR_SUCCESS; + } + } +#endif TRACE(("leave buf_get_priv_key")) @@ -207,6 +242,13 @@ buf_put_rsa_pub_key(pubkeys, key->rsakey); } #endif +#ifdef DROPBEAR_ECDSA + if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP256 + || type == DROPBEAR_SIGNKEY_ECDSA_NISTP384 + || type == DROPBEAR_SIGNKEY_ECDSA_NISTP521) { + buf_put_ecdsa_pub_key(pubkeys, key->ecckey); + } +#endif if (pubkeys->len == 0) { dropbear_exit("Bad key types in buf_put_pub_key"); } @@ -236,6 +278,14 @@ return; } #endif +#ifdef DROPBEAR_ECDSA + if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP256 + || type == DROPBEAR_SIGNKEY_ECDSA_NISTP384 + || type == DROPBEAR_SIGNKEY_ECDSA_NISTP521) { + buf_put_ecdsa_pub_key(buf, key->ecckey); + return; + } +#endif dropbear_exit("Bad key types in put pub key"); } @@ -251,6 +301,12 @@ rsa_key_free(key->rsakey); key->rsakey = NULL; #endif +#ifdef DROPBEAR_ECDSA + if (key->ecckey) { + ecc_free(key->ecckey); + key->ecckey = NULL; + } +#endif m_free(key->filename); @@ -259,7 +315,6 @@ } static char hexdig(unsigned char x) { - if (x > 0xf) return 'X'; @@ -323,14 +378,14 @@ sha1_done(&hs, hash); - /* "sha1 hexfingerprinthere\0", each hex digit is "AB:" etc */ - buflen = 5 + 3*SHA1_HASH_SIZE; + /* "sha1!! hexfingerprinthere\0", each hex digit is "AB:" etc */ + buflen = 7 + 3*SHA1_HASH_SIZE; ret = (char*)m_malloc(buflen); - strcpy(ret, "sha1 "); + strcpy(ret, "sha1!! "); for (i = 0; i < SHA1_HASH_SIZE; i++) { - unsigned int pos = 5 + 3*i; + unsigned int pos = 7 + 3*i; ret[pos] = hexdig(hash[i] >> 4); ret[pos+1] = hexdig(hash[i] & 0x0f); ret[pos+2] = ':'; @@ -368,6 +423,13 @@ buf_put_rsa_sign(sigblob, key->rsakey, data_buf); } #endif +#ifdef DROPBEAR_ECDSA + if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP256 + || type == DROPBEAR_SIGNKEY_ECDSA_NISTP384 + || type == DROPBEAR_SIGNKEY_ECDSA_NISTP521) { + buf_put_ecdsa_sign(sigblob, key->ecckey, data_buf); + } +#endif if (sigblob->len == 0) { dropbear_exit("Non-matching signing type"); } @@ -384,18 +446,18 @@ int buf_verify(buffer * buf, sign_key *key, buffer *data_buf) { unsigned int bloblen; - unsigned char * ident = NULL; - unsigned int identlen = 0; + unsigned char * type_name = NULL; + unsigned int type_name_len = 0; TRACE(("enter buf_verify")) bloblen = buf_getint(buf); - ident = buf_getstring(buf, &identlen); + type_name = buf_getstring(buf, &type_name_len); + enum signkey_type type = signkey_type_from_name(type_name, type_name_len); + m_free(type_name); #ifdef DROPBEAR_DSS - if (bloblen == DSS_SIGNATURE_SIZE && - memcmp(ident, SSH_SIGNKEY_DSS, identlen) == 0) { - m_free(ident); + if (type == DROPBEAR_SIGNKEY_DSS) { if (key->dsskey == NULL) { dropbear_exit("No DSS key to verify signature"); } @@ -404,16 +466,21 @@ #endif #ifdef DROPBEAR_RSA - if (memcmp(ident, SSH_SIGNKEY_RSA, identlen) == 0) { - m_free(ident); + if (type == DROPBEAR_SIGNKEY_RSA) { if (key->rsakey == NULL) { dropbear_exit("No RSA key to verify signature"); } return buf_rsa_verify(buf, key->rsakey, data_buf); } #endif +#ifdef DROPBEAR_ECDSA + if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP256 + || type == DROPBEAR_SIGNKEY_ECDSA_NISTP384 + || type == DROPBEAR_SIGNKEY_ECDSA_NISTP521) { + return buf_ecdsa_verify(buf, key->ecckey, data_buf); + } +#endif - m_free(ident); dropbear_exit("Non-matching signing type"); return DROPBEAR_FAILURE; } diff -r 70625eed40c9 -r d386defb5376 signkey.h --- a/signkey.h Sun Apr 14 00:50:03 2013 +0800 +++ b/signkey.h Sun Apr 28 23:17:43 2013 +0800 @@ -29,6 +29,30 @@ #include "dss.h" #include "rsa.h" +enum signkey_type { +#ifdef DROPBEAR_RSA + DROPBEAR_SIGNKEY_RSA, +#endif +#ifdef DROPBEAR_DSS + DROPBEAR_SIGNKEY_DSS, +#endif +#ifdef DROPBEAR_ECDSA +#ifdef DROPBEAR_ECC_256 + DROPBEAR_SIGNKEY_ECDSA_NISTP256, +#endif +#ifdef DROPBEAR_ECC_384 + DROPBEAR_SIGNKEY_ECDSA_NISTP384, +#endif +#ifdef DROPBEAR_ECC_521 + DROPBEAR_SIGNKEY_ECDSA_NISTP521, +#endif + DROPBEAR_SIGNKEY_ECDSA_KEYGEN, // just "ecdsa" for keygen +#endif // DROPBEAR_ECDSA + DROPBEAR_SIGNKEY_NUM_NAMED, + DROPBEAR_SIGNKEY_ANY = 80, + DROPBEAR_SIGNKEY_NONE = 90, +}; + /* Sources for signing keys */ typedef enum { @@ -59,8 +83,8 @@ typedef struct SIGN_key sign_key; sign_key * new_sign_key(); -const char* signkey_name_from_type(int type, int *namelen); -int signkey_type_from_name(const char* name, int namelen); +const char* signkey_name_from_type(enum signkey_type type, unsigned int *namelen); +enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen); int buf_get_pub_key(buffer *buf, sign_key *key, int *type); int buf_get_priv_key(buffer* buf, sign_key *key, int *type); void buf_put_pub_key(buffer* buf, sign_key *key, int type); diff -r 70625eed40c9 -r d386defb5376 sysoptions.h --- a/sysoptions.h Sun Apr 14 00:50:03 2013 +0800 +++ b/sysoptions.h Sun Apr 28 23:17:43 2013 +0800 @@ -60,14 +60,6 @@ #define DROPBEAR_SUCCESS 0 #define DROPBEAR_FAILURE -1 -enum { - DROPBEAR_SIGNKEY_ANY, - DROPBEAR_SIGNKEY_RSA, - DROPBEAR_SIGNKEY_DSS, - DROPBEAR_SIGNKEY_ECDSA, - DROPBEAR_SIGNKEY_NONE, -}; - /* Required for pubkey auth */ #if defined(ENABLE_SVR_PUBKEY_AUTH) || defined(DROPBEAR_CLIENT) #define DROPBEAR_SIGNKEY_VERIFY