Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2020-05-24 07:46:58 +0300
committerJames M Snell <jasnell@gmail.com>2020-06-24 22:33:07 +0300
commitec7ad1d0ec0b28c3b3782c48489d23f2b44efcd7 (patch)
treea5ea2d258074378dfe300e633163658e417b985b /deps
parentc3d85b7637fdd87cfee52d50286ce9036a6f1bc2 (diff)
deps: cherry-pick akamai/openssl/commit/bf4b08ecfbb7a26ca4b0b9ecaee3b31d18d7bda9
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: https://github.com/nodejs/node/pull/34033 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
Diffstat (limited to 'deps')
-rw-r--r--deps/openssl/openssl/ssl/ssl_local.h2
-rw-r--r--deps/openssl/openssl/ssl/ssl_quic.c104
2 files changed, 76 insertions, 30 deletions
diff --git a/deps/openssl/openssl/ssl/ssl_local.h b/deps/openssl/openssl/ssl/ssl_local.h
index fa61ec838c1..6277fa02c8e 100644
--- a/deps/openssl/openssl/ssl/ssl_local.h
+++ b/deps/openssl/openssl/ssl/ssl_local.h
@@ -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
/*
diff --git a/deps/openssl/openssl/ssl/ssl_quic.c b/deps/openssl/openssl/ssl/ssl_quic.c
index 339414ded02..bcf4657e912 100644
--- a/deps/openssl/openssl/ssl/ssl_quic.c
+++ b/deps/openssl/openssl/ssl/ssl_quic.c
@@ -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;