openssl: remove manual check for certificate expiration
[platform/upstream/glib-networking.git] / tls / openssl / gtlscertificate-openssl.c
1 /*
2  * gtlscertificate-openssl.c
3  *
4  * Copyright (C) 2015 NICE s.r.l.
5  *
6  * This file is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This file is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  *
19  * In addition, when the library is used with OpenSSL, a special
20  * exception applies. Refer to the LICENSE_EXCEPTION file for details.
21  *
22  * Authors: Ignacio Casal Quinteiro
23  */
24
25 #include "config.h"
26
27 #include <string.h>
28 #include "openssl-include.h"
29
30 #include "gtlscertificate-openssl.h"
31 #include "openssl-util.h"
32 #include <glib/gi18n-lib.h>
33
34 typedef struct _GTlsCertificateOpensslPrivate
35 {
36   X509 *cert;
37   EVP_PKEY *key;
38
39   GTlsCertificateOpenssl *issuer;
40
41   GError *construct_error;
42
43   guint have_cert : 1;
44   guint have_key  : 1;
45 } GTlsCertificateOpensslPrivate;
46
47 enum
48 {
49   PROP_0,
50
51   PROP_CERTIFICATE,
52   PROP_CERTIFICATE_PEM,
53   PROP_PRIVATE_KEY,
54   PROP_PRIVATE_KEY_PEM,
55   PROP_ISSUER
56 };
57
58 static void     g_tls_certificate_openssl_initable_iface_init (GInitableIface  *iface);
59
60 G_DEFINE_TYPE_WITH_CODE (GTlsCertificateOpenssl, g_tls_certificate_openssl, G_TYPE_TLS_CERTIFICATE,
61                          G_ADD_PRIVATE (GTlsCertificateOpenssl)
62                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
63                                                 g_tls_certificate_openssl_initable_iface_init))
64
65 static void
66 g_tls_certificate_openssl_finalize (GObject *object)
67 {
68   GTlsCertificateOpenssl *openssl = G_TLS_CERTIFICATE_OPENSSL (object);
69   GTlsCertificateOpensslPrivate *priv;
70
71   priv = g_tls_certificate_openssl_get_instance_private (openssl);
72
73   if (priv->cert)
74     X509_free (priv->cert);
75   if (priv->key)
76     EVP_PKEY_free (priv->key);
77
78   g_clear_object (&priv->issuer);
79
80   g_clear_error (&priv->construct_error);
81
82   G_OBJECT_CLASS (g_tls_certificate_openssl_parent_class)->finalize (object);
83 }
84
85 static void
86 g_tls_certificate_openssl_get_property (GObject    *object,
87                                         guint       prop_id,
88                                         GValue     *value,
89                                         GParamSpec *pspec)
90 {
91   GTlsCertificateOpenssl *openssl = G_TLS_CERTIFICATE_OPENSSL (object);
92   GTlsCertificateOpensslPrivate *priv;
93   GByteArray *certificate;
94   guint8 *data;
95   BIO *bio;
96   char *certificate_pem;
97   int size;
98
99   priv = g_tls_certificate_openssl_get_instance_private (openssl);
100
101   switch (prop_id)
102     {
103     case PROP_CERTIFICATE:
104       /* NOTE: we do the two calls to avoid openssl allocating the buffer for us */
105       size = i2d_X509 (priv->cert, NULL);
106       if (size < 0)
107         certificate = NULL;
108       else
109         {
110           certificate = g_byte_array_sized_new (size);
111           certificate->len = size;
112           data = certificate->data;
113           size = i2d_X509 (priv->cert, &data);
114           if (size < 0)
115             {
116               g_byte_array_free (certificate, TRUE);
117               certificate = NULL;
118             }
119         }
120       g_value_take_boxed (value, certificate);
121       break;
122
123     case PROP_CERTIFICATE_PEM:
124       bio = BIO_new (BIO_s_mem ());
125
126       if (!PEM_write_bio_X509 (bio, priv->cert) || !BIO_write (bio, "\0", 1))
127         certificate_pem = NULL;
128       else
129         {
130           BIO_get_mem_data (bio, &certificate_pem);
131           g_value_set_string (value, certificate_pem);
132
133           BIO_free_all (bio);
134         }
135       break;
136
137     case PROP_ISSUER:
138       g_value_set_object (value, priv->issuer);
139       break;
140
141     default:
142       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
143     }
144 }
145
146 static void
147 g_tls_certificate_openssl_set_property (GObject      *object,
148                                        guint         prop_id,
149                                        const GValue *value,
150                                        GParamSpec   *pspec)
151 {
152   GTlsCertificateOpenssl *openssl = G_TLS_CERTIFICATE_OPENSSL (object);
153   GTlsCertificateOpensslPrivate *priv;
154   GByteArray *bytes;
155   guint8 *data;
156   BIO *bio;
157   const char *string;
158
159   priv = g_tls_certificate_openssl_get_instance_private (openssl);
160
161   switch (prop_id)
162     {
163     case PROP_CERTIFICATE:
164       bytes = g_value_get_boxed (value);
165       if (!bytes)
166         break;
167       g_return_if_fail (priv->have_cert == FALSE);
168       /* see that we cannot use bytes->data directly since it will move the pointer */
169       data = bytes->data;
170       priv->cert = d2i_X509 (NULL, (const unsigned char **)&data, bytes->len);
171       if (priv->cert != NULL)
172         priv->have_cert = TRUE;
173       else if (!priv->construct_error)
174         {
175           priv->construct_error =
176             g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
177                          _("Could not parse DER certificate: %s"),
178                          ERR_error_string (ERR_get_error (), NULL));
179         }
180
181       break;
182
183     case PROP_CERTIFICATE_PEM:
184       string = g_value_get_string (value);
185       if (!string)
186         break;
187       g_return_if_fail (priv->have_cert == FALSE);
188       bio = BIO_new_mem_buf ((gpointer)string, -1);
189       priv->cert = PEM_read_bio_X509 (bio, NULL, NULL, NULL);
190       BIO_free (bio);
191       if (priv->cert != NULL)
192         priv->have_cert = TRUE;
193       else if (!priv->construct_error)
194         {
195           priv->construct_error =
196             g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
197                          _("Could not parse PEM certificate: %s"),
198                          ERR_error_string (ERR_get_error (), NULL));
199         }
200       break;
201
202     case PROP_PRIVATE_KEY:
203       bytes = g_value_get_boxed (value);
204       if (!bytes)
205         break;
206       g_return_if_fail (priv->have_key == FALSE);
207       bio = BIO_new_mem_buf (bytes->data, bytes->len);
208       priv->key = d2i_PrivateKey_bio (bio, NULL);
209       BIO_free (bio);
210       if (priv->key != NULL)
211         priv->have_key = TRUE;
212       else if (!priv->construct_error)
213         {
214           priv->construct_error =
215             g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
216                          _("Could not parse DER private key: %s"),
217                          ERR_error_string (ERR_get_error (), NULL));
218         }
219       break;
220
221     case PROP_PRIVATE_KEY_PEM:
222       string = g_value_get_string (value);
223       if (!string)
224         break;
225       g_return_if_fail (priv->have_key == FALSE);
226       bio = BIO_new_mem_buf ((gpointer)string, -1);
227       priv->key = PEM_read_bio_PrivateKey (bio, NULL, NULL, NULL);
228       BIO_free (bio);
229       if (priv->key != NULL)
230         priv->have_key = TRUE;
231       else if (!priv->construct_error)
232         {
233           priv->construct_error =
234             g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
235                          _("Could not parse PEM private key: %s"),
236                          ERR_error_string (ERR_get_error (), NULL));
237         }
238       break;
239
240     case PROP_ISSUER:
241       priv->issuer = g_value_dup_object (value);
242       break;
243
244     default:
245       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
246     }
247 }
248
249 static void
250 g_tls_certificate_openssl_init (GTlsCertificateOpenssl *openssl)
251 {
252 }
253
254 static gboolean
255 g_tls_certificate_openssl_initable_init (GInitable       *initable,
256                                          GCancellable    *cancellable,
257                                          GError         **error)
258 {
259   GTlsCertificateOpenssl *openssl = G_TLS_CERTIFICATE_OPENSSL (initable);
260   GTlsCertificateOpensslPrivate *priv;
261
262   priv = g_tls_certificate_openssl_get_instance_private (openssl);
263
264   if (priv->construct_error)
265     {
266       g_propagate_error (error, priv->construct_error);
267       priv->construct_error = NULL;
268       return FALSE;
269     }
270   else if (!priv->have_cert)
271     {
272       g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
273                            _("No certificate data provided"));
274       return FALSE;
275     }
276   else
277     return TRUE;
278 }
279
280 static GTlsCertificateFlags
281 g_tls_certificate_openssl_verify (GTlsCertificate     *cert,
282                                   GSocketConnectable  *identity,
283                                   GTlsCertificate     *trusted_ca)
284 {
285   GTlsCertificateOpenssl *cert_openssl;
286   GTlsCertificateOpensslPrivate *priv;
287   GTlsCertificateFlags gtls_flags;
288   X509 *x;
289   STACK_OF(X509) *untrusted;
290
291   cert_openssl = G_TLS_CERTIFICATE_OPENSSL (cert);
292   priv = g_tls_certificate_openssl_get_instance_private (cert_openssl);
293   x = priv->cert;
294
295   untrusted = sk_X509_new_null ();
296   for (; cert_openssl; cert_openssl = priv->issuer)
297     {
298       priv = g_tls_certificate_openssl_get_instance_private (cert_openssl);
299       sk_X509_push (untrusted, priv->cert);
300     }
301
302   gtls_flags = 0;
303
304   if (trusted_ca)
305     {
306       X509_STORE *store;
307       X509_STORE_CTX *csc;
308       STACK_OF(X509) *trusted;
309
310       store = X509_STORE_new ();
311       csc = X509_STORE_CTX_new ();
312
313       if (!X509_STORE_CTX_init (csc, store, x, untrusted))
314         {
315           sk_X509_free (untrusted);
316           X509_STORE_CTX_free (csc);
317           X509_STORE_free (store);
318           return G_TLS_CERTIFICATE_GENERIC_ERROR;
319         }
320
321       trusted = sk_X509_new_null ();
322       cert_openssl = G_TLS_CERTIFICATE_OPENSSL (trusted_ca);
323       for (; cert_openssl; cert_openssl = priv->issuer)
324         {
325           priv = g_tls_certificate_openssl_get_instance_private (cert_openssl);
326           sk_X509_push (trusted, priv->cert);
327         }
328
329       X509_STORE_CTX_trusted_stack (csc, trusted);
330       if (X509_verify_cert (csc) <= 0)
331         gtls_flags |= g_tls_certificate_openssl_convert_error (X509_STORE_CTX_get_error (csc));
332
333       sk_X509_free (trusted);
334       X509_STORE_CTX_free (csc);
335       X509_STORE_free (store);
336     }
337
338   sk_X509_free (untrusted);
339
340   if (identity)
341     gtls_flags |= g_tls_certificate_openssl_verify_identity (G_TLS_CERTIFICATE_OPENSSL (cert), identity);
342
343   return gtls_flags;
344 }
345
346 static void
347 g_tls_certificate_openssl_class_init (GTlsCertificateOpensslClass *klass)
348 {
349   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
350   GTlsCertificateClass *certificate_class = G_TLS_CERTIFICATE_CLASS (klass);
351
352   gobject_class->get_property = g_tls_certificate_openssl_get_property;
353   gobject_class->set_property = g_tls_certificate_openssl_set_property;
354   gobject_class->finalize     = g_tls_certificate_openssl_finalize;
355
356   certificate_class->verify = g_tls_certificate_openssl_verify;
357
358   g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
359   g_object_class_override_property (gobject_class, PROP_CERTIFICATE_PEM, "certificate-pem");
360   g_object_class_override_property (gobject_class, PROP_PRIVATE_KEY, "private-key");
361   g_object_class_override_property (gobject_class, PROP_PRIVATE_KEY_PEM, "private-key-pem");
362   g_object_class_override_property (gobject_class, PROP_ISSUER, "issuer");
363 }
364
365 static void
366 g_tls_certificate_openssl_initable_iface_init (GInitableIface  *iface)
367 {
368   iface->init = g_tls_certificate_openssl_initable_init;
369 }
370
371 GTlsCertificate *
372 g_tls_certificate_openssl_new (GBytes          *bytes,
373                                GTlsCertificate *issuer)
374 {
375   GTlsCertificateOpenssl *openssl;
376
377   openssl = g_object_new (G_TYPE_TLS_CERTIFICATE_OPENSSL,
378                           "issuer", issuer,
379                           NULL);
380   g_tls_certificate_openssl_set_data (openssl, bytes);
381
382   return G_TLS_CERTIFICATE (openssl);
383 }
384
385 GTlsCertificate *
386 g_tls_certificate_openssl_new_from_x509 (X509            *x,
387                                          GTlsCertificate *issuer)
388 {
389   GTlsCertificateOpenssl *openssl;
390   GTlsCertificateOpensslPrivate *priv;
391
392   openssl = g_object_new (G_TYPE_TLS_CERTIFICATE_OPENSSL,
393                           "issuer", issuer,
394                           NULL);
395
396   priv = g_tls_certificate_openssl_get_instance_private (openssl);
397
398   priv->cert = X509_dup (x);
399   priv->have_cert = TRUE;
400
401   return G_TLS_CERTIFICATE (openssl);
402 }
403
404 void
405 g_tls_certificate_openssl_set_data (GTlsCertificateOpenssl *openssl,
406                                     GBytes                 *bytes)
407 {
408   GTlsCertificateOpensslPrivate *priv;
409   const unsigned char *data;
410
411   g_return_if_fail (G_IS_TLS_CERTIFICATE_OPENSSL (openssl));
412
413   priv = g_tls_certificate_openssl_get_instance_private (openssl);
414
415   g_return_if_fail (!priv->have_cert);
416
417   data = (const unsigned char *)g_bytes_get_data (bytes, NULL);
418   priv->cert = d2i_X509 (NULL, &data, g_bytes_get_size (bytes));
419
420   if (priv->cert != NULL)
421     priv->have_cert = TRUE;
422 }
423
424 GBytes *
425 g_tls_certificate_openssl_get_bytes (GTlsCertificateOpenssl *openssl)
426 {
427   GByteArray *array;
428
429   g_return_val_if_fail (G_IS_TLS_CERTIFICATE_OPENSSL (openssl), NULL);
430
431   g_object_get (openssl, "certificate", &array, NULL);
432   return g_byte_array_free_to_bytes (array);
433 }
434
435 X509 *
436 g_tls_certificate_openssl_get_cert (GTlsCertificateOpenssl *openssl)
437 {
438   GTlsCertificateOpensslPrivate *priv;
439
440   g_return_val_if_fail (G_IS_TLS_CERTIFICATE_OPENSSL (openssl), FALSE);
441
442   priv = g_tls_certificate_openssl_get_instance_private (openssl);
443
444   return priv->cert;
445 }
446
447 EVP_PKEY *
448 g_tls_certificate_openssl_get_key (GTlsCertificateOpenssl *openssl)
449 {
450   GTlsCertificateOpensslPrivate *priv;
451
452   g_return_val_if_fail (G_IS_TLS_CERTIFICATE_OPENSSL (openssl), FALSE);
453
454   priv = g_tls_certificate_openssl_get_instance_private (openssl);
455
456   return priv->key;
457 }
458
459 void
460 g_tls_certificate_openssl_set_issuer (GTlsCertificateOpenssl *openssl,
461                                       GTlsCertificateOpenssl *issuer)
462 {
463   GTlsCertificateOpensslPrivate *priv;
464
465   g_return_if_fail (G_IS_TLS_CERTIFICATE_OPENSSL (openssl));
466   g_return_if_fail (!issuer || G_IS_TLS_CERTIFICATE_OPENSSL (issuer));
467
468   priv = g_tls_certificate_openssl_get_instance_private (openssl);
469
470   if (g_set_object (&priv->issuer, issuer))
471     g_object_notify (G_OBJECT (openssl), "issuer");
472 }
473
474 static gboolean
475 verify_identity_hostname (GTlsCertificateOpenssl *openssl,
476                           GSocketConnectable     *identity)
477 {
478   GTlsCertificateOpensslPrivate *priv;
479   const char *hostname;
480
481   priv = g_tls_certificate_openssl_get_instance_private (openssl);
482
483   if (G_IS_NETWORK_ADDRESS (identity))
484     hostname = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity));
485   else if (G_IS_NETWORK_SERVICE (identity))
486     hostname = g_network_service_get_domain (G_NETWORK_SERVICE (identity));
487   else
488     return FALSE;
489
490   return g_tls_X509_check_host (priv->cert, hostname, strlen (hostname), 0, NULL) == 1;
491 }
492
493 static gboolean
494 verify_identity_ip (GTlsCertificateOpenssl *openssl,
495                     GSocketConnectable     *identity)
496 {
497   GTlsCertificateOpensslPrivate *priv;
498   GInetAddress *addr;
499   gsize addr_size;
500   const guint8 *addr_bytes;
501   gboolean ret;
502
503   priv = g_tls_certificate_openssl_get_instance_private (openssl);
504
505   if (G_IS_INET_SOCKET_ADDRESS (identity))
506     addr = g_object_ref (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (identity)));
507   else {
508     const char *hostname;
509
510     if (G_IS_NETWORK_ADDRESS (identity))
511       hostname = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity));
512     else if (G_IS_NETWORK_SERVICE (identity))
513       hostname = g_network_service_get_domain (G_NETWORK_SERVICE (identity));
514     else
515       return FALSE;
516
517     addr = g_inet_address_new_from_string (hostname);
518     if (!addr)
519       return FALSE;
520   }
521
522   addr_bytes = g_inet_address_to_bytes (addr);
523   addr_size = g_inet_address_get_native_size (addr);
524
525   ret = g_tls_X509_check_ip (priv->cert, addr_bytes, addr_size, 0) == 1;
526
527   g_object_unref (addr);
528   return ret;
529 }
530
531 GTlsCertificateFlags
532 g_tls_certificate_openssl_verify_identity (GTlsCertificateOpenssl *openssl,
533                                            GSocketConnectable     *identity)
534 {
535   if (verify_identity_hostname (openssl, identity))
536     return 0;
537   else if (verify_identity_ip (openssl, identity))
538     return 0;
539
540   /* FIXME: check sRVName and uniformResourceIdentifier
541    * subjectAltNames, if appropriate for @identity.
542    */
543   TIZEN_LOGE("SSL HandShake - Bad Identity");
544   return G_TLS_CERTIFICATE_BAD_IDENTITY;
545 }
546
547 GTlsCertificateFlags
548 g_tls_certificate_openssl_convert_error (guint openssl_error)
549 {
550   GTlsCertificateFlags gtls_flags;
551
552   gtls_flags = 0;
553
554   /* FIXME: should we add more ? */
555   switch (openssl_error)
556     {
557     case X509_V_OK:
558       break;
559     case X509_V_ERR_CERT_NOT_YET_VALID:
560       gtls_flags = G_TLS_CERTIFICATE_NOT_ACTIVATED;
561       break;
562     case X509_V_ERR_CERT_HAS_EXPIRED:
563       gtls_flags = G_TLS_CERTIFICATE_EXPIRED;
564       break;
565     case X509_V_ERR_CERT_REVOKED:
566       gtls_flags = G_TLS_CERTIFICATE_REVOKED;
567       break;
568     case X509_V_ERR_AKID_SKID_MISMATCH:
569       gtls_flags = G_TLS_CERTIFICATE_BAD_IDENTITY;
570       break;
571     case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
572     case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
573 #ifdef TIZEN_EXT
574     case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
575 #endif
576       gtls_flags = G_TLS_CERTIFICATE_UNKNOWN_CA;
577       break;
578     default:
579       g_message ("certificate error: %s", X509_verify_cert_error_string (openssl_error));
580       gtls_flags = G_TLS_CERTIFICATE_GENERIC_ERROR;
581     }
582
583   return gtls_flags;
584 }
585
586 static gboolean
587 is_issuer (GTlsCertificateOpenssl *cert,
588            GTlsCertificateOpenssl *issuer)
589 {
590   X509 *x;
591   X509 *issuer_x;
592   X509_STORE *store;
593   X509_STORE_CTX *csc;
594   STACK_OF(X509) *trusted;
595   gboolean ret = FALSE;
596   gint err;
597
598   x = g_tls_certificate_openssl_get_cert (cert);
599   issuer_x = g_tls_certificate_openssl_get_cert (issuer);
600
601   store = X509_STORE_new ();
602   csc = X509_STORE_CTX_new ();
603
604   if (!X509_STORE_CTX_init (csc, store, x, NULL))
605     goto end;
606
607   trusted = sk_X509_new_null ();
608   sk_X509_push (trusted, issuer_x);
609
610   X509_STORE_CTX_trusted_stack (csc, trusted);
611   X509_STORE_CTX_set_flags (csc, X509_V_FLAG_CB_ISSUER_CHECK);
612
613   /* FIXME: is this the right way to do it? */
614   if (X509_verify_cert (csc) <= 0)
615     {
616       err = X509_STORE_CTX_get_error (csc);
617       if (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)
618         ret = TRUE;
619     }
620   else
621     ret = TRUE;
622
623   sk_X509_free (trusted);
624
625 end:
626   X509_STORE_CTX_free (csc);
627   X509_STORE_free (store);
628
629   return ret;
630 }
631
632 GTlsCertificateOpenssl *
633 g_tls_certificate_openssl_build_chain (X509            *x,
634                                        STACK_OF (X509) *chain)
635 {
636   GPtrArray *glib_certs;
637   GTlsCertificateOpenssl *issuer;
638   GTlsCertificateOpenssl *result;
639   guint i, j;
640
641   g_return_val_if_fail (x != NULL, NULL);
642   g_return_val_if_fail (chain, NULL);
643
644   glib_certs = g_ptr_array_new_full (sk_X509_num (chain), g_object_unref);
645   g_ptr_array_add (glib_certs, g_tls_certificate_openssl_new_from_x509 (x, NULL));
646   for (i = 1; i < sk_X509_num (chain); i++)
647     g_ptr_array_add (glib_certs, g_tls_certificate_openssl_new_from_x509 (sk_X509_value (chain, i), NULL));
648
649   /* Some servers send certs out of order, or will send duplicate
650    * certs, so we need to be careful when assigning the issuer of
651    * our new GTlsCertificateOpenssl.
652    */
653   for (i = 0; i < glib_certs->len; i++)
654     {
655       issuer = NULL;
656
657       /* Check if the cert issued itself */
658       if (is_issuer (glib_certs->pdata[i], glib_certs->pdata[i]))
659         continue;
660
661       if (i < glib_certs->len - 1 &&
662           is_issuer (glib_certs->pdata[i], glib_certs->pdata[i + 1]))
663         {
664           issuer = glib_certs->pdata[i + 1];
665         }
666       else
667         {
668           for (j = 0; j < glib_certs->len; j++)
669             {
670               if (j != i &&
671                   is_issuer (glib_certs->pdata[i], glib_certs->pdata[j]))
672                 {
673                   issuer = glib_certs->pdata[j];
674                   break;
675                 }
676             }
677         }
678
679       if (issuer)
680         g_tls_certificate_openssl_set_issuer (glib_certs->pdata[i], issuer);
681     }
682
683   result = g_object_ref (glib_certs->pdata[0]);
684   g_ptr_array_unref (glib_certs);
685
686   return result;
687 }