mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 15:30:49 +02:00
flaky ECH test: fix method for finding ECH extension
This commit is contained in:
+69
-71
@@ -16027,6 +16027,57 @@ static int test_wolfSSL_Tls13_ECH_long_SNI(void)
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
static int ech_seek_extensions(byte* buf, word16* innerExtLen)
|
||||
{
|
||||
word16 idx;
|
||||
byte sessionIdLen;
|
||||
word16 cipherSuitesLen;
|
||||
byte compressionLen;
|
||||
|
||||
idx = OPAQUE16_LEN + RAN_LEN;
|
||||
|
||||
sessionIdLen = buf[idx++];
|
||||
idx += sessionIdLen;
|
||||
|
||||
ato16(buf + idx, &cipherSuitesLen);
|
||||
idx += OPAQUE16_LEN + cipherSuitesLen;
|
||||
|
||||
compressionLen = buf[idx++];
|
||||
idx += compressionLen;
|
||||
|
||||
ato16(buf + idx, innerExtLen);
|
||||
idx += OPAQUE16_LEN;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static int ech_find_extension(byte* buf, word16* idx_p, word16 extType)
|
||||
{
|
||||
word16 idx;
|
||||
word16 innerExtIdx;
|
||||
word16 innerExtLen;
|
||||
|
||||
innerExtIdx = ech_seek_extensions(buf + *idx_p, &innerExtLen) + *idx_p;
|
||||
idx = innerExtIdx;
|
||||
|
||||
while (idx - innerExtIdx < innerExtLen) {
|
||||
word16 type;
|
||||
word16 len;
|
||||
|
||||
ato16(buf + idx, &type);
|
||||
if (type == extType) {
|
||||
*idx_p = idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
idx += OPAQUE16_LEN;
|
||||
ato16(buf + idx, &len);
|
||||
idx += OPAQUE16_LEN + len;
|
||||
}
|
||||
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Test the HRR ECH rejection fallback path:
|
||||
* client offers ECH, HRR is triggered, server sends HRR without ECH extension,
|
||||
* client falls back to the outer transcript, then aborts with ech_required. */
|
||||
@@ -16130,7 +16181,7 @@ static int test_wolfSSL_Tls13_ECH_ch2_decrypt_error(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
test_ssl_memio_ctx test_ctx;
|
||||
int i;
|
||||
word16 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
|
||||
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
|
||||
@@ -16163,22 +16214,20 @@ static int test_wolfSSL_Tls13_ECH_ch2_decrypt_error(void)
|
||||
/* Corrupt one byte of the ECH ciphertext in the CH2 record in s_buff.
|
||||
* ECH outer extension layout after the 0xFE0D type marker:
|
||||
* extLen(2) + outerType(1) + kdfId(2) + aeadId(2) + configId(1)
|
||||
* + encLen(2, always 0 in CH2) + payloadLen(2) = 12 bytes, so the
|
||||
* ciphertext starts 14 bytes past the first 0xFE byte. */
|
||||
for (i = 0; i < test_ctx.s_len - 1; i++) {
|
||||
if (test_ctx.s_buff[i] == 0xFE && test_ctx.s_buff[i + 1] == 0x0D) {
|
||||
if (i + 14 < test_ctx.s_len)
|
||||
test_ctx.s_buff[i + 14] ^= 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
* + encLen(2) + payloadLen(2) = 12 bytes,
|
||||
* so the ciphertext starts 14 bytes past the first 0xFE byte. */
|
||||
ExpectIntEQ(ech_find_extension(test_ctx.s_buff, &idx, TLSXT_ECH), 0);
|
||||
if (EXPECT_SUCCESS() && (idx + 14 < test_ctx.s_len))
|
||||
test_ctx.s_buff[idx + 14] ^= 0xFF;
|
||||
|
||||
/* Server processes the corrupted CH2.
|
||||
* hpkeContext is preserved, TLSX_ECH_Parse correctly identifies the CH2
|
||||
* round and sends decrypt_error. */
|
||||
(void)wolfSSL_accept(test_ctx.s_ssl);
|
||||
ExpectIntEQ(wolfSSL_get_error(test_ctx.s_ssl, 0),
|
||||
WC_NO_ERR_TRACE(DECRYPT_ERROR));
|
||||
if (EXPECT_SUCCESS()) {
|
||||
(void)wolfSSL_accept(test_ctx.s_ssl);
|
||||
ExpectIntEQ(wolfSSL_get_error(test_ctx.s_ssl, 0),
|
||||
WC_NO_ERR_TRACE(DECRYPT_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
test_ssl_memio_cleanup(&test_ctx);
|
||||
@@ -16388,65 +16437,14 @@ static int test_wolfSSL_Tls13_ECH_enable_disable(void)
|
||||
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) && \
|
||||
defined(WOLFSSL_TEST_ECH) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
!defined(WOLFSSL_NO_TLS12)
|
||||
static int ech_tamper_seek_extension(byte* innerCh, word16* innerExtLen)
|
||||
{
|
||||
word16 idx;
|
||||
byte sessionIdLen;
|
||||
word16 cipherSuitesLen;
|
||||
byte compressionLen;
|
||||
|
||||
idx = OPAQUE16_LEN + RAN_LEN;
|
||||
|
||||
sessionIdLen = innerCh[idx++];
|
||||
idx += sessionIdLen;
|
||||
|
||||
ato16(innerCh + idx, &cipherSuitesLen);
|
||||
idx += OPAQUE16_LEN + cipherSuitesLen;
|
||||
|
||||
compressionLen = innerCh[idx++];
|
||||
idx += compressionLen;
|
||||
|
||||
ato16(innerCh + idx, innerExtLen);
|
||||
idx += OPAQUE16_LEN;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static int ech_tamper_find_extension(byte* innerCh, word16* idx_p,
|
||||
word16 extType)
|
||||
{
|
||||
word16 idx;
|
||||
word16 innerExtIdx;
|
||||
word16 innerExtLen;
|
||||
|
||||
idx = innerExtIdx = ech_tamper_seek_extension(innerCh, &innerExtLen);
|
||||
|
||||
while (idx - innerExtIdx < innerExtLen) {
|
||||
word16 type;
|
||||
word16 len;
|
||||
|
||||
ato16(innerCh + idx, &type);
|
||||
if (type == extType) {
|
||||
*idx_p = idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
idx += OPAQUE16_LEN;
|
||||
ato16(innerCh + idx, &len);
|
||||
idx += OPAQUE16_LEN + len;
|
||||
}
|
||||
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
static int ech_tamper_downgrade(byte* innerCh, word32 innerChLen)
|
||||
{
|
||||
int ret;
|
||||
word16 idx;
|
||||
word16 idx = 0;
|
||||
|
||||
(void)innerChLen;
|
||||
|
||||
ret = ech_tamper_find_extension(innerCh, &idx, TLSXT_SUPPORTED_VERSIONS);
|
||||
ret = ech_find_extension(innerCh, &idx, TLSXT_SUPPORTED_VERSIONS);
|
||||
if (ret == 0) {
|
||||
/* change extension type to something unknown */
|
||||
innerCh[idx] = 0xFA;
|
||||
@@ -16464,7 +16462,7 @@ static int ech_tamper_padding(byte* innerCh, word32 innerChLen)
|
||||
word16 innerExtLen;
|
||||
|
||||
/* get the unpadded length */
|
||||
idx = ech_tamper_seek_extension(innerCh, &innerExtLen);
|
||||
idx = ech_seek_extensions(innerCh, &innerExtLen);
|
||||
idx += innerExtLen;
|
||||
|
||||
/* no padding, but the test would fail if the message is not incorrect...
|
||||
@@ -16481,11 +16479,11 @@ static int ech_tamper_padding(byte* innerCh, word32 innerChLen)
|
||||
static int ech_tamper_type(byte* innerCh, word32 innerChLen)
|
||||
{
|
||||
int ret;
|
||||
word16 idx;
|
||||
word16 idx = 0;
|
||||
|
||||
(void)innerChLen;
|
||||
|
||||
ret = ech_tamper_find_extension(innerCh, &idx, TLSXT_ECH);
|
||||
ret = ech_find_extension(innerCh, &idx, TLSXT_ECH);
|
||||
if (ret == 0) {
|
||||
/* change type to outer */
|
||||
innerCh[idx + 4] = ECH_TYPE_OUTER;
|
||||
@@ -16499,12 +16497,12 @@ static int ech_tamper_type(byte* innerCh, word32 innerChLen)
|
||||
static int ech_tamper_key_share(byte* innerCh, word32 innerChLen)
|
||||
{
|
||||
int ret;
|
||||
word16 idx;
|
||||
word16 idx = 0;
|
||||
word16 len;
|
||||
|
||||
(void)innerChLen;
|
||||
|
||||
ret = ech_tamper_find_extension(innerCh, &idx, TLSXT_KEY_SHARE);
|
||||
ret = ech_find_extension(innerCh, &idx, TLSXT_KEY_SHARE);
|
||||
if (ret == 0) {
|
||||
ato16(innerCh + idx + 8, &len);
|
||||
if (len == 0) {
|
||||
|
||||
Reference in New Issue
Block a user