Merge pull request #1209 from moisesguimaraes/tlsx-fix2

TLSX fixes
This commit is contained in:
dgarske
2017-11-10 08:44:58 -08:00
committed by GitHub
4 changed files with 121 additions and 69 deletions

View File

@ -14487,6 +14487,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case INVALID_PARAMETER: case INVALID_PARAMETER:
return "The security parameter is invalid"; return "The security parameter is invalid";
case UNSUPPORTED_EXTENSION:
return "TLS Extension not requested by the client";
case KEY_SHARE_ERROR: case KEY_SHARE_ERROR:
return "Key share extension did not contain a valid named group"; return "Key share extension did not contain a valid named group";

149
src/tls.c
View File

@ -952,8 +952,9 @@ static int TLSX_Push(TLSX** list, TLSX_Type type, void* data, void* heap)
TLSX_FreeAll(next, heap); TLSX_FreeAll(next, heap);
/* there is no way to occur more than */ /* there is no way to occur more than
/* two extensions of the same type. */ * two extensions of the same type.
*/
break; break;
} }
} while ((extension = extension->next)); } while ((extension = extension->next));
@ -961,6 +962,35 @@ static int TLSX_Push(TLSX** list, TLSX_Type type, void* data, void* heap)
return 0; 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)
{
SendAlert(ssl, alert_fatal, unsupported_extension);
return UNSUPPORTED_EXTENSION;
}
#else
#define TLSX_CheckUnsupportedExtension(ssl, type) 0
#define TLSX_HandleUnsupportedExtension(ssl) 0
#endif
#ifndef NO_WOLFSSL_SERVER #ifndef NO_WOLFSSL_SERVER
/** Mark an extension to be sent back to the client. */ /** Mark an extension to be sent back to the client. */
@ -968,10 +998,10 @@ void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type);
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) if (extension)
ext->resp = 1; extension->resp = 1;
} }
#endif #endif
@ -1172,9 +1202,8 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length,
#endif #endif
if (extension == NULL || extension->data == NULL) { if (extension == NULL || extension->data == NULL) {
WOLFSSL_MSG("No ALPN extensions not used or bad"); return isRequest ? 0
return isRequest ? 0 /* not using ALPN */ : TLSX_HandleUnsupportedExtension(ssl);
: BUFFER_ERROR; /* unexpected ALPN response */
} }
/* validating alpn list length */ /* validating alpn list length */
@ -1528,28 +1557,32 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length,
if (!extension) if (!extension)
extension = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME); extension = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
(void)isRequest; if (!isRequest) {
(void)input; #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) { if (!extension || !extension->data) {
#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. /* This will keep SNI even though TLSX_UseSNI has not been called.
* Enable it so that the received sni is available to functions * Enable it so that the received sni is available to functions
* that use a custom callback when SNI is received */ * that use a custom callback when SNI is received.
*/
cacheOnly = 1; cacheOnly = 1;
WOLFSSL_MSG("Forcing SSL object to store SNI parameter"); WOLFSSL_MSG("Forcing SSL object to store SNI parameter");
#else #else
return isRequest ? 0 /* not using SNI. */ /* Skipping, SNI not enabled at server side. */
: BUFFER_ERROR; /* unexpected SNI response. */ return 0;
#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) if (OPAQUE16_LEN > length)
return BUFFER_ERROR; return BUFFER_ERROR;
@ -1587,8 +1620,8 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length,
break; break;
#endif #endif
byte matched = cacheOnly || byte matched = cacheOnly ||
((XSTRLEN(sni->data.host_name) == size) ((XSTRLEN(sni->data.host_name) == size) &&
&& (XSTRNCMP(sni->data.host_name, (XSTRNCMP(sni->data.host_name,
(const char*)input + offset, size) == 0)); (const char*)input + offset, size) == 0));
if (matched || sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH) { if (matched || sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH) {
@ -1623,7 +1656,8 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length,
} }
} }
} }
#else
(void)input;
#endif #endif
return 0; return 0;
@ -1689,6 +1723,7 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size,
extension = TLSX_Find(*extensions, TLSX_SERVER_NAME); extension = TLSX_Find(*extensions, TLSX_SERVER_NAME);
if (!extension) { if (!extension) {
int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni, heap); int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni, heap);
if (ret != 0) { if (ret != 0) {
TLSX_SNI_Free(sni, heap); TLSX_SNI_Free(sni, heap);
return ret; return ret;
@ -1707,8 +1742,9 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size,
sni->next = next->next; sni->next = next->next;
TLSX_SNI_Free(next, heap); TLSX_SNI_Free(next, heap);
/* there is no way to occur more than */ /* there is no way to occur more than
/* two SNIs of the same type. */ * two SNIs of the same type.
*/
break; break;
} }
} while ((sni = sni->next)); } while ((sni = sni->next));
@ -1933,11 +1969,17 @@ static word16 TLSX_MFL_Write(byte* data, byte* output)
static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length,
byte isRequest) byte isRequest)
{ {
(void)isRequest;
if (length != ENUM_LEN) if (length != ENUM_LEN)
return BUFFER_ERROR; 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) { switch (*input) {
case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break; case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break;
case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break; case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break;
@ -1953,9 +1995,10 @@ static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length,
#ifndef NO_WOLFSSL_SERVER #ifndef NO_WOLFSSL_SERVER
if (isRequest) { 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); TLSX_SetResponse(ssl, TLSX_MAX_FRAGMENT_LENGTH);
} }
@ -1969,20 +2012,17 @@ int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap)
byte* data = NULL; 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; return BAD_FUNC_ARG;
if (mfl < WOLFSSL_MFL_2_9 || WOLFSSL_MFL_2_13 < mfl) data = (byte*)XMALLOC(ENUM_LEN, heap, DYNAMIC_TYPE_TLSX);
return BAD_FUNC_ARG; if (data == NULL)
if ((data = (byte*)XMALLOC(ENUM_LEN, heap, DYNAMIC_TYPE_TLSX)) == NULL)
return MEMORY_E; return MEMORY_E;
data[0] = mfl; data[0] = mfl;
/* push new MFL extension. */ ret = TLSX_Push(extensions, TLSX_MAX_FRAGMENT_LENGTH, data, heap);
if ((ret = TLSX_Push(extensions, TLSX_MAX_FRAGMENT_LENGTH, data, heap)) if (ret != 0) {
!= 0) {
XFREE(data, heap, DYNAMIC_TYPE_TLSX); XFREE(data, heap, DYNAMIC_TYPE_TLSX);
return ret; return ret;
} }
@ -2014,21 +2054,25 @@ int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap)
static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length, static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length,
byte isRequest) byte isRequest)
{ {
(void)isRequest;
if (length != 0 || input == NULL) if (length != 0 || input == NULL)
return BUFFER_ERROR; 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 #ifndef NO_WOLFSSL_SERVER
if (isRequest) { int ret = TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap);
int r = TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap);
if (r != WOLFSSL_SUCCESS) if (ret != WOLFSSL_SUCCESS)
return r; /* throw error */ return ret; /* throw error */
TLSX_SetResponse(ssl, TLSX_TRUNCATED_HMAC); TLSX_SetResponse(ssl, TLSX_TRUNCATED_HMAC);
}
#endif #endif
}
ssl->truncated_hmac = 1; ssl->truncated_hmac = 1;
@ -2042,7 +2086,8 @@ int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap)
if (extensions == NULL) if (extensions == NULL)
return BAD_FUNC_ARG; 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 ret;
return WOLFSSL_SUCCESS; return WOLFSSL_SUCCESS;
@ -2156,8 +2201,8 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length,
extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST); extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST);
csr = extension ? (CertificateStatusRequest*)extension->data : NULL; csr = extension ? (CertificateStatusRequest*)extension->data : NULL;
if (!csr) if (!csr) /* unexpected extension */
return BUFFER_ERROR; /* unexpected extension */ return TLSX_HandleUnsupportedExtension(ssl);
/* enable extension at ssl level */ /* enable extension at ssl level */
ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, ret = TLSX_UseCertificateStatusRequest(&ssl->extensions,
@ -2518,8 +2563,8 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length,
csr2 = extension ? csr2 = extension ?
(CertificateStatusRequestItemV2*)extension->data : NULL; (CertificateStatusRequestItemV2*)extension->data : NULL;
if (!csr2) if (!csr2) /* unexpected extension */
return BUFFER_ERROR; /* unexpected extension */ return TLSX_HandleUnsupportedExtension(ssl);
/* enable extension at ssl level */ /* enable extension at ssl level */
for (; csr2; csr2 = csr2->next) { for (; csr2; csr2 = csr2->next) {
@ -3038,7 +3083,8 @@ static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, byte* input, word16 length,
word16 name; word16 name;
int ret; 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) if (OPAQUE16_LEN > length || length % OPAQUE16_LEN)
return BUFFER_ERROR; return BUFFER_ERROR;
@ -3053,7 +3099,6 @@ static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, byte* input, word16 length,
ato16(input + offset, &name); ato16(input + offset, &name);
ret = TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap); ret = TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap);
if (ret != WOLFSSL_SUCCESS) if (ret != WOLFSSL_SUCCESS)
return ret; /* throw error */ return ret; /* throw error */
} }
@ -3724,7 +3769,9 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length,
(void) input; /* avoid unused parameter if NO_WOLFSSL_SERVER defined */ (void) input; /* avoid unused parameter if NO_WOLFSSL_SERVER defined */
if (!isRequest) { if (!isRequest) {
/* client side */ if (TLSX_CheckUnsupportedExtension(ssl, TLSX_SESSION_TICKET))
return TLSX_HandleUnsupportedExtension(ssl);
if (length != 0) if (length != 0)
return BUFFER_ERROR; return BUFFER_ERROR;

View File

@ -164,6 +164,7 @@ enum wolfSSL_ErrorCodes {
MCAST_HIGHWATER_CB_E = -426, /* Multicast highwater cb err */ MCAST_HIGHWATER_CB_E = -426, /* Multicast highwater cb err */
ALERT_COUNT_E = -427, /* Alert Count exceeded err */ ALERT_COUNT_E = -427, /* Alert Count exceeded err */
EXT_MISSING = -428, /* Required extension not found */ 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 !!!!! */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */
/* begin negotiation parameter errors */ /* begin negotiation parameter errors */

View File

@ -301,6 +301,7 @@ enum AlertDescription {
protocol_version = 70, protocol_version = 70,
#endif #endif
no_renegotiation = 100, no_renegotiation = 100,
unsupported_extension = 110, /**< RFC 5246, section 7.2.2 */
unrecognized_name = 112, /**< RFC 6066, section 3 */ unrecognized_name = 112, /**< RFC 6066, section 3 */
bad_certificate_status_response = 113, /**< RFC 6066, section 8 */ bad_certificate_status_response = 113, /**< RFC 6066, section 8 */
no_application_protocol = 120 no_application_protocol = 120