aboutsummaryrefslogtreecommitdiff
path: root/src/kex.c
diff options
context:
space:
mode:
authorJakub Jelen <jjelen@redhat.com>2018-11-15 13:43:18 +0100
committerAndreas Schneider <asn@cryptomilk.org>2019-01-09 10:31:49 +0100
commit58cae2366a801d6d3702d2fa8895976d4c169bd7 (patch)
tree7234181cbf462cf18938fd34f7f8d1bce7a0e800 /src/kex.c
parentc86a00d06b732c57153bdd5677a5d77f7f1be0a9 (diff)
downloadlibssh-58cae2366a801d6d3702d2fa8895976d4c169bd7.tar.gz
libssh-58cae2366a801d6d3702d2fa8895976d4c169bd7.tar.xz
libssh-58cae2366a801d6d3702d2fa8895976d4c169bd7.zip
packet: Implement rekeying based on the recommendation from RFC's
The default rekeying recommendations are specified in RFC4344 Section 3 (First and Second Rekeying Recommendations). Additionally, the rekeying can be specified in configuration file/options allowing us to turn the rekeying off, base it on time or make it more strict. The code is highly inspired by the OpenSSH rekeying code. Signed-off-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Daiki Ueno <dueno@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Diffstat (limited to 'src/kex.c')
-rw-r--r--src/kex.c55
1 files changed, 54 insertions, 1 deletions
diff --git a/src/kex.c b/src/kex.c
index 7a1c89c7..c2e02ff6 100644
--- a/src/kex.c
+++ b/src/kex.c
@@ -444,7 +444,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
(void)user;
if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED) {
- SSH_LOG(SSH_LOG_WARNING, "Other side initiating key re-exchange");
+ SSH_LOG(SSH_LOG_INFO, "Initiating key re-exchange");
} else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) {
ssh_set_error(session,SSH_FATAL,"SSH_KEXINIT received in wrong state");
goto error;
@@ -564,6 +564,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
}
}
+ /* Note, that his overwrites authenticated state in case of rekeying */
session->session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED;
session->dh_handshake_state = DH_STATE_INIT;
session->ssh_connection_callback(session);
@@ -880,6 +881,7 @@ int ssh_send_kex(ssh_session session, int server_kex) {
return -1;
}
+ SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_KEXINIT sent");
return 0;
error:
ssh_buffer_reinit(session->out_buffer);
@@ -889,6 +891,57 @@ error:
return -1;
}
+/*
+ * Key re-exchange (rekey) is triggered by this function.
+ * It can not be called again after the rekey is initialized!
+ */
+int ssh_send_rekex(ssh_session session)
+{
+ int rc;
+
+ if (session->dh_handshake_state != DH_STATE_FINISHED) {
+ /* Rekey/Key exchange is already in progress */
+ SSH_LOG(SSH_LOG_PACKET, "Attempting rekey in bad state");
+ return SSH_ERROR;
+ }
+
+ if (session->current_crypto == NULL) {
+ /* No current crypto used -- can not exchange it */
+ SSH_LOG(SSH_LOG_PACKET, "No crypto to rekey");
+ return SSH_ERROR;
+ }
+
+ if (session->client) {
+ rc = ssh_set_client_kex(session);
+ if (rc != SSH_OK) {
+ SSH_LOG(SSH_LOG_PACKET, "Failed to set client kex");
+ return rc;
+ }
+ } else {
+#ifdef WITH_SERVER
+ rc = server_set_kex(session);
+ if (rc == SSH_ERROR) {
+ SSH_LOG(SSH_LOG_PACKET, "Failed to set server kex");
+ return rc;
+ }
+#else
+ SSH_LOG(SSH_LOG_PACKET, "Invalid session state.");
+ return SSH_ERROR;
+#endif /* WITH_SERVER */
+ }
+
+ session->dh_handshake_state = DH_STATE_INIT;
+ rc = ssh_send_kex(session, session->server);
+ if (rc < 0) {
+ SSH_LOG(SSH_LOG_PACKET, "Failed to send kex");
+ return rc;
+ }
+
+ /* Reset the handshake state */
+ session->dh_handshake_state = DH_STATE_INIT_SENT;
+ return SSH_OK;
+}
+
/* returns 1 if at least one of the name algos is in the default algorithms table */
int ssh_verify_existing_algo(enum ssh_kex_types_e algo, const char *name)
{