/* returns success or failure, and the keytype in *type. If we want * to restrict the type, type can contain a type to return */ int readhostkey(const char * filename, sign_key * hostkey, int *type) { int ret = DROPBEAR_FAILURE; buffer *buf; buf = buf_new(MAX_PRIVKEY_SIZE); if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) { goto out; } buf_setpos(buf, 0); addrandom(buf_getptr(buf, buf->len), buf->len); if (buf_get_priv_key(buf, hostkey, type) == DROPBEAR_FAILURE) { goto out; } ret = DROPBEAR_SUCCESS; out: buf_burn(buf); buf_free(buf); return ret; }
/* returns success or failure */ static int readhostkey(const char * filename, sign_key * hostkey, int type) { int ret = DROPBEAR_FAILURE; int i; buffer *buf; buf = buf_new(2000); if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) { goto out; } buf_setpos(buf, 0); if (buf_get_priv_key(buf, hostkey, type) == DROPBEAR_FAILURE) { goto out; } ret = DROPBEAR_SUCCESS; out: if (ret == DROPBEAR_FAILURE) { for (i = 0; sshhostkey[i].name != NULL; i++) { if (sshhostkey[i].val == type) { sshhostkey[i].usable = 0; break; } } fprintf(stderr, "Failed reading '%s', disabling %s\n", filename, type == DROPBEAR_SIGNKEY_DSS ? "DSS" : "RSA"); } buf_burn(buf); buf_free(buf); return ret; }
static void cleanup_buf(buffer **buf) { if (!*buf) { return; } buf_burn(*buf); buf_free(*buf); *buf = NULL; }
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; }
static int printpubfile(const char* filename) { buffer *buf = NULL; sign_key *key = NULL; enum signkey_type keytype; int ret; int err = DROPBEAR_FAILURE; buf = buf_new(MAX_PRIVKEY_SIZE); ret = buf_readfile(buf, filename); if (ret != DROPBEAR_SUCCESS) { fprintf(stderr, "Failed reading '%s'\n", filename); goto out; } key = new_sign_key(); keytype = DROPBEAR_SIGNKEY_ANY; buf_setpos(buf, 0); ret = buf_get_priv_key(buf, key, &keytype); if (ret == DROPBEAR_FAILURE) { fprintf(stderr, "Bad key in '%s'\n", filename); goto out; } printpubkey(key, keytype); err = DROPBEAR_SUCCESS; out: buf_burn(buf); buf_free(buf); buf = NULL; if (key) { sign_key_free(key); key = NULL; } return err; }
/* 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; }