diff --git a/configure.ac b/configure.ac index ea87c63b9..cbb47dcc8 100644 --- a/configure.ac +++ b/configure.ac @@ -293,6 +293,18 @@ then fi +# TLS v1.3 Draft 22 +AC_ARG_ENABLE([tls13-draft22], + [AS_HELP_STRING([--enable-tls13-draft22],[Enable wolfSSL TLS v1.3 Draft 22 (default: disabled)])], + [ ENABLED_TLS13_DRAFT22=$enableval ], + [ ENABLED_TLS13_DRAFT22=no ] + ) +if test "$ENABLED_TLS13_DRAFT22" = "yes" +then + AM_CFLAGS="-DWOLFSSL_TLS13_DRAFT_22 $AM_CFLAGS" +fi + + # TLS v1.3 AC_ARG_ENABLE([tls13], [AS_HELP_STRING([--enable-tls13],[Enable wolfSSL TLS v1.3 (default: disabled)])], @@ -300,7 +312,7 @@ AC_ARG_ENABLE([tls13], [ ENABLED_TLS13=no ] ) -if test "$ENABLED_TLS13_DRAFT18" = "yes" +if test "$ENABLED_TLS13_DRAFT18" = "yes" || test "$ENABLED_TLS13_DRAFT22" = "yes" then ENABLED_TLS13="yes" fi diff --git a/src/tls.c b/src/tls.c index 3314f38c7..7ef746460 100644 --- a/src/tls.c +++ b/src/tls.c @@ -4898,7 +4898,7 @@ int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len, byte* mac, #endif /******************************************************************************/ -/* Sugnature Algorithms */ +/* Signature Algorithms */ /******************************************************************************/ /* Return the size of the SignatureAlgorithms extension's data. @@ -4997,7 +4997,7 @@ static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, byte* input, return TLSX_SignatureAlgorithms_MapPss(ssl, input, len); } -/* Sets a new SupportedVersions extension into the extension list. +/* Sets a new SignatureAlgorithms extension into the extension list. * * extensions The list of extensions. * data The extensions specific data. @@ -5017,6 +5017,101 @@ static int TLSX_SetSignatureAlgorithms(TLSX** extensions, const void* data, #define SA_WRITE TLSX_SignatureAlgorithms_Write #define SA_PARSE TLSX_SignatureAlgorithms_Parse +/******************************************************************************/ +/* Signature Algorithms Certificate */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) +/* Return the size of the SignatureAlgorithms extension's data. + * + * data Unused + * returns the length of data that will be in the extension. + */ +static word16 TLSX_SignatureAlgorithmsCert_GetSize(void* data) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + + return OPAQUE16_LEN + ssl->certHashSigAlgoSz; +} + +/* Writes the SignatureAlgorithmsCert extension into the buffer. + * + * data Unused + * output The buffer to write the extension into. + * returns the length of data that was written. + */ +static word16 TLSX_SignatureAlgorithmsCert_Write(void* data, byte* output) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + + c16toa(ssl->certHashSigAlgoSz, output); + XMEMCPY(output + OPAQUE16_LEN, ssl->certHashSigAlgo, + ssl->certHashSigAlgoSz); + + return OPAQUE16_LEN + ssl->certHashSigAlgoSz; +} + +/* Parse the SignatureAlgorithmsCert extension. + * + * ssl The SSL/TLS object. + * input The buffer with the extension data. + * length The length of the extension data. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SignatureAlgorithmsCert_Parse(WOLFSSL *ssl, byte* input, + word16 length, byte isRequest) +{ + word16 len; + + if (!isRequest) + return BUFFER_ERROR; + + /* Must contain a length and at least algorithm. */ + if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0) + return BUFFER_ERROR; + + ato16(input, &len); + input += OPAQUE16_LEN; + + /* Algorithm array must fill rest of data. */ + if (length != OPAQUE16_LEN + len) + return BUFFER_ERROR; + + /* truncate hashSigAlgo list if too long */ + ssl->certHashSigAlgoSz = len; + if (ssl->certHashSigAlgoSz > WOLFSSL_MAX_SIGALGO) { + WOLFSSL_MSG("TLSX SigAlgo list exceeds max, truncating"); + ssl->certHashSigAlgoSz = WOLFSSL_MAX_SIGALGO; + } + XMEMCPY(ssl->certHashSigAlgo, input, ssl->certHashSigAlgoSz); + + return 0; +} + +/* Sets a new SignatureAlgorithmsCert extension into the extension list. + * + * extensions The list of extensions. + * data The extensions specific data. + * heap The heap used for allocation. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SetSignatureAlgorithmsCert(TLSX** extensions, const void* data, + void* heap) +{ + if (extensions == NULL) + return BAD_FUNC_ARG; + + return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS_CERT, (void *)data, + heap); +} + +#define SAC_GET_SIZE TLSX_SignatureAlgorithmsCert_GetSize +#define SAC_WRITE TLSX_SignatureAlgorithmsCert_Write +#define SAC_PARSE TLSX_SignatureAlgorithmsCert_Parse +#endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */ +#endif /* WOLFSSL_TLS13 */ + /******************************************************************************/ /* Key Share */ @@ -7147,10 +7242,6 @@ void TLSX_FreeAll(TLSX* list, void* heap) CKE_FREE_ALL((Cookie*)extension->data, heap); break; - case TLSX_KEY_SHARE: - KS_FREE_ALL((KeyShareEntry*)extension->data, heap); - break; - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) case TLSX_PRE_SHARED_KEY: PSK_FREE_ALL((PreSharedKey*)extension->data, heap); @@ -7169,6 +7260,15 @@ void TLSX_FreeAll(TLSX* list, void* heap) case TLSX_POST_HANDSHAKE_AUTH: break; #endif + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + case TLSX_SIGNATURE_ALGORITHMS_CERT: + break; + #endif + + case TLSX_KEY_SHARE: + KS_FREE_ALL((KeyShareEntry*)extension->data, heap); + break; #endif } @@ -7272,10 +7372,6 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType) length += CKE_GET_SIZE((Cookie*)extension->data, msgType); break; - case TLSX_KEY_SHARE: - length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType); - break; - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) case TLSX_PRE_SHARED_KEY: length += PSK_GET_SIZE((PreSharedKey*)extension->data, msgType); @@ -7297,6 +7393,16 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType) length += PHA_GET_SIZE(msgType); break; #endif + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + case TLSX_SIGNATURE_ALGORITHMS_CERT: + length += SAC_GET_SIZE(extension->data); + break; + #endif + + case TLSX_KEY_SHARE: + length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType); + break; #endif } @@ -7421,12 +7527,6 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, msgType); break; - case TLSX_KEY_SHARE: - WOLFSSL_MSG("Key Share extension to write"); - offset += KS_WRITE((KeyShareEntry*)extension->data, - output + offset, msgType); - break; - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) case TLSX_PRE_SHARED_KEY: WOLFSSL_MSG("Pre-Shared Key extension to write"); @@ -7453,6 +7553,19 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, offset += PHA_WRITE(output + offset, msgType); break; #endif + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + case TLSX_SIGNATURE_ALGORITHMS_CERT: + WOLFSSL_MSG("Signature Algorithms extension to write"); + offset += SAC_WRITE(extension->data, output + offset); + break; + #endif + + case TLSX_KEY_SHARE: + WOLFSSL_MSG("Key Share extension to write"); + offset += KS_WRITE((KeyShareEntry*)extension->data, + output + offset, msgType); + break; #endif } @@ -7899,7 +8012,17 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #endif ret = 0; } + #endif + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + if (ssl->certHashSigAlgoSz > 0) { + WOLFSSL_MSG("Adding signature algorithms cert extension"); + if ((ret = TLSX_SetSignatureAlgorithmsCert(&ssl->extensions, + ssl, ssl->heap)) != 0) { + return ret; + } + } + #endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */ if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { #if defined(HAVE_ECC) && (!defined(NO_ECC256) || \ @@ -8631,20 +8754,6 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, ret = CKE_PARSE(ssl, input + offset, size, msgType); break; - case TLSX_KEY_SHARE: - WOLFSSL_MSG("Key Share extension received"); - - if (!IsAtLeastTLSv1_3(ssl->version)) - break; - - if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello && msgType != server_hello && - msgType != hello_retry_request) { - return EXT_NOT_ALLOWED; - } - ret = KS_PARSE(ssl, input + offset, size, msgType); - break; - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) case TLSX_PRE_SHARED_KEY: WOLFSSL_MSG("Pre-Shared Key extension received"); @@ -8703,6 +8812,37 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, ret = PHA_PARSE(ssl, input + offset, size, msgType); break; #endif + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + case TLSX_SIGNATURE_ALGORITHMS_CERT: + WOLFSSL_MSG("Signature Algorithms extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != certificate_request) { + return EXT_NOT_ALLOWED; + } + + ret = SAC_PARSE(ssl, input + offset, size, isRequest); + break; + #endif + + case TLSX_KEY_SHARE: + WOLFSSL_MSG("Key Share extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && msgType != server_hello && + msgType != hello_retry_request) { + return EXT_NOT_ALLOWED; + } + ret = KS_PARSE(ssl, input + offset, size, msgType); + break; #endif } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index adc72fb78..aab3a78bb 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -958,8 +958,10 @@ enum Misc { TLS_DRAFT_MAJOR = 0x7f, /* Draft TLS major version number */ #ifdef WOLFSSL_TLS13_DRAFT_18 TLS_DRAFT_MINOR = 0x12, /* Minor version number of TLS draft */ -#else +#elif defined(WOLFSSL_TLS13_DRAFT_22) TLS_DRAFT_MINOR = 0x16, /* Minor version number of TLS draft */ +#else + TLS_DRAFT_MINOR = 0x17, /* Minor version number of TLS draft */ #endif OLD_HELLO_ID = 0x01, /* SSLv2 Client Hello Indicator */ INVALID_BYTE = 0xff, /* Used to initialize cipher specs values */ @@ -1841,7 +1843,6 @@ typedef enum { TLSX_QUANTUM_SAFE_HYBRID = 0x0018, /* a.k.a. QSH */ TLSX_SESSION_TICKET = 0x0023, #ifdef WOLFSSL_TLS13 - TLSX_KEY_SHARE = 0x0028, #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TLSX_PRE_SHARED_KEY = 0x0029, #endif @@ -1856,6 +1857,12 @@ typedef enum { #ifdef WOLFSSL_POST_HANDSHAKE_AUTH TLSX_POST_HANDSHAKE_AUTH = 0x0031, #endif + #if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22) + TLSX_KEY_SHARE = 0x0028, + #else + TLSX_SIGNATURE_ALGORITHMS_CERT = 0x0032, + TLSX_KEY_SHARE = 0x0033, + #endif #endif TLSX_RENEGOTIATION_INFO = 0xff01 } TLSX_Type; @@ -3374,6 +3381,13 @@ struct WOLFSSL { word16 namedGroup; #endif byte pssAlgo; +#ifdef WOLFSSL_TLS13 + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + word16 certHashSigAlgoSz; /* SigAlgoCert ext length in bytes */ + byte certHashSigAlgo[WOLFSSL_MAX_SIGALGO]; /* cert sig/algo to + * offer */ + #endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */ +#endif #ifdef HAVE_NTRU word16 peerNtruKeyLen; byte peerNtruKey[MAX_NTRU_PUB_KEY_SZ];