Add ssl_set_renegotiation_enforced()
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index 91e3981..b90b232 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -221,6 +221,9 @@
#define SSL_RENEGOTIATION_DISABLED 0
#define SSL_RENEGOTIATION_ENABLED 1
+#define SSL_RENEGOTIATION_NOT_ENFORCED -1
+#define SSL_RENEGO_MAX_RECORDS_DEFAULT 16
+
#define SSL_LEGACY_NO_RENEGOTIATION 0
#define SSL_LEGACY_ALLOW_RENEGOTIATION 1
#define SSL_LEGACY_BREAK_HANDSHAKE 2
@@ -620,6 +623,7 @@
*/
int state; /*!< SSL handshake: current state */
int renegotiation; /*!< Initial or renegotiation */
+ int renego_records_seen; /*!< Records since renego request */
int major_ver; /*!< equal to SSL_MAJOR_VERSION_3 */
int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */
@@ -744,6 +748,7 @@
int verify_result; /*!< verification result */
int disable_renegotiation; /*!< enable/disable renegotiation */
int allow_legacy_renegotiation; /*!< allow legacy renegotiation */
+ int renego_max_records; /*!< grace period for renegotiation */
const int *ciphersuite_list[4]; /*!< allowed ciphersuites / version */
#if defined(POLARSSL_SSL_SET_CURVES)
const ecp_group_id *curve_list; /*!< allowed curves */
@@ -1422,6 +1427,33 @@
void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy );
/**
+ * \brief Enforce server-requested renegotiation.
+ * (Default: enforced, max_records = 16)
+ * (No effect on client.)
+ *
+ * When a server requests a renegotiation, the client can
+ * comply or ignore the request. This function allows the
+ * server to decide if it should enforce its renegotiation
+ * requests by closing the connection if the client doesn't
+ * initiate a renegotiation.
+ *
+ * However, records could already be in transit from the
+ * client to the server when the request is emitted. In order
+ * to increase reliability, the server can accept a number of
+ * records containing application data before the ClientHello
+ * that was requested.
+ *
+ * The optimal value is highly dependent on the specific usage
+ * scenario.
+ *
+ * \param ssl SSL context
+ * \param max_records Use SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to
+ * enforce renegotiation, or a non-negative value to enforce
+ * it but allow for a grace period of max_records records.
+ */
+void ssl_set_renegotiation_enforced( ssl_context *ssl, int max_records );
+
+/**
* \brief Return the number of data bytes available to read
*
* \param ssl SSL context
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index a1428dc..7c8f306 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -3055,7 +3055,10 @@
ssl->handshake = NULL;
if( ssl->renegotiation == SSL_RENEGOTIATION )
+ {
ssl->renegotiation = SSL_RENEGOTIATION_DONE;
+ ssl->renego_records_seen = 0;
+ }
/*
* Switch in our now active transform context
@@ -3345,6 +3348,8 @@
ssl_set_ciphersuites( ssl, ssl_list_ciphersuites() );
+ ssl->renego_max_records = SSL_RENEGO_MAX_RECORDS_DEFAULT;
+
#if defined(POLARSSL_DHM_C)
if( ( ret = mpi_read_string( &ssl->dhm_P, 16,
POLARSSL_DHM_RFC5114_MODP_1024_P) ) != 0 ||
@@ -3435,6 +3440,8 @@
ssl->transform_in = NULL;
ssl->transform_out = NULL;
+ ssl->renego_records_seen = 0;
+
memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
memset( ssl->in_ctr, 0, SSL_BUFFER_LEN );
@@ -3952,6 +3959,11 @@
ssl->allow_legacy_renegotiation = allow_legacy;
}
+void ssl_set_renegotiation_enforced( ssl_context *ssl, int max_records )
+{
+ ssl->renego_max_records = max_records;
+}
+
#if defined(POLARSSL_SSL_SESSION_TICKETS)
int ssl_set_session_tickets( ssl_context *ssl, int use_tickets )
{
@@ -4296,9 +4308,15 @@
}
else if( ssl->renegotiation == SSL_RENEGOTIATION_PENDING )
{
- SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
- "but not honored by client" ) );
- return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ ssl->renego_records_seen++;
+
+ if( ssl->renego_max_records >= 0 &&
+ ssl->renego_records_seen > ssl->renego_max_records )
+ {
+ SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
+ "but not honored by client" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
}
else if( ssl->in_msgtype != SSL_MSG_APPLICATION_DATA )
{
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 102a5b5..6c2a92d 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -630,8 +630,8 @@
-C "=> renegotiate" \
-S "=> renegotiate" \
-s "write hello request" \
- -s "SSL - An unexpected message was received from our peer" \
- -s "failed"
+ -S "SSL - An unexpected message was received from our peer" \
+ -S "failed"
# Tests for auth_mode