Add public API to query SubjectAltNames and ExtKeyUsage extensions
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 790016e..ca93e1a 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -751,6 +751,56 @@
                                  mbedtls_x509_name **issuer );
 
 /**
+ * \brief           Request the subject alternative name of a CRT, presented
+ *                  as a dynamically allocated linked list.
+ *
+ * \param crt       The CRT to use. This must be initialized and setup.
+ * \param subj_alt  The address at which to store the address of the
+ *                  first component of the subject alternative names list.
+ *
+ * \note            Depending in your use case, consider using the raw ASN.1
+ *                  describing the subject alternative names extension
+ *                  instead of the heap-allocated linked list generated by this
+ *                  call. The pointers to the raw ASN.1 data are part of the CRT
+ *                  frame that can be queried via mbedtls_x509_crt_get_frame(),
+ *                  and mbedtls_asn1_traverse_sequence_of() can be used to
+ *                  traverse the list of subject alternative names.
+ *
+ * \return          \c 0 on success. In this case, the user takes ownership
+ *                  of the name context, and is responsible for freeing it
+ *                  through a call to mbedtls_x509_sequence_free() once it's
+ *                  no longer needed.
+ * \return          A negative error code on failure.
+ */
+int mbedtls_x509_crt_get_subject_alt_names( mbedtls_x509_crt const *crt,
+                                            mbedtls_x509_sequence **subj_alt );
+
+/**
+ * \brief           Request the ExtendedKeyUsage extension of a CRT,
+ *                  presented as a dynamically allocated linked list.
+ *
+ * \param crt       The CRT to use. This must be initialized and setup.
+ * \param ext_key_usage The address at which to store the address of the
+ *                  first entry of the ExtendedKeyUsage extension.
+ *
+ * \note            Depending in your use case, consider using the raw ASN.1
+ *                  describing the extended key usage extension instead of
+ *                  the heap-allocated linked list generated by this call.
+ *                  The pointers to the raw ASN.1 data are part of the CRT
+ *                  frame that can be queried via mbedtls_x509_crt_get_frame(),
+ *                  and mbedtls_asn1_traverse_sequence_of() can be used to
+ *                  traverse the entries in the extended key usage extension.
+ *
+ * \return          \c 0 on success. In this case, the user takes ownership
+ *                  of the name context, and is responsible for freeing it
+ *                  through a call to mbedtls_x509_sequence_free() once it's
+ *                  no longer needed.
+ * \return          A negative error code on failure.
+ */
+int mbedtls_x509_crt_get_ext_key_usage( mbedtls_x509_crt const *crt,
+                                        mbedtls_x509_sequence **ext_key_usage );
+
+/**
  * \brief           Flush internal X.509 CRT parsing cache, if present.
  *
  * \param crt       The CRT structure whose cache to flush.
diff --git a/library/x509_crt.c b/library/x509_crt.c
index fe782bb..643b561 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -195,6 +195,52 @@
     return( 0 );
 }
 
+int mbedtls_x509_crt_get_subject_alt_names( mbedtls_x509_crt const *crt,
+                                            mbedtls_x509_sequence **subj_alt )
+{
+    int ret;
+    mbedtls_x509_crt_frame *frame;
+    mbedtls_x509_sequence *seq;
+
+    ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
+    if( ret != 0 )
+        return( ret );
+
+    seq = mbedtls_calloc( 1, sizeof( mbedtls_x509_sequence ) );
+    if( seq == NULL )
+        ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
+    else
+        ret = x509_crt_subject_alt_from_frame( frame, seq );
+
+    mbedtls_x509_crt_frame_release( crt, frame );
+
+    *subj_alt = seq;
+    return( ret );
+}
+
+int mbedtls_x509_crt_get_ext_key_usage( mbedtls_x509_crt const *crt,
+                                        mbedtls_x509_sequence **ext_key_usage )
+{
+    int ret;
+    mbedtls_x509_crt_frame *frame;
+    mbedtls_x509_sequence *seq;
+
+    ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
+    if( ret != 0 )
+        return( ret );
+
+    seq = mbedtls_calloc( 1, sizeof( mbedtls_x509_sequence ) );
+    if( seq == NULL )
+        ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
+    else
+        ret = x509_crt_ext_key_usage_from_frame( frame, seq );
+
+    mbedtls_x509_crt_frame_release( crt, frame );
+
+    *ext_key_usage = seq;
+    return( ret );
+}
+
 int mbedtls_x509_crt_get_subject( mbedtls_x509_crt const *crt,
                                   mbedtls_x509_name **subject )
 {