Merge option to disable truncated hmac on the server-side
diff --git a/ChangeLog b/ChangeLog
index 32e20bd..9d1d7eb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -56,6 +56,8 @@
    * A specific error is now returned when there are ciphersuites in common
      but none of them is usable due to external factors such as no certificate
      with a suitable (extended)KeyUsage or curve or no PSK set.
+   * It is now possible to disable neogtiation of truncated HMAC server-side
+     at runtime with ssl_set_truncated_hmac().
 
 = PolarSSL 1.3.9 released 2014-10-20
 Security
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index 0c5d8b2..012e629 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -1523,15 +1523,15 @@
 
 #if defined(POLARSSL_SSL_TRUNCATED_HMAC)
 /**
- * \brief          Activate negotiation of truncated HMAC (Client only)
- *                 (Default: SSL_TRUNC_HMAC_ENABLED)
+ * \brief          Activate negotiation of truncated HMAC
+ *                 (Default: SSL_TRUNC_HMAC_DISABLED on client,
+ *                           SSL_TRUNC_HMAC_ENABLED on server.)
  *
  * \param ssl      SSL context
  * \param truncate Enable or disable (SSL_TRUNC_HMAC_ENABLED or
  *                                    SSL_TRUNC_HMAC_DISABLED)
  *
- * \return         O if successful,
- *                 POLARSSL_ERR_SSL_BAD_INPUT_DATA if used server-side
+ * \return         Always 0.
  */
 int ssl_set_truncated_hmac( ssl_context *ssl, int truncate );
 #endif /* POLARSSL_SSL_TRUNCATED_HMAC */
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 4420e22..1fa9e76 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -633,7 +633,8 @@
 
     ((void) buf);
 
-    ssl->session_negotiate->trunc_hmac = SSL_TRUNC_HMAC_ENABLED;
+    if( ssl->trunc_hmac == SSL_TRUNC_HMAC_ENABLED )
+        ssl->session_negotiate->trunc_hmac = SSL_TRUNC_HMAC_ENABLED;
 
     return( 0 );
 }
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 6b9df33..050939b 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -3833,6 +3833,11 @@
     if( endpoint == SSL_IS_CLIENT )
         ssl->session_tickets = SSL_SESSION_TICKETS_ENABLED;
 #endif
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+    if( endpoint == SSL_IS_SERVER )
+        ssl->trunc_hmac = SSL_TRUNC_HMAC_ENABLED;
+#endif
 }
 
 void ssl_set_authmode( ssl_context *ssl, int authmode )
@@ -4258,9 +4263,6 @@
 #if defined(POLARSSL_SSL_TRUNCATED_HMAC)
 int ssl_set_truncated_hmac( ssl_context *ssl, int truncate )
 {
-    if( ssl->endpoint != SSL_IS_CLIENT )
-        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
-
     ssl->trunc_hmac = truncate;
 
     return( 0 );
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 71f5efa..2e3364d 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -90,7 +90,7 @@
 #define DFL_MAX_VERSION         -1
 #define DFL_AUTH_MODE           SSL_VERIFY_REQUIRED
 #define DFL_MFL_CODE            SSL_MAX_FRAG_LEN_NONE
-#define DFL_TRUNC_HMAC          0
+#define DFL_TRUNC_HMAC          -1
 #define DFL_RECSPLIT            -1
 #define DFL_RECONNECT           0
 #define DFL_RECO_DELAY          0
@@ -264,7 +264,7 @@
 
 #if defined(POLARSSL_SSL_TRUNCATED_HMAC)
 #define USAGE_TRUNC_HMAC                                    \
-    "    trunc_hmac=%%d       default: 0 (disabled)\n"
+    "    trunc_hmac=%%d       default: library default\n"
 #else
 #define USAGE_TRUNC_HMAC ""
 #endif /* POLARSSL_SSL_TRUNCATED_HMAC */
@@ -678,9 +678,12 @@
         }
         else if( strcmp( p, "trunc_hmac" ) == 0 )
         {
-            opt.trunc_hmac = atoi( q );
-            if( opt.trunc_hmac < 0 || opt.trunc_hmac > 1 )
-                goto usage;
+            switch( atoi( q ) )
+            {
+                case 0: opt.trunc_hmac = SSL_TRUNC_HMAC_DISABLED; break;
+                case 1: opt.trunc_hmac = SSL_TRUNC_HMAC_ENABLED; break;
+                default: goto usage;
+            }
         }
         else if( strcmp( p, "recsplit" ) == 0 )
         {
@@ -962,12 +965,8 @@
 #endif
 
 #if defined(POLARSSL_SSL_TRUNCATED_HMAC)
-    if( opt.trunc_hmac != 0 )
-        if( ( ret = ssl_set_truncated_hmac( &ssl, SSL_TRUNC_HMAC_ENABLED ) ) != 0 )
-        {
-            printf( " failed\n  ! ssl_set_truncated_hmac returned %d\n\n", ret );
-            goto exit;
-        }
+    if( opt.trunc_hmac != DFL_TRUNC_HMAC )
+        ssl_set_truncated_hmac( &ssl, opt.trunc_hmac );
 #endif
 
 #if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 18513c9..bf99b19 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -110,6 +110,7 @@
 #define DFL_MAX_VERSION         -1
 #define DFL_AUTH_MODE           SSL_VERIFY_OPTIONAL
 #define DFL_MFL_CODE            SSL_MAX_FRAG_LEN_NONE
+#define DFL_TRUNC_HMAC          -1
 #define DFL_TICKETS             SSL_SESSION_TICKETS_ENABLED
 #define DFL_TICKET_TIMEOUT      -1
 #define DFL_CACHE_MAX           -1
@@ -173,6 +174,7 @@
     int max_version;            /* maximum protocol version accepted        */
     int auth_mode;              /* verify mode for connection               */
     unsigned char mfl_code;     /* code for maximum fragment length         */
+    int trunc_hmac;             /* accept truncated hmac?                   */
     int tickets;                /* enable / disable session tickets         */
     int ticket_timeout;         /* session ticket lifetime                  */
     int cache_max;              /* max number of session cache entries      */
@@ -297,6 +299,13 @@
 #define USAGE_MAX_FRAG_LEN ""
 #endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
 
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+#define USAGE_TRUNC_HMAC \
+    "    trunc_hmac=%%d       default: library default\n"
+#else
+#define USAGE_TRUNC_HMAC ""
+#endif
+
 #if defined(POLARSSL_SSL_ALPN)
 #define USAGE_ALPN \
     "    alpn=%%s             default: \"\" (disabled)\n"   \
@@ -351,6 +360,7 @@
     USAGE_TICKETS                                           \
     USAGE_CACHE                                             \
     USAGE_MAX_FRAG_LEN                                      \
+    USAGE_TRUNC_HMAC                                        \
     USAGE_ALPN                                              \
     USAGE_EMS                                               \
     USAGE_ETM                                               \
@@ -741,6 +751,7 @@
     opt.max_version         = DFL_MAX_VERSION;
     opt.auth_mode           = DFL_AUTH_MODE;
     opt.mfl_code            = DFL_MFL_CODE;
+    opt.trunc_hmac          = DFL_TRUNC_HMAC;
     opt.tickets             = DFL_TICKETS;
     opt.ticket_timeout      = DFL_TICKET_TIMEOUT;
     opt.cache_max           = DFL_CACHE_MAX;
@@ -927,6 +938,15 @@
         {
             opt.alpn_string = q;
         }
+        else if( strcmp( p, "trunc_hmac" ) == 0 )
+        {
+            switch( atoi( q ) )
+            {
+                case 0: opt.trunc_hmac = SSL_TRUNC_HMAC_DISABLED; break;
+                case 1: opt.trunc_hmac = SSL_TRUNC_HMAC_ENABLED; break;
+                default: goto usage;
+            }
+        }
         else if( strcmp( p, "extended_ms" ) == 0 )
         {
             switch( atoi( q ) )
@@ -1322,6 +1342,11 @@
     };
 #endif
 
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+    if( opt.trunc_hmac != DFL_TRUNC_HMAC )
+        ssl_set_truncated_hmac( &ssl, opt.trunc_hmac );
+#endif
+
 #if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
     if( opt.extended_ms != DFL_EXTENDED_MS )
         ssl_set_extended_master_secret( &ssl, opt.extended_ms );
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 42e4eee..2874c81 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -429,16 +429,43 @@
 
 # Tests for Truncated HMAC extension
 
-run_test    "Truncated HMAC: reference" \
+run_test    "Truncated HMAC: client default, server default" \
             "$P_SRV debug_level=4" \
-            "$P_CLI trunc_hmac=0 force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
+            "$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
             0 \
-            -s "dumping 'computed mac' (20 bytes)"
+            -s "dumping 'computed mac' (20 bytes)" \
+            -S "dumping 'computed mac' (10 bytes)"
 
-run_test    "Truncated HMAC: actual test" \
+run_test    "Truncated HMAC: client disabled, server default" \
             "$P_SRV debug_level=4" \
-            "$P_CLI trunc_hmac=1 force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
+            "$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA \
+             trunc_hmac=0" \
             0 \
+            -s "dumping 'computed mac' (20 bytes)" \
+            -S "dumping 'computed mac' (10 bytes)"
+
+run_test    "Truncated HMAC: client enabled, server default" \
+            "$P_SRV debug_level=4" \
+            "$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA \
+             trunc_hmac=1" \
+            0 \
+            -S "dumping 'computed mac' (20 bytes)" \
+            -s "dumping 'computed mac' (10 bytes)"
+
+run_test    "Truncated HMAC: client enabled, server disabled" \
+            "$P_SRV debug_level=4 trunc_hmac=0" \
+            "$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA \
+             trunc_hmac=1" \
+            0 \
+            -s "dumping 'computed mac' (20 bytes)" \
+            -S "dumping 'computed mac' (10 bytes)"
+
+run_test    "Truncated HMAC: client enabled, server enabled" \
+            "$P_SRV debug_level=4 trunc_hmac=1" \
+            "$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA \
+             trunc_hmac=1" \
+            0 \
+            -S "dumping 'computed mac' (20 bytes)" \
             -s "dumping 'computed mac' (10 bytes)"
 
 # Tests for Encrypt-then-MAC extension