diff --git a/configure.ac b/configure.ac index 8ab2f932a..a829be7dc 100644 --- a/configure.ac +++ b/configure.ac @@ -1321,7 +1321,7 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_TRUNCATED_HMAC" fi -# Renegotiation Indication +# Renegotiation Indication - (FAKE Secure Renegotiation) AC_ARG_ENABLE([renegotiation-indication], [ --enable-renegotiation-indication Enable Renegotiation Indication (default: disabled)], [ ENABLED_RENEGOTIATION_INDICATION=$enableval ], @@ -1333,6 +1333,18 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_RENEGOTIATION_INDICATION" fi +# Secure Renegotiation +AC_ARG_ENABLE([secure-renegotiation], + [ --enable-secure-renegotiation Enable Secure Renegotiation (default: disabled)], + [ ENABLED_SECURE_RENEGOTIATION=$enableval ], + [ ENABLED_SECURE_RENEGOTIATION=no ] + ) + +if test "x$ENABLED_SECURE_RENEGOTIATION" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SECURE_RENEGOTIATION" +fi + # Supported Elliptic Curves Extensions AC_ARG_ENABLE([supportedcurves], [ --enable-supportedcurves Enable Supported Elliptic Curves (default: disabled)], @@ -1357,9 +1369,8 @@ then ENABLED_SNI=yes ENABLED_MAX_FRAGMENT=yes ENABLED_TRUNCATED_HMAC=yes - ENABLED_RENEGOTIATION_INDICATION=yes ENABLED_SUPPORTED_CURVES=yes - AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC -DHAVE_RENEGOTIATION_INDICATION -DHAVE_SUPPORTED_CURVES" + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC -DHAVE_SUPPORTED_CURVES" fi # PKCS7 @@ -1860,6 +1871,7 @@ echo " * SNI: $ENABLED_SNI" echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT" echo " * Truncated HMAC: $ENABLED_TRUNCATED_HMAC" echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION" +echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION" echo " * Supported Elliptic Curves: $ENABLED_SUPPORTED_CURVES" echo " * All TLS Extensions: $ENABLED_TLSX" echo " * PKCS#7 $ENABLED_PKCS7" diff --git a/cyassl/error-ssl.h b/cyassl/error-ssl.h index 71778ec15..40c6c0c8d 100644 --- a/cyassl/error-ssl.h +++ b/cyassl/error-ssl.h @@ -118,6 +118,7 @@ enum CyaSSL_ErrorCodes { KEYUSE_ENCIPHER_E = -385, /* KeyUse keyEncipher error */ EXTKEYUSE_AUTH_E = -386, /* ExtKeyUse server|client_auth */ SEND_OOB_READ_E = -387, /* Send Cb out of bounds read */ + SECURE_RENEGOTIATION_E = -388, /* Invalid Renegotiation Info */ /* add strings to SetErrorString !!!!! */ /* begin negotiation parameter errors */ diff --git a/cyassl/internal.h b/cyassl/internal.h index 1e5870e30..6799dde5d 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1262,7 +1262,7 @@ CYASSL_LOCAL int TLSX_ValidateEllipticCurves(CYASSL* ssl, byte first, /* Additional Conection State according to rfc5746 section 3.1 */ typedef struct SecureRenegotiation { - byte secure_renegotation; + byte enabled; /* secure_renegotiation flag from rfc */ byte client_verify_data[TLS_FINISHED_SZ]; byte server_verify_data[TLS_FINISHED_SZ]; } SecureRenegotiation; @@ -1896,7 +1896,7 @@ typedef struct DtlsMsg { typedef struct SecureR_State { byte client_verify_data[TLS_FINISHED_SZ]; /* previous handshake value */ byte server_verify_data[TLS_FINISHED_SZ]; /* previous handshake value */ - byte secure_renegotation; /* extensions flag */ + byte secure_renegotiation; /* extensions flag */ byte previous_handshake_used; /* did previous handshake use secure r */ byte enabled; /* runtime allowed? */ } SecureR_State; @@ -2016,6 +2016,7 @@ struct CYASSL { #endif #ifdef HAVE_SECURE_RENEGOTIATION SecureR_State secureR_state; /* secure renegotiation state */ + SecureRenegotiation* secure_renegotiation; #endif #endif /* HAVE_TLS_EXTENSIONS */ #ifdef HAVE_NETX diff --git a/cyassl/ssl.h b/cyassl/ssl.h index cf7819d56..601223272 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -1216,6 +1216,7 @@ CYASSL_API int CyaSSL_CTX_UseCavium(CYASSL_CTX*, int devId); /* Server Name Indication */ #ifdef HAVE_SNI + /* SNI types */ enum { CYASSL_SNI_HOST_NAME = 0 @@ -1227,6 +1228,7 @@ CYASSL_API int CyaSSL_CTX_UseSNI(CYASSL_CTX* ctx, unsigned char type, const void* data, unsigned short size); #ifndef NO_CYASSL_SERVER + /* SNI options */ enum { CYASSL_SNI_CONTINUE_ON_MISMATCH = 0x01, /* do not abort on mismatch flag */ @@ -1249,16 +1251,16 @@ CYASSL_API unsigned char CyaSSL_SNI_Status(CYASSL* ssl, unsigned char type); CYASSL_API unsigned short CyaSSL_SNI_GetRequest(CYASSL *ssl, unsigned char type, void** data); - CYASSL_API int CyaSSL_SNI_GetFromBuffer( const unsigned char* clientHello, unsigned int helloSz, unsigned char type, unsigned char* sni, unsigned int* inOutSz); -#endif /* NO_CYASSL_SERVER */ -#endif /* HAVE_SNI */ +#endif +#endif /* Maximum Fragment Length */ #ifdef HAVE_MAX_FRAGMENT + /* Fragment lengths */ enum { CYASSL_MFL_2_9 = 1, /* 512 bytes */ @@ -1273,8 +1275,8 @@ enum { CYASSL_API int CyaSSL_UseMaxFragment(CYASSL* ssl, unsigned char mfl); CYASSL_API int CyaSSL_CTX_UseMaxFragment(CYASSL_CTX* ctx, unsigned char mfl); -#endif /* NO_CYASSL_CLIENT */ -#endif /* HAVE_MAX_FRAGMENT */ +#endif +#endif /* Truncated HMAC */ #ifdef HAVE_TRUNCATED_HMAC @@ -1283,8 +1285,8 @@ CYASSL_API int CyaSSL_CTX_UseMaxFragment(CYASSL_CTX* ctx, unsigned char mfl); CYASSL_API int CyaSSL_UseTruncatedHMAC(CYASSL* ssl); CYASSL_API int CyaSSL_CTX_UseTruncatedHMAC(CYASSL_CTX* ctx); -#endif /* NO_CYASSL_CLIENT */ -#endif /* HAVE_TRUNCATED_HMAC */ +#endif +#endif /* Elliptic Curves */ #ifdef HAVE_SUPPORTED_CURVES @@ -1302,11 +1304,19 @@ enum { CYASSL_API int CyaSSL_UseSupportedCurve(CYASSL* ssl, unsigned short name); CYASSL_API int CyaSSL_CTX_UseSupportedCurve(CYASSL_CTX* ctx, - unsigned short name); + unsigned short name); -#endif /* NO_CYASSL_CLIENT */ -#endif /* HAVE_SUPPORTED_CURVES */ +#endif +#endif +/* Secure Renegotiation */ +#ifdef HAVE_SECURE_RENEGOTIATION +#ifndef NO_CYASSL_CLIENT + +CYASSL_API int CyaSSL_UseSecureRenegotiation(CYASSL* ssl); + +#endif +#endif #define CYASSL_CRL_MONITOR 0x01 /* monitor this dir flag */ #define CYASSL_CRL_START_MON 0x02 /* start monitoring flag */ diff --git a/src/internal.c b/src/internal.c index 1b1ee9f25..2a7b0bd98 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1738,6 +1738,9 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) #ifdef HAVE_TRUNCATED_HMAC ssl->truncated_hmac = 0; #endif +#ifdef HAVE_SECURE_RENEGOTIATION + ssl->secure_renegotiation = NULL; +#endif #endif ssl->rng = NULL; @@ -1773,7 +1776,7 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) #endif /* HAVE_PK_CALLBACKS */ #if defined(HAVE_SECURE_RENEGOTIATION) && defined(HAVE_TLS_EXTENSIONS) - ssl->secureR_state.secure_renegotation = 0; + ssl->secureR_state.secure_renegotiation = 0; ssl->secureR_state.previous_handshake_used = 0; ssl->secureR_state.enabled = 0; #endif /* HAVE_SECURE_RENEGOTIATION && HAVE_TLS_EXTENSIONS */ diff --git a/src/ssl.c b/src/ssl.c index 855ee2943..e861a8fbd 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -714,6 +714,27 @@ int CyaSSL_CTX_UseSupportedCurve(CYASSL_CTX* ctx, word16 name) #endif /* NO_CYASSL_CLIENT */ #endif /* HAVE_SUPPORTED_CURVES */ +/* Secure Renegotiation */ +#ifdef HAVE_SECURE_RENEGOTIATION + +int CyaSSL_UseSecureRenegotiation(CYASSL* ssl) +{ + int ret = BAD_FUNC_ARG; + + if (ssl) + ret = TLSX_UseSecureRenegotiation(&ssl->extensions); + + if (ret == SSL_SUCCESS) { + TLSX* extension = TLSX_Find(ssl->extensions, SECURE_RENEGOTIATION); + + if (extension) + ssl->secure_renegotiation = (SecureRenegotiation*)extension->data; + } + + return ret; +} + +#endif #ifndef CYASSL_LEANPSK int CyaSSL_send(CYASSL* ssl, const void* data, int sz, int flags) diff --git a/src/tls.c b/src/tls.c index 58ac441c4..7b0e1d612 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1617,7 +1617,7 @@ static byte TLSX_SCR_GetSize(SecureRenegotiation* data, int isRequest) { byte length = OPAQUE8_LEN; /* RenegotiationInfo length */ - if (data->secure_renegotiation) { + if (data->enabled) { /* client sends client_verify_data only */ length += TLS_FINISHED_SZ; @@ -1636,7 +1636,7 @@ static word16 TLSX_SCR_Write(SecureRenegotiation* data, byte* output, output[0] = TLSX_SCR_GetSize(data, isRequest); - if (data->secure_renegotiation) { + if (data->enabled) { /* client sends client_verify_data only */ XMEMCPY(output + offset, data->client_verify_data, TLS_FINISHED_SZ); offset += TLS_FINISHED_SZ; @@ -1654,33 +1654,44 @@ static word16 TLSX_SCR_Write(SecureRenegotiation* data, byte* output, static int TLSX_SCR_Parse(CYASSL* ssl, byte* input, word16 length, byte isRequest) { - if (length != ENUM_LEN) - return BUFFER_ERROR; + int ret = SECURE_RENEGOTIATION_E; - switch (*input) { - case CYASSL_MFL_2_9 : ssl->max_fragment = 512; break; - case CYASSL_MFL_2_10: ssl->max_fragment = 1024; break; - case CYASSL_MFL_2_11: ssl->max_fragment = 2048; break; - case CYASSL_MFL_2_12: ssl->max_fragment = 4096; break; - case CYASSL_MFL_2_13: ssl->max_fragment = 8192; break; - - default: - SendAlert(ssl, alert_fatal, illegal_parameter); - - return UNKNOWN_MAX_FRAG_LEN_E; + if (length >= OPAQUE8_LEN && *input == (length - OPAQUE8_LEN)) { + if (ssl->secure_renegotiation == NULL) { + #ifndef NO_CYASSL_SERVER + if (isRequest && *input == 0) { + ret = CyaSSL_UseSecureRenegotiation(ssl); + } + #endif + } + else if (isRequest) { + #ifndef NO_CYASSL_SERVER + if (*input == TLS_FINISHED_SZ) { + /* TODO compare client_verify_data */ + ret = 0; + } + #endif + } + else { + #ifndef NO_CYASSL_CLIENT + if (!ssl->secure_renegotiation->enabled) { + if (*input == 0) { + ssl->secure_renegotiation->enabled = 1; + ret = 0; + } + } + else if (*input == 2 * TLS_FINISHED_SZ) { + /* TODO compare client_verify_data and server_verify_data */ + ret = 0; + } + #endif + } } -#ifndef NO_CYASSL_SERVER - if (isRequest) { - int r = TLSX_UseMaxFragment(&ssl->extensions, *input); + if (ret != 0) + SendAlert(ssl, alert_fatal, handshake_failure); - if (r != SSL_SUCCESS) return r; /* throw error */ - - TLSX_SetResponse(ssl, MAX_FRAGMENT_LENGTH); - } -#endif - - return 0; + return ret; } int TLSX_UseSecureRenegotiation(TLSX** extensions)