From 60834ba51699d09cfe0ce386817c134df94fae25 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Fri, 20 May 2022 09:59:24 +0200 Subject: [PATCH] dtls13: new methods and version negotiation --- src/dtls13.c | 43 ++++++++++++ src/internal.c | 127 ++++++++++++++++++++++++++-------- src/ssl.c | 14 ++++ src/tls.c | 169 ++++++++++++++++++++++++++++++++++++--------- src/tls13.c | 118 +++++++++++++++++++++++++------ wolfssl/internal.h | 13 ++++ wolfssl/ssl.h | 13 ++++ 7 files changed, 412 insertions(+), 85 deletions(-) diff --git a/src/dtls13.c b/src/dtls13.c index 209ce30c8..3f860723c 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -27,4 +27,47 @@ #ifdef WOLFSSL_DTLS13 +#include +#include + +WOLFSSL_METHOD* wolfDTLSv1_3_client_method_ex(void* heap) +{ + WOLFSSL_METHOD* method; + + WOLFSSL_ENTER("DTLSv1_3_client_method_ex"); + + method = (WOLFSSL_METHOD*)XMALLOC(sizeof(WOLFSSL_METHOD), heap, + DYNAMIC_TYPE_METHOD); + if (method) + InitSSL_Method(method, MakeDTLSv1_3()); + + return method; +} + +WOLFSSL_METHOD* wolfDTLSv1_3_server_method_ex(void* heap) +{ + WOLFSSL_METHOD* method; + + WOLFSSL_ENTER("DTLSv1_3_server_method_ex"); + + method = (WOLFSSL_METHOD*)XMALLOC(sizeof(WOLFSSL_METHOD), heap, + DYNAMIC_TYPE_METHOD); + if (method) { + InitSSL_Method(method, MakeDTLSv1_3()); + method->side = WOLFSSL_SERVER_END; + } + + return method; +} + +WOLFSSL_METHOD* wolfDTLSv1_3_client_method(void) +{ + return wolfDTLSv1_3_client_method_ex(NULL); +} + +WOLFSSL_METHOD* wolfDTLSv1_3_server_method(void) +{ + return wolfDTLSv1_3_server_method_ex(NULL); +} + #endif /* WOLFSSL_DTLS13 */ diff --git a/src/internal.c b/src/internal.c index 1b2c4ee56..4ecd716b4 100644 --- a/src/internal.c +++ b/src/internal.c @@ -490,7 +490,15 @@ int IsAtLeastTLSv1_2(const WOLFSSL* ssl) int IsAtLeastTLSv1_3(const ProtocolVersion pv) { - return (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR); + int ret; + ret = (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR); + +#ifdef WOLFSSL_DTLS13 + if (ret == 0 && pv.major == DTLS_MAJOR && pv.minor <= DTLSv1_3_MINOR) + return 1; +#endif + + return ret; } static WC_INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend) @@ -2099,7 +2107,17 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) ctx->refCount = 1; /* so either CTX_free or SSL_free can release */ ctx->heap = ctx; /* defaults to self */ ctx->timeout = WOLFSSL_SESSION_TIMEOUT; - ctx->minDowngrade = WOLFSSL_MIN_DOWNGRADE; /* current default: TLSv1_MINOR */ + +#ifdef WOLFSSL_DTLS + if (method->version.major == DTLS_MAJOR) { + ctx->minDowngrade = WOLFSSL_MIN_DTLS_DOWNGRADE; + } + else +#endif /* WOLFSSL_DTLS */ + { + /* current default: TLSv1_MINOR */ + ctx->minDowngrade = WOLFSSL_MIN_DOWNGRADE; + } if (wc_InitMutex(&ctx->countMutex) < 0) { WOLFSSL_MSG("Mutex error on CTX init"); @@ -8350,6 +8368,18 @@ ProtocolVersion MakeDTLSv1_2(void) #endif /* !WOLFSSL_NO_TLS12 */ +#ifdef WOLFSSL_DTLS13 + +ProtocolVersion MakeDTLSv1_3(void) +{ + ProtocolVersion pv; + pv.major = DTLS_MAJOR; + pv.minor = DTLSv1_3_MINOR; + + return pv; +} + +#endif /* WOLFSSL_DTLS13 */ #endif /* WOLFSSL_DTLS */ @@ -9416,6 +9446,7 @@ int CheckAvailableSize(WOLFSSL *ssl, int size) static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, RecordLayerHeader* rh, word16 *size) { + byte tls12minor; #ifdef OPENSSL_ALL word32 start = *inOutIdx; #endif @@ -9469,13 +9500,18 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif + tls12minor = TLSv1_2_MINOR; +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) + tls12minor = DTLSv1_2_MINOR; +#endif /* WOLFSSL_DTLS13 */ /* catch version mismatch */ #ifndef WOLFSSL_TLS13 if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor) #else if (rh->pvMajor != ssl->version.major || (rh->pvMinor != ssl->version.minor && - (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_2_MINOR) + (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != tls12minor) )) #endif { @@ -9598,9 +9634,10 @@ int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input, idx += DTLS_HANDSHAKE_FRAG_SZ; c24to32(input + idx, fragSz); - if (ssl->curRL.pvMajor != ssl->version.major || - ssl->curRL.pvMinor != ssl->version.minor) { - + if ((ssl->curRL.pvMajor != ssl->version.major) || + (!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) { WOLFSSL_ERROR(VERSION_ERROR); return VERSION_ERROR; @@ -30173,6 +30210,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 i = *inOutIdx; word32 begin = i; int ret = 0; + byte lesserVersion; + #ifdef WOLFSSL_DTLS Hmac cookieHmac; byte newCookie[MAX_COOKIE_LEN]; @@ -30230,11 +30269,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR) pv.minor = TLSv1_2_MINOR; - if ((!ssl->options.dtls && ssl->version.minor > pv.minor) || - (ssl->options.dtls && ssl->version.minor != DTLS_MINOR - && ssl->version.minor != DTLSv1_2_MINOR && pv.minor != DTLS_MINOR - && pv.minor != DTLSv1_2_MINOR)) { + lesserVersion = !ssl->options.dtls && ssl->version.minor > pv.minor; + lesserVersion |= ssl->options.dtls && ssl->version.minor < pv.minor; + if (lesserVersion) { + byte belowMinDowngrade; word16 haveRSA = 0; word16 havePSK = 0; int keySz = 0; @@ -30247,7 +30286,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = VERSION_ERROR; goto out; } - if (pv.minor < ssl->options.minDowngrade) { + + belowMinDowngrade = pv.minor < ssl->options.minDowngrade; + + /* DTLS versions increase backwards (-1,-2,-3) ecc */ + if (ssl->options.dtls) + belowMinDowngrade = ssl->options.dtls + && pv.minor > ssl->options.minDowngrade; + + if (belowMinDowngrade) { WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); #if defined(WOLFSSL_EXTRA_ALERTS) || defined(OPENSSL_EXTRA) SendAlert(ssl, alert_fatal, handshake_failure); @@ -30256,26 +30303,46 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto out; } - 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; + if (!ssl->options.dtls) { + 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; + } } - 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; + else { + if (pv.minor == DTLSv1_2_MINOR) { + WOLFSSL_MSG("\tDowngrading to DTLSv1.2"); + ssl->options.tls1_3 = 0; + ssl->version.minor = DTLSv1_2_MINOR; + + /* reset hashes, DTLSv1.2 will take care of the hashing + later */ + ret = InitHandshakeHashes(ssl); + if (ret != 0) + return ret; + } + else if (pv.minor == DTLS_MINOR) { + WOLFSSL_MSG("\tDowngrading to DTLSv1.2"); + ssl->options.tls1_3 = 0; + ssl->version.minor = DTLS_MINOR; + } } #ifndef NO_RSA haveRSA = 1; diff --git a/src/ssl.c b/src/ssl.c index 7a0e15d32..25f27d237 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -4516,6 +4516,18 @@ static int SetMinVersionHelper(byte* minVersion, int version) break; #endif +#ifdef WOLFSSL_DTLS13 + case WOLFSSL_DTLSV1: + *minVersion = DTLS_MINOR; + break; + case WOLFSSL_DTLSV1_2: + *minVersion = DTLSv1_2_MINOR; + break; + case WOLFSSL_DTLSV1_3: + *minVersion = DTLSv1_3_MINOR; + break; +#endif /* WOLFSSL_DTLS13 */ + default: WOLFSSL_MSG("Bad function argument"); return BAD_FUNC_ARG; @@ -19795,6 +19807,8 @@ static const char* wolfSSL_internal_get_version(const ProtocolVersion* version) return "DTLS"; case DTLSv1_2_MINOR : return "DTLSv1.2"; + case DTLSv1_3_MINOR : + return "DTLSv1.3"; default: return "unknown"; } diff --git a/src/tls.c b/src/tls.c index 749a6e7bd..346d731b9 100644 --- a/src/tls.c +++ b/src/tls.c @@ -5628,6 +5628,58 @@ static int TLSX_UseSRTP(TLSX** extensions, word16 profiles, void* heap) /******************************************************************************/ #ifdef WOLFSSL_TLS13 +static WC_INLINE int versionIsGreater(byte isDtls, byte a, byte b) +{ + (void)isDtls; + +#ifdef WOLFSSL_DTLS + /* DTLS version increases backwards (-1,-2,-3,etc) */ + if (isDtls) + return a < b; +#endif /* WOLFSSL_DTLS */ + + return a > b; +} + +static WC_INLINE int versionIsLesser(byte isDtls, byte a, byte b) +{ + (void)isDtls; + +#ifdef WOLFSSL_DTLS + /* DTLS version increases backwards (-1,-2,-3,etc) */ + if (isDtls) + return a > b; +#endif /* WOLFSSL_DTLS */ + + return a < b; +} + +static WC_INLINE int versionIsAtLeast(byte isDtls, byte a, byte b) +{ + (void)isDtls; + +#ifdef WOLFSSL_DTLS + /* DTLS version increases backwards (-1,-2,-3,etc) */ + if (isDtls) + return a <= b; +#endif /* WOLFSSL_DTLS */ + + return a >= b; +} + +static WC_INLINE int versionIsLessEqual(byte isDtls, byte a, byte b) +{ + (void)isDtls; + +#ifdef WOLFSSL_DTLS + /* DTLS version increases backwards (-1,-2,-3,etc) */ + if (isDtls) + return a >= b; +#endif /* WOLFSSL_DTLS */ + + return a <= b; +} + /* Return the size of the SupportedVersions extension's data. * * data The SSL/TLS object. @@ -5637,12 +5689,23 @@ static int TLSX_UseSRTP(TLSX** extensions, word16 profiles, void* heap) static int TLSX_SupportedVersions_GetSize(void* data, byte msgType, word16* pSz) { WOLFSSL* ssl = (WOLFSSL*)data; + byte tls13Minor, tls12Minor, tls11Minor, isDtls; + + /* unused on some configuration */ + (void)tls12Minor; + (void)tls13Minor; + (void)tls11Minor; + + isDtls = !!ssl->options.dtls; + tls13Minor = (byte)(isDtls ? DTLSv1_3_MINOR : TLSv1_3_MINOR); + tls12Minor = (byte)(isDtls ? DTLSv1_2_MINOR : TLSv1_2_MINOR); + tls11Minor = (byte)(isDtls ? DTLS_MINOR : TLSv1_1_MINOR); if (msgType == client_hello) { /* TLS v1.2 and TLS v1.3 */ int cnt = 0; - if ((ssl->options.minDowngrade <= TLSv1_3_MINOR) + if (versionIsLessEqual(isDtls, ssl->options.minDowngrade, tls13Minor) #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ defined(WOLFSSL_WPAS_SMALL) && (ssl->options.mask & SSL_OP_NO_TLSv1_3) == 0 @@ -5653,17 +5716,19 @@ static int TLSX_SupportedVersions_GetSize(void* data, byte msgType, word16* pSz) if (ssl->options.downgrade) { #ifndef WOLFSSL_NO_TLS12 - if ((ssl->options.minDowngrade <= TLSv1_2_MINOR) - #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ - defined(WOLFSSL_WPAS_SMALL) + if (versionIsLessEqual( + isDtls, ssl->options.minDowngrade, tls12Minor) +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ + defined(WOLFSSL_WPAS_SMALL) && (ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0 - #endif +#endif ) { cnt++; } - #endif +#endif #ifndef NO_OLD_TLS - if ((ssl->options.minDowngrade <= TLSv1_1_MINOR) + if (versionIsLessEqual( + isDtls, ssl->options.minDowngrade, tls11Minor) #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ defined(WOLFSSL_WPAS_SMALL) && (ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0 @@ -5672,7 +5737,7 @@ static int TLSX_SupportedVersions_GetSize(void* data, byte msgType, word16* pSz) cnt++; } #ifdef WOLFSSL_ALLOW_TLSV10 - if ((ssl->options.minDowngrade <= TLSv1_MINOR) + if (!ssl->options.dtls && (ssl->options.minDowngrade <= TLSv1_MINOR) #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ defined(WOLFSSL_WPAS_SMALL) && (ssl->options.mask & SSL_OP_NO_TLSv1) == 0 @@ -5709,6 +5774,24 @@ static int TLSX_SupportedVersions_Write(void* data, byte* output, WOLFSSL* ssl = (WOLFSSL*)data; byte major; byte* cnt; + byte tls13minor, tls12minor, tls11minor, isDtls = 0; + + tls13minor = (byte)TLSv1_3_MINOR; + tls12minor = (byte)TLSv1_2_MINOR; + tls11minor = (byte)TLSv1_1_MINOR; + + /* unused in some configuration */ + (void)tls11minor; + (void)tls12minor; + +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) { + tls13minor = (byte)DTLSv1_3_MINOR; + tls12minor = (byte)DTLSv1_2_MINOR; + tls11minor = (byte)DTLS_MINOR; + isDtls = 1; + } +#endif /* WOLFSSL_DTLS13 */ if (msgType == client_hello) { major = ssl->ctx->method->version.major; @@ -5716,11 +5799,11 @@ static int TLSX_SupportedVersions_Write(void* data, byte* output, cnt = output++; *cnt = 0; - if ((ssl->options.minDowngrade <= TLSv1_3_MINOR) - #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ - defined(WOLFSSL_WPAS_SMALL) + if (versionIsLessEqual(isDtls, ssl->options.minDowngrade, tls13minor) +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ + defined(WOLFSSL_WPAS_SMALL) && (ssl->options.mask & SSL_OP_NO_TLSv1_3) == 0 - #endif +#endif ) { *cnt += OPAQUE16_LEN; #ifdef WOLFSSL_TLS13_DRAFT @@ -5730,26 +5813,26 @@ static int TLSX_SupportedVersions_Write(void* data, byte* output, *(output++) = TLS_DRAFT_MINOR; #else *(output++) = major; - *(output++) = (byte)TLSv1_3_MINOR; + *(output++) = tls13minor; #endif } if (ssl->options.downgrade) { #ifndef WOLFSSL_NO_TLS12 - if ((ssl->options.minDowngrade <= TLSv1_2_MINOR) - #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ + if (versionIsLessEqual(isDtls, ssl->options.minDowngrade, tls12minor) +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ defined(WOLFSSL_WPAS_SMALL) && (ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0 #endif ) { *cnt += OPAQUE16_LEN; *(output++) = major; - *(output++) = (byte)TLSv1_2_MINOR; + *(output++) = tls12minor; } #endif #ifndef NO_OLD_TLS - if ((ssl->options.minDowngrade <= TLSv1_1_MINOR) + if (versionIsLessEqual(isDtls, ssl->options.minDowngrade, tls11minor) #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ defined(WOLFSSL_WPAS_SMALL) && (ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0 @@ -5757,10 +5840,10 @@ static int TLSX_SupportedVersions_Write(void* data, byte* output, ) { *cnt += OPAQUE16_LEN; *(output++) = major; - *(output++) = (byte)TLSv1_1_MINOR; + *(output++) = tls11minor; } #ifdef WOLFSSL_ALLOW_TLSV10 - if ((ssl->options.minDowngrade <= TLSv1_MINOR) + if (!ssl->options.dtls && (ssl->options.minDowngrade <= TLSv1_MINOR) #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ defined(WOLFSSL_WPAS_SMALL) && (ssl->options.mask & SSL_OP_NO_TLSv1) == 0 @@ -5806,6 +5889,20 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, const byte* input, int newMinor = 0; int set = 0; int ret; + int tls13minor; + int tls12minor; + byte isDtls; + + tls13minor = TLSv1_3_MINOR; + tls12minor = TLSv1_2_MINOR; + isDtls = ssl->options.dtls == 1; + +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) { + tls13minor = DTLSv1_3_MINOR; + tls12minor = DTLSv1_2_MINOR; + } +#endif /* WOLFSSL_DTLS13 */ if (msgType == client_hello) { /* Must contain a length and at least one version. */ @@ -5839,23 +5936,27 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, const byte* input, continue; /* No upgrade allowed. */ - if (minor > ssl->version.minor) + if (versionIsGreater(isDtls, minor, ssl->version.minor)) continue; + /* Check downgrade. */ - if (minor < ssl->version.minor) { + if (versionIsLesser(isDtls, minor, ssl->version.minor)) { if (!ssl->options.downgrade) continue; - if (minor < ssl->options.minDowngrade) + if (versionIsLesser( + isDtls, minor, ssl->options.minDowngrade)) continue; - if (newMinor == 0 && minor > ssl->options.oldMinor) { + if (newMinor == 0 && + versionIsGreater( + isDtls, minor, ssl->options.oldMinor)) { /* Downgrade the version. */ ssl->version.minor = minor; } } - if (minor >= TLSv1_3_MINOR) { + if (versionIsAtLeast(isDtls, minor, tls13minor)) { if (!ssl->options.tls1_3) { ssl->options.tls1_3 = 1; ret = TLSX_Prepend(&ssl->extensions, @@ -5865,12 +5966,13 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, const byte* input, } TLSX_SetResponse(ssl, TLSX_SUPPORTED_VERSIONS); } - if (minor > newMinor) { + if (versionIsGreater(isDtls, minor, newMinor)) { ssl->version.minor = minor; newMinor = minor; } } - else if (minor > ssl->options.oldMinor) + else if (versionIsGreater( + isDtls, minor, ssl->options.oldMinor)) ssl->options.oldMinor = minor; set = 1; @@ -5896,25 +5998,26 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, const byte* input, return VERSION_ERROR; /* Can't downgrade with this extension below TLS v1.3. */ - if (minor < TLSv1_3_MINOR) + if (versionIsLesser(isDtls, minor, tls13minor)) return VERSION_ERROR; /* Version is TLS v1.2 to handle downgrading from TLS v1.3+. */ - if (ssl->options.downgrade && ssl->version.minor == TLSv1_2_MINOR) { + if (ssl->options.downgrade && ssl->version.minor == tls12minor) { /* Set minor version back to TLS v1.3+ */ ssl->version.minor = ssl->ctx->method->version.minor; } /* No upgrade allowed. */ - if (ssl->version.minor < minor) + if (versionIsLesser(isDtls, ssl->version.minor, minor)) return VERSION_ERROR; /* Check downgrade. */ - if (ssl->version.minor > minor) { + if (versionIsGreater(isDtls, ssl->version.minor, minor)) { if (!ssl->options.downgrade) return VERSION_ERROR; - if (minor < ssl->options.minDowngrade) + if (versionIsLesser( + isDtls, minor, ssl->options.minDowngrade)) return VERSION_ERROR; /* Downgrade the version. */ @@ -12768,7 +12871,9 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType, (void)heap; WOLFSSL_ENTER("DTLS_server_method_ex"); if (method) { - #if !defined(WOLFSSL_NO_TLS12) + #if defined(WOLFSSL_DTLS13) + InitSSL_Method(method, MakeDTLSv1_3()); + #elif !defined(WOLFSSL_NO_TLS12) InitSSL_Method(method, MakeDTLSv1_2()); #elif !defined(NO_OLD_TLS) InitSSL_Method(method, MakeDTLSv1()); diff --git a/src/tls13.c b/src/tls13.c index e0d9a97a9..b929e01ab 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3088,10 +3088,22 @@ int SendTls13ClientHello(WOLFSSL* ssl) #else Sch13Args args[1]; #endif + byte major, tls12minor; + WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND); WOLFSSL_ENTER("SendTls13ClientHello"); + major = SSLv3_MAJOR; + tls12minor = TLSv1_2_MINOR; + +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) { + major = DTLS_MAJOR; + tls12minor = DTLSv1_2_MINOR; + } +#endif /* WOLFSSL_DTLS */ + if (ssl == NULL) { return BAD_FUNC_ARG; } @@ -3217,8 +3229,9 @@ int SendTls13ClientHello(WOLFSSL* ssl) AddTls13Headers(args->output, args->length, client_hello, ssl); /* Protocol version - negotiation now in extension: supported_versions. */ - args->output[args->idx++] = SSLv3_MAJOR; - args->output[args->idx++] = TLSv1_2_MINOR; + args->output[args->idx++] = major; + args->output[args->idx++] = tls12minor; + /* Keep for downgrade. */ ssl->chVersion = ssl->version; @@ -3364,6 +3377,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { int ret; byte suite[2]; + byte tls12minor; #ifdef WOLFSSL_ASYNC_CRYPT Dsh13Args* args = NULL; WOLFSSL_ASSERT_SIZEOF_GE(ssl->async->args, *args); @@ -3374,6 +3388,14 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO); WOLFSSL_ENTER("DoTls13ServerHello"); + tls12minor = TLSv1_2_MINOR; + +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) + tls12minor = DTLSv1_2_MINOR; +#endif /* WOLFSSL_DTLS13 */ + + if (ssl == NULL || ssl->arrays == NULL) return BAD_FUNC_ARG; @@ -3428,18 +3450,37 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->idx += OPAQUE16_LEN; #ifndef WOLFSSL_NO_TLS12 - if (args->pv.major == ssl->version.major && - args->pv.minor < TLSv1_2_MINOR && - ssl->options.downgrade) { - /* Force client hello version 1.2 to work for static RSA. */ - ssl->chVersion.minor = TLSv1_2_MINOR; - ssl->version.minor = TLSv1_2_MINOR; - return DoServerHello(ssl, input, inOutIdx, helloSz); + byte wantDowngrade; + + wantDowngrade = args->pv.major == ssl->version.major && + args->pv.minor < TLSv1_2_MINOR; + +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) + wantDowngrade = args->pv.major == ssl->version.major && + args->pv.minor > DTLSv1_2_MINOR; +#endif /* WOLFSSL_DTLS13 */ + + if (wantDowngrade && ssl->options.downgrade) { + /* Force client hello version 1.2 to work for static RSA. */ + ssl->chVersion.minor = TLSv1_2_MINOR; + ssl->version.minor = TLSv1_2_MINOR; + +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) { + ssl->chVersion.minor = DTLSv1_2_MINOR; + ssl->version.minor = DTLSv1_2_MINOR; + } +#endif /* WOLFSSL_DTLS13 */ + + return DoServerHello(ssl, input, inOutIdx, helloSz); + } } #endif + if (args->pv.major != ssl->version.major || - args->pv.minor != TLSv1_2_MINOR) { + args->pv.minor != tls12minor) { return VERSION_ERROR; } @@ -3502,6 +3543,14 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Force client hello version 1.2 to work for static RSA. */ ssl->chVersion.minor = TLSv1_2_MINOR; ssl->version.minor = TLSv1_2_MINOR; + +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) { + ssl->chVersion.minor = DTLSv1_2_MINOR; + ssl->version.minor = DTLSv1_2_MINOR; + } +#endif /* WOLFSSL_DTLS13 */ + #endif ssl->options.haveEMS = 0; if (args->pv.minor < ssl->options.minDowngrade) @@ -3545,8 +3594,13 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif - if (args->pv.minor < ssl->options.minDowngrade) + if (!ssl->options.dtls && + args->pv.minor < ssl->options.minDowngrade) return VERSION_ERROR; + + if (ssl->options.dtls && args->pv.minor > ssl->options.minDowngrade) + return VERSION_ERROR; + ssl->version.minor = args->pv.minor; } } @@ -4739,6 +4793,9 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(&args->pv, input + args->idx, OPAQUE16_LEN); ssl->chVersion = args->pv; /* store */ args->idx += OPAQUE16_LEN; + + + /* this check pass for DTLS Major (0xff) */ if (args->pv.major < SSLv3_MAJOR) { WOLFSSL_MSG("Legacy version field contains unsupported value"); #ifdef WOLFSSL_MYSQL_COMPATIBLE @@ -4749,25 +4806,38 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(INVALID_PARAMETER, exit_dch); } - /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */ - if (args->pv.major > SSLv3_MAJOR || (args->pv.major == SSLv3_MAJOR && - args->pv.minor >= TLSv1_3_MINOR)) { - args->pv.major = SSLv3_MAJOR; - args->pv.minor = TLSv1_2_MINOR; +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls && + args->pv.major == DTLS_MAJOR && args->pv.minor > DTLSv1_2_MINOR) { wantDowngrade = 1; ssl->version.minor = args->pv.minor; } - /* Legacy version must be [ SSLv3_MAJOR, TLSv1_2_MINOR ] for TLS v1.3 */ - else if (args->pv.major == SSLv3_MAJOR && args->pv.minor < TLSv1_2_MINOR) { - wantDowngrade = 1; - ssl->version.minor = args->pv.minor; +#endif /* WOLFSSL_DTLS13 */ + + if (!ssl->options.dtls) { + /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */ + if (args->pv.major > SSLv3_MAJOR || (args->pv.major == SSLv3_MAJOR && + args->pv.minor >= TLSv1_3_MINOR)) { + args->pv.major = SSLv3_MAJOR; + args->pv.minor = TLSv1_2_MINOR; + wantDowngrade = 1; + ssl->version.minor = args->pv.minor; + } + /* Legacy version must be [ SSLv3_MAJOR, TLSv1_2_MINOR ] for TLS v1.3 */ + else if (args->pv.major == SSLv3_MAJOR && + args->pv.minor < TLSv1_2_MINOR) { + wantDowngrade = 1; + ssl->version.minor = args->pv.minor; + } } - else { + + if (!wantDowngrade) { ret = DoTls13SupportedVersions(ssl, input + args->begin, args->idx - args->begin, helloSz, &wantDowngrade); if (ret < 0) goto exit_dch; } + if (wantDowngrade) { #ifndef WOLFSSL_NO_TLS12 if (!ssl->options.downgrade) { @@ -4779,7 +4849,9 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(VERSION_ERROR, exit_dch); } - if (args->pv.minor < ssl->options.minDowngrade) { + if ((!ssl->options.dtls + && args->pv.minor < ssl->options.minDowngrade) || + (ssl->options.dtls && args->pv.minor > ssl->options.minDowngrade)) { WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); #if defined(WOLFSSL_EXTRA_ALERTS) || defined(OPENSSL_EXTRA) SendAlert(ssl, alert_fatal, handshake_failure); @@ -5096,7 +5168,7 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) /* The protocol version must be TLS v1.2 for middleboxes. */ output[idx++] = ssl->version.major; - output[idx++] = TLSv1_2_MINOR; + output[idx++] = ssl->options.dtls ? DTLSv1_2_MINOR : TLSv1_2_MINOR; if (extMsgType == server_hello) { /* Generate server random. */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index ccf27b81f..7603ab2a3 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1179,6 +1179,7 @@ enum Misc { DTLS_MAJOR = 0xfe, /* DTLS major version number */ DTLS_MINOR = 0xff, /* DTLS minor version number */ 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 */ SSLv3_MINOR = 0, /* TLSv1 minor version number */ TLSv1_MINOR = 1, /* TLSv1 minor version number */ @@ -1497,6 +1498,11 @@ enum Misc { #endif #endif +/* minimum DTLS Downgrade Minor version */ +#ifndef WOLFSSL_MIN_DTLS_DOWNGRADE +#define WOLFSSL_MIN_DTLS_DOWNGRADE DTLS_MINOR; +#endif + /* Set max implicit IV size for AEAD cipher suites */ #define AEAD_MAX_IMP_SZ 12 @@ -1666,6 +1672,10 @@ WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void); WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1(void); WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void); +#ifdef WOLFSSL_DTLS13 + WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_3(void); +#endif /* WOLFSSL_DTLS13 */ + #endif #ifdef WOLFSSL_SESSION_EXPORT WOLFSSL_LOCAL int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, @@ -5228,6 +5238,9 @@ WOLFSSL_LOCAL int oid2nid(word32 oid, int grp); WOLFSSL_LOCAL word32 nid2oid(int nid, int grp); #endif +#ifdef WOLFSSL_DTLS13 + +#endif /* WOLFSSL_DTLS13 */ #ifdef WOLFSSL_STATIC_EPHEMERAL WOLFSSL_LOCAL int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr); #endif diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 8b6382806..1d02e0f87 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -865,6 +865,12 @@ WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_client_method_ex(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_method_ex(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method_ex(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method_ex(void* heap); + +#ifdef WOLFSSL_DTLS13 + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_3_client_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_3_server_method_ex(void* heap); +#endif + #endif /* CTX Method Constructor Functions */ @@ -899,6 +905,12 @@ WOLFSSL_ABI WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method(void); + +#ifdef WOLFSSL_DTLS13 + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_3_client_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_3_server_method(void); +#endif + #endif #ifdef HAVE_POLY1305 @@ -2995,6 +3007,7 @@ enum { WOLFSSL_TLSV1_3 = 4, WOLFSSL_DTLSV1 = 5, WOLFSSL_DTLSV1_2 = 6, + WOLFSSL_DTLSV1_3 = 7, WOLFSSL_USER_CA = 1, /* user added as trusted */ WOLFSSL_CHAIN_CA = 2 /* added to cache from trusted chain */