forked from wolfSSL/wolfssl
Merge pull request #1390 from SparkiDev/tls13_downgrade
Fix downgrading from TLS v1.3 to TLS v1.2
This commit is contained in:
@@ -1027,6 +1027,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v' :
|
case 'v' :
|
||||||
|
if (myoptarg[0] == 'd') {
|
||||||
|
version = CLIENT_DOWNGRADE_VERSION;
|
||||||
|
break;
|
||||||
|
}
|
||||||
version = atoi(myoptarg);
|
version = atoi(myoptarg);
|
||||||
if (version < 0 || version > 4) {
|
if (version < 0 || version > 4) {
|
||||||
Usage();
|
Usage();
|
||||||
@@ -1414,6 +1418,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||||||
method = wolfTLSv1_3_client_method_ex;
|
method = wolfTLSv1_3_client_method_ex;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
case CLIENT_DOWNGRADE_VERSION:
|
||||||
|
method = wolfSSLv23_client_method_ex;
|
||||||
|
break;
|
||||||
#endif /* NO_TLS */
|
#endif /* NO_TLS */
|
||||||
|
|
||||||
#ifdef WOLFSSL_DTLS
|
#ifdef WOLFSSL_DTLS
|
||||||
|
@@ -643,6 +643,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v' :
|
case 'v' :
|
||||||
|
if (myoptarg[0] == 'd') {
|
||||||
|
version = SERVER_DOWNGRADE_VERSION;
|
||||||
|
break;
|
||||||
|
}
|
||||||
version = atoi(myoptarg);
|
version = atoi(myoptarg);
|
||||||
if (version < 0 || version > 4) {
|
if (version < 0 || version > 4) {
|
||||||
Usage();
|
Usage();
|
||||||
@@ -893,6 +897,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
|||||||
method = wolfTLSv1_3_server_method_ex;
|
method = wolfTLSv1_3_server_method_ex;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
case SERVER_DOWNGRADE_VERSION:
|
||||||
|
method = wolfSSLv23_server_method_ex;
|
||||||
|
break;
|
||||||
#endif /* NO_TLS */
|
#endif /* NO_TLS */
|
||||||
|
|
||||||
#ifdef CYASSL_DTLS
|
#ifdef CYASSL_DTLS
|
||||||
|
@@ -373,6 +373,22 @@ if [ $RESULT -eq 0 ]; then
|
|||||||
fi
|
fi
|
||||||
echo ""
|
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.
|
# TLS 1.2 server / TLS 1.3 client.
|
||||||
echo -e "\n\nTLS v1.3 client upgrading server to TLS v1.3"
|
echo -e "\n\nTLS v1.3 client upgrading server to TLS v1.3"
|
||||||
port=0
|
port=0
|
||||||
@@ -389,6 +405,22 @@ if [ $RESULT -eq 0 ]; then
|
|||||||
fi
|
fi
|
||||||
echo ""
|
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.
|
# TLS 1.3 server / TLS 1.3 client send KeyUpdate before sending app data.
|
||||||
echo -e "\n\nTLS v1.3 KeyUpdate"
|
echo -e "\n\nTLS v1.3 KeyUpdate"
|
||||||
port=0
|
port=0
|
||||||
|
@@ -17431,6 +17431,13 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_SECRET_CALLBACK */
|
#endif /* HAVE_SECRET_CALLBACK */
|
||||||
|
|
||||||
|
return CompleteServerHello(ssl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CompleteServerHello(WOLFSSL* ssl)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (ssl->options.resuming) {
|
if (ssl->options.resuming) {
|
||||||
if (DSH_CheckSessionId(ssl)) {
|
if (DSH_CheckSessionId(ssl)) {
|
||||||
if (SetCipherSpecs(ssl) == 0) {
|
if (SetCipherSpecs(ssl) == 0) {
|
||||||
|
@@ -4679,6 +4679,13 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input,
|
|||||||
if (major != pv.major)
|
if (major != pv.major)
|
||||||
return VERSION_ERROR;
|
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. */
|
/* No upgrade allowed. */
|
||||||
if (ssl->version.minor < minor)
|
if (ssl->version.minor < minor)
|
||||||
return VERSION_ERROR;
|
return VERSION_ERROR;
|
||||||
@@ -8062,7 +8069,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_SESSION_TICKET)
|
#if defined(HAVE_SESSION_TICKET)
|
||||||
if (ssl->options.resuming) {
|
if (ssl->options.resuming && ssl->session.ticketLen > 0) {
|
||||||
WOLFSSL_SESSION* sess = &ssl->session;
|
WOLFSSL_SESSION* sess = &ssl->session;
|
||||||
word32 milli;
|
word32 milli;
|
||||||
|
|
||||||
|
96
src/tls13.c
96
src/tls13.c
@@ -2605,6 +2605,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||||||
int ret;
|
int ret;
|
||||||
#ifndef WOLFSSL_TLS13_DRAFT_18
|
#ifndef WOLFSSL_TLS13_DRAFT_18
|
||||||
byte sessIdSz;
|
byte sessIdSz;
|
||||||
|
const byte* sessId;
|
||||||
byte b;
|
byte b;
|
||||||
#endif
|
#endif
|
||||||
word16 totalExtSz;
|
word16 totalExtSz;
|
||||||
@@ -2668,35 +2669,18 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||||||
sessIdSz = input[i++];
|
sessIdSz = input[i++];
|
||||||
if ((i - begin) + sessIdSz > helloSz)
|
if ((i - begin) + sessIdSz > helloSz)
|
||||||
return BUFFER_ERROR;
|
return BUFFER_ERROR;
|
||||||
#ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
|
sessId = input + i;
|
||||||
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 */
|
|
||||||
i += sessIdSz;
|
i += sessIdSz;
|
||||||
ssl->options.haveSessionId = 1;
|
|
||||||
#endif /* WOLFSSL_TLS13_DRAFT_18 */
|
#endif /* WOLFSSL_TLS13_DRAFT_18 */
|
||||||
|
ssl->options.haveSessionId = 1;
|
||||||
|
|
||||||
#ifdef WOLFSSL_TLS13_DRAFT_18
|
#ifdef WOLFSSL_TLS13_DRAFT_18
|
||||||
/* Ciphersuite and extensions length check */
|
/* Ciphersuite check */
|
||||||
if ((i - begin) + OPAQUE16_LEN + OPAQUE16_LEN > helloSz)
|
if ((i - begin) + OPAQUE16_LEN + OPAQUE16_LEN > helloSz)
|
||||||
return BUFFER_ERROR;
|
return BUFFER_ERROR;
|
||||||
#else
|
#else
|
||||||
/* Ciphersuite, compression and extensions length check */
|
/* Ciphersuite and compression check */
|
||||||
if ((i - begin) + OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN > helloSz)
|
if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz)
|
||||||
return BUFFER_ERROR;
|
return BUFFER_ERROR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2713,18 +2697,33 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#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. */
|
/* Get extension length and length check. */
|
||||||
ato16(&input[i], &totalExtSz);
|
ato16(&input[i], &totalExtSz);
|
||||||
i += OPAQUE16_LEN;
|
i += OPAQUE16_LEN;
|
||||||
if ((i - begin) + totalExtSz > helloSz)
|
if ((i - begin) + totalExtSz > helloSz)
|
||||||
return BUFFER_ERROR;
|
return BUFFER_ERROR;
|
||||||
|
|
||||||
|
#ifndef WOLFSSL_TLS13_DRAFT_18
|
||||||
|
if (ssl->options.downgrade)
|
||||||
|
ssl->version.minor = TLSv1_2_MINOR;
|
||||||
|
#endif
|
||||||
/* Parse and handle extensions. */
|
/* Parse and handle extensions. */
|
||||||
ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, extMsgType, NULL);
|
ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, extMsgType, NULL);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
i += totalExtSz;
|
i += totalExtSz;
|
||||||
|
}
|
||||||
*inOutIdx = i;
|
*inOutIdx = i;
|
||||||
|
|
||||||
ssl->options.serverState = SERVER_HELLO_COMPLETE;
|
ssl->options.serverState = SERVER_HELLO_COMPLETE;
|
||||||
@@ -2739,6 +2738,51 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_SECRET_CALLBACK */
|
#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);
|
ret = SetCipherSpecs(ssl);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -3173,6 +3217,9 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Hash the rest of the ClientHello. */
|
/* Hash the rest of the ClientHello. */
|
||||||
ret = HashInputRaw(ssl, input + helloSz - bindersLen, bindersLen);
|
ret = HashInputRaw(ssl, input + helloSz - bindersLen, bindersLen);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
@@ -3567,10 +3614,11 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_STUNNEL
|
#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
|
||||||
if ((ret = SNI_Callback(ssl)) != 0)
|
if ((ret = SNI_Callback(ssl)) != 0)
|
||||||
return ret;
|
return ret;
|
||||||
#endif /*HAVE_STUNNEL*/
|
ssl->options.side = WOLFSSL_SERVER_END;
|
||||||
|
#endif /* HAVE_STUNNELi || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
|
||||||
|
|
||||||
if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS) == NULL) {
|
if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS) == NULL) {
|
||||||
if (!ssl->options.downgrade) {
|
if (!ssl->options.downgrade) {
|
||||||
|
@@ -1481,6 +1481,7 @@ WOLFSSL_LOCAL int DoTls13ClientHello(WOLFSSL* ssl, const byte* input,
|
|||||||
#endif
|
#endif
|
||||||
WOLFSSL_LOCAL int DoServerHello(WOLFSSL* ssl, const byte* input, word32*,
|
WOLFSSL_LOCAL int DoServerHello(WOLFSSL* ssl, const byte* input, word32*,
|
||||||
word32);
|
word32);
|
||||||
|
WOLFSSL_LOCAL int CompleteServerHello(WOLFSSL *ssl);
|
||||||
WOLFSSL_LOCAL int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv);
|
WOLFSSL_LOCAL int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv);
|
||||||
WOLFSSL_LOCAL void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
|
WOLFSSL_LOCAL void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
|
||||||
word32 hashSigAlgoSz);
|
word32 hashSigAlgoSz);
|
||||||
|
@@ -234,9 +234,11 @@
|
|||||||
#define SERVER_DEFAULT_VERSION 3
|
#define SERVER_DEFAULT_VERSION 3
|
||||||
#define SERVER_DTLS_DEFAULT_VERSION (-2)
|
#define SERVER_DTLS_DEFAULT_VERSION (-2)
|
||||||
#define SERVER_INVALID_VERSION (-99)
|
#define SERVER_INVALID_VERSION (-99)
|
||||||
|
#define SERVER_DOWNGRADE_VERSION (-98)
|
||||||
#define CLIENT_DEFAULT_VERSION 3
|
#define CLIENT_DEFAULT_VERSION 3
|
||||||
#define CLIENT_DTLS_DEFAULT_VERSION (-2)
|
#define CLIENT_DTLS_DEFAULT_VERSION (-2)
|
||||||
#define CLIENT_INVALID_VERSION (-99)
|
#define CLIENT_INVALID_VERSION (-99)
|
||||||
|
#define CLIENT_DOWNGRADE_VERSION (-98)
|
||||||
#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH)
|
#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH)
|
||||||
#define DEFAULT_MIN_DHKEY_BITS 2048
|
#define DEFAULT_MIN_DHKEY_BITS 2048
|
||||||
#else
|
#else
|
||||||
|
Reference in New Issue
Block a user