mirror of https://github.com/wolfSSL/wolfssl.git
Merge pull request #5276 from rizlik/dtls13_client_downgrade
Dtls: improve version negotiationpull/5330/head
commit
b2d1bf96ed
|
@ -475,7 +475,163 @@ WOLFSSL_METHOD *wolfDTLSv1_client_method(void);
|
|||
\sa wolfSSL_CTX_new
|
||||
*/
|
||||
WOLFSSL_METHOD *wolfDTLSv1_server_method(void);
|
||||
/*!
|
||||
\ingroup Setup
|
||||
|
||||
\brief The wolfDTLSv1_3_server_method() function is used to indicate that
|
||||
the application is a server and will only support the DTLS 1.3
|
||||
protocol. This function allocates memory for and initializes a new
|
||||
wolfSSL_METHOD structure to be used when creating the SSL/TLS context with
|
||||
wolfSSL_CTX_new(). This function is only available when wolfSSL has been
|
||||
compiled with DTLSv1.3 support (--enable-dtls13, or by defining
|
||||
wolfSSL_DTLS13).
|
||||
|
||||
\return * If successful, the call will return a pointer to the newly
|
||||
created WOLFSSL_METHOD structure.
|
||||
\return FAIL If memory allocation fails when calling XMALLOC, the failure
|
||||
value of the underlying malloc() implementation will be returned
|
||||
(typically NULL with errno will be set to ENOMEM).
|
||||
|
||||
\param none No parameters.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
WOLFSSL_METHOD* method;
|
||||
WOLFSSL_CTX* ctx;
|
||||
|
||||
method = wolfDTLSv1_3_server_method();
|
||||
if (method == NULL) {
|
||||
// unable to get method
|
||||
}
|
||||
|
||||
ctx = wolfSSL_CTX_new(method);
|
||||
...
|
||||
\endcode
|
||||
|
||||
|
||||
\sa wolfDTLSv1_3_client_method
|
||||
*/
|
||||
|
||||
WOLFSSL_METHOD *wolfDTLSv1_3_server_method(void);
|
||||
/*!
|
||||
\ingroup Setup
|
||||
|
||||
\brief The wolfDTLSv1_3_client_method() function is used to indicate that
|
||||
the application is a client and will only support the DTLS 1.3
|
||||
protocol. This function allocates memory for and initializes a new
|
||||
wolfSSL_METHOD structure to be used when creating the SSL/TLS context with
|
||||
wolfSSL_CTX_new(). This function is only available when wolfSSL has been
|
||||
compiled with DTLSv1.3 support (--enable-dtls13, or by defining
|
||||
wolfSSL_DTLS13).
|
||||
|
||||
\return * If successful, the call will return a pointer to the newly
|
||||
created WOLFSSL_METHOD structure.
|
||||
\return FAIL If memory allocation fails when calling XMALLOC, the failure
|
||||
value of the underlying malloc() implementation will be returned
|
||||
(typically NULL with errno will be set to ENOMEM).
|
||||
|
||||
\param none No parameters.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
WOLFSSL_METHOD* method;
|
||||
WOLFSSL_CTX* ctx;
|
||||
|
||||
method = wolfDTLSv1_3_client_method();
|
||||
if (method == NULL) {
|
||||
// unable to get method
|
||||
}
|
||||
|
||||
ctx = wolfSSL_CTX_new(method);
|
||||
...
|
||||
\endcode
|
||||
|
||||
|
||||
\sa wolfDTLSv1_3_server_method
|
||||
*/
|
||||
WOLFSSL_METHOD* wolfDTLSv1_3_client_method(void);
|
||||
/*!
|
||||
\ingroup Setup
|
||||
|
||||
\brief The wolfDTLS_server_method() function is used to indicate that the
|
||||
application is a server and will support the highest version of DTLS
|
||||
available and all the version up to the minimum version allowed. The
|
||||
default minimum version allowed is based on the define
|
||||
WOLFSSL_MIN_DTLS_DOWNGRADE and can be changed at runtime using
|
||||
wolfSSL_SetMinVersion(). This function allocates memory for and initializes
|
||||
a new wolfSSL_METHOD structure to be used when creating the SSL/TLS context
|
||||
with wolfSSL_CTX_new(). This function is only available when wolfSSL has
|
||||
been compiled with DTLS support (--enable-dtls, or by defining
|
||||
wolfSSL_DTLS).
|
||||
|
||||
\return * If successful, the call will return a pointer to the newly
|
||||
created WOLFSSL_METHOD structure.
|
||||
\return FAIL If memory allocation fails when calling XMALLOC, the failure
|
||||
value of the underlying malloc() implementation will be returned
|
||||
(typically NULL with errno will be set to ENOMEM).
|
||||
|
||||
\param none No parameters.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
WOLFSSL_METHOD* method;
|
||||
WOLFSSL_CTX* ctx;
|
||||
|
||||
method = wolfDTLS_server_method();
|
||||
if (method == NULL) {
|
||||
// unable to get method
|
||||
}
|
||||
|
||||
ctx = wolfSSL_CTX_new(method);
|
||||
...
|
||||
\endcode
|
||||
|
||||
|
||||
\sa wolfDTLS_client_method
|
||||
\sa wolfSSL_SetMinVersion
|
||||
*/
|
||||
WOLFSSL_METHOD *wolfDTLS_server_method(void);
|
||||
/*!
|
||||
\ingroup Setup
|
||||
|
||||
\brief The wolfDTLS_client_method() function is used to indicate that the
|
||||
application is a client and will support the highest version of DTLS
|
||||
available and all the version up to the minimum version allowed. The
|
||||
default minimum version allowed is based on the define
|
||||
WOLFSSL_MIN_DTLS_DOWNGRADE and can be changed at runtime using
|
||||
wolfSSL_SetMinVersion(). This function allocates memory for and initializes
|
||||
a new wolfSSL_METHOD structure to be used when creating the SSL/TLS context
|
||||
with wolfSSL_CTX_new(). This function is only available when wolfSSL has
|
||||
been compiled with DTLS support (--enable-dtls, or by defining
|
||||
wolfSSL_DTLS).
|
||||
|
||||
\return * If successful, the call will return a pointer to the newly
|
||||
created WOLFSSL_METHOD structure.
|
||||
\return FAIL If memory allocation fails when calling XMALLOC, the failure
|
||||
value of the underlying malloc() implementation will be returned
|
||||
(typically NULL with errno will be set to ENOMEM).
|
||||
|
||||
\param none No parameters.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
WOLFSSL_METHOD* method;
|
||||
WOLFSSL_CTX* ctx;
|
||||
|
||||
method = wolfDTLS_client_method();
|
||||
if (method == NULL) {
|
||||
// unable to get method
|
||||
}
|
||||
|
||||
ctx = wolfSSL_CTX_new(method);
|
||||
...
|
||||
\endcode
|
||||
|
||||
|
||||
\sa wolfDTLS_server_method
|
||||
\sa wolfSSL_SetMinVersion
|
||||
*/
|
||||
WOLFSSL_METHOD *wolfDTLS_client_method(void);
|
||||
/*!
|
||||
\brief This function creates and initializes a WOLFSSL_METHOD for the
|
||||
server side.
|
||||
|
|
|
@ -2802,7 +2802,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||
err_sys("Bad DTLS version");
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
}
|
||||
else
|
||||
else if (version == 2)
|
||||
version = -1;
|
||||
}
|
||||
}
|
||||
|
@ -2859,7 +2859,16 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||
#endif
|
||||
|
||||
case CLIENT_DOWNGRADE_VERSION:
|
||||
method = wolfSSLv23_client_method_ex;
|
||||
if (!doDTLS) {
|
||||
method = wolfSSLv23_client_method_ex;
|
||||
}
|
||||
else {
|
||||
#ifdef WOLFSSL_DTLS
|
||||
method = wolfDTLS_client_method_ex;
|
||||
#else
|
||||
err_sys("version not supported");
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
}
|
||||
break;
|
||||
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
|
||||
case EITHER_DOWNGRADE_VERSION:
|
||||
|
@ -2934,7 +2943,28 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||
}
|
||||
#endif
|
||||
if (minVersion != CLIENT_INVALID_VERSION) {
|
||||
wolfSSL_CTX_SetMinVersion(ctx, minVersion);
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (doDTLS) {
|
||||
switch (minVersion) {
|
||||
case 4:
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
minVersion = WOLFSSL_DTLSV1_3;
|
||||
break;
|
||||
#else
|
||||
err_sys("invalid minimum downgrade version");
|
||||
break;
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
case 3:
|
||||
minVersion = WOLFSSL_DTLSV1_2;
|
||||
break;
|
||||
case 2:
|
||||
minVersion = WOLFSSL_DTLSV1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
if (wolfSSL_CTX_SetMinVersion(ctx, minVersion) != WOLFSSL_SUCCESS)
|
||||
err_sys("can't set minimum downgrade version");
|
||||
}
|
||||
if (simulateWantWrite) {
|
||||
#ifdef USE_WOLFSSL_IO
|
||||
|
|
|
@ -2265,11 +2265,11 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
|
|||
method = wolfSSLv23_server_method_ex;
|
||||
}
|
||||
else {
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
#ifdef WOLFSSL_DTLS
|
||||
method = wolfDTLS_server_method_ex;
|
||||
#else
|
||||
err_sys_ex(runWithErrors, "version not supported");
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
}
|
||||
break;
|
||||
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
|
||||
|
@ -2341,12 +2341,14 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
|
|||
err_sys_ex(catastrophic, "unable to get ctx");
|
||||
|
||||
if (minVersion != SERVER_INVALID_VERSION) {
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (doDTLS) {
|
||||
switch (minVersion) {
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
case 4:
|
||||
minVersion = WOLFSSL_DTLSV1_3;
|
||||
break;
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
case 3:
|
||||
minVersion = WOLFSSL_DTLSV1_2;
|
||||
break;
|
||||
|
@ -2356,7 +2358,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
|
|||
}
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
wolfSSL_CTX_SetMinVersion(ctx, minVersion);
|
||||
if (wolfSSL_CTX_SetMinVersion(ctx, minVersion) != WOLFSSL_SUCCESS)
|
||||
err_sys_ex(catastrophic, "can't set minimum downgrade version");
|
||||
}
|
||||
|
||||
#ifdef OPENSSL_COMPATIBLE_DEFAULTS
|
||||
|
|
32
src/dtls13.c
32
src/dtls13.c
|
@ -718,6 +718,35 @@ static void Dtls13RtxRemoveCurAck(WOLFSSL* ssl)
|
|||
}
|
||||
}
|
||||
|
||||
static void Dtls13MaybeSaveClientHello(WOLFSSL* ssl)
|
||||
{
|
||||
Dtls13RtxRecord *r, **prev_next;
|
||||
|
||||
r = ssl->dtls13Rtx.rtxRecords;
|
||||
prev_next = &ssl->dtls13Rtx.rtxRecords;
|
||||
|
||||
if (ssl->options.side == WOLFSSL_CLIENT_END &&
|
||||
ssl->options.connectState >= CLIENT_HELLO_SENT &&
|
||||
ssl->options.connectState <= HELLO_AGAIN_REPLY &&
|
||||
ssl->options.downgrade && ssl->options.minDowngrade >= DTLSv1_2_MINOR) {
|
||||
while (r != NULL) {
|
||||
if (r->handshakeType == client_hello) {
|
||||
Dtls13RtxRecordUnlink(ssl, prev_next, r);
|
||||
if (ssl->dtls13ClientHello != NULL)
|
||||
XFREE(ssl->dtls13ClientHello, ssl->heap,
|
||||
DYNAMIC_TYPE_DTLS_MSG);
|
||||
ssl->dtls13ClientHello = r->data;
|
||||
ssl->dtls13ClientHelloSz = r->length;
|
||||
r->data = NULL;
|
||||
Dtls13FreeRtxBufferRecord(ssl, r);
|
||||
return;
|
||||
}
|
||||
prev_next = &r->next;
|
||||
r = r->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int Dtls13RtxMsgRecvd(WOLFSSL* ssl, enum HandShakeType hs,
|
||||
word32 fragOffset)
|
||||
{
|
||||
|
@ -727,6 +756,9 @@ static int Dtls13RtxMsgRecvd(WOLFSSL* ssl, enum HandShakeType hs,
|
|||
ssl->keys.dtls_peer_handshake_number >=
|
||||
ssl->keys.dtls_expected_peer_handshake_number) {
|
||||
|
||||
if (hs == server_hello)
|
||||
Dtls13MaybeSaveClientHello(ssl);
|
||||
|
||||
/* In the handshake, receiving part of the next flight, acknowledge the
|
||||
sent flight. The only exception is, on the server side, receiving the
|
||||
last client flight does not ACK any sent new_session_ticket
|
||||
|
|
120
src/internal.c
120
src/internal.c
|
@ -147,8 +147,6 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
|
|||
#ifndef WOLFSSL_NO_TLS12
|
||||
|
||||
#ifndef NO_WOLFSSL_CLIENT
|
||||
static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input,
|
||||
word32* inOutIdx, word32 size);
|
||||
static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
|
||||
word32* inOutIdx, word32 size);
|
||||
#ifndef NO_CERTS
|
||||
|
@ -7286,6 +7284,15 @@ void SSL_ResourceFree(WOLFSSL* ssl)
|
|||
XFREE(ssl->buffers.dtlsCookieSecret.buffer, ssl->heap,
|
||||
DYNAMIC_TYPE_COOKIE_PWD);
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
if (ssl->dtls13ClientHello != NULL) {
|
||||
XFREE(ssl->dtls13ClientHello, ssl->heap, DYNAMIC_TYPE_DTLS_MSG);
|
||||
ssl->dtls13ClientHello = NULL;
|
||||
ssl->dtls13ClientHelloSz = 0;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
#ifdef OPENSSL_EXTRA
|
||||
#ifndef NO_BIO
|
||||
|
@ -7505,12 +7512,21 @@ void FreeHandshakeResources(WOLFSSL* ssl)
|
|||
WOLFSSL_ENTER("FreeHandshakeResources");
|
||||
|
||||
#ifdef WOLFSSL_DTLS
|
||||
/* DTLS_POOL (DTLSv1.3 flushes the queue autonomously) */
|
||||
if (ssl->options.dtls && !IsAtLeastTLSv1_3(ssl->version)) {
|
||||
DtlsMsgPoolReset(ssl);
|
||||
DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap);
|
||||
ssl->dtls_rx_msg_list = NULL;
|
||||
ssl->dtls_rx_msg_list_sz = 0;
|
||||
if (ssl->options.dtls) {
|
||||
/* DTLS_POOL (DTLSv1.3 flushes the queue autonomously) */
|
||||
if(!IsAtLeastTLSv1_3(ssl->version)) {
|
||||
DtlsMsgPoolReset(ssl);
|
||||
DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap);
|
||||
ssl->dtls_rx_msg_list = NULL;
|
||||
ssl->dtls_rx_msg_list_sz = 0;
|
||||
}
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
if (ssl->dtls13ClientHello != NULL) {
|
||||
XFREE(ssl->dtls13ClientHello, ssl->heap, DYNAMIC_TYPE_DTLS_MSG);
|
||||
ssl->dtls13ClientHello = NULL;
|
||||
ssl->dtls13ClientHelloSz = 0;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -10022,7 +10038,7 @@ int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input,
|
|||
(!IsAtLeastTLSv1_3(ssl->version) && ssl->curRL.pvMinor != ssl->version.minor) ||
|
||||
(IsAtLeastTLSv1_3(ssl->version) && ssl->curRL.pvMinor != DTLSv1_2_MINOR)
|
||||
) {
|
||||
if (*type != client_hello && *type != hello_verify_request) {
|
||||
if (*type != client_hello && *type != hello_verify_request && *type != server_hello) {
|
||||
WOLFSSL_ERROR(VERSION_ERROR);
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
|
@ -24605,8 +24621,8 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
|
|||
|
||||
|
||||
/* handle processing of DTLS hello_verify_request (3) */
|
||||
static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input,
|
||||
word32* inOutIdx, word32 size)
|
||||
int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
word32 size)
|
||||
{
|
||||
ProtocolVersion pv;
|
||||
byte cookieSz;
|
||||
|
@ -24648,7 +24664,18 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
|
|||
*inOutIdx += cookieSz;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_TLS13)
|
||||
if (IsAtLeastTLSv1_3(ssl->version) && ssl->options.dtls) {
|
||||
/* we sent a TLSv1.3 ClientHello but received a
|
||||
* HELLO_VERIFY_REQUEST */
|
||||
if (!ssl->options.downgrade ||
|
||||
ssl->options.minDowngrade < pv.minor)
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
#endif /* defined(WOLFSSL_DTLS13) && defined(WOLFSSL_TLS13) */
|
||||
|
||||
ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -24689,6 +24716,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
|
|||
*/
|
||||
int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv)
|
||||
{
|
||||
byte lowerVersion, higherVersion;
|
||||
#ifdef WOLFSSL_TLS13_DRAFT
|
||||
if (pv.major == TLS_DRAFT_MAJOR) {
|
||||
pv.major = SSLv3_MAJOR;
|
||||
|
@ -24702,11 +24730,24 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
|
|||
}
|
||||
#endif
|
||||
|
||||
if (pv.minor > ssl->version.minor) {
|
||||
if (ssl->options.dtls) {
|
||||
if (pv.major != DTLS_MAJOR || pv.minor == DTLS_BOGUS_MINOR)
|
||||
return VERSION_ERROR;
|
||||
lowerVersion = pv.minor > ssl->version.minor;
|
||||
higherVersion = pv.minor < ssl->version.minor;
|
||||
}
|
||||
else {
|
||||
if (pv.major != SSLv3_MAJOR)
|
||||
return VERSION_ERROR;
|
||||
lowerVersion = pv.minor < ssl->version.minor;
|
||||
higherVersion = pv.minor > ssl->version.minor;
|
||||
}
|
||||
|
||||
if (higherVersion) {
|
||||
WOLFSSL_MSG("Server using higher version, fatal error");
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
if (pv.minor < ssl->version.minor) {
|
||||
if (lowerVersion) {
|
||||
WOLFSSL_MSG("server using lower version");
|
||||
|
||||
/* Check for downgrade attack. */
|
||||
|
@ -24714,7 +24755,8 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
|
|||
WOLFSSL_MSG("\tno downgrade allowed, fatal error");
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
if (pv.minor < ssl->options.minDowngrade) {
|
||||
if ((!ssl->options.dtls && pv.minor < ssl->options.minDowngrade) ||
|
||||
(ssl->options.dtls && pv.minor > ssl->options.minDowngrade)) {
|
||||
WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
|
@ -24729,27 +24771,35 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
|
|||
#endif
|
||||
|
||||
/* Checks made - OK to downgrade. */
|
||||
if (pv.minor == SSLv3_MINOR) {
|
||||
/* turn off tls */
|
||||
WOLFSSL_MSG("\tdowngrading to SSLv3");
|
||||
ssl->options.tls = 0;
|
||||
ssl->options.tls1_1 = 0;
|
||||
ssl->version.minor = SSLv3_MINOR;
|
||||
}
|
||||
else if (pv.minor == TLSv1_MINOR) {
|
||||
/* turn off tls 1.1+ */
|
||||
WOLFSSL_MSG("\tdowngrading to TLSv1");
|
||||
ssl->options.tls1_1 = 0;
|
||||
ssl->version.minor = TLSv1_MINOR;
|
||||
}
|
||||
else if (pv.minor == TLSv1_1_MINOR) {
|
||||
WOLFSSL_MSG("\tdowngrading to TLSv1.1");
|
||||
ssl->version.minor = TLSv1_1_MINOR;
|
||||
}
|
||||
else if (pv.minor == TLSv1_2_MINOR) {
|
||||
WOLFSSL_MSG(" downgrading to TLSv1.2");
|
||||
ssl->version.minor = TLSv1_2_MINOR;
|
||||
}
|
||||
ssl->version.minor = pv.minor;
|
||||
switch(pv.minor) {
|
||||
case SSLv3_MINOR:
|
||||
/* turn off tls */
|
||||
WOLFSSL_MSG("\tdowngrading to SSLv3");
|
||||
ssl->options.tls = 0;
|
||||
ssl->options.tls1_1 = 0;
|
||||
break;
|
||||
case TLSv1_MINOR:
|
||||
/* turn off tls 1.1+ */
|
||||
WOLFSSL_MSG("\tdowngrading to TLSv1");
|
||||
ssl->options.tls1_1 = 0;
|
||||
break;
|
||||
case TLSv1_1_MINOR:
|
||||
WOLFSSL_MSG("\tdowngrading to TLSv1.1");
|
||||
break;
|
||||
case DTLS_MINOR:
|
||||
WOLFSSL_MSG("\tdowngrading to DTLSv1.1");
|
||||
break;
|
||||
case TLSv1_2_MINOR:
|
||||
WOLFSSL_MSG("\tdowngrading to TLSv1.2");
|
||||
break;
|
||||
case DTLSv1_2_MINOR:
|
||||
WOLFSSL_MSG("\tdowngrading to DTLSv1.2");
|
||||
break;
|
||||
default:
|
||||
WOLFSSL_MSG("\tbad minor version");
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OPENSSL_EXTRA
|
||||
|
|
|
@ -4549,17 +4549,19 @@ static int SetMinVersionHelper(byte* minVersion, int version)
|
|||
break;
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
#ifdef WOLFSSL_DTLS
|
||||
case WOLFSSL_DTLSV1:
|
||||
*minVersion = DTLS_MINOR;
|
||||
break;
|
||||
case WOLFSSL_DTLSV1_2:
|
||||
*minVersion = DTLSv1_2_MINOR;
|
||||
break;
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
case WOLFSSL_DTLSV1_3:
|
||||
*minVersion = DTLSv1_3_MINOR;
|
||||
break;
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
|
||||
default:
|
||||
WOLFSSL_MSG("Bad function argument");
|
||||
|
|
130
src/tls13.c
130
src/tls13.c
|
@ -3424,9 +3424,14 @@ int SendTls13ClientHello(WOLFSSL* ssl)
|
|||
#endif
|
||||
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
/* legacy_cookie_id (always 0 length) */
|
||||
if (ssl->options.dtls)
|
||||
args->length += OPAQUE8_LEN;
|
||||
if (ssl->options.dtls) {
|
||||
/* legacy_cookie_id len */
|
||||
args->length += ENUM_LEN;
|
||||
|
||||
/* server sent us an HelloVerifyRequest and we allow downgrade */
|
||||
if (ssl->arrays->cookieSz > 0 && ssl->options.downgrade)
|
||||
args->length += ssl->arrays->cookieSz;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
|
||||
/* Advance state and proceed */
|
||||
|
@ -3532,9 +3537,19 @@ int SendTls13ClientHello(WOLFSSL* ssl)
|
|||
}
|
||||
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
/* legacy_cookie_id. always 0 length vector */
|
||||
if (ssl->options.dtls)
|
||||
args->output[args->idx++] = 0;
|
||||
if (ssl->options.dtls) {
|
||||
args->output[args->idx++] = ssl->arrays->cookieSz;
|
||||
|
||||
if (ssl->arrays->cookieSz > 0) {
|
||||
/* We have a cookie saved, so the server sent us an
|
||||
* HelloVerifyRequest, it means it is a v1.2 server */
|
||||
if (!ssl->options.downgrade)
|
||||
return VERSION_ERROR;
|
||||
XMEMCPY(args->output + args->idx, ssl->arrays->cookie,
|
||||
ssl->arrays->cookieSz);
|
||||
args->idx += ssl->arrays->cookieSz;
|
||||
}
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
|
||||
/* Cipher suites */
|
||||
|
@ -3639,6 +3654,32 @@ int SendTls13ClientHello(WOLFSSL* ssl)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_NO_CLIENT)
|
||||
static int Dtls13DoDowngrade(WOLFSSL* ssl)
|
||||
{
|
||||
int ret;
|
||||
if (ssl->dtls13ClientHello == NULL)
|
||||
return BAD_STATE_E;
|
||||
|
||||
/* v1.3 and v1.2 hash messages to compute the transcript hash. When we are
|
||||
* using DTLSv1.3 we hash the first clientHello following v1.3 but the
|
||||
* server can negotiate a lower version. So we need to re-hash the
|
||||
* clientHello to adhere to DTLS <= v1.2 rules. */
|
||||
ret = InitHandshakeHashes(ssl);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret = HashRaw(ssl, ssl->dtls13ClientHello, ssl->dtls13ClientHelloSz);
|
||||
XFREE(ssl->dtls13ClientHello, ssl->heap, DYNAMIC_TYPE_DTLS_MSG);
|
||||
ssl->dtls13ClientHello = NULL;
|
||||
ssl->dtls13ClientHelloSz = 0;
|
||||
ssl->keys.dtls_sequence_number_hi =
|
||||
w64GetHigh32(ssl->dtls13EncryptEpoch->nextSeqNumber);
|
||||
ssl->keys.dtls_sequence_number_lo =
|
||||
w64GetLow32(ssl->dtls13EncryptEpoch->nextSeqNumber);
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS13 && !WOLFSSL_NO_CLIENT*/
|
||||
|
||||
/* handle processing of TLS 1.3 server_hello (2) and hello_retry_request (6) */
|
||||
/* Handle the ServerHello message from the server.
|
||||
* Only a client will receive this message.
|
||||
|
@ -3738,6 +3779,12 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||
XMEMCPY(&args->pv, input + args->idx, OPAQUE16_LEN);
|
||||
args->idx += OPAQUE16_LEN;
|
||||
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (ssl->options.dtls &&
|
||||
(args->pv.major != DTLS_MAJOR || args->pv.minor == DTLS_BOGUS_MINOR))
|
||||
return VERSION_ERROR;
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
|
||||
#ifndef WOLFSSL_NO_TLS12
|
||||
{
|
||||
byte wantDowngrade;
|
||||
|
@ -3760,6 +3807,9 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||
if (ssl->options.dtls) {
|
||||
ssl->chVersion.minor = DTLSv1_2_MINOR;
|
||||
ssl->version.minor = DTLSv1_2_MINOR;
|
||||
ret = Dtls13DoDowngrade(ssl);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
|
||||
|
@ -3837,6 +3887,9 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||
if (ssl->options.dtls) {
|
||||
ssl->chVersion.minor = DTLSv1_2_MINOR;
|
||||
ssl->version.minor = DTLSv1_2_MINOR;
|
||||
ret = Dtls13DoDowngrade(ssl);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
|
||||
|
@ -3891,9 +3944,28 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||
return VERSION_ERROR;
|
||||
|
||||
ssl->version.minor = args->pv.minor;
|
||||
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
if (ssl->options.dtls) {
|
||||
ret = Dtls13DoDowngrade(ssl);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
/* we are sure that version is >= v1.3 now, we can get rid of buffered
|
||||
* ClientHello that was buffered to re-compute the hash in case of
|
||||
* downgrade */
|
||||
if (ssl->options.dtls && ssl->dtls13ClientHello != NULL) {
|
||||
XFREE(ssl->dtls13ClientHello, ssl->heap, DYNAMIC_TYPE_DTLS_MSG);
|
||||
ssl->dtls13ClientHello = NULL;
|
||||
ssl->dtls13ClientHelloSz = 0;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
|
||||
/* Advance state and proceed */
|
||||
ssl->options.asyncState = TLS_ASYNC_BUILD;
|
||||
} /* case TLS_ASYNC_BEGIN */
|
||||
|
@ -9178,6 +9250,40 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
|
|||
}
|
||||
/* Multiple KeyUpdates can be sent. */
|
||||
break;
|
||||
#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_NO_TLS12)
|
||||
case hello_verify_request:
|
||||
if (!ssl->options.dtls) {
|
||||
WOLFSSL_MSG("HelloVerifyRequest when not in DTLS");
|
||||
return OUT_OF_ORDER_E;
|
||||
}
|
||||
if (ssl->msgsReceived.got_hello_verify_request) {
|
||||
WOLFSSL_MSG("Duplicate HelloVerifyRequest received");
|
||||
return DUPLICATE_MSG_E;
|
||||
}
|
||||
ssl->msgsReceived.got_hello_verify_request = 1;
|
||||
if (ssl->msgsReceived.got_hello_retry_request) {
|
||||
WOLFSSL_MSG(
|
||||
"Both HelloVerifyRequest and HelloRetryRequest received");
|
||||
return DUPLICATE_MSG_E;
|
||||
}
|
||||
if (ssl->options.serverState >=
|
||||
SERVER_HELLO_RETRY_REQUEST_COMPLETE ||
|
||||
ssl->options.connectState != CLIENT_HELLO_SENT) {
|
||||
WOLFSSL_MSG("HelloVerifyRequest received out of order");
|
||||
return OUT_OF_ORDER_E;
|
||||
}
|
||||
if (ssl->options.side == WOLFSSL_SERVER_END) {
|
||||
WOLFSSL_MSG("HelloVerifyRequest recevied on the server");
|
||||
return SIDE_ERROR;
|
||||
}
|
||||
if (!ssl->options.downgrade ||
|
||||
ssl->options.minDowngrade < DTLSv1_2_MINOR) {
|
||||
WOLFSSL_MSG(
|
||||
"HelloVerifyRequest recevied but not DTLSv1.2 allowed");
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
break;
|
||||
#endif /* WOLFSSL_DTLS13 && !WOLFSSL_NO_TLS12*/
|
||||
|
||||
default:
|
||||
WOLFSSL_MSG("Unknown message type");
|
||||
|
@ -9238,7 +9344,11 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||
|
||||
if (ssl->options.side == WOLFSSL_CLIENT_END &&
|
||||
ssl->options.serverState == NULL_STATE &&
|
||||
type != server_hello && type != hello_retry_request) {
|
||||
type != server_hello && type != hello_retry_request
|
||||
#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_NO_TLS12)
|
||||
&& (!ssl->options.dtls || type != hello_verify_request)
|
||||
#endif /* defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_NO_TLS12) */
|
||||
) {
|
||||
WOLFSSL_MSG("First server message not server hello");
|
||||
SendAlert(ssl, alert_fatal, unexpected_message);
|
||||
return OUT_OF_ORDER_E;
|
||||
|
@ -9332,6 +9442,12 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||
ret = DoTls13KeyUpdate(ssl, input, inOutIdx, size);
|
||||
break;
|
||||
|
||||
#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_NO_TLS12)
|
||||
case hello_verify_request:
|
||||
WOLFSSL_MSG("processing hello verify request");
|
||||
ret = DoHelloVerifyRequest(ssl, input, inOutIdx, size);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
WOLFSSL_MSG("Unknown handshake message type");
|
||||
ret = UNKNOWN_HANDSHAKE_TYPE;
|
||||
|
|
|
@ -30,6 +30,7 @@ EXTRA_DIST += tests/unit.h \
|
|||
tests/test-psk-no-id.conf \
|
||||
tests/test-psk-no-id-sha2.conf \
|
||||
tests/test-dtls.conf \
|
||||
tests/test-dtls-downgrade.conf \
|
||||
tests/test-dtls-fails.conf \
|
||||
tests/test-dtls-fails-cipher.conf \
|
||||
tests/test-dtls-group.conf \
|
||||
|
|
|
@ -1023,6 +1023,17 @@ int SuiteTest(int argc, char** argv)
|
|||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Add dtls downgrade test */
|
||||
XSTRLCPY(argv0[1], "tests/test-dtls-downgrade.conf", sizeof(argv0[1]));
|
||||
printf("starting dtls downgrade tests\n");
|
||||
test_harness(&args);
|
||||
if (args.return_code != 0) {
|
||||
printf("error from script %d\n", args.return_code);
|
||||
args.return_code = EXIT_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
|
||||
/* add dtls extra suites */
|
||||
XSTRLCPY(argv0[1], "tests/test-dtls-sha2.conf", sizeof(argv0[1]));
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# server DTLS multiversion allow downgrading
|
||||
-vd
|
||||
-7 2
|
||||
-u
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
|
||||
# client DTLSv1.0
|
||||
-v 2
|
||||
-u
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
|
||||
# server DTLSv1.0
|
||||
-v 2
|
||||
-u
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
|
||||
# client DTLS multiversion allow downgrading
|
||||
-vd
|
||||
-7 2
|
||||
-u
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
|
@ -1,11 +1,43 @@
|
|||
# server DTLSv1.3 allow downgrading
|
||||
# server DTLS multiversion allow downgrade
|
||||
-vd
|
||||
-7 2
|
||||
-u
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
|
||||
# client TLSv1.2 group message
|
||||
# client DTLSv1.2
|
||||
-v 3
|
||||
-u
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||
-f
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
|
||||
# server DTLS multiversion allow downgrade
|
||||
-vd
|
||||
-7 2
|
||||
-u
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
|
||||
# client DTLSv1.0
|
||||
-v 2
|
||||
-u
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
|
||||
# server DTLSv1.0
|
||||
-v 2
|
||||
-u
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
|
||||
# client DTLS multiversion, allow downgrade
|
||||
-vd
|
||||
-7 2
|
||||
-u
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
|
||||
# server DTLSv1.2
|
||||
-v 3
|
||||
-u
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
|
||||
# client DTLS multiversion, allow downgrade
|
||||
-vd
|
||||
-7 2
|
||||
-u
|
||||
-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
|
|
|
@ -1205,6 +1205,7 @@ enum Misc {
|
|||
|
||||
DTLS_MAJOR = 0xfe, /* DTLS major version number */
|
||||
DTLS_MINOR = 0xff, /* DTLS minor version number */
|
||||
DTLS_BOGUS_MINOR = 0xfe, /* DTLS 0xfe was skipped, see RFC6347 Sec. 1 */
|
||||
DTLSv1_2_MINOR = 0xfd, /* DTLS minor version number */
|
||||
DTLSv1_3_MINOR = 0xfc, /* DTLS minor version number */
|
||||
SSLv3_MAJOR = 3, /* SSLv3 and TLSv1+ major version number */
|
||||
|
@ -4670,6 +4671,8 @@ struct WOLFSSL {
|
|||
word32 dtls13FragOffset;
|
||||
byte dtls13FragHandshakeType;
|
||||
Dtls13Rtx dtls13Rtx;
|
||||
byte *dtls13ClientHello;
|
||||
word16 dtls13ClientHelloSz;
|
||||
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
|
@ -5186,6 +5189,8 @@ WOLFSSL_LOCAL int cipherExtraData(WOLFSSL* ssl);
|
|||
|
||||
#ifndef NO_WOLFSSL_CLIENT
|
||||
WOLFSSL_LOCAL int SendClientHello(WOLFSSL* ssl);
|
||||
WOLFSSL_LOCAL int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
word32 size);
|
||||
#ifdef WOLFSSL_TLS13
|
||||
WOLFSSL_LOCAL int SendTls13ClientHello(WOLFSSL* ssl);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue