Newer
Older
/*
* Should block due to the NewSessionTicket arrival unless we're using
* read_ahead
*/
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)))
/* If using PSK then clientpsk and sess are the same */
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
static int hostname_cb(SSL *s, int *al, void *arg)
{
const char *hostname = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
if (hostname != NULL && strcmp(hostname, "goodhost") == 0)
return SSL_TLSEXT_ERR_OK;
return SSL_TLSEXT_ERR_NOACK;
}
static const char *servalpn;
static int alpn_select_cb(SSL *ssl, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg)
for (prot = in; prot < in + inlen; prot += protlen) {
protlen = *prot++;
return SSL_TLSEXT_ERR_NOACK;
if (protlen == strlen(servalpn)
&& memcmp(prot, servalpn, protlen) == 0) {
*out = prot;
*outlen = protlen;
return SSL_TLSEXT_ERR_OK;
}
}
return SSL_TLSEXT_ERR_NOACK;
}
/* Test that a PSK can be used to send early_data */
static int test_early_data_psk(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;
unsigned char alpnlist[] = {
0x08, 'g', 'o', 'o', 'd', 'a', 'l', 'p', 'n', 0x07, 'b', 'a', 'd', 'a',
'l', 'p', 'n'
};
#define GOODALPNLEN 9
#define BADALPNLEN 8
#define GOODALPN (alpnlist)
#define BADALPN (alpnlist + GOODALPNLEN)
int err = 0;
unsigned char buf[20];
size_t readbytes, written;
int readearlyres = SSL_READ_EARLY_DATA_SUCCESS, connectres = 1;
int edstatus = SSL_EARLY_DATA_ACCEPTED;
/* We always set this up with a final parameter of "2" for PSK */
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, 2)))
goto end;
servalpn = "goodalpn";
/*
* Note: There is no test for inconsistent SNI with late client detection.
* This is because servers do not acknowledge SNI even if they are using
* it in a resumption handshake - so it is not actually possible for a
* client to detect a problem.
*/
/* Set inconsistent SNI (early client detection) */
err = SSL_R_INCONSISTENT_EARLY_DATA_SNI;
if (!TEST_true(SSL_SESSION_set1_hostname(sess, "goodhost"))
|| !TEST_true(SSL_set_tlsext_host_name(clientssl, "badhost")))
goto end;
break;
case 1:
/* Set inconsistent ALPN (early client detection) */
err = SSL_R_INCONSISTENT_EARLY_DATA_ALPN;
/* SSL_set_alpn_protos returns 0 for success and 1 for failure */
if (!TEST_true(SSL_SESSION_set1_alpn_selected(sess, GOODALPN,
GOODALPNLEN))
|| !TEST_false(SSL_set_alpn_protos(clientssl, BADALPN,
BADALPNLEN)))
goto end;
break;
case 2:
/*
* Set invalid protocol version. Technically this affects PSKs without
* early_data too, but we test it here because it is similar to the
* SNI/ALPN consistency tests.
*/
err = SSL_R_BAD_PSK;
if (!TEST_true(SSL_SESSION_set_protocol_version(sess, TLS1_2_VERSION)))
goto end;
break;
case 3:
/*
* Set inconsistent SNI (server detected). In this case the connection
* will succeed but reject early_data.
*/
SSL_SESSION_free(serverpsk);
serverpsk = SSL_SESSION_dup(clientpsk);
if (!TEST_ptr(serverpsk)
|| !TEST_true(SSL_SESSION_set1_hostname(serverpsk, "badhost")))
goto end;
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
edstatus = SSL_EARLY_DATA_REJECTED;
readearlyres = SSL_READ_EARLY_DATA_FINISH;
/* Fall through */
case 4:
/* Set consistent SNI */
if (!TEST_true(SSL_SESSION_set1_hostname(sess, "goodhost"))
|| !TEST_true(SSL_set_tlsext_host_name(clientssl, "goodhost"))
|| !TEST_true(SSL_CTX_set_tlsext_servername_callback(sctx,
hostname_cb)))
goto end;
break;
case 5:
/*
* Set inconsistent ALPN (server detected). In this case the connection
* will succeed but reject early_data.
*/
servalpn = "badalpn";
edstatus = SSL_EARLY_DATA_REJECTED;
readearlyres = SSL_READ_EARLY_DATA_FINISH;
/* Fall through */
case 6:
/*
* Set consistent ALPN.
* SSL_set_alpn_protos returns 0 for success and 1 for failure. It
* accepts a list of protos (each one length prefixed).
* SSL_set1_alpn_selected accepts a single protocol (not length
* prefixed)
*/
if (!TEST_true(SSL_SESSION_set1_alpn_selected(sess, GOODALPN + 1,
GOODALPNLEN - 1))
|| !TEST_false(SSL_set_alpn_protos(clientssl, GOODALPN,
GOODALPNLEN)))
goto end;
SSL_CTX_set_alpn_select_cb(sctx, alpn_select_cb, NULL);
break;
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
case 7:
/* Set inconsistent ALPN (late client detection) */
SSL_SESSION_free(serverpsk);
serverpsk = SSL_SESSION_dup(clientpsk);
if (!TEST_ptr(serverpsk)
|| !TEST_true(SSL_SESSION_set1_alpn_selected(clientpsk,
BADALPN + 1,
BADALPNLEN - 1))
|| !TEST_true(SSL_SESSION_set1_alpn_selected(serverpsk,
GOODALPN + 1,
GOODALPNLEN - 1))
|| !TEST_false(SSL_set_alpn_protos(clientssl, alpnlist,
sizeof(alpnlist))))
goto end;
SSL_CTX_set_alpn_select_cb(sctx, alpn_select_cb, NULL);
edstatus = SSL_EARLY_DATA_ACCEPTED;
readearlyres = SSL_READ_EARLY_DATA_SUCCESS;
/* SSL_connect() call should fail */
connectres = -1;
break;
default:
TEST_error("Bad test index");
goto end;
}
SSL_set_connect_state(clientssl);
if (err != 0) {
if (!TEST_false(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written))
|| !TEST_int_eq(SSL_get_error(clientssl, 0), SSL_ERROR_SSL)
|| !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), err))
goto end;
} else {
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written)))
goto end;
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes), readearlyres)
|| (readearlyres == SSL_READ_EARLY_DATA_SUCCESS
&& !TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1)))
|| !TEST_int_eq(SSL_get_early_data_status(serverssl), edstatus)
|| !TEST_int_eq(SSL_connect(clientssl), connectres))
goto end;
}
testresult = 1;
end:
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
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)))
/* If using PSK then clientpsk and sess are the same */
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
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(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, NULL, idx)))
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)))
/* If using PSK then clientpsk and sess are the same */
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
# 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;
# if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
/* 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)))
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
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"))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, clntsess))
/*
* We use SSL_ERROR_WANT_READ below so that we can pause the
* connection after the initial ClientHello has been sent to
* enable us to make some session changes.
*/
|| !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;
/*
* Continue the previously started connection. 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;
}
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
const SSL_CIPHER *cipher = NULL;
const unsigned char key[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
};
int testresult = 0;
if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
TLS_client_method(), &sctx,
&cctx, cert, privkey)))
goto end;
/*
* We use a ciphersuite with SHA256 to ease testing old style PSK callbacks
* which will always default to SHA256
*/
if (!TEST_true(SSL_CTX_set_cipher_list(cctx, "TLS13-AES-128-GCM-SHA256")))
goto end;
/*
* Test 0: New style callbacks only
* Test 1: New and old style callbacks (only the new ones should be used)
* Test 2: Old style callbacks only
*/
if (idx == 0 || idx == 1) {
SSL_CTX_set_psk_use_session_callback(cctx, use_session_cb);
SSL_CTX_set_psk_find_session_callback(sctx, find_session_cb);
}
if (idx == 1 || idx == 2) {
SSL_CTX_set_psk_client_callback(cctx, psk_client_cb);
SSL_CTX_set_psk_server_callback(sctx, psk_server_cb);
}
use_session_cb_cnt = 0;
find_session_cb_cnt = 0;
psk_client_cb_cnt = 0;
psk_server_cb_cnt = 0;
/* Check we can create a connection if callback decides not to send a PSK */
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_false(SSL_session_reused(clientssl))
|| !TEST_false(SSL_session_reused(serverssl)))
if (idx == 0 || idx == 1) {
if (!TEST_true(use_session_cb_cnt == 1)
|| !TEST_true(find_session_cb_cnt == 0)
/*
* If no old style callback then below should be 0
* otherwise 1
*/
|| !TEST_true(psk_client_cb_cnt == idx)
|| !TEST_true(psk_server_cb_cnt == 0))
goto end;
} else {
if (!TEST_true(use_session_cb_cnt == 0)
|| !TEST_true(find_session_cb_cnt == 0)
|| !TEST_true(psk_client_cb_cnt == 1)
|| !TEST_true(psk_server_cb_cnt == 0))
goto end;
}
shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
/* Create the PSK */
cipher = SSL_CIPHER_find(clientssl, TLS13_AES_128_GCM_SHA256_BYTES);
clientpsk = SSL_SESSION_new();
if (!TEST_ptr(clientpsk)
|| !TEST_true(SSL_SESSION_set1_master_key(clientpsk, key,
sizeof(key)))
|| !TEST_true(SSL_SESSION_set_cipher(clientpsk, cipher))
|| !TEST_true(SSL_SESSION_set_protocol_version(clientpsk,
TLS1_3_VERSION))
|| !TEST_true(SSL_SESSION_up_ref(clientpsk)))
serverpsk = clientpsk;
/* Check we can create a connection and the PSK is used */
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl))
|| !TEST_true(SSL_session_reused(serverssl)))
if (idx == 0 || idx == 1) {
if (!TEST_true(use_session_cb_cnt == 1)
|| !TEST_true(find_session_cb_cnt == 1)
|| !TEST_true(psk_client_cb_cnt == 0)
|| !TEST_true(psk_server_cb_cnt == 0))
goto end;
} else {
if (!TEST_true(use_session_cb_cnt == 0)
|| !TEST_true(find_session_cb_cnt == 0)
|| !TEST_true(psk_client_cb_cnt == 1)
|| !TEST_true(psk_server_cb_cnt == 1))
goto end;
}
shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
use_session_cb_cnt = find_session_cb_cnt = 0;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
/* Force an HRR */
if (!TEST_true(SSL_set1_groups_list(serverssl, "P-256")))
goto end;
/*
* Check we can create a connection, the PSK is used and the callbacks are
* called twice.
*/
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl))
|| !TEST_true(SSL_session_reused(serverssl)))
if (idx == 0 || idx == 1) {
if (!TEST_true(use_session_cb_cnt == 2)
|| !TEST_true(find_session_cb_cnt == 2)
|| !TEST_true(psk_client_cb_cnt == 0)
|| !TEST_true(psk_server_cb_cnt == 0))
goto end;
} else {
if (!TEST_true(use_session_cb_cnt == 0)
|| !TEST_true(find_session_cb_cnt == 0)
|| !TEST_true(psk_client_cb_cnt == 2)
|| !TEST_true(psk_server_cb_cnt == 2))
goto end;
}
shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
use_session_cb_cnt = find_session_cb_cnt = 0;
/*
* Check that if the server rejects the PSK we can still connect, but with
* a full handshake
*/
srvid = "Dummy Identity";
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_false(SSL_session_reused(clientssl))
|| !TEST_false(SSL_session_reused(serverssl)))
if (idx == 0 || idx == 1) {
if (!TEST_true(use_session_cb_cnt == 1)
|| !TEST_true(find_session_cb_cnt == 1)
|| !TEST_true(psk_client_cb_cnt == 0)
/*
* If no old style callback then below should be 0
* otherwise 1
*/
|| !TEST_true(psk_server_cb_cnt == idx))
goto end;
} else {
if (!TEST_true(use_session_cb_cnt == 0)
|| !TEST_true(find_session_cb_cnt == 0)
|| !TEST_true(psk_client_cb_cnt == 1)
|| !TEST_true(psk_server_cb_cnt == 1))
goto end;
}
shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
testresult = 1;
end:
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
static unsigned char cookie_magic_value[] = "cookie magic";
static int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
unsigned int *cookie_len)
{
/*
* Not suitable as a real cookie generation function but good enough for
* testing!
*/
memcpy(cookie, cookie_magic_value, sizeof(cookie_magic_value) - 1);
*cookie_len = sizeof(cookie_magic_value) - 1;
return 1;
}
static int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
unsigned int cookie_len)
{
if (cookie_len == sizeof(cookie_magic_value) - 1
&& memcmp(cookie, cookie_magic_value, cookie_len) == 0)
return 1;
return 0;
}
static int test_stateless(void)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
int testresult = 0;
if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
TLS_client_method(), &sctx,
&cctx, cert, privkey)))
goto end;
/* The arrival of CCS messages can confuse the test */
SSL_CTX_clear_options(cctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
/* Send the first ClientHello */
|| !TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_WANT_READ))
/*
* This should fail with a -1 return because we have no callbacks
* set up
*/
|| !TEST_int_eq(SSL_stateless(serverssl), -1))
goto end;
/* Fatal error so abandon the connection from this client */
SSL_free(clientssl);
clientssl = NULL;
/* Set up the cookie generation and verification callbacks */
SSL_CTX_set_cookie_generate_cb(sctx, generate_cookie_callback);
SSL_CTX_set_cookie_verify_cb(sctx, verify_cookie_callback);
/*
* Create a new connection from the client (we can reuse the server SSL
* object).
*/
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
/* Send the first ClientHello */
|| !TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_WANT_READ))
/* This should fail because there is no cookie */
|| !TEST_int_eq(SSL_stateless(serverssl), 0))
goto end;
/* Abandon the connection from this client */
SSL_free(clientssl);
clientssl = NULL;
/*
* Now create a connection from a new client but with the same server SSL
* object
*/
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
/* Send the first ClientHello */
|| !TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_WANT_READ))
/* This should fail because there is no cookie */
|| !TEST_int_eq(SSL_stateless(serverssl), 0)
/* Send the second ClientHello */
|| !TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_WANT_READ))
/* This should succeed because a cookie is now present */
|| !TEST_int_eq(SSL_stateless(serverssl), 1)
/* Complete the connection */
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
testresult = 1;
end:
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)
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
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;
return 1;
}
static void new_free_cb(SSL *s, unsigned int ext_type, unsigned int context,
const unsigned char *out, void *add_arg)
{
OPENSSL_free((unsigned char *)out);
}
static int new_parse_cb(SSL *s, unsigned int ext_type, unsigned int context,
const unsigned char *in, size_t inlen, X509 *x,
size_t chainidx, int *al, void *parse_arg)
{
int *server = (int *)parse_arg;
if (SSL_is_server(s))
srvparsenewcb++;
else
clntparsenewcb++;
if (*server != SSL_is_server(s)
|| inlen != sizeof(char) || *in != 1)
return -1;
return 1;
}
static int sni_cb(SSL *s, int *al, void *arg)
{
SSL_CTX *ctx = (SSL_CTX *)arg;
if (SSL_set_SSL_CTX(s, ctx) == NULL) {
*al = SSL_AD_INTERNAL_ERROR;
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
snicb++;
return SSL_TLSEXT_ERR_OK;
}
/*
* Custom call back tests.
* Test 0: Old style callbacks in TLSv1.2
* Test 1: New style callbacks in TLSv1.2
* Test 2: New style callbacks in TLSv1.2 with SNI
* Test 3: New style callbacks in TLSv1.3. Extensions in CH and EE
* Test 4: New style callbacks in TLSv1.3. Extensions in CH, SH, EE, Cert + NST
static int test_custom_exts(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL, *sctx2 = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
static int server = 1;
static int client = 0;
SSL_SESSION *sess = NULL;
unsigned int context;
#if defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_3)
/* Skip tests for TLSv1.2 and below in this case */
if (tst < 3)
return 1;
#endif
/* Reset callback counters */
clntaddoldcb = clntparseoldcb = srvaddoldcb = srvparseoldcb = 0;
clntaddnewcb = clntparsenewcb = srvaddnewcb = srvparsenewcb = 0;
if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
TLS_client_method(), &sctx,
&cctx, cert, privkey)))
goto end;
if (tst == 2
&& !TEST_true(create_ssl_ctx_pair(TLS_server_method(), NULL, &sctx2,
NULL, cert, privkey)))
goto end;
if (tst < 3) {
SSL_CTX_set_options(cctx, SSL_OP_NO_TLSv1_3);
SSL_CTX_set_options(sctx, SSL_OP_NO_TLSv1_3);
if (sctx2 != NULL)
SSL_CTX_set_options(sctx2, SSL_OP_NO_TLSv1_3);
if (tst == 4) {
context = SSL_EXT_CLIENT_HELLO
| SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_SERVER_HELLO
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
| SSL_EXT_TLS1_3_CERTIFICATE
| SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
} else {
context = SSL_EXT_CLIENT_HELLO
| SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
}
/* Create a client side custom extension */
if (tst == 0) {
if (!TEST_true(SSL_CTX_add_client_custom_ext(cctx, TEST_EXT_TYPE1,
old_add_cb, old_free_cb,
&client, old_parse_cb,
&client)))
goto end;
if (!TEST_true(SSL_CTX_add_custom_ext(cctx, TEST_EXT_TYPE1, context,
new_add_cb, new_free_cb,
&client, new_parse_cb, &client)))
goto end;