diff --git a/src/internal.c b/src/internal.c index a3d568782..b8eaa4240 100644 --- a/src/internal.c +++ b/src/internal.c @@ -10015,7 +10015,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; } @@ -24669,6 +24669,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; @@ -24682,11 +24683,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. */ @@ -24694,7 +24708,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; } @@ -24709,27 +24724,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 diff --git a/src/ssl.c b/src/ssl.c index 3f19647b9..ff37f8028 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -4516,17 +4516,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"); diff --git a/src/tls13.c b/src/tls13.c index 23901be61..d5d3e939d 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3659,6 +3659,10 @@ static int Dtls13DoDowngrade(WOLFSSL* ssl) 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*/ @@ -3762,6 +3766,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; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index a8f37fe57..2822eef1a 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -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 */