mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 17:40:50 +02:00
c674cec4ac
Move out DTLS 1.3 specific tests into test_dtls13.c. (Also move out from test_dtls.c) Move out DTLS tests into test_dtls.c. Move out LMS and XMSS tests into test_lms_xmss.c. Move out SSL session tests into test_session.c. Move out remaining ML-DSA/Dilithium tests in api.c into test_mldsa.c.
1617 lines
58 KiB
C
1617 lines
58 KiB
C
/* test_session.c
|
|
*
|
|
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* wolfSSL is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSL is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
#include <tests/unit.h>
|
|
|
|
#ifdef NO_INLINE
|
|
#include <wolfssl/wolfcrypt/misc.h>
|
|
#else
|
|
#define WOLFSSL_MISC_INCLUDED
|
|
#include <wolfcrypt/src/misc.c>
|
|
#endif
|
|
|
|
#include <wolfssl/ssl.h>
|
|
#include <wolfssl/internal.h>
|
|
#include <wolfssl/error-ssl.h>
|
|
#include <tests/api/api.h>
|
|
#include <tests/utils.h>
|
|
#include <tests/api/test_session.h>
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/* WOLFSSL_CTX_add_session / session resumption */
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \
|
|
!defined(SINGLE_THREADED) && defined(WOLFSSL_TLS13) && \
|
|
!defined(NO_SESSION_CACHE)
|
|
|
|
/* Sessions to restore/store */
|
|
static WOLFSSL_SESSION* test_wolfSSL_CTX_add_session_client_sess;
|
|
static WOLFSSL_SESSION* test_wolfSSL_CTX_add_session_server_sess;
|
|
static WOLFSSL_CTX* test_wolfSSL_CTX_add_session_server_ctx;
|
|
|
|
static void test_wolfSSL_CTX_add_session_ctx_ready(WOLFSSL_CTX* ctx)
|
|
{
|
|
/* Don't store sessions. Lookup is still enabled. */
|
|
AssertIntEQ(wolfSSL_CTX_set_session_cache_mode(ctx,
|
|
WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE), WOLFSSL_SUCCESS);
|
|
#ifdef OPENSSL_EXTRA
|
|
AssertIntEQ(wolfSSL_CTX_get_session_cache_mode(ctx) &
|
|
WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE,
|
|
WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE);
|
|
#endif
|
|
/* Require both peers to provide certs */
|
|
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL);
|
|
}
|
|
|
|
static void test_wolfSSL_CTX_add_session_on_result(WOLFSSL* ssl)
|
|
{
|
|
WOLFSSL_SESSION** sess;
|
|
#ifdef WOLFSSL_MUTEX_INITIALIZER
|
|
static wolfSSL_Mutex m = WOLFSSL_MUTEX_INITIALIZER(m);
|
|
|
|
(void)wc_LockMutex(&m);
|
|
#endif
|
|
if (wolfSSL_is_server(ssl))
|
|
sess = &test_wolfSSL_CTX_add_session_server_sess;
|
|
else
|
|
sess = &test_wolfSSL_CTX_add_session_client_sess;
|
|
if (*sess == NULL) {
|
|
#ifdef NO_SESSION_CACHE_REF
|
|
*sess = wolfSSL_get1_session(ssl);
|
|
AssertNotNull(*sess);
|
|
#else
|
|
/* Test for backwards compatibility */
|
|
if (wolfSSL_is_server(ssl)) {
|
|
*sess = wolfSSL_get1_session(ssl);
|
|
AssertNotNull(*sess);
|
|
}
|
|
else {
|
|
*sess = wolfSSL_get_session(ssl);
|
|
AssertNotNull(*sess);
|
|
}
|
|
#endif
|
|
/* Now save the session in the internal store to make it available
|
|
* for lookup. For TLS 1.3, we can't save the session without
|
|
* WOLFSSL_TICKET_HAVE_ID because there is no way to retrieve the
|
|
* session from cache. */
|
|
if (wolfSSL_is_server(ssl)
|
|
#ifndef WOLFSSL_TICKET_HAVE_ID
|
|
&& wolfSSL_version(ssl) != TLS1_3_VERSION
|
|
#endif
|
|
)
|
|
AssertIntEQ(wolfSSL_CTX_add_session(wolfSSL_get_SSL_CTX(ssl),
|
|
*sess), WOLFSSL_SUCCESS);
|
|
}
|
|
else {
|
|
/* If we have a session retrieved then remaining connections should be
|
|
* resuming on that session */
|
|
AssertIntEQ(wolfSSL_session_reused(ssl), 1);
|
|
}
|
|
#ifdef WOLFSSL_MUTEX_INITIALIZER
|
|
wc_UnLockMutex(&m);
|
|
#endif
|
|
|
|
/* Save CTX to be able to decrypt tickets */
|
|
if (wolfSSL_is_server(ssl) &&
|
|
test_wolfSSL_CTX_add_session_server_ctx == NULL) {
|
|
test_wolfSSL_CTX_add_session_server_ctx = wolfSSL_get_SSL_CTX(ssl);
|
|
AssertNotNull(test_wolfSSL_CTX_add_session_server_ctx);
|
|
AssertIntEQ(wolfSSL_CTX_up_ref(wolfSSL_get_SSL_CTX(ssl)),
|
|
WOLFSSL_SUCCESS);
|
|
}
|
|
#if defined(SESSION_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
|
|
#ifndef WOLFSSL_TICKET_HAVE_ID
|
|
if (wolfSSL_version(ssl) != TLS1_3_VERSION &&
|
|
wolfSSL_session_reused(ssl))
|
|
#endif
|
|
{
|
|
/* With WOLFSSL_TICKET_HAVE_ID the peer certs should be available
|
|
* for all connections. TLS 1.3 only has tickets so if we don't
|
|
* include the session id in the ticket then the certificates
|
|
* will not be available on resumption. */
|
|
#ifdef KEEP_PEER_CERT
|
|
WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl);
|
|
AssertNotNull(peer);
|
|
wolfSSL_X509_free(peer);
|
|
#endif
|
|
AssertNotNull(wolfSSL_SESSION_get_peer_chain(*sess));
|
|
#ifdef OPENSSL_EXTRA
|
|
AssertNotNull(SSL_SESSION_get0_peer(*sess));
|
|
#endif
|
|
}
|
|
#endif /* SESSION_CERTS && !WOLFSSL_NO_CLIENT_AUTH */
|
|
}
|
|
|
|
static void test_wolfSSL_CTX_add_session_ssl_ready(WOLFSSL* ssl)
|
|
{
|
|
/* Set the session to reuse for the client */
|
|
AssertIntEQ(wolfSSL_set_session(ssl,
|
|
test_wolfSSL_CTX_add_session_client_sess), WOLFSSL_SUCCESS);
|
|
}
|
|
#endif
|
|
|
|
int test_wolfSSL_CTX_add_session(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \
|
|
!defined(SINGLE_THREADED) && defined(WOLFSSL_TLS13) && \
|
|
!defined(NO_SESSION_CACHE)
|
|
tcp_ready ready;
|
|
func_args client_args;
|
|
func_args server_args;
|
|
THREAD_TYPE serverThread;
|
|
callback_functions client_cb;
|
|
callback_functions server_cb;
|
|
method_provider methods[][2] = {
|
|
#if !defined(NO_OLD_TLS) && ((!defined(NO_AES) && !defined(NO_AES_CBC)) || \
|
|
!defined(NO_DES3))
|
|
/* Without AES there are almost no ciphersuites available. This leads
|
|
* to no ciphersuites being available and an error. */
|
|
{ wolfTLSv1_1_client_method, wolfTLSv1_1_server_method },
|
|
#endif
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
{ wolfTLSv1_2_client_method, wolfTLSv1_2_server_method },
|
|
#endif
|
|
/* Needs the default ticket callback since it is tied to the
|
|
* connection context and this makes it easy to carry over the ticket
|
|
* crypto context between connections */
|
|
#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \
|
|
defined(HAVE_SESSION_TICKET)
|
|
{ wolfTLSv1_3_client_method, wolfTLSv1_3_server_method },
|
|
#endif
|
|
};
|
|
const size_t methodsLen = sizeof(methods)/sizeof(*methods);
|
|
size_t i, j;
|
|
|
|
for (i = 0; i < methodsLen; i++) {
|
|
/* First run creates a connection while the second+ run will attempt
|
|
* to resume the connection. The trick is that the internal cache
|
|
* is turned off. wolfSSL_CTX_add_session should put the session in
|
|
* the cache anyway. */
|
|
test_wolfSSL_CTX_add_session_client_sess = NULL;
|
|
test_wolfSSL_CTX_add_session_server_sess = NULL;
|
|
test_wolfSSL_CTX_add_session_server_ctx = NULL;
|
|
|
|
#ifdef NO_SESSION_CACHE_REF
|
|
for (j = 0; j < 4; j++) {
|
|
#else
|
|
/* The session may be overwritten in this case. Do only one resumption
|
|
* to stop this test from failing intermittently. */
|
|
for (j = 0; j < 2; j++) {
|
|
#endif
|
|
#ifdef WOLFSSL_TIRTOS
|
|
fdOpenSession(Task_self());
|
|
#endif
|
|
|
|
StartTCP();
|
|
InitTcpReady(&ready);
|
|
|
|
XMEMSET(&client_args, 0, sizeof(func_args));
|
|
XMEMSET(&server_args, 0, sizeof(func_args));
|
|
|
|
XMEMSET(&client_cb, 0, sizeof(callback_functions));
|
|
XMEMSET(&server_cb, 0, sizeof(callback_functions));
|
|
client_cb.method = methods[i][0];
|
|
server_cb.method = methods[i][1];
|
|
|
|
server_args.signal = &ready;
|
|
server_args.callbacks = &server_cb;
|
|
client_args.signal = &ready;
|
|
client_args.callbacks = &client_cb;
|
|
|
|
if (test_wolfSSL_CTX_add_session_server_ctx != NULL) {
|
|
server_cb.ctx = test_wolfSSL_CTX_add_session_server_ctx;
|
|
server_cb.isSharedCtx = 1;
|
|
}
|
|
server_cb.ctx_ready = test_wolfSSL_CTX_add_session_ctx_ready;
|
|
client_cb.ctx_ready = test_wolfSSL_CTX_add_session_ctx_ready;
|
|
if (j != 0)
|
|
client_cb.ssl_ready = test_wolfSSL_CTX_add_session_ssl_ready;
|
|
server_cb.on_result = test_wolfSSL_CTX_add_session_on_result;
|
|
client_cb.on_result = test_wolfSSL_CTX_add_session_on_result;
|
|
server_cb.ticNoInit = 1; /* Use default builtin */
|
|
|
|
start_thread(test_server_nofail, &server_args, &serverThread);
|
|
wait_tcp_ready(&server_args);
|
|
test_client_nofail(&client_args, NULL);
|
|
join_thread(serverThread);
|
|
|
|
ExpectTrue(client_args.return_code);
|
|
ExpectTrue(server_args.return_code);
|
|
|
|
FreeTcpReady(&ready);
|
|
|
|
if (EXPECT_FAIL())
|
|
break;
|
|
}
|
|
wolfSSL_SESSION_free(test_wolfSSL_CTX_add_session_client_sess);
|
|
wolfSSL_SESSION_free(test_wolfSSL_CTX_add_session_server_sess);
|
|
wolfSSL_CTX_free(test_wolfSSL_CTX_add_session_server_ctx);
|
|
|
|
if (EXPECT_FAIL())
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
return EXPECT_RESULT();
|
|
}
|
|
#if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \
|
|
defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \
|
|
defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \
|
|
defined(HAVE_SESSION_TICKET) && \
|
|
!defined(TITAN_SESSION_CACHE) && \
|
|
!defined(HUGE_SESSION_CACHE) && \
|
|
!defined(BIG_SESSION_CACHE) && \
|
|
!defined(MEDIUM_SESSION_CACHE)
|
|
|
|
/* twcase - prefix for test_wolfSSL_CTX_add_session_ext */
|
|
/* Sessions to restore/store */
|
|
static WOLFSSL_SESSION* twcase_server_first_session_ptr;
|
|
static WOLFSSL_SESSION* twcase_client_first_session_ptr;
|
|
static WOLFSSL_CTX* twcase_server_current_ctx_ptr;
|
|
static int twcase_new_session_called = 0;
|
|
static int twcase_remove_session_called = 0;
|
|
static int twcase_get_session_called = 0;
|
|
|
|
/* Test default, SESSIONS_PER_ROW*SESSION_ROWS = 3*11, see ssl.c */
|
|
#define SESSION_CACHE_SIZE 33
|
|
|
|
typedef struct {
|
|
const byte* key; /* key, altSessionID, session ID, NULL if empty */
|
|
WOLFSSL_SESSION* value;
|
|
} hashTable_entry;
|
|
|
|
typedef struct {
|
|
hashTable_entry entries[SESSION_CACHE_SIZE]; /* hash slots */
|
|
size_t capacity; /* size of entries */
|
|
size_t length; /* number of items in the hash table */
|
|
wolfSSL_Mutex htLock; /* lock */
|
|
}hashTable;
|
|
|
|
static hashTable server_sessionCache;
|
|
|
|
static int twcase_new_sessionCb(WOLFSSL *ssl, WOLFSSL_SESSION *sess)
|
|
{
|
|
int i;
|
|
unsigned int len;
|
|
(void)ssl;
|
|
|
|
/*
|
|
* This example uses a hash table.
|
|
* Steps you should take for a non-demo code:
|
|
* - acquire a lock for the file named according to the session id
|
|
* - open the file
|
|
* - encrypt and write the SSL_SESSION object to the file
|
|
* - release the lock
|
|
*
|
|
* Return:
|
|
* 0: The callback does not wish to hold a reference of the sess
|
|
* 1: The callback wants to hold a reference of the sess. The callback is
|
|
* now also responsible for calling wolfSSL_SESSION_free() on sess.
|
|
*/
|
|
if (sess == NULL)
|
|
return 0;
|
|
|
|
if (wc_LockMutex(&server_sessionCache.htLock) != 0) {
|
|
return 0;
|
|
}
|
|
for (i = 0; i < SESSION_CACHE_SIZE; i++) {
|
|
if (server_sessionCache.entries[i].value == NULL) {
|
|
server_sessionCache.entries[i].key = SSL_SESSION_get_id(sess, &len);
|
|
server_sessionCache.entries[i].value = sess;
|
|
server_sessionCache.length++;
|
|
break;
|
|
}
|
|
}
|
|
++twcase_new_session_called;
|
|
wc_UnLockMutex(&server_sessionCache.htLock);
|
|
fprintf(stderr, "\t\ttwcase_new_session_called %d\n",
|
|
twcase_new_session_called);
|
|
return 1;
|
|
}
|
|
|
|
static void twcase_remove_sessionCb(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *sess)
|
|
{
|
|
int i;
|
|
(void)ctx;
|
|
(void)sess;
|
|
|
|
if (sess == NULL)
|
|
return;
|
|
/*
|
|
* This example uses a hash table.
|
|
* Steps you should take for a non-demo code:
|
|
* - acquire a lock for the file named according to the session id
|
|
* - remove the file
|
|
* - release the lock
|
|
*/
|
|
if (wc_LockMutex(&server_sessionCache.htLock) != 0) {
|
|
return;
|
|
}
|
|
for (i = 0; i < SESSION_CACHE_SIZE; i++) {
|
|
if (server_sessionCache.entries[i].key != NULL &&
|
|
XMEMCMP(server_sessionCache.entries[i].key,
|
|
sess->sessionID, SSL_MAX_SSL_SESSION_ID_LENGTH) == 0) {
|
|
wolfSSL_SESSION_free(server_sessionCache.entries[i].value);
|
|
server_sessionCache.entries[i].value = NULL;
|
|
server_sessionCache.entries[i].key = NULL;
|
|
server_sessionCache.length--;
|
|
break;
|
|
}
|
|
}
|
|
++twcase_remove_session_called;
|
|
wc_UnLockMutex(&server_sessionCache.htLock);
|
|
fprintf(stderr, "\t\ttwcase_remove_session_called %d\n",
|
|
twcase_remove_session_called);
|
|
}
|
|
|
|
static WOLFSSL_SESSION *twcase_get_sessionCb(WOLFSSL *ssl,
|
|
const unsigned char *id, int len, int *ref)
|
|
{
|
|
int i;
|
|
(void)ssl;
|
|
(void)id;
|
|
(void)len;
|
|
|
|
/*
|
|
* This example uses a hash table.
|
|
* Steps you should take for a non-demo code:
|
|
* - acquire a lock for the file named according to the session id in the
|
|
* 2nd arg
|
|
* - read and decrypt contents of file and create a new SSL_SESSION
|
|
* - object release the lock
|
|
* - return the new session object
|
|
*/
|
|
fprintf(stderr, "\t\ttwcase_get_session_called %d\n",
|
|
++twcase_get_session_called);
|
|
/* This callback want to retain a copy of the object. If we want wolfSSL to
|
|
* be responsible for the pointer then set to 0. */
|
|
*ref = 1;
|
|
|
|
for (i = 0; i < SESSION_CACHE_SIZE; i++) {
|
|
if (server_sessionCache.entries[i].key != NULL &&
|
|
XMEMCMP(server_sessionCache.entries[i].key, id,
|
|
SSL_MAX_SSL_SESSION_ID_LENGTH) == 0) {
|
|
return server_sessionCache.entries[i].value;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
static int twcase_get_sessionCb_cleanup(void)
|
|
{
|
|
int i;
|
|
int cnt = 0;
|
|
|
|
/* If twcase_get_sessionCb sets *ref = 1, the application is responsible
|
|
* for freeing sessions */
|
|
|
|
for (i = 0; i < SESSION_CACHE_SIZE; i++) {
|
|
if (server_sessionCache.entries[i].value != NULL) {
|
|
wolfSSL_SESSION_free(server_sessionCache.entries[i].value);
|
|
cnt++;
|
|
}
|
|
}
|
|
|
|
fprintf(stderr, "\t\ttwcase_get_sessionCb_cleanup freed %d sessions\n",
|
|
cnt);
|
|
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
static int twcase_cache_intOff_extOff(WOLFSSL_CTX* ctx)
|
|
{
|
|
EXPECT_DECLS;
|
|
/* off - Disable internal cache */
|
|
ExpectIntEQ(wolfSSL_CTX_set_session_cache_mode(ctx,
|
|
WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE), WOLFSSL_SUCCESS);
|
|
#ifdef OPENSSL_EXTRA
|
|
ExpectIntEQ(wolfSSL_CTX_get_session_cache_mode(ctx) &
|
|
WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE,
|
|
WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE);
|
|
#endif
|
|
/* off - Do not setup external cache */
|
|
|
|
/* Require both peers to provide certs */
|
|
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL);
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
static int twcase_cache_intOn_extOff(WOLFSSL_CTX* ctx)
|
|
{
|
|
/* on - internal cache is on by default */
|
|
/* off - Do not setup external cache */
|
|
/* Require both peers to provide certs */
|
|
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
static int twcase_cache_intOff_extOn(WOLFSSL_CTX* ctx)
|
|
{
|
|
EXPECT_DECLS;
|
|
/* off - Disable internal cache */
|
|
ExpectIntEQ(wolfSSL_CTX_set_session_cache_mode(ctx,
|
|
WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE), WOLFSSL_SUCCESS);
|
|
#ifdef OPENSSL_EXTRA
|
|
ExpectIntEQ(wolfSSL_CTX_get_session_cache_mode(ctx) &
|
|
WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE,
|
|
WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE);
|
|
#endif
|
|
/* on - Enable external cache */
|
|
wolfSSL_CTX_sess_set_new_cb(ctx, twcase_new_sessionCb);
|
|
wolfSSL_CTX_sess_set_remove_cb(ctx, twcase_remove_sessionCb);
|
|
wolfSSL_CTX_sess_set_get_cb(ctx, twcase_get_sessionCb);
|
|
|
|
/* Require both peers to provide certs */
|
|
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL);
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
static int twcase_cache_intOn_extOn(WOLFSSL_CTX* ctx)
|
|
{
|
|
/* on - internal cache is on by default */
|
|
/* on - Enable external cache */
|
|
wolfSSL_CTX_sess_set_new_cb(ctx, twcase_new_sessionCb);
|
|
wolfSSL_CTX_sess_set_remove_cb(ctx, twcase_remove_sessionCb);
|
|
wolfSSL_CTX_sess_set_get_cb(ctx, twcase_get_sessionCb);
|
|
|
|
/* Require both peers to provide certs */
|
|
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL);
|
|
return TEST_SUCCESS;
|
|
}
|
|
static int twcase_cache_intOn_extOn_noTicket(WOLFSSL_CTX* ctx)
|
|
{
|
|
/* on - internal cache is on by default */
|
|
/* on - Enable external cache */
|
|
wolfSSL_CTX_sess_set_new_cb(ctx, twcase_new_sessionCb);
|
|
wolfSSL_CTX_sess_set_remove_cb(ctx, twcase_remove_sessionCb);
|
|
wolfSSL_CTX_sess_set_get_cb(ctx, twcase_get_sessionCb);
|
|
|
|
wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TICKET);
|
|
/* Require both peers to provide certs */
|
|
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL);
|
|
return TEST_SUCCESS;
|
|
}
|
|
static int twcase_server_sess_ctx_pre_shutdown(WOLFSSL* ssl)
|
|
{
|
|
EXPECT_DECLS;
|
|
WOLFSSL_SESSION** sess;
|
|
if (wolfSSL_is_server(ssl))
|
|
sess = &twcase_server_first_session_ptr;
|
|
else
|
|
return TEST_SUCCESS;
|
|
|
|
if (*sess == NULL) {
|
|
ExpectNotNull(*sess = wolfSSL_get1_session(ssl));
|
|
/* Now save the session in the internal store to make it available
|
|
* for lookup. For TLS 1.3, we can't save the session without
|
|
* WOLFSSL_TICKET_HAVE_ID because there is no way to retrieve the
|
|
* session from cache. */
|
|
if (wolfSSL_is_server(ssl)
|
|
#ifndef WOLFSSL_TICKET_HAVE_ID
|
|
&& wolfSSL_version(ssl) != TLS1_3_VERSION
|
|
&& wolfSSL_version(ssl) != DTLS1_3_VERSION
|
|
#endif
|
|
) {
|
|
ExpectIntEQ(wolfSSL_CTX_add_session(wolfSSL_get_SSL_CTX(ssl),
|
|
*sess), WOLFSSL_SUCCESS);
|
|
}
|
|
}
|
|
/* Save CTX to be able to decrypt tickets */
|
|
if (twcase_server_current_ctx_ptr == NULL) {
|
|
ExpectNotNull(twcase_server_current_ctx_ptr = wolfSSL_get_SSL_CTX(ssl));
|
|
ExpectIntEQ(wolfSSL_CTX_up_ref(wolfSSL_get_SSL_CTX(ssl)),
|
|
WOLFSSL_SUCCESS);
|
|
}
|
|
#if defined(SESSION_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
|
|
#ifndef WOLFSSL_TICKET_HAVE_ID
|
|
if (wolfSSL_version(ssl) != TLS1_3_VERSION &&
|
|
wolfSSL_session_reused(ssl))
|
|
#endif
|
|
{
|
|
/* With WOLFSSL_TICKET_HAVE_ID the peer certs should be available
|
|
* for all connections. TLS 1.3 only has tickets so if we don't
|
|
* include the session id in the ticket then the certificates
|
|
* will not be available on resumption. */
|
|
#ifdef KEEP_PEER_CERT
|
|
WOLFSSL_X509* peer = NULL;
|
|
ExpectNotNull(peer = wolfSSL_get_peer_certificate(ssl));
|
|
wolfSSL_X509_free(peer);
|
|
#endif
|
|
ExpectNotNull(wolfSSL_SESSION_get_peer_chain(*sess));
|
|
}
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
static int twcase_client_sess_ctx_pre_shutdown(WOLFSSL* ssl)
|
|
{
|
|
EXPECT_DECLS;
|
|
WOLFSSL_SESSION** sess;
|
|
sess = &twcase_client_first_session_ptr;
|
|
if (*sess == NULL) {
|
|
ExpectNotNull(*sess = wolfSSL_get1_session(ssl));
|
|
}
|
|
else {
|
|
/* If we have a session retrieved then remaining connections should be
|
|
* resuming on that session */
|
|
ExpectIntEQ(wolfSSL_session_reused(ssl), 1);
|
|
}
|
|
|
|
#if defined(SESSION_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
|
|
#ifndef WOLFSSL_TICKET_HAVE_ID
|
|
if (wolfSSL_version(ssl) != TLS1_3_VERSION &&
|
|
wolfSSL_session_reused(ssl))
|
|
#endif
|
|
{
|
|
#ifdef KEEP_PEER_CERT
|
|
WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl);
|
|
ExpectNotNull(peer);
|
|
wolfSSL_X509_free(peer);
|
|
#endif
|
|
ExpectNotNull(wolfSSL_SESSION_get_peer_chain(*sess));
|
|
#ifdef OPENSSL_EXTRA
|
|
ExpectNotNull(wolfSSL_SESSION_get0_peer(*sess));
|
|
#endif
|
|
}
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
static int twcase_client_set_sess_ssl_ready(WOLFSSL* ssl)
|
|
{
|
|
EXPECT_DECLS;
|
|
/* Set the session to reuse for the client */
|
|
ExpectNotNull(ssl);
|
|
ExpectNotNull(twcase_client_first_session_ptr);
|
|
ExpectIntEQ(wolfSSL_set_session(ssl,twcase_client_first_session_ptr),
|
|
WOLFSSL_SUCCESS);
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
struct test_add_session_ext_params {
|
|
method_provider client_meth;
|
|
method_provider server_meth;
|
|
const char* tls_version;
|
|
};
|
|
|
|
/* Marked WC_MAYBE_UNUSED: each registered test_wolfSSL_CTX_add_session_ext_*
|
|
* variant below calls this helper, but each variant is gated on a specific
|
|
* TLS/DTLS version combination. In builds where no version combination is
|
|
* enabled, the helper is defined but unused. */
|
|
static WC_MAYBE_UNUSED int test_wolfSSL_CTX_add_session_ext(
|
|
struct test_add_session_ext_params* param)
|
|
{
|
|
EXPECT_DECLS;
|
|
/* Test the default 33 sessions */
|
|
int j;
|
|
|
|
/* Clear cache before starting */
|
|
wolfSSL_CTX_flush_sessions(NULL, -1);
|
|
|
|
XMEMSET(&server_sessionCache, 0, sizeof(hashTable));
|
|
if (wc_InitMutex(&server_sessionCache.htLock) != 0)
|
|
return BAD_MUTEX_E;
|
|
server_sessionCache.capacity = SESSION_CACHE_SIZE;
|
|
|
|
fprintf(stderr, "\tBegin %s\n", param->tls_version);
|
|
for (j = 0; j < 5; j++) {
|
|
int tls13 = XSTRSTR(param->tls_version, "TLSv1_3") != NULL;
|
|
int dtls = XSTRSTR(param->tls_version, "DTLS") != NULL;
|
|
test_ssl_cbf client_cb;
|
|
test_ssl_cbf server_cb;
|
|
|
|
(void)dtls;
|
|
|
|
/* Test five cache configurations */
|
|
twcase_client_first_session_ptr = NULL;
|
|
twcase_server_first_session_ptr = NULL;
|
|
twcase_server_current_ctx_ptr = NULL;
|
|
twcase_new_session_called = 0;
|
|
twcase_remove_session_called = 0;
|
|
twcase_get_session_called = 0;
|
|
|
|
/* connection 1 - first connection */
|
|
fprintf(stderr, "\tconnect: %s: j=%d\n", param->tls_version, j);
|
|
|
|
XMEMSET(&client_cb, 0, sizeof(client_cb));
|
|
XMEMSET(&server_cb, 0, sizeof(server_cb));
|
|
client_cb.method = param->client_meth;
|
|
server_cb.method = param->server_meth;
|
|
|
|
if (dtls)
|
|
client_cb.doUdp = server_cb.doUdp = 1;
|
|
|
|
/* Setup internal and external cache */
|
|
switch (j) {
|
|
case 0:
|
|
/* SSL_OP_NO_TICKET stateful ticket case */
|
|
server_cb.ctx_ready = twcase_cache_intOn_extOn_noTicket;
|
|
break;
|
|
case 1:
|
|
server_cb.ctx_ready = twcase_cache_intOn_extOn;
|
|
break;
|
|
case 2:
|
|
server_cb.ctx_ready = twcase_cache_intOff_extOn;
|
|
break;
|
|
case 3:
|
|
server_cb.ctx_ready = twcase_cache_intOn_extOff;
|
|
break;
|
|
case 4:
|
|
server_cb.ctx_ready = twcase_cache_intOff_extOff;
|
|
break;
|
|
}
|
|
client_cb.ctx_ready = twcase_cache_intOff_extOff;
|
|
|
|
/* Add session to internal cache and save SSL session for testing */
|
|
server_cb.on_result = twcase_server_sess_ctx_pre_shutdown;
|
|
/* Save client SSL session for testing */
|
|
client_cb.on_result = twcase_client_sess_ctx_pre_shutdown;
|
|
server_cb.ticNoInit = 1; /* Use default builtin */
|
|
/* Don't free/release ctx */
|
|
server_cb.ctx = twcase_server_current_ctx_ptr;
|
|
server_cb.isSharedCtx = 1;
|
|
|
|
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cb,
|
|
&server_cb, NULL), TEST_SUCCESS);
|
|
|
|
ExpectIntEQ(twcase_get_session_called, 0);
|
|
if (EXPECT_FAIL()) {
|
|
wolfSSL_SESSION_free(twcase_client_first_session_ptr);
|
|
wolfSSL_SESSION_free(twcase_server_first_session_ptr);
|
|
wolfSSL_CTX_free(twcase_server_current_ctx_ptr);
|
|
break;
|
|
}
|
|
|
|
switch (j) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
/* cache cannot be searched with out a connection */
|
|
/* Add a new session */
|
|
ExpectIntEQ(twcase_new_session_called, 1);
|
|
/* In twcase_server_sess_ctx_pre_shutdown
|
|
* wolfSSL_CTX_add_session which evicts the existing session
|
|
* in cache and adds it back in */
|
|
ExpectIntLE(twcase_remove_session_called, 1);
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
/* no external cache */
|
|
ExpectIntEQ(twcase_new_session_called, 0);
|
|
ExpectIntEQ(twcase_remove_session_called, 0);
|
|
break;
|
|
}
|
|
|
|
/* connection 2 - session resume */
|
|
fprintf(stderr, "\tresume: %s: j=%d\n", param->tls_version, j);
|
|
twcase_new_session_called = 0;
|
|
twcase_remove_session_called = 0;
|
|
twcase_get_session_called = 0;
|
|
server_cb.on_result = 0;
|
|
client_cb.on_result = 0;
|
|
server_cb.ticNoInit = 1; /* Use default builtin */
|
|
|
|
server_cb.ctx = twcase_server_current_ctx_ptr;
|
|
|
|
/* try session resumption */
|
|
client_cb.ssl_ready = twcase_client_set_sess_ssl_ready;
|
|
|
|
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cb,
|
|
&server_cb, NULL), TEST_SUCCESS);
|
|
|
|
/* Clear cache before checking */
|
|
wolfSSL_CTX_flush_sessions(NULL, -1);
|
|
|
|
switch (j) {
|
|
case 0:
|
|
if (tls13) {
|
|
/* (D)TLSv1.3 stateful case */
|
|
/* cache hit */
|
|
/* DTLS accesses cache once for stateless parsing and
|
|
* once for stateful parsing */
|
|
ExpectIntEQ(twcase_get_session_called, !dtls ? 1 : 2);
|
|
|
|
/* (D)TLSv1.3 creates a new ticket,
|
|
* updates both internal and external cache */
|
|
ExpectIntEQ(twcase_new_session_called, 1);
|
|
/* A new session ID is created for a new ticket */
|
|
ExpectIntEQ(twcase_remove_session_called, 2);
|
|
|
|
}
|
|
else {
|
|
/* non (D)TLSv1.3 case, no update */
|
|
/* DTLS accesses cache once for stateless parsing and
|
|
* once for stateful parsing */
|
|
#ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME
|
|
ExpectIntEQ(twcase_get_session_called, !dtls ? 1 : 2);
|
|
#else
|
|
ExpectIntEQ(twcase_get_session_called, 1);
|
|
#endif
|
|
ExpectIntEQ(twcase_new_session_called, 0);
|
|
/* Called on session added in
|
|
* twcase_server_sess_ctx_pre_shutdown */
|
|
ExpectIntEQ(twcase_remove_session_called, 1);
|
|
}
|
|
break;
|
|
case 1:
|
|
if (tls13) {
|
|
/* (D)TLSv1.3 case */
|
|
/* cache hit */
|
|
ExpectIntEQ(twcase_get_session_called, 1);
|
|
/* (D)TLSv1.3 creates a new ticket,
|
|
* updates both internal and external cache */
|
|
ExpectIntEQ(twcase_new_session_called, 1);
|
|
/* Called on session added in
|
|
* twcase_server_sess_ctx_pre_shutdown and by wolfSSL */
|
|
ExpectIntEQ(twcase_remove_session_called, 1);
|
|
}
|
|
else {
|
|
/* non (D)TLSv1.3 case */
|
|
/* cache hit */
|
|
/* DTLS accesses cache once for stateless parsing and
|
|
* once for stateful parsing */
|
|
#ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME
|
|
ExpectIntEQ(twcase_get_session_called, !dtls ? 1 : 2);
|
|
#else
|
|
ExpectIntEQ(twcase_get_session_called, 1);
|
|
#endif
|
|
ExpectIntEQ(twcase_new_session_called, 0);
|
|
/* Called on session added in
|
|
* twcase_server_sess_ctx_pre_shutdown */
|
|
ExpectIntEQ(twcase_remove_session_called, 1);
|
|
}
|
|
break;
|
|
case 2:
|
|
if (tls13) {
|
|
/* (D)TLSv1.3 case */
|
|
/* cache hit */
|
|
ExpectIntEQ(twcase_get_session_called, 1);
|
|
/* (D)TLSv1.3 creates a new ticket,
|
|
* updates both internal and external cache */
|
|
ExpectIntEQ(twcase_new_session_called, 1);
|
|
/* Called on session added in
|
|
* twcase_server_sess_ctx_pre_shutdown and by wolfSSL */
|
|
ExpectIntEQ(twcase_remove_session_called, 1);
|
|
}
|
|
else {
|
|
/* non (D)TLSv1.3 case */
|
|
/* cache hit */
|
|
/* DTLS accesses cache once for stateless parsing and
|
|
* once for stateful parsing */
|
|
#ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME
|
|
ExpectIntEQ(twcase_get_session_called, !dtls ? 1 : 2);
|
|
#else
|
|
ExpectIntEQ(twcase_get_session_called, 1);
|
|
#endif
|
|
ExpectIntEQ(twcase_new_session_called, 0);
|
|
/* Called on session added in
|
|
* twcase_server_sess_ctx_pre_shutdown */
|
|
ExpectIntEQ(twcase_remove_session_called, 1);
|
|
}
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
/* no external cache */
|
|
ExpectIntEQ(twcase_get_session_called, 0);
|
|
ExpectIntEQ(twcase_new_session_called, 0);
|
|
ExpectIntEQ(twcase_remove_session_called, 0);
|
|
break;
|
|
}
|
|
wolfSSL_SESSION_free(twcase_client_first_session_ptr);
|
|
wolfSSL_SESSION_free(twcase_server_first_session_ptr);
|
|
wolfSSL_CTX_free(twcase_server_current_ctx_ptr);
|
|
|
|
if (EXPECT_FAIL())
|
|
break;
|
|
}
|
|
twcase_get_sessionCb_cleanup();
|
|
XMEMSET(&server_sessionCache.entries, 0,
|
|
sizeof(server_sessionCache.entries));
|
|
fprintf(stderr, "\tEnd %s\n", param->tls_version);
|
|
|
|
wc_FreeMutex(&server_sessionCache.htLock);
|
|
|
|
return EXPECT_RESULT();
|
|
}
|
|
#endif
|
|
|
|
int test_wolfSSL_CTX_add_session_ext_tls13(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \
|
|
defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \
|
|
defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \
|
|
defined(HAVE_SESSION_TICKET) && \
|
|
!defined(TITAN_SESSION_CACHE) && \
|
|
!defined(HUGE_SESSION_CACHE) && \
|
|
!defined(BIG_SESSION_CACHE) && \
|
|
!defined(MEDIUM_SESSION_CACHE)
|
|
#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \
|
|
defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TICKET_HAVE_ID)
|
|
struct test_add_session_ext_params param[1] = {
|
|
{ wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, "TLSv1_3" }
|
|
};
|
|
ExpectIntEQ(test_wolfSSL_CTX_add_session_ext(param), TEST_SUCCESS);
|
|
#endif
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
int test_wolfSSL_CTX_add_session_ext_dtls13(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \
|
|
defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \
|
|
defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \
|
|
defined(HAVE_SESSION_TICKET) && \
|
|
!defined(TITAN_SESSION_CACHE) && \
|
|
!defined(HUGE_SESSION_CACHE) && \
|
|
!defined(BIG_SESSION_CACHE) && \
|
|
!defined(MEDIUM_SESSION_CACHE)
|
|
#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \
|
|
defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TICKET_HAVE_ID)
|
|
#ifdef WOLFSSL_DTLS13
|
|
struct test_add_session_ext_params param[1] = {
|
|
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, "DTLSv1_3" }
|
|
};
|
|
ExpectIntEQ(test_wolfSSL_CTX_add_session_ext(param), TEST_SUCCESS);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
int test_wolfSSL_CTX_add_session_ext_tls12(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \
|
|
defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \
|
|
defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \
|
|
defined(HAVE_SESSION_TICKET) && \
|
|
!defined(TITAN_SESSION_CACHE) && \
|
|
!defined(HUGE_SESSION_CACHE) && \
|
|
!defined(BIG_SESSION_CACHE) && \
|
|
!defined(MEDIUM_SESSION_CACHE)
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
struct test_add_session_ext_params param[1] = {
|
|
{ wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, "TLSv1_2" }
|
|
};
|
|
ExpectIntEQ(test_wolfSSL_CTX_add_session_ext(param), TEST_SUCCESS);
|
|
#endif
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
int test_wolfSSL_CTX_add_session_ext_dtls12(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \
|
|
defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \
|
|
defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \
|
|
defined(HAVE_SESSION_TICKET) && \
|
|
!defined(TITAN_SESSION_CACHE) && \
|
|
!defined(HUGE_SESSION_CACHE) && \
|
|
!defined(BIG_SESSION_CACHE) && \
|
|
!defined(MEDIUM_SESSION_CACHE)
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
#ifdef WOLFSSL_DTLS
|
|
struct test_add_session_ext_params param[1] = {
|
|
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, "DTLSv1_2" }
|
|
};
|
|
ExpectIntEQ(test_wolfSSL_CTX_add_session_ext(param), TEST_SUCCESS);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
int test_wolfSSL_CTX_add_session_ext_tls11(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \
|
|
defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \
|
|
defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \
|
|
defined(HAVE_SESSION_TICKET) && \
|
|
!defined(TITAN_SESSION_CACHE) && \
|
|
!defined(HUGE_SESSION_CACHE) && \
|
|
!defined(BIG_SESSION_CACHE) && \
|
|
!defined(MEDIUM_SESSION_CACHE)
|
|
#if !defined(NO_OLD_TLS) && ((!defined(NO_AES) && !defined(NO_AES_CBC)) || \
|
|
!defined(NO_DES3))
|
|
struct test_add_session_ext_params param[1] = {
|
|
{ wolfTLSv1_1_client_method, wolfTLSv1_1_server_method, "TLSv1_1" }
|
|
};
|
|
ExpectIntEQ(test_wolfSSL_CTX_add_session_ext(param), TEST_SUCCESS);
|
|
#endif
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
int test_wolfSSL_CTX_add_session_ext_dtls1(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \
|
|
defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \
|
|
defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \
|
|
defined(HAVE_SESSION_TICKET) && \
|
|
!defined(TITAN_SESSION_CACHE) && \
|
|
!defined(HUGE_SESSION_CACHE) && \
|
|
!defined(BIG_SESSION_CACHE) && \
|
|
!defined(MEDIUM_SESSION_CACHE)
|
|
#if !defined(NO_OLD_TLS) && ((!defined(NO_AES) && !defined(NO_AES_CBC)) || \
|
|
!defined(NO_DES3))
|
|
#ifdef WOLFSSL_DTLS
|
|
struct test_add_session_ext_params param[1] = {
|
|
{ wolfDTLSv1_client_method, wolfDTLSv1_server_method, "DTLSv1_0" }
|
|
};
|
|
ExpectIntEQ(test_wolfSSL_CTX_add_session_ext(param), TEST_SUCCESS);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/* WOLFSSL_SESSION, ticket keys and session removal callbacks */
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
int test_wolfSSL_SESSION(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \
|
|
!defined(NO_RSA) && !defined(NO_SHA256) && \
|
|
defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(NO_SESSION_CACHE)
|
|
WOLFSSL* ssl = NULL;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL_SESSION* sess = NULL;
|
|
WOLFSSL_SESSION* sess_copy = NULL;
|
|
#ifdef OPENSSL_EXTRA
|
|
#ifdef HAVE_EXT_CACHE
|
|
unsigned char* sessDer = NULL;
|
|
unsigned char* ptr = NULL;
|
|
int sz = 0;
|
|
#endif
|
|
const unsigned char context[] = "user app context";
|
|
unsigned int contextSz = (unsigned int)sizeof(context);
|
|
#endif
|
|
int ret = 0, err = 0;
|
|
SOCKET_T sockfd;
|
|
tcp_ready ready;
|
|
func_args server_args;
|
|
THREAD_TYPE serverThread;
|
|
char msg[80];
|
|
const char* sendGET = "GET";
|
|
|
|
/* TLS v1.3 requires session tickets */
|
|
/* CHACHA and POLY1305 required for myTicketEncCb */
|
|
#if !defined(WOLFSSL_NO_TLS12) && (!defined(WOLFSSL_TLS13) || \
|
|
!(defined(HAVE_SESSION_TICKET) && ((defined(HAVE_CHACHA) && \
|
|
defined(HAVE_POLY1305)) || defined(HAVE_AESGCM))))
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()));
|
|
#else
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
|
#endif
|
|
|
|
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, cliCertFile,
|
|
CERT_FILETYPE));
|
|
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile,
|
|
CERT_FILETYPE));
|
|
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0),
|
|
WOLFSSL_SUCCESS);
|
|
#ifdef WOLFSSL_ENCRYPTED_KEYS
|
|
wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
|
|
#endif
|
|
#ifdef HAVE_SESSION_TICKET
|
|
/* Use session tickets, for ticket tests below */
|
|
ExpectIntEQ(wolfSSL_CTX_UseSessionTicket(ctx), WOLFSSL_SUCCESS);
|
|
#endif
|
|
|
|
XMEMSET(&server_args, 0, sizeof(func_args));
|
|
#ifdef WOLFSSL_TIRTOS
|
|
fdOpenSession(Task_self());
|
|
#endif
|
|
|
|
StartTCP();
|
|
InitTcpReady(&ready);
|
|
|
|
server_args.signal = &ready;
|
|
start_thread(test_server_nofail, &server_args, &serverThread);
|
|
wait_tcp_ready(&server_args);
|
|
|
|
/* client connection */
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
tcp_connect(&sockfd, wolfSSLIP, ready.port, 0, 0, ssl);
|
|
ExpectIntEQ(wolfSSL_set_fd(ssl, sockfd), WOLFSSL_SUCCESS);
|
|
|
|
WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_connect(ssl),
|
|
ret != WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(ret, WOLFSSL_SUCCESS);
|
|
|
|
WOLFSSL_ASYNC_WHILE_PENDING(
|
|
ret = wolfSSL_write(ssl, sendGET, (int)XSTRLEN(sendGET)),
|
|
ret <= 0);
|
|
ExpectIntEQ(ret, (int)XSTRLEN(sendGET));
|
|
|
|
WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_read(ssl, msg, sizeof(msg)),
|
|
ret != 23);
|
|
ExpectIntEQ(ret, 23);
|
|
|
|
ExpectPtrNE((sess = wolfSSL_get1_session(ssl)), NULL); /* ref count 1 */
|
|
ExpectPtrNE((sess_copy = wolfSSL_get1_session(ssl)), NULL); /* ref count 2 */
|
|
ExpectIntEQ(wolfSSL_SessionIsSetup(sess), 1);
|
|
#ifdef HAVE_EXT_CACHE
|
|
ExpectPtrEq(sess, sess_copy); /* they should be the same pointer but without
|
|
* HAVE_EXT_CACHE we get new objects each time */
|
|
#endif
|
|
wolfSSL_SESSION_free(sess_copy); sess_copy = NULL;
|
|
wolfSSL_SESSION_free(sess); sess = NULL; /* free session ref */
|
|
|
|
sess = wolfSSL_get_session(ssl);
|
|
|
|
#ifdef OPENSSL_EXTRA
|
|
ExpectIntEQ(SSL_SESSION_is_resumable(NULL), 0);
|
|
ExpectIntEQ(SSL_SESSION_is_resumable(sess), 1);
|
|
|
|
ExpectIntEQ(wolfSSL_SESSION_has_ticket(NULL), 0);
|
|
ExpectIntEQ(wolfSSL_SESSION_get_ticket_lifetime_hint(NULL), 0);
|
|
#ifdef HAVE_SESSION_TICKET
|
|
ExpectIntEQ(wolfSSL_SESSION_has_ticket(sess), 1);
|
|
ExpectIntEQ(wolfSSL_SESSION_get_ticket_lifetime_hint(sess),
|
|
SESSION_TICKET_HINT_DEFAULT);
|
|
#else
|
|
ExpectIntEQ(wolfSSL_SESSION_has_ticket(sess), 0);
|
|
#endif
|
|
#else
|
|
(void)sess;
|
|
#endif /* OPENSSL_EXTRA */
|
|
|
|
/* Retain copy of the session for later testing */
|
|
ExpectNotNull(sess = wolfSSL_get1_session(ssl));
|
|
|
|
wolfSSL_shutdown(ssl);
|
|
wolfSSL_free(ssl); ssl = NULL;
|
|
|
|
CloseSocket(sockfd);
|
|
|
|
join_thread(serverThread);
|
|
|
|
FreeTcpReady(&ready);
|
|
|
|
#ifdef WOLFSSL_TIRTOS
|
|
fdOpenSession(Task_self());
|
|
#endif
|
|
|
|
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
|
|
{
|
|
X509 *x509 = NULL;
|
|
char buf[30];
|
|
int bufSz = 0;
|
|
|
|
ExpectNotNull(x509 = SSL_SESSION_get0_peer(sess));
|
|
ExpectIntGT((bufSz = X509_NAME_get_text_by_NID(
|
|
X509_get_subject_name(x509), NID_organizationalUnitName, buf,
|
|
sizeof(buf))), 0);
|
|
ExpectIntNE((bufSz == 7 || bufSz == 16), 0); /* should be one of these*/
|
|
if (bufSz == 7) {
|
|
ExpectIntEQ(XMEMCMP(buf, "Support", bufSz), 0);
|
|
}
|
|
if (bufSz == 16) {
|
|
ExpectIntEQ(XMEMCMP(buf, "Programming-2048", bufSz), 0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_EXT_CACHE
|
|
ExpectNotNull(sess_copy = wolfSSL_SESSION_dup(sess));
|
|
wolfSSL_SESSION_free(sess_copy); sess_copy = NULL;
|
|
sess_copy = NULL;
|
|
#endif
|
|
|
|
#if defined(OPENSSL_EXTRA) && defined(HAVE_EXT_CACHE)
|
|
/* get session from DER and update the timeout */
|
|
ExpectIntEQ(wolfSSL_i2d_SSL_SESSION(NULL, &sessDer), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntGT((sz = wolfSSL_i2d_SSL_SESSION(sess, &sessDer)), 0);
|
|
wolfSSL_SESSION_free(sess); sess = NULL;
|
|
sess = NULL;
|
|
ptr = sessDer;
|
|
ExpectNull(sess = wolfSSL_d2i_SSL_SESSION(NULL, NULL, sz));
|
|
ExpectNotNull(sess = wolfSSL_d2i_SSL_SESSION(NULL,
|
|
(const unsigned char**)&ptr, sz));
|
|
XFREE(sessDer, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
sessDer = NULL;
|
|
|
|
ExpectIntGT(wolfSSL_SESSION_get_time(sess), 0);
|
|
ExpectIntEQ(wolfSSL_SSL_SESSION_set_timeout(sess, 500), SSL_SUCCESS);
|
|
#endif
|
|
|
|
/* successful set session test */
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
ExpectIntEQ(wolfSSL_set_session(ssl, sess), WOLFSSL_SUCCESS);
|
|
|
|
#ifdef HAVE_SESSION_TICKET
|
|
/* Test set/get session ticket */
|
|
{
|
|
const char* ticket = "This is a session ticket";
|
|
char buf[64] = {0};
|
|
word32 bufSz = (word32)sizeof(buf);
|
|
word32 retSz = 0;
|
|
|
|
ExpectIntEQ(WOLFSSL_SUCCESS,
|
|
wolfSSL_set_SessionTicket(ssl, (byte *)ticket,
|
|
(word32)XSTRLEN(ticket)));
|
|
ExpectIntEQ(WOLFSSL_SUCCESS,
|
|
wolfSSL_get_SessionTicket(ssl, (byte *)buf, &bufSz));
|
|
ExpectStrEQ(ticket, buf);
|
|
|
|
/* return ticket length if buffer parameter is null */
|
|
wolfSSL_get_SessionTicket(ssl, NULL, &retSz);
|
|
ExpectIntEQ(bufSz, retSz);
|
|
}
|
|
#endif
|
|
|
|
#ifdef OPENSSL_EXTRA
|
|
/* session timeout case */
|
|
/* make the session to be expired */
|
|
ExpectIntEQ(SSL_SESSION_set_timeout(sess,1), SSL_SUCCESS);
|
|
XSLEEP_MS(1200);
|
|
|
|
/* SSL_set_session should reject specified session but return success
|
|
* if WOLFSSL_ERROR_CODE_OPENSSL macro is defined for OpenSSL compatibility.
|
|
*/
|
|
#if defined(WOLFSSL_ERROR_CODE_OPENSSL)
|
|
ExpectIntEQ(wolfSSL_set_session(ssl,sess), SSL_SUCCESS);
|
|
#else
|
|
ExpectIntEQ(wolfSSL_set_session(ssl,sess), WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_SSL_SESSION_set_timeout(sess, 500), SSL_SUCCESS);
|
|
|
|
#ifdef WOLFSSL_SESSION_ID_CTX
|
|
/* fail case with miss match session context IDs (use compatibility API) */
|
|
ExpectIntEQ(SSL_set_session_id_context(ssl, context, contextSz),
|
|
SSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_set_session(ssl, sess), WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
wolfSSL_free(ssl); ssl = NULL;
|
|
|
|
ExpectIntEQ(SSL_CTX_set_session_id_context(NULL, context, contextSz),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(SSL_CTX_set_session_id_context(ctx, context, contextSz),
|
|
SSL_SUCCESS);
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
ExpectIntEQ(wolfSSL_set_session(ssl, sess), WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
#endif
|
|
#endif /* OPENSSL_EXTRA */
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_SESSION_free(sess);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \
|
|
!defined(NO_RSA) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \
|
|
!defined(NO_SESSION_CACHE) && defined(OPENSSL_EXTRA) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
static WOLFSSL_SESSION* test_wolfSSL_SESSION_expire_sess = NULL;
|
|
|
|
static void test_wolfSSL_SESSION_expire_downgrade_ctx_ready(WOLFSSL_CTX* ctx)
|
|
{
|
|
#ifdef WOLFSSL_ERROR_CODE_OPENSSL
|
|
/* returns previous timeout value */
|
|
AssertIntEQ(wolfSSL_CTX_set_timeout(ctx, 1), 500);
|
|
#else
|
|
AssertIntEQ(wolfSSL_CTX_set_timeout(ctx, 1), WOLFSSL_SUCCESS);
|
|
#endif
|
|
}
|
|
|
|
|
|
/* set the session to timeout in a second */
|
|
static void test_wolfSSL_SESSION_expire_downgrade_ssl_ready(WOLFSSL* ssl)
|
|
{
|
|
AssertIntEQ(wolfSSL_set_timeout(ssl, 2), 1);
|
|
}
|
|
|
|
|
|
/* store the client side session from the first successful connection */
|
|
static void test_wolfSSL_SESSION_expire_downgrade_ssl_result(WOLFSSL* ssl)
|
|
{
|
|
AssertPtrNE((test_wolfSSL_SESSION_expire_sess = wolfSSL_get1_session(ssl)),
|
|
NULL); /* ref count 1 */
|
|
}
|
|
|
|
|
|
/* wait till session is expired then set it in the WOLFSSL struct for use */
|
|
static void test_wolfSSL_SESSION_expire_downgrade_ssl_ready_wait(WOLFSSL* ssl)
|
|
{
|
|
AssertIntEQ(wolfSSL_set_timeout(ssl, 1), 1);
|
|
AssertIntEQ(wolfSSL_set_session(ssl, test_wolfSSL_SESSION_expire_sess),
|
|
WOLFSSL_SUCCESS);
|
|
XSLEEP_MS(2000); /* wait 2 seconds for session to expire */
|
|
}
|
|
|
|
|
|
/* set expired session in the WOLFSSL struct for use */
|
|
static void test_wolfSSL_SESSION_expire_downgrade_ssl_ready_set(WOLFSSL* ssl)
|
|
{
|
|
XSLEEP_MS(1200); /* wait a second for session to expire */
|
|
|
|
/* set the expired session, call to set session fails but continuing on
|
|
after failure should be handled here */
|
|
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_ERROR_CODE_OPENSSL)
|
|
AssertIntEQ(wolfSSL_set_session(ssl, test_wolfSSL_SESSION_expire_sess),
|
|
WOLFSSL_SUCCESS);
|
|
#else
|
|
AssertIntNE(wolfSSL_set_session(ssl, test_wolfSSL_SESSION_expire_sess),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
}
|
|
|
|
|
|
/* check that the expired session was not reused */
|
|
static void test_wolfSSL_SESSION_expire_downgrade_ssl_result_reuse(WOLFSSL* ssl)
|
|
{
|
|
/* since the session has expired it should not have been reused */
|
|
AssertIntEQ(wolfSSL_session_reused(ssl), 0);
|
|
}
|
|
#endif
|
|
|
|
int test_wolfSSL_SESSION_expire_downgrade(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \
|
|
!defined(NO_RSA) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \
|
|
!defined(NO_SESSION_CACHE) && defined(OPENSSL_EXTRA) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
callback_functions server_cbf, client_cbf;
|
|
|
|
XMEMSET(&server_cbf, 0, sizeof(callback_functions));
|
|
XMEMSET(&client_cbf, 0, sizeof(callback_functions));
|
|
|
|
/* force server side to use TLS 1.2 */
|
|
server_cbf.method = wolfTLSv1_2_server_method;
|
|
|
|
client_cbf.method = wolfSSLv23_client_method;
|
|
server_cbf.ctx_ready = test_wolfSSL_SESSION_expire_downgrade_ctx_ready;
|
|
client_cbf.ssl_ready = test_wolfSSL_SESSION_expire_downgrade_ssl_ready;
|
|
client_cbf.on_result = test_wolfSSL_SESSION_expire_downgrade_ssl_result;
|
|
|
|
test_wolfSSL_client_server_nofail(&client_cbf, &server_cbf);
|
|
ExpectIntEQ(client_cbf.return_code, TEST_SUCCESS);
|
|
ExpectIntEQ(server_cbf.return_code, TEST_SUCCESS);
|
|
|
|
client_cbf.method = wolfSSLv23_client_method;
|
|
server_cbf.ctx_ready = test_wolfSSL_SESSION_expire_downgrade_ctx_ready;
|
|
client_cbf.ssl_ready = test_wolfSSL_SESSION_expire_downgrade_ssl_ready_wait;
|
|
client_cbf.on_result =
|
|
test_wolfSSL_SESSION_expire_downgrade_ssl_result_reuse;
|
|
|
|
test_wolfSSL_client_server_nofail(&client_cbf, &server_cbf);
|
|
ExpectIntEQ(client_cbf.return_code, TEST_SUCCESS);
|
|
ExpectIntEQ(server_cbf.return_code, TEST_SUCCESS);
|
|
|
|
client_cbf.method = wolfSSLv23_client_method;
|
|
server_cbf.ctx_ready = test_wolfSSL_SESSION_expire_downgrade_ctx_ready;
|
|
client_cbf.ssl_ready = test_wolfSSL_SESSION_expire_downgrade_ssl_ready_set;
|
|
client_cbf.on_result =
|
|
test_wolfSSL_SESSION_expire_downgrade_ssl_result_reuse;
|
|
|
|
test_wolfSSL_client_server_nofail(&client_cbf, &server_cbf);
|
|
ExpectIntEQ(client_cbf.return_code, TEST_SUCCESS);
|
|
ExpectIntEQ(server_cbf.return_code, TEST_SUCCESS);
|
|
|
|
wolfSSL_SESSION_free(test_wolfSSL_SESSION_expire_sess);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
#if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
defined(HAVE_EX_DATA) && !defined(NO_SESSION_CACHE)
|
|
#ifdef WOLFSSL_ATOMIC_OPS
|
|
typedef wolfSSL_Atomic_Int SessRemCounter_t;
|
|
#else
|
|
typedef int SessRemCounter_t;
|
|
#endif
|
|
static SessRemCounter_t clientSessRemCountMalloc;
|
|
static SessRemCounter_t serverSessRemCountMalloc;
|
|
static SessRemCounter_t clientSessRemCountFree;
|
|
static SessRemCounter_t serverSessRemCountFree;
|
|
|
|
static WOLFSSL_CTX* serverSessCtx = NULL;
|
|
static WOLFSSL_SESSION* serverSess = NULL;
|
|
#if (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) || \
|
|
!defined(NO_SESSION_CACHE_REF)
|
|
static WOLFSSL_CTX* clientSessCtx = NULL;
|
|
static WOLFSSL_SESSION* clientSess = NULL;
|
|
#endif
|
|
static int serverSessRemIdx = 3;
|
|
static int sessRemCtx_Server = WOLFSSL_SERVER_END;
|
|
static int sessRemCtx_Client = WOLFSSL_CLIENT_END;
|
|
|
|
static void SessRemCtxCb(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *sess)
|
|
{
|
|
int* side;
|
|
|
|
(void)ctx;
|
|
|
|
side = (int*)SSL_SESSION_get_ex_data(sess, serverSessRemIdx);
|
|
if (side != NULL) {
|
|
if (*side == WOLFSSL_CLIENT_END)
|
|
(void)wolfSSL_Atomic_Int_FetchAdd(&clientSessRemCountFree, 1);
|
|
else
|
|
(void)wolfSSL_Atomic_Int_FetchAdd(&serverSessRemCountFree, 1);
|
|
|
|
SSL_SESSION_set_ex_data(sess, serverSessRemIdx, NULL);
|
|
}
|
|
}
|
|
|
|
static int SessRemCtxSetupCb(WOLFSSL_CTX* ctx)
|
|
{
|
|
SSL_CTX_sess_set_remove_cb(ctx, SessRemCtxCb);
|
|
#if defined(WOLFSSL_TLS13) && !defined(HAVE_SESSION_TICKET) && \
|
|
!defined(NO_SESSION_CACHE_REF)
|
|
{
|
|
EXPECT_DECLS;
|
|
/* Allow downgrade, set min version, and disable TLS 1.3.
|
|
* Do this because without NO_SESSION_CACHE_REF we will want to return a
|
|
* reference to the session cache. But with WOLFSSL_TLS13 and without
|
|
* HAVE_SESSION_TICKET we won't have a session ID to be able to place
|
|
* the session in the cache. In this case we need to downgrade to
|
|
* previous versions to just use the legacy session ID field. */
|
|
ExpectIntEQ(SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION),
|
|
SSL_SUCCESS);
|
|
ExpectIntEQ(SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION),
|
|
SSL_SUCCESS);
|
|
return EXPECT_RESULT();
|
|
}
|
|
#else
|
|
return TEST_SUCCESS;
|
|
#endif
|
|
}
|
|
|
|
static int SessRemSslSetupCb(WOLFSSL* ssl)
|
|
{
|
|
EXPECT_DECLS;
|
|
int* side;
|
|
|
|
if (SSL_is_server(ssl)) {
|
|
side = &sessRemCtx_Server;
|
|
(void)wolfSSL_Atomic_Int_FetchAdd(&serverSessRemCountMalloc, 1);
|
|
ExpectNotNull(serverSess = SSL_get1_session(ssl));
|
|
ExpectIntEQ(SSL_CTX_up_ref(serverSessCtx = SSL_get_SSL_CTX(ssl)),
|
|
SSL_SUCCESS);
|
|
}
|
|
else {
|
|
side = &sessRemCtx_Client;
|
|
(void)wolfSSL_Atomic_Int_FetchAdd(&clientSessRemCountMalloc, 1);
|
|
#if (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) || \
|
|
!defined(NO_SESSION_CACHE_REF)
|
|
ExpectNotNull(clientSess = SSL_get1_session(ssl));
|
|
ExpectIntEQ(SSL_CTX_up_ref(clientSessCtx = SSL_get_SSL_CTX(ssl)),
|
|
SSL_SUCCESS);
|
|
#endif
|
|
}
|
|
ExpectIntEQ(SSL_SESSION_set_ex_data(SSL_get_session(ssl),
|
|
serverSessRemIdx, side), SSL_SUCCESS);
|
|
|
|
return EXPECT_RESULT();
|
|
}
|
|
#endif
|
|
|
|
int test_wolfSSL_CTX_sess_set_remove_cb(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
defined(HAVE_EX_DATA) && !defined(NO_SESSION_CACHE)
|
|
/* Check that the remove callback gets called for external data in a
|
|
* session object */
|
|
test_ssl_cbf func_cb;
|
|
|
|
wolfSSL_Atomic_Int_Init(&clientSessRemCountMalloc, 0);
|
|
wolfSSL_Atomic_Int_Init(&serverSessRemCountMalloc, 0);
|
|
wolfSSL_Atomic_Int_Init(&clientSessRemCountFree, 0);
|
|
wolfSSL_Atomic_Int_Init(&serverSessRemCountFree, 0);
|
|
|
|
XMEMSET(&func_cb, 0, sizeof(func_cb));
|
|
func_cb.ctx_ready = SessRemCtxSetupCb;
|
|
func_cb.on_result = SessRemSslSetupCb;
|
|
|
|
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb, &func_cb,
|
|
NULL), TEST_SUCCESS);
|
|
|
|
/* Both should have been allocated */
|
|
ExpectIntEQ(clientSessRemCountMalloc, 1);
|
|
ExpectIntEQ(serverSessRemCountMalloc, 1);
|
|
|
|
/* This should not be called yet. Session wasn't evicted from cache yet. */
|
|
ExpectIntEQ(clientSessRemCountFree, 0);
|
|
#if (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) || \
|
|
!defined(NO_SESSION_CACHE_REF)
|
|
/* Force a cache lookup */
|
|
ExpectNotNull(SSL_SESSION_get_ex_data(clientSess, serverSessRemIdx));
|
|
/* Force a cache update */
|
|
ExpectNotNull(SSL_SESSION_set_ex_data(clientSess, serverSessRemIdx - 1, 0));
|
|
/* This should set the timeout to 0 and call the remove callback from within
|
|
* the session cache. Returns 1 per OpenSSL semantics (session was
|
|
* present in the cache and removed). */
|
|
ExpectIntEQ(SSL_CTX_remove_session(clientSessCtx, clientSess), 1);
|
|
ExpectNull(SSL_SESSION_get_ex_data(clientSess, serverSessRemIdx));
|
|
ExpectIntEQ(clientSessRemCountFree, 1);
|
|
#endif
|
|
/* Server session is in the cache so ex_data isn't free'd with the SSL
|
|
* object */
|
|
ExpectIntEQ(serverSessRemCountFree, 0);
|
|
/* Force a cache lookup */
|
|
ExpectNotNull(SSL_SESSION_get_ex_data(serverSess, serverSessRemIdx));
|
|
/* Force a cache update */
|
|
ExpectNotNull(SSL_SESSION_set_ex_data(serverSess, serverSessRemIdx - 1, 0));
|
|
/* This should set the timeout to 0 and call the remove callback from within
|
|
* the session cache. Returns 1 per OpenSSL semantics (session was
|
|
* present in the cache and removed). */
|
|
ExpectIntEQ(SSL_CTX_remove_session(serverSessCtx, serverSess), 1);
|
|
ExpectNull(SSL_SESSION_get_ex_data(serverSess, serverSessRemIdx));
|
|
ExpectIntEQ(serverSessRemCountFree, 1);
|
|
/* Need to free the references that we kept */
|
|
SSL_CTX_free(serverSessCtx);
|
|
SSL_SESSION_free(serverSess);
|
|
#if (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) || \
|
|
!defined(NO_SESSION_CACHE_REF)
|
|
SSL_CTX_free(clientSessCtx);
|
|
SSL_SESSION_free(clientSess);
|
|
#endif
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_ticket_keys(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \
|
|
!defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
byte keys[WOLFSSL_TICKET_KEYS_SZ];
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
|
|
ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(NULL, NULL, 0),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(ctx, NULL, 0),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(ctx, keys, 0),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(NULL, keys, 0),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(NULL, NULL, sizeof(keys)),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(ctx, NULL, sizeof(keys)),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(NULL, keys, sizeof(keys)),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
|
|
ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(NULL, NULL, 0),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(ctx, NULL, 0),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(ctx, keys, 0),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(NULL, keys, 0),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(NULL, NULL, sizeof(keys)),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(ctx, NULL, sizeof(keys)),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(NULL, keys, sizeof(keys)),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
|
|
ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(ctx, keys, sizeof(keys)),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(ctx, keys, sizeof(keys)),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/* SESSION ex_data new index */
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
#if defined(HAVE_EX_DATA_CRYPTO) && defined(OPENSSL_EXTRA)
|
|
|
|
#define SESSION_NEW_IDX_LONG 0xDEADBEEF
|
|
#define SESSION_NEW_IDX_VAL ((void*)0xAEADAEAD)
|
|
#define SESSION_DUP_IDX_VAL ((void*)0xDEDEDEDE)
|
|
#define SESSION_NEW_IDX_PTR "Testing"
|
|
|
|
static void test_wolfSSL_SESSION_get_ex_new_index_new_cb(void* p, void* ptr,
|
|
CRYPTO_EX_DATA* a, int idx, long argValue, void* arg)
|
|
{
|
|
AssertNotNull(p);
|
|
AssertNull(ptr);
|
|
AssertIntEQ(CRYPTO_set_ex_data(a, idx, SESSION_NEW_IDX_VAL), SSL_SUCCESS);
|
|
AssertIntEQ(argValue, SESSION_NEW_IDX_LONG);
|
|
AssertStrEQ(arg, SESSION_NEW_IDX_PTR);
|
|
}
|
|
|
|
static int test_wolfSSL_SESSION_get_ex_new_index_dup_cb(CRYPTO_EX_DATA* out,
|
|
const CRYPTO_EX_DATA* in, void* inPtr, int idx, long argV,
|
|
void* arg)
|
|
{
|
|
EXPECT_DECLS;
|
|
|
|
ExpectNotNull(out);
|
|
ExpectNotNull(in);
|
|
ExpectPtrEq(*(void**)inPtr, SESSION_NEW_IDX_VAL);
|
|
ExpectPtrEq(CRYPTO_get_ex_data(in, idx), SESSION_NEW_IDX_VAL);
|
|
ExpectPtrEq(CRYPTO_get_ex_data(out, idx), SESSION_NEW_IDX_VAL);
|
|
ExpectIntEQ(argV, SESSION_NEW_IDX_LONG);
|
|
ExpectStrEQ(arg, SESSION_NEW_IDX_PTR);
|
|
*(void**)inPtr = SESSION_DUP_IDX_VAL;
|
|
if (EXPECT_SUCCESS()) {
|
|
return SSL_SUCCESS;
|
|
}
|
|
else {
|
|
return SSL_FAILURE;
|
|
}
|
|
}
|
|
|
|
static int test_wolfSSL_SESSION_get_ex_new_index_free_cb_called = 0;
|
|
static void test_wolfSSL_SESSION_get_ex_new_index_free_cb(void* p, void* ptr,
|
|
CRYPTO_EX_DATA* a, int idx, long argValue, void* arg)
|
|
{
|
|
EXPECT_DECLS;
|
|
|
|
ExpectNotNull(p);
|
|
ExpectNull(ptr);
|
|
ExpectPtrNE(CRYPTO_get_ex_data(a, idx), 0);
|
|
ExpectIntEQ(argValue, SESSION_NEW_IDX_LONG);
|
|
ExpectStrEQ(arg, SESSION_NEW_IDX_PTR);
|
|
if (EXPECT_SUCCESS()) {
|
|
test_wolfSSL_SESSION_get_ex_new_index_free_cb_called++;
|
|
}
|
|
}
|
|
|
|
int test_wolfSSL_SESSION_get_ex_new_index(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
int idx = SSL_SESSION_get_ex_new_index(SESSION_NEW_IDX_LONG,
|
|
(void*)SESSION_NEW_IDX_PTR,
|
|
test_wolfSSL_SESSION_get_ex_new_index_new_cb,
|
|
test_wolfSSL_SESSION_get_ex_new_index_dup_cb,
|
|
test_wolfSSL_SESSION_get_ex_new_index_free_cb);
|
|
SSL_SESSION* s = SSL_SESSION_new();
|
|
SSL_SESSION* d = NULL;
|
|
|
|
ExpectNotNull(s);
|
|
ExpectPtrEq(SSL_SESSION_get_ex_data(s, idx), SESSION_NEW_IDX_VAL);
|
|
ExpectNotNull(d = SSL_SESSION_dup(s));
|
|
ExpectPtrEq(SSL_SESSION_get_ex_data(d, idx), SESSION_DUP_IDX_VAL);
|
|
SSL_SESSION_free(s);
|
|
ExpectIntEQ(test_wolfSSL_SESSION_get_ex_new_index_free_cb_called, 1);
|
|
SSL_SESSION_free(d);
|
|
ExpectIntEQ(test_wolfSSL_SESSION_get_ex_new_index_free_cb_called, 2);
|
|
|
|
crypto_ex_cb_free(crypto_ex_cb_ctx_session);
|
|
crypto_ex_cb_ctx_session = NULL;
|
|
return EXPECT_RESULT();
|
|
}
|
|
#else
|
|
int test_wolfSSL_SESSION_get_ex_new_index(void)
|
|
{
|
|
return TEST_SKIPPED;
|
|
}
|
|
#endif
|