Merge support for enabling / disabling renegotiation support at compile-time
diff --git a/ChangeLog b/ChangeLog
index aa36db2..dadca0e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -27,6 +27,7 @@
    * Add x509_crl_parse_der().
    * Add compile-time option POLARSSL_X509_MAX_INTERMEDIATE_CA to limit the
      length of an X.509 verification chain.
+   * Support for renegotiation can now be disabled at compile-time
 
 Bugfix
    * Stack buffer overflow if ctr_drbg_update() is called with too large
diff --git a/configs/config-ccm-psk-tls1_2.h b/configs/config-ccm-psk-tls1_2.h
index 1da9f6a..00f92b7 100644
--- a/configs/config-ccm-psk-tls1_2.h
+++ b/configs/config-ccm-psk-tls1_2.h
@@ -19,6 +19,7 @@
 /* PolarSSL feature support */
 #define POLARSSL_KEY_EXCHANGE_PSK_ENABLED
 #define POLARSSL_SSL_PROTO_TLS1_2
+#define POLARSSL_SSL_DISABLE_RENEGOTIATION
 
 /* PolarSSL modules */
 #define POLARSSL_AES_C
diff --git a/configs/config-mini-tls1_1.h b/configs/config-mini-tls1_1.h
index 338fecf..47c94c1 100644
--- a/configs/config-mini-tls1_1.h
+++ b/configs/config-mini-tls1_1.h
@@ -18,6 +18,7 @@
 #define POLARSSL_PKCS1_V15
 #define POLARSSL_KEY_EXCHANGE_RSA_ENABLED
 #define POLARSSL_SSL_PROTO_TLS1_1
+#define POLARSSL_SSL_DISABLE_RENEGOTIATION
 
 /* PolarSSL modules */
 #define POLARSSL_AES_C
diff --git a/configs/config-psk-rc4-tls1_0.h b/configs/config-psk-rc4-tls1_0.h
index c967b4c..7eafb24 100644
--- a/configs/config-psk-rc4-tls1_0.h
+++ b/configs/config-psk-rc4-tls1_0.h
@@ -19,6 +19,7 @@
 /* PolarSSL feature support */
 #define POLARSSL_KEY_EXCHANGE_PSK_ENABLED
 #define POLARSSL_SSL_PROTO_TLS1
+#define POLARSSL_SSL_DISABLE_RENEGOTIATION
 
 /* PolarSSL modules */
 #define POLARSSL_AES_C
diff --git a/configs/config-suite-b.h b/configs/config-suite-b.h
index cd38f33..cabc3d1 100644
--- a/configs/config-suite-b.h
+++ b/configs/config-suite-b.h
@@ -25,6 +25,7 @@
 #define POLARSSL_ECP_DP_SECP384R1_ENABLED
 #define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 #define POLARSSL_SSL_PROTO_TLS1_2
+#define POLARSSL_SSL_DISABLE_RENEGOTIATION
 
 /* PolarSSL modules */
 #define POLARSSL_AES_C
diff --git a/include/polarssl/config.h b/include/polarssl/config.h
index c99b448..b155e26 100644
--- a/include/polarssl/config.h
+++ b/include/polarssl/config.h
@@ -887,6 +887,24 @@
 //#define POLARSSL_SSL_HW_RECORD_ACCEL
 
 /**
+ * \def POLARSSL_SSL_DISABLE_RENEGOTIATION
+ *
+ * Disable support for TLS renegotiation.
+ *
+ * The two main uses of renegotiation are (1) refresh keys on long-lived
+ * connections and (2) client authentication after the initial handshake.
+ * If you don't need renegotiation, it's probably better to disable it, since
+ * it has been associated with security issues in the past and is easy to
+ * misuse/misunderstand.
+ *
+ * Warning: in the next stable branch, this switch will be replaced by
+ * POLARSSL_SSL_RENEGOTIATION to enable support for renegotiation.
+ *
+ * Uncomment this to disable support for renegotiation.
+ */
+//#define POLARSSL_SSL_DISABLE_RENEGOTIATION
+
+/**
  * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
  *
  * Enable support for receiving and parsing SSLv2 Client Hello messages for the
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index 63ec314..bf2527a 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -32,6 +32,12 @@
 #else
 #include POLARSSL_CONFIG_FILE
 #endif
+
+/* Temporary compatibility trick for the current stable branch */
+#if !defined(POLARSSL_SSL_DISABLE_RENEGOTIATION)
+#define POLARSSL_SSL_RENEGOTIATION
+#endif
+
 #include "net.h"
 #include "bignum.h"
 #include "ecp.h"
@@ -314,6 +320,15 @@
                         )
 
 /*
+ * Length of the verify data for secure renegotiation
+ */
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+#define SSL_VERIFY_DATA_MAX_LEN 36
+#else
+#define SSL_VERIFY_DATA_MAX_LEN 12
+#endif
+
+/*
  * Signaling ciphersuite values (SCSV)
  */
 #define SSL_EMPTY_RENEGOTIATION_INFO    0xFF   /**< renegotiation info ext */
@@ -708,7 +723,9 @@
      */
     int state;                  /*!< SSL handshake: current state     */
     int renegotiation;          /*!< Initial or renegotiation         */
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     int renego_records_seen;    /*!< Records since renego request     */
+#endif
 
     int major_ver;              /*!< equal to  SSL_MAJOR_VERSION_3    */
     int minor_ver;              /*!< either 0 (SSL3) or 1 (TLS1.0)    */
@@ -841,9 +858,13 @@
     int authmode;                       /*!<  verification mode       */
     int client_auth;                    /*!<  flag for client auth.   */
     int verify_result;                  /*!<  verification result     */
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     int disable_renegotiation;          /*!<  enable/disable renegotiation   */
-    int allow_legacy_renegotiation;     /*!<  allow legacy renegotiation     */
     int renego_max_records;             /*!<  grace period for renegotiation */
+    unsigned char renego_period[8];     /*!<  value of the record counters
+                                              that triggers renegotiation    */
+#endif
+    int allow_legacy_renegotiation;     /*!<  allow legacy renegotiation     */
     const int *ciphersuite_list[4];     /*!<  allowed ciphersuites / version */
 #if defined(POLARSSL_SSL_SET_CURVES)
     const ecp_group_id *curve_list;     /*!<  allowed curves                 */
@@ -892,9 +913,11 @@
      */
     int secure_renegotiation;           /*!<  does peer support legacy or
                                               secure renegotiation           */
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     size_t verify_data_len;             /*!<  length of verify data stored   */
-    char own_verify_data[36];           /*!<  previous handshake verify data */
-    char peer_verify_data[36];          /*!<  previous handshake verify data */
+    char own_verify_data[SSL_VERIFY_DATA_MAX_LEN]; /*!<  previous handshake verify data */
+    char peer_verify_data[SSL_VERIFY_DATA_MAX_LEN]; /*!<  previous handshake verify data */
+#endif
 };
 
 #if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
@@ -1534,6 +1557,7 @@
 void ssl_set_session_ticket_lifetime( ssl_context *ssl, int lifetime );
 #endif /* POLARSSL_SSL_SESSION_TICKETS */
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
 /**
  * \brief          Enable / Disable renegotiation support for connection when
  *                 initiated by peer
@@ -1548,6 +1572,7 @@
  *                                             SSL_RENEGOTIATION_DISABLED)
  */
 void ssl_set_renegotiation( ssl_context *ssl, int renegotiation );
+#endif /* POLARSSL_SSL_RENEGOTIATION */
 
 /**
  * \brief          Prevent or allow legacy renegotiation.
@@ -1578,8 +1603,9 @@
  */
 void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy );
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
 /**
- * \brief          Enforce server-requested renegotiation.
+ * \brief          Enforce requested renegotiation.
  *                 (Default: enforced, max_records = 16)
  *
  *                 When we request a renegotiation, the peer can comply or
@@ -1609,6 +1635,27 @@
 void ssl_set_renegotiation_enforced( ssl_context *ssl, int max_records );
 
 /**
+ * \brief          Set record counter threshold for periodic renegotiation.
+ *                 (Default: 2^64 - 256.)
+ *
+ *                 Renegotiation is automatically triggered when a record
+ *                 counter (outgoing or ingoing) crosses the defined
+ *                 threshold. The default value is meant to prevent the
+ *                 connection from being closed when the counter is about to
+ *                 reached its maximal value (it is not allowed to wrap).
+ *
+ *                 Lower values can be used to enforce policies such as "keys
+ *                 must be refreshed every N packets with cipher X".
+ *
+ * \param ssl      SSL context
+ * \param period   The threshold value: a big-endian 64-bit number.
+ *                 Set to 2^64 - 1 to disable periodic renegotiation
+ */
+void ssl_set_renegotiation_period( ssl_context *ssl,
+                                   const unsigned char period[8] );
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
+/**
  * \brief          Return the number of data bytes available to read
  *
  * \param ssl      SSL context
@@ -1710,6 +1757,7 @@
  */
 int ssl_handshake_step( ssl_context *ssl );
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
 /**
  * \brief          Initiate an SSL renegotiation on the running connection.
  *                 Client: perform the renegotiation right now.
@@ -1721,6 +1769,7 @@
  * \return         0 if successful, or any ssl_handshake() return value.
  */
 int ssl_renegotiate( ssl_context *ssl );
+#endif /* POLARSSL_SSL_RENEGOTIATION */
 
 /**
  * \brief          Read at most 'len' application data bytes
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 0db9e23..cf8e46c 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -114,6 +114,7 @@
 }
 #endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
 static void ssl_write_renegotiation_ext( ssl_context *ssl,
                                          unsigned char *buf,
                                          size_t *olen )
@@ -141,6 +142,7 @@
 
     *olen = 5 + ssl->verify_data_len;
 }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
 
 /*
  * Only if we handle at least one key exchange that needs signatures.
@@ -521,7 +523,9 @@
         return( POLARSSL_ERR_SSL_NO_RNG );
     }
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+#endif
     {
         ssl->major_ver = ssl->min_major_ver;
         ssl->minor_ver = ssl->min_minor_ver;
@@ -585,7 +589,10 @@
      */
     n = ssl->session_negotiate->length;
 
-    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE || n < 16 || n > 32 ||
+    if( n < 16 || n > 32 ||
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+        ssl->renegotiation != SSL_INITIAL_HANDSHAKE ||
+#endif
         ssl->handshake->resume == 0 )
     {
         n = 0;
@@ -596,8 +603,10 @@
      * RFC 5077 section 3.4: "When presenting a ticket, the client MAY
      * generate and include a Session ID in the TLS ClientHello."
      */
-    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE &&
-        ssl->session_negotiate->ticket != NULL &&
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+#endif
+    if( ssl->session_negotiate->ticket != NULL &&
         ssl->session_negotiate->ticket_len != 0 )
     {
         ret = ssl->f_rng( ssl->p_rng, ssl->session_negotiate->id, 32 );
@@ -627,7 +636,9 @@
     /*
      * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
      */
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+#endif
     {
         *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO >> 8 );
         *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO      );
@@ -693,8 +704,10 @@
     ext_len += olen;
 #endif
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen );
     ext_len += olen;
+#endif
 
 #if defined(POLARSSL_SSL_PROTO_TLS1_2) && \
     defined(POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED)
@@ -740,6 +753,9 @@
     ext_len += olen;
 #endif
 
+    /* olen unused if all extensions are disabled */
+    ((void) olen);
+
     SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d",
                    ext_len ) );
 
@@ -773,21 +789,8 @@
 {
     int ret;
 
-    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
-    {
-        if( len != 1 || buf[0] != 0x0 )
-        {
-            SSL_DEBUG_MSG( 1, ( "non-zero length renegotiated connection field" ) );
-
-            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
-                return( ret );
-
-            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
-        }
-
-        ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
-    }
-    else
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
     {
         /* Check verify-data in constant-time. The length OTOH is no secret */
         if( len    != 1 + ssl->verify_data_len * 2 ||
@@ -797,7 +800,7 @@
             safer_memcmp( buf + 1 + ssl->verify_data_len,
                           ssl->peer_verify_data, ssl->verify_data_len ) != 0 )
         {
-            SSL_DEBUG_MSG( 1, ( "non-matching renegotiated connection field" ) );
+            SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) );
 
             if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
                 return( ret );
@@ -805,6 +808,21 @@
             return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
         }
     }
+    else
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+    {
+        if( len != 1 || buf[0] != 0x00 )
+        {
+            SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) );
+
+            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+                return( ret );
+
+            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+        }
+
+        ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
+    }
 
     return( 0 );
 }
@@ -996,7 +1014,9 @@
     size_t n;
     size_t ext_len;
     unsigned char *buf, *ext;
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     int renegotiation_info_seen = 0;
+#endif
     int handshake_failure = 0;
 #if defined(POLARSSL_DEBUG_C)
     uint32_t t;
@@ -1021,6 +1041,7 @@
 
     if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
     {
+#if defined(POLARSSL_SSL_RENEGOTIATION)
         if( ssl->renegotiation == SSL_RENEGOTIATION )
         {
             ssl->renego_records_seen++;
@@ -1036,6 +1057,7 @@
             SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) );
             return( POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO );
         }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
 
         SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
         return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
@@ -1144,8 +1166,10 @@
     /*
      * Check if the session can be resumed
      */
-    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE ||
-        ssl->handshake->resume == 0 || n == 0 ||
+    if( ssl->handshake->resume == 0 || n == 0 ||
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+        ssl->renegotiation != SSL_INITIAL_HANDSHAKE ||
+#endif
         ssl->session_negotiate->ciphersuite != i ||
         ssl->session_negotiate->compression != comp ||
         ssl->session_negotiate->length != n ||
@@ -1226,7 +1250,9 @@
         {
         case TLS_EXT_RENEGOTIATION_INFO:
             SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
+#if defined(POLARSSL_SSL_RENEGOTIATION)
             renegotiation_info_seen = 1;
+#endif
 
             if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4,
                                                       ext_size ) ) != 0 )
@@ -1346,6 +1372,7 @@
         SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
         handshake_failure = 1;
     }
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     else if( ssl->renegotiation == SSL_RENEGOTIATION &&
              ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION &&
              renegotiation_info_seen == 0 )
@@ -1367,6 +1394,7 @@
         SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) );
         handshake_failure = 1;
     }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
 
     if( handshake_failure == 1 )
     {
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 7bcec57..4fac0e4 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -431,11 +431,29 @@
 {
     int ret;
 
-    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
+    {
+        /* Check verify-data in constant-time. The length OTOH is no secret */
+        if( len    != 1 + ssl->verify_data_len ||
+            buf[0] !=     ssl->verify_data_len ||
+            safer_memcmp( buf + 1, ssl->peer_verify_data,
+                          ssl->verify_data_len ) != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) );
+
+            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+                return( ret );
+
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+    }
+    else
+#endif /* POLARSSL_SSL_RENEGOTIATION */
     {
         if( len != 1 || buf[0] != 0x0 )
         {
-            SSL_DEBUG_MSG( 1, ( "non-zero length renegotiated connection field" ) );
+            SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) );
 
             if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
                 return( ret );
@@ -445,22 +463,6 @@
 
         ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
     }
-    else
-    {
-        /* Check verify-data in constant-time. The length OTOH is no secret */
-        if( len    != 1 + ssl->verify_data_len ||
-            buf[0] !=     ssl->verify_data_len ||
-            safer_memcmp( buf + 1, ssl->peer_verify_data,
-                          ssl->verify_data_len ) != 0 )
-        {
-            SSL_DEBUG_MSG( 1, ( "non-matching renegotiated connection field" ) );
-
-            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
-                return( ret );
-
-            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
-        }
-    }
 
     return( 0 );
 }
@@ -701,11 +703,13 @@
     if( len == 0 )
         return( 0 );
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
     {
         SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) );
         return( 0 );
     }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
 
     /*
      * Failures are ok: just ignore the ticket and proceed.
@@ -941,6 +945,7 @@
 
     SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) );
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
     {
         SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) );
@@ -950,6 +955,7 @@
 
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
     }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
 
     buf = ssl->in_hdr;
 
@@ -1086,15 +1092,18 @@
         if( p[0] == 0 && p[1] == 0 && p[2] == SSL_EMPTY_RENEGOTIATION_INFO )
         {
             SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) );
+#if defined(POLARSSL_SSL_RENEGOTIATION)
             if( ssl->renegotiation == SSL_RENEGOTIATION )
             {
-                SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) );
+                SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV "
+                                    "during renegotiation" ) );
 
                 if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
                     return( ret );
 
                 return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
             }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
             ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
             break;
         }
@@ -1191,15 +1200,19 @@
     unsigned int comp_len;
     unsigned int ext_len = 0;
     unsigned char *buf, *p, *ext;
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     int renegotiation_info_seen = 0;
+#endif
     int handshake_failure = 0;
     const int *ciphersuites;
     const ssl_ciphersuite_t *ciphersuite_info;
 
     SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
 
-    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE &&
-        ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 )
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+#endif
+    if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 )
     {
         SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
         return( ret );
@@ -1249,18 +1262,22 @@
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
     }
 
-    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE &&
-        ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 )
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+#endif
+    if( ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 )
     {
         SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
         return( ret );
     }
 
     buf = ssl->in_msg;
-    if( !ssl->renegotiation )
-        n = ssl->in_left - 5;
-    else
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
         n = ssl->in_msglen;
+    else
+#endif
+        n = ssl->in_left - 5;
 
     ssl->handshake->update_checksum( ssl, buf, n );
 
@@ -1423,6 +1440,7 @@
         if( p[0] == 0 && p[1] == SSL_EMPTY_RENEGOTIATION_INFO )
         {
             SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) );
+#if defined(POLARSSL_SSL_RENEGOTIATION)
             if( ssl->renegotiation == SSL_RENEGOTIATION )
             {
                 SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) );
@@ -1432,6 +1450,8 @@
 
                 return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
             }
+            renegotiation_info_seen = 1;
+#endif /* POLARSSL_SSL_RENEGOTIATION */
             ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
             break;
         }
@@ -1490,7 +1510,9 @@
 
         case TLS_EXT_RENEGOTIATION_INFO:
             SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
+#if defined(POLARSSL_SSL_RENEGOTIATION)
             renegotiation_info_seen = 1;
+#endif
 
             ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size );
             if( ret != 0 )
@@ -1501,8 +1523,10 @@
     defined(POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED)
         case TLS_EXT_SIG_ALG:
             SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
+#if defined(POLARSSL_SSL_RENEGOTIATION)
             if( ssl->renegotiation == SSL_RENEGOTIATION )
                 break;
+#endif
 
             ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size );
             if( ret != 0 )
@@ -1608,12 +1632,13 @@
     /*
      * Renegotiation security checks
      */
-    if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+    if( ssl->secure_renegotiation != SSL_SECURE_RENEGOTIATION &&
         ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE )
     {
         SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
         handshake_failure = 1;
     }
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     else if( ssl->renegotiation == SSL_RENEGOTIATION &&
              ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION &&
              renegotiation_info_seen == 0 )
@@ -1635,6 +1660,7 @@
         SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) );
         handshake_failure = 1;
     }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
 
     if( handshake_failure == 1 )
     {
@@ -1831,16 +1857,29 @@
     *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO      ) & 0xFF );
 
-    *p++ = 0x00;
-    *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF;
-    *p++ = ssl->verify_data_len * 2 & 0xFF;
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
+    {
+        *p++ = 0x00;
+        *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF;
+        *p++ = ssl->verify_data_len * 2 & 0xFF;
 
-    memcpy( p, ssl->peer_verify_data, ssl->verify_data_len );
-    p += ssl->verify_data_len;
-    memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
-    p += ssl->verify_data_len;
+        memcpy( p, ssl->peer_verify_data, ssl->verify_data_len );
+        p += ssl->verify_data_len;
+        memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
+        p += ssl->verify_data_len;
 
-    *olen = 5 + ssl->verify_data_len * 2;
+        *olen = 5 + ssl->verify_data_len * 2;
+    }
+    else
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+    {
+        *p++ = 0x00;
+        *p++ = 0x01;
+        *p++ = 0x00;
+
+        *olen = 5;
+    }
 }
 
 #if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
@@ -1999,7 +2038,9 @@
      * If not, try looking up session ID in our cache.
      */
     if( ssl->handshake->resume == 0 &&
+#if defined(POLARSSL_SSL_RENEGOTIATION)
         ssl->renegotiation == SSL_INITIAL_HANDSHAKE &&
+#endif
         ssl->session_negotiate->length != 0 &&
         ssl->f_get_cache != NULL &&
         ssl->f_get_cache( ssl->p_get_cache, ssl->session_negotiate ) == 0 )
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 7eec364..91ce32d 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -2797,7 +2797,7 @@
      * On client, make sure the server cert doesn't change during renego to
      * avoid "triple handshake" attack: https://secure-resumption.com/
      */
-#if defined(POLARSSL_SSL_CLI_C)
+#if defined(POLARSSL_SSL_RENEGOTIATION) && defined(POLARSSL_SSL_CLI_C)
     if( ssl->endpoint == SSL_IS_CLIENT &&
         ssl->renegotiation == SSL_RENEGOTIATION )
     {
@@ -2817,7 +2817,7 @@
             return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
         }
     }
-#endif /* POLARSSL_SSL_CLI_C */
+#endif /* POLARSSL_SSL_RENEGOTIATION && POLARSSL_SSL_CLI_C */
 
     if( ssl->authmode != SSL_VERIFY_NONE )
     {
@@ -3260,11 +3260,13 @@
     polarssl_free( ssl->handshake );
     ssl->handshake = NULL;
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     if( ssl->renegotiation == SSL_RENEGOTIATION )
     {
         ssl->renegotiation =  SSL_RENEGOTIATION_DONE;
         ssl->renego_records_seen = 0;
     }
+#endif
 
     /*
      * Switch in our now active transform context
@@ -3329,8 +3331,10 @@
     // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63)
     hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12;
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     ssl->verify_data_len = hash_len;
     memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len );
+#endif
 
     ssl->out_msglen  = 4 + hash_len;
     ssl->out_msgtype = SSL_MSG_HANDSHAKE;
@@ -3454,8 +3458,10 @@
         return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );
     }
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     ssl->verify_data_len = hash_len;
     memcpy( ssl->peer_verify_data, buf, hash_len );
+#endif
 
     if( ssl->handshake->resume != 0 )
     {
@@ -3607,7 +3613,11 @@
 
     ssl_set_ciphersuites( ssl, ssl_list_ciphersuites() );
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     ssl->renego_max_records = SSL_RENEGO_MAX_RECORDS_DEFAULT;
+    memset( ssl->renego_period, 0xFF, 7 );
+    ssl->renego_period[7] = 0x00;
+#endif
 
 #if defined(POLARSSL_DHM_C)
     if( ( ret = mpi_read_string( &ssl->dhm_P, 16,
@@ -3681,12 +3691,16 @@
     int ret;
 
     ssl->state = SSL_HELLO_REQUEST;
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     ssl->renegotiation = SSL_INITIAL_HANDSHAKE;
-    ssl->secure_renegotiation = SSL_LEGACY_RENEGOTIATION;
+    ssl->renego_records_seen = 0;
 
     ssl->verify_data_len = 0;
-    memset( ssl->own_verify_data, 0, 36 );
-    memset( ssl->peer_verify_data, 0, 36 );
+    memset( ssl->own_verify_data, 0, SSL_VERIFY_DATA_MAX_LEN );
+    memset( ssl->peer_verify_data, 0, SSL_VERIFY_DATA_MAX_LEN );
+#endif
+    ssl->secure_renegotiation = SSL_LEGACY_RENEGOTIATION;
 
     ssl->in_offt = NULL;
 
@@ -3707,8 +3721,6 @@
     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 );
 
@@ -4251,21 +4263,29 @@
 }
 #endif /* POLARSSL_SSL_TRUNCATED_HMAC */
 
-void ssl_set_renegotiation( ssl_context *ssl, int renegotiation )
-{
-    ssl->disable_renegotiation = renegotiation;
-}
-
 void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy )
 {
     ssl->allow_legacy_renegotiation = allow_legacy;
 }
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+void ssl_set_renegotiation( ssl_context *ssl, int renegotiation )
+{
+    ssl->disable_renegotiation = renegotiation;
+}
+
 void ssl_set_renegotiation_enforced( ssl_context *ssl, int max_records )
 {
     ssl->renego_max_records = max_records;
 }
 
+void ssl_set_renegotiation_period( ssl_context *ssl,
+                                   const unsigned char period[8] )
+{
+    memcpy( ssl->renego_period, period, 8 );
+}
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
 #if defined(POLARSSL_SSL_SESSION_TICKETS)
 int ssl_set_session_tickets( ssl_context *ssl, int use_tickets )
 {
@@ -4400,6 +4420,7 @@
     return( ret );
 }
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
 #if defined(POLARSSL_SSL_SRV_C)
 /*
  * Write HelloRequest to request renegotiation on server
@@ -4513,6 +4534,30 @@
 }
 
 /*
+ * Check record counters and renegotiate if they're above the limit.
+ */
+static int ssl_check_ctr_renegotiate( ssl_context *ssl )
+{
+    if( ssl->state != SSL_HANDSHAKE_OVER ||
+        ssl->renegotiation == SSL_RENEGOTIATION_PENDING ||
+        ssl->disable_renegotiation == SSL_RENEGOTIATION_DISABLED )
+    {
+        return( 0 );
+    }
+
+    // TODO: adapt for DTLS
+    if( memcmp( ssl->in_ctr,  ssl->renego_period, 8 ) <= 0 &&
+        memcmp( ssl->out_ctr, ssl->renego_period, 8 ) <= 0 )
+    {
+        return( 0 );
+    }
+
+    SSL_DEBUG_MSG( 0, ( "record counter limit reached: renegotiate" ) );
+    return( ssl_renegotiate( ssl ) );
+}
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
+/*
  * Receive application data decrypted from the SSL layer
  */
 int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len )
@@ -4522,6 +4567,14 @@
 
     SSL_DEBUG_MSG( 2, ( "=> read" ) );
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
+        return( ret );
+    }
+#endif
+
     if( ssl->state != SSL_HANDSHAKE_OVER )
     {
         ret = ssl_handshake( ssl );
@@ -4566,6 +4619,7 @@
             }
         }
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
         if( ssl->in_msgtype == SSL_MSG_HANDSHAKE )
         {
             SSL_DEBUG_MSG( 1, ( "received handshake message" ) );
@@ -4648,6 +4702,7 @@
                 return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
             }
         }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
 
         /* Fatal and closure alerts handled by ssl_read_record() */
         if( ssl->in_msgtype == SSL_MSG_ALERT )
@@ -4694,6 +4749,14 @@
 
     SSL_DEBUG_MSG( 2, ( "=> write" ) );
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
+        return( ret );
+    }
+#endif
+
     if( ssl->state != SSL_HANDSHAKE_OVER )
     {
         if( ( ret = ssl_handshake( ssl ) ) != 0 )
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 3457828..2ad6158 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -83,7 +83,7 @@
 #define DFL_PSK_IDENTITY        "Client_identity"
 #define DFL_FORCE_CIPHER        0
 #define DFL_RENEGOTIATION       SSL_RENEGOTIATION_DISABLED
-#define DFL_ALLOW_LEGACY        SSL_LEGACY_NO_RENEGOTIATION
+#define DFL_ALLOW_LEGACY        -2
 #define DFL_RENEGOTIATE         0
 #define DFL_EXCHANGES           1
 #define DFL_MIN_VERSION         -1
@@ -311,6 +311,14 @@
 #define USAGE_ETM ""
 #endif
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+#define USAGE_RENEGO \
+    "    renegotiation=%%d    default: 0 (disabled)\n"      \
+    "    renegotiate=%%d      default: 0 (disabled)\n"
+#else
+#define USAGE_RENEGO ""
+#endif
+
 #define USAGE \
     "\n usage: ssl_client2 param=<>...\n"                   \
     "\n acceptable parameters:\n"                           \
@@ -330,9 +338,8 @@
     "\n"                                                    \
     USAGE_PSK                                               \
     "\n"                                                    \
-    "    renegotiation=%%d    default: 1 (enabled)\n"       \
-    "    allow_legacy=%%d     default: 0 (disabled)\n"      \
-    "    renegotiate=%%d      default: 0 (disabled)\n"      \
+    "    allow_legacy=%%d     default: (library default: no)\n"      \
+    USAGE_RENEGO                                            \
     "    exchanges=%%d        default: 1\n"                 \
     "    reconnect=%%d        default: 0 (disabled)\n"      \
     USAGE_TIME                                              \
@@ -514,9 +521,13 @@
         }
         else if( strcmp( p, "allow_legacy" ) == 0 )
         {
-            opt.allow_legacy = atoi( q );
-            if( opt.allow_legacy < 0 || opt.allow_legacy > 1 )
-                goto usage;
+            switch( atoi( q ) )
+            {
+                case -1: opt.allow_legacy = SSL_LEGACY_BREAK_HANDSHAKE; break;
+                case 0:  opt.allow_legacy = SSL_LEGACY_NO_RENEGOTIATION; break;
+                case 1:  opt.allow_legacy = SSL_LEGACY_ALLOW_RENEGOTIATION; break;
+                default: goto usage;
+            }
         }
         else if( strcmp( p, "renegotiate" ) == 0 )
         {
@@ -980,8 +991,11 @@
     if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER )
         ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );
 
+    if( opt.allow_legacy != DFL_ALLOW_LEGACY )
+        ssl_legacy_renegotiation( &ssl, opt.allow_legacy );
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     ssl_set_renegotiation( &ssl, opt.renegotiation );
-    ssl_legacy_renegotiation( &ssl, opt.allow_legacy );
+#endif
 
 #if defined(POLARSSL_X509_CRT_PARSE_C)
     if( strcmp( opt.ca_path, "none" ) != 0 &&
@@ -1113,6 +1127,7 @@
     }
 #endif /* POLARSSL_X509_CRT_PARSE_C */
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     if( opt.renegotiate )
     {
         /*
@@ -1132,6 +1147,7 @@
         }
         printf( " ok\n" );
     }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
 
     /*
      * 6. Write the GET request
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 9d4443f..b02b176 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -101,9 +101,10 @@
 #define DFL_FORCE_CIPHER        0
 #define DFL_VERSION_SUITES      NULL
 #define DFL_RENEGOTIATION       SSL_RENEGOTIATION_DISABLED
-#define DFL_ALLOW_LEGACY        SSL_LEGACY_NO_RENEGOTIATION
+#define DFL_ALLOW_LEGACY        -2
 #define DFL_RENEGOTIATE         0
 #define DFL_RENEGO_DELAY        -2
+#define DFL_RENEGO_PERIOD       -1
 #define DFL_EXCHANGES           1
 #define DFL_MIN_VERSION         -1
 #define DFL_MAX_VERSION         -1
@@ -166,6 +167,7 @@
     int allow_legacy;           /* allow legacy renegotiation               */
     int renegotiate;            /* attempt renegotiation?                   */
     int renego_delay;           /* delay before enforcing renegotiation     */
+    int renego_period;          /* period for automatic renegotiation       */
     int exchanges;              /* number of data exchanges                 */
     int min_version;            /* minimum protocol version accepted        */
     int max_version;            /* maximum protocol version accepted        */
@@ -317,6 +319,16 @@
 #define USAGE_ETM ""
 #endif
 
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+#define USAGE_RENEGO \
+    "    renegotiation=%%d    default: 0 (disabled)\n"      \
+    "    renegotiate=%%d      default: 0 (disabled)\n"      \
+    "    renego_delay=%%d     default: -2 (library default)\n" \
+    "    renego_period=%%d    default: (library default)\n"
+#else
+#define USAGE_RENEGO ""
+#endif
+
 #define USAGE \
     "\n usage: ssl_server2 param=<>...\n"                   \
     "\n acceptable parameters:\n"                           \
@@ -333,10 +345,8 @@
     "\n"                                                    \
     USAGE_PSK                                               \
     "\n"                                                    \
-    "    renegotiation=%%d    default: 1 (enabled)\n"       \
-    "    allow_legacy=%%d     default: 0 (disabled)\n"      \
-    "    renegotiate=%%d      default: 0 (disabled)\n"      \
-    "    renego_delay=%%d     default: -2 (library default)\n" \
+    "    allow_legacy=%%d     default: (library default: no)\n"      \
+    USAGE_RENEGO                                            \
     "    exchanges=%%d        default: 1\n"                 \
     USAGE_TICKETS                                           \
     USAGE_CACHE                                             \
@@ -621,6 +631,9 @@
     entropy_context entropy;
     ctr_drbg_context ctr_drbg;
     ssl_context ssl;
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    unsigned char renego_period[8] = { 0 };
+#endif
 #if defined(POLARSSL_X509_CRT_PARSE_C)
     x509_crt cacert;
     x509_crt srvcert;
@@ -722,6 +735,7 @@
     opt.allow_legacy        = DFL_ALLOW_LEGACY;
     opt.renegotiate         = DFL_RENEGOTIATE;
     opt.renego_delay        = DFL_RENEGO_DELAY;
+    opt.renego_period       = DFL_RENEGO_PERIOD;
     opt.exchanges           = DFL_EXCHANGES;
     opt.min_version         = DFL_MIN_VERSION;
     opt.max_version         = DFL_MAX_VERSION;
@@ -804,9 +818,13 @@
         }
         else if( strcmp( p, "allow_legacy" ) == 0 )
         {
-            opt.allow_legacy = atoi( q );
-            if( opt.allow_legacy < 0 || opt.allow_legacy > 1 )
-                goto usage;
+            switch( atoi( q ) )
+            {
+                case -1: opt.allow_legacy = SSL_LEGACY_BREAK_HANDSHAKE; break;
+                case 0:  opt.allow_legacy = SSL_LEGACY_NO_RENEGOTIATION; break;
+                case 1:  opt.allow_legacy = SSL_LEGACY_ALLOW_RENEGOTIATION; break;
+                default: goto usage;
+            }
         }
         else if( strcmp( p, "renegotiate" ) == 0 )
         {
@@ -818,6 +836,12 @@
         {
             opt.renego_delay = atoi( q );
         }
+        else if( strcmp( p, "renego_period" ) == 0 )
+        {
+            opt.renego_period = atoi( q );
+            if( opt.renego_period < 2 || opt.renego_period > 255 )
+                goto usage;
+        }
         else if( strcmp( p, "exchanges" ) == 0 )
         {
             opt.exchanges = atoi( q );
@@ -1361,11 +1385,21 @@
                                           SSL_MINOR_VERSION_3 );
     }
 
+    if( opt.allow_legacy != DFL_ALLOW_LEGACY )
+        ssl_legacy_renegotiation( &ssl, opt.allow_legacy );
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     ssl_set_renegotiation( &ssl, opt.renegotiation );
-    ssl_legacy_renegotiation( &ssl, opt.allow_legacy );
+
     if( opt.renego_delay != DFL_RENEGO_DELAY )
         ssl_set_renegotiation_enforced( &ssl, opt.renego_delay );
 
+    if( opt.renego_period != DFL_RENEGO_PERIOD )
+    {
+        renego_period[7] = opt.renego_period;
+        ssl_set_renegotiation_period( &ssl, renego_period );
+    }
+#endif
+
 #if defined(POLARSSL_X509_CRT_PARSE_C)
     if( strcmp( opt.ca_path, "none" ) != 0 &&
         strcmp( opt.ca_file, "none" ) != 0 )
@@ -1666,6 +1700,7 @@
      * 7a. Request renegotiation while client is waiting for input from us.
      * (only if we're going to exhange more data afterwards)
      */
+#if defined(POLARSSL_SSL_RENEGOTIATION)
     if( opt.renegotiate && exchanges > 1 )
     {
         printf( "  . Requestion renegotiation..." );
@@ -1683,6 +1718,7 @@
 
         printf( " ok\n" );
     }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
 
     /*
      * 7. Write the 200 Response
diff --git a/scripts/config.pl b/scripts/config.pl
index 8998fd6..c105a23 100755
--- a/scripts/config.pl
+++ b/scripts/config.pl
@@ -28,6 +28,7 @@
 POLARSSL_NO_DEFAULT_ENTROPY_SOURCES
 POLARSSL_NO_PLATFORM_ENTROPY
 POLARSSL_SSL_HW_RECORD_ACCEL
+POLARSSL_SSL_DISABLE_RENEGOTIATION
 POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3
 POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
 POLARSSL_ZLIB_SUPPORT
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index f1ff917..456dbab 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -20,7 +20,7 @@
 O_SRV="$OPENSSL_CMD s_server -www -cert data_files/server5.crt -key data_files/server5.key"
 O_CLI="echo 'GET / HTTP/1.0' | $OPENSSL_CMD s_client"
 G_SRV="$GNUTLS_SERV --x509certfile data_files/server5.crt --x509keyfile data_files/server5.key"
-G_CLI="$GNUTLS_CLI"
+G_CLI="echo 'GET / HTTP/1.0' | $GNUTLS_CLI --x509cafile data_files/test-ca_cat12.crt"
 
 TESTS=0
 FAILS=0
@@ -380,7 +380,7 @@
 O_SRV="$O_SRV -accept $PORT"
 O_CLI="$O_CLI -connect localhost:$PORT"
 G_SRV="$G_SRV -p $PORT"
-G_CLI="$G_CLI -p $PORT"
+G_CLI="$G_CLI -p $PORT localhost"
 
 # Also pick a unique name for intermediate files
 SRV_OUT="srv_out.$$"
@@ -1007,6 +1007,70 @@
             -S "SSL - An unexpected message was received from our peer" \
             -S "failed"
 
+run_test    "Renegotiation: periodic, just below period" \
+            "$P_SRV debug_level=3 exchanges=9 renegotiation=1 renego_period=3" \
+            "$P_CLI debug_level=3 exchanges=2 renegotiation=1" \
+            0 \
+            -C "client hello, adding renegotiation extension" \
+            -s "received TLS_EMPTY_RENEGOTIATION_INFO" \
+            -S "found renegotiation extension" \
+            -s "server hello, secure renegotiation extension" \
+            -c "found renegotiation extension" \
+            -S "record counter limit reached: renegotiate" \
+            -C "=> renegotiate" \
+            -S "=> renegotiate" \
+            -S "write hello request" \
+            -S "SSL - An unexpected message was received from our peer" \
+            -S "failed"
+
+run_test    "Renegotiation: periodic, just above period" \
+            "$P_SRV debug_level=3 exchanges=9 renegotiation=1 renego_period=3" \
+            "$P_CLI debug_level=3 exchanges=3 renegotiation=1" \
+            0 \
+            -c "client hello, adding renegotiation extension" \
+            -s "received TLS_EMPTY_RENEGOTIATION_INFO" \
+            -s "found renegotiation extension" \
+            -s "server hello, secure renegotiation extension" \
+            -c "found renegotiation extension" \
+            -s "record counter limit reached: renegotiate" \
+            -c "=> renegotiate" \
+            -s "=> renegotiate" \
+            -s "write hello request" \
+            -S "SSL - An unexpected message was received from our peer" \
+            -S "failed"
+
+run_test    "Renegotiation: periodic, two times period" \
+            "$P_SRV debug_level=3 exchanges=9 renegotiation=1 renego_period=3" \
+            "$P_CLI debug_level=3 exchanges=6 renegotiation=1" \
+            0 \
+            -c "client hello, adding renegotiation extension" \
+            -s "received TLS_EMPTY_RENEGOTIATION_INFO" \
+            -s "found renegotiation extension" \
+            -s "server hello, secure renegotiation extension" \
+            -c "found renegotiation extension" \
+            -s "record counter limit reached: renegotiate" \
+            -c "=> renegotiate" \
+            -s "=> renegotiate" \
+            -s "write hello request" \
+            -S "SSL - An unexpected message was received from our peer" \
+            -S "failed"
+
+run_test    "Renegotiation: periodic, above period, disabled" \
+            "$P_SRV debug_level=3 exchanges=9 renegotiation=0 renego_period=3" \
+            "$P_CLI debug_level=3 exchanges=4 renegotiation=1" \
+            0 \
+            -C "client hello, adding renegotiation extension" \
+            -s "received TLS_EMPTY_RENEGOTIATION_INFO" \
+            -S "found renegotiation extension" \
+            -s "server hello, secure renegotiation extension" \
+            -c "found renegotiation extension" \
+            -S "record counter limit reached: renegotiate" \
+            -C "=> renegotiate" \
+            -S "=> renegotiate" \
+            -S "write hello request" \
+            -S "SSL - An unexpected message was received from our peer" \
+            -S "failed"
+
 run_test    "Renegotiation: nbio, client-initiated" \
             "$P_SRV debug_level=3 nbio=2 exchanges=2 renegotiation=1" \
             "$P_CLI debug_level=3 nbio=2 exchanges=2 renegotiation=1 renegotiate=1" \
@@ -1040,21 +1104,103 @@
             -c "client hello, adding renegotiation extension" \
             -c "found renegotiation extension" \
             -c "=> renegotiate" \
-            -C "ssl_handshake returned" \
+            -C "ssl_hanshake() returned" \
             -C "error" \
             -c "HTTP/1.0 200 [Oo][Kk]"
 
-run_test    "Renegotiation: gnutls server, client-initiated" \
-            "$G_SRV" \
+run_test    "Renegotiation: gnutls server strict, client-initiated" \
+            "$G_SRV --priority=NORMAL:%SAFE_RENEGOTIATION" \
             "$P_CLI debug_level=3 exchanges=1 renegotiation=1 renegotiate=1" \
             0 \
             -c "client hello, adding renegotiation extension" \
             -c "found renegotiation extension" \
             -c "=> renegotiate" \
-            -C "ssl_handshake returned" \
+            -C "ssl_hanshake() returned" \
             -C "error" \
             -c "HTTP/1.0 200 [Oo][Kk]"
 
+run_test    "Renegotiation: gnutls server unsafe, client-initiated default" \
+            "$G_SRV --priority=NORMAL:%DISABLE_SAFE_RENEGOTIATION" \
+            "$P_CLI debug_level=3 exchanges=1 renegotiation=1 renegotiate=1" \
+            1 \
+            -c "client hello, adding renegotiation extension" \
+            -C "found renegotiation extension" \
+            -c "=> renegotiate" \
+            -c "ssl_handshake() returned" \
+            -c "error" \
+            -C "HTTP/1.0 200 [Oo][Kk]"
+
+run_test    "Renegotiation: gnutls server unsafe, client-inititated no legacy" \
+            "$G_SRV --priority=NORMAL:%DISABLE_SAFE_RENEGOTIATION" \
+            "$P_CLI debug_level=3 exchanges=1 renegotiation=1 renegotiate=1 \
+             allow_legacy=0" \
+            1 \
+            -c "client hello, adding renegotiation extension" \
+            -C "found renegotiation extension" \
+            -c "=> renegotiate" \
+            -c "ssl_handshake() returned" \
+            -c "error" \
+            -C "HTTP/1.0 200 [Oo][Kk]"
+
+run_test    "Renegotiation: gnutls server unsafe, client-inititated legacy" \
+            "$G_SRV --priority=NORMAL:%DISABLE_SAFE_RENEGOTIATION" \
+            "$P_CLI debug_level=3 exchanges=1 renegotiation=1 renegotiate=1 \
+             allow_legacy=1" \
+            0 \
+            -c "client hello, adding renegotiation extension" \
+            -C "found renegotiation extension" \
+            -c "=> renegotiate" \
+            -C "ssl_hanshake() returned" \
+            -C "error" \
+            -c "HTTP/1.0 200 [Oo][Kk]"
+
+# Test for the "secure renegotation" extension only (no actual renegotiation)
+
+run_test    "Renego ext: gnutls server strict, client default" \
+            "$G_SRV --priority=NORMAL:%SAFE_RENEGOTIATION" \
+            "$P_CLI debug_level=3" \
+            0 \
+            -c "found renegotiation extension" \
+            -C "error" \
+            -c "HTTP/1.0 200 [Oo][Kk]"
+
+run_test    "Renego ext: gnutls server unsafe, client default" \
+            "$G_SRV --priority=NORMAL:%DISABLE_SAFE_RENEGOTIATION" \
+            "$P_CLI debug_level=3" \
+            0 \
+            -C "found renegotiation extension" \
+            -C "error" \
+            -c "HTTP/1.0 200 [Oo][Kk]"
+
+run_test    "Renego ext: gnutls server unsafe, client break legacy" \
+            "$G_SRV --priority=NORMAL:%DISABLE_SAFE_RENEGOTIATION" \
+            "$P_CLI debug_level=3 allow_legacy=-1" \
+            1 \
+            -C "found renegotiation extension" \
+            -c "error" \
+            -C "HTTP/1.0 200 [Oo][Kk]"
+
+run_test    "Renego ext: gnutls client strict, server default" \
+            "$P_SRV debug_level=3" \
+            "$G_CLI --priority=NORMAL:%SAFE_RENEGOTIATION" \
+            0 \
+            -s "received TLS_EMPTY_RENEGOTIATION_INFO\|found renegotiation extension" \
+            -s "server hello, secure renegotiation extension"
+
+run_test    "Renego ext: gnutls client unsafe, server default" \
+            "$P_SRV debug_level=3" \
+            "$G_CLI --priority=NORMAL:%DISABLE_SAFE_RENEGOTIATION" \
+            0 \
+            -S "received TLS_EMPTY_RENEGOTIATION_INFO\|found renegotiation extension" \
+            -S "server hello, secure renegotiation extension"
+
+run_test    "Renego ext: gnutls client unsafe, server break legacy" \
+            "$P_SRV debug_level=3 allow_legacy=-1" \
+            "$G_CLI --priority=NORMAL:%DISABLE_SAFE_RENEGOTIATION" \
+            1 \
+            -S "received TLS_EMPTY_RENEGOTIATION_INFO\|found renegotiation extension" \
+            -S "server hello, secure renegotiation extension"
+
 # Tests for auth_mode
 
 run_test    "Authentication: server badcert, client required" \