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 )