Merge branch 'mbedtls-1.3' into mbedtls-1.3
diff --git a/ChangeLog b/ChangeLog
index 6e171f1..cbbb1ac 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -27,6 +27,8 @@
      don't use the optimized assembly for bignum multiplication. This removes
      the need to pass -fomit-frame-pointer to avoid a build error with -O0.
    * Disabled SSLv3 in the default configuration.
+   * Fix non-compliance server extension handling. Extensions for SSLv3 are now
+     ignored, as required by RFC6101.
 
 = mbed TLS 1.3.16 released 2016-01-05
 
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 473f87d..0fd6709 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -1564,154 +1564,164 @@
     }
 #endif /* POLARSSL_SSL_FALLBACK_SCSV */
 
-    ext = buf + 44 + sess_len + ciph_len + comp_len;
-
-    while( ext_len )
+    /* Do not parse the extensions if the protocol is SSLv3 */
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+    if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) )
     {
-        unsigned int ext_id   = ( ( ext[0] <<  8 )
-                                | ( ext[1]       ) );
-        unsigned int ext_size = ( ( ext[2] <<  8 )
-                                | ( ext[3]       ) );
-
-        if( ext_size + 4 > ext_len )
-        {
-            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
-        }
-        switch( ext_id )
-        {
-#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
-        case TLS_EXT_SERVERNAME:
-            SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) );
-            if( ssl->f_sni == NULL )
-                break;
-
-            ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size );
-            if( ret != 0 )
-                return( ret );
-            break;
-#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
-
-        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 )
-                return( ret );
-            break;
+        ext = buf + 44 + sess_len + ciph_len + comp_len;
 
-#if defined(POLARSSL_SSL_PROTO_TLS1_2) && \
-    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 )
-                return( ret );
-            break;
-#endif /* POLARSSL_SSL_PROTO_TLS1_2 &&
-          POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED */
-
-#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
-        case TLS_EXT_SUPPORTED_ELLIPTIC_CURVES:
-            SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) );
-
-            ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size );
-            if( ret != 0 )
-                return( ret );
-            break;
-
-        case TLS_EXT_SUPPORTED_POINT_FORMATS:
-            SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) );
-            ssl->handshake->cli_exts |= TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT;
-
-            ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size );
-            if( ret != 0 )
-                return( ret );
-            break;
-#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
-
-#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
-        case TLS_EXT_MAX_FRAGMENT_LENGTH:
-            SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) );
-
-            ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size );
-            if( ret != 0 )
-                return( ret );
-            break;
-#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
-
-#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
-        case TLS_EXT_TRUNCATED_HMAC:
-            SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) );
-
-            ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size );
-            if( ret != 0 )
-                return( ret );
-            break;
-#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
-
-#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
-        case TLS_EXT_ENCRYPT_THEN_MAC:
-            SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) );
-
-            ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size );
-            if( ret != 0 )
-                return( ret );
-            break;
-#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
-
-#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
-        case TLS_EXT_EXTENDED_MASTER_SECRET:
-            SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) );
-
-            ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size );
-            if( ret != 0 )
-                return( ret );
-            break;
-#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */
-
-#if defined(POLARSSL_SSL_SESSION_TICKETS)
-        case TLS_EXT_SESSION_TICKET:
-            SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) );
-
-            ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size );
-            if( ret != 0 )
-                return( ret );
-            break;
-#endif /* POLARSSL_SSL_SESSION_TICKETS */
-
-#if defined(POLARSSL_SSL_ALPN)
-        case TLS_EXT_ALPN:
-            SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
-
-            ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size );
-            if( ret != 0 )
-                return( ret );
-            break;
-#endif /* POLARSSL_SSL_SESSION_TICKETS */
-
-        default:
-            SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
-                           ext_id ) );
-        }
-
-        ext_len -= 4 + ext_size;
-        ext += 4 + ext_size;
-
-        if( ext_len > 0 && ext_len < 4 )
+        while( ext_len )
         {
-            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+            unsigned int ext_id   = ( ( ext[0] <<  8 )
+                                    | ( ext[1]       ) );
+            unsigned int ext_size = ( ( ext[2] <<  8 )
+                                    | ( ext[3]       ) );
+
+            if( ext_size + 4 > ext_len )
+            {
+                SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+                return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+            }
+            switch( ext_id )
+            {
+    #if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+            case TLS_EXT_SERVERNAME:
+                SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) );
+                if( ssl->f_sni == NULL )
+                    break;
+
+                ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size );
+                if( ret != 0 )
+                    return( ret );
+                break;
+    #endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
+
+            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 )
+                    return( ret );
+                break;
+
+    #if defined(POLARSSL_SSL_PROTO_TLS1_2) && \
+        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 )
+                    return( ret );
+                break;
+    #endif /* POLARSSL_SSL_PROTO_TLS1_2 &&
+              POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED */
+
+    #if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+            case TLS_EXT_SUPPORTED_ELLIPTIC_CURVES:
+                SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) );
+
+                ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size );
+                if( ret != 0 )
+                    return( ret );
+                break;
+
+            case TLS_EXT_SUPPORTED_POINT_FORMATS:
+                SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) );
+                ssl->handshake->cli_exts |= TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT;
+
+                ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size );
+                if( ret != 0 )
+                    return( ret );
+                break;
+    #endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
+
+    #if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+            case TLS_EXT_MAX_FRAGMENT_LENGTH:
+                SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) );
+
+                ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size );
+                if( ret != 0 )
+                    return( ret );
+                break;
+    #endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+
+    #if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+            case TLS_EXT_TRUNCATED_HMAC:
+                SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) );
+
+                ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size );
+                if( ret != 0 )
+                    return( ret );
+                break;
+    #endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+
+    #if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
+            case TLS_EXT_ENCRYPT_THEN_MAC:
+                SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) );
+
+                ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size );
+                if( ret != 0 )
+                    return( ret );
+                break;
+    #endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
+
+    #if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+            case TLS_EXT_EXTENDED_MASTER_SECRET:
+                SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) );
+
+                ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size );
+                if( ret != 0 )
+                    return( ret );
+                break;
+    #endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */
+
+    #if defined(POLARSSL_SSL_SESSION_TICKETS)
+            case TLS_EXT_SESSION_TICKET:
+                SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) );
+
+                ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size );
+                if( ret != 0 )
+                    return( ret );
+                break;
+    #endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+    #if defined(POLARSSL_SSL_ALPN)
+            case TLS_EXT_ALPN:
+                SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
+
+                ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size );
+                if( ret != 0 )
+                    return( ret );
+                break;
+    #endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+            default:
+                SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
+                               ext_id ) );
+            }
+
+            ext_len -= 4 + ext_size;
+            ext += 4 + ext_size;
+
+            if( ext_len > 0 && ext_len < 4 )
+            {
+                SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+                return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+            }
         }
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
     }
+#endif
 
     /*
      * Renegotiation security checks
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index ae82f7b..602da2c 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -234,7 +234,8 @@
 scripts/config.pl unset POLARSSL_THREADING_C
 scripts/config.pl unset POLARSSL_MEMORY_BACKTRACE # execinfo.h
 scripts/config.pl unset POLARSSL_MEMORY_BUFFER_ALLOC_C # calls exit
-CC=armcc AR=armar WARNING_CFLAGS= make lib 2> armcc.stderr
+CC=armcc AR=armar WARNING_CFLAGS=
+make lib 2> armcc.stderr
 if [ -s armcc.stderr ]; then
     cat armcc.stderr
     exit 1;
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index dcf9bb1..d0a2106 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -587,7 +587,7 @@
             "$P_CLI debug_level=3 min_version=ssl3" \
             0 \
             -c "client hello, adding encrypt_then_mac extension" \
-            -s "found encrypt then mac extension" \
+            -S "found encrypt then mac extension" \
             -S "server hello, adding encrypt then mac extension" \
             -C "found encrypt_then_mac extension" \
             -C "using encrypt then mac" \
@@ -646,7 +646,7 @@
             "$P_CLI debug_level=3 min_version=ssl3" \
             0 \
             -c "client hello, adding extended_master_secret extension" \
-            -s "found extended master secret extension" \
+            -S "found extended master secret extension" \
             -S "server hello, adding extended master secret extension" \
             -C "found extended_master_secret extension" \
             -C "using extended master secret" \
@@ -2354,6 +2354,16 @@
             0 \
             -s "Read from client: 1 bytes read"
 
+# A test for extensions in SSLv3
+
+requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
+run_test    "SSLv3 with extensions, server side" \
+            "$P_SRV min_version=ssl3 debug_level=3" \
+            "$P_CLI force_version=ssl3 tickets=1 max_frag_len=4096 alpn=abc,1234" \
+            0 \
+            -S "dumping 'client hello extensions'" \
+            -S "server hello, total extension length:"
+
 # Test for large packets
 
 requires_config_enabled POLARSSL_SSL_PROTO_SSL3