Merge pull request #1390 from SparkiDev/tls13_downgrade

Fix downgrading from TLS v1.3 to TLS v1.2
pull/1388/head
toddouska 2018-02-22 08:53:48 -08:00 committed by GitHub
commit 41ae47fa3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 148 additions and 35 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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;
@ -8062,7 +8069,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
}
#if defined(HAVE_SESSION_TICKET)
if (ssl->options.resuming) {
if (ssl->options.resuming && ssl->session.ticketLen > 0) {
WOLFSSL_SESSION* sess = &ssl->session;
word32 milli;

View File

@ -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;
@ -3173,6 +3217,9 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
break;
}
if (current == NULL)
return 0;
/* Hash the rest of the ClientHello. */
ret = HashInputRaw(ssl, input + helloSz - bindersLen, bindersLen);
if (ret != 0)
@ -3567,10 +3614,11 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
return ret;
}
#ifdef HAVE_STUNNEL
#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
if ((ret = SNI_Callback(ssl)) != 0)
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 (!ssl->options.downgrade) {

View File

@ -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);

View File

@ -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