TLS 1.3 fixes/improvements

Support Draft 28: able to compile code to return BAD_BINDER if no PSKs
match and certificates not to be used.
Change key share implementation to use server preference - server now
checks each client key share's group is in supported_groups extension.
Client and server examples modified to support server preference.
Application can set client's and server's supported groups by rank.
Server's supported groups is sent back in encrypted_extensions if
preferred group is not in client's list - able to be turned off at
compile time.
Application can query server's preferred group from client.
Able to compile using 0x0304 as version instead of draft version.
Fix state machine in TLS 1.3 to support unexpected hello_retry_request.
Also fixes non-blocking.
Fix resumption to use the named group from session.
Fix named group in session structure to be a 2-byte field.
Better detection of errors in message flow.
Fix DoTls13ClientHello when downgrading - don't do TLS 1.3 things.
Not downgrading on client fixed.
Downgrade protocol version from TLS 1.3 when not TLS 1.3 ciphersuite.
Get downgrading from TLS 1.3 and resumption working.
Change earlyData value to an enum.
Support no extensions data (as opposed to zero length extension data) in
TLS 1.3 ClientHello.
Check PSK cipher suite is available to both client and server before
using.
Check first PSK identity chosen when server says it is using early data
at client.
Check PSK extension is last in client_hello on server.
Check the PSK cipher suite to use is supported on client.
Check the returned cipher suite for pre-shared keys is the same as
client expects.
Send alert decrypt_error when verification fails in certificate_verify
or finished message doesn't match calculated value.
Fail when certificate messages recieved in handshake when using PSK.
Validate on the server that EndOfEarlyData message has been recieved
before finished message when server sent EarlyData extension.
This commit is contained in:
Sean Parkinson 2018-04-13 11:53:42 +10:00
parent a116b5ba83
commit 94157634e1
12 changed files with 1713 additions and 765 deletions

View File

@ -189,6 +189,50 @@ static void ShowVersions(void)
printf("\n");
}
#ifdef WOLFSSL_TLS13
static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519)
{
(void)useX25519;
WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
if (onlyKeyShare == 0 || onlyKeyShare == 2) {
#ifdef HAVE_CURVE25519
if (useX25519) {
int groups[1] = { WOLFSSL_ECC_X25519 };
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) != WOLFSSL_SUCCESS)
err_sys("unable to use curve x25519");
if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS)
err_sys("unable to set groups: x25519");
}
else
#endif
{
#ifdef HAVE_ECC
#if defined(HAVE_ECC256) || defined(HAVE_ALL_CURVES)
int groups[1] = { WOLFSSL_ECC_SECP256R1 };
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1)
!= WOLFSSL_SUCCESS) {
err_sys("unable to use curve secp256r1");
}
if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS)
err_sys("unable to set groups: secp256r1");
#endif
#endif
}
}
if (onlyKeyShare == 0 || onlyKeyShare == 1) {
#ifdef HAVE_FFDHE_2048
int groups[1] = { WOLFSSL_FFDHE_2048 };
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) != WOLFSSL_SUCCESS)
err_sys("unable to use DH 2048-bit parameters");
if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS)
err_sys("unable to set groups: DH 2048-bit");
#endif
}
WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
}
#endif
/* Measures average time to create, connect and disconnect a connection (TPS).
Benchmark = number of connections. */
static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port,
@ -230,55 +274,21 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port,
if (ssl == NULL)
err_sys("unable to get SSL object");
#ifndef NO_SESSION_CACHE
if (benchResume)
wolfSSL_set_session(ssl, benchSession);
#endif
#ifdef WOLFSSL_TLS13
if (version >= 4) {
if (!helloRetry) {
WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
if (onlyKeyShare == 0 || onlyKeyShare == 2) {
#ifdef HAVE_CURVE25519
if (useX25519) {
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519)
!= WOLFSSL_SUCCESS) {
err_sys("unable to use curve x25519");
}
}
else
#endif
#ifdef HAVE_ECC
#if defined(HAVE_ECC256) || defined(HAVE_ALL_CURVES)
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1)
!= WOLFSSL_SUCCESS) {
err_sys("unable to use curve secp256r1");
}
else
#endif
#endif
{
}
}
if (onlyKeyShare == 0 || onlyKeyShare == 1) {
#ifdef HAVE_FFDHE_2048
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048)
!= WOLFSSL_SUCCESS) {
err_sys("unable to use DH 2048-bit parameters");
}
#endif
}
WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
}
else {
else if (version >= 4) {
if (!helloRetry)
SetKeyShare(ssl, onlyKeyShare, useX25519);
else
wolfSSL_NoKeyShares(ssl);
}
}
#endif
tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl);
#ifndef NO_SESSION_CACHE
if (benchResume)
wolfSSL_set_session(ssl, benchSession);
#endif
if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) {
err_sys("error in setting fd");
}
@ -1198,7 +1208,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#ifdef HAVE_MAX_FRAGMENT
maxFragment = atoi(myoptarg);
if (maxFragment < WOLFSSL_MFL_2_9 ||
maxFragment > WOLFSSL_MFL_2_13) {
maxFragment > WOLFSSL_MFL_2_13) {
Usage();
exit(MY_EX_USAGE);
}
@ -1801,6 +1811,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
!= WOLFSSL_SUCCESS) {
err_sys("unable to support secp256r1");
}
if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_SECP384R1)
!= WOLFSSL_SUCCESS) {
err_sys("unable to support secp384r1");
}
}
#endif /* HAVE_CURVE25519 && HAVE_SUPPORTED_CURVES */
@ -1893,7 +1907,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#ifdef HAVE_CURVE25519
if (useX25519) {
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519)
!= WOLFSSL_SUCCESS) {
!= WOLFSSL_SUCCESS) {
err_sys("unable to use curve x25519");
}
}
@ -1901,13 +1915,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#ifdef HAVE_ECC
#if defined(HAVE_ECC256) || defined(HAVE_ALL_CURVES)
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1)
!= WOLFSSL_SUCCESS) {
!= WOLFSSL_SUCCESS) {
err_sys("unable to use curve secp256r1");
}
#endif
#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP384R1)
!= WOLFSSL_SUCCESS) {
!= WOLFSSL_SUCCESS) {
err_sys("unable to use curve secp384r1");
}
#endif
@ -2310,38 +2324,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
(void*)"resumed session");
#endif
#ifdef WOLFSSL_TLS13
if (!helloRetry) {
#ifdef HAVE_CURVE25519
if (useX25519) {
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) != WOLFSSL_SUCCESS) {
err_sys("unable to use curve x25519");
}
}
#endif
#ifdef HAVE_ECC
if (wolfSSL_UseKeyShare(sslResume,
WOLFSSL_ECC_SECP256R1) != WOLFSSL_SUCCESS) {
err_sys("unable to use curve secp256r1");
}
#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
if (wolfSSL_UseKeyShare(sslResume,
WOLFSSL_ECC_SECP384R1) != WOLFSSL_SUCCESS) {
err_sys("unable to use curve secp384r1");
}
#endif
#endif
#ifdef HAVE_FFDHE_2048
if (wolfSSL_UseKeyShare(sslResume, WOLFSSL_FFDHE_2048) != WOLFSSL_SUCCESS) {
err_sys("unable to use DH 2048-bit parameters");
}
#endif
}
else {
wolfSSL_NoKeyShares(ssl);
}
#endif
#ifndef WOLFSSL_CALLBACKS
if (nonBlocking) {
wolfSSL_set_using_nonblock(sslResume, 1);
@ -2420,7 +2402,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#else
timeout.tv_sec = DEFAULT_TIMEOUT_SEC;
timeout.tv_usec = 0;
ret = NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */
ret = NonBlockingSSL_Connect(sslResume); /* will keep retrying on timeout */
#endif
if (ret != WOLFSSL_SUCCESS) {
printf("wolfSSL_connect resume error %d, %s\n", err,

View File

@ -1206,10 +1206,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
#endif /* WOLFSSL_ASYNC_CRYPT */
#ifdef WOLFSSL_TLS13
if (noPskDheKe)
wolfSSL_CTX_no_dhe_psk(ctx);
if (noTicket)
wolfSSL_CTX_no_ticket_TLSv13(ctx);
if (noPskDheKe)
wolfSSL_CTX_no_dhe_psk(ctx);
if (noTicket)
wolfSSL_CTX_no_ticket_TLSv13(ctx);
#endif
while (1) {
@ -1337,30 +1337,45 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
if (onlyKeyShare == 2) {
if (useX25519 == 1) {
#ifdef HAVE_CURVE25519
int groups[1] = { WOLFSSL_ECC_X25519 };
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519)
!= WOLFSSL_SUCCESS) {
err_sys("unable to use curve x25519");
}
if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) {
err_sys("unable to set groups: x25519");
}
#endif
}
else
{
#ifdef HAVE_ECC
#if defined(HAVE_ECC256) || defined(HAVE_ALL_CURVES)
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1)
int groups[1] = { WOLFSSL_ECC_SECP256R1 };
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1)
!= WOLFSSL_SUCCESS) {
err_sys("unable to use curve secp256r1");
}
err_sys("unable to use curve secp256r1");
}
if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) {
err_sys("unable to set groups: secp256r1");
}
#endif
#endif
}
}
else if (onlyKeyShare == 1) {
#ifdef HAVE_FFDHE_2048
int groups[1] = { WOLFSSL_FFDHE_2048 };
if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048)
!= WOLFSSL_SUCCESS) {
err_sys("unable to use DH 2048-bit parameters");
}
if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) {
err_sys("unable to set groups: DH 2048-bit");
}
#endif
}
WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO);

View File

@ -421,6 +421,71 @@ if [ $RESULT -ne 0 ]; then
fi
echo ""
# TLS Downgrade server / TLS Downgrade client.
echo -e "\n\nTLS server and client able to downgrade but don't"
port=0
./examples/server/server -v d -R $ready_file -p $port &
server_pid=$!
create_port
./examples/client/client -v d -p $port
RESULT=$?
remove_ready_file
if [ $RESULT -ne 0 ]; then
echo -e "\n\nIssue with TLS not downgrading"
do_cleanup
exit 1
fi
echo ""
# TLS Downgrade server / TLS Downgrade client resumption.
echo -e "\n\nTLS server and client able to downgrade but don't and resume"
port=0
./examples/server/server -v d -r -R $ready_file -p $port &
server_pid=$!
create_port
./examples/client/client -v d -r -p $port
RESULT=$?
remove_ready_file
if [ $RESULT -ne 0 ]; then
echo -e "\n\nIssue with TLS not downgrading and resumption"
do_cleanup
exit 1
fi
echo ""
# TLS Downgrade server / TLS 1.2 client and resume.
echo -e "\n\nTLS server downgrade and resume"
port=0
./examples/server/server -v d -r -R $ready_file -p $port &
server_pid=$!
create_port
./examples/client/client -v 3 -r -p $port
RESULT=$?
remove_ready_file
if [ $RESULT -ne 0 ]; then
echo -e "\n\nIssue with TLS server downgrading and resumption"
do_cleanup
exit 1
fi
echo ""
# TLS 1.2 server / TLS downgrade client and resume.
echo -e "\n\nTLS client downgrade and resume"
port=0
./examples/server/server -v 3 -r -R $ready_file -p $port &
server_pid=$!
create_port
./examples/client/client -v d -r -p $port
RESULT=$?
remove_ready_file
if [ $RESULT -ne 0 ]; then
echo -e "\n\nIssue with TLS client downgrading and resumption"
do_cleanup
exit 1
fi
echo ""
# TLS Downgrade server / TLS Downgrade client.
# TLS 1.3 server / TLS 1.3 client send KeyUpdate before sending app data.
echo -e "\n\nTLS v1.3 KeyUpdate"
port=0

View File

@ -4458,6 +4458,11 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
#if defined(WOLFSSL_POST_HANDSHAKE_AUTH)
ssl->options.postHandshakeAuth = ctx->postHandshakeAuth;
#endif
if (ctx->numGroups > 0) {
XMEMCPY(ssl->group, ctx->group, sizeof(*ctx->group) * ctx->numGroups);
ssl->numGroups = ctx->numGroups;
}
#endif
#ifdef HAVE_TLS_EXTENSIONS
@ -9374,10 +9379,6 @@ exit_ppc:
ssl->nonblockarg = NULL;
#endif
#ifdef OPENSSL_EXTRA
ssl->options.serverState = SERVER_CERT_COMPLETE;
#endif
FreeKeyExchange(ssl);
return ret;
@ -9394,6 +9395,10 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ret = ProcessPeerCerts(ssl, input, inOutIdx, size);
#ifdef OPENSSL_EXTRA
ssl->options.serverState = SERVER_CERT_COMPLETE;
#endif
WOLFSSL_LEAVE("DoCertificateVerify", ret);
WOLFSSL_END(WC_FUNC_CERTIFICATE_DO);
@ -11938,7 +11943,7 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx)
#endif
#ifdef WOLFSSL_EARLY_DATA
if (ssl->earlyData) {
if (ssl->earlyData != no_early_data) {
}
else
#endif
@ -11963,7 +11968,7 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx)
return BUFFER_ERROR;
}
#ifdef WOLFSSL_EARLY_DATA
if (ssl->earlyData) {
if (ssl->earlyData != no_early_data) {
if (ssl->earlyDataSz + dataSz > ssl->options.maxEarlyDataSz) {
SendAlert(ssl, alert_fatal, unexpected_message);
return WOLFSSL_FATAL_ERROR;
@ -12592,7 +12597,7 @@ int ProcessReply(WOLFSSL* ssl)
if (ssl->options.side == WOLFSSL_SERVER_END &&
ssl->earlyData &&
ssl->options.handShakeState == HANDSHAKE_DONE) {
ssl->earlyData = 0;
ssl->earlyData = no_early_data;
ssl->options.processReply = doProcessInit;
return ZERO_RETURN;
}
@ -14435,7 +14440,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
#endif /* WOLFSSL_DTLS */
#ifdef WOLFSSL_EARLY_DATA
if (ssl->earlyData) {
if (ssl->earlyData != no_early_data) {
if (ssl->options.handShakeState == HANDSHAKE_DONE) {
WOLFSSL_MSG("handshake complete, trying to send early data");
return BUILD_MSG_ERROR;
@ -14599,7 +14604,7 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
}
#ifdef WOLFSSL_EARLY_DATA
if (ssl->earlyData) {
if (ssl->earlyData != no_early_data) {
}
else
#endif
@ -16833,31 +16838,26 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
#endif
if (sigAlgo == ssl->suites->sigAlgo || (sigAlgo == rsa_pss_sa_algo &&
ssl->suites->sigAlgo == rsa_sa_algo)) {
if (hashAlgo == sha_mac) {
ssl->suites->sigAlgo = sigAlgo;
break;
}
switch (hashAlgo) {
case sha_mac:
#ifndef NO_SHA256
else if (hashAlgo == sha256_mac) {
ssl->suites->hashAlgo = sha256_mac;
ssl->suites->sigAlgo = sigAlgo;
break;
}
case sha256_mac:
#endif
#ifdef WOLFSSL_SHA384
else if (hashAlgo == sha384_mac) {
ssl->suites->hashAlgo = sha384_mac;
ssl->suites->sigAlgo = sigAlgo;
break;
}
case sha384_mac:
#endif
#ifdef WOLFSSL_SHA512
else if (hashAlgo == sha512_mac) {
ssl->suites->hashAlgo = sha512_mac;
ssl->suites->sigAlgo = sigAlgo;
break;
}
case sha512_mac:
#endif
if (hashAlgo < ssl->suites->hashAlgo)
continue;
ssl->suites->hashAlgo = hashAlgo;
ssl->suites->sigAlgo = sigAlgo;
break;
default:
continue;
}
break;
}
else if (ssl->specs.sig_algo == 0) {
ssl->suites->hashAlgo = ssl->specs.mac_algorithm;
@ -17383,6 +17383,7 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv)
{
#ifdef WOLFSSL_TLS13
#ifndef WOLFSSL_TLS13_FINAL
/* TODO: [TLS13] Remove this.
* Translate the draft TLS v1.3 version to final version.
*/
@ -17390,6 +17391,7 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
pv.major = SSLv3_MAJOR;
pv.minor = TLSv1_3_MINOR;
}
#endif
#endif
#ifdef OPENSSL_EXTRA
@ -17520,38 +17522,43 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
return ret;
#ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(pv))
return DoTls13ServerHello(ssl, input, inOutIdx, helloSz);
if (IsAtLeastTLSv1_3(pv)) {
byte type = server_hello;
return DoTls13ServerHello(ssl, input, inOutIdx, helloSz, &type);
}
#endif
/* random */
XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN);
i += RAN_LEN;
if (!ssl->options.resuming) {
#ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) {
/* TLS v1.3 capable client not allowed to downgrade when connecting
* to TLS v1.3 capable server.
*/
if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1),
tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) {
/* TLS v1.3 capable client not allowed to downgrade when
* connecting to TLS v1.3 capable server unless cipher suite
* demands it.
*/
if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1),
tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
(*(input + i - 1) == 0 || *(input + i - 1) == 1)) {
SendAlert(ssl, alert_fatal, illegal_parameter);
return VERSION_ERROR;
SendAlert(ssl, alert_fatal, illegal_parameter);
return VERSION_ERROR;
}
}
}
else
else
#endif
if (ssl->ctx->method->version.major == SSLv3_MAJOR &&
if (ssl->ctx->method->version.major == SSLv3_MAJOR &&
ssl->ctx->method->version.minor == TLSv1_2_MINOR) {
/* TLS v1.2 capable client not allowed to downgrade when connecting
* to TLS v1.2 capable server.
*/
if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1),
tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
/* TLS v1.2 capable client not allowed to downgrade when
* connecting to TLS v1.2 capable server.
*/
if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1),
tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
*(input + i - 1) == 0) {
SendAlert(ssl, alert_fatal, illegal_parameter);
return VERSION_ERROR;
SendAlert(ssl, alert_fatal, illegal_parameter);
return VERSION_ERROR;
}
}
}
@ -22963,7 +22970,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#if defined(HAVE_SUPPORTED_CURVES) && defined(HAVE_ECC)
if (!TLSX_ValidateSupportedCurves(ssl, first, second)) {
WOLFSSL_MSG("Don't have matching curves");
return 0;
return 0;
}
#endif
@ -22976,7 +22983,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ssl->options.haveQSH = 1; /* matched TLS_QSH */
}
else {
WOLFSSL_MSG("Version of SSL connection does not support TLS_QSH");
WOLFSSL_MSG("Version of SSL connection does not support "
"TLS_QSH");
}
return 0;
}
@ -22988,10 +22996,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
/* Try to establish a key share. */
int ret = TLSX_KeyShare_Establish(ssl);
if (ret == KEY_SHARE_ERROR)
ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST;
ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
else if (ret != 0)
return 0;
}
else if (first == TLS13_BYTE) {
/* Can't negotiate TLS 1.3 ciphersuites with lower protocol
* version. */
return 0;
}
#endif
return 1;
@ -23267,6 +23280,76 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif /* OLD_HELLO_ALLOWED */
int HandleTlsResumption(WOLFSSL* ssl, int bogusID, Suites* clSuites)
{
int ret = 0;
WOLFSSL_SESSION* session = GetSession(ssl,
ssl->arrays->masterSecret, 1);
(void)bogusID;
#ifdef HAVE_SESSION_TICKET
if (ssl->options.useTicket == 1) {
session = &ssl->session;
} else if (bogusID == 1 && ssl->options.rejectTicket == 0) {
WOLFSSL_MSG("Bogus session ID without session ticket");
return BUFFER_ERROR;
}
#endif
if (!session) {
WOLFSSL_MSG("Session lookup for resume failed");
ssl->options.resuming = 0;
}
else if (session->haveEMS != ssl->options.haveEMS) {
/* RFC 7627, 5.3, server-side */
/* if old sess didn't have EMS, but new does, full handshake */
if (!session->haveEMS && ssl->options.haveEMS) {
WOLFSSL_MSG("Attempting to resume a session that didn't "
"use EMS with a new session with EMS. Do full "
"handshake.");
ssl->options.resuming = 0;
}
/* if old sess used EMS, but new doesn't, MUST abort */
else if (session->haveEMS && !ssl->options.haveEMS) {
WOLFSSL_MSG("Trying to resume a session with EMS without "
"using EMS");
return EXT_MASTER_SECRET_NEEDED_E;
}
#ifdef HAVE_EXT_CACHE
wolfSSL_SESSION_free(session);
#endif
}
else {
#ifdef HAVE_EXT_CACHE
wolfSSL_SESSION_free(session);
#endif
if (MatchSuite(ssl, clSuites) < 0) {
WOLFSSL_MSG("Unsupported cipher suite, ClientHello");
return UNSUPPORTED_SUITE;
}
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
RAN_LEN);
if (ret != 0)
return ret;
#ifdef NO_OLD_TLS
ret = DeriveTlsKeys(ssl);
#else
#ifndef NO_TLS
if (ssl->options.tls)
ret = DeriveTlsKeys(ssl);
#endif
if (!ssl->options.tls)
ret = DeriveKeys(ssl);
#endif
ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
}
return ret;
}
/* handle processing of client_hello (1) */
int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
@ -23331,6 +23414,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif /* WOLFSSL_DTLS */
i += OPAQUE16_LEN;
/* Legacy protocol version cannot negotiate TLS 1.3 or higher. */
if (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR)
pv.minor = TLSv1_2_MINOR;
if ((!ssl->options.dtls && ssl->version.minor > pv.minor) ||
(ssl->options.dtls && ssl->version.minor != DTLS_MINOR
&& ssl->version.minor != DTLSv1_2_MINOR && pv.minor != DTLS_MINOR
@ -23643,10 +23730,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#ifdef HAVE_QSH
QSH_Init(ssl);
#endif
if (TLSX_SupportExtensions(ssl)) {
if (TLSX_SupportExtensions(ssl))
#else
if (IsAtLeastTLSv1_2(ssl)) {
if (IsAtLeastTLSv1_2(ssl))
#endif
{
/* Process the hello extension. Skip unsupported. */
word16 totalExtSz;
@ -23742,66 +23830,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
/* ProcessOld uses same resume code */
if (ssl->options.resuming) {
WOLFSSL_SESSION* session = GetSession(ssl,
ssl->arrays->masterSecret, 1);
#ifdef HAVE_SESSION_TICKET
if (ssl->options.useTicket == 1) {
session = &ssl->session;
} else if (bogusID == 1 && ssl->options.rejectTicket == 0) {
WOLFSSL_MSG("Bogus session ID without session ticket");
return BUFFER_ERROR;
}
#endif
if (!session) {
WOLFSSL_MSG("Session lookup for resume failed");
ssl->options.resuming = 0;
}
else if (session->haveEMS != ssl->options.haveEMS) {
/* RFC 7627, 5.3, server-side */
/* if old sess didn't have EMS, but new does, full handshake */
if (!session->haveEMS && ssl->options.haveEMS) {
WOLFSSL_MSG("Attempting to resume a session that didn't "
"use EMS with a new session with EMS. Do full "
"handshake.");
ssl->options.resuming = 0;
}
/* if old sess used EMS, but new doesn't, MUST abort */
else if (session->haveEMS && !ssl->options.haveEMS) {
WOLFSSL_MSG("Trying to resume a session with EMS without "
"using EMS");
return EXT_MASTER_SECRET_NEEDED_E;
}
#ifdef HAVE_EXT_CACHE
wolfSSL_SESSION_free(session);
#endif
}
else {
#ifdef HAVE_EXT_CACHE
wolfSSL_SESSION_free(session);
#endif
if (MatchSuite(ssl, &clSuites) < 0) {
WOLFSSL_MSG("Unsupported cipher suite, ClientHello");
return UNSUPPORTED_SUITE;
}
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
RAN_LEN);
if (ret != 0)
return ret;
#ifdef NO_OLD_TLS
ret = DeriveTlsKeys(ssl);
#else
#ifndef NO_TLS
if (ssl->options.tls)
ret = DeriveTlsKeys(ssl);
#endif
if (!ssl->options.tls)
ret = DeriveKeys(ssl);
#endif
ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
ret = HandleTlsResumption(ssl, bogusID, &clSuites);
if (ret != 0)
return ret;
if (ssl->options.clientState == CLIENT_KEYEXCHANGE_COMPLETE) {
WOLFSSL_LEAVE("DoClientHello", ret);
WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
@ -24227,7 +24259,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
word16 haveEMS; /* have extended master secret */
#ifdef WOLFSSL_TLS13
word32 ageAdd; /* Obfuscation of age */
byte namedGroup; /* Named group used */
word16 namedGroup; /* Named group used */
#ifndef WOLFSSL_TLS13_DRAFT_18
TicketNonce ticketNonce; /* Ticket nonce */
#endif
@ -24278,7 +24310,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#ifdef WOLFSSL_TLS13
/* Client adds to ticket age to obfuscate. */
ret = wc_RNG_GenerateBlock(ssl->rng, (byte*)&it.ageAdd,
sizeof(it.ageAdd));
sizeof(it.ageAdd));
if (ret != 0)
return BAD_TICKET_ENCRYPT;
ssl->session.ticketAdd = it.ageAdd;
@ -24387,6 +24419,23 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
/* get master secret */
if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) {
if (ssl->version.minor < it->pv.minor) {
WOLFSSL_MSG("Ticket has greater version");
return VERSION_ERROR;
}
else if (ssl->version.minor > it->pv.minor) {
if (!ssl->options.downgrade) {
WOLFSSL_MSG("Ticket has lesser version");
return VERSION_ERROR;
}
WOLFSSL_MSG("Downgrading protocol due to ticket");
if (it->pv.minor < ssl->options.minDowngrade)
return VERSION_ERROR;
ssl->version.minor = it->pv.minor;
}
if (!IsAtLeastTLSv1_3(ssl->version)) {
XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN);
/* Copy the haveExtendedMasterSecret property from the ticket to

View File

@ -1599,11 +1599,11 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_EARLY_DATA
if (ssl->earlyData && (ret = wolfSSL_negotiate(ssl)) < 0) {
if (ssl->earlyData != no_early_data && (ret = wolfSSL_negotiate(ssl)) < 0) {
ssl->error = ret;
return WOLFSSL_FATAL_ERROR;
}
ssl->earlyData = 0;
ssl->earlyData = no_early_data;
#endif
#ifdef HAVE_WRITE_DUP
@ -8581,6 +8581,10 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
#endif
/* get response */
while (ssl->options.serverState < neededState) {
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3)
return wolfSSL_connect_TLSv13(ssl);
#endif
if ( (ssl->error = ProcessReply(ssl)) < 0) {
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
@ -8635,13 +8639,14 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
/* get response */
while (ssl->options.serverState < neededState) {
if ( (ssl->error = ProcessReply(ssl)) < 0) {
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
}
/* if resumption failed, reset needed state */
else if (neededState == SERVER_FINISHED_COMPLETE)
if (neededState == SERVER_FINISHED_COMPLETE) {
if (!ssl->options.resuming)
neededState = SERVER_HELLODONE_COMPLETE;
}
}
}
#endif
@ -9759,9 +9764,13 @@ int AddSession(WOLFSSL* ssl)
session->cipherSuite = ssl->options.cipherSuite;
}
#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & HAVE_SESSION_TICKET) */
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
#if defined(WOLFSSL_TLS13)
if (error == 0) {
session->namedGroup = ssl->session.namedGroup;
}
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
if (error == 0) {
session->ticketSeen = ssl->session.ticketSeen;
session->ticketAdd = ssl->session.ticketAdd;
#ifndef WOLFSSL_TLS13_DRAFT_18

856
src/tls.c

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -18087,6 +18087,8 @@ static int test_tls13_apis(void)
#ifdef WOLFSSL_EARLY_DATA
int outSz;
#endif
int groups[1] = { WOLFSSL_ECC_X25519 };
int numGroups = 1;
clientTls12Ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
clientTls12Ssl = wolfSSL_new(clientTls12Ctx);
@ -18190,6 +18192,38 @@ static int test_tls13_apis(void)
AssertIntEQ(wolfSSL_request_certificate(serverSsl), NOT_READY_ERROR);
#endif
#ifndef WOLFSSL_NO_SERVER_GROUPS_EXT
AssertIntEQ(wolfSSL_preferred_group(NULL), BAD_FUNC_ARG);
AssertIntEQ(wolfSSL_preferred_group(serverSsl), SIDE_ERROR);
AssertIntEQ(wolfSSL_preferred_group(clientTls12Ssl), BAD_FUNC_ARG);
AssertIntEQ(wolfSSL_preferred_group(clientSsl), NOT_READY_ERROR);
#endif
AssertIntEQ(wolfSSL_CTX_set_groups(NULL, NULL, 0), BAD_FUNC_ARG);
AssertIntEQ(wolfSSL_CTX_set_groups(clientCtx, NULL, 0), BAD_FUNC_ARG);
AssertIntEQ(wolfSSL_CTX_set_groups(NULL, groups, numGroups), BAD_FUNC_ARG);
AssertIntEQ(wolfSSL_CTX_set_groups(clientTls12Ctx, groups, numGroups),
BAD_FUNC_ARG);
AssertIntEQ(wolfSSL_CTX_set_groups(clientCtx, groups,
WOLFSSL_MAX_GROUP_COUNT + 1),
BAD_FUNC_ARG);
AssertIntEQ(wolfSSL_CTX_set_groups(clientCtx, groups, numGroups),
WOLFSSL_SUCCESS);
AssertIntEQ(wolfSSL_CTX_set_groups(serverCtx, groups, numGroups),
WOLFSSL_SUCCESS);
AssertIntEQ(wolfSSL_set_groups(NULL, NULL, 0), BAD_FUNC_ARG);
AssertIntEQ(wolfSSL_set_groups(clientSsl, NULL, 0), BAD_FUNC_ARG);
AssertIntEQ(wolfSSL_set_groups(NULL, groups, numGroups), BAD_FUNC_ARG);
AssertIntEQ(wolfSSL_set_groups(clientTls12Ssl, groups, numGroups),
BAD_FUNC_ARG);
AssertIntEQ(wolfSSL_set_groups(clientSsl, groups,
WOLFSSL_MAX_GROUP_COUNT + 1), BAD_FUNC_ARG);
AssertIntEQ(wolfSSL_set_groups(clientSsl, groups, numGroups),
WOLFSSL_SUCCESS);
AssertIntEQ(wolfSSL_set_groups(serverSsl, groups, numGroups),
WOLFSSL_SUCCESS);
#ifdef WOLFSSL_EARLY_DATA
AssertIntEQ(wolfSSL_CTX_set_max_early_data(NULL, 0), BAD_FUNC_ARG);
AssertIntEQ(wolfSSL_CTX_set_max_early_data(clientCtx, 0), SIDE_ERROR);

View File

@ -1,12 +1,12 @@
# server TLSv1.3 TLS13-CHACH20-POLY1305-SHA256
# server TLSv1.3 TLS13-CHACHA20-POLY1305-SHA256
-v 4
-l TLS13-CHACH20-POLY1305-SHA256
-l TLS13-CHACHA20-POLY1305-SHA256
-c ./certs/server-ecc.pem
-k ./certs/ecc-key.pem
# client TLSv1.3 TLS13-CHACH20-POLY1305-SHA256
# client TLSv1.3 TLS13-CHACHA20-POLY1305-SHA256
-v 4
-l TLS13-CHACH20-POLY1305-SHA256
-l TLS13-CHACHA20-POLY1305-SHA256
-A ./certs/ca-ecc-cert.pem
# server TLSv1.3 TLS13-AES128-GCM-SHA256
@ -58,6 +58,7 @@
-l TLS13-AES128-GCM-SHA256
-c ./certs/server-ecc.pem
-k ./certs/ecc-key.pem
-t
# client TLSv1.3 TLS13-AES128-GCM-SHA256
-v 4
@ -65,3 +66,16 @@
-A ./certs/ca-ecc-cert.pem
-t
# server TLSv1.3 TLS13-AES128-GCM-SHA256
-v 4
-l TLS13-AES128-GCM-SHA256
-c ./certs/server-ecc.pem
-k ./certs/ecc-key.pem
-Y
# client TLSv1.3 TLS13-AES128-GCM-SHA256
-v 4
-l TLS13-AES128-GCM-SHA256
-A ./certs/ca-ecc-cert.pem
-y

View File

@ -1,10 +1,10 @@
# server TLSv1.3 TLS13-CHACH20-POLY1305-SHA256
# server TLSv1.3 TLS13-CHACHA20-POLY1305-SHA256
-v 4
-l TLS13-CHACH20-POLY1305-SHA256
-l TLS13-CHACHA20-POLY1305-SHA256
# client TLSv1.3 TLS13-CHACH20-POLY1305-SHA256
# client TLSv1.3 TLS13-CHACHA20-POLY1305-SHA256
-v 4
-l TLS13-CHACH20-POLY1305-SHA256
-l TLS13-CHACHA20-POLY1305-SHA256
# server TLSv1.3 TLS13-AES128-GCM-SHA256
-v 4

View File

@ -1026,6 +1026,7 @@ enum Misc {
TLSv1_1_MINOR = 2, /* TLSv1_1 minor version number */
TLSv1_2_MINOR = 3, /* TLSv1_2 minor version number */
TLSv1_3_MINOR = 4, /* TLSv1_3 minor version number */
#ifndef WOLFSSL_TLS13_FINAL
TLS_DRAFT_MAJOR = 0x7f, /* Draft TLS major version number */
#ifdef WOLFSSL_TLS13_DRAFT_18
TLS_DRAFT_MINOR = 0x12, /* Minor version number of TLS draft */
@ -1034,7 +1035,8 @@ enum Misc {
#elif defined(WOLFSSL_TLS13_DRAFT_23)
TLS_DRAFT_MINOR = 0x17, /* Minor version number of TLS draft */
#else
TLS_DRAFT_MINOR = 0x1b, /* Minor version number of TLS draft */
TLS_DRAFT_MINOR = 0x1c, /* Minor version number of TLS draft */
#endif
#endif
OLD_HELLO_ID = 0x01, /* SSLv2 Client Hello Indicator */
INVALID_BYTE = 0xff, /* Used to initialize cipher specs values */
@ -1380,6 +1382,7 @@ enum states {
NULL_STATE = 0,
SERVER_HELLOVERIFYREQUEST_COMPLETE,
SERVER_HELLO_RETRY_REQUEST_COMPLETE,
SERVER_HELLO_COMPLETE,
SERVER_ENCRYPTED_EXTENSIONS_COMPLETE,
SERVER_CERT_COMPLETE,
@ -1387,7 +1390,6 @@ enum states {
SERVER_HELLODONE_COMPLETE,
SERVER_CHANGECIPHERSPEC_COMPLETE,
SERVER_FINISHED_COMPLETE,
SERVER_HELLO_RETRY_REQUEST,
CLIENT_HELLO_COMPLETE,
CLIENT_KEYEXCHANGE_COMPLETE,
@ -1465,6 +1467,8 @@ struct WOLFSSL_METHOD {
/* wolfSSL buffer type - internal uses "buffer" type */
typedef WOLFSSL_BUFFER_INFO buffer;
typedef struct Suites Suites;
/* defaults to client */
WOLFSSL_LOCAL void InitSSL_Method(WOLFSSL_METHOD*, ProtocolVersion);
@ -1474,6 +1478,8 @@ WOLFSSL_LOCAL int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
word32 size, word32 totalSz, int sniff);
WOLFSSL_LOCAL int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx);
/* TLS v1.3 needs these */
WOLFSSL_LOCAL int HandleTlsResumption(WOLFSSL* ssl, int bogusID,
Suites* clSuites);
WOLFSSL_LOCAL int DoClientHello(WOLFSSL* ssl, const byte* input, word32*,
word32);
#ifdef WOLFSSL_TLS13
@ -1513,7 +1519,8 @@ WOLFSSL_LOCAL int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input,
WOLFSSL_LOCAL int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input,
word32* inOutIdx, word32 totalSz);
WOLFSSL_LOCAL int DoTls13ServerHello(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, word32 helloSz);
word32* inOutIdx, word32 helloSz,
byte* extMsgType);
#endif
@ -1594,7 +1601,7 @@ typedef struct {
} bufferStatic;
/* Cipher Suites holder */
typedef struct Suites {
struct Suites {
word16 suiteSz; /* suite length in bytes */
word16 hashSigAlgoSz; /* SigAlgo extension length in bytes */
byte suites[WOLFSSL_MAX_SUITE_SZ];
@ -1602,7 +1609,7 @@ typedef struct Suites {
byte setSuites; /* user set suites from default */
byte hashAlgo; /* selected hash algorithm */
byte sigAlgo; /* selected sig algorithm */
} Suites;
};
WOLFSSL_LOCAL void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig,
@ -1935,6 +1942,7 @@ typedef struct TLSX {
} TLSX;
WOLFSSL_LOCAL TLSX* TLSX_Find(TLSX* list, TLSX_Type type);
WOLFSSL_LOCAL void TLSX_Remove(TLSX** list, TLSX_Type type, void* heap);
WOLFSSL_LOCAL void TLSX_FreeAll(TLSX* list, void* heap);
WOLFSSL_LOCAL int TLSX_SupportExtensions(WOLFSSL* ssl);
WOLFSSL_LOCAL int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isRequest);
@ -2100,6 +2108,9 @@ WOLFSSL_LOCAL int TLSX_UsePointFormat(TLSX** extensions, byte point,
#ifndef NO_WOLFSSL_SERVER
WOLFSSL_LOCAL int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first,
byte second);
WOLFSSL_LOCAL int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl);
WOLFSSL_LOCAL int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl,
int checkSupported);
#endif
#endif /* HAVE_SUPPORTED_CURVES */
@ -2420,6 +2431,10 @@ struct WOLFSSL_CTX {
wc_psk_server_callback server_psk_cb; /* server callback */
char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN];
#endif /* HAVE_SESSION_TICKET || !NO_PSK */
#ifdef WOLFSSL_TLS13
word16 group[WOLFSSL_MAX_GROUP_COUNT];
byte numGroups;
#endif
#ifdef WOLFSSL_EARLY_DATA
word32 maxEarlyDataSz;
#endif
@ -2773,9 +2788,11 @@ struct WOLFSSL_SESSION {
byte sessionCtxSz; /* sessionCtx length */
byte sessionCtx[ID_LEN]; /* app specific context id */
#endif
#ifdef WOLFSSL_TLS13
word16 namedGroup;
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
#ifdef WOLFSSL_TLS13
byte namedGroup;
word32 ticketSeen; /* Time ticket seen (ms) */
word32 ticketAdd; /* Added by client */
#ifndef WOLFSSL_TLS13_DRAFT_18
@ -3060,8 +3077,12 @@ typedef struct Options {
byte verifyDepth; /* maximum verification depth */
#endif
#ifdef WOLFSSL_EARLY_DATA
word16 pskIdIndex;
word32 maxEarlyDataSz;
#endif
#ifdef WOLFSSL_TLS13
byte oldMinor; /* client preferred version < TLS 1.3 */
#endif
} Options;
typedef struct Arrays {
@ -3357,6 +3378,15 @@ struct CertReqCtx {
};
#endif
#ifdef WOLFSSL_EARLY_DATA
typedef enum EarlyDataState {
no_early_data,
expecting_early_data,
process_early_data,
done_early_data
} EarlyDataState;
#endif
/* wolfSSL ssl type */
struct WOLFSSL {
WOLFSSL_CTX* ctx;
@ -3448,6 +3478,8 @@ struct WOLFSSL {
#endif
#ifdef WOLFSSL_TLS13
word16 namedGroup;
word16 group[WOLFSSL_MAX_GROUP_COUNT];
byte numGroups;
#endif
byte pssAlgo;
#ifdef WOLFSSL_TLS13
@ -3636,7 +3668,7 @@ struct WOLFSSL {
void* jObjectRef; /* reference to WolfSSLSession in JNI wrapper */
#endif /* WOLFSSL_JNI */
#ifdef WOLFSSL_EARLY_DATA
int earlyData;
EarlyDataState earlyData;
word32 earlyDataSz;
#endif
};

View File

@ -396,6 +396,8 @@ enum AlertLevel {
/* Maximum master key length (SECRET_LEN) */
#define WOLFSSL_MAX_MASTER_KEY_LENGTH 48
/* Maximum number of groups that can be set */
#define WOLFSSL_MAX_GROUP_COUNT 10
typedef WOLFSSL_METHOD* (*wolfSSL_method_func)(void* heap);
WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method_ex(void* heap);
@ -552,6 +554,11 @@ WOLFSSL_API int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx);
WOLFSSL_API int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_request_certificate(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_preferred_group(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups,
int count);
WOLFSSL_API int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count);
WOLFSSL_API int wolfSSL_connect_TLSv13(WOLFSSL*);
WOLFSSL_API int wolfSSL_accept_TLSv13(WOLFSSL*);
@ -575,12 +582,11 @@ WOLFSSL_API void wolfSSL_set_quiet_shutdown(WOLFSSL*, int);
WOLFSSL_API int wolfSSL_get_error(WOLFSSL*, int);
WOLFSSL_API int wolfSSL_get_alert_history(WOLFSSL*, WOLFSSL_ALERT_HISTORY *);
WOLFSSL_API int wolfSSL_set_session(WOLFSSL* ssl,WOLFSSL_SESSION* session);
WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* session, long t);
WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl);
WOLFSSL_API void wolfSSL_flush_sessions(WOLFSSL_CTX *ctx, long tm);
WOLFSSL_API int wolfSSL_SetServerID(WOLFSSL* ssl, const unsigned char*,
int, int);
WOLFSSL_API int wolfSSL_set_session(WOLFSSL*, WOLFSSL_SESSION*);
WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION*, long);
WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL*);
WOLFSSL_API void wolfSSL_flush_sessions(WOLFSSL_CTX*, long);
WOLFSSL_API int wolfSSL_SetServerID(WOLFSSL*, const unsigned char*, int, int);
#ifdef SESSION_INDEX
WOLFSSL_API int wolfSSL_GetSessionIndex(WOLFSSL* ssl);