Skip to content

Commit 8a94314

Browse files
committed
TLS 1.3, plaintext alert: ignore when expecting encrypted
In TLS 1.3, ignore valid unencrypted alerts that appear after encryption has started. Only ignore WOLFSSL_ALERT_COUNT_MAX-1 alerts.
1 parent 59f4fa5 commit 8a94314

File tree

3 files changed

+284
-37
lines changed

3 files changed

+284
-37
lines changed

src/internal.c

Lines changed: 60 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -21679,20 +21679,20 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type)
2167921679
byte code;
2168021680
word32 dataSz = (word32)ssl->curSize;
2168121681

21682-
#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
21683-
if (ssl->hsInfoOn)
21684-
AddPacketName(ssl, "Alert");
21685-
if (ssl->toInfoOn) {
21686-
/* add record header back on to info + alert bytes level/code */
21687-
int ret = AddPacketInfo(ssl, "Alert", alert, input + *inOutIdx,
21688-
ALERT_SIZE, READ_PROTO, RECORD_HEADER_SZ, ssl->heap);
21689-
if (ret != 0)
21690-
return ret;
21691-
#ifdef WOLFSSL_CALLBACKS
21692-
AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
21693-
#endif
21694-
}
21695-
#endif
21682+
#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
21683+
if (ssl->hsInfoOn)
21684+
AddPacketName(ssl, "Alert");
21685+
if (ssl->toInfoOn) {
21686+
/* add record header back on to info + alert bytes level/code */
21687+
int ret = AddPacketInfo(ssl, "Alert", alert, input + *inOutIdx,
21688+
ALERT_SIZE, READ_PROTO, RECORD_HEADER_SZ, ssl->heap);
21689+
if (ret != 0)
21690+
return ret;
21691+
#ifdef WOLFSSL_CALLBACKS
21692+
AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
21693+
#endif
21694+
}
21695+
#endif
2169621696

2169721697
if (IsEncryptionOn(ssl, 0))
2169821698
dataSz -= ssl->keys.padSz;
@@ -21707,11 +21707,18 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type)
2170721707

2170821708
level = input[(*inOutIdx)++];
2170921709
code = input[(*inOutIdx)++];
21710-
ssl->alert_history.last_rx.code = code;
21711-
ssl->alert_history.last_rx.level = level;
2171221710
*type = code;
21713-
if (level == alert_fatal) {
21714-
ssl->options.isClosed = 1; /* Don't send close_notify */
21711+
#ifdef WOLFSSL_TLS13_IGNORE_PT_ALERT_ON_ENC
21712+
/* Don't process alert when TLS 1.3 and encrypting but plaintext alert. */
21713+
if (!IsAtLeastTLSv1_3(ssl->version) || !IsEncryptionOn(ssl, 0) ||
21714+
ssl->keys.decryptedCur)
21715+
#endif
21716+
{
21717+
ssl->alert_history.last_rx.code = code;
21718+
ssl->alert_history.last_rx.level = level;
21719+
if (level == alert_fatal) {
21720+
ssl->options.isClosed = 1; /* Don't send close_notify */
21721+
}
2171521722
}
2171621723

2171721724
if (++ssl->options.alertCount >= WOLFSSL_ALERT_COUNT_MAX) {
@@ -21725,20 +21732,36 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type)
2172521732
}
2172621733

2172721734
LogAlert(*type);
21728-
if (*type == close_notify) {
21729-
ssl->options.closeNotify = 1;
21735+
if (IsAtLeastTLSv1_3(ssl->version) && IsEncryptionOn(ssl, 0) &&
21736+
!ssl->keys.decryptedCur)
21737+
{
21738+
#ifdef WOLFSSL_TLS13_IGNORE_PT_ALERT_ON_ENC
21739+
/* Ignore alert if TLS 1.3 and encrypting but was plaintext alert. */
21740+
*type = invalid_alert;
21741+
level = alert_none;
21742+
21743+
#else
21744+
/* Unexpected message when encryption is on and alert not encrypted. */
21745+
SendAlert(ssl, alert_fatal, unexpected_message);
21746+
WOLFSSL_ERROR_VERBOSE(PARSE_ERROR);
21747+
return PARSE_ERROR;
21748+
#endif
2173021749
}
21731-
else {
21732-
/*
21733-
* A close_notify alert doesn't mean there's been an error, so we only
21734-
* add other types of alerts to the error queue
21735-
*/
21736-
WOLFSSL_ERROR(*type);
21750+
else
21751+
{
21752+
if (*type == close_notify) {
21753+
ssl->options.closeNotify = 1;
21754+
}
21755+
else {
21756+
/*
21757+
* A close_notify alert doesn't mean there's been an error, so we
21758+
* only add other types of alerts to the error queue
21759+
*/
21760+
WOLFSSL_ERROR(*type);
21761+
}
2173721762
}
21738-
21739-
if (IsEncryptionOn(ssl, 0)) {
21763+
if (IsEncryptionOn(ssl, 0))
2174021764
*inOutIdx += ssl->keys.padSz;
21741-
}
2174221765

2174321766
return level;
2174421767
}
@@ -22489,7 +22512,8 @@ static int DoProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
2248922512
#ifdef WOLFSSL_TLS13
2249022513
if (IsAtLeastTLSv1_3(ssl->version) && IsEncryptionOn(ssl, 0) &&
2249122514
ssl->curRL.type != application_data &&
22492-
ssl->curRL.type != change_cipher_spec) {
22515+
ssl->curRL.type != change_cipher_spec &&
22516+
ssl->curRL.type != alert) {
2249322517
SendAlert(ssl, alert_fatal, unexpected_message);
2249422518
WOLFSSL_ERROR_VERBOSE(PARSE_ERROR);
2249522519
return PARSE_ERROR;
@@ -22597,9 +22621,9 @@ static int DoProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
2259722621
case decryptMessage:
2259822622

2259922623
if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 &&
22600-
(!IsAtLeastTLSv1_3(ssl->version) ||
22601-
ssl->curRL.type != change_cipher_spec))
22602-
{
22624+
(!IsAtLeastTLSv1_3(ssl->version) ||
22625+
(ssl->curRL.type != change_cipher_spec &&
22626+
ssl->curRL.type != alert))) {
2260322627
ret = DoDecrypt(ssl);
2260422628
#ifdef WOLFSSL_ASYNC_CRYPT
2260522629
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
@@ -22676,9 +22700,9 @@ static int DoProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
2267622700
case verifyMessage:
2267722701

2267822702
if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 &&
22679-
(!IsAtLeastTLSv1_3(ssl->version) ||
22680-
ssl->curRL.type != change_cipher_spec))
22681-
{
22703+
(!IsAtLeastTLSv1_3(ssl->version) ||
22704+
(ssl->curRL.type != change_cipher_spec &&
22705+
ssl->curRL.type != alert))) {
2268222706
if (!atomicUser
2268322707
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
2268422708
&& !ssl->options.startedETMRead

tests/api/test_tls13.c

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2318,3 +2318,224 @@ int test_tls13_hrr_different_cs(void)
23182318
#endif
23192319
return EXPECT_RESULT();
23202320
}
2321+
2322+
#if defined(WOLFSSL_TLS13) && !defined(NO_RSA) && defined(HAVE_ECC) && \
2323+
defined(HAVE_AESGCM) && !defined(NO_WOLFSSL_SERVER)
2324+
/* Called when writing. */
2325+
static int Tls13PTASend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
2326+
{
2327+
(void)ssl;
2328+
(void)buf;
2329+
(void)ctx;
2330+
2331+
return sz;
2332+
}
2333+
/* Called when reading. */
2334+
static int Tls13PTARecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
2335+
{
2336+
WOLFSSL_BUFFER_INFO* msg = (WOLFSSL_BUFFER_INFO*)ctx;
2337+
int len;
2338+
2339+
(void)ssl;
2340+
(void)sz;
2341+
2342+
if (msg->length == 0) {
2343+
/* Only do as many alerts as required to get to max alert count. */
2344+
msg->buffer[0]--;
2345+
if (msg->buffer[0] > 0) {
2346+
msg->buffer -= 7;
2347+
msg->length += 7;
2348+
}
2349+
else {
2350+
return -1;
2351+
}
2352+
}
2353+
2354+
len = (int)msg->length;
2355+
/* Pass back as much of message as will fit in buffer. */
2356+
if (len > sz)
2357+
len = sz;
2358+
XMEMCPY(buf, msg->buffer, len);
2359+
/* Move over returned data. */
2360+
msg->buffer += len;
2361+
msg->length -= len;
2362+
2363+
/* Amount actually copied. */
2364+
return len;
2365+
}
2366+
#endif
2367+
2368+
int test_tls13_plaintext_alert(void)
2369+
{
2370+
EXPECT_DECLS;
2371+
#if defined(WOLFSSL_TLS13) && !defined(NO_RSA) && defined(HAVE_ECC) && \
2372+
defined(HAVE_AESGCM) && !defined(NO_WOLFSSL_SERVER)
2373+
byte clientMsgs[] = {
2374+
/* Client Hello */
2375+
0x16, 0x03, 0x03, 0x01, 0x9b, 0x01, 0x00, 0x01,
2376+
0x97, 0x03, 0x03, 0xf4, 0x65, 0xbd, 0x22, 0xfe,
2377+
0x6e, 0xab, 0x66, 0xdd, 0xcf, 0xe9, 0x65, 0x55,
2378+
0xe8, 0xdf, 0xc3, 0x8e, 0x4b, 0x00, 0xbc, 0xf8,
2379+
0x23, 0x57, 0x1b, 0xa0, 0xc8, 0xa9, 0xe2, 0x8c,
2380+
0x91, 0x6e, 0xf9, 0x20, 0xf7, 0x5c, 0xc5, 0x5b,
2381+
0x75, 0x8c, 0x47, 0x0a, 0x0e, 0xc4, 0x1a, 0xda,
2382+
0xef, 0x75, 0xe5, 0x21, 0x00, 0x00, 0x00, 0x00,
2383+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2384+
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x13, 0x01,
2385+
0x13, 0x02, 0x01, 0x00, 0x01, 0x4a, 0x00, 0x2d,
2386+
0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x33, 0x00,
2387+
0x47, 0x00, 0x45, 0x00, 0x17, 0x00, 0x41, 0x04,
2388+
0x90, 0xfc, 0xe2, 0x97, 0x05, 0x7c, 0xb5, 0x23,
2389+
0x5d, 0x5f, 0x5b, 0xcd, 0x0c, 0x1e, 0xe0, 0xe9,
2390+
0xab, 0x38, 0x6b, 0x1e, 0x20, 0x5c, 0x1c, 0x90,
2391+
0x2a, 0x9e, 0x68, 0x8e, 0x70, 0x05, 0x10, 0xa8,
2392+
0x02, 0x1b, 0xf9, 0x5c, 0xef, 0xc9, 0xaf, 0xca,
2393+
0x1a, 0x3b, 0x16, 0x8b, 0xe4, 0x1b, 0x3c, 0x15,
2394+
0xb8, 0x0d, 0xbd, 0xaf, 0x62, 0x8d, 0xa7, 0x13,
2395+
0xa0, 0x7c, 0xe0, 0x59, 0x0c, 0x4f, 0x8a, 0x6d,
2396+
0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04, 0x00,
2397+
0x0d, 0x00, 0x20, 0x00, 0x1e, 0x06, 0x03, 0x05,
2398+
0x03, 0x04, 0x03, 0x02, 0x03, 0x08, 0x06, 0x08,
2399+
0x0b, 0x08, 0x05, 0x08, 0x0a, 0x08, 0x04, 0x08,
2400+
0x09, 0x06, 0x01, 0x05, 0x01, 0x04, 0x01, 0x03,
2401+
0x01, 0x02, 0x01, 0x00, 0x0a, 0x00, 0x04, 0x00,
2402+
0x02, 0x00, 0x17, 0x00, 0x16, 0x00, 0x00, 0x00,
2403+
0x23, 0x00, 0x00, 0x00, 0x29, 0x00, 0xb9, 0x00,
2404+
0x94, 0x00, 0x8e, 0x0f, 0x12, 0xfa, 0x84, 0x1f,
2405+
0x76, 0x94, 0xd7, 0x09, 0x5e, 0xad, 0x08, 0x51,
2406+
0xb6, 0x80, 0x28, 0x31, 0x8b, 0xfd, 0xc6, 0xbd,
2407+
0x9e, 0xf5, 0x3b, 0x4d, 0x02, 0xbe, 0x1d, 0x73,
2408+
0xea, 0x13, 0x68, 0x00, 0x4c, 0xfd, 0x3d, 0x48,
2409+
0x51, 0xf9, 0x06, 0xbb, 0x92, 0xed, 0x42, 0x9f,
2410+
0x7f, 0x2c, 0x73, 0x9f, 0xd9, 0xb4, 0xef, 0x05,
2411+
0x26, 0x5b, 0x60, 0x5c, 0x0a, 0xfc, 0xa3, 0xbd,
2412+
0x2d, 0x2d, 0x8b, 0xf9, 0xaa, 0x5c, 0x96, 0x3a,
2413+
0xf2, 0xec, 0xfa, 0xe5, 0x57, 0x2e, 0x87, 0xbe,
2414+
0x27, 0xc5, 0x3d, 0x4f, 0x5d, 0xdd, 0xde, 0x1c,
2415+
0x1b, 0xb3, 0xcc, 0x27, 0x27, 0x57, 0x5a, 0xd9,
2416+
0xea, 0x99, 0x27, 0x23, 0xa6, 0x0e, 0xea, 0x9c,
2417+
0x0d, 0x85, 0xcb, 0x72, 0xeb, 0xd7, 0x93, 0xe3,
2418+
0xfe, 0xf7, 0x5c, 0xc5, 0x5b, 0x75, 0x8c, 0x47,
2419+
0x0a, 0x0e, 0xc4, 0x1a, 0xda, 0xef, 0x75, 0xe5,
2420+
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2421+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2422+
0x00, 0xfb, 0x92, 0xce, 0xaa, 0x00, 0x21, 0x20,
2423+
0xcb, 0x73, 0x25, 0x80, 0x46, 0x78, 0x4f, 0xe5,
2424+
0x34, 0xf6, 0x91, 0x13, 0x7f, 0xc8, 0x8d, 0xdc,
2425+
0x81, 0x04, 0xb7, 0x0d, 0x49, 0x85, 0x2e, 0x12,
2426+
0x7a, 0x07, 0x23, 0xe9, 0x13, 0xa4, 0x6d, 0x8c,
2427+
0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x00, 0x00
2428+
};
2429+
2430+
WOLFSSL_CTX* ctx = NULL;
2431+
WOLFSSL* ssl = NULL;
2432+
WOLFSSL_BUFFER_INFO msg;
2433+
2434+
#ifdef WOLFSSL_TLS13_IGNORE_PT_ALERT_ON_ENC
2435+
/* We fail on WOLFSSL_ALERT_COUNT_MAX alerts. */
2436+
2437+
/* Set up wolfSSL context. */
2438+
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
2439+
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
2440+
CERT_FILETYPE));
2441+
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile,
2442+
CERT_FILETYPE));
2443+
if (EXPECT_SUCCESS()) {
2444+
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL);
2445+
}
2446+
/* Read from 'msg'. */
2447+
wolfSSL_SetIORecv(ctx, Tls13PTARecv);
2448+
/* No where to send to - dummy sender. */
2449+
wolfSSL_SetIOSend(ctx, Tls13PTASend);
2450+
2451+
ExpectNotNull(ssl = wolfSSL_new(ctx));
2452+
msg.buffer = clientMsgs;
2453+
msg.length = (unsigned int)sizeof(clientMsgs) - 1;
2454+
clientMsgs[sizeof(clientMsgs) - 1] = WOLFSSL_ALERT_COUNT_MAX;
2455+
if (EXPECT_SUCCESS()) {
2456+
wolfSSL_SetIOReadCtx(ssl, &msg);
2457+
}
2458+
/* Alert will be ignored until too many. */
2459+
/* Read all message include CertificateVerify with invalid signature
2460+
* algorithm. */
2461+
ExpectIntEQ(wolfSSL_accept(ssl), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
2462+
/* Expect an invalid parameter error. */
2463+
ExpectIntEQ(wolfSSL_get_error(ssl, WOLFSSL_FATAL_ERROR),
2464+
WC_NO_ERR_TRACE(ALERT_COUNT_E));
2465+
2466+
wolfSSL_free(ssl);
2467+
ssl = NULL;
2468+
wolfSSL_CTX_free(ctx);
2469+
ctx = NULL;
2470+
2471+
/* Set up wolfSSL context. */
2472+
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
2473+
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
2474+
CERT_FILETYPE));
2475+
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile,
2476+
CERT_FILETYPE));
2477+
if (EXPECT_SUCCESS()) {
2478+
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL);
2479+
}
2480+
/* Read from 'msg'. */
2481+
wolfSSL_SetIORecv(ctx, Tls13PTARecv);
2482+
/* No where to send to - dummy sender. */
2483+
wolfSSL_SetIOSend(ctx, Tls13PTASend);
2484+
2485+
ExpectNotNull(ssl = wolfSSL_new(ctx));
2486+
msg.buffer = clientMsgs;
2487+
msg.length = (unsigned int)sizeof(clientMsgs) - 1;
2488+
clientMsgs[sizeof(clientMsgs) - 1] = WOLFSSL_ALERT_COUNT_MAX - 1;
2489+
if (EXPECT_SUCCESS()) {
2490+
wolfSSL_SetIOReadCtx(ssl, &msg);
2491+
}
2492+
/* Alert will be ignored until too many. */
2493+
/* Read all message include CertificateVerify with invalid signature
2494+
* algorithm. */
2495+
ExpectIntEQ(wolfSSL_accept(ssl), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
2496+
/* Expect an invalid parameter error. */
2497+
ExpectIntEQ(wolfSSL_get_error(ssl, WOLFSSL_FATAL_ERROR),
2498+
WC_NO_ERR_TRACE(SOCKET_ERROR_E));
2499+
2500+
wolfSSL_free(ssl);
2501+
wolfSSL_CTX_free(ctx);
2502+
#else
2503+
/* Fail on plaintext alert when encryption keys on. */
2504+
2505+
/* Set up wolfSSL context. */
2506+
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
2507+
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
2508+
CERT_FILETYPE));
2509+
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile,
2510+
CERT_FILETYPE));
2511+
if (EXPECT_SUCCESS()) {
2512+
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL);
2513+
}
2514+
/* Read from 'msg'. */
2515+
wolfSSL_SetIORecv(ctx, Tls13PTARecv);
2516+
/* No where to send to - dummy sender. */
2517+
wolfSSL_SetIOSend(ctx, Tls13PTASend);
2518+
2519+
ExpectNotNull(ssl = wolfSSL_new(ctx));
2520+
msg.buffer = clientMsgs;
2521+
msg.length = (unsigned int)sizeof(clientMsgs) - 1;
2522+
clientMsgs[sizeof(clientMsgs) - 1] = 1;
2523+
if (EXPECT_SUCCESS()) {
2524+
wolfSSL_SetIOReadCtx(ssl, &msg);
2525+
}
2526+
/* Alert will be ignored until too many. */
2527+
/* Read all message include CertificateVerify with invalid signature
2528+
* algorithm. */
2529+
ExpectIntEQ(wolfSSL_accept(ssl), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
2530+
/* Expect an invalid parameter error. */
2531+
ExpectIntEQ(wolfSSL_get_error(ssl, WOLFSSL_FATAL_ERROR),
2532+
WC_NO_ERR_TRACE(PARSE_ERROR));
2533+
2534+
wolfSSL_free(ssl);
2535+
wolfSSL_CTX_free(ctx);
2536+
#endif
2537+
#endif
2538+
2539+
return EXPECT_RESULT();
2540+
}
2541+

tests/api/test_tls13.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ int test_tls13_pq_groups(void);
3232
int test_tls13_early_data(void);
3333
int test_tls13_same_ch(void);
3434
int test_tls13_hrr_different_cs(void);
35+
int test_tls13_plaintext_alert(void);
3536

3637
#define TEST_TLS13_DECLS \
3738
TEST_DECL_GROUP("tls13", test_tls13_apis), \
@@ -41,6 +42,7 @@ int test_tls13_hrr_different_cs(void);
4142
TEST_DECL_GROUP("tls13", test_tls13_pq_groups), \
4243
TEST_DECL_GROUP("tls13", test_tls13_early_data), \
4344
TEST_DECL_GROUP("tls13", test_tls13_same_ch), \
44-
TEST_DECL_GROUP("tls13", test_tls13_hrr_different_cs)
45+
TEST_DECL_GROUP("tls13", test_tls13_hrr_different_cs), \
46+
TEST_DECL_GROUP("tls13", test_tls13_plaintext_alert)
4547

4648
#endif /* WOLFCRYPT_TEST_TLS13_H */

0 commit comments

Comments
 (0)