Commit 5c56a7f5ef for openssl.org
commit 5c56a7f5ef993d3b0a4b8ee4ed31366949a542b6
Author: Andrew Dinh <andrewd@openssl.org>
Date: Mon Sep 7 23:47:41 2026 -0400
Port script_68
Assisted-by: Claude:claude-sonnet-5
Reviewed-by: Saša NedvÄ›dický <sashan@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
Merge-date: Mon Oct 5 10:18:47 2026
Merged-from: https://github.com/openssl/openssl/pull/32786
diff --git a/test/quic_multistream_test.c b/test/quic_multistream_test.c
index e9d59c4c17..154e8164ed 100644
--- a/test/quic_multistream_test.c
+++ b/test/quic_multistream_test.c
@@ -2568,22 +2568,7 @@ static int script_68_inject_handshake(struct helper *h, unsigned char *msg,
/* Send a CertificateRequest message post-handshake */
static const struct script_op script_68[] = {
- OP_S_SET_INJECT_HANDSHAKE(script_68_inject_handshake),
- OP_C_SET_ALPN("ossltest"),
- OP_C_CONNECT_WAIT(),
- OP_C_SET_DEFAULT_STREAM_MODE(SSL_DEFAULT_STREAM_MODE_NONE),
-
- OP_C_NEW_STREAM_BIDI(a, C_BIDI_ID(0)),
- OP_C_WRITE(a, "apple", 5),
- OP_S_BIND_STREAM_ID(a, C_BIDI_ID(0)),
- OP_S_READ_EXPECT(a, "apple", 5),
-
- OP_SET_INJECT_WORD(1, 0),
- OP_S_NEW_TICKET(),
- OP_S_WRITE(a, "orange", 6),
-
- OP_C_EXPECT_CONN_CLOSE_INFO(OSSL_QUIC_ERR_PROTOCOL_VIOLATION, 0, 0),
-
+ /* test moved to test/radix/quic_tests.c */
OP_END
};
diff --git a/test/radix/quic_ops.c b/test/radix/quic_ops.c
index b4bd59e9ec..f1e6147842 100644
--- a/test/radix/quic_ops.c
+++ b/test/radix/quic_ops.c
@@ -1375,7 +1375,7 @@ struct radix_fault_st {
uint64_t word0, word1;
/* Handshake message mutator state. */
unsigned char *handbuf;
- size_t handbuflen;
+ size_t handbuflen, handbufalloc;
radix_fault_handshake_cb hcb;
};
@@ -1495,6 +1495,73 @@ static int radix_fault_prepend_frame(RADIX_FAULT *fault,
return 1;
}
+#define RADIX_FAULT_GROWTH_ALLOWANCE 1024
+
+static int radix_fault_handshake_mutate(const unsigned char *msgin,
+ size_t msginlen,
+ unsigned char **msgout, size_t *msgoutlen,
+ void *arg)
+{
+ RADIX_FAULT *fault = arg;
+ unsigned char *buf;
+
+ buf = OPENSSL_malloc(msginlen + RADIX_FAULT_GROWTH_ALLOWANCE);
+ if (buf == NULL)
+ return 0;
+
+ OPENSSL_free(fault->handbuf);
+ fault->handbuf = buf;
+ fault->handbuflen = msginlen;
+ fault->handbufalloc = msginlen + RADIX_FAULT_GROWTH_ALLOWANCE;
+ memcpy(buf, msgin, msginlen);
+
+ if (fault->hcb != NULL && !fault->hcb(fault, buf, fault->handbuflen))
+ return 0;
+
+ *msgout = buf;
+ *msgoutlen = fault->handbuflen;
+
+ return 1;
+}
+
+static void radix_fault_handshake_finish(void *arg)
+{
+ RADIX_FAULT *fault = arg;
+
+ OPENSSL_free(fault->handbuf);
+ fault->handbuf = NULL;
+}
+
+static int radix_fault_resize_handshake(RADIX_FAULT *fault, size_t newlen)
+{
+ unsigned char *buf;
+ size_t oldlen = fault->handbuflen;
+
+ if (fault->handbufalloc == 0 || newlen > fault->handbufalloc)
+ return 0;
+
+ buf = fault->handbuf;
+
+ if (newlen > oldlen)
+ memset(buf + oldlen, 0, newlen - oldlen);
+
+ fault->handbuflen = newlen;
+
+ return 1;
+}
+
+static int radix_fault_resize_message(RADIX_FAULT *fault, size_t newlen)
+{
+ if (!radix_fault_resize_handshake(fault, newlen + SSL3_HM_HEADER_LENGTH))
+ return 0;
+
+ fault->handbuf[1] = (unsigned char)((newlen >> 16) & 0xff);
+ fault->handbuf[2] = (unsigned char)((newlen >> 8) & 0xff);
+ fault->handbuf[3] = (unsigned char)((newlen) & 0xff);
+
+ return 1;
+}
+
DEF_FUNC(hf_set_inject_plain)
{
int ok = 0;
@@ -1533,45 +1600,6 @@ err:
return ok;
}
-/*
- * ossl_statem_mutate_handshake_cb: intercepts an outgoing TLS handshake
- * message on the crypto stream before it is queued for transmission.
- */
-static int radix_fault_handshake_mutate(const unsigned char *msgin,
- size_t msginlen,
- unsigned char **msgout,
- size_t *msgoutlen,
- void *arg)
-{
- RADIX_FAULT *fault = arg;
- unsigned char *buf;
-
- buf = OPENSSL_malloc(msginlen);
- if (buf == NULL)
- return 0;
-
- OPENSSL_free(fault->handbuf);
- fault->handbuf = buf;
- fault->handbuflen = msginlen;
- memcpy(buf, msgin, msginlen);
-
- if (fault->hcb != NULL && !fault->hcb(fault, buf, fault->handbuflen))
- return 0;
-
- *msgout = buf;
- *msgoutlen = fault->handbuflen;
-
- return 1;
-}
-
-static void radix_fault_handshake_finish(void *arg)
-{
- RADIX_FAULT *fault = arg;
-
- OPENSSL_free(fault->handbuf);
- fault->handbuf = NULL;
-}
-
/*
* Arms the handshake mutator callback without attaching it to any
* connection yet. Used by scripts that need to intercept a server's very
@@ -1598,6 +1626,45 @@ err:
return ok;
}
+DEF_FUNC(hf_set_inject_handshake)
+{
+ int ok = 0;
+ SSL *ssl;
+ void *cbptr;
+
+ F_POP(cbptr);
+ REQUIRE_SSL(ssl);
+
+ OPENSSL_free(radix_fault.handbuf);
+ radix_fault.handbuf = NULL;
+ radix_fault.handbuflen = 0;
+ radix_fault.handbufalloc = 0;
+ radix_fault.hcb = radix_fault_ptr_to_handshake_cb(cbptr);
+
+ if (!TEST_true(ossl_statem_set_mutator(ssl, radix_fault_handshake_mutate,
+ radix_fault_handshake_finish, &radix_fault)))
+ goto err;
+
+ ok = 1;
+err:
+ return ok;
+}
+
+DEF_FUNC(hf_new_ticket)
+{
+ int ok = 0;
+ SSL *ssl;
+
+ REQUIRE_SSL(ssl);
+
+ if (!TEST_true(SSL_new_session_ticket(ssl)))
+ goto err;
+
+ ok = 1;
+err:
+ return ok;
+}
+
DEF_FUNC(hf_push_stream_id_plus_one)
{
int ok = 0;
@@ -1978,6 +2045,15 @@ err:
(OP_PUSH_P(radix_fault_handshake_cb_to_ptr(cb)), \
OP_FUNC(hf_set_inject_handshake_cb))
+#define OP_SET_INJECT_HANDSHAKE(name, cb) \
+ (OP_SELECT_SSL(0, name), \
+ OP_PUSH_P(radix_fault_handshake_cb_to_ptr(cb)), \
+ OP_FUNC(hf_set_inject_handshake))
+
+#define OP_NEW_TICKET(name) \
+ (OP_SELECT_SSL(0, name), \
+ OP_FUNC(hf_new_ticket))
+
#define OP_PUSH_STREAM_ID_PLUS_ONE(name) \
(OP_SELECT_SSL(0, name), \
OP_FUNC(hf_push_stream_id_plus_one))
diff --git a/test/radix/quic_tests.c b/test/radix/quic_tests.c
index a137a29851..7e9573346b 100644
--- a/test/radix/quic_tests.c
+++ b/test/radix/quic_tests.c
@@ -3841,8 +3841,76 @@ DEF_SCRIPT(script_67, "Fault injection - large MAX_DATA")
OP_READ_EXPECT(Sa, "Strawberry", 10);
}
-DEF_SCRIPT(script_68, "place holder for multistrem script_68")
+static int script_68_inject_handshake(RADIX_FAULT *fault, unsigned char *msg,
+ size_t msglen)
+{
+ const unsigned char *data;
+ size_t datalen;
+ const unsigned char certreq[] = {
+ SSL3_MT_CERTIFICATE_REQUEST, /* CertificateRequest message */
+ 0, 0, 12, /* Length of message */
+ 1, 1, /* certificate_request_context */
+ 0, 8, /* Extensions block length */
+ 0, TLSEXT_TYPE_signature_algorithms, /* sig_algs extension*/
+ 0, 4, /* 4 bytes of sig algs extension*/
+ 0, 2, /* sigalgs list is 2 bytes long */
+ 8, 4 /* rsa_pss_rsae_sha256 */
+ };
+ const unsigned char keyupdate[] = {
+ SSL3_MT_KEY_UPDATE, /* KeyUpdate message */
+ 0, 0, 1, /* Length of message */
+ SSL_KEY_UPDATE_NOT_REQUESTED /* update_not_requested */
+ };
+
+ /* We transform the NewSessionTicket message into something else */
+ switch (fault->word0) {
+ case 0:
+ return 1;
+
+ case 1:
+ /* CertificateRequest message */
+ data = certreq;
+ datalen = sizeof(certreq);
+ break;
+
+ case 2:
+ /* KeyUpdate message */
+ data = keyupdate;
+ datalen = sizeof(keyupdate);
+ break;
+
+ default:
+ return 0;
+ }
+
+ if (!TEST_true(radix_fault_resize_message(fault,
+ datalen - SSL3_HM_HEADER_LENGTH)))
+ return 0;
+
+ memcpy(msg, data, datalen);
+
+ return 1;
+}
+
+DEF_SCRIPT(script_68, "Send a CertificateRequest message post-handshake")
{
+ OP_SIMPLE_PAIR_CONN_ND();
+ OP_ACCEPT_CONN_WAIT_ND(L, S, 0);
+
+ OP_SET_INJECT_HANDSHAKE(S, script_68_inject_handshake);
+
+ OP_NEW_STREAM(C, Ca, 0);
+ OP_WRITE(Ca, "apple", 5);
+ OP_ACCEPT_STREAM_WAIT(S, Sa, 0);
+ OP_READ_EXPECT(Sa, "apple", 5);
+
+ OP_ENGINE_TICK_DISABLE(S);
+ OP_SET_INJECT_WORD(1, 0);
+ OP_NEW_TICKET(S);
+ OP_WRITE(Sa, "orange", 6);
+ OP_ENGINE_TICK_ENABLE(S);
+
+ OP_EXPECT_CONN_CLOSE_INFO(C, OSSL_QUIC_ERR_PROTOCOL_VIOLATION, 0, 0);
}
DEF_SCRIPT(script_69, "place holder for multistrem script_69")