Countermeasure against "triple handshake" attack
diff --git a/ChangeLog b/ChangeLog
index df0ef77..f131280 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -14,6 +14,11 @@
    * entropy_add_source(), entropy_update_manual() and entropy_gather()
      now thread-safe if POLARSSL_THREADING_C defined
 
+Security
+   * Forbid change of server certificate during renegotiation to prevent
+     "triple handshake" attack when authentication mode is optional (the
+     attack was already impossible when authentication is required).
+
 Bugfix
    * ecp_gen_keypair() does more tries to prevent failure because of
      statistics
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 4a9211f..4f3095c 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -2650,6 +2650,30 @@
 
     SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert );
 
+    /*
+     * On client, make sure the server cert doesn't change during renego to
+     * avoid "triple handshake" attack: https://secure-resumption.com/
+     */
+    if( ssl->endpoint == SSL_IS_CLIENT &&
+        ssl->renegotiation == SSL_RENEGOTIATION )
+    {
+        if( ssl->session->peer_cert == NULL )
+        {
+            SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+        }
+
+        if( ssl->session->peer_cert->raw.len !=
+            ssl->session_negotiate->peer_cert->raw.len ||
+            memcmp( ssl->session->peer_cert->raw.p,
+                    ssl->session_negotiate->peer_cert->raw.p,
+                    ssl->session->peer_cert->raw.len ) != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+        }
+    }
+
     if( ssl->authmode != SSL_VERIFY_NONE )
     {
         if( ssl->ca_chain == NULL )