Sitelet https://web.archive.org/web/20220420061252im_/https://github.com/nodejs/node/commit/ec7ad1d0ec
Skip to content
Permalink
Browse files
deps: cherry-pick akamai/openssl/commit/bf4b08ecfbb7a26ca4b0b9ecaee3b…
…31d18d7bda9

Original Commit Message:

  Fix out-of-bounds read when TLS msg is split up into multiple chunks

  Previously, SSL_provide_quic_data tried to handle this kind of
  situation, but it failed when the length of input data is less than
  SSL3_HM_HEADER_LENGTH.  If that happens, the code might get wrong
  message length by reading value from out-of-bounds region.

PR-URL: #34033
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
  • Loading branch information
tatsuhiro-t authored and jasnell committed Jun 24, 2020
1 parent c3d85b7 commit ec7ad1d0ec0b28c3b3782c48489d23f2b44efcd7
Showing with 76 additions and 30 deletions.
  1. +2 −0 deps/openssl/openssl/ssl/ssl_local.h
  2. +74 −30 deps/openssl/openssl/ssl/ssl_quic.c
@@ -1410,6 +1410,8 @@ struct ssl_st {
OSSL_ENCRYPTION_LEVEL quic_write_level;
QUIC_DATA *quic_input_data_head;
QUIC_DATA *quic_input_data_tail;
uint8_t quic_msg_hd[SSL3_HM_HEADER_LENGTH];
size_t quic_msg_hd_offset;
const SSL_QUIC_METHOD *quic_method;
#endif
/*
@@ -93,6 +93,7 @@ int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
{
size_t l;
uint8_t mt;
QUIC_DATA *qd;

if (!SSL_IS_QUIC(ssl)) {
SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
@@ -106,35 +107,65 @@ int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
return 0;
}

/* Split on handshake message boundaries, if necessary */
while (len > 0) {
QUIC_DATA *qd;
const uint8_t *p;
if (len == 0) {
return 1;
}

/* Check for an incomplete block */
qd = ssl->quic_input_data_tail;
if (qd != NULL) {
l = qd->length - qd->offset;
if (l != 0) {
/* we still need to copy `l` bytes into the last data block */
if (l > len)
l = len;
memcpy((char*)(qd+1) + qd->offset, data, l);
qd->offset += l;
len -= l;
data += l;
continue;
}
/* Check for an incomplete block */
qd = ssl->quic_input_data_tail;
if (qd != NULL) {
l = qd->length - qd->offset;
if (l != 0) {
/* we still need to copy `l` bytes into the last data block */
if (l > len)
l = len;
memcpy((char *)(qd + 1) + qd->offset, data, l);
qd->offset += l;
len -= l;
data += l;
}
}

if (len < SSL3_HM_HEADER_LENGTH) {
SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, SSL_R_BAD_LENGTH);
return 0;
/* Split the QUIC messages up, if necessary */
while (len > 0) {
const uint8_t *p;
uint8_t *dst;

if (ssl->quic_msg_hd_offset != 0) {
/* If we have already buffered premature message header,
try to add new data to it to form complete message
header. */
size_t nread =
SSL3_HM_HEADER_LENGTH - ssl->quic_msg_hd_offset;

if (len < nread)
nread = len;
memcpy(ssl->quic_msg_hd + ssl->quic_msg_hd_offset, data, nread);
ssl->quic_msg_hd_offset += nread;

if (ssl->quic_msg_hd_offset < SSL3_HM_HEADER_LENGTH) {
/* We still have premature message header. */
break;
}
data += nread;
len -= nread;
/* TLS Handshake message header has 1-byte type and 3-byte length */
mt = *ssl->quic_msg_hd;
p = ssl->quic_msg_hd + 1;
n2l3(p, l);
} else if (len < SSL3_HM_HEADER_LENGTH) {
/* We don't get complete message header. Just buffer the
received data and wait for the next data to arrive. */
memcpy(ssl->quic_msg_hd, data, len);
ssl->quic_msg_hd_offset += len;
break;
} else {
/* We have complete message header in data. */
/* TLS Handshake message header has 1-byte type and 3-byte length */
mt = *data;
p = data + 1;
n2l3(p, l);
}
/* TLS Handshake message header has 1-byte type and 3-byte length */
mt = *data;
p = data + 1;
n2l3(p, l);
l += SSL3_HM_HEADER_LENGTH;
if (mt == SSL3_MT_KEY_UPDATE) {
SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, SSL_R_UNEXPECTED_MESSAGE);
@@ -150,12 +181,23 @@ int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
qd->next = NULL;
qd->length = l;
qd->level = level;
/* partial data received? */
if (l > len)
l = len;
qd->offset = l;

memcpy((void*)(qd + 1), data, l);
dst = (uint8_t *)(qd + 1);
if (ssl->quic_msg_hd_offset) {
memcpy(dst, ssl->quic_msg_hd, ssl->quic_msg_hd_offset);
dst += ssl->quic_msg_hd_offset;
l -= SSL3_HM_HEADER_LENGTH;
if (l > len)
l = len;
qd->offset = SSL3_HM_HEADER_LENGTH + l;
memcpy(dst, data, l);
} else {
/* partial data received? */
if (l > len)
l = len;
qd->offset = l;
memcpy(dst, data, l);
}
if (ssl->quic_input_data_tail != NULL)
ssl->quic_input_data_tail->next = qd;
else
@@ -164,6 +206,8 @@ int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,

data += l;
len -= l;

ssl->quic_msg_hd_offset = 0;
}

return 1;

0 comments on commit ec7ad1d

Please sign in to comment.