diff --git a/gio/gtlscertificate.c b/gio/gtlscertificate.c
index 47de03d..f7082b4 100644
--- a/gio/gtlscertificate.c
+++ b/gio/gtlscertificate.c
@@ -197,8 +197,9 @@ g_tls_certificate_class_init (GTlsCertificateClass *class)
 
 static GTlsCertificate *
 g_tls_certificate_new_internal (const gchar  *certificate_pem,
-				const gchar  *private_key_pem,
-				GError      **error)
+				const gchar      *private_key_pem,
+				GTlsCertificate  *issuer,
+				GError          **error)
 {
   GObject *cert;
   GTlsBackend *backend;
@@ -209,6 +210,7 @@ g_tls_certificate_new_internal (const gchar  *certificate_pem,
 			 NULL, error,
 			 "certificate-pem", certificate_pem,
 			 "private-key-pem", private_key_pem,
+			 "issuer", issuer,
 			 NULL);
   return G_TLS_CERTIFICATE (cert);
 }
@@ -305,6 +307,101 @@ parse_next_pem_certificate (const gchar **data,
   return g_strndup (start, end - start);
 }
 
+static GTlsCertificate *
+parse_and_create_certificate (const gchar *data,
+                              gsize        data_len,
+                              const gchar *key_pem,
+                              GError      **error)
+
+{
+  GQueue queue = G_QUEUE_INIT;
+  GTlsCertificate *cert = NULL;
+  gchar *cert_pem;
+  const gchar *p, *end;
+  gboolean required = TRUE;
+
+  p = data;
+  end = p + data_len;
+  while (p && *p)
+    {
+      cert_pem = parse_next_pem_certificate (&p, end, required, error);
+
+      if (error && *error)
+        {
+          g_list_free_full (queue.head, g_free);
+          goto cleanup;
+        }
+
+      /* If we don't get an error and cert_pem is NULL it means the
+       * certificate was not required (we already loaded one) and no
+       * more certificates were found. */
+      if (cert_pem == NULL)
+        break;
+
+      g_queue_push_head (&queue, cert_pem);
+      required = FALSE;
+    }
+
+  cert_pem = g_queue_pop_head (&queue);
+  while (cert_pem)
+    {
+      GTlsCertificate *loaded;
+
+      /* Create the certificate (with no issuer). */
+      loaded = g_tls_certificate_new_internal (cert_pem, key_pem, NULL, error);
+
+      if (error && *error)
+        {
+          g_free (cert_pem);
+          g_list_free_full (queue.head, g_free);
+          goto cleanup;
+        }
+
+      if (cert)
+        {
+          GTlsCertificateFlags flags;
+
+          /* Next certificate should be the issuer of the last loaded
+           * certificate. */
+          flags = g_tls_certificate_verify (loaded, NULL, cert);
+          if (flags == 0)
+            {
+              /* We need to free the loaded certificate as it has no
+               * issuer and create it with the issuer. */
+              g_object_unref (loaded);
+
+              loaded = g_tls_certificate_new_internal (cert_pem, key_pem, cert, error);
+
+              /* We don't want to keep a copy of the issuer. */
+              g_object_unref (cert);
+
+              cert = loaded;
+            }
+          else
+            {
+              g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
+                                   _("Could not verify the certificate chain"));
+              goto cleanup;
+            }
+        }
+      else
+        cert = loaded;
+
+      g_free (cert_pem);
+      cert_pem = g_queue_pop_head (&queue);
+    }
+
+  return cert;
+
+  /* ERRORS */
+ cleanup:
+  {
+    if (cert)
+      g_object_unref (cert);
+    return NULL;
+  }
+}
+
 /**
  * g_tls_certificate_new_from_pem:
  * @data: PEM-encoded certificate data
@@ -329,8 +426,7 @@ g_tls_certificate_new_from_pem  (const gchar  *data,
 				 gssize        length,
 				 GError      **error)
 {
-  const gchar *data_end;
-  gchar *key_pem, *cert_pem;
+  gchar *key_pem;
   GTlsCertificate *cert;
 
   g_return_val_if_fail (data != NULL, NULL);
@@ -338,22 +434,12 @@ g_tls_certificate_new_from_pem  (const gchar  *data,
   if (length == -1)
     length = strlen (data);
 
-  data_end = data + length;
-
   key_pem = parse_private_key (data, length, FALSE, error);
   if (error && *error)
     return NULL;
 
-  cert_pem = parse_next_pem_certificate (&data, data_end, TRUE, error);
-  if (error && *error)
-    {
-      g_free (key_pem);
-      return NULL;
-    }
-
-  cert = g_tls_certificate_new_internal (cert_pem, key_pem, error);
+  cert = parse_and_create_certificate (data, length, key_pem, error);
   g_free (key_pem);
-  g_free (cert_pem);
 
   return cert;
 }
@@ -405,38 +491,30 @@ g_tls_certificate_new_from_file (const gchar  *file,
  */
 GTlsCertificate *
 g_tls_certificate_new_from_files (const gchar  *cert_file,
-				  const gchar  *key_file,
-				  GError      **error)
+                                  const gchar  *key_file,
+                                  GError      **error)
 {
   GTlsCertificate *cert;
   gchar *cert_data, *key_data;
   gsize cert_len, key_len;
-  gchar *cert_pem, *key_pem;
-  const gchar *p;
+  gchar *key_pem;
 
-  if (!g_file_get_contents (cert_file, &cert_data, &cert_len, error))
-    return NULL;
-  p = cert_data;
-  cert_pem = parse_next_pem_certificate (&p, p + cert_len, TRUE, error);
-  g_free (cert_data);
-  if (error && *error)
+  if (!g_file_get_contents (key_file, &key_data, &key_len, error))
     return NULL;
 
-  if (!g_file_get_contents (key_file, &key_data, &key_len, error))
-    {
-      g_free (cert_pem);
-      return NULL;
-    }
   key_pem = parse_private_key (key_data, key_len, TRUE, error);
   g_free (key_data);
   if (error && *error)
+    return NULL;
+
+  if (!g_file_get_contents (cert_file, &cert_data, &cert_len, error))
     {
-      g_free (cert_pem);
+      g_free (key_pem);
       return NULL;
     }
 
-  cert = g_tls_certificate_new_internal (cert_pem, key_pem, error);
-  g_free (cert_pem);
+  cert = parse_and_create_certificate (cert_data, cert_len, key_pem, error);
+  g_free (cert_data);
   g_free (key_pem);
   return cert;
 }
@@ -481,7 +559,7 @@ g_tls_certificate_list_new_from_file (const gchar  *file,
       cert_pem = parse_next_pem_certificate (&p, end, FALSE, &parse_error);
       if (cert_pem)
         {
-          cert = g_tls_certificate_new_internal (cert_pem, NULL, &parse_error);
+          cert = g_tls_certificate_new_internal (cert_pem, NULL, NULL, &parse_error);
           g_free (cert_pem);
         }
       if (!cert)
