From 0dd2ba2d80a3f711995d044650b91b2dbde63c72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Tue, 24 Oct 2017 13:19:39 -0300 Subject: [PATCH 1/8] adds unsupported_extension behavior to SNI --- src/internal.c | 3 +++ src/tls.c | 61 +++++++++++++++++++++++++++++---------------- wolfssl/error-ssl.h | 1 + wolfssl/ssl.h | 1 + 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/internal.c b/src/internal.c index c45aa2bb4..540376aa9 100644 --- a/src/internal.c +++ b/src/internal.c @@ -14487,6 +14487,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case INVALID_PARAMETER: return "The security parameter is invalid"; + case UNSUPPORTED_EXTENSION: + return "TLS Extension not requested by the client"; + case KEY_SHARE_ERROR: return "Key share extension did not contain a valid named group"; diff --git a/src/tls.c b/src/tls.c index 2177d9b65..1327c8cd3 100644 --- a/src/tls.c +++ b/src/tls.c @@ -952,8 +952,9 @@ static int TLSX_Push(TLSX** list, TLSX_Type type, void* data, void* heap) TLSX_FreeAll(next, heap); - /* there is no way to occur more than */ - /* two extensions of the same type. */ + /* there is no way to occur more than + * two extensions of the same type. + */ break; } } while ((extension = extension->next)); @@ -968,10 +969,10 @@ void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type); void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type) { - TLSX *ext = TLSX_Find(ssl->extensions, type); + TLSX *extension = TLSX_Find(ssl->extensions, type); - if (ext) - ext->resp = 1; + if (extension) + extension->resp = 1; } #endif @@ -1480,7 +1481,7 @@ static word16 TLSX_SNI_Write(SNI* list, byte* output) /** Finds a SNI object in the provided list. */ static SNI* TLSX_SNI_Find(SNI *list, byte type) { - SNI *sni = list; + SNI* sni = list; while (sni && sni->type != type) sni = sni->next; @@ -1532,16 +1533,30 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, (void)input; if (!extension || !extension->data) { + /* server_side */ + if (isRequest) { #if defined(WOLFSSL_ALWAYS_KEEP_SNI) && !defined(NO_WOLFSSL_SERVER) - /* This will keep SNI even though TLSX_UseSNI has not been called. - * Enable it so that the received sni is available to functions - * that use a custom callback when SNI is received */ - cacheOnly = 1; - WOLFSSL_MSG("Forcing SSL object to store SNI parameter"); + /* This will keep SNI even though TLSX_UseSNI has not been called. + * Enable it so that the received sni is available to functions + * that use a custom callback when SNI is received. + */ + + cacheOnly = 1; + WOLFSSL_MSG("Forcing SSL object to store SNI parameter"); #else - return isRequest ? 0 /* not using SNI. */ - : BUFFER_ERROR; /* unexpected SNI response. */ + /* Skipping, SNI not enabled at server side. */ + return 0; #endif + } + /* client_side */ + else { +#ifdef WOLFSSL_SKIP_UNEXPECTED_TLSX + return 0; +#else + SendAlert(ssl, alert_fatal, unsupported_extension); + return UNSUPPORTED_EXTENSION; +#endif + } } if (!isRequest) @@ -1587,9 +1602,9 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, break; #endif byte matched = cacheOnly || - ((XSTRLEN(sni->data.host_name) == size) - && (XSTRNCMP(sni->data.host_name, - (const char*)input + offset, size) == 0)); + ((XSTRLEN(sni->data.host_name) == size) && + (XSTRNCMP(sni->data.host_name, + (const char*)input + offset, size) == 0)); if (matched || sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH) { int r = TLSX_UseSNI(&ssl->extensions, @@ -1678,7 +1693,7 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, void* heap) { TLSX* extension; - SNI* sni = NULL; + SNI* sni = NULL; if (extensions == NULL || data == NULL) return BAD_FUNC_ARG; @@ -1689,6 +1704,7 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, extension = TLSX_Find(*extensions, TLSX_SERVER_NAME); if (!extension) { int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni, heap); + if (ret != 0) { TLSX_SNI_Free(sni, heap); return ret; @@ -1702,13 +1718,14 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, /* remove duplicate SNI, there should be only one of each type. */ do { if (sni->next && sni->next->type == type) { - SNI *next = sni->next; + SNI* next = sni->next; sni->next = next->next; TLSX_SNI_Free(next, heap); - /* there is no way to occur more than */ - /* two SNIs of the same type. */ + /* there is no way to occur more than + * two SNIs of the same type. + */ break; } } while ((sni = sni->next)); @@ -1753,8 +1770,8 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, byte type, byte* sni, word32* inOutSz) { word32 offset = 0; - word32 len32 = 0; - word16 len16 = 0; + word32 len32 = 0; + word16 len16 = 0; if (helloSz < RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + CLIENT_HELLO_FIRST) return INCOMPLETE_DATA; diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index cef6ed945..ff1bb0b71 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -164,6 +164,7 @@ enum wolfSSL_ErrorCodes { MCAST_HIGHWATER_CB_E = -426, /* Multicast highwater cb err */ ALERT_COUNT_E = -427, /* Alert Count exceeded err */ EXT_MISSING = -428, /* Required extension not found */ + UNSUPPORTED_EXTENSION = -429, /* TLSX not requested by client */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ /* begin negotiation parameter errors */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index deb248317..4eacb2aab 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -301,6 +301,7 @@ enum AlertDescription { protocol_version = 70, #endif no_renegotiation = 100, + unsupported_extension = 110, /**< RFC 5246, section 7.2.2 */ unrecognized_name = 112, /**< RFC 6066, section 3 */ bad_certificate_status_response = 113, /**< RFC 6066, section 8 */ no_application_protocol = 120 From cd4eb2c5b1e42b516abab80bc034a920e817636c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Sat, 3 Jun 2017 13:20:51 -0300 Subject: [PATCH 2/8] adds unsupported_extension behavior to MFL --- src/tls.c | 99 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 62 insertions(+), 37 deletions(-) diff --git a/src/tls.c b/src/tls.c index 1327c8cd3..4ac34513f 100644 --- a/src/tls.c +++ b/src/tls.c @@ -962,6 +962,40 @@ static int TLSX_Push(TLSX** list, TLSX_Type type, void* data, void* heap) return 0; } +#ifndef NO_WOLFSSL_CLIENT + +int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type); + +int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type) +{ + TLSX *extension = TLSX_Find(ssl->extensions, type); + + if (!extension) + extension = TLSX_Find(ssl->ctx->extensions, type); + + return extension == NULL; +} + +int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl); + +int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl) +{ + #ifdef WOLFSSL_SKIP_UNSUPPORTED_EXTENSION + (void)ssl; + return 0; + #else + SendAlert(ssl, alert_fatal, unsupported_extension); + return UNSUPPORTED_EXTENSION; + #endif +} + +#else + +#define TLSX_CheckUnsupportedExtension(ssl, type) 0 +#define TLSX_HandleUnsupportedExtension(ssl) 0 + +#endif + #ifndef NO_WOLFSSL_SERVER /** Mark an extension to be sent back to the client. */ @@ -1529,13 +1563,19 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, if (!extension) extension = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME); - (void)isRequest; - (void)input; + if (!isRequest) { + #ifndef NO_WOLFSSL_CLIENT + if (!extension || !extension->data) + return TLSX_HandleUnsupportedExtension(ssl); + return length ? BUFFER_ERROR /* SNI response MUST be empty. */ + : 0; /* nothing else to do. */ + #endif + } + +#ifndef NO_WOLFSSL_SERVER if (!extension || !extension->data) { - /* server_side */ - if (isRequest) { -#if defined(WOLFSSL_ALWAYS_KEEP_SNI) && !defined(NO_WOLFSSL_SERVER) + #if defined(WOLFSSL_ALWAYS_KEEP_SNI) && !defined(NO_WOLFSSL_SERVER) /* This will keep SNI even though TLSX_UseSNI has not been called. * Enable it so that the received sni is available to functions * that use a custom callback when SNI is received. @@ -1543,28 +1583,12 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, cacheOnly = 1; WOLFSSL_MSG("Forcing SSL object to store SNI parameter"); -#else + #else /* Skipping, SNI not enabled at server side. */ return 0; -#endif - } - /* client_side */ - else { -#ifdef WOLFSSL_SKIP_UNEXPECTED_TLSX - return 0; -#else - SendAlert(ssl, alert_fatal, unsupported_extension); - return UNSUPPORTED_EXTENSION; -#endif - } + #endif } - if (!isRequest) - return length ? BUFFER_ERROR /* SNI response MUST be empty. */ - : 0; /* nothing else to do. */ - -#ifndef NO_WOLFSSL_SERVER - if (OPAQUE16_LEN > length) return BUFFER_ERROR; @@ -1638,7 +1662,8 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, } } } - +#else + void(input); #endif return 0; @@ -1950,11 +1975,13 @@ static word16 TLSX_MFL_Write(byte* data, byte* output) static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest) { - (void)isRequest; - if (length != ENUM_LEN) return BUFFER_ERROR; + if (!isRequest) + if (TLSX_CheckUnsupportedExtension(ssl, TLSX_MAX_FRAGMENT_LENGTH)) + return TLSX_HandleUnsupportedExtension(ssl); + switch (*input) { case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break; case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break; @@ -1970,9 +1997,10 @@ static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, #ifndef NO_WOLFSSL_SERVER if (isRequest) { - int r = TLSX_UseMaxFragment(&ssl->extensions, *input, ssl->heap); + int ret = TLSX_UseMaxFragment(&ssl->extensions, *input, ssl->heap); - if (r != WOLFSSL_SUCCESS) return r; /* throw error */ + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ TLSX_SetResponse(ssl, TLSX_MAX_FRAGMENT_LENGTH); } @@ -1984,22 +2012,19 @@ static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap) { byte* data = NULL; - int ret = 0; + int ret = 0; - if (extensions == NULL) + if (extensions == NULL || mfl < WOLFSSL_MFL_2_9 || WOLFSSL_MFL_2_13 < mfl) return BAD_FUNC_ARG; - if (mfl < WOLFSSL_MFL_2_9 || WOLFSSL_MFL_2_13 < mfl) - return BAD_FUNC_ARG; - - if ((data = (byte*)XMALLOC(ENUM_LEN, heap, DYNAMIC_TYPE_TLSX)) == NULL) + data = (byte*)XMALLOC(ENUM_LEN, heap, DYNAMIC_TYPE_TLSX); + if (data == NULL) return MEMORY_E; data[0] = mfl; - /* push new MFL extension. */ - if ((ret = TLSX_Push(extensions, TLSX_MAX_FRAGMENT_LENGTH, data, heap)) - != 0) { + ret = TLSX_Push(extensions, TLSX_MAX_FRAGMENT_LENGTH, data, heap); + if (ret != 0) { XFREE(data, heap, DYNAMIC_TYPE_TLSX); return ret; } From a636858a497904b6ab2d22c412d4a279d11bc2a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Sat, 3 Jun 2017 13:36:13 -0300 Subject: [PATCH 3/8] adds unsupported_extension behavior to THMAC --- src/tls.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/tls.c b/src/tls.c index 4ac34513f..bf44aad51 100644 --- a/src/tls.c +++ b/src/tls.c @@ -2056,21 +2056,23 @@ int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap) static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest) { - (void)isRequest; - if (length != 0 || input == NULL) return BUFFER_ERROR; -#ifndef NO_WOLFSSL_SERVER - if (isRequest) { - int r = TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap); - - if (r != WOLFSSL_SUCCESS) - return r; /* throw error */ - - TLSX_SetResponse(ssl, TLSX_TRUNCATED_HMAC); + if (!isRequest) { + if (TLSX_CheckUnsupportedExtension(ssl, TLSX_TRUNCATED_HMAC)) + return TLSX_HandleUnsupportedExtension(ssl); + } + else { + #ifndef NO_WOLFSSL_SERVER + int ret = TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap); + + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ + + TLSX_SetResponse(ssl, TLSX_TRUNCATED_HMAC); + #endif } -#endif ssl->truncated_hmac = 1; @@ -2084,7 +2086,8 @@ int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap) if (extensions == NULL) return BAD_FUNC_ARG; - if ((ret = TLSX_Push(extensions, TLSX_TRUNCATED_HMAC, NULL, heap)) != 0) + ret = TLSX_Push(extensions, TLSX_TRUNCATED_HMAC, NULL, heap); + if (ret != 0) return ret; return WOLFSSL_SUCCESS; From c8e5558f3f0978dcc6d1fdead402b8061b8af33b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Sat, 3 Jun 2017 13:43:36 -0300 Subject: [PATCH 4/8] adds unsupported_extension behavior to CSR and CSR2 --- src/tls.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tls.c b/src/tls.c index bf44aad51..258e64af6 100644 --- a/src/tls.c +++ b/src/tls.c @@ -2201,8 +2201,8 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST); csr = extension ? (CertificateStatusRequest*)extension->data : NULL; - if (!csr) - return BUFFER_ERROR; /* unexpected extension */ + if (!csr) /* unexpected extension */ + return TLSX_HandleUnsupportedExtension(ssl); /* enable extension at ssl level */ ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, @@ -2563,8 +2563,8 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, csr2 = extension ? (CertificateStatusRequestItemV2*)extension->data : NULL; - if (!csr2) - return BUFFER_ERROR; /* unexpected extension */ + if (!csr2) /* unexpected extension */ + return TLSX_HandleUnsupportedExtension(ssl); /* enable extension at ssl level */ for (; csr2; csr2 = csr2->next) { From 56b38946ed12d642939ad2e620f7a83c08d9409b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Sat, 3 Jun 2017 14:12:16 -0300 Subject: [PATCH 5/8] adds unsupported_extension behavior to Session Tickets and Supported Curves --- src/tls.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tls.c b/src/tls.c index 258e64af6..625da6c24 100644 --- a/src/tls.c +++ b/src/tls.c @@ -3077,7 +3077,8 @@ static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, word16 name; int ret; - (void) isRequest; /* shut up compiler! */ + if(!isRequest) + return BUFFER_ERROR; /* servers doesn't send this extension. */ if (OPAQUE16_LEN > length || length % OPAQUE16_LEN) return BUFFER_ERROR; @@ -3092,7 +3093,6 @@ static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, ato16(input + offset, &name); ret = TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; /* throw error */ } @@ -3763,7 +3763,9 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, (void) input; /* avoid unused parameter if NO_WOLFSSL_SERVER defined */ if (!isRequest) { - /* client side */ + if (TLSX_CheckUnsupportedExtension(ssl, TLSX_SESSION_TICKET)) + return TLSX_HandleUnsupportedExtension(ssl); + if (length != 0) return BUFFER_ERROR; From caf5708bb638425191dd623948f905668d94a232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Sat, 3 Jun 2017 14:37:17 -0300 Subject: [PATCH 6/8] adds unsupported_extension behavior to ALPN --- src/tls.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/tls.c b/src/tls.c index 625da6c24..86bed5982 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1207,9 +1207,8 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, #endif if (extension == NULL || extension->data == NULL) { - WOLFSSL_MSG("No ALPN extensions not used or bad"); - return isRequest ? 0 /* not using ALPN */ - : BUFFER_ERROR; /* unexpected ALPN response */ + return isRequest ? 0 + : TLSX_HandleUnsupportedExtension(ssl); } /* validating alpn list length */ From b672616b38a1c779e5b2d8040b307ffdddcbec26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Fri, 21 Jul 2017 10:57:41 -0300 Subject: [PATCH 7/8] fixes cast to void --- src/tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tls.c b/src/tls.c index 86bed5982..8efbda0e0 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1662,7 +1662,7 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, } } #else - void(input); + (void)input; #endif return 0; From d7abd5c8fb72a8f9efce20bfb763a296bf955bfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Fri, 10 Nov 2017 11:35:49 -0200 Subject: [PATCH 8/8] changes WOLFSSL_SKIP_UNSUPPORTED_EXTENSION to WOLFSSL_OLD_UNSUPPORTED_EXTENSION --- src/tls.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/tls.c b/src/tls.c index 8efbda0e0..404f12247 100644 --- a/src/tls.c +++ b/src/tls.c @@ -980,13 +980,8 @@ int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl); int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl) { - #ifdef WOLFSSL_SKIP_UNSUPPORTED_EXTENSION - (void)ssl; - return 0; - #else - SendAlert(ssl, alert_fatal, unsupported_extension); - return UNSUPPORTED_EXTENSION; - #endif + SendAlert(ssl, alert_fatal, unsupported_extension); + return UNSUPPORTED_EXTENSION; } #else @@ -1196,7 +1191,7 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, ssl->alpnSelectArg) == 0) { WOLFSSL_MSG("ALPN protocol match"); if (TLSX_UseALPN(&ssl->extensions, (char*)out, outLen, 0, ssl->heap) - == WOLFSSL_SUCCESS) { + == WOLFSSL_SUCCESS) { if (extension == NULL) { extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); @@ -1977,9 +1972,13 @@ static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, if (length != ENUM_LEN) return BUFFER_ERROR; +#ifdef WOLFSSL_OLD_UNSUPPORTED_EXTENSION + (void) isRequest; +#else if (!isRequest) if (TLSX_CheckUnsupportedExtension(ssl, TLSX_MAX_FRAGMENT_LENGTH)) return TLSX_HandleUnsupportedExtension(ssl); +#endif switch (*input) { case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break; @@ -2059,8 +2058,10 @@ static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length, return BUFFER_ERROR; if (!isRequest) { + #ifndef WOLFSSL_OLD_UNSUPPORTED_EXTENSION if (TLSX_CheckUnsupportedExtension(ssl, TLSX_TRUNCATED_HMAC)) return TLSX_HandleUnsupportedExtension(ssl); + #endif } else { #ifndef NO_WOLFSSL_SERVER