diff options
Diffstat (limited to 'gensignkey.c')
-rw-r--r-- | gensignkey.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/gensignkey.c b/gensignkey.c new file mode 100644 index 0000000..88a3949 --- /dev/null +++ b/gensignkey.c @@ -0,0 +1,131 @@ +#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(); + + seedrandom(); + + 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"); + } + + seedrandom(); + + 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; +} |