if (maxprot == TLS1_3_VERSION) {
/*
* In TLSv1.3 we should have created a new session even though we have
- * resumed.
+ * resumed. Since we attempted a resume we should also have removed the
+ * old ticket from the cache so that we try to only use tickets once.
*/
if (use_ext_cache
&& (!TEST_int_eq(new_called, 1)
- || !TEST_int_eq(remove_called, 0)))
+ || !TEST_int_eq(remove_called, 1)))
goto end;
} else {
/*
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
+ * confopt == 0: Configure anti-replay directly
+ * confopt == 1: Configure anti-replay using SSL_CONF
+ */
+static int test_early_data_replay_int(int idx, int usecb, int confopt)
{
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) {
+ if (confopt == 0) {
+ SSL_CTX_set_options(sctx, SSL_OP_NO_ANTI_REPLAY);
+ } else {
+ SSL_CONF_CTX *confctx = SSL_CONF_CTX_new();
+
+ if (!TEST_ptr(confctx))
+ goto end;
+ SSL_CONF_CTX_set_flags(confctx, SSL_CONF_FLAG_FILE
+ | SSL_CONF_FLAG_SERVER);
+ SSL_CONF_CTX_set_ssl_ctx(confctx, sctx);
+ if (!TEST_int_eq(SSL_CONF_cmd(confctx, "Options", "-AntiReplay"),
+ 2)) {
+ SSL_CONF_CTX_free(confctx);
+ goto end;
+ }
+ SSL_CONF_CTX_free(confctx);
+ }
+ 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 = 1, usecb, confopt;
+
+ for (usecb = 0; usecb < 3; usecb++) {
+ for (confopt = 0; confopt < 2; confopt++)
+ ret &= test_early_data_replay_int(idx, usecb, confopt);
+ }
+
+ 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.
size_t written, readbytes;
#ifdef OPENSSL_NO_TLS1_2
- if (tst == 0)
+ if (tst <= 1)
return 1;
#endif
#ifdef OPENSSL_NO_TLS1_3
- if (tst != 0)
+ if (tst >= 2)
return 1;
#endif
}
/* Writing on the client after sending close_notify shouldn't be possible */
- if (!TEST_false(SSL_write_ex(clientssl, msg, sizeof(msg), &written))
- /*
- * Writing on the server after sending close_notify shouldn't be
- * possible.
- */
- || !TEST_false(SSL_write_ex(clientssl, msg, sizeof(msg), &written)))
+ if (!TEST_false(SSL_write_ex(clientssl, msg, sizeof(msg), &written)))
goto end;
if (tst < 4) {
* yet.
*/
if (!TEST_int_eq(SSL_shutdown(serverssl), 0)
+ /*
+ * Writing on the server after sending close_notify shouldn't
+ * be possible.
+ */
+ || !TEST_false(SSL_write_ex(serverssl, msg, sizeof(msg), &written))
|| !TEST_int_eq(SSL_shutdown(clientssl), 1)
|| !TEST_int_eq(SSL_shutdown(serverssl), 1))
goto end;
- } else {
+ } else if (tst == 4) {
/*
* In this test the client has sent close_notify and it has been
* received by the server which has responded with a close_notify. The
- * client needs to read the close_notify sent by the server. When
- * tst == 5, there is application data to be read first but this is
- * discarded with a -1 return value.
+ * client needs to read the close_notify sent by the server.
*/
- if (tst == 5 && !TEST_int_eq(SSL_shutdown(clientssl), -1))
- goto end;
if (!TEST_int_eq(SSL_shutdown(clientssl), 1))
goto end;
+ } else {
+ /*
+ * tst == 5
+ *
+ * The client has sent close_notify and is expecting a close_notify
+ * back, but instead there is application data first. The shutdown
+ * should fail with a fatal error.
+ */
+ if (!TEST_int_eq(SSL_shutdown(clientssl), -1)
+ || !TEST_int_eq(SSL_get_error(clientssl, -1), SSL_ERROR_SSL))
+ goto end;
}
testresult = 1;