Make use of CRT acquire/release in mbedtls_x509_crt_info()

This commit adapts `mbedtls_x509_crt_info()` to no longer access
structure fields from `mbedtls_x509_crt` directly, but to instead
query for a `mbedtls_x509_crt_frame` and `mbedtls_pk_context` and
use these to extract the required CRT information.
diff --git a/library/x509_crt.c b/library/x509_crt.c
index aa82c2c..63823d3 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1762,81 +1762,204 @@
     return( 0 );
 }
 
+typedef struct mbedtls_x509_crt_sig_info
+{
+    mbedtls_md_type_t sig_md;
+    mbedtls_pk_type_t sig_pk;
+    void *sig_opts;
+    uint8_t crt_hash[MBEDTLS_MD_MAX_SIZE];
+    size_t crt_hash_len;
+    mbedtls_x509_buf_raw sig;
+    mbedtls_x509_buf_raw issuer_raw;
+} mbedtls_x509_crt_sig_info;
+
+static void x509_crt_free_sig_info( mbedtls_x509_crt_sig_info *info )
+{
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+    mbedtls_free( info->sig_opts );
+#else
+    ((void) info);
+#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+}
+
+static int x509_crt_get_sig_info( mbedtls_x509_crt_frame const *frame,
+                                  mbedtls_x509_crt_sig_info *info )
+{
+    const mbedtls_md_info_t *md_info;
+
+    md_info = mbedtls_md_info_from_type( frame->sig_md );
+    if( mbedtls_md( md_info, frame->tbs.p, frame->tbs.len,
+                    info->crt_hash ) != 0 )
+    {
+        /* Note: this can't happen except after an internal error */
+        return( -1 );
+    }
+
+    info->crt_hash_len = mbedtls_md_get_size( md_info );
+
+    /* Make sure that this function leaves the target structure
+     * ready to be freed, regardless of success of failure. */
+    info->sig_opts = NULL;
+
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+    {
+        int ret;
+        unsigned char *alg_start = frame->sig_alg.p;
+        unsigned char *alg_end = alg_start + frame->sig_alg.len;
+
+        /* Get signature options -- currently only
+         * necessary for RSASSA-PSS. */
+        ret = mbedtls_x509_get_sig_alg_raw( &alg_start, alg_end, &info->sig_md,
+                                            &info->sig_pk, &info->sig_opts );
+        if( ret != 0 )
+        {
+            /* Note: this can't happen except after an internal error */
+            return( -1 );
+        }
+    }
+#else /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+    info->sig_md   = frame->sig_md;
+    info->sig_pk   = frame->sig_pk;
+#endif /* !MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+
+    info->issuer_raw = frame->issuer_raw;
+    info->sig = frame->sig;
+    return( 0 );
+}
+
 /*
  * Return an informational string about the certificate.
  */
 #define BEFORE_COLON    18
 #define BC              "18"
 int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
-                   const mbedtls_x509_crt *crt )
+                           const mbedtls_x509_crt *crt_raw )
 {
     int ret;
     size_t n;
     char *p;
     char key_size_str[BEFORE_COLON];
+    mbedtls_x509_crt_frame *crt;
+    mbedtls_pk_context *pk;
+
+    mbedtls_x509_name issuer, subject;
+    mbedtls_x509_sequence ext_key_usage, subject_alt_names;
+    mbedtls_x509_crt_sig_info sig_info;
 
     p = buf;
     n = size;
 
-    if( NULL == crt )
+    memset( &sig_info, 0, sizeof( mbedtls_x509_crt_sig_info ) );
+    if( NULL == crt_raw )
     {
         ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" );
-        MBEDTLS_X509_SAFE_SNPRINTF;
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
         return( (int) ( size - n ) );
     }
 
+    ret = x509_crt_frame_acquire( crt_raw, &crt );
+    if( ret != 0 )
+        return( MBEDTLS_ERR_X509_FATAL_ERROR );
+
+    ret = x509_crt_pk_acquire( (mbedtls_x509_crt*) crt_raw, &pk );
+    if( ret != 0 )
+    {
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+        goto cleanup;
+    }
+
+    ret = x509_crt_get_sig_info( crt, &sig_info );
+    if( ret != 0 )
+    {
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+        goto cleanup;
+    }
+
+    ret = x509_crt_subject_from_frame( crt, &subject );
+    if( ret != 0 )
+    {
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+        goto cleanup;
+    }
+
+    ret = x509_crt_issuer_from_frame( crt, &issuer );
+    if( ret != 0 )
+    {
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+        goto cleanup;
+    }
+
+    ret = x509_crt_subject_alt_from_frame( crt, &subject_alt_names );
+    if( ret != 0 )
+    {
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+        goto cleanup;
+    }
+
+    ret = x509_crt_ext_key_usage_from_frame( crt, &ext_key_usage );
+    if( ret != 0 )
+    {
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+        goto cleanup;
+    }
+
     ret = mbedtls_snprintf( p, n, "%scert. version     : %d\n",
                                prefix, crt->version );
-    MBEDTLS_X509_SAFE_SNPRINTF;
-    ret = mbedtls_snprintf( p, n, "%sserial number     : ",
-                               prefix );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
-    ret = mbedtls_x509_serial_gets( p, n, &crt->serial );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    {
+        mbedtls_x509_buf serial;
+        serial.p   = crt->serial.p;
+        serial.len = crt->serial.len;
+        ret = mbedtls_snprintf( p, n, "%sserial number     : ",
+                                prefix );
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
+        ret = mbedtls_x509_serial_gets( p, n, &serial );
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
+    }
 
     ret = mbedtls_snprintf( p, n, "\n%sissuer name       : ", prefix );
-    MBEDTLS_X509_SAFE_SNPRINTF;
-    ret = mbedtls_x509_dn_gets( p, n, &crt->issuer  );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
+    ret = mbedtls_x509_dn_gets( p, n, &issuer  );
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
     ret = mbedtls_snprintf( p, n, "\n%ssubject name      : ", prefix );
-    MBEDTLS_X509_SAFE_SNPRINTF;
-    ret = mbedtls_x509_dn_gets( p, n, &crt->subject );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
+    ret = mbedtls_x509_dn_gets( p, n, &subject );
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
     ret = mbedtls_snprintf( p, n, "\n%sissued  on        : " \
                    "%04d-%02d-%02d %02d:%02d:%02d", prefix,
                    crt->valid_from.year, crt->valid_from.mon,
                    crt->valid_from.day,  crt->valid_from.hour,
                    crt->valid_from.min,  crt->valid_from.sec );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
     ret = mbedtls_snprintf( p, n, "\n%sexpires on        : " \
                    "%04d-%02d-%02d %02d:%02d:%02d", prefix,
                    crt->valid_to.year, crt->valid_to.mon,
                    crt->valid_to.day,  crt->valid_to.hour,
                    crt->valid_to.min,  crt->valid_to.sec );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
     ret = mbedtls_snprintf( p, n, "\n%ssigned using      : ", prefix );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
     ret = mbedtls_x509_sig_alg_gets( p, n, sig_info.sig_pk,
                                      sig_info.sig_md, sig_info.sig_opts );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
     /* Key size */
     if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
-                                      mbedtls_pk_get_name( &crt->pk ) ) ) != 0 )
+                                      mbedtls_pk_get_name( pk ) ) ) != 0 )
     {
         return( ret );
     }
 
     ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
-                          (int) mbedtls_pk_get_bitlen( &crt->pk ) );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+                          (int) mbedtls_pk_get_bitlen( pk ) );
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
     /*
      * Optional extensions
@@ -1846,29 +1969,29 @@
     {
         ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
                         crt->ca_istrue ? "true" : "false" );
-        MBEDTLS_X509_SAFE_SNPRINTF;
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
         if( crt->max_pathlen > 0 )
         {
             ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 );
-            MBEDTLS_X509_SAFE_SNPRINTF;
+            MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
         }
     }
 
     if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
     {
         ret = mbedtls_snprintf( p, n, "\n%ssubject alt name  : ", prefix );
-        MBEDTLS_X509_SAFE_SNPRINTF;
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
         if( ( ret = x509_info_subject_alt_name( &p, &n,
-                                            &crt->subject_alt_names ) ) != 0 )
+                                            &subject_alt_names ) ) != 0 )
             return( ret );
     }
 
     if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE )
     {
         ret = mbedtls_snprintf( p, n, "\n%scert. type        : ", prefix );
-        MBEDTLS_X509_SAFE_SNPRINTF;
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
         if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 )
             return( ret );
@@ -1877,7 +2000,7 @@
     if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE )
     {
         ret = mbedtls_snprintf( p, n, "\n%skey usage         : ", prefix );
-        MBEDTLS_X509_SAFE_SNPRINTF;
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
         if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 )
             return( ret );
@@ -1886,17 +2009,30 @@
     if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE )
     {
         ret = mbedtls_snprintf( p, n, "\n%sext key usage     : ", prefix );
-        MBEDTLS_X509_SAFE_SNPRINTF;
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
         if( ( ret = x509_info_ext_key_usage( &p, &n,
-                                             &crt->ext_key_usage ) ) != 0 )
+                                             &ext_key_usage ) ) != 0 )
             return( ret );
     }
 
     ret = mbedtls_snprintf( p, n, "\n" );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
 
-    return( (int) ( size - n ) );
+    ret = (int) ( size - n );
+
+cleanup:
+
+    x509_crt_frame_release( crt_raw, crt );
+    x509_crt_pk_release( (mbedtls_x509_crt*) crt_raw, pk );
+
+    x509_crt_free_sig_info( &sig_info );
+    x509_free_name( issuer.next );
+    x509_free_name( subject.next );
+    x509_free_sequence( ext_key_usage.next );
+    x509_free_sequence( subject_alt_names.next );
+
+    return( ret );
 }
 
 struct x509_crt_verify_string {
@@ -2273,71 +2409,6 @@
     return( 0 );
 }
 
-typedef struct mbedtls_x509_crt_sig_info
-{
-    mbedtls_md_type_t sig_md;
-    mbedtls_pk_type_t sig_pk;
-    void *sig_opts;
-    uint8_t crt_hash[MBEDTLS_MD_MAX_SIZE];
-    size_t crt_hash_len;
-    mbedtls_x509_buf_raw sig;
-    mbedtls_x509_buf_raw issuer_raw;
-} mbedtls_x509_crt_sig_info;
-
-static void x509_crt_free_sig_info( mbedtls_x509_crt_sig_info *info )
-{
-#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
-    mbedtls_free( info->sig_opts );
-#else
-    ((void) info);
-#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
-}
-
-static int x509_crt_get_sig_info( mbedtls_x509_crt_frame const *frame,
-                                  mbedtls_x509_crt_sig_info *info )
-{
-    const mbedtls_md_info_t *md_info;
-
-    md_info = mbedtls_md_info_from_type( frame->sig_md );
-    if( mbedtls_md( md_info, frame->tbs.p, frame->tbs.len,
-                    info->crt_hash ) != 0 )
-    {
-        /* Note: this can't happen except after an internal error */
-        return( -1 );
-    }
-
-    info->crt_hash_len = mbedtls_md_get_size( md_info );
-
-    /* Make sure that this function leaves the target structure
-     * ready to be freed, regardless of success of failure. */
-    info->sig_opts = NULL;
-
-#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
-    {
-        int ret;
-        unsigned char *alg_start = frame->sig_alg.p;
-        unsigned char *alg_end = alg_start + frame->sig_alg.len;
-
-        /* Get signature options -- currently only
-         * necessary for RSASSA-PSS. */
-        ret = mbedtls_x509_get_sig_alg_raw( &alg_start, alg_end, &info->sig_md,
-                                            &info->sig_pk, &info->sig_opts );
-        if( ret != 0 )
-        {
-            /* Note: this can't happen except after an internal error */
-            return( -1 );
-        }
-    }
-#else /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
-    info->sig_md   = frame->sig_md;
-    info->sig_pk   = frame->sig_pk;
-#endif /* !MBEDTLS_X509_RSASSA_PSS_SUPPORT */
-
-    info->issuer_raw = frame->issuer_raw;
-    info->sig = frame->sig;
-    return( 0 );
-}
-
 /*
  * Find a suitable parent for child in candidates, or return NULL.
  *