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; }
/* if skip_exist is set it will silently return if the key file exists */ int signkey_generate(enum signkey_type keytype, int bits, const char* filename, int skip_exist) { sign_key * key = NULL; buffer *buf = NULL; char *fn_temp = NULL; int ret = DROPBEAR_FAILURE; bits = signkey_generate_get_bits(keytype, bits); /* now we can generate the key */ key = new_sign_key(); seedrandom(); switch(keytype) { #if DROPBEAR_RSA case DROPBEAR_SIGNKEY_RSA: key->rsakey = gen_rsa_priv_key(bits); break; #endif #if DROPBEAR_DSS case DROPBEAR_SIGNKEY_DSS: key->dsskey = gen_dss_priv_key(bits); break; #endif #if 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); fn_temp = m_malloc(strlen(filename) + 30); snprintf(fn_temp, strlen(filename)+30, "%s.tmp%d", filename, getpid()); ret = buf_writefile(buf, fn_temp); if (ret == DROPBEAR_FAILURE) { goto out; } if (link(fn_temp, filename) < 0) { /* If generating keys on connection (skipexist) it's OK to get EEXIST - we probably just lost a race with another connection to generate the key */ if (!(skip_exist && errno == EEXIST)) { dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", filename, strerror(errno)); /* XXX fallback to non-atomic copy for some filesystems? */ ret = DROPBEAR_FAILURE; goto out; } } out: if (buf) { buf_burn(buf); buf_free(buf); } if (fn_temp) { unlink(fn_temp); m_free(fn_temp); } return ret; }