summaryrefslogtreecommitdiff
path: root/libs/libssh2/src/kex.c
diff options
context:
space:
mode:
authordartraiden <wowemuh@gmail.com>2019-06-20 22:31:19 +0300
committerdartraiden <wowemuh@gmail.com>2019-06-20 22:31:19 +0300
commit1d72e07ffb7b349ac9a8f825eae7cce082b5e2cd (patch)
tree03a97724b412a04a7a3848dc8c5edb24b2d29c0e /libs/libssh2/src/kex.c
parentfdf29bb66f0b9be0b8518db0a827cc2bd20a38ac (diff)
iibssh2: update to 1.9.0
Diffstat (limited to 'libs/libssh2/src/kex.c')
-rw-r--r--libs/libssh2/src/kex.c2518
1 files changed, 2062 insertions, 456 deletions
diff --git a/libs/libssh2/src/kex.c b/libs/libssh2/src/kex.c
index 3634cb5a91..cb1663937d 100644
--- a/libs/libssh2/src/kex.c
+++ b/libs/libssh2/src/kex.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
- * Copyright (c) 2010, Daniel Stenberg <daniel@haxx.se>
+ * Copyright (c) 2010-2019, Daniel Stenberg <daniel@haxx.se>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -43,24 +43,26 @@
#include "mac.h"
/* TODO: Switch this to an inline and handle alloc() failures */
-/* Helper macro called from kex_method_diffie_hellman_group1_sha1_key_exchange */
+/* Helper macro called from
+ kex_method_diffie_hellman_group1_sha1_key_exchange */
#define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(value, reqlen, version) \
{ \
libssh2_sha1_ctx hash; \
unsigned long len = 0; \
- if (!(value)) { \
+ if(!(value)) { \
value = LIBSSH2_ALLOC(session, reqlen + SHA_DIGEST_LENGTH); \
} \
- if (value) \
- while (len < (unsigned long)reqlen) { \
+ if(value) \
+ while(len < (unsigned long)reqlen) { \
libssh2_sha1_init(&hash); \
libssh2_sha1_update(hash, exchange_state->k_value, \
exchange_state->k_value_len); \
libssh2_sha1_update(hash, exchange_state->h_sig_comp, \
SHA_DIGEST_LENGTH); \
- if (len > 0) { \
+ if(len > 0) { \
libssh2_sha1_update(hash, value, len); \
- } else { \
+ } \
+ else { \
libssh2_sha1_update(hash, (version), 1); \
libssh2_sha1_update(hash, session->session_id, \
session->session_id_len); \
@@ -68,35 +70,53 @@
libssh2_sha1_final(hash, (value) + len); \
len += SHA_DIGEST_LENGTH; \
} \
- }
+ } \
-/* Helper macro called from kex_method_diffie_hellman_group1_sha256_key_exchange */
-#define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(value, reqlen, version) \
- { \
- libssh2_sha256_ctx hash; \
- unsigned long len = 0; \
- if (!(value)) { \
- value = LIBSSH2_ALLOC(session, reqlen + SHA256_DIGEST_LENGTH); \
- } \
- if (value) \
- while (len < (unsigned long)reqlen) { \
- libssh2_sha256_init(&hash); \
- libssh2_sha256_update(hash, exchange_state->k_value, \
- exchange_state->k_value_len); \
- libssh2_sha256_update(hash, exchange_state->h_sig_comp, \
- SHA256_DIGEST_LENGTH); \
- if (len > 0) { \
- libssh2_sha256_update(hash, value, len); \
- } else { \
- libssh2_sha256_update(hash, (version), 1); \
- libssh2_sha256_update(hash, session->session_id, \
- session->session_id_len); \
- } \
- libssh2_sha256_final(hash, (value) + len); \
- len += SHA256_DIGEST_LENGTH; \
- } \
- }
+#define LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(value, reqlen, version) \
+ { \
+ if(type == LIBSSH2_EC_CURVE_NISTP256) { \
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, value, reqlen, version); \
+ } \
+ else if(type == LIBSSH2_EC_CURVE_NISTP384) { \
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(384, value, reqlen, version); \
+ } \
+ else if(type == LIBSSH2_EC_CURVE_NISTP521) { \
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(512, value, reqlen, version); \
+ } \
+ } \
+
+
+#define LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(digest_type, value, \
+ reqlen, version) \
+{ \
+ libssh2_sha##digest_type##_ctx hash; \
+ unsigned long len = 0; \
+ if(!(value)) { \
+ value = LIBSSH2_ALLOC(session, \
+ reqlen + SHA##digest_type##_DIGEST_LENGTH); \
+ } \
+ if(value) \
+ while(len < (unsigned long)reqlen) { \
+ libssh2_sha##digest_type##_init(&hash); \
+ libssh2_sha##digest_type##_update(hash, \
+ exchange_state->k_value, \
+ exchange_state->k_value_len); \
+ libssh2_sha##digest_type##_update(hash, \
+ exchange_state->h_sig_comp, \
+ SHA##digest_type##_DIGEST_LENGTH); \
+ if(len > 0) { \
+ libssh2_sha##digest_type##_update(hash, value, len); \
+ } \
+ else { \
+ libssh2_sha##digest_type##_update(hash, (version), 1); \
+ libssh2_sha##digest_type##_update(hash, session->session_id, \
+ session->session_id_len); \
+ } \
+ libssh2_sha##digest_type##_final(hash, (value) + len); \
+ len += SHA##digest_type##_DIGEST_LENGTH; \
+ } \
+}
/*
@@ -118,37 +138,40 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
int rc;
libssh2_sha1_ctx exchange_hash_ctx;
- if (exchange_state->state == libssh2_NB_state_idle) {
+ if(exchange_state->state == libssh2_NB_state_idle) {
/* Setup initial values */
exchange_state->e_packet = NULL;
exchange_state->s_packet = NULL;
exchange_state->k_value = NULL;
exchange_state->ctx = _libssh2_bn_ctx_new();
- exchange_state->x = _libssh2_bn_init(); /* Random from client */
+ libssh2_dh_init(&exchange_state->x);
exchange_state->e = _libssh2_bn_init(); /* g^x mod p */
- exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from server) mod p */
- exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod p */
+ exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from
+ server) mod p */
+ exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod
+ p */
/* Zero the whole thing out */
memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t));
/* Generate x and e */
- _libssh2_bn_rand(exchange_state->x, group_order * 8 - 1, 0, -1);
- _libssh2_bn_mod_exp(exchange_state->e, g, exchange_state->x, p,
- exchange_state->ctx);
+ rc = libssh2_dh_key_pair(&exchange_state->x, exchange_state->e, g, p,
+ group_order, exchange_state->ctx);
+ if(rc)
+ goto clean_exit;
/* Send KEX init */
/* packet_type(1) + String Length(4) + leading 0(1) */
exchange_state->e_packet_len =
_libssh2_bn_bytes(exchange_state->e) + 6;
- if (_libssh2_bn_bits(exchange_state->e) % 8) {
+ if(_libssh2_bn_bits(exchange_state->e) % 8) {
/* Leading 00 not needed */
exchange_state->e_packet_len--;
}
exchange_state->e_packet =
LIBSSH2_ALLOC(session, exchange_state->e_packet_len);
- if (!exchange_state->e_packet) {
+ if(!exchange_state->e_packet) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Out of memory error");
goto clean_exit;
@@ -156,10 +179,11 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
exchange_state->e_packet[0] = packet_type_init;
_libssh2_htonu32(exchange_state->e_packet + 1,
exchange_state->e_packet_len - 5);
- if (_libssh2_bn_bits(exchange_state->e) % 8) {
+ if(_libssh2_bn_bits(exchange_state->e) % 8) {
_libssh2_bn_to_bin(exchange_state->e,
exchange_state->e_packet + 5);
- } else {
+ }
+ else {
exchange_state->e_packet[5] = 0;
_libssh2_bn_to_bin(exchange_state->e,
exchange_state->e_packet + 6);
@@ -170,13 +194,14 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_created;
}
- if (exchange_state->state == libssh2_NB_state_created) {
+ if(exchange_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, exchange_state->e_packet,
exchange_state->e_packet_len,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc,
"Unable to send KEX init message");
goto clean_exit;
@@ -184,20 +209,22 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_sent;
}
- if (exchange_state->state == libssh2_NB_state_sent) {
- if (session->burn_optimistic_kexinit) {
+ if(exchange_state->state == libssh2_NB_state_sent) {
+ if(session->burn_optimistic_kexinit) {
/* The first KEX packet to come along will be the guess initially
* sent by the server. That guess turned out to be wrong so we
* need to silently ignore it */
int burn_type;
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
- "Waiting for badly guessed KEX packet (to be ignored)");
+ "Waiting for badly guessed KEX packet "
+ "(to be ignored)");
burn_type =
_libssh2_packet_burn(session, &exchange_state->burn_state);
- if (burn_type == LIBSSH2_ERROR_EAGAIN) {
+ if(burn_type == LIBSSH2_ERROR_EAGAIN) {
return burn_type;
- } else if (burn_type <= 0) {
+ }
+ else if(burn_type <= 0) {
/* Failed to receive a packet */
ret = burn_type;
goto clean_exit;
@@ -212,16 +239,19 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_sent1;
}
- if (exchange_state->state == libssh2_NB_state_sent1) {
+ if(exchange_state->state == libssh2_NB_state_sent1) {
/* Wait for KEX reply */
+ struct string_buf buf;
+ size_t host_key_len;
+
rc = _libssh2_packet_require(session, packet_type_reply,
&exchange_state->s_packet,
&exchange_state->s_packet_len, 0, NULL,
0, &exchange_state->req_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- if (rc) {
+ if(rc) {
ret = _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
"Timed out waiting for KEX reply");
goto clean_exit;
@@ -234,37 +264,28 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
goto clean_exit;
}
- exchange_state->s = exchange_state->s_packet + 1;
-
- session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s);
- exchange_state->s += 4;
-
- if(session->server_hostkey_len > exchange_state->s_packet_len - 5) {
- ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
- "Host key length out of bounds");
- goto clean_exit;
- }
+ buf.data = exchange_state->s_packet;
+ buf.len = exchange_state->s_packet_len;
+ buf.dataptr = buf.data;
+ buf.dataptr++; /* advance past type */
- if (session->server_hostkey)
+ if(session->server_hostkey)
LIBSSH2_FREE(session, session->server_hostkey);
- session->server_hostkey =
- LIBSSH2_ALLOC(session, session->server_hostkey_len);
- if (!session->server_hostkey) {
+ if(_libssh2_copy_string(session, &buf, &(session->server_hostkey),
+ &host_key_len)) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
- "Unable to allocate memory for a copy "
- "of the host key");
+ "Could not copy host key");
goto clean_exit;
}
- memcpy(session->server_hostkey, exchange_state->s,
- session->server_hostkey_len);
- exchange_state->s += session->server_hostkey_len;
+
+ session->server_hostkey_len = (uint32_t)host_key_len;
#if LIBSSH2_MD5
{
libssh2_md5_ctx fingerprint_ctx;
- if (libssh2_md5_init(&fingerprint_ctx)) {
+ if(libssh2_md5_init(&fingerprint_ctx)) {
libssh2_md5_update(fingerprint_ctx, session->server_hostkey,
session->server_hostkey_len);
libssh2_md5_final(fingerprint_ctx,
@@ -292,7 +313,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
{
libssh2_sha1_ctx fingerprint_ctx;
- if (libssh2_sha1_init(&fingerprint_ctx)) {
+ if(libssh2_sha1_init(&fingerprint_ctx)) {
libssh2_sha1_update(fingerprint_ctx, session->server_hostkey,
session->server_hostkey_len);
libssh2_sha1_final(fingerprint_ctx,
@@ -317,7 +338,38 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
}
#endif /* LIBSSH2DEBUG */
- if (session->hostkey->init(session, session->server_hostkey,
+ {
+ libssh2_sha256_ctx fingerprint_ctx;
+
+ if(libssh2_sha256_init(&fingerprint_ctx)) {
+ libssh2_sha256_update(fingerprint_ctx, session->server_hostkey,
+ session->server_hostkey_len);
+ libssh2_sha256_final(fingerprint_ctx,
+ session->server_hostkey_sha256);
+ session->server_hostkey_sha256_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_sha256_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char *base64Fingerprint = NULL;
+ _libssh2_base64_encode(session,
+ (const char *)
+ session->server_hostkey_sha256,
+ SHA256_DIGEST_LENGTH, &base64Fingerprint);
+ if(base64Fingerprint != NULL) {
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's SHA256 Fingerprint: %s",
+ base64Fingerprint);
+ LIBSSH2_FREE(session, base64Fingerprint);
+ }
+ }
+#endif /* LIBSSH2DEBUG */
+
+
+ if(session->hostkey->init(session, session->server_hostkey,
session->server_hostkey_len,
&session->server_hostkey_abstract)) {
ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
@@ -325,58 +377,67 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
goto clean_exit;
}
- exchange_state->f_value_len = _libssh2_ntohu32(exchange_state->s);
- exchange_state->s += 4;
- exchange_state->f_value = exchange_state->s;
- exchange_state->s += exchange_state->f_value_len;
+ if(_libssh2_get_string(&buf, &(exchange_state->f_value),
+ &(exchange_state->f_value_len))) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unable to get f value");
+ goto clean_exit;
+ }
+
_libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len,
exchange_state->f_value);
- exchange_state->h_sig_len = _libssh2_ntohu32(exchange_state->s);
- exchange_state->s += 4;
- exchange_state->h_sig = exchange_state->s;
+ if(_libssh2_get_string(&buf, &(exchange_state->h_sig),
+ &(exchange_state->h_sig_len))) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unable to get h sig");
+ goto clean_exit;
+ }
/* Compute the shared secret */
- _libssh2_bn_mod_exp(exchange_state->k, exchange_state->f,
- exchange_state->x, p, exchange_state->ctx);
+ libssh2_dh_secret(&exchange_state->x, exchange_state->k,
+ exchange_state->f, p, exchange_state->ctx);
exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
- if (_libssh2_bn_bits(exchange_state->k) % 8) {
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
/* don't need leading 00 */
exchange_state->k_value_len--;
}
exchange_state->k_value =
LIBSSH2_ALLOC(session, exchange_state->k_value_len);
- if (!exchange_state->k_value) {
+ if(!exchange_state->k_value) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate buffer for K");
goto clean_exit;
}
_libssh2_htonu32(exchange_state->k_value,
exchange_state->k_value_len - 4);
- if (_libssh2_bn_bits(exchange_state->k) % 8) {
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
_libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4);
- } else {
+ }
+ else {
exchange_state->k_value[4] = 0;
_libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
}
- exchange_state->exchange_hash = (void*)&exchange_hash_ctx;
+ exchange_state->exchange_hash = (void *)&exchange_hash_ctx;
libssh2_sha1_init(&exchange_hash_ctx);
- if (session->local.banner) {
+ if(session->local.banner) {
_libssh2_htonu32(exchange_state->h_sig_comp,
strlen((char *) session->local.banner) - 2);
libssh2_sha1_update(exchange_hash_ctx,
exchange_state->h_sig_comp, 4);
libssh2_sha1_update(exchange_hash_ctx,
- (char *) session->local.banner,
+ session->local.banner,
strlen((char *) session->local.banner) - 2);
- } else {
+ }
+ else {
_libssh2_htonu32(exchange_state->h_sig_comp,
sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
libssh2_sha1_update(exchange_hash_ctx,
exchange_state->h_sig_comp, 4);
libssh2_sha1_update(exchange_hash_ctx,
+ (const unsigned char *)
LIBSSH2_SSH_DEFAULT_BANNER,
sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
}
@@ -413,7 +474,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
session->server_hostkey,
session->server_hostkey_len);
- if (packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
+ if(packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
/* diffie-hellman-group-exchange hashes additional fields */
#ifdef LIBSSH2_DH_GEX_NEW
_libssh2_htonu32(exchange_state->h_sig_comp,
@@ -432,7 +493,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
#endif
}
- if (midhash) {
+ if(midhash) {
libssh2_sha1_update(exchange_hash_ctx, midhash,
midhash_len);
}
@@ -456,7 +517,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
libssh2_sha1_final(exchange_hash_ctx,
exchange_state->h_sig_comp);
- if (session->hostkey->
+ if(session->hostkey->
sig_verify(session, exchange_state->h_sig,
exchange_state->h_sig_len, exchange_state->h_sig_comp,
20, &session->server_hostkey_abstract)) {
@@ -471,26 +532,29 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_sent2;
}
- if (exchange_state->state == libssh2_NB_state_sent2) {
+ if(exchange_state->state == libssh2_NB_state_sent2) {
rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
- ret = _libssh2_error(session, rc, "Unable to send NEWKEYS message");
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Unable to send NEWKEYS message");
goto clean_exit;
}
exchange_state->state = libssh2_NB_state_sent3;
}
- if (exchange_state->state == libssh2_NB_state_sent3) {
+ if(exchange_state->state == libssh2_NB_state_sent3) {
rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
&exchange_state->tmp,
&exchange_state->tmp_len, 0, NULL, 0,
&exchange_state->req_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
goto clean_exit;
}
@@ -503,46 +567,52 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
for this packet type anyway */
LIBSSH2_FREE(session, exchange_state->tmp);
- if (!session->session_id) {
+ if(!session->session_id) {
session->session_id = LIBSSH2_ALLOC(session, SHA_DIGEST_LENGTH);
- if (!session->session_id) {
+ if(!session->session_id) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
- "Unable to allocate buffer for SHA digest");
+ "Unable to allocate buffer for "
+ "SHA digest");
goto clean_exit;
}
memcpy(session->session_id, exchange_state->h_sig_comp,
SHA_DIGEST_LENGTH);
session->session_id_len = SHA_DIGEST_LENGTH;
- _libssh2_debug(session, LIBSSH2_TRACE_KEX, "session_id calculated");
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "session_id calculated");
}
/* Cleanup any existing cipher */
- if (session->local.crypt->dtor) {
+ if(session->local.crypt->dtor) {
session->local.crypt->dtor(session,
&session->local.crypt_abstract);
}
/* Calculate IV/Secret/Key for each direction */
- if (session->local.crypt->init) {
+ if(session->local.crypt->init) {
unsigned char *iv = NULL, *secret = NULL;
int free_iv = 0, free_secret = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv,
session->local.crypt->
- iv_len, "A");
- if (!iv) {
+ iv_len,
+ (const unsigned char *)
+ "A");
+ if(!iv) {
ret = -1;
goto clean_exit;
}
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
session->local.crypt->
- secret_len, "C");
- if (!secret) {
+ secret_len,
+ (const unsigned char *)
+ "C");
+ if(!secret) {
LIBSSH2_FREE(session, iv);
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
- if (session->local.crypt->
+ if(session->local.crypt->
init(session, session->local.crypt, iv, &free_iv, secret,
&free_secret, 1, &session->local.crypt_abstract)) {
LIBSSH2_FREE(session, iv);
@@ -551,45 +621,50 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
goto clean_exit;
}
- if (free_iv) {
- memset(iv, 0, session->local.crypt->iv_len);
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
LIBSSH2_FREE(session, iv);
}
- if (free_secret) {
- memset(secret, 0, session->local.crypt->secret_len);
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->local.crypt->secret_len);
LIBSSH2_FREE(session, secret);
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server IV and Key calculated");
- if (session->remote.crypt->dtor) {
+ if(session->remote.crypt->dtor) {
/* Cleanup any existing cipher */
session->remote.crypt->dtor(session,
&session->remote.crypt_abstract);
}
- if (session->remote.crypt->init) {
+ if(session->remote.crypt->init) {
unsigned char *iv = NULL, *secret = NULL;
int free_iv = 0, free_secret = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv,
session->remote.crypt->
- iv_len, "B");
- if (!iv) {
+ iv_len,
+ (const unsigned char *)
+ "B");
+ if(!iv) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
session->remote.crypt->
- secret_len, "D");
- if (!secret) {
+ secret_len,
+ (const unsigned char *)
+ "D");
+ if(!secret) {
LIBSSH2_FREE(session, iv);
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
- if (session->remote.crypt->
+ if(session->remote.crypt->
init(session, session->remote.crypt, iv, &free_iv, secret,
&free_secret, 0, &session->remote.crypt_abstract)) {
LIBSSH2_FREE(session, iv);
@@ -598,65 +673,70 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
goto clean_exit;
}
- if (free_iv) {
- memset(iv, 0, session->remote.crypt->iv_len);
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
LIBSSH2_FREE(session, iv);
}
- if (free_secret) {
- memset(secret, 0, session->remote.crypt->secret_len);
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->remote.crypt->secret_len);
LIBSSH2_FREE(session, secret);
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Server to Client IV and Key calculated");
- if (session->local.mac->dtor) {
+ if(session->local.mac->dtor) {
session->local.mac->dtor(session, &session->local.mac_abstract);
}
- if (session->local.mac->init) {
+ if(session->local.mac->init) {
unsigned char *key = NULL;
int free_key = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key,
session->local.mac->
- key_len, "E");
- if (!key) {
+ key_len,
+ (const unsigned char *)
+ "E");
+ if(!key) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
session->local.mac->init(session, key, &free_key,
&session->local.mac_abstract);
- if (free_key) {
- memset(key, 0, session->local.mac->key_len);
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->local.mac->key_len);
LIBSSH2_FREE(session, key);
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server HMAC Key calculated");
- if (session->remote.mac->dtor) {
+ if(session->remote.mac->dtor) {
session->remote.mac->dtor(session, &session->remote.mac_abstract);
}
- if (session->remote.mac->init) {
+ if(session->remote.mac->init) {
unsigned char *key = NULL;
int free_key = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key,
session->remote.mac->
- key_len, "F");
- if (!key) {
+ key_len,
+ (const unsigned char *)
+ "F");
+ if(!key) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
session->remote.mac->init(session, key, &free_key,
&session->remote.mac_abstract);
- if (free_key) {
- memset(key, 0, session->remote.mac->key_len);
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->remote.mac->key_len);
LIBSSH2_FREE(session, key);
}
}
@@ -666,13 +746,13 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
/* Initialize compression for each direction */
/* Cleanup any existing compression */
- if (session->local.comp && session->local.comp->dtor) {
+ if(session->local.comp && session->local.comp->dtor) {
session->local.comp->dtor(session, 1,
&session->local.comp_abstract);
}
- if (session->local.comp && session->local.comp->init) {
- if (session->local.comp->init(session, 1,
+ if(session->local.comp && session->local.comp->init) {
+ if(session->local.comp->init(session, 1,
&session->local.comp_abstract)) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
@@ -681,13 +761,13 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server compression initialized");
- if (session->remote.comp && session->remote.comp->dtor) {
+ if(session->remote.comp && session->remote.comp->dtor) {
session->remote.comp->dtor(session, 0,
&session->remote.comp_abstract);
}
- if (session->remote.comp && session->remote.comp->init) {
- if (session->remote.comp->init(session, 0,
+ if(session->remote.comp && session->remote.comp->init) {
+ if(session->remote.comp->init(session, 0,
&session->remote.comp_abstract)) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
@@ -699,8 +779,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
}
clean_exit:
- _libssh2_bn_free(exchange_state->x);
- exchange_state->x = NULL;
+ libssh2_dh_dtor(&exchange_state->x);
_libssh2_bn_free(exchange_state->e);
exchange_state->e = NULL;
_libssh2_bn_free(exchange_state->f);
@@ -710,17 +789,17 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
_libssh2_bn_ctx_free(exchange_state->ctx);
exchange_state->ctx = NULL;
- if (exchange_state->e_packet) {
+ if(exchange_state->e_packet) {
LIBSSH2_FREE(session, exchange_state->e_packet);
exchange_state->e_packet = NULL;
}
- if (exchange_state->s_packet) {
+ if(exchange_state->s_packet) {
LIBSSH2_FREE(session, exchange_state->s_packet);
exchange_state->s_packet = NULL;
}
- if (exchange_state->k_value) {
+ if(exchange_state->k_value) {
LIBSSH2_FREE(session, exchange_state->k_value);
exchange_state->k_value = NULL;
}
@@ -750,37 +829,40 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
int rc;
libssh2_sha256_ctx exchange_hash_ctx;
- if (exchange_state->state == libssh2_NB_state_idle) {
+ if(exchange_state->state == libssh2_NB_state_idle) {
/* Setup initial values */
exchange_state->e_packet = NULL;
exchange_state->s_packet = NULL;
exchange_state->k_value = NULL;
exchange_state->ctx = _libssh2_bn_ctx_new();
- exchange_state->x = _libssh2_bn_init(); /* Random from client */
+ libssh2_dh_init(&exchange_state->x);
exchange_state->e = _libssh2_bn_init(); /* g^x mod p */
- exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from server) mod p */
- exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod p */
+ exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from
+ server) mod p */
+ exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod
+ p */
/* Zero the whole thing out */
memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t));
/* Generate x and e */
- _libssh2_bn_rand(exchange_state->x, group_order * 8 - 1, 0, -1);
- _libssh2_bn_mod_exp(exchange_state->e, g, exchange_state->x, p,
- exchange_state->ctx);
+ rc = libssh2_dh_key_pair(&exchange_state->x, exchange_state->e, g, p,
+ group_order, exchange_state->ctx);
+ if(rc)
+ goto clean_exit;
/* Send KEX init */
/* packet_type(1) + String Length(4) + leading 0(1) */
exchange_state->e_packet_len =
_libssh2_bn_bytes(exchange_state->e) + 6;
- if (_libssh2_bn_bits(exchange_state->e) % 8) {
+ if(_libssh2_bn_bits(exchange_state->e) % 8) {
/* Leading 00 not needed */
exchange_state->e_packet_len--;
}
exchange_state->e_packet =
LIBSSH2_ALLOC(session, exchange_state->e_packet_len);
- if (!exchange_state->e_packet) {
+ if(!exchange_state->e_packet) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Out of memory error");
goto clean_exit;
@@ -788,10 +870,11 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
exchange_state->e_packet[0] = packet_type_init;
_libssh2_htonu32(exchange_state->e_packet + 1,
exchange_state->e_packet_len - 5);
- if (_libssh2_bn_bits(exchange_state->e) % 8) {
+ if(_libssh2_bn_bits(exchange_state->e) % 8) {
_libssh2_bn_to_bin(exchange_state->e,
exchange_state->e_packet + 5);
- } else {
+ }
+ else {
exchange_state->e_packet[5] = 0;
_libssh2_bn_to_bin(exchange_state->e,
exchange_state->e_packet + 6);
@@ -802,13 +885,14 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_created;
}
- if (exchange_state->state == libssh2_NB_state_created) {
+ if(exchange_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, exchange_state->e_packet,
exchange_state->e_packet_len,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc,
"Unable to send KEX init message");
goto clean_exit;
@@ -816,20 +900,22 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_sent;
}
- if (exchange_state->state == libssh2_NB_state_sent) {
- if (session->burn_optimistic_kexinit) {
+ if(exchange_state->state == libssh2_NB_state_sent) {
+ if(session->burn_optimistic_kexinit) {
/* The first KEX packet to come along will be the guess initially
* sent by the server. That guess turned out to be wrong so we
* need to silently ignore it */
int burn_type;
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
- "Waiting for badly guessed KEX packet (to be ignored)");
+ "Waiting for badly guessed KEX packet "
+ "(to be ignored)");
burn_type =
_libssh2_packet_burn(session, &exchange_state->burn_state);
- if (burn_type == LIBSSH2_ERROR_EAGAIN) {
+ if(burn_type == LIBSSH2_ERROR_EAGAIN) {
return burn_type;
- } else if (burn_type <= 0) {
+ }
+ else if(burn_type <= 0) {
/* Failed to receive a packet */
ret = burn_type;
goto clean_exit;
@@ -844,16 +930,19 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_sent1;
}
- if (exchange_state->state == libssh2_NB_state_sent1) {
+ if(exchange_state->state == libssh2_NB_state_sent1) {
/* Wait for KEX reply */
+ struct string_buf buf;
+ size_t host_key_len;
+
rc = _libssh2_packet_require(session, packet_type_reply,
&exchange_state->s_packet,
&exchange_state->s_packet_len, 0, NULL,
0, &exchange_state->req_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- if (rc) {
+ if(rc) {
ret = _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
"Timed out waiting for KEX reply");
goto clean_exit;
@@ -865,38 +954,29 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
"Unexpected packet length");
goto clean_exit;
}
-
- exchange_state->s = exchange_state->s_packet + 1;
- session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s);
- exchange_state->s += 4;
+ buf.data = exchange_state->s_packet;
+ buf.len = exchange_state->s_packet_len;
+ buf.dataptr = buf.data;
+ buf.dataptr++; /* advance past type */
- if(session->server_hostkey_len > exchange_state->s_packet_len - 5) {
- ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
- "Host key length out of bounds");
- goto clean_exit;
- }
-
- if (session->server_hostkey)
+ if(session->server_hostkey)
LIBSSH2_FREE(session, session->server_hostkey);
- session->server_hostkey =
- LIBSSH2_ALLOC(session, session->server_hostkey_len);
- if (!session->server_hostkey) {
+ if(_libssh2_copy_string(session, &buf, &(session->server_hostkey),
+ &host_key_len)) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
- "Unable to allocate memory for a copy "
- "of the host key");
+ "Could not copy host key");
goto clean_exit;
}
- memcpy(session->server_hostkey, exchange_state->s,
- session->server_hostkey_len);
- exchange_state->s += session->server_hostkey_len;
+
+ session->server_hostkey_len = (uint32_t)host_key_len;
#if LIBSSH2_MD5
{
libssh2_md5_ctx fingerprint_ctx;
- if (libssh2_md5_init(&fingerprint_ctx)) {
+ if(libssh2_md5_init(&fingerprint_ctx)) {
libssh2_md5_update(fingerprint_ctx, session->server_hostkey,
session->server_hostkey_len);
libssh2_md5_final(fingerprint_ctx,
@@ -924,7 +1004,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
{
libssh2_sha1_ctx fingerprint_ctx;
- if (libssh2_sha1_init(&fingerprint_ctx)) {
+ if(libssh2_sha1_init(&fingerprint_ctx)) {
libssh2_sha1_update(fingerprint_ctx, session->server_hostkey,
session->server_hostkey_len);
libssh2_sha1_final(fingerprint_ctx,
@@ -949,7 +1029,37 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
}
#endif /* LIBSSH2DEBUG */
- if (session->hostkey->init(session, session->server_hostkey,
+ {
+ libssh2_sha256_ctx fingerprint_ctx;
+
+ if(libssh2_sha256_init(&fingerprint_ctx)) {
+ libssh2_sha256_update(fingerprint_ctx, session->server_hostkey,
+ session->server_hostkey_len);
+ libssh2_sha256_final(fingerprint_ctx,
+ session->server_hostkey_sha256);
+ session->server_hostkey_sha256_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_sha256_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char *base64Fingerprint = NULL;
+ _libssh2_base64_encode(session,
+ (const char *)
+ session->server_hostkey_sha256,
+ SHA256_DIGEST_LENGTH, &base64Fingerprint);
+ if(base64Fingerprint != NULL) {
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's SHA256 Fingerprint: %s",
+ base64Fingerprint);
+ LIBSSH2_FREE(session, base64Fingerprint);
+ }
+ }
+#endif /* LIBSSH2DEBUG */
+
+ if(session->hostkey->init(session, session->server_hostkey,
session->server_hostkey_len,
&session->server_hostkey_abstract)) {
ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
@@ -957,58 +1067,67 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
goto clean_exit;
}
- exchange_state->f_value_len = _libssh2_ntohu32(exchange_state->s);
- exchange_state->s += 4;
- exchange_state->f_value = exchange_state->s;
- exchange_state->s += exchange_state->f_value_len;
+ if(_libssh2_get_string(&buf, &(exchange_state->f_value),
+ &(exchange_state->f_value_len))) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unable to get f value");
+ goto clean_exit;
+ }
+
_libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len,
exchange_state->f_value);
- exchange_state->h_sig_len = _libssh2_ntohu32(exchange_state->s);
- exchange_state->s += 4;
- exchange_state->h_sig = exchange_state->s;
+ if(_libssh2_get_string(&buf, &(exchange_state->h_sig),
+ &(exchange_state->h_sig_len))) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unable to get h sig");
+ goto clean_exit;
+ }
/* Compute the shared secret */
- _libssh2_bn_mod_exp(exchange_state->k, exchange_state->f,
- exchange_state->x, p, exchange_state->ctx);
+ libssh2_dh_secret(&exchange_state->x, exchange_state->k,
+ exchange_state->f, p, exchange_state->ctx);
exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
- if (_libssh2_bn_bits(exchange_state->k) % 8) {
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
/* don't need leading 00 */
exchange_state->k_value_len--;
}
exchange_state->k_value =
LIBSSH2_ALLOC(session, exchange_state->k_value_len);
- if (!exchange_state->k_value) {
+ if(!exchange_state->k_value) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate buffer for K");
goto clean_exit;
}
_libssh2_htonu32(exchange_state->k_value,
exchange_state->k_value_len - 4);
- if (_libssh2_bn_bits(exchange_state->k) % 8) {
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
_libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4);
- } else {
+ }
+ else {
exchange_state->k_value[4] = 0;
_libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
}
- exchange_state->exchange_hash = (void*)&exchange_hash_ctx;
+ exchange_state->exchange_hash = (void *)&exchange_hash_ctx;
libssh2_sha256_init(&exchange_hash_ctx);
- if (session->local.banner) {
+ if(session->local.banner) {
_libssh2_htonu32(exchange_state->h_sig_comp,
strlen((char *) session->local.banner) - 2);
libssh2_sha256_update(exchange_hash_ctx,
exchange_state->h_sig_comp, 4);
libssh2_sha256_update(exchange_hash_ctx,
- (char *) session->local.banner,
+ session->local.banner,
strlen((char *) session->local.banner) - 2);
- } else {
+ }
+ else {
_libssh2_htonu32(exchange_state->h_sig_comp,
sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
libssh2_sha256_update(exchange_hash_ctx,
exchange_state->h_sig_comp, 4);
libssh2_sha256_update(exchange_hash_ctx,
+ (const unsigned char *)
LIBSSH2_SSH_DEFAULT_BANNER,
sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
}
@@ -1045,7 +1164,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
session->server_hostkey,
session->server_hostkey_len);
- if (packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
+ if(packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
/* diffie-hellman-group-exchange hashes additional fields */
#ifdef LIBSSH2_DH_GEX_NEW
_libssh2_htonu32(exchange_state->h_sig_comp,
@@ -1064,7 +1183,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
#endif
}
- if (midhash) {
+ if(midhash) {
libssh2_sha256_update(exchange_hash_ctx, midhash,
midhash_len);
}
@@ -1088,10 +1207,11 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
libssh2_sha256_final(exchange_hash_ctx,
exchange_state->h_sig_comp);
- if (session->hostkey->
- sig_verify(session, exchange_state->h_sig,
- exchange_state->h_sig_len, exchange_state->h_sig_comp,
- SHA256_DIGEST_LENGTH, &session->server_hostkey_abstract)) {
+ if(session->hostkey->
+ sig_verify(session, exchange_state->h_sig,
+ exchange_state->h_sig_len, exchange_state->h_sig_comp,
+ SHA256_DIGEST_LENGTH,
+ &session->server_hostkey_abstract)) {
ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
"Unable to verify hostkey signature");
goto clean_exit;
@@ -1105,26 +1225,29 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_sent2;
}
- if (exchange_state->state == libssh2_NB_state_sent2) {
+ if(exchange_state->state == libssh2_NB_state_sent2) {
rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
- ret = _libssh2_error(session, rc, "Unable to send NEWKEYS message");
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Unable to send NEWKEYS message");
goto clean_exit;
}
exchange_state->state = libssh2_NB_state_sent3;
}
- if (exchange_state->state == libssh2_NB_state_sent3) {
+ if(exchange_state->state == libssh2_NB_state_sent3) {
rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
&exchange_state->tmp,
&exchange_state->tmp_len, 0, NULL, 0,
&exchange_state->req_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
goto clean_exit;
}
@@ -1137,46 +1260,50 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
for this packet type anyway */
LIBSSH2_FREE(session, exchange_state->tmp);
- if (!session->session_id) {
+ if(!session->session_id) {
session->session_id = LIBSSH2_ALLOC(session, SHA256_DIGEST_LENGTH);
- if (!session->session_id) {
+ if(!session->session_id) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
- "Unable to allocate buffer for SHA digest");
+ "Unable to allocate buffer for "
+ "SHA digest");
goto clean_exit;
}
memcpy(session->session_id, exchange_state->h_sig_comp,
SHA256_DIGEST_LENGTH);
session->session_id_len = SHA256_DIGEST_LENGTH;
- _libssh2_debug(session, LIBSSH2_TRACE_KEX, "session_id calculated");
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "session_id calculated");
}
/* Cleanup any existing cipher */
- if (session->local.crypt->dtor) {
+ if(session->local.crypt->dtor) {
session->local.crypt->dtor(session,
&session->local.crypt_abstract);
}
/* Calculate IV/Secret/Key for each direction */
- if (session->local.crypt->init) {
+ if(session->local.crypt->init) {
unsigned char *iv = NULL, *secret = NULL;
int free_iv = 0, free_secret = 0;
- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(iv,
- session->local.crypt->
- iv_len, "A");
- if (!iv) {
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
+ session->local.crypt->
+ iv_len,
+ (const unsigned char *)"A");
+ if(!iv) {
ret = -1;
goto clean_exit;
}
- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(secret,
- session->local.crypt->
- secret_len, "C");
- if (!secret) {
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
+ session->local.crypt->
+ secret_len,
+ (const unsigned char *)"C");
+ if(!secret) {
LIBSSH2_FREE(session, iv);
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
- if (session->local.crypt->
+ if(session->local.crypt->
init(session, session->local.crypt, iv, &free_iv, secret,
&free_secret, 1, &session->local.crypt_abstract)) {
LIBSSH2_FREE(session, iv);
@@ -1185,45 +1312,48 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
goto clean_exit;
}
- if (free_iv) {
- memset(iv, 0, session->local.crypt->iv_len);
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
LIBSSH2_FREE(session, iv);
}
- if (free_secret) {
- memset(secret, 0, session->local.crypt->secret_len);
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->local.crypt->secret_len);
LIBSSH2_FREE(session, secret);
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server IV and Key calculated");
- if (session->remote.crypt->dtor) {
+ if(session->remote.crypt->dtor) {
/* Cleanup any existing cipher */
session->remote.crypt->dtor(session,
&session->remote.crypt_abstract);
}
- if (session->remote.crypt->init) {
+ if(session->remote.crypt->init) {
unsigned char *iv = NULL, *secret = NULL;
int free_iv = 0, free_secret = 0;
- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(iv,
- session->remote.crypt->
- iv_len, "B");
- if (!iv) {
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
+ session->remote.crypt->
+ iv_len,
+ (const unsigned char *)"B");
+ if(!iv) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(secret,
- session->remote.crypt->
- secret_len, "D");
- if (!secret) {
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
+ session->remote.crypt->
+ secret_len,
+ (const unsigned char *)"D");
+ if(!secret) {
LIBSSH2_FREE(session, iv);
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
- if (session->remote.crypt->
+ if(session->remote.crypt->
init(session, session->remote.crypt, iv, &free_iv, secret,
&free_secret, 0, &session->remote.crypt_abstract)) {
LIBSSH2_FREE(session, iv);
@@ -1232,65 +1362,68 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
goto clean_exit;
}
- if (free_iv) {
- memset(iv, 0, session->remote.crypt->iv_len);
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
LIBSSH2_FREE(session, iv);
}
- if (free_secret) {
- memset(secret, 0, session->remote.crypt->secret_len);
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->remote.crypt->secret_len);
LIBSSH2_FREE(session, secret);
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Server to Client IV and Key calculated");
- if (session->local.mac->dtor) {
+ if(session->local.mac->dtor) {
session->local.mac->dtor(session, &session->local.mac_abstract);
}
- if (session->local.mac->init) {
+ if(session->local.mac->init) {
unsigned char *key = NULL;
int free_key = 0;
- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(key,
- session->local.mac->
- key_len, "E");
- if (!key) {
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
+ session->local.mac->
+ key_len,
+ (const unsigned char *)"E");
+ if(!key) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
session->local.mac->init(session, key, &free_key,
&session->local.mac_abstract);
- if (free_key) {
- memset(key, 0, session->local.mac->key_len);
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->local.mac->key_len);
LIBSSH2_FREE(session, key);
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server HMAC Key calculated");
- if (session->remote.mac->dtor) {
+ if(session->remote.mac->dtor) {
session->remote.mac->dtor(session, &session->remote.mac_abstract);
}
- if (session->remote.mac->init) {
+ if(session->remote.mac->init) {
unsigned char *key = NULL;
int free_key = 0;
- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(key,
- session->remote.mac->
- key_len, "F");
- if (!key) {
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
+ session->remote.mac->
+ key_len,
+ (const unsigned char *)"F");
+ if(!key) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
session->remote.mac->init(session, key, &free_key,
&session->remote.mac_abstract);
- if (free_key) {
- memset(key, 0, session->remote.mac->key_len);
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->remote.mac->key_len);
LIBSSH2_FREE(session, key);
}
}
@@ -1300,13 +1433,13 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
/* Initialize compression for each direction */
/* Cleanup any existing compression */
- if (session->local.comp && session->local.comp->dtor) {
+ if(session->local.comp && session->local.comp->dtor) {
session->local.comp->dtor(session, 1,
&session->local.comp_abstract);
}
- if (session->local.comp && session->local.comp->init) {
- if (session->local.comp->init(session, 1,
+ if(session->local.comp && session->local.comp->init) {
+ if(session->local.comp->init(session, 1,
&session->local.comp_abstract)) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
@@ -1315,13 +1448,13 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server compression initialized");
- if (session->remote.comp && session->remote.comp->dtor) {
+ if(session->remote.comp && session->remote.comp->dtor) {
session->remote.comp->dtor(session, 0,
&session->remote.comp_abstract);
}
- if (session->remote.comp && session->remote.comp->init) {
- if (session->remote.comp->init(session, 0,
+ if(session->remote.comp && session->remote.comp->init) {
+ if(session->remote.comp->init(session, 0,
&session->remote.comp_abstract)) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
@@ -1333,8 +1466,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
}
clean_exit:
- _libssh2_bn_free(exchange_state->x);
- exchange_state->x = NULL;
+ libssh2_dh_dtor(&exchange_state->x);
_libssh2_bn_free(exchange_state->e);
exchange_state->e = NULL;
_libssh2_bn_free(exchange_state->f);
@@ -1344,17 +1476,17 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
_libssh2_bn_ctx_free(exchange_state->ctx);
exchange_state->ctx = NULL;
- if (exchange_state->e_packet) {
+ if(exchange_state->e_packet) {
LIBSSH2_FREE(session, exchange_state->e_packet);
exchange_state->e_packet = NULL;
}
- if (exchange_state->s_packet) {
+ if(exchange_state->s_packet) {
LIBSSH2_FREE(session, exchange_state->s_packet);
exchange_state->s_packet = NULL;
}
- if (exchange_state->k_value) {
+ if(exchange_state->k_value) {
LIBSSH2_FREE(session, exchange_state->k_value);
exchange_state->k_value = NULL;
}
@@ -1395,9 +1527,10 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session,
int ret;
- if (key_state->state == libssh2_NB_state_idle) {
+ if(key_state->state == libssh2_NB_state_idle) {
/* g == 2 */
- key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value (p_value) */
+ key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value
+ (p_value) */
key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */
/* Initialize P and G */
@@ -1412,7 +1545,7 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session,
ret = diffie_hellman_sha1(session, key_state->g, key_state->p, 128,
SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
NULL, 0, &key_state->exchange_state);
- if (ret == LIBSSH2_ERROR_EAGAIN) {
+ if(ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
@@ -1471,8 +1604,9 @@ kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session,
};
int ret;
- if (key_state->state == libssh2_NB_state_idle) {
- key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value (p_value) */
+ if(key_state->state == libssh2_NB_state_idle) {
+ key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value
+ (p_value) */
key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */
/* g == 2 */
@@ -1488,7 +1622,7 @@ kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session,
ret = diffie_hellman_sha1(session, key_state->g, key_state->p,
256, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
NULL, 0, &key_state->exchange_state);
- if (ret == LIBSSH2_ERROR_EAGAIN) {
+ if(ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
@@ -1511,11 +1645,10 @@ static int
kex_method_diffie_hellman_group_exchange_sha1_key_exchange
(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
{
- unsigned long p_len, g_len;
int ret = 0;
int rc;
- if (key_state->state == libssh2_NB_state_idle) {
+ if(key_state->state == libssh2_NB_state_idle) {
key_state->p = _libssh2_bn_init_from_bin();
key_state->g = _libssh2_bn_init_from_bin();
/* Ask for a P and G pair */
@@ -1526,24 +1659,27 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
_libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP);
key_state->request_len = 13;
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
- "Initiating Diffie-Hellman Group-Exchange (New Method)");
+ "Initiating Diffie-Hellman Group-Exchange "
+ "(New Method)");
#else
key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD;
_libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_OPTGROUP);
key_state->request_len = 5;
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
- "Initiating Diffie-Hellman Group-Exchange (Old Method)");
+ "Initiating Diffie-Hellman Group-Exchange "
+ "(Old Method)");
#endif
key_state->state = libssh2_NB_state_created;
}
- if (key_state->state == libssh2_NB_state_created) {
+ if(key_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, key_state->request,
key_state->request_len, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc,
"Unable to send Group Exchange Request");
goto dh_gex_clean_exit;
@@ -1552,13 +1688,14 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
key_state->state = libssh2_NB_state_sent;
}
- if (key_state->state == libssh2_NB_state_sent) {
+ if(key_state->state == libssh2_NB_state_sent) {
rc = _libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP,
&key_state->data, &key_state->data_len,
0, NULL, 0, &key_state->req_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc,
"Timeout waiting for GEX_GROUP reply");
goto dh_gex_clean_exit;
@@ -1567,16 +1704,37 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
key_state->state = libssh2_NB_state_sent1;
}
- if (key_state->state == libssh2_NB_state_sent1) {
- unsigned char *s = key_state->data + 1;
- p_len = _libssh2_ntohu32(s);
- s += 4;
- _libssh2_bn_from_bin(key_state->p, p_len, s);
- s += p_len;
+ if(key_state->state == libssh2_NB_state_sent1) {
+ size_t p_len, g_len;
+ unsigned char *p, *g;
+ struct string_buf buf;
- g_len = _libssh2_ntohu32(s);
- s += 4;
- _libssh2_bn_from_bin(key_state->g, g_len, s);
+ if(key_state->data_len < 9) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected key length");
+ goto dh_gex_clean_exit;
+ }
+
+ buf.data = key_state->data;
+ buf.dataptr = buf.data;
+ buf.len = key_state->data_len;
+
+ buf.dataptr++; /* increment to big num */
+
+ if(_libssh2_get_bignum_bytes(&buf, &p, &p_len)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected value");
+ goto dh_gex_clean_exit;
+ }
+
+ if(_libssh2_get_bignum_bytes(&buf, &g, &g_len)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected value");
+ goto dh_gex_clean_exit;
+ }
+
+ _libssh2_bn_from_bin(key_state->p, p_len, p);
+ _libssh2_bn_from_bin(key_state->g, g_len, g);
ret = diffie_hellman_sha1(session, key_state->g, key_state->p, p_len,
SSH_MSG_KEX_DH_GEX_INIT,
@@ -1584,7 +1742,7 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
key_state->data + 1,
key_state->data_len - 1,
&key_state->exchange_state);
- if (ret == LIBSSH2_ERROR_EAGAIN) {
+ if(ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
@@ -1611,11 +1769,10 @@ static int
kex_method_diffie_hellman_group_exchange_sha256_key_exchange
(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
{
- unsigned long p_len, g_len;
int ret = 0;
int rc;
- if (key_state->state == libssh2_NB_state_idle) {
+ if(key_state->state == libssh2_NB_state_idle) {
key_state->p = _libssh2_bn_init();
key_state->g = _libssh2_bn_init();
/* Ask for a P and G pair */
@@ -1626,39 +1783,44 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange
_libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP);
key_state->request_len = 13;
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
- "Initiating Diffie-Hellman Group-Exchange (New Method SHA256)");
+ "Initiating Diffie-Hellman Group-Exchange "
+ "(New Method SHA256)");
#else
key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD;
_libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_OPTGROUP);
key_state->request_len = 5;
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
- "Initiating Diffie-Hellman Group-Exchange (Old Method SHA256)");
+ "Initiating Diffie-Hellman Group-Exchange "
+ "(Old Method SHA256)");
#endif
key_state->state = libssh2_NB_state_created;
}
- if (key_state->state == libssh2_NB_state_created) {
+ if(key_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, key_state->request,
key_state->request_len, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc,
- "Unable to send Group Exchange Request SHA256");
+ "Unable to send "
+ "Group Exchange Request SHA256");
goto dh_gex_clean_exit;
}
key_state->state = libssh2_NB_state_sent;
}
- if (key_state->state == libssh2_NB_state_sent) {
+ if(key_state->state == libssh2_NB_state_sent) {
rc = _libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP,
&key_state->data, &key_state->data_len,
0, NULL, 0, &key_state->req_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc,
"Timeout waiting for GEX_GROUP reply SHA256");
goto dh_gex_clean_exit;
@@ -1667,16 +1829,37 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange
key_state->state = libssh2_NB_state_sent1;
}
- if (key_state->state == libssh2_NB_state_sent1) {
- unsigned char *s = key_state->data + 1;
- p_len = _libssh2_ntohu32(s);
- s += 4;
- _libssh2_bn_from_bin(key_state->p, p_len, s);
- s += p_len;
+ if(key_state->state == libssh2_NB_state_sent1) {
+ unsigned char *p, *g;
+ size_t p_len, g_len;
+ struct string_buf buf;
- g_len = _libssh2_ntohu32(s);
- s += 4;
- _libssh2_bn_from_bin(key_state->g, g_len, s);
+ if(key_state->data_len < 9) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected key length");
+ goto dh_gex_clean_exit;
+ }
+
+ buf.data = key_state->data;
+ buf.dataptr = buf.data;
+ buf.len = key_state->data_len;
+
+ buf.dataptr++; /* increment to big num */
+
+ if(_libssh2_get_bignum_bytes(&buf, &p, &p_len)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected value");
+ goto dh_gex_clean_exit;
+ }
+
+ if(_libssh2_get_bignum_bytes(&buf, &g, &g_len)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected value");
+ goto dh_gex_clean_exit;
+ }
+
+ _libssh2_bn_from_bin(key_state->p, p_len, p);
+ _libssh2_bn_from_bin(key_state->g, g_len, g);
ret = diffie_hellman_sha256(session, key_state->g, key_state->p, p_len,
SSH_MSG_KEX_DH_GEX_INIT,
@@ -1684,7 +1867,7 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange
key_state->data + 1,
key_state->data_len - 1,
&key_state->exchange_state);
- if (ret == LIBSSH2_ERROR_EAGAIN) {
+ if(ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
@@ -1702,6 +1885,1369 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange
}
+#if LIBSSH2_ECDSA
+
+/* kex_session_ecdh_curve_type
+ * returns the EC curve type by name used in key exchange
+ */
+
+static int
+kex_session_ecdh_curve_type(const char *name, libssh2_curve_type *out_type)
+{
+ int ret = 0;
+ libssh2_curve_type type;
+
+ if(name == NULL)
+ return -1;
+
+ if(strcmp(name, "ecdh-sha2-nistp256") == 0)
+ type = LIBSSH2_EC_CURVE_NISTP256;
+ else if(strcmp(name, "ecdh-sha2-nistp384") == 0)
+ type = LIBSSH2_EC_CURVE_NISTP384;
+ else if(strcmp(name, "ecdh-sha2-nistp521") == 0)
+ type = LIBSSH2_EC_CURVE_NISTP521;
+ else {
+ ret = -1;
+ }
+
+ if(ret == 0 && out_type) {
+ *out_type = type;
+ }
+
+ return ret;
+}
+
+
+/* LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY
+ *
+ * Macro that create and verifies EC SHA hash with a given digest bytes
+ *
+ * Payload format:
+ *
+ * string V_C, client's identification string (CR and LF excluded)
+ * string V_S, server's identification string (CR and LF excluded)
+ * string I_C, payload of the client's SSH_MSG_KEXINIT
+ * string I_S, payload of the server's SSH_MSG_KEXINIT
+ * string K_S, server's public host key
+ * string Q_C, client's ephemeral public key octet string
+ * string Q_S, server's ephemeral public key octet string
+ * mpint K, shared secret
+ *
+ */
+
+#define LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(digest_type) \
+{ \
+ libssh2_sha##digest_type##_ctx ctx; \
+ exchange_state->exchange_hash = (void *)&ctx; \
+ libssh2_sha##digest_type##_init(&ctx); \
+ if(session->local.banner) { \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ strlen((char *) session->local.banner) - 2); \
+ libssh2_sha##digest_type##_update(ctx, \
+ exchange_state->h_sig_comp, 4); \
+ libssh2_sha##digest_type##_update(ctx, \
+ (char *) session->local.banner, \
+ strlen((char *) \
+ session->local.banner) \
+ - 2); \
+ } \
+ else { \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); \
+ libssh2_sha##digest_type##_update(ctx, \
+ exchange_state->h_sig_comp, 4); \
+ libssh2_sha##digest_type##_update(ctx, \
+ LIBSSH2_SSH_DEFAULT_BANNER, \
+ sizeof(LIBSSH2_SSH_DEFAULT_BANNER) \
+ - 1); \
+ } \
+ \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ strlen((char *) session->remote.banner)); \
+ libssh2_sha##digest_type##_update(ctx, \
+ exchange_state->h_sig_comp, 4); \
+ libssh2_sha##digest_type##_update(ctx, \
+ session->remote.banner, \
+ strlen((char *) \
+ session->remote.banner)); \
+ \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ session->local.kexinit_len); \
+ libssh2_sha##digest_type##_update(ctx, \
+ exchange_state->h_sig_comp, 4); \
+ libssh2_sha##digest_type##_update(ctx, \
+ session->local.kexinit, \
+ session->local.kexinit_len); \
+ \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ session->remote.kexinit_len); \
+ libssh2_sha##digest_type##_update(ctx, \
+ exchange_state->h_sig_comp, 4); \
+ libssh2_sha##digest_type##_update(ctx, \
+ session->remote.kexinit, \
+ session->remote.kexinit_len); \
+ \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ session->server_hostkey_len); \
+ libssh2_sha##digest_type##_update(ctx, \
+ exchange_state->h_sig_comp, 4); \
+ libssh2_sha##digest_type##_update(ctx, \
+ session->server_hostkey, \
+ session->server_hostkey_len); \
+ \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ public_key_len); \
+ libssh2_sha##digest_type##_update(ctx, \
+ exchange_state->h_sig_comp, 4); \
+ libssh2_sha##digest_type##_update(ctx, \
+ public_key, \
+ public_key_len); \
+ \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ server_public_key_len); \
+ libssh2_sha##digest_type##_update(ctx, \
+ exchange_state->h_sig_comp, 4); \
+ libssh2_sha##digest_type##_update(ctx, \
+ server_public_key, \
+ server_public_key_len); \
+ \
+ libssh2_sha##digest_type##_update(ctx, \
+ exchange_state->k_value, \
+ exchange_state->k_value_len); \
+ \
+ libssh2_sha##digest_type##_final(ctx, exchange_state->h_sig_comp); \
+ \
+ if(session->hostkey-> \
+ sig_verify(session, exchange_state->h_sig, \
+ exchange_state->h_sig_len, exchange_state->h_sig_comp, \
+ SHA##digest_type##_DIGEST_LENGTH, \
+ &session->server_hostkey_abstract)) { \
+ rc = -1; \
+ } \
+} \
+
+
+/* ecdh_sha2_nistp
+ * Elliptic Curve Diffie Hellman Key Exchange
+ */
+
+static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type,
+ unsigned char *data, size_t data_len,
+ unsigned char *public_key,
+ size_t public_key_len, _libssh2_ec_key *private_key,
+ kmdhgGPshakex_state_t *exchange_state)
+{
+ int ret = 0;
+ int rc;
+
+ if(data_len < 5) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Host key data is too short");
+ return ret;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_idle) {
+
+ /* Setup initial values */
+ exchange_state->k = _libssh2_bn_init();
+
+ exchange_state->state = libssh2_NB_state_created;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_created) {
+ /* parse INIT reply data */
+
+ /* host key K_S */
+ unsigned char *s = data + 1; /* Advance past packet type */
+ unsigned char *server_public_key;
+ size_t server_public_key_len;
+ size_t host_sig_len;
+
+ session->server_hostkey_len =
+ _libssh2_ntohu32((const unsigned char *)s);
+ s += 4;
+
+ session->server_hostkey = LIBSSH2_ALLOC(session,
+ session->server_hostkey_len);
+ if(!session->server_hostkey) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate memory for a copy "
+ "of the host key");
+ goto clean_exit;
+ }
+
+ memcpy(session->server_hostkey, s, session->server_hostkey_len);
+ s += session->server_hostkey_len;
+
+#if LIBSSH2_MD5
+ {
+ libssh2_md5_ctx fingerprint_ctx;
+
+ if(libssh2_md5_init(&fingerprint_ctx)) {
+ libssh2_md5_update(fingerprint_ctx, session->server_hostkey,
+ session->server_hostkey_len);
+ libssh2_md5_final(fingerprint_ctx,
+ session->server_hostkey_md5);
+ session->server_hostkey_md5_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_md5_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char fingerprint[50], *fprint = fingerprint;
+ int i;
+ for(i = 0; i < 16; i++, fprint += 3) {
+ snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
+ }
+ *(--fprint) = '\0';
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's MD5 Fingerprint: %s", fingerprint);
+ }
+#endif /* LIBSSH2DEBUG */
+#endif /* ! LIBSSH2_MD5 */
+
+ {
+ libssh2_sha1_ctx fingerprint_ctx;
+
+ if(libssh2_sha1_init(&fingerprint_ctx)) {
+ libssh2_sha1_update(fingerprint_ctx, session->server_hostkey,
+ session->server_hostkey_len);
+ libssh2_sha1_final(fingerprint_ctx,
+ session->server_hostkey_sha1);
+ session->server_hostkey_sha1_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_sha1_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char fingerprint[64], *fprint = fingerprint;
+ int i;
+
+ for(i = 0; i < 20; i++, fprint += 3) {
+ snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
+ }
+ *(--fprint) = '\0';
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's SHA1 Fingerprint: %s", fingerprint);
+ }
+#endif /* LIBSSH2DEBUG */
+
+ /* SHA256 */
+ {
+ libssh2_sha256_ctx fingerprint_ctx;
+
+ if(libssh2_sha256_init(&fingerprint_ctx)) {
+ libssh2_sha256_update(fingerprint_ctx, session->server_hostkey,
+ session->server_hostkey_len);
+ libssh2_sha256_final(fingerprint_ctx,
+ session->server_hostkey_sha256);
+ session->server_hostkey_sha256_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_sha256_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char *base64Fingerprint = NULL;
+ _libssh2_base64_encode(session,
+ (const char *)
+ session->server_hostkey_sha256,
+ SHA256_DIGEST_LENGTH, &base64Fingerprint);
+ if(base64Fingerprint != NULL) {
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's SHA256 Fingerprint: %s",
+ base64Fingerprint);
+ LIBSSH2_FREE(session, base64Fingerprint);
+ }
+ }
+#endif /* LIBSSH2DEBUG */
+
+ if(session->hostkey->init(session, session->server_hostkey,
+ session->server_hostkey_len,
+ &session->server_hostkey_abstract)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unable to initialize hostkey importer");
+ goto clean_exit;
+ }
+
+ /* server public key Q_S */
+ server_public_key_len = _libssh2_ntohu32((const unsigned char *)s);
+ s += 4;
+
+ server_public_key = s;
+ s += server_public_key_len;
+
+ /* server signature */
+ host_sig_len = _libssh2_ntohu32((const unsigned char *)s);
+ s += 4;
+
+ exchange_state->h_sig = s;
+ exchange_state->h_sig_len = host_sig_len;
+ s += host_sig_len;
+
+ /* Compute the shared secret K */
+ rc = _libssh2_ecdh_gen_k(&exchange_state->k, private_key,
+ server_public_key, server_public_key_len);
+ if(rc != 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
+ "Unable to create ECDH shared secret");
+ goto clean_exit;
+ }
+
+ exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
+ /* don't need leading 00 */
+ exchange_state->k_value_len--;
+ }
+ exchange_state->k_value =
+ LIBSSH2_ALLOC(session, exchange_state->k_value_len);
+ if(!exchange_state->k_value) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate buffer for K");
+ goto clean_exit;
+ }
+ _libssh2_htonu32(exchange_state->k_value,
+ exchange_state->k_value_len - 4);
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
+ _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4);
+ }
+ else {
+ exchange_state->k_value[4] = 0;
+ _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
+ }
+
+ /* verify hash */
+
+ switch(type) {
+ case LIBSSH2_EC_CURVE_NISTP256:
+ LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(256);
+ break;
+
+ case LIBSSH2_EC_CURVE_NISTP384:
+ LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(384);
+ break;
+ case LIBSSH2_EC_CURVE_NISTP521:
+ LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(512);
+ break;
+ }
+
+ if(rc != 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
+ "Unable to verify hostkey signature");
+ goto clean_exit;
+ }
+
+ exchange_state->c = SSH_MSG_NEWKEYS;
+ exchange_state->state = libssh2_NB_state_sent;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_sent) {
+ rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Unable to send NEWKEYS message");
+ goto clean_exit;
+ }
+
+ exchange_state->state = libssh2_NB_state_sent2;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_sent2) {
+ rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
+ &exchange_state->tmp,
+ &exchange_state->tmp_len, 0, NULL, 0,
+ &exchange_state->req_state);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
+ goto clean_exit;
+ }
+
+ /* The first key exchange has been performed,
+ switch to active crypt/comp/mac mode */
+ session->state |= LIBSSH2_STATE_NEWKEYS;
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message");
+
+ /* This will actually end up being just packet_type(1)
+ for this packet type anyway */
+ LIBSSH2_FREE(session, exchange_state->tmp);
+
+ if(!session->session_id) {
+
+ size_t digest_length = 0;
+
+ if(type == LIBSSH2_EC_CURVE_NISTP256)
+ digest_length = SHA256_DIGEST_LENGTH;
+ else if(type == LIBSSH2_EC_CURVE_NISTP384)
+ digest_length = SHA384_DIGEST_LENGTH;
+ else if(type == LIBSSH2_EC_CURVE_NISTP521)
+ digest_length = SHA512_DIGEST_LENGTH;
+ else{
+ ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
+ "Unknown SHA digest for EC curve");
+ goto clean_exit;
+
+ }
+ session->session_id = LIBSSH2_ALLOC(session, digest_length);
+ if(!session->session_id) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate buffer for "
+ "SHA digest");
+ goto clean_exit;
+ }
+ memcpy(session->session_id, exchange_state->h_sig_comp,
+ digest_length);
+ session->session_id_len = digest_length;
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "session_id calculated");
+ }
+
+ /* Cleanup any existing cipher */
+ if(session->local.crypt->dtor) {
+ session->local.crypt->dtor(session,
+ &session->local.crypt_abstract);
+ }
+
+ /* Calculate IV/Secret/Key for each direction */
+ if(session->local.crypt->init) {
+ unsigned char *iv = NULL, *secret = NULL;
+ int free_iv = 0, free_secret = 0;
+
+ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(iv,
+ session->local.crypt->
+ iv_len, "A");
+ if(!iv) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(secret,
+ session->local.crypt->
+ secret_len, "C");
+
+ if(!secret) {
+ LIBSSH2_FREE(session, iv);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ if(session->local.crypt->
+ init(session, session->local.crypt, iv, &free_iv, secret,
+ &free_secret, 1, &session->local.crypt_abstract)) {
+ LIBSSH2_FREE(session, iv);
+ LIBSSH2_FREE(session, secret);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
+ LIBSSH2_FREE(session, iv);
+ }
+
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->local.crypt->secret_len);
+ LIBSSH2_FREE(session, secret);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Client to Server IV and Key calculated");
+
+ if(session->remote.crypt->dtor) {
+ /* Cleanup any existing cipher */
+ session->remote.crypt->dtor(session,
+ &session->remote.crypt_abstract);
+ }
+
+ if(session->remote.crypt->init) {
+ unsigned char *iv = NULL, *secret = NULL;
+ int free_iv = 0, free_secret = 0;
+
+ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(iv,
+ session->remote.crypt->
+ iv_len, "B");
+
+ if(!iv) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(secret,
+ session->remote.crypt->
+ secret_len, "D");
+
+ if(!secret) {
+ LIBSSH2_FREE(session, iv);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ if(session->remote.crypt->
+ init(session, session->remote.crypt, iv, &free_iv, secret,
+ &free_secret, 0, &session->remote.crypt_abstract)) {
+ LIBSSH2_FREE(session, iv);
+ LIBSSH2_FREE(session, secret);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
+ LIBSSH2_FREE(session, iv);
+ }
+
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->remote.crypt->secret_len);
+ LIBSSH2_FREE(session, secret);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server to Client IV and Key calculated");
+
+ if(session->local.mac->dtor) {
+ session->local.mac->dtor(session, &session->local.mac_abstract);
+ }
+
+ if(session->local.mac->init) {
+ unsigned char *key = NULL;
+ int free_key = 0;
+
+ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(key,
+ session->local.mac->
+ key_len, "E");
+
+ if(!key) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ session->local.mac->init(session, key, &free_key,
+ &session->local.mac_abstract);
+
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->local.mac->key_len);
+ LIBSSH2_FREE(session, key);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Client to Server HMAC Key calculated");
+
+ if(session->remote.mac->dtor) {
+ session->remote.mac->dtor(session, &session->remote.mac_abstract);
+ }
+
+ if(session->remote.mac->init) {
+ unsigned char *key = NULL;
+ int free_key = 0;
+
+ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(key,
+ session->remote.mac->
+ key_len, "F");
+
+ if(!key) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ session->remote.mac->init(session, key, &free_key,
+ &session->remote.mac_abstract);
+
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->remote.mac->key_len);
+ LIBSSH2_FREE(session, key);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server to Client HMAC Key calculated");
+
+ /* Initialize compression for each direction */
+
+ /* Cleanup any existing compression */
+ if(session->local.comp && session->local.comp->dtor) {
+ session->local.comp->dtor(session, 1,
+ &session->local.comp_abstract);
+ }
+
+ if(session->local.comp && session->local.comp->init) {
+ if(session->local.comp->init(session, 1,
+ &session->local.comp_abstract)) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Client to Server compression initialized");
+
+ if(session->remote.comp && session->remote.comp->dtor) {
+ session->remote.comp->dtor(session, 0,
+ &session->remote.comp_abstract);
+ }
+
+ if(session->remote.comp && session->remote.comp->init) {
+ if(session->remote.comp->init(session, 0,
+ &session->remote.comp_abstract)) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server to Client compression initialized");
+
+ }
+
+clean_exit:
+ _libssh2_bn_free(exchange_state->k);
+ exchange_state->k = NULL;
+
+ if(exchange_state->k_value) {
+ LIBSSH2_FREE(session, exchange_state->k_value);
+ exchange_state->k_value = NULL;
+ }
+
+ exchange_state->state = libssh2_NB_state_idle;
+
+ return ret;
+}
+
+/* kex_method_ecdh_key_exchange
+ *
+ * Elliptic Curve Diffie Hellman Key Exchange
+ * supports SHA256/384/512 hashes based on negotated ecdh method
+ *
+ */
+
+static int
+kex_method_ecdh_key_exchange
+(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
+{
+ int ret = 0;
+ int rc = 0;
+ unsigned char *s;
+ libssh2_curve_type type;
+
+ if(key_state->state == libssh2_NB_state_idle) {
+
+ key_state->public_key_oct = NULL;
+ key_state->state = libssh2_NB_state_created;
+ }
+
+ if(key_state->state == libssh2_NB_state_created) {
+ rc = kex_session_ecdh_curve_type(session->kex->name, &type);
+
+ if(rc != 0) {
+ ret = _libssh2_error(session, -1,
+ "Unknown KEX nistp curve type");
+ goto ecdh_clean_exit;
+ }
+
+ rc = _libssh2_ecdsa_create_key(session, &key_state->private_key,
+ &key_state->public_key_oct,
+ &key_state->public_key_oct_len, type);
+
+ if(rc != 0) {
+ ret = _libssh2_error(session, rc,
+ "Unable to create private key");
+ goto ecdh_clean_exit;
+ }
+
+ key_state->request[0] = SSH2_MSG_KEX_ECDH_INIT;
+ s = key_state->request + 1;
+ _libssh2_store_str(&s, (const char *)key_state->public_key_oct,
+ key_state->public_key_oct_len);
+ key_state->request_len = key_state->public_key_oct_len + 5;
+
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Initiating ECDH SHA2 NISTP256");
+
+ key_state->state = libssh2_NB_state_sent;
+ }
+
+ if(key_state->state == libssh2_NB_state_sent) {
+ rc = _libssh2_transport_send(session, key_state->request,
+ key_state->request_len, NULL, 0);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Unable to send ECDH_INIT");
+ goto ecdh_clean_exit;
+ }
+
+ key_state->state = libssh2_NB_state_sent1;
+ }
+
+ if(key_state->state == libssh2_NB_state_sent1) {
+ rc = _libssh2_packet_require(session, SSH2_MSG_KEX_ECDH_REPLY,
+ &key_state->data, &key_state->data_len,
+ 0, NULL, 0, &key_state->req_state);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Timeout waiting for ECDH_REPLY reply");
+ goto ecdh_clean_exit;
+ }
+
+ key_state->state = libssh2_NB_state_sent2;
+ }
+
+ if(key_state->state == libssh2_NB_state_sent2) {
+
+ (void)kex_session_ecdh_curve_type(session->kex->name, &type);
+
+ ret = ecdh_sha2_nistp(session, type, key_state->data,
+ key_state->data_len,
+ (unsigned char *)key_state->public_key_oct,
+ key_state->public_key_oct_len,
+ key_state->private_key,
+ &key_state->exchange_state);
+
+ if(ret == LIBSSH2_ERROR_EAGAIN) {
+ return ret;
+ }
+
+ LIBSSH2_FREE(session, key_state->data);
+ }
+
+ecdh_clean_exit:
+
+ if(key_state->public_key_oct) {
+ LIBSSH2_FREE(session, key_state->public_key_oct);
+ key_state->public_key_oct = NULL;
+ }
+
+ if(key_state->private_key) {
+ _libssh2_ecdsa_free(key_state->private_key);
+ key_state->private_key = NULL;
+ }
+
+ key_state->state = libssh2_NB_state_idle;
+
+ return ret;
+}
+
+#endif /*LIBSSH2_ECDSA*/
+
+
+#if LIBSSH2_ED25519
+
+/* curve25519_sha256
+ * Elliptic Curve Key Exchange
+ */
+
+static int
+curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data,
+ size_t data_len,
+ unsigned char public_key[LIBSSH2_ED25519_KEY_LEN],
+ unsigned char private_key[LIBSSH2_ED25519_KEY_LEN],
+ kmdhgGPshakex_state_t *exchange_state)
+{
+ int ret = 0;
+ int rc;
+ int public_key_len = LIBSSH2_ED25519_KEY_LEN;
+
+ if(data_len < 5) {
+ return _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Data is too short");
+ }
+
+ if(exchange_state->state == libssh2_NB_state_idle) {
+
+ /* Setup initial values */
+ exchange_state->k = _libssh2_bn_init();
+
+ exchange_state->state = libssh2_NB_state_created;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_created) {
+ /* parse INIT reply data */
+ unsigned char *server_public_key, *server_host_key;
+ size_t server_public_key_len, hostkey_len;
+ struct string_buf buf;
+
+ if(data_len < 5) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected key length");
+ goto clean_exit;
+ }
+
+ buf.data = data;
+ buf.len = data_len;
+ buf.dataptr = buf.data;
+ buf.dataptr++; /* advance past packet type */
+
+ if(_libssh2_get_string(&buf, &server_host_key, &hostkey_len)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected key length");
+ goto clean_exit;
+ }
+
+ session->server_hostkey_len = (uint32_t)hostkey_len;
+ session->server_hostkey = LIBSSH2_ALLOC(session,
+ session->server_hostkey_len);
+ if(!session->server_hostkey) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate memory for a copy "
+ "of the host key");
+ goto clean_exit;
+ }
+
+ memcpy(session->server_hostkey, server_host_key,
+ session->server_hostkey_len);
+
+#if LIBSSH2_MD5
+ {
+ libssh2_md5_ctx fingerprint_ctx;
+
+ if(libssh2_md5_init(&fingerprint_ctx)) {
+ libssh2_md5_update(fingerprint_ctx, session->server_hostkey,
+ session->server_hostkey_len);
+ libssh2_md5_final(fingerprint_ctx,
+ session->server_hostkey_md5);
+ session->server_hostkey_md5_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_md5_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char fingerprint[50], *fprint = fingerprint;
+ int i;
+ for(i = 0; i < 16; i++, fprint += 3) {
+ snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
+ }
+ *(--fprint) = '\0';
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's MD5 Fingerprint: %s", fingerprint);
+ }
+#endif /* LIBSSH2DEBUG */
+#endif /* ! LIBSSH2_MD5 */
+
+ {
+ libssh2_sha1_ctx fingerprint_ctx;
+
+ if(libssh2_sha1_init(&fingerprint_ctx)) {
+ libssh2_sha1_update(fingerprint_ctx, session->server_hostkey,
+ session->server_hostkey_len);
+ libssh2_sha1_final(fingerprint_ctx,
+ session->server_hostkey_sha1);
+ session->server_hostkey_sha1_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_sha1_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char fingerprint[64], *fprint = fingerprint;
+ int i;
+
+ for(i = 0; i < 20; i++, fprint += 3) {
+ snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
+ }
+ *(--fprint) = '\0';
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's SHA1 Fingerprint: %s", fingerprint);
+ }
+#endif /* LIBSSH2DEBUG */
+
+ /* SHA256 */
+ {
+ libssh2_sha256_ctx fingerprint_ctx;
+
+ if(libssh2_sha256_init(&fingerprint_ctx)) {
+ libssh2_sha256_update(fingerprint_ctx, session->server_hostkey,
+ session->server_hostkey_len);
+ libssh2_sha256_final(fingerprint_ctx,
+ session->server_hostkey_sha256);
+ session->server_hostkey_sha256_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_sha256_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char *base64Fingerprint = NULL;
+ _libssh2_base64_encode(session,
+ (const char *)
+ session->server_hostkey_sha256,
+ SHA256_DIGEST_LENGTH, &base64Fingerprint);
+ if(base64Fingerprint != NULL) {
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's SHA256 Fingerprint: %s",
+ base64Fingerprint);
+ LIBSSH2_FREE(session, base64Fingerprint);
+ }
+ }
+#endif /* LIBSSH2DEBUG */
+
+ if(session->hostkey->init(session, session->server_hostkey,
+ session->server_hostkey_len,
+ &session->server_hostkey_abstract)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unable to initialize hostkey importer");
+ goto clean_exit;
+ }
+
+ /* server public key Q_S */
+ if(_libssh2_get_string(&buf, &server_public_key,
+ &server_public_key_len)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected key length");
+ goto clean_exit;
+ }
+
+ if(server_public_key_len != LIBSSH2_ED25519_KEY_LEN) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unexpected curve25519 server "
+ "public key length");
+ goto clean_exit;
+ }
+
+ /* server signature */
+ if(_libssh2_get_string(&buf, &exchange_state->h_sig,
+ &(exchange_state->h_sig_len))) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unexpected curve25519 server sig length");
+ goto clean_exit;
+ }
+
+ /* Compute the shared secret K */
+ rc = _libssh2_curve25519_gen_k(&exchange_state->k, private_key,
+ server_public_key);
+ if(rc != 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
+ "Unable to create ECDH shared secret");
+ goto clean_exit;
+ }
+
+ exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
+ /* don't need leading 00 */
+ exchange_state->k_value_len--;
+ }
+ exchange_state->k_value =
+ LIBSSH2_ALLOC(session, exchange_state->k_value_len);
+ if(!exchange_state->k_value) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate buffer for K");
+ goto clean_exit;
+ }
+ _libssh2_htonu32(exchange_state->k_value,
+ exchange_state->k_value_len - 4);
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
+ _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4);
+ }
+ else {
+ exchange_state->k_value[4] = 0;
+ _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
+ }
+
+ /*/ verify hash */
+ LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(256);
+
+ if(rc != 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
+ "Unable to verify hostkey signature");
+ goto clean_exit;
+ }
+
+ exchange_state->c = SSH_MSG_NEWKEYS;
+ exchange_state->state = libssh2_NB_state_sent;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_sent) {
+ rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Unable to send NEWKEYS message");
+ goto clean_exit;
+ }
+
+ exchange_state->state = libssh2_NB_state_sent2;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_sent2) {
+ rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
+ &exchange_state->tmp,
+ &exchange_state->tmp_len, 0, NULL, 0,
+ &exchange_state->req_state);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
+ goto clean_exit;
+ }
+
+ /* The first key exchange has been performed, switch to active
+ crypt/comp/mac mode */
+
+ session->state |= LIBSSH2_STATE_NEWKEYS;
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message");
+
+ /* This will actually end up being just packet_type(1) for this packet
+ type anyway */
+ LIBSSH2_FREE(session, exchange_state->tmp);
+
+ if(!session->session_id) {
+
+ size_t digest_length = SHA256_DIGEST_LENGTH;
+ session->session_id = LIBSSH2_ALLOC(session, digest_length);
+ if(!session->session_id) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allxcocate buffer for "
+ "SHA digest");
+ goto clean_exit;
+ }
+ memcpy(session->session_id, exchange_state->h_sig_comp,
+ digest_length);
+ session->session_id_len = digest_length;
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "session_id calculated");
+ }
+
+ /* Cleanup any existing cipher */
+ if(session->local.crypt->dtor) {
+ session->local.crypt->dtor(session,
+ &session->local.crypt_abstract);
+ }
+
+ /* Calculate IV/Secret/Key for each direction */
+ if(session->local.crypt->init) {
+ unsigned char *iv = NULL, *secret = NULL;
+ int free_iv = 0, free_secret = 0;
+
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
+ session->local.crypt->
+ iv_len, "A");
+ if(!iv) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
+ session->local.crypt->
+ secret_len, "C");
+
+ if(!secret) {
+ LIBSSH2_FREE(session, iv);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ if(session->local.crypt->
+ init(session, session->local.crypt, iv, &free_iv, secret,
+ &free_secret, 1, &session->local.crypt_abstract)) {
+ LIBSSH2_FREE(session, iv);
+ LIBSSH2_FREE(session, secret);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
+ LIBSSH2_FREE(session, iv);
+ }
+
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->local.crypt->secret_len);
+ LIBSSH2_FREE(session, secret);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Client to Server IV and Key calculated");
+
+ if(session->remote.crypt->dtor) {
+ /* Cleanup any existing cipher */
+ session->remote.crypt->dtor(session,
+ &session->remote.crypt_abstract);
+ }
+
+ if(session->remote.crypt->init) {
+ unsigned char *iv = NULL, *secret = NULL;
+ int free_iv = 0, free_secret = 0;
+
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
+ session->remote.crypt->
+ iv_len, "B");
+
+ if(!iv) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
+ session->remote.crypt->
+ secret_len, "D");
+
+ if(!secret) {
+ LIBSSH2_FREE(session, iv);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ if(session->remote.crypt->
+ init(session, session->remote.crypt, iv, &free_iv, secret,
+ &free_secret, 0, &session->remote.crypt_abstract)) {
+ LIBSSH2_FREE(session, iv);
+ LIBSSH2_FREE(session, secret);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
+ LIBSSH2_FREE(session, iv);
+ }
+
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->remote.crypt->secret_len);
+ LIBSSH2_FREE(session, secret);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server to Client IV and Key calculated");
+
+ if(session->local.mac->dtor) {
+ session->local.mac->dtor(session, &session->local.mac_abstract);
+ }
+
+ if(session->local.mac->init) {
+ unsigned char *key = NULL;
+ int free_key = 0;
+
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
+ session->local.mac->
+ key_len, "E");
+
+ if(!key) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ session->local.mac->init(session, key, &free_key,
+ &session->local.mac_abstract);
+
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->local.mac->key_len);
+ LIBSSH2_FREE(session, key);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Client to Server HMAC Key calculated");
+
+ if(session->remote.mac->dtor) {
+ session->remote.mac->dtor(session, &session->remote.mac_abstract);
+ }
+
+ if(session->remote.mac->init) {
+ unsigned char *key = NULL;
+ int free_key = 0;
+
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
+ session->remote.mac->
+ key_len, "F");
+
+ if(!key) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ session->remote.mac->init(session, key, &free_key,
+ &session->remote.mac_abstract);
+
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->remote.mac->key_len);
+ LIBSSH2_FREE(session, key);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server to Client HMAC Key calculated");
+
+ /* Initialize compression for each direction */
+
+ /* Cleanup any existing compression */
+ if(session->local.comp && session->local.comp->dtor) {
+ session->local.comp->dtor(session, 1,
+ &session->local.comp_abstract);
+ }
+
+ if(session->local.comp && session->local.comp->init) {
+ if(session->local.comp->init(session, 1,
+ &session->local.comp_abstract)) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Client to Server compression initialized");
+
+ if(session->remote.comp && session->remote.comp->dtor) {
+ session->remote.comp->dtor(session, 0,
+ &session->remote.comp_abstract);
+ }
+
+ if(session->remote.comp && session->remote.comp->init) {
+ if(session->remote.comp->init(session, 0,
+ &session->remote.comp_abstract)) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server to Client compression initialized");
+ }
+
+clean_exit:
+ _libssh2_bn_free(exchange_state->k);
+ exchange_state->k = NULL;
+
+ if(exchange_state->k_value) {
+ LIBSSH2_FREE(session, exchange_state->k_value);
+ exchange_state->k_value = NULL;
+ }
+
+ exchange_state->state = libssh2_NB_state_idle;
+
+ return ret;
+}
+
+/* kex_method_curve25519_key_exchange
+ *
+ * Elliptic Curve X25519 Key Exchange with SHA256 hash
+ *
+ */
+
+static int
+kex_method_curve25519_key_exchange
+(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
+{
+ int ret = 0;
+ int rc = 0;
+
+ if(key_state->state == libssh2_NB_state_idle) {
+
+ key_state->public_key_oct = NULL;
+ key_state->state = libssh2_NB_state_created;
+ }
+
+ if(key_state->state == libssh2_NB_state_created) {
+ unsigned char *s = NULL;
+
+ rc = strcmp(session->kex->name, "curve25519-sha256@libssh.org");
+ if(rc != 0)
+ rc = strcmp(session->kex->name, "curve25519-sha256");
+
+ if(rc != 0) {
+ ret = _libssh2_error(session, -1,
+ "Unknown KEX curve25519 curve type");
+ goto clean_exit;
+ }
+
+ rc = _libssh2_curve25519_new(session, NULL,
+ &key_state->curve25519_public_key,
+ &key_state->curve25519_private_key);
+
+ if(rc != 0) {
+ ret = _libssh2_error(session, rc,
+ "Unable to create private key");
+ goto clean_exit;
+ }
+
+ key_state->request[0] = SSH2_MSG_KEX_ECDH_INIT;
+ s = key_state->request + 1;
+ _libssh2_store_str(&s, (const char *)key_state->curve25519_public_key,
+ LIBSSH2_ED25519_KEY_LEN);
+ key_state->request_len = LIBSSH2_ED25519_KEY_LEN + 5;
+
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Initiating curve25519 SHA2");
+
+ key_state->state = libssh2_NB_state_sent;
+ }
+
+ if(key_state->state == libssh2_NB_state_sent) {
+ rc = _libssh2_transport_send(session, key_state->request,
+ key_state->request_len, NULL, 0);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Unable to send ECDH_INIT");
+ goto clean_exit;
+ }
+
+ key_state->state = libssh2_NB_state_sent1;
+ }
+
+ if(key_state->state == libssh2_NB_state_sent1) {
+ rc = _libssh2_packet_require(session, SSH2_MSG_KEX_ECDH_REPLY,
+ &key_state->data, &key_state->data_len,
+ 0, NULL, 0, &key_state->req_state);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Timeout waiting for ECDH_REPLY reply");
+ goto clean_exit;
+ }
+
+ key_state->state = libssh2_NB_state_sent2;
+ }
+
+ if(key_state->state == libssh2_NB_state_sent2) {
+
+ ret = curve25519_sha256(session, key_state->data, key_state->data_len,
+ key_state->curve25519_public_key,
+ key_state->curve25519_private_key,
+ &key_state->exchange_state);
+
+ if(ret == LIBSSH2_ERROR_EAGAIN) {
+ return ret;
+ }
+
+ LIBSSH2_FREE(session, key_state->data);
+ }
+
+clean_exit:
+
+ if(key_state->curve25519_public_key) {
+ _libssh2_explicit_zero(key_state->curve25519_public_key,
+ LIBSSH2_ED25519_KEY_LEN);
+ LIBSSH2_FREE(session, key_state->curve25519_public_key);
+ key_state->curve25519_public_key = NULL;
+ }
+
+ if(key_state->curve25519_private_key) {
+ _libssh2_explicit_zero(key_state->curve25519_private_key,
+ LIBSSH2_ED25519_KEY_LEN);
+ LIBSSH2_FREE(session, key_state->curve25519_private_key);
+ key_state->curve25519_private_key = NULL;
+ }
+
+ key_state->state = libssh2_NB_state_idle;
+
+ return ret;
+}
+
+
+#endif /*LIBSSH2_ED25519*/
+
+
#define LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY 0x0001
#define LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY 0x0002
@@ -1731,7 +3277,54 @@ kex_method_diffie_helman_group_exchange_sha256 = {
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
+#if LIBSSH2_ECDSA
+static const LIBSSH2_KEX_METHOD
+kex_method_ecdh_sha2_nistp256 = {
+ "ecdh-sha2-nistp256",
+ kex_method_ecdh_key_exchange,
+ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+
+static const LIBSSH2_KEX_METHOD
+kex_method_ecdh_sha2_nistp384 = {
+ "ecdh-sha2-nistp384",
+ kex_method_ecdh_key_exchange,
+ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+
+static const LIBSSH2_KEX_METHOD
+kex_method_ecdh_sha2_nistp521 = {
+ "ecdh-sha2-nistp521",
+ kex_method_ecdh_key_exchange,
+ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+#endif
+
+#if LIBSSH2_ED25519
+static const LIBSSH2_KEX_METHOD
+kex_method_ssh_curve25519_sha256_libssh = {
+ "curve25519-sha256@libssh.org",
+ kex_method_curve25519_key_exchange,
+ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+static const LIBSSH2_KEX_METHOD
+kex_method_ssh_curve25519_sha256 = {
+ "curve25519-sha256",
+ kex_method_curve25519_key_exchange,
+ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+#endif
+
static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = {
+#if LIBSSH2_ECDSA
+ &kex_method_ecdh_sha2_nistp256,
+ &kex_method_ecdh_sha2_nistp384,
+ &kex_method_ecdh_sha2_nistp521,
+#endif
+#if LIBSSH2_ED25519
+ &kex_method_ssh_curve25519_sha256,
+ &kex_method_ssh_curve25519_sha256_libssh,
+#endif
&kex_method_diffie_helman_group_exchange_sha256,
&kex_method_diffie_helman_group_exchange_sha1,
&kex_method_diffie_helman_group14_sha1,
@@ -1746,7 +3339,8 @@ typedef struct _LIBSSH2_COMMON_METHOD
/* kex_method_strlen
* Calculate the length of a particular method list's resulting string
- * Includes SUM(strlen() of each individual method plus 1 (for coma)) - 1 (because the last coma isn't used)
+ * Includes SUM(strlen() of each individual method plus 1 (for coma)) - 1
+ * (because the last coma isn't used)
* Another sign of bad coding practices gone mad. Pretend you don't see this.
*/
static size_t
@@ -1754,11 +3348,11 @@ kex_method_strlen(LIBSSH2_COMMON_METHOD ** method)
{
size_t len = 0;
- if (!method || !*method) {
+ if(!method || !*method) {
return 0;
}
- while (*method && (*method)->name) {
+ while(*method && (*method)->name) {
len += strlen((*method)->name) + 1;
method++;
}
@@ -1778,11 +3372,11 @@ kex_method_list(unsigned char *buf, size_t list_strlen,
_libssh2_htonu32(buf, list_strlen);
buf += 4;
- if (!method || !*method) {
+ if(!method || !*method) {
return 4;
}
- while (*method && (*method)->name) {
+ while(*method && (*method)->name) {
int mlen = strlen((*method)->name);
memcpy(buf, (*method)->name, mlen);
buf += mlen;
@@ -1800,12 +3394,13 @@ kex_method_list(unsigned char *buf, size_t list_strlen,
kex_method_strlen((LIBSSH2_COMMON_METHOD**)(defaultvar)))
#define LIBSSH2_METHOD_PREFS_STR(buf, prefvarlen, prefvar, defaultvar) \
- if (prefvar) { \
+ if(prefvar) { \
_libssh2_htonu32((buf), (prefvarlen)); \
buf += 4; \
memcpy((buf), (prefvar), (prefvarlen)); \
buf += (prefvarlen); \
- } else { \
+ } \
+ else { \
buf += kex_method_list((buf), (prefvarlen), \
(LIBSSH2_COMMON_METHOD**)(defaultvar)); \
}
@@ -1826,7 +3421,7 @@ static int kexinit(LIBSSH2_SESSION * session)
unsigned char *data, *s;
int rc;
- if (session->kexinit_state == libssh2_NB_state_idle) {
+ if(session->kexinit_state == libssh2_NB_state_idle) {
kex_len =
LIBSSH2_METHOD_PREFS_LEN(session->kex_prefs, libssh2_kex_methods);
hostkey_len =
@@ -1860,7 +3455,7 @@ static int kexinit(LIBSSH2_SESSION * session)
lang_cs_len + lang_sc_len;
s = data = LIBSSH2_ALLOC(session, data_len);
- if (!data) {
+ if(!data) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory");
}
@@ -1907,7 +3502,7 @@ static int kexinit(LIBSSH2_SESSION * session)
#ifdef LIBSSH2DEBUG
{
/* Funnily enough, they'll all "appear" to be '\0' terminated */
- unsigned char *p = data + 21; /* type(1) + cookie(16) + len(4) */
+ unsigned char *p = data + 21; /* type(1) + cookie(16) + len(4) */
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent KEX: %s", p);
p += kex_len + 4;
@@ -1933,7 +3528,8 @@ static int kexinit(LIBSSH2_SESSION * session)
#endif /* LIBSSH2DEBUG */
session->kexinit_state = libssh2_NB_state_created;
- } else {
+ }
+ else {
data = session->kexinit_data;
data_len = session->kexinit_data_len;
/* zap the variables to ensure there is NOT a double free later */
@@ -1942,12 +3538,12 @@ static int kexinit(LIBSSH2_SESSION * session)
}
rc = _libssh2_transport_send(session, data, data_len, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
session->kexinit_data = data;
session->kexinit_data_len = data_len;
return rc;
}
- else if (rc) {
+ else if(rc) {
LIBSSH2_FREE(session, data);
session->kexinit_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
@@ -1955,7 +3551,7 @@ static int kexinit(LIBSSH2_SESSION * session)
}
- if (session->local.kexinit) {
+ if(session->local.kexinit) {
LIBSSH2_FREE(session, session->local.kexinit);
}
@@ -1969,7 +3565,7 @@ static int kexinit(LIBSSH2_SESSION * session)
/* kex_agree_instr
* Kex specific variant of strstr()
- * Needle must be preceed by BOL or ',', and followed by ',' or EOL
+ * Needle must be precede by BOL or ',', and followed by ',' or EOL
*/
static unsigned char *
kex_agree_instr(unsigned char *haystack, unsigned long haystack_len,
@@ -1978,12 +3574,12 @@ kex_agree_instr(unsigned char *haystack, unsigned long haystack_len,
unsigned char *s;
/* Haystack too short to bother trying */
- if (haystack_len < needle_len) {
+ if(haystack_len < needle_len) {
return NULL;
}
/* Needle at start of haystack */
- if ((strncmp((char *) haystack, (char *) needle, needle_len) == 0) &&
+ if((strncmp((char *) haystack, (char *) needle, needle_len) == 0) &&
(needle_len == haystack_len || haystack[needle_len] == ',')) {
return haystack;
}
@@ -1991,11 +3587,11 @@ kex_agree_instr(unsigned char *haystack, unsigned long haystack_len,
s = haystack;
/* Search until we run out of comas or we run out of haystack,
whichever comes first */
- while ((s = (unsigned char *) strchr((char *) s, ','))
+ while((s = (unsigned char *) strchr((char *) s, ','))
&& ((haystack_len - (s - haystack)) > needle_len)) {
s++;
/* Needle at X position */
- if ((strncmp((char *) s, (char *) needle, needle_len) == 0) &&
+ if((strncmp((char *) s, (char *) needle, needle_len) == 0) &&
(((s - haystack) + needle_len) == haystack_len
|| s[needle_len] == ',')) {
return s;
@@ -2013,8 +3609,8 @@ static const LIBSSH2_COMMON_METHOD *
kex_get_method_by_name(const char *name, size_t name_len,
const LIBSSH2_COMMON_METHOD ** methodlist)
{
- while (*methodlist) {
- if ((strlen((*methodlist)->name) == name_len) &&
+ while(*methodlist) {
+ if((strlen((*methodlist)->name) == name_len) &&
(strncmp((*methodlist)->name, name, name_len) == 0)) {
return *methodlist;
}
@@ -2035,31 +3631,31 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session,
const LIBSSH2_HOSTKEY_METHOD **hostkeyp = libssh2_hostkey_methods();
unsigned char *s;
- if (session->hostkey_prefs) {
+ if(session->hostkey_prefs) {
s = (unsigned char *) session->hostkey_prefs;
- while (s && *s) {
+ while(s && *s) {
unsigned char *p = (unsigned char *) strchr((char *) s, ',');
size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
- if (kex_agree_instr(hostkey, hostkey_len, s, method_len)) {
+ if(kex_agree_instr(hostkey, hostkey_len, s, method_len)) {
const LIBSSH2_HOSTKEY_METHOD *method =
(const LIBSSH2_HOSTKEY_METHOD *)
kex_get_method_by_name((char *) s, method_len,
(const LIBSSH2_COMMON_METHOD **)
hostkeyp);
- if (!method) {
+ if(!method) {
/* Invalid method -- Should never be reached */
return -1;
}
/* So far so good, but does it suit our purposes? (Encrypting
vs Signing) */
- if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) ==
+ if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) ==
0) || (method->encrypt)) {
/* Either this hostkey can do encryption or this kex just
doesn't require it */
- if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY)
+ if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY)
== 0) || (method->sig_verify)) {
/* Either this hostkey can do signing or this kex just
doesn't require it */
@@ -2074,18 +3670,18 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session,
return -1;
}
- while (hostkeyp && (*hostkeyp) && (*hostkeyp)->name) {
+ while(hostkeyp && (*hostkeyp) && (*hostkeyp)->name) {
s = kex_agree_instr(hostkey, hostkey_len,
(unsigned char *) (*hostkeyp)->name,
strlen((*hostkeyp)->name));
- if (s) {
+ if(s) {
/* So far so good, but does it suit our purposes? (Encrypting vs
Signing) */
- if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) ||
+ if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) ||
((*hostkeyp)->encrypt)) {
/* Either this hostkey can do encryption or this kex just
doesn't require it */
- if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) ==
+ if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) ==
0) || ((*hostkeyp)->sig_verify)) {
/* Either this hostkey can do signing or this kex just
doesn't require it */
@@ -2112,19 +3708,20 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
const LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods;
unsigned char *s;
- if (session->kex_prefs) {
+ if(session->kex_prefs) {
s = (unsigned char *) session->kex_prefs;
- while (s && *s) {
+ while(s && *s) {
unsigned char *q, *p = (unsigned char *) strchr((char *) s, ',');
size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
- if ((q = kex_agree_instr(kex, kex_len, s, method_len))) {
+ q = kex_agree_instr(kex, kex_len, s, method_len);
+ if(q) {
const LIBSSH2_KEX_METHOD *method = (const LIBSSH2_KEX_METHOD *)
kex_get_method_by_name((char *) s, method_len,
(const LIBSSH2_COMMON_METHOD **)
kexp);
- if (!method) {
+ if(!method) {
/* Invalid method -- Should never be reached */
return -1;
}
@@ -2132,13 +3729,13 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
/* We've agreed on a key exchange method,
* Can we agree on a hostkey that works with this kex?
*/
- if (kex_agree_hostkey(session, method->flags, hostkey,
+ if(kex_agree_hostkey(session, method->flags, hostkey,
hostkey_len) == 0) {
session->kex = method;
- if (session->burn_optimistic_kexinit && (kex == q)) {
- /* Server sent an optimistic packet,
- * and client agrees with preference
- * cancel burning the first KEX_INIT packet that comes in */
+ if(session->burn_optimistic_kexinit && (kex == q)) {
+ /* Server sent an optimistic packet, and client agrees
+ * with preference cancel burning the first KEX_INIT
+ * packet that comes in */
session->burn_optimistic_kexinit = 0;
}
return 0;
@@ -2150,21 +3747,21 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
return -1;
}
- while (*kexp && (*kexp)->name) {
+ while(*kexp && (*kexp)->name) {
s = kex_agree_instr(kex, kex_len,
(unsigned char *) (*kexp)->name,
strlen((*kexp)->name));
- if (s) {
+ if(s) {
/* We've agreed on a key exchange method,
* Can we agree on a hostkey that works with this kex?
*/
- if (kex_agree_hostkey(session, (*kexp)->flags, hostkey,
+ if(kex_agree_hostkey(session, (*kexp)->flags, hostkey,
hostkey_len) == 0) {
session->kex = *kexp;
- if (session->burn_optimistic_kexinit && (kex == s)) {
- /* Server sent an optimistic packet,
- * and client agrees with preference
- * cancel burning the first KEX_INIT packet that comes in */
+ if(session->burn_optimistic_kexinit && (kex == s)) {
+ /* Server sent an optimistic packet, and client agrees
+ * with preference cancel burning the first KEX_INIT
+ * packet that comes in */
session->burn_optimistic_kexinit = 0;
}
return 0;
@@ -2190,21 +3787,21 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session,
(void) session;
- if (endpoint->crypt_prefs) {
+ if(endpoint->crypt_prefs) {
s = (unsigned char *) endpoint->crypt_prefs;
- while (s && *s) {
+ while(s && *s) {
unsigned char *p = (unsigned char *) strchr((char *) s, ',');
size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
- if (kex_agree_instr(crypt, crypt_len, s, method_len)) {
+ if(kex_agree_instr(crypt, crypt_len, s, method_len)) {
const LIBSSH2_CRYPT_METHOD *method =
(const LIBSSH2_CRYPT_METHOD *)
kex_get_method_by_name((char *) s, method_len,
(const LIBSSH2_COMMON_METHOD **)
cryptp);
- if (!method) {
+ if(!method) {
/* Invalid method -- Should never be reached */
return -1;
}
@@ -2218,11 +3815,11 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session,
return -1;
}
- while (*cryptp && (*cryptp)->name) {
+ while(*cryptp && (*cryptp)->name) {
s = kex_agree_instr(crypt, crypt_len,
(unsigned char *) (*cryptp)->name,
strlen((*cryptp)->name));
- if (s) {
+ if(s) {
endpoint->crypt = *cryptp;
return 0;
}
@@ -2245,20 +3842,20 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
unsigned char *s;
(void) session;
- if (endpoint->mac_prefs) {
+ if(endpoint->mac_prefs) {
s = (unsigned char *) endpoint->mac_prefs;
- while (s && *s) {
+ while(s && *s) {
unsigned char *p = (unsigned char *) strchr((char *) s, ',');
size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
- if (kex_agree_instr(mac, mac_len, s, method_len)) {
+ if(kex_agree_instr(mac, mac_len, s, method_len)) {
const LIBSSH2_MAC_METHOD *method = (const LIBSSH2_MAC_METHOD *)
kex_get_method_by_name((char *) s, method_len,
(const LIBSSH2_COMMON_METHOD **)
macp);
- if (!method) {
+ if(!method) {
/* Invalid method -- Should never be reached */
return -1;
}
@@ -2272,10 +3869,10 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
return -1;
}
- while (*macp && (*macp)->name) {
+ while(*macp && (*macp)->name) {
s = kex_agree_instr(mac, mac_len, (unsigned char *) (*macp)->name,
strlen((*macp)->name));
- if (s) {
+ if(s) {
endpoint->mac = *macp;
return 0;
}
@@ -2298,21 +3895,21 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
unsigned char *s;
(void) session;
- if (endpoint->comp_prefs) {
+ if(endpoint->comp_prefs) {
s = (unsigned char *) endpoint->comp_prefs;
- while (s && *s) {
+ while(s && *s) {
unsigned char *p = (unsigned char *) strchr((char *) s, ',');
size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
- if (kex_agree_instr(comp, comp_len, s, method_len)) {
+ if(kex_agree_instr(comp, comp_len, s, method_len)) {
const LIBSSH2_COMP_METHOD *method =
(const LIBSSH2_COMP_METHOD *)
kex_get_method_by_name((char *) s, method_len,
(const LIBSSH2_COMMON_METHOD **)
compp);
- if (!method) {
+ if(!method) {
/* Invalid method -- Should never be reached */
return -1;
}
@@ -2326,10 +3923,10 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
return -1;
}
- while (*compp && (*compp)->name) {
+ while(*compp && (*compp)->name) {
s = kex_agree_instr(comp, comp_len, (unsigned char *) (*compp)->name,
strlen((*compp)->name));
- if (s) {
+ if(s) {
endpoint->comp = *compp;
return 0;
}
@@ -2360,7 +3957,7 @@ static int kex_string_pair(unsigned char **sp, /* parsing position */
/* the length of the string must fit within the current pointer and the
end of the packet */
- if (*lenp > (data_len - (s - data) -4))
+ if(*lenp > (data_len - (s - data) -4))
return 1;
*strp = s + 4;
s += 4 + *lenp;
@@ -2411,30 +4008,31 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
session->burn_optimistic_kexinit = *(s++);
/* Next uint32 in packet is all zeros (reserved) */
- if (data_len < (unsigned) (s - data))
+ if(data_len < (unsigned) (s - data))
return -1; /* short packet */
- if (kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) {
+ if(kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) {
return -1;
}
- if (kex_agree_crypt(session, &session->local, crypt_cs, crypt_cs_len)
- || kex_agree_crypt(session, &session->remote, crypt_sc, crypt_sc_len)) {
+ if(kex_agree_crypt(session, &session->local, crypt_cs, crypt_cs_len)
+ || kex_agree_crypt(session, &session->remote, crypt_sc,
+ crypt_sc_len)) {
return -1;
}
- if (kex_agree_mac(session, &session->local, mac_cs, mac_cs_len) ||
+ if(kex_agree_mac(session, &session->local, mac_cs, mac_cs_len) ||
kex_agree_mac(session, &session->remote, mac_sc, mac_sc_len)) {
return -1;
}
- if (kex_agree_comp(session, &session->local, comp_cs, comp_cs_len) ||
+ if(kex_agree_comp(session, &session->local, comp_cs, comp_cs_len) ||
kex_agree_comp(session, &session->remote, comp_sc, comp_sc_len)) {
return -1;
}
#if 0
- if (libssh2_kex_agree_lang(session, &session->local, lang_cs, lang_cs_len)
+ if(libssh2_kex_agree_lang(session, &session->local, lang_cs, lang_cs_len)
|| libssh2_kex_agree_lang(session, &session->remote, lang_sc,
lang_sc_len)) {
return -1;
@@ -2478,14 +4076,14 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
session->state |= LIBSSH2_STATE_KEX_ACTIVE;
- if (key_state->state == libssh2_NB_state_idle) {
+ if(key_state->state == libssh2_NB_state_idle) {
/* Prevent loop in packet_add() */
session->state |= LIBSSH2_STATE_EXCHANGING_KEYS;
- if (reexchange) {
+ if(reexchange) {
session->kex = NULL;
- if (session->hostkey && session->hostkey->dtor) {
+ if(session->hostkey && session->hostkey->dtor) {
session->hostkey->dtor(session,
&session->server_hostkey_abstract);
}
@@ -2495,8 +4093,8 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
key_state->state = libssh2_NB_state_created;
}
- if (!session->kex || !session->hostkey) {
- if (key_state->state == libssh2_NB_state_created) {
+ if(!session->kex || !session->hostkey) {
+ if(key_state->state == libssh2_NB_state_created) {
/* Preserve in case of failure */
key_state->oldlocal = session->local.kexinit;
key_state->oldlocal_len = session->local.kexinit_len;
@@ -2506,12 +4104,13 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
key_state->state = libssh2_NB_state_sent;
}
- if (key_state->state == libssh2_NB_state_sent) {
+ if(key_state->state == libssh2_NB_state_sent) {
retcode = kexinit(session);
- if (retcode == LIBSSH2_ERROR_EAGAIN) {
+ if(retcode == LIBSSH2_ERROR_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return retcode;
- } else if (retcode) {
+ }
+ else if(retcode) {
session->local.kexinit = key_state->oldlocal;
session->local.kexinit_len = key_state->oldlocal_len;
key_state->state = libssh2_NB_state_idle;
@@ -2523,18 +4122,18 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
key_state->state = libssh2_NB_state_sent1;
}
- if (key_state->state == libssh2_NB_state_sent1) {
+ if(key_state->state == libssh2_NB_state_sent1) {
retcode =
_libssh2_packet_require(session, SSH_MSG_KEXINIT,
&key_state->data,
&key_state->data_len, 0, NULL, 0,
&key_state->req_state);
- if (retcode == LIBSSH2_ERROR_EAGAIN) {
+ if(retcode == LIBSSH2_ERROR_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return retcode;
}
- else if (retcode) {
- if (session->local.kexinit) {
+ else if(retcode) {
+ if(session->local.kexinit) {
LIBSSH2_FREE(session, session->local.kexinit);
}
session->local.kexinit = key_state->oldlocal;
@@ -2545,42 +4144,45 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
return -1;
}
- if (session->remote.kexinit) {
+ if(session->remote.kexinit) {
LIBSSH2_FREE(session, session->remote.kexinit);
}
session->remote.kexinit = key_state->data;
session->remote.kexinit_len = key_state->data_len;
- if (kex_agree_methods(session, key_state->data,
+ if(kex_agree_methods(session, key_state->data,
key_state->data_len))
rc = LIBSSH2_ERROR_KEX_FAILURE;
key_state->state = libssh2_NB_state_sent2;
}
- } else {
+ }
+ else {
key_state->state = libssh2_NB_state_sent2;
}
- if (rc == 0 && session->kex) {
- if (key_state->state == libssh2_NB_state_sent2) {
+ if(rc == 0 && session->kex) {
+ if(key_state->state == libssh2_NB_state_sent2) {
retcode = session->kex->exchange_keys(session,
&key_state->key_state_low);
- if (retcode == LIBSSH2_ERROR_EAGAIN) {
+ if(retcode == LIBSSH2_ERROR_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return retcode;
- } else if (retcode) {
- rc = _libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
+ }
+ else if(retcode) {
+ rc = _libssh2_error(session,
+ LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
"Unrecoverable error exchanging keys");
}
}
}
/* Done with kexinit buffers */
- if (session->local.kexinit) {
+ if(session->local.kexinit) {
LIBSSH2_FREE(session, session->local.kexinit);
session->local.kexinit = NULL;
}
- if (session->remote.kexinit) {
+ if(session->remote.kexinit) {
LIBSSH2_FREE(session, session->remote.kexinit);
session->remote.kexinit = NULL;
}
@@ -2606,7 +4208,7 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
int prefs_len = strlen(prefs);
const LIBSSH2_COMMON_METHOD **mlist;
- switch (method_type) {
+ switch(method_type) {
case LIBSSH2_METHOD_KEX:
prefvar = &session->kex_prefs;
mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods;
@@ -2665,40 +4267,43 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
}
s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1);
- if (!newprefs) {
+ if(!newprefs) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Error allocated space for method preferences");
}
memcpy(s, prefs, prefs_len + 1);
- while (s && *s && mlist) {
+ while(s && *s && mlist) {
char *p = strchr(s, ',');
int method_len = p ? (p - s) : (int) strlen(s);
- if (!kex_get_method_by_name(s, method_len, mlist)) {
+ if(!kex_get_method_by_name(s, method_len, mlist)) {
/* Strip out unsupported method */
- if (p) {
+ if(p) {
memcpy(s, p + 1, strlen(s) - method_len);
- } else {
- if (s > newprefs) {
+ }
+ else {
+ if(s > newprefs) {
*(--s) = '\0';
- } else {
+ }
+ else {
*s = '\0';
}
}
}
-
- s = p ? (p + 1) : NULL;
+ else {
+ s = p ? (p + 1) : NULL;
+ }
}
- if (strlen(newprefs) == 0) {
+ if(strlen(newprefs) == 0) {
LIBSSH2_FREE(session, newprefs);
return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"The requested method(s) are not currently "
"supported");
}
- if (*prefvar) {
+ if(*prefvar) {
LIBSSH2_FREE(session, *prefvar);
}
*prefvar = newprefs;
@@ -2714,7 +4319,7 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
int method_type,
- const char*** algs)
+ const char ***algs)
{
unsigned int i;
unsigned int j;
@@ -2722,11 +4327,11 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
const LIBSSH2_COMMON_METHOD **mlist;
/* to prevent coredumps due to dereferencing of NULL */
- if (NULL == algs)
+ if(NULL == algs)
return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
"algs must not be NULL");
- switch (method_type) {
+ switch(method_type) {
case LIBSSH2_METHOD_KEX:
mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods;
break;
@@ -2747,7 +4352,8 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
case LIBSSH2_METHOD_COMP_CS:
case LIBSSH2_METHOD_COMP_SC:
- mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_comp_methods(session);
+ mlist = (const LIBSSH2_COMMON_METHOD **)
+ _libssh2_comp_methods(session);
break;
default:
@@ -2756,7 +4362,7 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
} /* switch */
/* weird situation */
- if (NULL==mlist)
+ if(NULL == mlist)
return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
"No algorithm found");
@@ -2773,28 +4379,28 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
*/
/* count the number of supported algorithms */
- for ( i=0, ialg=0; NULL!=mlist[i]; i++) {
+ for(i = 0, ialg = 0; NULL != mlist[i]; i++) {
/* do not count fields with NULL name */
- if (mlist[i]->name)
+ if(mlist[i]->name)
ialg++;
}
/* weird situation, no algorithm found */
- if (0==ialg)
+ if(0 == ialg)
return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
"No algorithm found");
/* allocate buffer */
- *algs = (const char**) LIBSSH2_ALLOC(session, ialg*sizeof(const char*));
- if ( NULL==*algs ) {
+ *algs = (const char **) LIBSSH2_ALLOC(session, ialg*sizeof(const char *));
+ if(NULL == *algs) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Memory allocation failed");
}
/* Past this point *algs must be deallocated in case of an error!! */
/* copy non-NULL pointers only */
- for ( i=0, j=0; NULL!=mlist[i] && j<ialg; i++ ) {
- if ( NULL==mlist[i]->name ){
+ for(i = 0, j = 0; NULL != mlist[i] && j < ialg; i++) {
+ if(NULL == mlist[i]->name) {
/* maybe a weird situation but if it occurs, do not include NULL
pointers */
continue;
@@ -2805,7 +4411,7 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
}
/* correct number of pointers copied? (test the code above) */
- if ( j!=ialg ) {
+ if(j != ialg) {
/* deallocate buffer */
LIBSSH2_FREE(session, (void *)*algs);
*algs = NULL;