Skip to content
Permalink
Browse files

kex.c : additional bounds checks in diffie_sha1/256

Added _libssh2_copy_string() to misc.c to return an allocated and filled char buffer from a string_buf offset. Removed no longer needed s var in kmdhgGPshakex_state_t.
  • Loading branch information...
willco007 committed Apr 23, 2019
1 parent 1cdbe63 commit a62a73ab448e65d08db734dcb8768f5d1548fcde
Showing with 76 additions and 58 deletions.
  1. +51 −57 src/kex.c
  2. +0 −1 src/libssh2_priv.h
  3. +23 −0 src/misc.c
  4. +2 −0 src/misc.h
108 src/kex.c
@@ -241,6 +241,9 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,

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,
@@ -261,31 +264,19 @@ 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;
}

if(session->server_hostkey)
LIBSSH2_FREE(session, session->server_hostkey);
buf.data = exchange_state->s_packet;
buf.len = exchange_state->s_packet_len;
buf.dataptr = buf.data;
buf.dataptr++; /* advance past type */

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
{
@@ -383,16 +374,22 @@ 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_dh_secret(&exchange_state->x, exchange_state->k,
@@ -932,6 +929,9 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,

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,
@@ -952,31 +952,19 @@ static int diffie_hellman_sha256(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;
}

if(session->server_hostkey)
LIBSSH2_FREE(session, session->server_hostkey);
buf.data = exchange_state->s_packet;
buf.len = exchange_state->s_packet_len;
buf.dataptr = buf.data;
buf.dataptr++; /* advance past type */

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
{
@@ -1073,16 +1061,22 @@ 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_dh_secret(&exchange_state->x, exchange_state->k,
@@ -261,7 +261,6 @@ typedef struct kmdhgGPshakex_state_t
_libssh2_bn *e;
_libssh2_bn *f;
_libssh2_bn *k;
unsigned char *s;
unsigned char *f_value;
unsigned char *k_value;
unsigned char *h_sig;
@@ -786,6 +786,29 @@ int _libssh2_get_string(struct string_buf *buf, unsigned char **outbuf,
return 0;
}

int _libssh2_copy_string(LIBSSH2_SESSION *session, struct string_buf *buf,
unsigned char **outbuf, size_t *outlen)
{
size_t str_len;
unsigned char *str;

if(_libssh2_get_string(buf, &str, &str_len)) {
return -1;
}

*outbuf = LIBSSH2_ALLOC(session, str_len);
if(*outbuf) {
memcpy(*outbuf, str, str_len);
}else {
return -1;
}

if(outlen)
*outlen = str_len;

return 0;
}

int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf,
size_t *outlen)
{
@@ -96,6 +96,8 @@ int _libssh2_get_u64(struct string_buf *buf, libssh2_uint64_t *out);
int _libssh2_match_string(struct string_buf *buf, const char *match);
int _libssh2_get_string(struct string_buf *buf, unsigned char **outbuf,
size_t *outlen);
int _libssh2_copy_string(LIBSSH2_SESSION* session, struct string_buf *buf,
unsigned char **outbuf, size_t *outlen);
int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf,
size_t *outlen);
int _libssh2_check_length(struct string_buf *buf, size_t requested_len);

0 comments on commit a62a73a

Please sign in to comment.
You can’t perform that action at this time.