Skip to content

Commit beca44b

Browse files
authored
Merge pull request #10795 from embhorn/gh10791
Fix to send record_overflow alert
2 parents 22b552c + 5d0678d commit beca44b

3 files changed

Lines changed: 109 additions & 3 deletions

File tree

src/internal.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23434,12 +23434,11 @@ static int DoProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
2343423434
SendAlert(ssl, alert_fatal,
2343523435
wolfssl_alert_protocol_version);
2343623436
break;
23437-
#ifdef HAVE_MAX_FRAGMENT
2343823437
case WC_NO_ERR_TRACE(LENGTH_ERROR):
23438+
/* invalid record length, RFC 8446 section 5.1 */
2343923439
SendAlert(ssl, alert_fatal, record_overflow);
2344023440
break;
23441-
#endif /* HAVE_MAX_FRAGMENT */
23442-
default:
23441+
default:
2344323442
break;
2344423443
}
2344523444
return ret;

tests/api/test_tls.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,111 @@ int test_tls13_unexpected_ccs(void)
192192
#endif
193193
return EXPECT_RESULT();
194194
}
195+
196+
/* A record whose length field exceeds the protocol limit must be answered
197+
* with a record_overflow alert (RFC 8446 section 5.1, RFC 5246 section 6.2.1).
198+
* Before the fix the alert was only sent when HAVE_MAX_FRAGMENT was defined,
199+
* so a default build dropped the connection with no alert on the wire. */
200+
int test_tls_record_overflow_alert(void)
201+
{
202+
EXPECT_DECLS;
203+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
204+
(!defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13))
205+
/* Record header only: handshake type, legacy version, length 0xFFFF.
206+
* 0xFFFF is past MAX_RECORD_SIZE + MAX_MSG_EXTRA, so GetRecordHeader()
207+
* returns LENGTH_ERROR before any body bytes are needed. The handshake
208+
* type keeps the server off the OLD_HELLO_ALLOWED SSLv2 detection path. */
209+
const byte oversized[] = {
210+
0x16, /* handshake type */
211+
0x03, 0x03, /* legacy record version */
212+
0xFF, 0xFF /* length 65535 */
213+
};
214+
/* Cleartext record_overflow alert the peer is expected to emit. */
215+
const byte overflowAlert[] = {
216+
0x15, /* alert record */
217+
0x03, 0x03, /* version */
218+
0x00, 0x02, /* length */
219+
0x02, /* level: fatal */
220+
0x16 /* description: record_overflow (22) */
221+
};
222+
WOLFSSL_CTX *ctx_s = NULL;
223+
WOLFSSL *ssl_s = NULL;
224+
struct test_memio_ctx test_ctx;
225+
#ifdef WOLFSSL_TLS13
226+
WOLFSSL_CTX *ctx_c = NULL;
227+
WOLFSSL *ssl_c = NULL;
228+
WOLFSSL_ALERT_HISTORY history;
229+
byte readBuf[64];
230+
#endif
231+
232+
/* Server side before negotiation: the alert is in the clear, so the exact
233+
* record can be matched on the wire. */
234+
#ifndef WOLFSSL_NO_TLS12
235+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
236+
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0,
237+
(const char*)oversized, sizeof(oversized)), 0);
238+
ExpectIntEQ(test_memio_setup(&test_ctx, NULL, &ctx_s, NULL, &ssl_s,
239+
NULL, wolfTLSv1_2_server_method), 0);
240+
ExpectIntEQ(wolfSSL_accept(ssl_s), WOLFSSL_FATAL_ERROR);
241+
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR), LENGTH_ERROR);
242+
ExpectIntEQ(test_ctx.c_len, sizeof(overflowAlert));
243+
ExpectBufEQ(test_ctx.c_buff, overflowAlert, sizeof(overflowAlert));
244+
wolfSSL_free(ssl_s);
245+
wolfSSL_CTX_free(ctx_s);
246+
ssl_s = NULL;
247+
ctx_s = NULL;
248+
#endif /* !WOLFSSL_NO_TLS12 */
249+
250+
#ifdef WOLFSSL_TLS13
251+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
252+
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0,
253+
(const char*)oversized, sizeof(oversized)), 0);
254+
ExpectIntEQ(test_memio_setup(&test_ctx, NULL, &ctx_s, NULL, &ssl_s,
255+
NULL, wolfTLSv1_3_server_method), 0);
256+
ExpectIntEQ(wolfSSL_accept(ssl_s), WOLFSSL_FATAL_ERROR);
257+
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR), LENGTH_ERROR);
258+
ExpectIntEQ(test_ctx.c_len, sizeof(overflowAlert));
259+
ExpectBufEQ(test_ctx.c_buff, overflowAlert, sizeof(overflowAlert));
260+
wolfSSL_free(ssl_s);
261+
wolfSSL_CTX_free(ctx_s);
262+
ssl_s = NULL;
263+
ctx_s = NULL;
264+
265+
/* Client side after a completed TLS 1.3 handshake: the reported scenario.
266+
* The alert is encrypted now, so it is decoded by letting the server read
267+
* it and inspecting its received-alert history. */
268+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
269+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
270+
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
271+
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
272+
273+
/* Drop any queued post-handshake traffic (session tickets) so only the
274+
* crafted record and the resulting alert remain in the buffers. */
275+
test_memio_clear_buffer(&test_ctx, 1);
276+
test_memio_clear_buffer(&test_ctx, 0);
277+
278+
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1,
279+
(const char*)oversized, sizeof(oversized)), 0);
280+
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)),
281+
WOLFSSL_FATAL_ERROR);
282+
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR), LENGTH_ERROR);
283+
284+
/* Server consumes the encrypted alert and records it. */
285+
ExpectIntLE(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), 0);
286+
XMEMSET(&history, 0, sizeof(history));
287+
ExpectIntEQ(wolfSSL_get_alert_history(ssl_s, &history), WOLFSSL_SUCCESS);
288+
ExpectIntEQ(history.last_rx.code, record_overflow);
289+
ExpectIntEQ(history.last_rx.level, alert_fatal);
290+
291+
wolfSSL_free(ssl_c);
292+
wolfSSL_free(ssl_s);
293+
wolfSSL_CTX_free(ctx_c);
294+
wolfSSL_CTX_free(ctx_s);
295+
#endif /* WOLFSSL_TLS13 */
296+
#endif /* HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES && (!NO_TLS12 || TLS13) */
297+
return EXPECT_RESULT();
298+
}
299+
195300
int test_tls12_curve_intersection(void) {
196301
EXPECT_DECLS;
197302
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \

tests/api/test_tls.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
int test_utils_memio_move_message(void);
2626
int test_tls12_unexpected_ccs(void);
2727
int test_tls13_unexpected_ccs(void);
28+
int test_tls_record_overflow_alert(void);
2829
int test_tls12_curve_intersection(void);
2930
int test_tls12_dhe_rsa_pss_sigalg(void);
3031
int test_tls13_curve_intersection(void);
@@ -58,6 +59,7 @@ int test_wolfSSL_get_shared_ciphers(void);
5859
TEST_DECL_GROUP("tls", test_utils_memio_move_message), \
5960
TEST_DECL_GROUP("tls", test_tls12_unexpected_ccs), \
6061
TEST_DECL_GROUP("tls", test_tls13_unexpected_ccs), \
62+
TEST_DECL_GROUP("tls", test_tls_record_overflow_alert), \
6163
TEST_DECL_GROUP("tls", test_tls12_curve_intersection), \
6264
TEST_DECL_GROUP("tls", test_tls12_dhe_rsa_pss_sigalg), \
6365
TEST_DECL_GROUP("tls", test_tls13_curve_intersection), \

0 commit comments

Comments
 (0)