-  Added permissive certificate parsing to x509parse_crt() and x509parse_crtfile(). With permissive parsing the parsing does not stop on encountering a parse-error

diff --git a/library/error.c b/library/error.c
index d5ad617..33fad85 100644
--- a/library/error.c
+++ b/library/error.c
@@ -297,8 +297,8 @@
             snprintf( buf, buflen, "X509 - Unsupported RSA key version" );
         if( use_ret == -(POLARSSL_ERR_X509_KEY_INVALID_FORMAT) )
             snprintf( buf, buflen, "X509 - Invalid RSA key tag or value" );
-        if( use_ret == -(POLARSSL_ERR_X509_POINT_ERROR) )
-            snprintf( buf, buflen, "X509 - Not used" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT) )
+            snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" );
         if( use_ret == -(POLARSSL_ERR_X509_VALUE_TO_LENGTH) )
             snprintf( buf, buflen, "X509 - Not used" );
 #endif /* POLARSSL_X509_PARSE_C */
diff --git a/library/pem.c b/library/pem.c
index 3e8f79e..33e74ab 100644
--- a/library/pem.c
+++ b/library/pem.c
@@ -345,6 +345,8 @@
 
     if( ctx->info )
         free( ctx->info );
+
+    memset( ctx, 0, sizeof( pem_context ) );
 }
 
 #endif
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index a865a75..26e7dfa 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1401,7 +1401,8 @@
             return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
         }
 
-        ret = x509parse_crt( ssl->peer_cert, ssl->in_msg + i, n );
+        ret = x509parse_crt( ssl->peer_cert, ssl->in_msg + i, n,
+                             X509_NON_PERMISSIVE );
         if( ret != 0 )
         {
             SSL_DEBUG_RET( 1, " x509parse_crt", ret );
diff --git a/library/x509parse.c b/library/x509parse.c
index e14a163..326c986 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -1006,20 +1006,13 @@
 }
 
 /*
- * Parse one or more certificates and add them to the chained list
+ * Parse and fill a single X.509 certificate in DER format
  */
-int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen )
+int x509parse_crt_der( x509_cert *crt, const unsigned char *buf, size_t buflen )
 {
     int ret;
     size_t len;
     unsigned char *p, *end;
-    x509_cert *crt;
-#if defined(POLARSSL_PEM_C)
-    pem_context pem;
-    size_t use_len;
-#endif
-
-    crt = chain;
 
     /*
      * Check for valid input
@@ -1027,69 +1020,6 @@
     if( crt == NULL || buf == NULL )
         return( 1 );
 
-    while( crt->version != 0 && crt->next != NULL )
-        crt = crt->next;
-
-    /*
-     * Add new certificate on the end of the chain if needed.
-     */
-    if ( crt->version != 0 && crt->next == NULL)
-    {
-        crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
-
-        if( crt->next == NULL )
-        {
-            x509_free( crt );
-            return( 1 );
-        }
-
-        crt = crt->next;
-        memset( crt, 0, sizeof( x509_cert ) );
-    }
-
-#if defined(POLARSSL_PEM_C)
-    pem_init( &pem );
-    ret = pem_read_buffer( &pem,
-                           "-----BEGIN CERTIFICATE-----",
-                           "-----END CERTIFICATE-----",
-                           buf, NULL, 0, &use_len );
-
-    if( ret == 0 )
-    {
-        /*
-         * Was PEM encoded
-         */
-        buflen -= use_len;
-        buf += use_len;
-
-        /*
-         * Steal PEM buffer
-         */
-        p = pem.buf;
-        pem.buf = NULL;
-        len = pem.buflen;
-        pem_free( &pem );
-    }
-    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
-    {
-        pem_free( &pem );
-        return( ret );
-    }
-    else
-    {
-        /*
-         * nope, copy the raw DER data
-         */
-        p = (unsigned char *) malloc( len = buflen );
-
-        if( p == NULL )
-            return( 1 );
-
-        memcpy( p, buf, buflen );
-
-        buflen = 0;
-    }
-#else
     p = (unsigned char *) malloc( len = buflen );
 
     if( p == NULL )
@@ -1098,7 +1028,6 @@
     memcpy( p, buf, buflen );
 
     buflen = 0;
-#endif
 
     crt->raw.p = p;
     crt->raw.len = len;
@@ -1324,23 +1253,154 @@
                 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
     }
 
-    if( buflen > 0 )
+    return( 0 );
+}
+
+/*
+ * Parse one or more PEM certificates from a buffer and add them to the chained list
+ */
+int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen,
+                   int permissive )
+{
+    int ret, success = 0, first_error = 0;
+    x509_cert *crt, *prev = NULL;
+    int buf_format = X509_FORMAT_DER;
+
+    crt = chain;
+
+    /*
+     * Check for valid input
+     */
+    if( crt == NULL || buf == NULL )
+        return( 1 );
+
+    while( crt->version != 0 && crt->next != NULL )
+    {
+        prev = crt;
+        crt = crt->next;
+    }
+
+    /*
+     * Add new certificate on the end of the chain if needed.
+     */
+    if ( crt->version != 0 && crt->next == NULL)
     {
         crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
 
         if( crt->next == NULL )
-        {
-            x509_free( crt );
             return( 1 );
-        }
 
+        prev = crt;
         crt = crt->next;
         memset( crt, 0, sizeof( x509_cert ) );
-
-        return( x509parse_crt( crt, buf, buflen ) );
     }
 
-    return( 0 );
+    /*
+     * Determine buffer content. Buffer contains either one DER certificate or
+     * one or more PEM certificates.
+     */
+#if defined(POLARSSL_PEM_C)
+    if( strstr( (char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
+        buf_format = X509_FORMAT_PEM;
+#endif
+
+    if( buf_format == X509_FORMAT_DER )
+        return x509parse_crt_der( crt, buf, buflen );
+    
+#if defined(POLARSSL_PEM_C)
+    if( buf_format == X509_FORMAT_PEM )
+    {
+        pem_context pem;
+
+        while( buflen > 0 )
+        {
+            size_t use_len;
+            pem_init( &pem );
+
+            ret = pem_read_buffer( &pem,
+                           "-----BEGIN CERTIFICATE-----",
+                           "-----END CERTIFICATE-----",
+                           buf, NULL, 0, &use_len );
+
+            if( ret == 0 )
+            {
+                /*
+                 * Was PEM encoded
+                 */
+                buflen -= use_len;
+                buf += use_len;
+            }
+            else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
+            {
+                pem_free( &pem );
+
+                if( first_error == 0 )
+                    first_error = ret;
+
+                continue;
+            }
+            else
+                break;
+
+            ret = x509parse_crt_der( crt, pem.buf, pem.buflen );
+
+            pem_free( &pem );
+
+            if( ret != 0 )
+            {
+                /*
+                 * quit parsing on a memory error or if in non-permissive parsing mode
+                 */
+                if( ret == 1 || permissive != 1 )
+                {
+                    if( prev )
+                        prev->next = NULL;
+
+                    if( crt != chain )
+                        free( crt );
+
+                    return( ret );
+                }
+
+                if( first_error == 0 )
+                    first_error = ret;
+
+                memset( crt, 0, sizeof( x509_cert ) );
+                continue;
+            }
+
+            success = 1;
+
+            /*
+             * Add new certificate to the list
+             */
+            crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
+
+            if( crt->next == NULL )
+                return( 1 );
+
+            prev = crt;
+            crt = crt->next;
+            memset( crt, 0, sizeof( x509_cert ) );
+        }
+    }
+#endif
+
+    if( crt->version == 0 )
+    {
+        if( prev )
+            prev->next = NULL;
+
+        if( crt != chain )
+            free( crt );
+    }
+
+    if( success )
+        return( 0 );
+    else if( first_error )
+        return( first_error );
+    else
+        return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT );
 }
 
 /*
@@ -1667,7 +1727,7 @@
 /*
  * Load one or more certificates and add them to the chained list
  */
-int x509parse_crtfile( x509_cert *chain, const char *path )
+int x509parse_crtfile( x509_cert *chain, const char *path, int permissive )
 {
     int ret;
     size_t n;
@@ -1676,7 +1736,7 @@
     if ( load_file( path, &buf, &n ) )
         return( 1 );
 
-    ret = x509parse_crt( chain, buf, n );
+    ret = x509parse_crt( chain, buf, n, permissive );
 
     memset( buf, 0, n + 1 );
     free( buf );
@@ -3099,7 +3159,7 @@
     memset( &clicert, 0, sizeof( x509_cert ) );
 
     ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
-                         strlen( test_cli_crt ) );
+                         strlen( test_cli_crt ), X509_NON_PERMISSIVE );
     if( ret != 0 )
     {
         if( verbose != 0 )
@@ -3111,7 +3171,7 @@
     memset( &cacert, 0, sizeof( x509_cert ) );
 
     ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
-                         strlen( test_ca_crt ) );
+                         strlen( test_ca_crt ), X509_NON_PERMISSIVE );
     if( ret != 0 )
     {
         if( verbose != 0 )