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 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
@ -24562,8 +24560,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;
@ -24605,7 +24603,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;
}

View File

@ -3411,9 +3411,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 */
@ -3519,9 +3524,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 */
@ -9111,6 +9126,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");
@ -9171,7 +9220,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;
@ -9265,6 +9318,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;

View File

@ -5175,6 +5175,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