Pass "certificate policies" extension to callback

Pass the "certificate policies" extension to the callback supplied to
mbedtls_x509_crt_parse_der_with_ext_cb() if it contains unsupported
policies. This allows the callback to fully replicate the behaviour
of the deprecated MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
configuration.

Signed-off-by: Nicola Di Lieto <nicola.dilieto@gmail.com>
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index 54e5156..a72532f 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -303,17 +303,91 @@
 }
 
 int parse_crt_ext_cb( void *p_ctx, mbedtls_x509_crt const *crt, mbedtls_x509_buf const *oid,
-                      int critical, const unsigned char *p, const unsigned char *end )
+                      int critical, const unsigned char *cp, const unsigned char *end )
 {
     ( void ) crt;
-    ( void ) p;
+    ( void ) cp;
     ( void ) end;
     ( void ) critical;
     mbedtls_x509_buf *new_oid = (mbedtls_x509_buf *)p_ctx;
-    if( new_oid == NULL || new_oid->tag != oid->tag || new_oid->len != oid->len ||
-        memcmp(new_oid->p, oid->p, oid->len) != 0 )
+    if( oid->tag == MBEDTLS_ASN1_OID &&
+        MBEDTLS_OID_CMP( MBEDTLS_OID_CERTIFICATE_POLICIES, oid ) == 0 )
+    {
+        /* Handle unknown certificate policy */
+        int ret, parse_ret = 0;
+        size_t len;
+        unsigned char **p = (unsigned char **)&cp;
+
+        /* Get main sequence tag */
+        ret = mbedtls_asn1_get_tag( p, end, &len,
+                                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
+        if( ret != 0 )
+            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        if( *p + len != end )
+            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+        /*
+         * Cannot be an empty sequence.
+         */
+        if( len == 0 )
+            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+        while( *p < end )
+        {
+            const unsigned char *policy_end;
+
+            /*
+             * Get the policy sequence
+             */
+            if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
+                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+            policy_end = *p + len;
+
+            if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
+                                              MBEDTLS_ASN1_OID ) ) != 0 )
+                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+            if( len != 1 || *p[0] != 1 )
+                parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
+
+            *p += len;
+
+           /*
+            * If there is an optional qualifier, then *p < policy_end
+            * Check the Qualifier len to verify it doesn't exceed policy_end.
+            */
+            if( *p < policy_end )
+            {
+                if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
+                         MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+                    return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+                /*
+                 * Skip the optional policy qualifiers.
+                 */
+                *p += len;
+            }
+
+            if( *p != policy_end )
+                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                        MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        }
+
+        if( *p != end )
+            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+        return( parse_ret );
+    }
+    else if( new_oid != NULL && new_oid->tag == oid->tag && new_oid->len == oid->len &&
+             memcmp( new_oid->p, oid->p, oid->len ) == 0 )
+        return( 0 );
+    else
         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
-    return( 0 );
 }
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 /* END_HEADER */