static int server_set_kex(ssh_session session) { struct ssh_kex_struct *server = &session->next_crypto->server_kex; int i, j, rc; const char *wanted; char hostkeys[64] = {0}; enum ssh_keytypes_e keytype; size_t len; ZERO_STRUCTP(server); ssh_get_random(server->cookie, 16, 0); #ifdef HAVE_ECC if (session->srv.ecdsa_key != NULL) { snprintf(hostkeys, sizeof(hostkeys), "%s", session->srv.ecdsa_key->type_c); } #endif if (session->srv.dsa_key != NULL) { len = strlen(hostkeys); keytype = ssh_key_type(session->srv.dsa_key); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",%s", ssh_key_type_to_char(keytype)); } if (session->srv.rsa_key != NULL) { len = strlen(hostkeys); keytype = ssh_key_type(session->srv.rsa_key); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",%s", ssh_key_type_to_char(keytype)); } if (strlen(hostkeys) == 0) { return -1; } rc = ssh_options_set_algo(session, SSH_HOSTKEYS, hostkeys[0] == ',' ? hostkeys + 1 : hostkeys); if (rc < 0) { return -1; } for (i = 0; i < 10; i++) { if ((wanted = session->opts.wanted_methods[i]) == NULL) { wanted = ssh_kex_get_supported_method(i); } server->methods[i] = strdup(wanted); if (server->methods[i] == NULL) { for (j = 0; j < i; j++) { SAFE_FREE(server->methods[j]); } return -1; } } return 0; }
ssh_key pki_publickey_from_privatekey(ssh_key privkey) { ssh_key pubkey = NULL; if (privkey == NULL || !ssh_key_is_private(privkey)) { return NULL; } pubkey = ssh_key_new(); if (pubkey == NULL) { return NULL; } pubkey->type = privkey->type; switch (pubkey->type) { case SSH_KEYTYPE_DSS: pubkey->dsa = DSA_new(); if (pubkey->dsa == NULL) { goto fail; } pubkey->dsa->p = BN_dup(privkey->dsa->p); pubkey->dsa->q = BN_dup(privkey->dsa->q); pubkey->dsa->g = BN_dup(privkey->dsa->g); pubkey->dsa->pub_key = BN_dup(privkey->dsa->pub_key); if (pubkey->dsa->p == NULL || pubkey->dsa->q == NULL || pubkey->dsa->g == NULL || pubkey->dsa->pub_key == NULL) { goto fail; } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: pubkey->rsa = RSA_new(); if (pubkey->rsa == NULL) { goto fail; } pubkey->rsa->e = BN_dup(privkey->rsa->e); pubkey->rsa->n = BN_dup(privkey->rsa->n); if (pubkey->rsa->e == NULL || pubkey->rsa->n == NULL) { goto fail; } break; case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: ssh_key_free(pubkey); return NULL; } pubkey->type_c = ssh_key_type_to_char(privkey->type); return pubkey; fail: ssh_key_free(pubkey); return NULL; }
/** * @brief Generates a keypair. * * @param[in] type Type of key to create * * @param[in] parameter Parameter to the creation of key: * rsa : length of the key in bits (e.g. 1024, 2048, 4096) * dsa : length of the key in bits (e.g. 1024, 2048, 3072) * ecdsa : bits of the key (e.g. 256, 384, 512) * @param[out] pkey A pointer to store the allocated private key. You need * to free the memory. * * @return SSH_OK on success, SSH_ERROR on error. * * @warning Generating a key pair may take some time. */ int ssh_pki_generate(enum ssh_keytypes_e type, int parameter, ssh_key *pkey){ int rc; ssh_key key = ssh_key_new(); if (key == NULL) { return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; switch(type){ case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: rc = pki_key_generate_rsa(key, parameter); if(rc == SSH_ERROR) goto error; break; case SSH_KEYTYPE_DSS: rc = pki_key_generate_dss(key, parameter); if(rc == SSH_ERROR) goto error; break; case SSH_KEYTYPE_ECDSA: #ifdef HAVE_ECC rc = pki_key_generate_ecdsa(key, parameter); if (rc == SSH_ERROR) { goto error; } /* Update key type */ key->type_c = ssh_pki_key_ecdsa_name(key); break; #endif case SSH_KEYTYPE_ED25519: rc = pki_key_generate_ed25519(key); if (rc == SSH_ERROR) { goto error; } break; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_UNKNOWN: goto error; } *pkey = key; return SSH_OK; error: ssh_key_free(key); return SSH_ERROR; }
static void torture_pki_keytype(void **state) { enum ssh_keytypes_e type; const char *type_c; (void) state; /* unused */ type = ssh_key_type(NULL); assert_true(type == SSH_KEYTYPE_UNKNOWN); type = ssh_key_type_from_name(NULL); assert_true(type == SSH_KEYTYPE_UNKNOWN); type = ssh_key_type_from_name("42"); assert_true(type == SSH_KEYTYPE_UNKNOWN); type_c = ssh_key_type_to_char(SSH_KEYTYPE_UNKNOWN); assert_true(type_c == NULL); type_c = ssh_key_type_to_char(42); assert_true(type_c == NULL); }
static int pki_import_cert_buffer(ssh_buffer buffer, enum ssh_keytypes_e type, ssh_key *pkey) { ssh_buffer cert; ssh_string type_s; ssh_key key; int rc; key = ssh_key_new(); if (key == NULL) { return SSH_ERROR; } cert = ssh_buffer_new(); if (cert == NULL) { ssh_key_free(key); return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PUBLIC; /* * The cert blob starts with the key type as an ssh_string, but this * string has been read out of the buffer to identify the key type. * Simply add it again as first element before copying the rest. */ type_s = ssh_string_from_char(key->type_c); if (type_s == NULL) { goto fail; } rc = ssh_buffer_add_ssh_string(cert, type_s); ssh_string_free(type_s); if (rc != 0) { goto fail; } rc = ssh_buffer_add_buffer(cert, buffer); if (rc != 0) { goto fail; } key->cert = (void*) cert; *pkey = key; return SSH_OK; fail: ssh_key_free(key); ssh_buffer_free(cert); return SSH_ERROR; }
static int pkd_auth_pubkey_cb(ssh_session s, const char *user, ssh_key key, char state, void *userdata) { (void) s; (void) user; (void) key; (void) state; (void) userdata; pkdout("pkd_auth_pubkey_cb keytype %s, state: %d\n", ssh_key_type_to_char(ssh_key_type(key)), state); if ((state == SSH_PUBLICKEY_STATE_NONE) || (state == SSH_PUBLICKEY_STATE_VALID)) { return SSH_AUTH_SUCCESS; } return SSH_AUTH_DENIED; }
ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data) { ssh_key key = NULL; mbedtls_pk_context *rsa = NULL; mbedtls_pk_context *ecdsa = NULL; ed25519_privkey *ed25519 = NULL; enum ssh_keytypes_e type; int valid; /* mbedtls pk_parse_key expects strlen to count the 0 byte */ size_t b64len = strlen(b64_key) + 1; unsigned char tmp[MAX_PASSPHRASE_SIZE] = {0}; type = pki_privatekey_type_from_string(b64_key); if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key."); return NULL; } switch (type) { case SSH_KEYTYPE_RSA: rsa = malloc(sizeof(mbedtls_pk_context)); if (rsa == NULL) { return NULL; } mbedtls_pk_init(rsa); if (passphrase == NULL) { if (auth_fn) { valid = auth_fn("Passphrase for private key:", (char *) tmp, MAX_PASSPHRASE_SIZE, 0, 0, auth_data); if (valid < 0) { return NULL; } /* TODO fix signedness and strlen */ valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, tmp, strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE)); } else { valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, NULL, 0); } } else { valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, (const unsigned char *) passphrase, strnlen(passphrase, MAX_PASSPHRASE_SIZE)); } if (valid != 0) { char error_buf[100]; mbedtls_strerror(valid, error_buf, 100); SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf); goto fail; } break; case SSH_KEYTYPE_ECDSA: ecdsa = malloc(sizeof(mbedtls_pk_context)); if (ecdsa == NULL) { return NULL; } mbedtls_pk_init(ecdsa); if (passphrase == NULL) { if (auth_fn) { valid = auth_fn("Passphrase for private key:", (char *) tmp, MAX_PASSPHRASE_SIZE, 0, 0, auth_data); if (valid < 0) { return NULL; } valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, tmp, strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE)); } else { valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, NULL, 0); } } else { valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, (const unsigned char *) passphrase, strnlen(passphrase, MAX_PASSPHRASE_SIZE)); } if (valid != 0) { char error_buf[100]; mbedtls_strerror(valid, error_buf, 100); SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf); goto fail; } break; case SSH_KEYTYPE_ED25519: /* Cannot open ed25519 keys with libmbedcrypto */ default: SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", type); return NULL; } key = ssh_key_new(); if (key == NULL) { goto fail; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; key->rsa = rsa; if (ecdsa != NULL) { mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*ecdsa); key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context)); if (key->ecdsa == NULL) { goto fail; } mbedtls_ecdsa_init(key->ecdsa); mbedtls_ecdsa_from_keypair(key->ecdsa, keypair); mbedtls_pk_free(ecdsa); SAFE_FREE(ecdsa); } else { key->ecdsa = NULL; } key->ed25519_privkey = ed25519; rsa = NULL; ecdsa = NULL; if (key->type == SSH_KEYTYPE_ECDSA) { key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa); key->type_c = pki_key_ecdsa_nid_to_name(key->ecdsa_nid); } return key; fail: ssh_key_free(key); if (rsa != NULL) { mbedtls_pk_free(rsa); SAFE_FREE(rsa); } if (ecdsa != NULL) { mbedtls_pk_free(ecdsa); SAFE_FREE(ecdsa); } return NULL; }
static int pki_import_pubkey_buffer(ssh_buffer buffer, enum ssh_keytypes_e type, ssh_key *pkey) { ssh_key key; int rc; key = ssh_key_new(); if (key == NULL) { return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PUBLIC; switch (type) { case SSH_KEYTYPE_DSS: { ssh_string p; ssh_string q; ssh_string g; ssh_string pubkey; p = ssh_buffer_get_ssh_string(buffer); if (p == NULL) { goto fail; } q = ssh_buffer_get_ssh_string(buffer); if (q == NULL) { ssh_string_burn(p); ssh_string_free(p); goto fail; } g = ssh_buffer_get_ssh_string(buffer); if (g == NULL) { ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); goto fail; } pubkey = ssh_buffer_get_ssh_string(buffer); if (pubkey == NULL) { ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); goto fail; } rc = pki_pubkey_build_dss(key, p, q, g, pubkey); #ifdef DEBUG_CRYPTO ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p)); ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q)); ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g)); #endif ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); ssh_string_burn(pubkey); ssh_string_free(pubkey); if (rc == SSH_ERROR) { goto fail; } } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: { ssh_string e; ssh_string n; e = ssh_buffer_get_ssh_string(buffer); if (e == NULL) { goto fail; } n = ssh_buffer_get_ssh_string(buffer); if (n == NULL) { ssh_string_burn(e); ssh_string_free(e); goto fail; } rc = pki_pubkey_build_rsa(key, e, n); #ifdef DEBUG_CRYPTO ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e)); ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n)); #endif ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); if (rc == SSH_ERROR) { goto fail; } } break; case SSH_KEYTYPE_ECDSA: #ifdef HAVE_ECC { ssh_string e; ssh_string i; int nid; i = ssh_buffer_get_ssh_string(buffer); if (i == NULL) { goto fail; } nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i)); ssh_string_free(i); if (nid == -1) { goto fail; } e = ssh_buffer_get_ssh_string(buffer); if (e == NULL) { goto fail; } rc = pki_pubkey_build_ecdsa(key, nid, e); ssh_string_burn(e); ssh_string_free(e); if (rc < 0) { goto fail; } /* Update key type */ key->type_c = ssh_pki_key_ecdsa_name(key); } break; #endif case SSH_KEYTYPE_ED25519: { ssh_string pubkey = ssh_buffer_get_ssh_string(buffer); if (ssh_string_len(pubkey) != ED25519_PK_LEN) { SSH_LOG(SSH_LOG_WARN, "Invalid public key length"); ssh_string_burn(pubkey); ssh_string_free(pubkey); goto fail; } key->ed25519_pubkey = malloc(ED25519_PK_LEN); if (key->ed25519_pubkey == NULL) { ssh_string_burn(pubkey); ssh_string_free(pubkey); goto fail; } memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_PK_LEN); ssh_string_burn(pubkey); ssh_string_free(pubkey); } break; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_WARN, "Unknown public key protocol %d", type); goto fail; } *pkey = key; return SSH_OK; fail: ssh_key_free(key); return SSH_ERROR; }
ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data) { gcry_sexp_t dsa = NULL; gcry_sexp_t rsa = NULL; ssh_key key = NULL; enum ssh_keytypes_e type; int valid; /* needed for gcrypt initialization */ if (ssh_init() < 0) { return NULL; } type = pki_privatekey_type_from_string(b64_key); if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key."); return NULL; } switch (type) { case SSH_KEYTYPE_DSS: if (passphrase == NULL) { if (auth_fn) { valid = b64decode_dsa_privatekey(b64_key, &dsa, auth_fn, auth_data, "Passphrase for private key:"); } else { valid = b64decode_dsa_privatekey(b64_key, &dsa, NULL, NULL, NULL); } } else { valid = b64decode_dsa_privatekey(b64_key, &dsa, NULL, (void *) passphrase, NULL); } if (!valid) { SSH_LOG(SSH_LOG_WARN, "Parsing private key"); goto fail; } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: if (passphrase == NULL) { if (auth_fn) { valid = b64decode_rsa_privatekey(b64_key, &rsa, auth_fn, auth_data, "Passphrase for private key:"); } else { valid = b64decode_rsa_privatekey(b64_key, &rsa, NULL, NULL, NULL); } } else { valid = b64decode_rsa_privatekey(b64_key, &rsa, NULL, (void *)passphrase, NULL); } if (!valid) { SSH_LOG(SSH_LOG_WARN, "Parsing private key"); goto fail; } break; case SSH_KEYTYPE_ED25519: /* Cannot open ed25519 keys with libgcrypt */ case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_WARN, "Unkown or invalid private key type %d", type); return NULL; } key = ssh_key_new(); if (key == NULL) { goto fail; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; key->dsa = dsa; key->rsa = rsa; return key; fail: ssh_key_free(key); gcry_sexp_release(dsa); gcry_sexp_release(rsa); return NULL; }
static const gchar * verify_knownhost (CockpitSshData *data) { const gchar *ret = "unknown-hostkey"; ssh_key key = NULL; unsigned char *hash = NULL; const char *type = NULL; int state; gsize len; data->host_key = get_knownhosts_line (data->session); if (data->host_key == NULL) { ret = "internal-error"; goto done; } if (ssh_get_publickey (data->session, &key) != SSH_OK) { g_warning ("Couldn't look up ssh host key"); ret = "internal-error"; goto done; } type = ssh_key_type_to_char (ssh_key_type (key)); if (type == NULL) { g_warning ("Couldn't lookup host key type"); ret = "internal-error"; goto done; } if (ssh_get_publickey_hash (key, SSH_PUBLICKEY_HASH_MD5, &hash, &len) < 0) { g_warning ("Couldn't hash ssh public key"); ret = "internal-error"; goto done; } else { data->host_fingerprint = ssh_get_hexa (hash, len); ssh_clean_pubkey_hash (&hash); } if (data->expect_key) { /* Only check that the host key matches this specifically */ if (g_str_equal (data->host_key, data->expect_key)) { g_debug ("%s: host key matched expected", data->logname); ret = NULL; /* success */ } else { /* A empty expect_key is used by the frontend to force failure. Don't warn about it. */ if (data->expect_key[0]) g_message ("%s: host key did not match expected", data->logname); } } else { if (ssh_options_set (data->session, SSH_OPTIONS_KNOWNHOSTS, data->knownhosts_file) != SSH_OK) { g_warning ("Couldn't set knownhosts file location"); ret = "internal-error"; goto done; } state = ssh_is_server_known (data->session); if (state == SSH_SERVER_KNOWN_OK) { g_debug ("%s: verified host key", data->logname); ret = NULL; /* success */ goto done; } else if (state == SSH_SERVER_ERROR) { if (g_atomic_int_get (data->connecting)) g_warning ("%s: couldn't check host key: %s", data->logname, ssh_get_error (data->session)); ret = "internal-error"; goto done; } switch (state) { case SSH_SERVER_KNOWN_OK: case SSH_SERVER_ERROR: g_assert_not_reached (); break; case SSH_SERVER_KNOWN_CHANGED: g_message ("%s: %s host key for server has changed to: %s", data->logname, type, data->host_fingerprint); break; case SSH_SERVER_FOUND_OTHER: g_message ("%s: host key for this server changed key type: %s", data->logname, type); break; case SSH_SERVER_FILE_NOT_FOUND: g_debug ("Couldn't find the known hosts file"); /* fall through */ case SSH_SERVER_NOT_KNOWN: g_message ("%s: %s host key for server is not known: %s", data->logname, type, data->host_fingerprint); break; } } done: if (key) ssh_key_free (key); return ret; }
ssh_key pki_private_key_from_base64(ssh_session session, const char *b64_key, const char *passphrase) { BIO *mem = NULL; DSA *dsa = NULL; RSA *rsa = NULL; ssh_key key; enum ssh_keytypes_e type; /* needed for openssl initialization */ if (ssh_init() < 0) { return NULL; } type = pki_privatekey_type_from_string(b64_key); if (type == SSH_KEYTYPE_UNKNOWN) { ssh_set_error(session, SSH_FATAL, "Unknown or invalid private key."); return NULL; } mem = BIO_new_mem_buf((void*)b64_key, -1); switch (type) { case SSH_KEYTYPE_DSS: if (passphrase == NULL) { if (session->common.callbacks && session->common.callbacks->auth_function) { dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, pem_get_password, session); } else { /* openssl uses its own callback to get the passphrase here */ dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, NULL, NULL); } } else { dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, NULL, (void *) passphrase); } BIO_free(mem); if (dsa == NULL) { ssh_set_error(session, SSH_FATAL, "Parsing private key: %s", ERR_error_string(ERR_get_error(), NULL)); return NULL; } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: if (passphrase == NULL) { if (session->common.callbacks && session->common.callbacks->auth_function) { rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, pem_get_password, session); } else { /* openssl uses its own callback to get the passphrase here */ rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, NULL); } } else { rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, (void *) passphrase); } BIO_free(mem); if (rsa == NULL) { ssh_set_error(session, SSH_FATAL, "Parsing private key: %s", ERR_error_string(ERR_get_error(),NULL)); return NULL; } break; case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: BIO_free(mem); ssh_set_error(session, SSH_FATAL, "Unkown or invalid private key type %d", type); return NULL; } key = ssh_key_new(); if (key == NULL) { goto fail; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; key->dsa = dsa; key->rsa = rsa; return key; fail: ssh_key_free(key); DSA_free(dsa); RSA_free(rsa); return NULL; }
int server_set_kex(ssh_session session) { struct ssh_kex_struct *server = &session->next_crypto->server_kex; int i, j, rc; const char *wanted; char hostkeys[128] = {0}; enum ssh_keytypes_e keytype; size_t len; int ok; ZERO_STRUCTP(server); ok = ssh_get_random(server->cookie, 16, 0); if (!ok) { ssh_set_error(session, SSH_FATAL, "PRNG error"); return -1; } if (session->srv.ed25519_key != NULL) { snprintf(hostkeys, sizeof(hostkeys), "%s", ssh_key_type_to_char(ssh_key_type(session->srv.ed25519_key))); } #ifdef HAVE_ECC if (session->srv.ecdsa_key != NULL) { len = strlen(hostkeys); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",%s", session->srv.ecdsa_key->type_c); } #endif #ifdef HAVE_DSA if (session->srv.dsa_key != NULL) { len = strlen(hostkeys); keytype = ssh_key_type(session->srv.dsa_key); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",%s", ssh_key_type_to_char(keytype)); } #endif if (session->srv.rsa_key != NULL) { /* We support also the SHA2 variants */ len = strlen(hostkeys); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",rsa-sha2-512,rsa-sha2-256"); len = strlen(hostkeys); keytype = ssh_key_type(session->srv.rsa_key); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",%s", ssh_key_type_to_char(keytype)); } if (strlen(hostkeys) == 0) { return -1; } rc = ssh_options_set_algo(session, SSH_HOSTKEYS, hostkeys[0] == ',' ? hostkeys + 1 : hostkeys); if (rc < 0) { return -1; } for (i = 0; i < 10; i++) { if ((wanted = session->opts.wanted_methods[i]) == NULL) { wanted = ssh_kex_get_supported_method(i); } server->methods[i] = strdup(wanted); if (server->methods[i] == NULL) { for (j = 0; j < i; j++) { SAFE_FREE(server->methods[j]); } return -1; } } return 0; }
int ssh_pki_import_pubkey_base64(ssh_session session, const char *b64_key, enum ssh_keytypes_e type, ssh_key *pkey) { ssh_buffer buffer; ssh_key key; int rc; key = ssh_key_new(); if (key == NULL) { return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PUBLIC; buffer = base64_to_bin(b64_key); switch (type) { case SSH_KEYTYPE_DSS: { ssh_string p; ssh_string q; ssh_string g; ssh_string pubkey; p = buffer_get_ssh_string(buffer); if (p == NULL) { goto fail; } q = buffer_get_ssh_string(buffer); if (q == NULL) { ssh_string_burn(p); ssh_string_free(p); goto fail; } g = buffer_get_ssh_string(buffer); if (g == NULL) { ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); goto fail; } pubkey = buffer_get_ssh_string(buffer); if (g == NULL) { ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); goto fail; } rc = pki_pubkey_build_dss(key, p, q, g, pubkey); #ifdef DEBUG_CRYPTO ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p)); ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q)); ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g)); #endif ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); if (rc == SSH_ERROR) { goto fail; } } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: { ssh_string e; ssh_string n; e = buffer_get_ssh_string(buffer); if (e == NULL) { goto fail; } n = buffer_get_ssh_string(buffer); if (n == NULL) { ssh_string_burn(e); ssh_string_free(e); goto fail; } rc = pki_pubkey_build_rsa(key, e, n); #ifdef DEBUG_CRYPTO ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e)); ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n)); #endif ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); if (rc == SSH_ERROR) { goto fail; } } break; case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: ssh_set_error(session, SSH_FATAL, "Unknown public key protocol %d", type); goto fail; } ssh_buffer_free(buffer); *pkey = key; return SSH_OK; fail: ssh_buffer_free(buffer); ssh_key_free(key); return SSH_ERROR; }
/** * @internal * * @brief Import a private key from a ssh buffer. * * @param[in] key_blob_buffer The key blob to import as specified in * key.c:key_private_serialize in OpenSSH source * code. * * @param[out] pkey A pointer where the allocated key can be stored. You * need to free the memory. * * @return SSH_OK on success, SSH_ERROR on error. * * @see ssh_key_free() */ static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer, ssh_key *pkey) { enum ssh_keytypes_e type; char *type_s = NULL; ssh_key key = NULL; ssh_string pubkey = NULL, privkey = NULL; int rc; if (pkey == NULL) { return SSH_ERROR; } rc = ssh_buffer_unpack(key_blob_buffer, "s", &type_s); if (rc == SSH_ERROR){ ssh_pki_log("Unpack error"); return SSH_ERROR; } type = ssh_key_type_from_name(type_s); if (type == SSH_KEYTYPE_UNKNOWN) { ssh_pki_log("Unknown key type found!"); return SSH_ERROR; } SAFE_FREE(type_s); key = ssh_key_new(); if (key == NULL) { ssh_pki_log("Out of memory"); return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; switch (type) { case SSH_KEYTYPE_ED25519: rc = ssh_buffer_unpack(key_blob_buffer, "SS", &pubkey, &privkey); if (rc != SSH_OK){ ssh_pki_log("Unpack error"); goto fail; } if(ssh_string_len(pubkey) != ED25519_PK_LEN || ssh_string_len(privkey) != ED25519_SK_LEN){ ssh_pki_log("Invalid ed25519 key len"); goto fail; } key->ed25519_privkey = malloc(ED25519_SK_LEN); key->ed25519_pubkey = malloc(ED25519_PK_LEN); if(key->ed25519_privkey == NULL || key->ed25519_pubkey == NULL){ goto fail; } memcpy(key->ed25519_privkey, ssh_string_data(privkey), ED25519_SK_LEN); memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_PK_LEN); memset(ssh_string_data(privkey), 0, ED25519_SK_LEN); SAFE_FREE(privkey); SAFE_FREE(pubkey); break; case SSH_KEYTYPE_DSS: /* p,q,g,pub_key,priv_key */ case SSH_KEYTYPE_RSA: /* n,e,d,iqmp,p,q */ case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_ECDSA: /* curve_name, group, privkey */ ssh_pki_log("Unsupported private key method %s", key->type_c); goto fail; case SSH_KEYTYPE_UNKNOWN: ssh_pki_log("Unknown private key protocol %s", key->type_c); goto fail; } *pkey = key; return SSH_OK; fail: ssh_key_free(key); if(privkey != NULL){ memset(ssh_string_data(privkey), 0, ssh_string_len(privkey)); } SAFE_FREE(pubkey); SAFE_FREE(privkey); return SSH_ERROR; }