Merge branch 'mbedtls-1.3'

Conflicts:
	ChangeLog
diff --git a/ChangeLog b/ChangeLog
index f53530d..00a771e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,16 +1,27 @@
 mbed TLS ChangeLog (Sorted per branch, date)
 
-= mbed TLS 1.3.x
+= mbed TLS 1.3.x branch 2016-xx-xx
+
+Security
+   * Removed the MBEDTLS_SSL_AEAD_RANDOM_IV option, because it was not compliant
+     with RFC-5116 and could lead to session key recovery in very long TLS
+     sessions. "Nonce-Disrespecting Adversaries Practical Forgery Attacks on GCM in
+     TLS" - H. Bock, A. Zauner, S. Devlin, J. Somorovsky, P. Jovanovic.
+     https://eprint.iacr.org/2016/475.pdf
+   * Fixed potential stack corruption in mbedtls_x509write_crt_der() and
+     mbedtls_x509write_csr_der() when the signature is copied to the buffer
+     without checking whether there is enough space in the destination. The
+     issue cannot be triggered remotely. Found by Jethro Beekman.
 
 Bugfix
    * Fix an issue that caused valid certificates being rejected whenever an
      expired or not yet valid version of the trusted certificate was before the
      valid version in the trusted certificate list.
-   * Fix incorrect handling of block lengths in crypt_and_hash sample program,
-     when GCM is used. #441
+   * Fix incorrect handling of block lengths in crypt_and_hash.c sample program,
+     when GCM is used. Found by udf2457. #441
    * Fix for key exchanges based on ECDH-RSA or ECDH-ECDSA which weren't
      enabled unless others were also present. Found by David Fernandez. #428
-   * Fixed cert_app sample program for debug output and for use when no root
+   * Fixed cert_app.c sample program for debug output and for use when no root
      certificates are provided.
    * Fix conditional statement that would cause a 1 byte overread in
      mbedtls_asn1_get_int(). Found and fixed by Guido Vranken. #599
@@ -20,6 +31,15 @@
    * Fix documentation and implementation missmatch for function arguments of
      mbedtls_gcm_finish(). Found by cmiatpaar. #602
    * Guarantee that P>Q at RSA key generation. Found by inestlerode. #558
+   * Fix missing return code check after call to md_init_ctx() that could
+     result in usage of invalid md_ctx in rsa_rsaes_oaep_encrypt(),
+     rsa_rsaes_oaep_decrypt(), rsa_rsassa_pss_sign() and
+     rsa_rsassa_pss_verify_ext(). Fixed by Brian J. Murray. #502
+
+Changes
+   * Add compile time option for relaxed X.509 time verification to enable
+     accepting certificates with non-standard time format (that is without
+     seconds or with a time zone). Patch provided by James Yonan of OpenVPN.
 
 = mbed TLS 1.3.17 branch 2016-06-28
 
diff --git a/include/polarssl/config.h b/include/polarssl/config.h
index 8fdf36e..498fc5b 100644
--- a/include/polarssl/config.h
+++ b/include/polarssl/config.h
@@ -839,18 +839,6 @@
 #define POLARSSL_SELF_TEST
 
 /**
- * \def POLARSSL_SSL_AEAD_RANDOM_IV
- *
- * Generate a random IV rather than using the record sequence number as a
- * nonce for ciphersuites using and AEAD algorithm (GCM or CCM).
- *
- * Using the sequence number is generally recommended.
- *
- * Uncomment this macro to always use random IVs with AEAD ciphersuites.
- */
-//#define POLARSSL_SSL_AEAD_RANDOM_IV
-
-/**
  * \def POLARSSL_SSL_ALL_ALERT_MESSAGES
  *
  * Enable sending of alert messages in case of encountered errors as per RFC.
@@ -1177,6 +1165,17 @@
 //#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
 
 /**
+ * \def POLARSSL_X509_ALLOW_RELAXED_DATE
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering ASN.1 UTCTime or ASN.1 GeneralizedTime without seconds or
+ * with a time zone.
+ *
+ * Uncomment to prevent an error.
+ */
+//#define POLARSSL_X509_ALLOW_RELAXED_DATE
+
+/**
  * \def POLARSSL_X509_CHECK_KEY_USAGE
  *
  * Enable verification of the keyUsage extension (CA and leaf certificates).
diff --git a/library/rsa.c b/library/rsa.c
index bf77cb5..79726c1 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -547,7 +547,11 @@
     memcpy( p, input, ilen );
 
     md_init( &md_ctx );
-    md_init_ctx( &md_ctx, md_info );
+    if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
+    {
+        md_free( &md_ctx );
+        return( ret );
+    }
 
     // maskedDB: Apply dbMask to DB
     //
@@ -728,7 +732,11 @@
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
     md_init( &md_ctx );
-    md_init_ctx( &md_ctx, md_info );
+    if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
+    {
+        md_free( &md_ctx );
+        return( ret );
+    }
 
     /* Generate lHash */
     md( md_info, label, label_len, lhash );
@@ -974,7 +982,11 @@
     p += slen;
 
     md_init( &md_ctx );
-    md_init_ctx( &md_ctx, md_info );
+    if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
+    {
+        md_free( &md_ctx );
+        return( ret );
+    }
 
     // Generate H = Hash( M' )
     //
@@ -1247,7 +1259,11 @@
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
     md_init( &md_ctx );
-    md_init_ctx( &md_ctx, md_info );
+    if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
+    {
+        md_free( &md_ctx );
+        return( ret );
+    }
 
     mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx );
 
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index d9eb0a9..2eb24b2 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1217,17 +1217,6 @@
         /*
          * Generate IV
          */
-#if defined(POLARSSL_SSL_AEAD_RANDOM_IV)
-        ret = ssl->f_rng( ssl->p_rng,
-                ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
-                ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
-        if( ret != 0 )
-            return( ret );
-
-        memcpy( ssl->out_iv,
-                ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
-                ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
-#else
         if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 )
         {
             /* Reminder if we ever add an AEAD mode with a different size */
@@ -1238,7 +1227,6 @@
         memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
                              ssl->out_ctr, 8 );
         memcpy( ssl->out_iv, ssl->out_ctr, 8 );
-#endif
 
         SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv,
                 ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
diff --git a/library/version_features.c b/library/version_features.c
index d5f4468..08bdfe2 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -285,9 +285,6 @@
 #if defined(POLARSSL_SELF_TEST)
     "POLARSSL_SELF_TEST",
 #endif /* POLARSSL_SELF_TEST */
-#if defined(POLARSSL_SSL_AEAD_RANDOM_IV)
-    "POLARSSL_SSL_AEAD_RANDOM_IV",
-#endif /* POLARSSL_SSL_AEAD_RANDOM_IV */
 #if defined(POLARSSL_SSL_ALERT_MESSAGES)
     "POLARSSL_SSL_ALERT_MESSAGES",
 #endif /* POLARSSL_SSL_ALERT_MESSAGES */
@@ -366,6 +363,9 @@
 #if defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
     "POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION",
 #endif /* POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */
+#if defined(POLARSSL_X509_ALLOW_RELAXED_DATE)
+    "POLARSSL_X509_ALLOW_RELAXED_DATE",
+#endif /* POLARSSL_X509_ALLOW_RELAXED_DATE */
 #if defined(POLARSSL_X509_CHECK_KEY_USAGE)
     "POLARSSL_X509_CHECK_KEY_USAGE",
 #endif /* POLARSSL_X509_CHECK_KEY_USAGE */
diff --git a/library/x509.c b/library/x509.c
index ab105d8..0d54beb 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -490,6 +490,88 @@
 }
 
 /*
+ * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) field.
+ */
+static int x509_parse_time( unsigned char **p, size_t len, unsigned int yearlen, x509_time *time )
+{
+    int ret;
+
+    /*
+     * minimum length is 10 or 12 depending on yearlen
+     */
+    if ( len < yearlen + 8 )
+        return POLARSSL_ERR_X509_INVALID_DATE;
+    len -= yearlen + 8;
+
+    /*
+     * parse year, month, day, hour, minute
+     */
+    CHECK( x509_parse_int( p, yearlen, &time->year ) );
+    if ( 2 == yearlen )
+    {
+        if ( time->year < 50 )
+            time->year += 100;
+
+        time->year += 1900;
+    }
+
+    CHECK( x509_parse_int( p, 2, &time->mon ) );
+    CHECK( x509_parse_int( p, 2, &time->day ) );
+    CHECK( x509_parse_int( p, 2, &time->hour ) );
+    CHECK( x509_parse_int( p, 2, &time->min ) );
+
+    /*
+     * parse seconds if present 
+     */
+    if ( len >= 2 && **p >= '0' && **p <= '9' )
+    {
+        CHECK( x509_parse_int( p, 2, &time->sec ) );
+        len -= 2;
+    }
+    else
+    {
+#if defined(POLARSSL_X509_ALLOW_RELAXED_DATE)
+        /*
+         * if relaxed mode, allow seconds to be absent
+         */
+        time->sec = 0;
+#else
+        return POLARSSL_ERR_X509_INVALID_DATE;
+#endif
+    }
+
+    /*
+     * parse trailing 'Z' if present
+     */
+    if ( 1 == len && 'Z' == **p )
+    {
+        (*p)++;
+        return 0;
+    }
+#if defined(POLARSSL_X509_ALLOW_RELAXED_DATE)
+    /*
+     * if relaxed mode, allow timezone to be present
+     */
+    else if ( 5 == len && ( '+' == **p || '-' == **p ) )
+    {
+        int tz; /* throwaway timezone */
+
+        (*p)++;
+        CHECK( x509_parse_int( p, 4, &tz ) );
+
+        return 0;
+    }
+#endif
+    /*
+     * okay if no trailing 'Z' or timezone specified
+     */
+    else if ( 0 == len )
+        return 0;
+    else
+        return POLARSSL_ERR_X509_INVALID_DATE;
+}
+
+/*
  *  Time ::= CHOICE {
  *       utcTime        UTCTime,
  *       generalTime    GeneralizedTime }
@@ -515,20 +597,7 @@
         if( ret != 0 )
             return( POLARSSL_ERR_X509_INVALID_DATE + ret );
 
-        CHECK( x509_parse_int( p, 2, &time->year ) );
-        CHECK( x509_parse_int( p, 2, &time->mon ) );
-        CHECK( x509_parse_int( p, 2, &time->day ) );
-        CHECK( x509_parse_int( p, 2, &time->hour ) );
-        CHECK( x509_parse_int( p, 2, &time->min ) );
-        if( len > 10 )
-            CHECK( x509_parse_int( p, 2, &time->sec ) );
-        if( len > 12 && *(*p)++ != 'Z' )
-            return( POLARSSL_ERR_X509_INVALID_DATE );
-
-        time->year +=  100 * ( time->year < 50 );
-        time->year += 1900;
-
-        return( 0 );
+        return x509_parse_time( p, len, 2, time );
     }
     else if( tag == ASN1_GENERALIZED_TIME )
     {
@@ -538,17 +607,7 @@
         if( ret != 0 )
             return( POLARSSL_ERR_X509_INVALID_DATE + ret );
 
-        CHECK( x509_parse_int( p, 4, &time->year ) );
-        CHECK( x509_parse_int( p, 2, &time->mon ) );
-        CHECK( x509_parse_int( p, 2, &time->day ) );
-        CHECK( x509_parse_int( p, 2, &time->hour ) );
-        CHECK( x509_parse_int( p, 2, &time->min ) );
-        if( len > 12 )
-            CHECK( x509_parse_int( p, 2, &time->sec ) );
-        if( len > 14 && *(*p)++ != 'Z' )
-            return( POLARSSL_ERR_X509_INVALID_DATE );
-
-        return( 0 );
+        return x509_parse_time( p, len, 4, time );
     }
     else
         return( POLARSSL_ERR_X509_INVALID_DATE +
diff --git a/library/x509write_crt.c b/library/x509write_crt.c
index 80913ec..23d46ee 100644
--- a/library/x509write_crt.c
+++ b/library/x509write_crt.c
@@ -408,6 +408,9 @@
     ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
                                         sig_oid, sig_oid_len, sig, sig_len ) );
 
+    if( len > (size_t)( c2 - buf ) )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
     c2 -= len;
     memcpy( c2, c, len );
 
diff --git a/library/x509write_csr.c b/library/x509write_csr.c
index c5a5875..1b3d2f5 100644
--- a/library/x509write_csr.c
+++ b/library/x509write_csr.c
@@ -214,6 +214,9 @@
     ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
                                         sig_oid, sig_oid_len, sig, sig_len ) );
 
+    if( len > (size_t)( c2 - buf ) )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
     c2 -= len;
     memcpy( c2, c, len );
 
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index d0a2106..a018f64 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -204,8 +204,10 @@
 # Usage: run_test name srv_cmd cli_cmd cli_exit [option [...]]
 # Options:  -s pattern  pattern that must be present in server output
 #           -c pattern  pattern that must be present in client output
+#           -u pattern  lines after pattern must be unique in client output
 #           -S pattern  pattern that must be absent in server output
 #           -C pattern  pattern that must be absent in client output
+#           -U pattern  lines after pattern must be unique in server output
 run_test() {
     NAME="$1"
     SRV_CMD="$2"
@@ -291,29 +293,50 @@
     do
         case $1 in
             "-s")
-                if grep -v '^==' $SRV_OUT | grep "$2" >/dev/null; then :; else
-                    fail "-s $2"
+                if grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then :; else
+                    fail "pattern '$2' MUST be present in the Server output"
                     return
                 fi
                 ;;
 
             "-c")
-                if grep -v '^==' $CLI_OUT | grep "$2" >/dev/null; then :; else
-                    fail "-c $2"
+                if grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then :; else
+                    fail "pattern '$2' MUST be present in the Client output"
                     return
                 fi
                 ;;
 
             "-S")
-                if grep -v '^==' $SRV_OUT | grep "$2" >/dev/null; then
-                    fail "-S $2"
+                if grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then
+                    fail "pattern '$2' MUST NOT be present in the Server output"
                     return
                 fi
                 ;;
 
             "-C")
-                if grep -v '^==' $CLI_OUT | grep "$2" >/dev/null; then
-                    fail "-C $2"
+                if grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then
+                    fail "pattern '$2' MUST NOT be present in the Client output"
+                    return
+                fi
+                ;;
+
+                # The filtering in the following two options (-u and -U) do the following
+                #   - ignore valgrind output
+                #   - filter out everything but lines right after the pattern occurances
+                #   - keep one of each non-unique line
+                #   - count how many lines remain
+                # A line with '--' will remain in the result from previous outputs, so the number of lines in the result will be 1
+                # if there were no duplicates.
+            "-U")
+                if [ $(grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep -A1 "$2" | grep -v "$2" | sort | uniq -d | wc -l) -gt 1 ]; then
+                    fail "lines following pattern '$2' must be unique in Server output"
+                    return
+                fi
+                ;;
+
+            "-u")
+                if [ $(grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep -A1 "$2" | grep -v "$2" | sort | uniq -d | wc -l) -gt 1 ]; then
+                    fail "lines following pattern '$2' must be unique in Client output"
                     return
                 fi
                 ;;
@@ -424,6 +447,14 @@
             -S "error" \
             -C "error"
 
+# Test for uniqueness of IVs in AEAD ciphersuites
+run_test    "Unique IV in GCM" \
+            "$P_SRV exchanges=20 debug_level=4" \
+            "$P_CLI exchanges=20 debug_level=4 force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384" \
+            0 \
+            -u "IV used" \
+            -U "IV used"
+
 # Tests for rc4 option
 
 run_test    "RC4: server disabled, client enabled" \
diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function
index 63f35a6..825a593 100644
--- a/tests/suites/test_suite_x509write.function
+++ b/tests/suites/test_suite_x509write.function
@@ -16,10 +16,11 @@
 {
     pk_context key;
     x509write_csr req;
-    unsigned char buf[4000];
+    unsigned char buf[4096];
     unsigned char check_buf[4000];
     int ret;
     size_t olen = 0, pem_len = 0;
+    int der_len = -1;
     FILE *f;
     const char *subject_name = "C=NL,O=PolarSSL,CN=PolarSSL Server 1";
     rnd_pseudo_info rnd_info;
@@ -52,6 +53,17 @@
     TEST_ASSERT( olen >= pem_len - 1 );
     TEST_ASSERT( memcmp( buf, check_buf, pem_len - 1 ) == 0 );
 
+    der_len = x509write_csr_der( &req, buf, sizeof( buf ),
+                                 rnd_pseudo_rand, &rnd_info );
+    TEST_ASSERT( der_len >= 0 );
+
+    if( der_len == 0 )
+        goto exit;
+
+    ret = x509write_csr_der( &req, buf, (size_t)( der_len - 1 ),
+                             rnd_pseudo_rand, &rnd_info );
+    TEST_ASSERT( ret == POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
 exit:
     x509write_csr_free( &req );
     pk_free( &key );
@@ -68,11 +80,12 @@
 {
     pk_context subject_key, issuer_key;
     x509write_cert crt;
-    unsigned char buf[4000];
+    unsigned char buf[4096];
     unsigned char check_buf[5000];
     mpi serial;
     int ret;
     size_t olen = 0, pem_len = 0;
+    int der_len = -1;
     FILE *f;
     rnd_pseudo_info rnd_info;
 
@@ -125,6 +138,17 @@
     TEST_ASSERT( olen >= pem_len - 1 );
     TEST_ASSERT( memcmp( buf, check_buf, pem_len - 1 ) == 0 );
 
+    der_len = x509write_crt_der( &crt, buf, sizeof( buf ),
+                                 rnd_pseudo_rand, &rnd_info );
+    TEST_ASSERT( der_len >= 0 );
+
+    if( der_len == 0 )
+        goto exit;
+
+    ret = x509write_crt_der( &crt, buf, (size_t)( der_len - 1 ),
+                             rnd_pseudo_rand, &rnd_info );
+    TEST_ASSERT( ret == POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
 exit:
     x509write_crt_free( &crt );
     pk_free( &issuer_key );