Extracting SubjectKeyId and AuthorityKeyId in case of x509 V3 extensions. Updating mbedtls_x509_crt_free function to also free the new dynamic elements (issuer field of AuthorityKeyId).
A few tests are also added which test the feature with a correct certificate and multiple ones with erroneous ASN1 tags.

Signed-off-by: toth92g <toth92g@gmail.com>
diff --git a/library/oid.c b/library/oid.c
index aa5f69c..732b386 100644
--- a/library/oid.c
+++ b/library/oid.c
@@ -291,7 +291,15 @@
         MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES,
     },
     {
-        NULL_OID_DESCRIPTOR,
+        { ADD_LEN(MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER), "id-ce-subjectKeyIdentifier",           "Subject Key Identifier" },
+        MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER,
+    },
+    {
+        { ADD_LEN(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER), "id-ce-authorityKeyIdentifier",       "Authority Key Identifier" },
+        MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER,
+    },
+    {
+        { NULL, 0, NULL, NULL },
         0,
     },
 };
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 0eee97c..0aca50f 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -613,6 +613,129 @@
 }
 
 /*
+* SubjectKeyIdentifier ::= KeyIdentifier
+*
+* KeyIdentifier ::= OCTET STRING
+*/
+static int x509_get_subject_key_id(unsigned char** p,
+    const unsigned char* end,
+    mbedtls_x509_buf* subject_key_id)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len = 0u;
+
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+        MBEDTLS_ASN1_OCTET_STRING)) != 0)
+    {
+        return(ret);
+    }
+    else
+    {
+        subject_key_id->len = len;
+        subject_key_id->tag = MBEDTLS_ASN1_OCTET_STRING;
+        subject_key_id->p = *p;
+        *p += len;
+    }
+
+    return(0);
+}
+
+/*
+ * AuthorityKeyIdentifier ::= SEQUENCE {
+ *        keyIdentifier [0] KeyIdentifier OPTIONAL,
+ *        authorityCertIssuer [1] GeneralNames OPTIONAL,
+ *        authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
+ *
+ *    KeyIdentifier ::= OCTET STRING
+ */
+static int x509_get_authority_key_id(unsigned char** p,
+    unsigned char* end,
+    mbedtls_x509_authority* authority_key_id)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len = 0u;
+
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0)
+    {
+        return(ret);
+    }
+
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+        MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 0)
+    {
+        /* KeyIdentifier is an OPTIONAL field */
+    }
+    else
+    {
+        authority_key_id->keyIdentifier.len = len;
+        authority_key_id->keyIdentifier.p = *p;
+        authority_key_id->keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING;
+
+        *p += len;
+    }
+
+    if ( *p < end )
+    {
+        if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+            MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_BOOLEAN)) != 0)
+        {
+            /* authorityCertIssuer is an OPTIONAL field */
+        }
+        else
+        {
+            if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_OCTET_STRING)) != 0)
+            {
+                return(ret);
+            }
+            else
+            {
+                authority_key_id->raw.p = *p;
+
+                if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0)
+                {
+                    return(ret);
+                }
+
+                if ((ret = mbedtls_x509_get_name(p, *p + len, &authority_key_id->authorityCertIssuer)) != 0)
+                {
+                    return(ret);
+                }
+
+                authority_key_id->raw.len = *p - authority_key_id->raw.p;
+            }
+        }
+    }
+
+    if ( *p < end )
+    {
+        if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+            MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_INTEGER)) != 0)
+        {
+            /* authorityCertSerialNumber is an OPTIONAL field, but if there are still data it must be the serial number */
+            return(ret);
+        }
+        else
+        {
+            authority_key_id->authorityCertSerialNumber.len = len;
+            authority_key_id->authorityCertSerialNumber.p = *p;
+            authority_key_id->authorityCertSerialNumber.tag = MBEDTLS_ASN1_OCTET_STRING;
+            *p += len;
+        }
+    }
+
+    if (*p != end)
+    {
+        return(MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+            MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    return(0);
+}
+
+/*
  * SubjectAltName ::= GeneralNames
  *
  * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
@@ -1005,7 +1128,22 @@
                     &crt->ext_key_usage ) ) != 0 )
                 return( ret );
             break;
-
+        case MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER:
+            /* Parse subject key identifier */
+            if ( ( ret = x509_get_subject_key_id( p, end_ext_data,
+                    &crt->subject_key_id ) ) != 0 )
+            {
+                return ( ret );
+            }
+            break;
+        case MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER:
+            /* Parse authority key identifier */
+            if ( (ret = x509_get_authority_key_id(p, end_ext_octet,
+                    &crt->authority_key_id)) != 0 )
+            {
+                return (ret);
+            }
+            break;
         case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
             /* Parse subject alt name */
             if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
@@ -3300,6 +3438,15 @@
         mbedtls_asn1_sequence_free( cert_cur->subject_alt_names.next );
         mbedtls_asn1_sequence_free( cert_cur->certificate_policies.next );
 
+        name_cur = cert_cur->authority_key_id.authorityCertIssuer.next;
+        while (name_cur != NULL)
+        {
+            name_prv = name_cur;
+            name_cur = name_cur->next;
+            mbedtls_platform_zeroize(name_prv, sizeof(mbedtls_x509_name));
+            mbedtls_free(name_prv);
+        }
+
         if( cert_cur->raw.p != NULL && cert_cur->own_buffer )
         {
             mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len );