Skip to content

Commit ec7ad1d

Browse files
tatsuhiro-tjasnell
authored andcommitted
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: #34033 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
1 parent c3d85b7 commit ec7ad1d

File tree

2 files changed

+76
-30
lines changed

2 files changed

+76
-30
lines changed

deps/openssl/openssl/ssl/ssl_local.h

+2
Original file line numberDiff line numberDiff line change
@@ -1410,6 +1410,8 @@ struct ssl_st {
14101410
OSSL_ENCRYPTION_LEVEL quic_write_level;
14111411
QUIC_DATA *quic_input_data_head;
14121412
QUIC_DATA *quic_input_data_tail;
1413+
uint8_t quic_msg_hd[SSL3_HM_HEADER_LENGTH];
1414+
size_t quic_msg_hd_offset;
14131415
const SSL_QUIC_METHOD *quic_method;
14141416
#endif
14151417
/*

deps/openssl/openssl/ssl/ssl_quic.c

+74-30
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
9393
{
9494
size_t l;
9595
uint8_t mt;
96+
QUIC_DATA *qd;
9697

9798
if (!SSL_IS_QUIC(ssl)) {
9899
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,
106107
return 0;
107108
}
108109

109-
/* Split on handshake message boundaries, if necessary */
110-
while (len > 0) {
111-
QUIC_DATA *qd;
112-
const uint8_t *p;
110+
if (len == 0) {
111+
return 1;
112+
}
113113

114-
/* Check for an incomplete block */
115-
qd = ssl->quic_input_data_tail;
116-
if (qd != NULL) {
117-
l = qd->length - qd->offset;
118-
if (l != 0) {
119-
/* we still need to copy `l` bytes into the last data block */
120-
if (l > len)
121-
l = len;
122-
memcpy((char*)(qd+1) + qd->offset, data, l);
123-
qd->offset += l;
124-
len -= l;
125-
data += l;
126-
continue;
127-
}
114+
/* Check for an incomplete block */
115+
qd = ssl->quic_input_data_tail;
116+
if (qd != NULL) {
117+
l = qd->length - qd->offset;
118+
if (l != 0) {
119+
/* we still need to copy `l` bytes into the last data block */
120+
if (l > len)
121+
l = len;
122+
memcpy((char *)(qd + 1) + qd->offset, data, l);
123+
qd->offset += l;
124+
len -= l;
125+
data += l;
128126
}
127+
}
129128

130-
if (len < SSL3_HM_HEADER_LENGTH) {
131-
SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, SSL_R_BAD_LENGTH);
132-
return 0;
129+
/* Split the QUIC messages up, if necessary */
130+
while (len > 0) {
131+
const uint8_t *p;
132+
uint8_t *dst;
133+
134+
if (ssl->quic_msg_hd_offset != 0) {
135+
/* If we have already buffered premature message header,
136+
try to add new data to it to form complete message
137+
header. */
138+
size_t nread =
139+
SSL3_HM_HEADER_LENGTH - ssl->quic_msg_hd_offset;
140+
141+
if (len < nread)
142+
nread = len;
143+
memcpy(ssl->quic_msg_hd + ssl->quic_msg_hd_offset, data, nread);
144+
ssl->quic_msg_hd_offset += nread;
145+
146+
if (ssl->quic_msg_hd_offset < SSL3_HM_HEADER_LENGTH) {
147+
/* We still have premature message header. */
148+
break;
149+
}
150+
data += nread;
151+
len -= nread;
152+
/* TLS Handshake message header has 1-byte type and 3-byte length */
153+
mt = *ssl->quic_msg_hd;
154+
p = ssl->quic_msg_hd + 1;
155+
n2l3(p, l);
156+
} else if (len < SSL3_HM_HEADER_LENGTH) {
157+
/* We don't get complete message header. Just buffer the
158+
received data and wait for the next data to arrive. */
159+
memcpy(ssl->quic_msg_hd, data, len);
160+
ssl->quic_msg_hd_offset += len;
161+
break;
162+
} else {
163+
/* We have complete message header in data. */
164+
/* TLS Handshake message header has 1-byte type and 3-byte length */
165+
mt = *data;
166+
p = data + 1;
167+
n2l3(p, l);
133168
}
134-
/* TLS Handshake message header has 1-byte type and 3-byte length */
135-
mt = *data;
136-
p = data + 1;
137-
n2l3(p, l);
138169
l += SSL3_HM_HEADER_LENGTH;
139170
if (mt == SSL3_MT_KEY_UPDATE) {
140171
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,
150181
qd->next = NULL;
151182
qd->length = l;
152183
qd->level = level;
153-
/* partial data received? */
154-
if (l > len)
155-
l = len;
156-
qd->offset = l;
157184

158-
memcpy((void*)(qd + 1), data, l);
185+
dst = (uint8_t *)(qd + 1);
186+
if (ssl->quic_msg_hd_offset) {
187+
memcpy(dst, ssl->quic_msg_hd, ssl->quic_msg_hd_offset);
188+
dst += ssl->quic_msg_hd_offset;
189+
l -= SSL3_HM_HEADER_LENGTH;
190+
if (l > len)
191+
l = len;
192+
qd->offset = SSL3_HM_HEADER_LENGTH + l;
193+
memcpy(dst, data, l);
194+
} else {
195+
/* partial data received? */
196+
if (l > len)
197+
l = len;
198+
qd->offset = l;
199+
memcpy(dst, data, l);
200+
}
159201
if (ssl->quic_input_data_tail != NULL)
160202
ssl->quic_input_data_tail->next = qd;
161203
else
@@ -164,6 +206,8 @@ int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
164206

165207
data += l;
166208
len -= l;
209+
210+
ssl->quic_msg_hd_offset = 0;
167211
}
168212

169213
return 1;

0 commit comments

Comments
 (0)