| #include "includes.h" |
| #include "dbutil.h" |
| #include "buffer.h" |
| #include "ecdsa.h" |
| #include "genrsa.h" |
| #include "gendss.h" |
| #include "signkey.h" |
| #include "dbrandom.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 (len == -1 && 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) { |
| if (fsync(fd) != 0) { |
| dropbear_log(LOG_ERR, "fsync of %s failed: %s", filename, strerror(errno)); |
| } |
| 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; |
| } |