Fix downgrading from TLS v1.3 to TLS v1.2
Fix handling of ServerHello in TLS v1.3 to support TLS v1.2 when downgrading. Added support in client and server examples for using downgrade method: wolfSSLv23_client_method_ex() or wolfSSLv23_server_method_ex(). Add tests, using downgrade version, of client or server downgrading from TLS v1.3 to TLS v1.2.
This commit is contained in:
parent
dc4edd0cd9
commit
da4024b46a
@ -1027,6 +1027,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
||||
break;
|
||||
|
||||
case 'v' :
|
||||
if (myoptarg[0] == 'd') {
|
||||
version = CLIENT_DOWNGRADE_VERSION;
|
||||
break;
|
||||
}
|
||||
version = atoi(myoptarg);
|
||||
if (version < 0 || version > 4) {
|
||||
Usage();
|
||||
@ -1414,6 +1418,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
||||
method = wolfTLSv1_3_client_method_ex;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CLIENT_DOWNGRADE_VERSION:
|
||||
method = wolfSSLv23_client_method_ex;
|
||||
break;
|
||||
#endif /* NO_TLS */
|
||||
|
||||
#ifdef WOLFSSL_DTLS
|
||||
|
@ -643,6 +643,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
||||
break;
|
||||
|
||||
case 'v' :
|
||||
if (myoptarg[0] == 'd') {
|
||||
version = SERVER_DOWNGRADE_VERSION;
|
||||
break;
|
||||
}
|
||||
version = atoi(myoptarg);
|
||||
if (version < 0 || version > 4) {
|
||||
Usage();
|
||||
@ -893,6 +897,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
||||
method = wolfTLSv1_3_server_method_ex;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SERVER_DOWNGRADE_VERSION:
|
||||
method = wolfSSLv23_server_method_ex;
|
||||
break;
|
||||
#endif /* NO_TLS */
|
||||
|
||||
#ifdef CYASSL_DTLS
|
||||
|
@ -373,6 +373,22 @@ if [ $RESULT -eq 0 ]; then
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# TLS Downgrade server / TLS 1.2 client.
|
||||
echo -e "\n\nTLS server downgrading to TLS v1.2"
|
||||
port=0
|
||||
./examples/server/server -v d -R $ready_file -p $port &
|
||||
server_pid=$!
|
||||
create_port
|
||||
./examples/client/client -v 3 -p $port
|
||||
RESULT=$?
|
||||
remove_ready_file
|
||||
if [ $RESULT -ne 0 ]; then
|
||||
echo -e "\n\nIssue with TLS server downgrading to TLS v1.2"
|
||||
do_cleanup
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# TLS 1.2 server / TLS 1.3 client.
|
||||
echo -e "\n\nTLS v1.3 client upgrading server to TLS v1.3"
|
||||
port=0
|
||||
@ -389,6 +405,22 @@ if [ $RESULT -eq 0 ]; then
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# TLS 1.2 server / TLS downgrade client.
|
||||
echo -e "\n\nTLS client downgrading to TLS v1.2"
|
||||
port=0
|
||||
./examples/server/server -v 3 -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 client downgrading to TLS v1.2"
|
||||
do_cleanup
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# TLS 1.3 server / TLS 1.3 client send KeyUpdate before sending app data.
|
||||
echo -e "\n\nTLS v1.3 KeyUpdate"
|
||||
port=0
|
||||
|
@ -17431,6 +17431,13 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
|
||||
}
|
||||
#endif /* HAVE_SECRET_CALLBACK */
|
||||
|
||||
return CompleteServerHello(ssl);
|
||||
}
|
||||
|
||||
int CompleteServerHello(WOLFSSL* ssl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ssl->options.resuming) {
|
||||
if (DSH_CheckSessionId(ssl)) {
|
||||
if (SetCipherSpecs(ssl) == 0) {
|
||||
|
@ -4679,6 +4679,13 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input,
|
||||
if (major != pv.major)
|
||||
return VERSION_ERROR;
|
||||
|
||||
/* Version is TLS v1.2 to handle downgrading from TLS v1.3+. */
|
||||
if (ssl->options.downgrade && ssl->version.minor == TLSv1_2_MINOR &&
|
||||
minor >= TLSv1_3_MINOR) {
|
||||
/* Set minor version back to TLS v1.3+ */
|
||||
ssl->version.minor = ssl->ctx->method->version.minor;
|
||||
}
|
||||
|
||||
/* No upgrade allowed. */
|
||||
if (ssl->version.minor < minor)
|
||||
return VERSION_ERROR;
|
||||
|
108
src/tls13.c
108
src/tls13.c
@ -2605,6 +2605,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
int ret;
|
||||
#ifndef WOLFSSL_TLS13_DRAFT_18
|
||||
byte sessIdSz;
|
||||
const byte* sessId;
|
||||
byte b;
|
||||
#endif
|
||||
word16 totalExtSz;
|
||||
@ -2668,35 +2669,18 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
sessIdSz = input[i++];
|
||||
if ((i - begin) + sessIdSz > helloSz)
|
||||
return BUFFER_ERROR;
|
||||
#ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
|
||||
if (sessIdSz == 0)
|
||||
return INVALID_PARAMETER;
|
||||
if (ssl->session.sessionIDSz != 0) {
|
||||
if (ssl->session.sessionIDSz != sessIdSz ||
|
||||
XMEMCMP(ssl->session.sessionID, input + i, sessIdSz) != 0) {
|
||||
return INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
else if (XMEMCMP(ssl->arrays->clientRandom, input + i, sessIdSz) != 0)
|
||||
return INVALID_PARAMETER;
|
||||
#else
|
||||
if (sessIdSz != ssl->session.sessionIDSz || (sessIdSz > 0 &&
|
||||
XMEMCMP(ssl->session.sessionID, input + i, sessIdSz) != 0)) {
|
||||
WOLFSSL_MSG("Server sent different session id");
|
||||
return INVALID_PARAMETER;
|
||||
}
|
||||
#endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */
|
||||
sessId = input + i;
|
||||
i += sessIdSz;
|
||||
ssl->options.haveSessionId = 1;
|
||||
#endif /* WOLFSSL_TLS13_DRAFT_18 */
|
||||
ssl->options.haveSessionId = 1;
|
||||
|
||||
#ifdef WOLFSSL_TLS13_DRAFT_18
|
||||
/* Ciphersuite and extensions length check */
|
||||
/* Ciphersuite check */
|
||||
if ((i - begin) + OPAQUE16_LEN + OPAQUE16_LEN > helloSz)
|
||||
return BUFFER_ERROR;
|
||||
#else
|
||||
/* Ciphersuite, compression and extensions length check */
|
||||
if ((i - begin) + OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN > helloSz)
|
||||
/* Ciphersuite and compression check */
|
||||
if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz)
|
||||
return BUFFER_ERROR;
|
||||
#endif
|
||||
|
||||
@ -2713,18 +2697,33 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get extension length and length check. */
|
||||
ato16(&input[i], &totalExtSz);
|
||||
i += OPAQUE16_LEN;
|
||||
if ((i - begin) + totalExtSz > helloSz)
|
||||
return BUFFER_ERROR;
|
||||
#ifndef WOLFSSL_TLS13_DRAFT_18
|
||||
if ((i - begin) + OPAQUE16_LEN > helloSz) {
|
||||
if (!ssl->options.downgrade)
|
||||
return BUFFER_ERROR;
|
||||
ssl->version.minor = TLSv1_2_MINOR;
|
||||
ssl->options.haveEMS = 0;
|
||||
}
|
||||
if ((i - begin) < helloSz)
|
||||
#endif
|
||||
{
|
||||
/* Get extension length and length check. */
|
||||
ato16(&input[i], &totalExtSz);
|
||||
i += OPAQUE16_LEN;
|
||||
if ((i - begin) + totalExtSz > helloSz)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
/* Parse and handle extensions. */
|
||||
ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, extMsgType, NULL);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
#ifndef WOLFSSL_TLS13_DRAFT_18
|
||||
if (ssl->options.downgrade)
|
||||
ssl->version.minor = TLSv1_2_MINOR;
|
||||
#endif
|
||||
/* Parse and handle extensions. */
|
||||
ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, extMsgType, NULL);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
i += totalExtSz;
|
||||
i += totalExtSz;
|
||||
}
|
||||
*inOutIdx = i;
|
||||
|
||||
ssl->options.serverState = SERVER_HELLO_COMPLETE;
|
||||
@ -2739,6 +2738,51 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
}
|
||||
#endif /* HAVE_SECRET_CALLBACK */
|
||||
|
||||
#ifndef WOLFSSL_TLS13_DRAFT_18
|
||||
/* Version only negotiated in extensions for TLS v1.3.
|
||||
* Only now do we know how to deal with session id.
|
||||
*/
|
||||
if (!IsAtLeastTLSv1_3(ssl->version)) {
|
||||
ssl->arrays->sessionIDSz = sessIdSz;
|
||||
|
||||
if (ssl->arrays->sessionIDSz > ID_LEN) {
|
||||
WOLFSSL_MSG("Invalid session ID size");
|
||||
ssl->arrays->sessionIDSz = 0;
|
||||
return BUFFER_ERROR;
|
||||
}
|
||||
else if (ssl->arrays->sessionIDSz) {
|
||||
XMEMCPY(ssl->arrays->sessionID, sessId, ssl->arrays->sessionIDSz);
|
||||
ssl->options.haveSessionId = 1;
|
||||
}
|
||||
|
||||
/* Complete TLS v1.2 processing of ServerHello. */
|
||||
ret = CompleteServerHello(ssl);
|
||||
|
||||
WOLFSSL_LEAVE("DoTls13ServerHello", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
|
||||
if (sessIdSz == 0)
|
||||
return INVALID_PARAMETER;
|
||||
if (ssl->session.sessionIDSz != 0) {
|
||||
if (ssl->session.sessionIDSz != sessIdSz ||
|
||||
XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0) {
|
||||
return INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
else if (XMEMCMP(ssl->arrays->clientRandom, sessId, sessIdSz) != 0)
|
||||
return INVALID_PARAMETER;
|
||||
#else
|
||||
if (sessIdSz != ssl->session.sessionIDSz || (sessIdSz > 0 &&
|
||||
XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0)) {
|
||||
WOLFSSL_MSG("Server sent different session id");
|
||||
return INVALID_PARAMETER;
|
||||
}
|
||||
#endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */
|
||||
#endif
|
||||
|
||||
ret = SetCipherSpecs(ssl);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
@ -1481,6 +1481,7 @@ WOLFSSL_LOCAL int DoTls13ClientHello(WOLFSSL* ssl, const byte* input,
|
||||
#endif
|
||||
WOLFSSL_LOCAL int DoServerHello(WOLFSSL* ssl, const byte* input, word32*,
|
||||
word32);
|
||||
WOLFSSL_LOCAL int CompleteServerHello(WOLFSSL *ssl);
|
||||
WOLFSSL_LOCAL int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv);
|
||||
WOLFSSL_LOCAL void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
|
||||
word32 hashSigAlgoSz);
|
||||
|
@ -234,9 +234,11 @@
|
||||
#define SERVER_DEFAULT_VERSION 3
|
||||
#define SERVER_DTLS_DEFAULT_VERSION (-2)
|
||||
#define SERVER_INVALID_VERSION (-99)
|
||||
#define SERVER_DOWNGRADE_VERSION (-98)
|
||||
#define CLIENT_DEFAULT_VERSION 3
|
||||
#define CLIENT_DTLS_DEFAULT_VERSION (-2)
|
||||
#define CLIENT_INVALID_VERSION (-99)
|
||||
#define CLIENT_DOWNGRADE_VERSION (-98)
|
||||
#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH)
|
||||
#define DEFAULT_MIN_DHKEY_BITS 2048
|
||||
#else
|
||||
|
Loading…
x
Reference in New Issue
Block a user