Safer buffer comparisons in the SSL modules
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index 6383c0e..0900a2c 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -1136,6 +1136,20 @@
 void ssl_optimize_checksum( ssl_context *ssl, int ciphersuite );
 int ssl_get_ciphersuite_min_version( const int ciphersuite_id );
 
+/* constant-time buffer comparison */
+static inline int safer_memcmp( const void *a, const void *b, size_t n )
+{
+    size_t i;
+    const unsigned char *A = (const unsigned char *) a;
+    const unsigned char *B = (const unsigned char *) b;
+    unsigned char diff = 0;
+
+    for( i = 0; i < n; i++ )
+        diff |= A[i] ^ B[i];
+
+    return( diff );
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 4ebee35..fc82002 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -341,11 +341,13 @@
     }
     else
     {
+        /* Check verify-data in constant-time. The length OTOH is no secret */
         if( len    != 1 + ssl->verify_data_len * 2 ||
             buf[0] !=     ssl->verify_data_len * 2 ||
-            memcmp( buf + 1, ssl->own_verify_data,  ssl->verify_data_len ) != 0 ||
-            memcmp( buf + 1 + ssl->verify_data_len,
-                    ssl->peer_verify_data, ssl->verify_data_len ) != 0 )
+            safer_memcmp( buf + 1,
+                          ssl->own_verify_data, ssl->verify_data_len ) != 0 ||
+            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" ) );
 
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index d166986..ea1d63e 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -106,9 +106,11 @@
     }
     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 ||
-            memcmp( buf + 1, ssl->peer_verify_data, ssl->verify_data_len ) != 0 )
+            safer_memcmp( buf + 1, ssl->peer_verify_data,
+                          ssl->verify_data_len ) != 0 )
         {
             SSL_DEBUG_MSG( 1, ( "non-matching renegotiated connection field" ) );
 
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 15cb3bc..a8cc501 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1547,8 +1547,8 @@
     SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen,
                    ssl->transform_in->maclen );
 
-    if( memcmp( tmp, ssl->in_msg + ssl->in_msglen,
-                     ssl->transform_in->maclen ) != 0 )
+    if( safer_memcmp( tmp, ssl->in_msg + ssl->in_msglen,
+                      ssl->transform_in->maclen ) != 0 )
     {
 #if defined(POLARSSL_SSL_DEBUG_ALL)
         SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
@@ -2886,7 +2886,7 @@
         return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );
     }
 
-    if( memcmp( ssl->in_msg + 4, buf, hash_len ) != 0 )
+    if( safer_memcmp( ssl->in_msg + 4, buf, hash_len ) != 0 )
     {
         SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
         return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );