diff --git a/src/internal.c b/src/internal.c index eab408824..8a3e89b70 100755 --- a/src/internal.c +++ b/src/internal.c @@ -143,6 +143,12 @@ enum cipherState { CIPHER_STATE_END, }; +/* Server random bytes for TLS v1.3 described downgrade protection mechanism. */ +static const byte tls13Downgrade[7] = { + 0x44, 0x4f, 0x47, 0x4e, 0x47, 0x52, 0x44 +}; +#define TLS13_DOWNGRADE_SZ sizeof(tls13Downgrade) + #ifndef NO_OLD_TLS static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, @@ -15764,6 +15770,33 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); i += RAN_LEN; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) { + /* TLS v1.3 capable client not allowed to downgrade when connecting + * to TLS v1.3 capable server. + */ + if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && + (*(input + i - 1) == 0 || *(input + i - 1) == 1)) { + SendAlert(ssl, alert_fatal, illegal_parameter); + return VERSION_ERROR; + } + } + else +#endif + if (ssl->ctx->method->version.major == SSLv3_MAJOR && + ssl->ctx->method->version.minor == TLSv1_2_MINOR) { + /* TLS v1.2 capable client not allowed to downgrade when connecting + * to TLS v1.2 capable server. + */ + if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && + *(input + i - 1) == 0) { + SendAlert(ssl, alert_fatal, illegal_parameter); + return VERSION_ERROR; + } + } + /* session id */ ssl->arrays->sessionIDSz = input[i++]; @@ -19072,7 +19105,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* NO_WOLFSSL_CLIENT */ - #ifndef NO_WOLFSSL_SERVER int SendServerHello(WOLFSSL* ssl) @@ -19161,6 +19193,24 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) return ret; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) { + /* TLS v1.3 capable server downgraded. */ + XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ); + output[idx + RAN_LEN - 1] = IsAtLeastTLSv1_2(ssl); + } + else +#endif + if (ssl->ctx->method->version.major == SSLv3_MAJOR && + ssl->ctx->method->version.minor == TLSv1_2_MINOR && + !IsAtLeastTLSv1_2(ssl)) { + /* TLS v1.2 capable server downgraded. */ + XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ); + output[idx + RAN_LEN - 1] = 0; + } + /* store info in SSL for later */ XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN); idx += RAN_LEN; diff --git a/src/tls13.c b/src/tls13.c index 539df7d73..b5beff8d7 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -2164,7 +2164,6 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Server random - keep for debugging. */ XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); i += RAN_LEN; - /* TODO: [TLS13] Check last 8 bytes. */ /* Set the cipher suite from the message. */ ssl->options.cipherSuite0 = input[i++]; @@ -2779,7 +2778,6 @@ int SendTls13ServerHello(WOLFSSL* ssl) output[idx++] = TLS_DRAFT_MAJOR; output[idx++] = TLS_DRAFT_MINOR; - /* TODO: [TLS13] Last 8 bytes have special meaning. */ /* Generate server random. */ ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); if (ret != 0)