static int setupearly_data_test(SSL_CTX **cctx, SSL_CTX **sctx, SSL **clientssl,
SSL **serverssl, SSL_SESSION **sess, int idx)
{
- if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(),
- TLS1_VERSION, TLS_MAX_VERSION,
- sctx, cctx, cert, privkey))
- || !TEST_true(SSL_CTX_set_max_early_data(*sctx,
- SSL3_RT_MAX_PLAIN_LENGTH)))
+ if (*sctx == NULL
+ && !TEST_true(create_ssl_ctx_pair(TLS_server_method(),
+ TLS_client_method(),
+ TLS1_VERSION, TLS_MAX_VERSION,
+ sctx, cctx, cert, privkey)))
+ return 0;
+
+ if (!TEST_true(SSL_CTX_set_max_early_data(*sctx, SSL3_RT_MAX_PLAIN_LENGTH)))
return 0;
if (idx == 1) {
return testresult;
}
-static int test_early_data_replay(int idx)
+static int allow_ed_cb_called = 0;
+
+static int allow_early_data_cb(SSL *s, void *arg)
+{
+ int *usecb = (int *)arg;
+
+ allow_ed_cb_called++;
+
+ if (*usecb == 1)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * idx == 0: Standard early_data setup
+ * idx == 1: early_data setup using read_ahead
+ * usecb == 0: Don't use a custom early data callback
+ * usecb == 1: Use a custom early data callback and reject the early data
+ * usecb == 2: Use a custom early data callback and accept the early data
+ */
+static int test_early_data_replay_int(int idx, int usecb)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;
+ size_t readbytes, written;
+ unsigned char buf[20];
+
+ allow_ed_cb_called = 0;
+
+ if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(),
+ TLS1_VERSION, TLS_MAX_VERSION, &sctx,
+ &cctx, cert, privkey)))
+ return 0;
+
+ if (usecb > 0) {
+ SSL_CTX_set_options(sctx, SSL_OP_NO_ANTI_REPLAY);
+ SSL_CTX_set_allow_early_data_cb(sctx, allow_early_data_cb, &usecb);
+ }
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, idx)))
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
- || !TEST_true(SSL_set_session(clientssl, sess))
- || !TEST_true(create_ssl_connection(serverssl, clientssl,
- SSL_ERROR_NONE))
- /*
- * This time we should not have resumed the session because we
- * already used it once.
- */
- || !TEST_false(SSL_session_reused(clientssl)))
+ || !TEST_true(SSL_set_session(clientssl, sess)))
+ goto end;
+
+ /* Write and read some early data */
+ if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
+ &written))
+ || !TEST_size_t_eq(written, strlen(MSG1)))
+ goto end;
+
+ if (usecb <= 1) {
+ if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
+ &readbytes),
+ SSL_READ_EARLY_DATA_FINISH)
+ /*
+ * The ticket was reused, so the we should have rejected the
+ * early data
+ */
+ || !TEST_int_eq(SSL_get_early_data_status(serverssl),
+ SSL_EARLY_DATA_REJECTED))
+ goto end;
+ } else {
+ /* In this case the callback decides to accept the early data */
+ if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
+ &readbytes),
+ SSL_READ_EARLY_DATA_SUCCESS)
+ || !TEST_mem_eq(MSG1, strlen(MSG1), buf, readbytes)
+ /*
+ * Server will have sent its flight so client can now send
+ * end of early data and complete its half of the handshake
+ */
+ || !TEST_int_gt(SSL_connect(clientssl), 0)
+ || !TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
+ &readbytes),
+ SSL_READ_EARLY_DATA_FINISH)
+ || !TEST_int_eq(SSL_get_early_data_status(serverssl),
+ SSL_EARLY_DATA_ACCEPTED))
+ goto end;
+ }
+
+ /* Complete the connection */
+ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))
+ || !TEST_int_eq(SSL_session_reused(clientssl), (usecb > 0) ? 1 : 0)
+ || !TEST_int_eq(allow_ed_cb_called, usecb > 0 ? 1 : 0))
goto end;
testresult = 1;
return testresult;
}
+static int test_early_data_replay(int idx)
+{
+ int ret;
+
+ ret = test_early_data_replay_int(idx, 0);
+ ret &= test_early_data_replay_int(idx, 1);
+ ret &= test_early_data_replay_int(idx, 2);
+
+ return ret;
+}
+
/*
* Helper function to test that a server attempting to read early data can
* handle a connection from a client where the early data should be skipped.