Skip to content

Commit 6c5097e

Browse files
committed
Enforce only 1 protocolname in serverhello
1 parent ac1c727 commit 6c5097e

4 files changed

Lines changed: 50 additions & 0 deletions

File tree

src/tls.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2026,6 +2026,7 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, const byte *input, word16 length,
20262026
word16 size = 0, offset = 0, wlen;
20272027
int r = WC_NO_ERR_TRACE(BUFFER_ERROR);
20282028
const byte *s;
2029+
word16 entryCount = 0;
20292030

20302031
if (OPAQUE16_LEN > length)
20312032
return BUFFER_ERROR;
@@ -2042,6 +2043,15 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, const byte *input, word16 length,
20422043
wlen = *s++;
20432044
if (wlen == 0 || (s + wlen - input) > length)
20442045
return BUFFER_ERROR;
2046+
entryCount++;
2047+
}
2048+
2049+
/* RFC 7301 Section 3.1: the server's ProtocolNameList in its ALPN
2050+
* response MUST contain exactly one ProtocolName. */
2051+
if (!isRequest && entryCount != 1) {
2052+
SendAlert(ssl, alert_fatal, decode_error);
2053+
WOLFSSL_ERROR_VERBOSE(BUFFER_ERROR);
2054+
return BUFFER_ERROR;
20452055
}
20462056

20472057
if (isRequest) {

tests/api.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40753,6 +40753,7 @@ TEST_CASE testCases[] = {
4075340753
TEST_DECL(test_TLSX_SNI_GetSize_overflow),
4075440754
TEST_DECL(test_TLSX_ECH_msg_type_validation),
4075540755
TEST_DECL(test_TLSX_SRTP_msg_type_validation),
40756+
TEST_DECL(test_TLSX_ALPN_server_response_count),
4075640757
TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation),
4075740758
TEST_DECL(test_wolfSSL_clear_secure_renegotiation),
4075840759
TEST_DECL(test_wolfSSL_SCR_Reconnect),

tests/api/test_tls_ext.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,3 +1033,41 @@ int test_TLSX_SRTP_msg_type_validation(void)
10331033
#endif
10341034
return EXPECT_RESULT();
10351035
}
1036+
1037+
/* RFC 7301 Section 3.1: the server's ProtocolNameList in its ALPN response
1038+
* MUST contain exactly one ProtocolName. A ServerHello carrying two entries
1039+
* must be rejected rather than silently accepted. */
1040+
int test_TLSX_ALPN_server_response_count(void)
1041+
{
1042+
EXPECT_DECLS;
1043+
#if defined(HAVE_ALPN) && !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS) && \
1044+
!defined(WOLFSSL_NO_TLS12)
1045+
WOLFSSL_CTX* ctx = NULL;
1046+
WOLFSSL* ssl = NULL;
1047+
/* ServerHello-style ALPN extension whose ProtocolNameList contains
1048+
* two entries ("h2" and "http/1.1"). */
1049+
static const byte extBytes[] = {
1050+
0x00, 0x10, /* extension type = ALPN (16) */
1051+
0x00, 0x0E, /* extension length = 14 */
1052+
0x00, 0x0C, /* ProtocolNameList length */
1053+
0x02, 'h', '2', /* entry 1: "h2" */
1054+
0x08, 'h', 't', 't', 'p', '/', '1', '.', '1' /* entry 2 */
1055+
};
1056+
static char alpn_h2[] = "h2";
1057+
1058+
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()));
1059+
ExpectNotNull(ssl = wolfSSL_new(ctx));
1060+
1061+
ExpectIntEQ(wolfSSL_UseALPN(ssl, alpn_h2, (unsigned int)XSTRLEN(alpn_h2),
1062+
WOLFSSL_ALPN_FAILED_ON_MISMATCH),
1063+
WOLFSSL_SUCCESS);
1064+
1065+
ExpectIntEQ(TLSX_Parse(ssl, extBytes, (word16)sizeof(extBytes),
1066+
server_hello, NULL),
1067+
WC_NO_ERR_TRACE(BUFFER_ERROR));
1068+
1069+
wolfSSL_free(ssl);
1070+
wolfSSL_CTX_free(ctx);
1071+
#endif
1072+
return EXPECT_RESULT();
1073+
}

tests/api/test_tls_ext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,6 @@ int test_TLSX_TCA_Find(void);
3636
int test_TLSX_SNI_GetSize_overflow(void);
3737
int test_TLSX_ECH_msg_type_validation(void);
3838
int test_TLSX_SRTP_msg_type_validation(void);
39+
int test_TLSX_ALPN_server_response_count(void);
3940

4041
#endif /* TESTS_API_TEST_TLS_EMS_H */

0 commit comments

Comments
 (0)