summaryrefslogtreecommitdiff
path: root/libs/libssh2/src/kex.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libssh2/src/kex.c')
-rw-r--r--libs/libssh2/src/kex.c456
1 files changed, 321 insertions, 135 deletions
diff --git a/libs/libssh2/src/kex.c b/libs/libssh2/src/kex.c
index 8c65a0fee6..4ca9c34c74 100644
--- a/libs/libssh2/src/kex.c
+++ b/libs/libssh2/src/kex.c
@@ -228,6 +228,60 @@ static void _libssh2_sha_algo_value_hash(int sha_algo,
}
+static void
+diffie_hellman_state_cleanup(LIBSSH2_SESSION * session,
+ kmdhgGPshakex_state_t *exchange_state)
+{
+ libssh2_dh_dtor(&exchange_state->x);
+ _libssh2_bn_free(exchange_state->e);
+ exchange_state->e = NULL;
+ _libssh2_bn_free(exchange_state->f);
+ exchange_state->f = NULL;
+ _libssh2_bn_free(exchange_state->k);
+ exchange_state->k = NULL;
+ _libssh2_bn_ctx_free(exchange_state->ctx);
+ exchange_state->ctx = NULL;
+
+ if(exchange_state->e_packet) {
+ LIBSSH2_FREE(session, exchange_state->e_packet);
+ exchange_state->e_packet = NULL;
+ }
+
+ if(exchange_state->s_packet) {
+ LIBSSH2_FREE(session, exchange_state->s_packet);
+ exchange_state->s_packet = 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;
+}
+
+static void
+kex_diffie_hellman_cleanup(LIBSSH2_SESSION * session,
+ key_exchange_state_low_t * key_state) {
+ if(key_state->state != libssh2_NB_state_idle) {
+ _libssh2_bn_free(key_state->p);
+ key_state->p = NULL;
+ _libssh2_bn_free(key_state->g);
+ key_state->g = NULL;
+
+ if(key_state->data) {
+ LIBSSH2_FREE(session, key_state->data);
+ key_state->data = NULL;
+ }
+ key_state->state = libssh2_NB_state_idle;
+ }
+
+ if(key_state->exchange_state.state != libssh2_NB_state_idle) {
+ diffie_hellman_state_cleanup(session, &key_state->exchange_state);
+ }
+}
+
+
/*!
* @function diffie_hellman_sha_algo
* @abstract Diffie Hellman Key Exchange, Group Agnostic,
@@ -316,13 +370,21 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session,
_libssh2_htonu32(exchange_state->e_packet + 1,
(uint32_t)(exchange_state->e_packet_len - 5));
if(_libssh2_bn_bits(exchange_state->e) % 8) {
- _libssh2_bn_to_bin(exchange_state->e,
- exchange_state->e_packet + 5);
+ if(_libssh2_bn_to_bin(exchange_state->e,
+ exchange_state->e_packet + 5)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+ "Can't write exchange_state->e");
+ goto clean_exit;
+ }
}
else {
exchange_state->e_packet[5] = 0;
- _libssh2_bn_to_bin(exchange_state->e,
- exchange_state->e_packet + 6);
+ if(_libssh2_bn_to_bin(exchange_state->e,
+ exchange_state->e_packet + 6)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+ "Can't write exchange_state->e");
+ goto clean_exit;
+ }
}
_libssh2_debug((session, LIBSSH2_TRACE_KEX, "Sending KEX packet %u",
@@ -407,8 +469,11 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session,
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 = NULL;
+ session->server_hostkey_len = 0;
+ }
if(_libssh2_copy_string(session, &buf, &(session->server_hostkey),
&host_key_len)) {
@@ -522,8 +587,13 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session,
goto clean_exit;
}
- _libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len,
- exchange_state->f_value);
+ if(_libssh2_bn_from_bin(exchange_state->f,
+ exchange_state->f_value_len,
+ exchange_state->f_value)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Invalid DH-SHA f value");
+ goto clean_exit;
+ }
if(_libssh2_get_string(&buf, &(exchange_state->h_sig),
&(exchange_state->h_sig_len))) {
@@ -550,11 +620,21 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session,
_libssh2_htonu32(exchange_state->k_value,
(uint32_t)(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);
+ if(_libssh2_bn_to_bin(exchange_state->k,
+ exchange_state->k_value + 4)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+ "Can't write exchange_state->k");
+ goto clean_exit;
+ }
}
else {
exchange_state->k_value[4] = 0;
- _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
+ if(_libssh2_bn_to_bin(exchange_state->k,
+ exchange_state->k_value + 5)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+ "Can't write exchange_state->k");
+ goto clean_exit;
+ }
}
exchange_state->exchange_hash = (void *)&exchange_hash_ctx;
@@ -933,32 +1013,7 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session,
}
clean_exit:
- libssh2_dh_dtor(&exchange_state->x);
- _libssh2_bn_free(exchange_state->e);
- exchange_state->e = NULL;
- _libssh2_bn_free(exchange_state->f);
- exchange_state->f = NULL;
- _libssh2_bn_free(exchange_state->k);
- exchange_state->k = NULL;
- _libssh2_bn_ctx_free(exchange_state->ctx);
- exchange_state->ctx = NULL;
-
- if(exchange_state->e_packet) {
- LIBSSH2_FREE(session, exchange_state->e_packet);
- exchange_state->e_packet = NULL;
- }
-
- if(exchange_state->s_packet) {
- LIBSSH2_FREE(session, exchange_state->s_packet);
- exchange_state->s_packet = 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;
+ diffie_hellman_state_cleanup(session, exchange_state);
return ret;
}
@@ -1002,8 +1057,16 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session,
key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */
/* Initialize P and G */
- _libssh2_bn_set_word(key_state->g, 2);
- _libssh2_bn_from_bin(key_state->p, 128, p_value);
+ if(!key_state->g || _libssh2_bn_set_word(key_state->g, 2)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Failed to allocate key state g.");
+ goto clean_exit;
+ }
+ if(!key_state->p || _libssh2_bn_from_bin(key_state->p, 128, p_value)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Failed to allocate key state p.");
+ goto clean_exit;
+ }
_libssh2_debug((session, LIBSSH2_TRACE_KEX,
"Initiating Diffie-Hellman Group1 Key Exchange"));
@@ -1019,11 +1082,8 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session,
return ret;
}
- _libssh2_bn_free(key_state->p);
- key_state->p = NULL;
- _libssh2_bn_free(key_state->g);
- key_state->g = NULL;
- key_state->state = libssh2_NB_state_idle;
+clean_exit:
+ kex_diffie_hellman_cleanup(session, key_state);
return ret;
}
@@ -1095,8 +1155,17 @@ kex_method_diffie_hellman_group14_key_exchange(LIBSSH2_SESSION *session,
/* g == 2 */
/* Initialize P and G */
- _libssh2_bn_set_word(key_state->g, 2);
- _libssh2_bn_from_bin(key_state->p, 256, p_value);
+ if(!key_state->g || _libssh2_bn_set_word(key_state->g, 2)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Failed to allocate key state g.");
+ goto clean_exit;
+ }
+ else if(!key_state->p ||
+ _libssh2_bn_from_bin(key_state->p, 256, p_value)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Failed to allocate key state p.");
+ goto clean_exit;
+ }
_libssh2_debug((session, LIBSSH2_TRACE_KEX,
"Initiating Diffie-Hellman Group14 Key Exchange"));
@@ -1110,11 +1179,8 @@ kex_method_diffie_hellman_group14_key_exchange(LIBSSH2_SESSION *session,
return ret;
}
- key_state->state = libssh2_NB_state_idle;
- _libssh2_bn_free(key_state->p);
- key_state->p = NULL;
- _libssh2_bn_free(key_state->g);
- key_state->g = NULL;
+clean_exit:
+ kex_diffie_hellman_cleanup(session, key_state);
return ret;
}
@@ -1216,8 +1282,16 @@ kex_method_diffie_hellman_group16_sha512_key_exchange(LIBSSH2_SESSION *session,
/* g == 2 */
/* Initialize P and G */
- _libssh2_bn_set_word(key_state->g, 2);
- _libssh2_bn_from_bin(key_state->p, 512, p_value);
+ if(!key_state->g || _libssh2_bn_set_word(key_state->g, 2)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Failed to allocate key state g.");
+ goto clean_exit;
+ }
+ if(!key_state->p || _libssh2_bn_from_bin(key_state->p, 512, p_value)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Failed to allocate key state p.");
+ goto clean_exit;
+ }
_libssh2_debug((session, LIBSSH2_TRACE_KEX,
"Initiating Diffie-Hellman Group16 Key Exchange"));
@@ -1233,11 +1307,8 @@ kex_method_diffie_hellman_group16_sha512_key_exchange(LIBSSH2_SESSION *session,
return ret;
}
- key_state->state = libssh2_NB_state_idle;
- _libssh2_bn_free(key_state->p);
- key_state->p = NULL;
- _libssh2_bn_free(key_state->g);
- key_state->g = NULL;
+clean_exit:
+ kex_diffie_hellman_cleanup(session, key_state);
return ret;
}
@@ -1348,8 +1419,17 @@ kex_method_diffie_hellman_group18_sha512_key_exchange(LIBSSH2_SESSION *session,
/* g == 2 */
/* Initialize P and G */
- _libssh2_bn_set_word(key_state->g, 2);
- _libssh2_bn_from_bin(key_state->p, 1024, p_value);
+ if(!key_state->g || _libssh2_bn_set_word(key_state->g, 2)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Failed to allocate key state g.");
+ goto clean_exit;
+ }
+ else if(!key_state->p ||
+ _libssh2_bn_from_bin(key_state->p, 1024, p_value)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Failed to allocate key state p.");
+ goto clean_exit;
+ }
_libssh2_debug((session, LIBSSH2_TRACE_KEX,
"Initiating Diffie-Hellman Group18 Key Exchange"));
@@ -1365,11 +1445,8 @@ kex_method_diffie_hellman_group18_sha512_key_exchange(LIBSSH2_SESSION *session,
return ret;
}
- key_state->state = libssh2_NB_state_idle;
- _libssh2_bn_free(key_state->p);
- key_state->p = NULL;
- _libssh2_bn_free(key_state->g);
- key_state->g = NULL;
+clean_exit:
+ kex_diffie_hellman_cleanup(session, key_state);
return ret;
}
@@ -1462,8 +1539,17 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange(
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);
+ if(_libssh2_bn_from_bin(key_state->p, p_len, p)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Invalid DH-SHA1 p");
+ goto dh_gex_clean_exit;
+ }
+
+ if(_libssh2_bn_from_bin(key_state->g, g_len, g)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Invalid DH-SHA1 g");
+ goto dh_gex_clean_exit;
+ }
ret = diffie_hellman_sha_algo(session, key_state->g, key_state->p,
(int)p_len, 1,
@@ -1476,16 +1562,10 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange(
if(ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
-
- LIBSSH2_FREE(session, key_state->data);
}
dh_gex_clean_exit:
- key_state->state = libssh2_NB_state_idle;
- _libssh2_bn_free(key_state->g);
- key_state->g = NULL;
- _libssh2_bn_free(key_state->p);
- key_state->p = NULL;
+ kex_diffie_hellman_cleanup(session, key_state);
return ret;
}
@@ -1581,8 +1661,17 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange(
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);
+ if(_libssh2_bn_from_bin(key_state->p, p_len, p)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Invalid DH-SHA256 p");
+ goto dh_gex_clean_exit;
+ }
+
+ if(_libssh2_bn_from_bin(key_state->g, g_len, g)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Invalid DH-SHA256 g");
+ goto dh_gex_clean_exit;
+ }
ret = diffie_hellman_sha_algo(session, key_state->g, key_state->p,
(int)p_len, 256,
@@ -1595,16 +1684,10 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange(
if(ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
-
- LIBSSH2_FREE(session, key_state->data);
}
dh_gex_clean_exit:
- key_state->state = libssh2_NB_state_idle;
- _libssh2_bn_free(key_state->g);
- key_state->g = NULL;
- _libssh2_bn_free(key_state->p);
- key_state->p = NULL;
+ kex_diffie_hellman_cleanup(session, key_state);
return ret;
}
@@ -1755,6 +1838,49 @@ kex_session_ecdh_curve_type(const char *name, libssh2_curve_type *out_type)
}
+static void
+ecdh_exchange_state_cleanup(LIBSSH2_SESSION * session,
+ kmdhgGPshakex_state_t *exchange_state)
+{
+ _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;
+}
+
+
+static void
+kex_method_ecdh_cleanup
+(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
+{
+ 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;
+ }
+
+ if(key_state->data) {
+ LIBSSH2_FREE(session, key_state->data);
+ key_state->data = NULL;
+ }
+
+ key_state->state = libssh2_NB_state_idle;
+
+ if(key_state->exchange_state.state != libssh2_NB_state_idle) {
+ ecdh_exchange_state_cleanup(session, &key_state->exchange_state);
+ }
+}
+
+
/* ecdh_sha2_nistp
* Elliptic Curve Diffie Hellman Key Exchange
*/
@@ -1941,11 +2067,21 @@ static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type,
_libssh2_htonu32(exchange_state->k_value,
(uint32_t)(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);
+ if(_libssh2_bn_to_bin(exchange_state->k,
+ exchange_state->k_value + 4)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+ "Can't write exchange_state->k");
+ goto clean_exit;
+ }
}
else {
exchange_state->k_value[4] = 0;
- _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
+ if(_libssh2_bn_to_bin(exchange_state->k,
+ exchange_state->k_value + 5)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+ "Can't write exchange_state->e");
+ goto clean_exit;
+ }
}
/* verify hash */
@@ -2231,15 +2367,7 @@ static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type,
}
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;
+ ecdh_exchange_state_cleanup(session, exchange_state);
return ret;
}
@@ -2347,23 +2475,11 @@ kex_method_ecdh_key_exchange
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;
+ kex_method_ecdh_cleanup(session, key_state);
return ret;
}
@@ -2373,6 +2489,51 @@ ecdh_clean_exit:
#if LIBSSH2_ED25519
+static void
+curve25519_exchange_state_cleanup(LIBSSH2_SESSION * session,
+ kmdhgGPshakex_state_t *exchange_state)
+{
+ _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;
+}
+
+static void
+kex_method_curve25519_cleanup
+(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
+{
+ 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;
+ }
+
+ if(key_state->data) {
+ LIBSSH2_FREE(session, key_state->data);
+ key_state->data = NULL;
+ }
+
+ key_state->state = libssh2_NB_state_idle;
+
+ if(key_state->exchange_state.state != libssh2_NB_state_idle) {
+ curve25519_exchange_state_cleanup(session, &key_state->exchange_state);
+ }
+}
+
/* curve25519_sha256
* Elliptic Curve Key Exchange
*/
@@ -2579,11 +2740,21 @@ curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data,
_libssh2_htonu32(exchange_state->k_value,
(uint32_t)(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);
+ if(_libssh2_bn_to_bin(exchange_state->k,
+ exchange_state->k_value + 4)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+ "Can't write exchange_state->e");
+ goto clean_exit;
+ }
}
else {
exchange_state->k_value[4] = 0;
- _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
+ if(_libssh2_bn_to_bin(exchange_state->k,
+ exchange_state->k_value + 5)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+ "Can't write exchange_state->e");
+ goto clean_exit;
+ }
}
/*/ verify hash */
@@ -2845,15 +3016,7 @@ curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data,
}
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;
+ curve25519_exchange_state_cleanup(session, exchange_state);
return ret;
}
@@ -2952,27 +3115,11 @@ kex_method_curve25519_key_exchange
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;
+ kex_method_curve25519_cleanup(session, key_state);
return ret;
}
@@ -2987,30 +3134,35 @@ clean_exit:
static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group1_sha1 = {
"diffie-hellman-group1-sha1",
kex_method_diffie_hellman_group1_sha1_key_exchange,
+ kex_diffie_hellman_cleanup,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group14_sha1 = {
"diffie-hellman-group14-sha1",
kex_method_diffie_hellman_group14_sha1_key_exchange,
+ kex_diffie_hellman_cleanup,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group14_sha256 = {
"diffie-hellman-group14-sha256",
kex_method_diffie_hellman_group14_sha256_key_exchange,
+ kex_diffie_hellman_cleanup,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group16_sha512 = {
"diffie-hellman-group16-sha512",
kex_method_diffie_hellman_group16_sha512_key_exchange,
+ kex_diffie_hellman_cleanup,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group18_sha512 = {
"diffie-hellman-group18-sha512",
kex_method_diffie_hellman_group18_sha512_key_exchange,
+ kex_diffie_hellman_cleanup,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
@@ -3018,6 +3170,7 @@ static const LIBSSH2_KEX_METHOD
kex_method_diffie_helman_group_exchange_sha1 = {
"diffie-hellman-group-exchange-sha1",
kex_method_diffie_hellman_group_exchange_sha1_key_exchange,
+ kex_diffie_hellman_cleanup,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
@@ -3025,6 +3178,7 @@ static const LIBSSH2_KEX_METHOD
kex_method_diffie_helman_group_exchange_sha256 = {
"diffie-hellman-group-exchange-sha256",
kex_method_diffie_hellman_group_exchange_sha256_key_exchange,
+ kex_diffie_hellman_cleanup,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
@@ -3033,6 +3187,7 @@ static const LIBSSH2_KEX_METHOD
kex_method_ecdh_sha2_nistp256 = {
"ecdh-sha2-nistp256",
kex_method_ecdh_key_exchange,
+ kex_method_ecdh_cleanup,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
@@ -3040,6 +3195,7 @@ static const LIBSSH2_KEX_METHOD
kex_method_ecdh_sha2_nistp384 = {
"ecdh-sha2-nistp384",
kex_method_ecdh_key_exchange,
+ kex_method_ecdh_cleanup,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
@@ -3047,6 +3203,7 @@ static const LIBSSH2_KEX_METHOD
kex_method_ecdh_sha2_nistp521 = {
"ecdh-sha2-nistp521",
kex_method_ecdh_key_exchange,
+ kex_method_ecdh_cleanup,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
#endif
@@ -3056,12 +3213,14 @@ static const LIBSSH2_KEX_METHOD
kex_method_ssh_curve25519_sha256_libssh = {
"curve25519-sha256@libssh.org",
kex_method_curve25519_key_exchange,
+ kex_method_curve25519_cleanup,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
static const LIBSSH2_KEX_METHOD
kex_method_ssh_curve25519_sha256 = {
"curve25519-sha256",
kex_method_curve25519_key_exchange,
+ kex_method_curve25519_cleanup,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
#endif
@@ -3074,6 +3233,7 @@ static const LIBSSH2_KEX_METHOD
kex_method_extension_negotiation = {
"ext-info-c",
NULL,
+ NULL,
0,
};
@@ -3081,6 +3241,7 @@ static const LIBSSH2_KEX_METHOD
kex_method_strict_client_extension = {
"kex-strict-c-v00@openssh.com",
NULL,
+ NULL,
0,
};
@@ -3900,6 +4061,10 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
session->state |= LIBSSH2_STATE_EXCHANGING_KEYS;
if(reexchange) {
+ if(session->kex && session->kex->cleanup) {
+ session->kex->cleanup(session, &key_state->key_state_low);
+ }
+
session->kex = NULL;
if(session->hostkey && session->hostkey->dtor) {
@@ -3970,9 +4135,10 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
}
session->remote.kexinit = key_state->data;
session->remote.kexinit_len = key_state->data_len;
+ key_state->data = NULL;
- if(kex_agree_methods(session, key_state->data,
- key_state->data_len))
+ if(kex_agree_methods(session, session->remote.kexinit,
+ session->remote.kexinit_len))
rc = LIBSSH2_ERROR_KEX_FAILURE;
key_state->state = libssh2_NB_state_sent2;
@@ -4027,13 +4193,26 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
const char *prefs)
{
char **prefvar, *s, *newprefs;
+ char *tmpprefs = NULL;
size_t prefs_len = strlen(prefs);
const LIBSSH2_COMMON_METHOD **mlist;
+ const char *kex_extensions = "ext-info-c,kex-strict-c-v00@openssh.com,";
+ size_t kex_extensions_len = strlen(kex_extensions);
switch(method_type) {
case LIBSSH2_METHOD_KEX:
prefvar = &session->kex_prefs;
mlist = (const LIBSSH2_COMMON_METHOD **)libssh2_kex_methods;
+ tmpprefs = LIBSSH2_ALLOC(session, kex_extensions_len + prefs_len + 1);
+ if(!tmpprefs) {
+ return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Error allocated space for kex method"
+ " preferences");
+ }
+ memcpy(tmpprefs, kex_extensions, kex_extensions_len);
+ memcpy(tmpprefs + kex_extensions_len, prefs, prefs_len + 1);
+ prefs = tmpprefs;
+ prefs_len = strlen(prefs);
break;
case LIBSSH2_METHOD_HOSTKEY:
@@ -4093,6 +4272,9 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1);
if(!newprefs) {
+ if(tmpprefs) {
+ LIBSSH2_FREE(session, tmpprefs);
+ }
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Error allocated space for method preferences");
}
@@ -4121,6 +4303,10 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
}
}
+ if(tmpprefs) {
+ LIBSSH2_FREE(session, tmpprefs);
+ }
+
if(!*newprefs) {
LIBSSH2_FREE(session, newprefs);
return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,