Check for extended key usage by traversing raw extension data

This commit re-implements `mbedtls_x509_crt_check_extended_key_usage()`
to not use the dynamically allocated linked list presentation of the
`ExtendedKeyUsage` but to search for the required usage by traversing
the raw ASN.1 data.
diff --git a/library/x509_crt.c b/library/x509_crt.c
index afc707b..46d6434 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1677,33 +1677,66 @@
 
 #if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
 int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt,
-                                       const char *usage_oid,
-                                       size_t usage_len )
+                                               const char *usage_oid,
+                                               size_t usage_len )
 {
-    const mbedtls_x509_sequence *cur;
+    int ret;
+    size_t len;
+    unsigned ext_types;
+    unsigned char *p, *end;
 
     /* Extension is not mandatory, absent means no restriction */
-    if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
+    ext_types = crt->ext_types;
+    if( ( ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
         return( 0 );
 
-    /*
-     * Look for the requested usage (or wildcard ANY) in our list
-     */
-    for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next )
-    {
-        const mbedtls_x509_buf *cur_oid = &cur->buf;
+    p = crt->ext_key_usage_raw.p;
+    end = p + crt->ext_key_usage_raw.len;
 
-        if( cur_oid->len == usage_len &&
-            memcmp( cur_oid->p, usage_oid, usage_len ) == 0 )
+    ret = mbedtls_asn1_get_tag( &p, end, &len,
+                                MBEDTLS_ASN1_CONSTRUCTED |
+                                MBEDTLS_ASN1_SEQUENCE );
+    if( ret != 0 )
+        goto exit;
+
+    if( end != p + len )
+    {
+        ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+        goto exit;
+    }
+
+    if( len == 0 )
+    {
+        ret = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+        goto exit;
+    }
+
+    while( p < end )
+    {
+        ret = mbedtls_asn1_get_tag( &p, end, &len,
+                                    MBEDTLS_ASN1_OID );
+        if( ret != 0 )
+            goto exit;
+
+        if( usage_oid != NULL )
         {
-            return( 0 );
+            if( len == usage_len && memcmp( p, usage_oid, len ) == 0 )
+                return( 0 );
+
+            if( MBEDTLS_OID_CMP_RAW( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE,
+                                     p, len ) == 0 )
+            {
+                return( 0 );
+            }
         }
 
-        if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 )
-            return( 0 );
+        p += len;
     }
 
     return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+
+exit:
+    return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
 }
 #endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */