dtls13: allow processing of HelloVerifyRequest to support downgrade

HelloVerifyRequest is used in DTLSv1.2 to perform a return routability check, so
it can be the legitim reply from a DTLSv1.2 server to a ClientHello.
This commit is contained in:
Marco Oliverio
2022-06-22 15:12:36 +02:00
parent 1b64b82a6f
commit 5d74c49ecb
3 changed files with 81 additions and 11 deletions

View File

@ -147,8 +147,6 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
#ifndef WOLFSSL_NO_TLS12 #ifndef WOLFSSL_NO_TLS12
#ifndef NO_WOLFSSL_CLIENT #ifndef NO_WOLFSSL_CLIENT
static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, word32 size);
static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, word32 size); word32* inOutIdx, word32 size);
#ifndef NO_CERTS #ifndef NO_CERTS
@ -24562,8 +24560,8 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
/* handle processing of DTLS hello_verify_request (3) */ /* handle processing of DTLS hello_verify_request (3) */
static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
word32* inOutIdx, word32 size) word32 size)
{ {
ProtocolVersion pv; ProtocolVersion pv;
byte cookieSz; byte cookieSz;
@ -24605,7 +24603,18 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
*inOutIdx += cookieSz; *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; ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
return 0; return 0;
} }

View File

@ -3411,9 +3411,14 @@ int SendTls13ClientHello(WOLFSSL* ssl)
#endif #endif
#ifdef WOLFSSL_DTLS13 #ifdef WOLFSSL_DTLS13
/* legacy_cookie_id (always 0 length) */ if (ssl->options.dtls) {
if (ssl->options.dtls) /* legacy_cookie_id len */
args->length += OPAQUE8_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 */ #endif /* WOLFSSL_DTLS13 */
/* Advance state and proceed */ /* Advance state and proceed */
@ -3519,9 +3524,19 @@ int SendTls13ClientHello(WOLFSSL* ssl)
} }
#ifdef WOLFSSL_DTLS13 #ifdef WOLFSSL_DTLS13
/* legacy_cookie_id. always 0 length vector */ if (ssl->options.dtls) {
if (ssl->options.dtls) args->output[args->idx++] = ssl->arrays->cookieSz;
args->output[args->idx++] = 0;
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 */ #endif /* WOLFSSL_DTLS13 */
/* Cipher suites */ /* Cipher suites */
@ -9111,6 +9126,40 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
} }
/* Multiple KeyUpdates can be sent. */ /* Multiple KeyUpdates can be sent. */
break; 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: default:
WOLFSSL_MSG("Unknown message type"); WOLFSSL_MSG("Unknown message type");
@ -9171,7 +9220,11 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (ssl->options.side == WOLFSSL_CLIENT_END && if (ssl->options.side == WOLFSSL_CLIENT_END &&
ssl->options.serverState == NULL_STATE && 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"); WOLFSSL_MSG("First server message not server hello");
SendAlert(ssl, alert_fatal, unexpected_message); SendAlert(ssl, alert_fatal, unexpected_message);
return OUT_OF_ORDER_E; return OUT_OF_ORDER_E;
@ -9265,6 +9318,12 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ret = DoTls13KeyUpdate(ssl, input, inOutIdx, size); ret = DoTls13KeyUpdate(ssl, input, inOutIdx, size);
break; 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: default:
WOLFSSL_MSG("Unknown handshake message type"); WOLFSSL_MSG("Unknown handshake message type");
ret = UNKNOWN_HANDSHAKE_TYPE; ret = UNKNOWN_HANDSHAKE_TYPE;

View File

@ -5175,6 +5175,8 @@ WOLFSSL_LOCAL int cipherExtraData(WOLFSSL* ssl);
#ifndef NO_WOLFSSL_CLIENT #ifndef NO_WOLFSSL_CLIENT
WOLFSSL_LOCAL int SendClientHello(WOLFSSL* ssl); WOLFSSL_LOCAL int SendClientHello(WOLFSSL* ssl);
WOLFSSL_LOCAL int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
word32 size);
#ifdef WOLFSSL_TLS13 #ifdef WOLFSSL_TLS13
WOLFSSL_LOCAL int SendTls13ClientHello(WOLFSSL* ssl); WOLFSSL_LOCAL int SendTls13ClientHello(WOLFSSL* ssl);
#endif #endif