Newer
Older
if (initrbio == USE_BIO_1
|| initwbio == USE_BIO_1
|| newrbio == USE_BIO_1
if (!TEST_ptr(bio1 = BIO_new(BIO_s_mem())))
if (initrbio == USE_BIO_2
|| initwbio == USE_BIO_2
|| newrbio == USE_BIO_2
if (!TEST_ptr(bio2 = BIO_new(BIO_s_mem())))
goto end;
}
setupbio(&irbio, bio1, bio2, initrbio);
setupbio(&iwbio, bio1, bio2, initwbio);
/*
* We want to maintain our own refs to these BIO, so do an up ref for each
* BIO that will have ownership transferred in the SSL_set_bio() call
*/
if (irbio != NULL)
BIO_up_ref(irbio);
if (iwbio != NULL && iwbio != irbio)
BIO_up_ref(iwbio);
SSL_set_bio(ssl, irbio, iwbio);
setupbio(&nrbio, bio1, bio2, newrbio);
setupbio(&nwbio, bio1, bio2, newwbio);
/*
* We will (maybe) transfer ownership again so do more up refs.
* SSL_set_bio() has some really complicated ownership rules where BIOs have
* already been set!
*/
if (nrbio != NULL
&& nrbio != irbio
&& (nwbio != iwbio || nrbio != nwbio))
if (nwbio != NULL
&& nwbio != nrbio
&& (nwbio != iwbio || (nwbio == iwbio && irbio == iwbio)))
BIO_up_ref(nwbio);
SSL_set_bio(ssl, nrbio, nwbio);
testresult = 1;
end:
SSL_free(ssl);
BIO_free(bio1);
BIO_free(bio2);
/*
* This test is checking that the ref counting for SSL_set_bio is correct.
* If we get here and we did too many frees then we will fail in the above
* functions. If we haven't done enough then this will only be detected in
* a crypto-mdebug build
*/
SSL_CTX_free(ctx);
return testresult;
}
typedef struct ssl_bio_test_fixture {
const char *test_case_name;
int pop_ssl;
enum { NO_BIO_CHANGE, CHANGE_RBIO, CHANGE_WBIO } change_bio;
} SSL_BIO_TEST_FIXTURE;
static SSL_BIO_TEST_FIXTURE ssl_bio_set_up(const char *const test_case_name)
{
SSL_BIO_TEST_FIXTURE fixture;
fixture.test_case_name = test_case_name;
fixture.pop_ssl = 0;
return fixture;
}
static void ssl_bio_tear_down(SSL_BIO_TEST_FIXTURE fixture)
{
}
static int execute_test_ssl_bio(SSL_BIO_TEST_FIXTURE fix)
{
BIO *sslbio = NULL, *membio1 = NULL, *membio2 = NULL;
if (!TEST_ptr(ctx = SSL_CTX_new(TLS_method()))
|| !TEST_ptr(ssl = SSL_new(ctx))
|| !TEST_ptr(sslbio = BIO_new(BIO_f_ssl()))
|| !TEST_ptr(membio1 = BIO_new(BIO_s_mem())))
goto end;
BIO_set_ssl(sslbio, ssl, BIO_CLOSE);
/*
* If anything goes wrong here then we could leak memory, so this will
* be caught in a crypto-mdebug build
*/
BIO_push(sslbio, membio1);
/* Verify changing the rbio/wbio directly does not cause leaks */
if (!TEST_ptr(membio2 = BIO_new(BIO_s_mem())))
goto end;
if (fix.change_bio == CHANGE_RBIO)
SSL_set0_rbio(ssl, membio2);
SSL_set0_wbio(ssl, membio2);
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
}
ssl = NULL;
if (fix.pop_ssl)
BIO_pop(sslbio);
else
BIO_pop(membio1);
testresult = 1;
end:
BIO_free(membio1);
BIO_free(sslbio);
SSL_free(ssl);
SSL_CTX_free(ctx);
return testresult;
}
static int test_ssl_bio_pop_next_bio(void)
{
SETUP_TEST_FIXTURE(SSL_BIO_TEST_FIXTURE, ssl_bio_set_up);
EXECUTE_TEST(execute_test_ssl_bio, ssl_bio_tear_down);
}
static int test_ssl_bio_pop_ssl_bio(void)
{
SETUP_TEST_FIXTURE(SSL_BIO_TEST_FIXTURE, ssl_bio_set_up);
fixture.pop_ssl = 1;
EXECUTE_TEST(execute_test_ssl_bio, ssl_bio_tear_down);
}
static int test_ssl_bio_change_rbio(void)
{
SETUP_TEST_FIXTURE(SSL_BIO_TEST_FIXTURE, ssl_bio_set_up);
fixture.change_bio = CHANGE_RBIO;
EXECUTE_TEST(execute_test_ssl_bio, ssl_bio_tear_down);
}
static int test_ssl_bio_change_wbio(void)
{
SETUP_TEST_FIXTURE(SSL_BIO_TEST_FIXTURE, ssl_bio_set_up);
fixture.change_bio = CHANGE_WBIO;
EXECUTE_TEST(execute_test_ssl_bio, ssl_bio_tear_down);
}
typedef struct {
/* The list of sig algs */
const int *list;
/* The length of the list */
size_t listlen;
/* A sigalgs list in string format */
const char *liststr;
/* Whether setting the list should succeed */
int valid;
/* Whether creating a connection with the list should succeed */
int connsuccess;
} sigalgs_list;
static const int validlist1[] = {NID_sha256, EVP_PKEY_RSA};
static const int validlist2[] = {NID_sha256, EVP_PKEY_RSA, NID_sha512, EVP_PKEY_EC};
static const int validlist3[] = {NID_sha512, EVP_PKEY_EC};
static const int invalidlist1[] = {NID_undef, EVP_PKEY_RSA};
static const int invalidlist2[] = {NID_sha256, NID_undef};
static const int invalidlist3[] = {NID_sha256, EVP_PKEY_RSA, NID_sha256};
static const int invalidlist4[] = {NID_sha256};
static const sigalgs_list testsigalgs[] = {
{validlist1, OSSL_NELEM(validlist1), NULL, 1, 1},
{validlist2, OSSL_NELEM(validlist2), NULL, 1, 1},
{validlist3, OSSL_NELEM(validlist3), NULL, 1, 0},
{NULL, 0, "RSA+SHA256:ECDSA+SHA512", 1, 1},
{NULL, 0, "ECDSA+SHA512", 1, 0},
{invalidlist1, OSSL_NELEM(invalidlist1), NULL, 0, 0},
{invalidlist2, OSSL_NELEM(invalidlist2), NULL, 0, 0},
{invalidlist3, OSSL_NELEM(invalidlist3), NULL, 0, 0},
{invalidlist4, OSSL_NELEM(invalidlist4), NULL, 0, 0},
{NULL, 0, "RSA", 0, 0},
{NULL, 0, "SHA256", 0, 0},
{NULL, 0, "RSA+SHA256:SHA256", 0, 0},
static int test_set_sigalgs(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
const sigalgs_list *curr;
int testctx;
/* Should never happen */
if (!TEST_size_t_le((size_t)idx, OSSL_NELEM(testsigalgs) * 2))
return 0;
testctx = ((size_t)idx < OSSL_NELEM(testsigalgs));
curr = testctx ? &testsigalgs[idx]
: &testsigalgs[idx - OSSL_NELEM(testsigalgs)];
if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
TLS_client_method(), &sctx,
&cctx, cert, privkey)))
/*
* TODO(TLS1.3): These APIs cannot set TLSv1.3 sig algs so we just test it
* for TLSv1.2 for now until we add a new API.
*/
SSL_CTX_set_max_proto_version(cctx, TLS1_2_VERSION);
if (curr->list != NULL)
ret = SSL_CTX_set1_sigalgs(cctx, curr->list, curr->listlen);
else
ret = SSL_CTX_set1_sigalgs_list(cctx, curr->liststr);
if (!ret) {
if (curr->valid)
TEST_info("Failure setting sigalgs in SSL_CTX (%d)\n", idx);
else
testresult = 1;
goto end;
}
if (!curr->valid) {
TEST_info("Not-failed setting sigalgs in SSL_CTX (%d)\n", idx);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
if (!testctx) {
int ret;
if (curr->list != NULL)
ret = SSL_set1_sigalgs(clientssl, curr->list, curr->listlen);
else
ret = SSL_set1_sigalgs_list(clientssl, curr->liststr);
if (!ret) {
if (curr->valid)
TEST_info("Failure setting sigalgs in SSL (%d)\n", idx);
else
testresult = 1;
goto end;
}
if (!TEST_int_eq(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE),
curr->connsuccess))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#ifndef OPENSSL_NO_TLS1_3
#define MSG1 "Hello"
#define MSG2 "World."
#define MSG3 "This"
#define MSG4 "is"
#define MSG5 "a"
#define MSG6 "test"
#define MSG7 "message."
/*
* Helper method to setup objects for early data test. Caller frees objects on
* error.
*/
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(), sctx,
cctx, cert, privkey)))
/* When idx == 1 we repeat the tests with read_ahead set */
if (idx > 0) {
SSL_CTX_set_read_ahead(*cctx, 1);
SSL_CTX_set_read_ahead(*sctx, 1);
}
if (!TEST_true(create_ssl_objects(*sctx, *cctx, serverssl, clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(*serverssl, *clientssl,
SSL_ERROR_NONE)))
return 0;
*sess = SSL_get1_session(*clientssl);
SSL_shutdown(*clientssl);
SSL_shutdown(*serverssl);
SSL_free(*serverssl);
SSL_free(*clientssl);
*serverssl = *clientssl = NULL;
if (!TEST_true(create_ssl_objects(*sctx, *cctx, serverssl,
clientssl, NULL, NULL))
|| !TEST_true(SSL_set_session(*clientssl, *sess)))
static int test_early_data_read_write(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;
unsigned char buf[20], data[1024];
size_t readbytes, written, eoedlen, rawread, rawwritten;
BIO *rbio;
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, idx)))
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))
|| !TEST_int_eq(SSL_read_early_data(serverssl, buf,
sizeof(buf), &readbytes),
SSL_READ_EARLY_DATA_SUCCESS)
|| !TEST_mem_eq(MSG1, readbytes, buf, strlen(MSG1))
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_ACCEPTED))
* Server should be able to write data, and client should be able to
if (!TEST_true(SSL_write_early_data(serverssl, MSG2, strlen(MSG2),
&written))
|| !TEST_size_t_eq(written, strlen(MSG2))
|| !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG2, strlen(MSG2)))
goto end;
/* Even after reading normal data, client should be able write early data */
if (!TEST_true(SSL_write_early_data(clientssl, MSG3, strlen(MSG3),
&written))
|| !TEST_size_t_eq(written, strlen(MSG3)))
/* Server should still be able read early data after writing data */
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_SUCCESS)
|| !TEST_mem_eq(buf, readbytes, MSG3, strlen(MSG3)))
/* Write more data from server and read it from client */
if (!TEST_true(SSL_write_early_data(serverssl, MSG4, strlen(MSG4),
&written))
|| !TEST_size_t_eq(written, strlen(MSG4))
|| !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG4, strlen(MSG4)))
goto end;
/*
* If client writes normal data it should mean writing early data is no
* longer possible.
*/
if (!TEST_true(SSL_write_ex(clientssl, MSG5, strlen(MSG5), &written))
|| !TEST_size_t_eq(written, strlen(MSG5))
|| !TEST_int_eq(SSL_get_early_data_status(clientssl),
SSL_EARLY_DATA_ACCEPTED))
/*
* At this point the client has written EndOfEarlyData, ClientFinished and
* normal (fully protected) data. We are going to cause a delay between the
* arrival of EndOfEarlyData and ClientFinished. We read out all the data
* in the read BIO, and then just put back the EndOfEarlyData message.
*/
rbio = SSL_get_rbio(serverssl);
if (!TEST_true(BIO_read_ex(rbio, data, sizeof(data), &rawread))
|| !TEST_size_t_lt(rawread, sizeof(data))
|| !TEST_size_t_gt(rawread, SSL3_RT_HEADER_LENGTH))
/* Record length is in the 4th and 5th bytes of the record header */
eoedlen = SSL3_RT_HEADER_LENGTH + (data[3] << 8 | data[4]);
if (!TEST_true(BIO_write_ex(rbio, data, eoedlen, &rawwritten))
|| !TEST_size_t_eq(rawwritten, eoedlen))
/* Server should be told that there is no more early data */
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_FINISH)
|| !TEST_size_t_eq(readbytes, 0))
/*
* Server has not finished init yet, so should still be able to write early
* data.
*/
if (!TEST_true(SSL_write_early_data(serverssl, MSG6, strlen(MSG6),
&written))
|| !TEST_size_t_eq(written, strlen(MSG6)))
/* Push the ClientFinished and the normal data back into the server rbio */
if (!TEST_true(BIO_write_ex(rbio, data + eoedlen, rawread - eoedlen,
&rawwritten))
|| !TEST_size_t_eq(rawwritten, rawread - eoedlen))
if (!TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_size_t_eq(readbytes, strlen(MSG5)))
/* Client and server should not be able to write/read early data now */
if (!TEST_false(SSL_write_early_data(clientssl, MSG6, strlen(MSG6),
&written)))
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_ERROR))
/* Client should be able to read the data sent by the server */
if (!TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG6, strlen(MSG6)))
/*
* Make sure we process the NewSessionTicket. This arrives post-handshake.
* We attempt a read which we do not expect to return any data.
*/
if (!TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes)))
/* Server should be able to write normal data */
if (!TEST_true(SSL_write_ex(serverssl, MSG7, strlen(MSG7), &written))
|| !TEST_size_t_eq(written, strlen(MSG7))
|| !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG7, strlen(MSG7)))
SSL_SESSION_free(sess);
sess = SSL_get1_session(clientssl);
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !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))
|| !TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_SUCCESS)
|| !TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1)))
if (!TEST_int_gt(SSL_connect(clientssl), 0)
|| !TEST_int_gt(SSL_accept(serverssl), 0))
/* Client and server should not be able to write/read early data now */
if (!TEST_false(SSL_write_early_data(clientssl, MSG6, strlen(MSG6),
&written)))
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_ERROR))
goto end;
ERR_clear_error();
/* Client and server should be able to write/read normal data */
if (!TEST_true(SSL_write_ex(clientssl, MSG5, strlen(MSG5), &written))
|| !TEST_size_t_eq(written, strlen(MSG5))
|| !TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_size_t_eq(readbytes, strlen(MSG5)))
goto end;
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Test that a server attempting to read early data can handle a connection
* from a client where the early data is not acceptable.
*/
static int test_early_data_skip(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
unsigned char buf[20];
size_t readbytes, written;
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, idx)))
goto end;
/*
* Deliberately corrupt the creation time. We take 20 seconds off the time.
* It could be any value as long as it is not within tolerance. This should
* mean the ticket is rejected.
*/
if (!TEST_true(SSL_SESSION_set_time(sess, time(NULL) - 20)))
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written))
|| !TEST_size_t_eq(written, strlen(MSG1)))
goto end;
/* Server should reject the early data and skip over it */
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_FINISH)
|| !TEST_size_t_eq(readbytes, 0)
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_REJECTED))
/* Should be able to send normal data despite rejection of early data */
if (!TEST_true(SSL_write_ex(clientssl, MSG2, strlen(MSG2), &written))
|| !TEST_size_t_eq(written, strlen(MSG2))
|| !TEST_int_eq(SSL_get_early_data_status(clientssl),
SSL_EARLY_DATA_REJECTED)
|| !TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG2, strlen(MSG2)))
goto end;
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Test that a server attempting to read early data can handle a connection
* from a client that doesn't send any.
*/
static int test_early_data_not_sent(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
unsigned char buf[20];
size_t readbytes, written;
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, idx)))
goto end;
/* Write some data - should block due to handshake with server */
SSL_set_connect_state(clientssl);
if (!TEST_false(SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written)))
goto end;
/* Server should detect that early data has not been sent */
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_FINISH)
|| !TEST_size_t_eq(readbytes, 0)
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_NOT_SENT)
|| !TEST_int_eq(SSL_get_early_data_status(clientssl),
SSL_EARLY_DATA_NOT_SENT))
goto end;
/* Continue writing the message we started earlier */
if (!TEST_true(SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written))
|| !TEST_size_t_eq(written, strlen(MSG1))
|| !TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1))
|| !SSL_write_ex(serverssl, MSG2, strlen(MSG2), &written)
|| !TEST_size_t_eq(written, strlen(MSG2)))
/*
* Should block due to the NewSessionTicket arrival unless we're using
* read_ahead
*/
if (idx == 0) {
if (!TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes)))
if (!TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG2, strlen(MSG2)))
goto end;
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Test that a server that doesn't try to read early data can handle a
* client sending some.
*/
static int test_early_data_not_expected(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
unsigned char buf[20];
size_t readbytes, written;
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, idx)))
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written)))
goto end;
/*
* Server should skip over early data and then block waiting for client to
* continue handshake
*/
if (!TEST_int_le(SSL_accept(serverssl), 0)
|| !TEST_int_gt(SSL_connect(clientssl), 0)
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_REJECTED)
|| !TEST_int_gt(SSL_accept(serverssl), 0)
|| !TEST_int_eq(SSL_get_early_data_status(clientssl),
SSL_EARLY_DATA_REJECTED))
goto end;
/* Send some normal data from client to server */
if (!TEST_true(SSL_write_ex(clientssl, MSG2, strlen(MSG2), &written))
|| !TEST_size_t_eq(written, strlen(MSG2)))
if (!TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG2, strlen(MSG2)))
goto end;
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
# ifndef OPENSSL_NO_TLS1_2
/*
* Test that a server attempting to read early data can handle a connection
* from a TLSv1.2 client.
*/
static int test_early_data_tls1_2(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
unsigned char buf[20];
size_t readbytes, written;
if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
TLS_client_method(), &sctx,
&cctx, cert, privkey)))
/* When idx == 1 we repeat the tests with read_ahead set */
if (idx > 0) {
SSL_CTX_set_read_ahead(cctx, 1);
SSL_CTX_set_read_ahead(sctx, 1);
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
/* Write some data - should block due to handshake with server */
SSL_set_max_proto_version(clientssl, TLS1_2_VERSION);
SSL_set_connect_state(clientssl);
if (!TEST_false(SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written)))
goto end;
/*
* Server should do TLSv1.2 handshake. First it will block waiting for more
* messages from client after ServerDone. Then SSL_read_early_data should
* finish and detect that early data has not been sent
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_ERROR))
goto end;
/*
* Continue writing the message we started earlier. Will still block waiting
* for the CCS/Finished from server
*/
if (!TEST_false(SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written))
|| !TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_FINISH)
|| !TEST_size_t_eq(readbytes, 0)
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_NOT_SENT))
goto end;
/* Continue writing the message we started earlier */
if (!TEST_true(SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written))
|| !TEST_size_t_eq(written, strlen(MSG1))
|| !TEST_int_eq(SSL_get_early_data_status(clientssl),
SSL_EARLY_DATA_NOT_SENT)
|| !TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1))
|| !TEST_true(SSL_write_ex(serverssl, MSG2, strlen(MSG2), &written))
|| !TEST_size_t_eq(written, strlen(MSG2))
|| !SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes)
|| !TEST_mem_eq(buf, readbytes, MSG2, strlen(MSG2)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
# endif /* OPENSSL_NO_TLS1_2 */
static int test_ciphersuite_change(void)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
SSL_SESSION *clntsess = NULL;
int testresult = 0;
const SSL_CIPHER *aes_128_gcm_sha256 = NULL;
/* Create a session based on SHA-256 */
if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
TLS_client_method(), &sctx,
&cctx, cert, privkey))
|| !TEST_true(SSL_CTX_set_cipher_list(cctx,
"TLS13-AES-128-GCM-SHA256"))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
clntsess = SSL_get1_session(clientssl);
/* Save for later */
aes_128_gcm_sha256 = SSL_SESSION_get0_cipher(clntsess);
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
/* Check we can resume a session with a different SHA-256 ciphersuite */
if (!TEST_true(SSL_CTX_set_cipher_list(cctx,
"TLS13-CHACHA20-POLY1305-SHA256"))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, clntsess))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl)))
goto end;
SSL_SESSION_free(clntsess);
clntsess = SSL_get1_session(clientssl);
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
/*
* Check attempting to resume a SHA-256 session with no SHA-256 ciphersuites
* succeeds but does not resume.
*/
if (!TEST_true(SSL_CTX_set_cipher_list(cctx, "TLS13-AES-256-GCM-SHA384"))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, clntsess))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
|| !TEST_false(SSL_session_reused(clientssl)))
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
goto end;
SSL_SESSION_free(clntsess);
clntsess = NULL;
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
/* Create a session based on SHA384 */
if (!TEST_true(SSL_CTX_set_cipher_list(cctx, "TLS13-AES-256-GCM-SHA384"))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
clntsess = SSL_get1_session(clientssl);
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
if (!TEST_true(SSL_CTX_set_cipher_list(cctx,
"TLS13-AES-128-GCM-SHA256:TLS13-AES-256-GCM-SHA384"))
|| !TEST_true(SSL_CTX_set_cipher_list(sctx,
"TLS13-AES-256-GCM-SHA384"))
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, clntsess))
|| !TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_WANT_READ)))
goto end;
/* Trick the client into thinking this session is for a different digest */
clntsess->cipher = aes_128_gcm_sha256;
clntsess->cipher_id = clntsess->cipher->id;
/*
* Server has selected a SHA-384 ciphersuite, but client thinks the session
* is for SHA-256, so it should bail out.
*/
if (!TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_SSL))
|| !TEST_int_eq(ERR_GET_REASON(ERR_get_error()),
SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED))
goto end;
testresult = 1;
end:
SSL_SESSION_free(clntsess);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif /* OPENSSL_NO_TLS1_3 */
static int clntaddoldcb = 0;
static int clntparseoldcb = 0;
static int srvaddoldcb = 0;
static int srvparseoldcb = 0;
static int clntaddnewcb = 0;
static int clntparsenewcb = 0;
static int srvaddnewcb = 0;
static int srvparsenewcb = 0;
static int snicb = 0;
#define TEST_EXT_TYPE1 0xff00
static int old_add_cb(SSL *s, unsigned int ext_type, const unsigned char **out,
size_t *outlen, int *al, void *add_arg)
{
int *server = (int *)add_arg;
unsigned char *data;
if (SSL_is_server(s))
srvaddoldcb++;
else
clntaddoldcb++;
if (*server != SSL_is_server(s)
|| (data = OPENSSL_malloc(sizeof(*data))) == NULL)
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
return -1;
*data = 1;
*out = data;
*outlen = sizeof(char);
return 1;
}
static void old_free_cb(SSL *s, unsigned int ext_type, const unsigned char *out,
void *add_arg)
{
OPENSSL_free((unsigned char *)out);
}
static int old_parse_cb(SSL *s, unsigned int ext_type, const unsigned char *in,
size_t inlen, int *al, void *parse_arg)
{
int *server = (int *)parse_arg;
if (SSL_is_server(s))
srvparseoldcb++;
else
clntparseoldcb++;
if (*server != SSL_is_server(s)
|| inlen != sizeof(char)
|| *in != 1)
return -1;
return 1;
}
static int new_add_cb(SSL *s, unsigned int ext_type, unsigned int context,
const unsigned char **out, size_t *outlen, X509 *x,
size_t chainidx, int *al, void *add_arg)
{
int *server = (int *)add_arg;
unsigned char *data;
if (SSL_is_server(s))
srvaddnewcb++;
else
clntaddnewcb++;
if (*server != SSL_is_server(s)
|| (data = OPENSSL_malloc(sizeof(*data))) == NULL)
return -1;
*data = 1;
*out = data;