Coverage Report

Created: 2025-07-01 07:09

/src/glib/gio/gtlscertificate.c
Line
Count
Source (jump to first uncovered line)
1
/* GIO - GLib Input, Output and Certificateing Library
2
 *
3
 * Copyright (C) 2010 Red Hat, Inc.
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2.1 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General
16
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
#include "config.h"
20
21
#include "gtlscertificate.h"
22
23
#include <string.h>
24
#include "ginitable.h"
25
#include "gtlsbackend.h"
26
#include "gtlsconnection.h"
27
#include "glibintl.h"
28
29
/**
30
 * SECTION:gtlscertificate
31
 * @title: GTlsCertificate
32
 * @short_description: TLS certificate
33
 * @include: gio/gio.h
34
 * @see_also: #GTlsConnection
35
 *
36
 * A certificate used for TLS authentication and encryption.
37
 * This can represent either a certificate only (eg, the certificate
38
 * received by a client from a server), or the combination of
39
 * a certificate and a private key (which is needed when acting as a
40
 * #GTlsServerConnection).
41
 *
42
 * Since: 2.28
43
 */
44
45
/**
46
 * GTlsCertificate:
47
 *
48
 * Abstract base class for TLS certificate types.
49
 *
50
 * Since: 2.28
51
 */
52
53
G_DEFINE_ABSTRACT_TYPE (GTlsCertificate, g_tls_certificate, G_TYPE_OBJECT)
54
55
enum
56
{
57
  PROP_0,
58
59
  PROP_CERTIFICATE,
60
  PROP_CERTIFICATE_PEM,
61
  PROP_PRIVATE_KEY,
62
  PROP_PRIVATE_KEY_PEM,
63
  PROP_ISSUER,
64
  PROP_PKCS11_URI,
65
  PROP_PRIVATE_KEY_PKCS11_URI,
66
};
67
68
static void
69
g_tls_certificate_init (GTlsCertificate *cert)
70
0
{
71
0
}
72
73
static void
74
g_tls_certificate_get_property (GObject    *object,
75
        guint       prop_id,
76
        GValue     *value,
77
        GParamSpec *pspec)
78
0
{
79
0
  switch (prop_id)
80
0
    {
81
0
    case PROP_PKCS11_URI:
82
0
    case PROP_PRIVATE_KEY_PKCS11_URI:
83
      /* Subclasses must override this property but this allows older backends to not fatally error */
84
0
      g_value_set_static_string (value, NULL);
85
0
      break;
86
0
    default:
87
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
88
0
    }
89
0
}
90
91
static void
92
g_tls_certificate_set_property (GObject      *object,
93
        guint         prop_id,
94
        const GValue *value,
95
        GParamSpec   *pspec)
96
0
{
97
0
  switch (prop_id)
98
0
    {
99
0
    case PROP_PKCS11_URI:
100
0
    case PROP_PRIVATE_KEY_PKCS11_URI:
101
      /* Subclasses must override this property but this allows older backends to not fatally error */
102
0
      break;
103
0
    default:
104
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
105
0
    }
106
0
}
107
108
static void
109
g_tls_certificate_class_init (GTlsCertificateClass *class)
110
0
{
111
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
112
113
0
  gobject_class->set_property = g_tls_certificate_set_property;
114
0
  gobject_class->get_property = g_tls_certificate_get_property;
115
116
  /**
117
   * GTlsCertificate:certificate:
118
   *
119
   * The DER (binary) encoded representation of the certificate.
120
   * This property and the #GTlsCertificate:certificate-pem property
121
   * represent the same data, just in different forms.
122
   *
123
   * Since: 2.28
124
   */
125
0
  g_object_class_install_property (gobject_class, PROP_CERTIFICATE,
126
0
           g_param_spec_boxed ("certificate",
127
0
                   P_("Certificate"),
128
0
                   P_("The DER representation of the certificate"),
129
0
                   G_TYPE_BYTE_ARRAY,
130
0
                   G_PARAM_READWRITE |
131
0
                   G_PARAM_CONSTRUCT_ONLY |
132
0
                   G_PARAM_STATIC_STRINGS));
133
  /**
134
   * GTlsCertificate:certificate-pem:
135
   *
136
   * The PEM (ASCII) encoded representation of the certificate.
137
   * This property and the #GTlsCertificate:certificate
138
   * property represent the same data, just in different forms.
139
   *
140
   * Since: 2.28
141
   */
142
0
  g_object_class_install_property (gobject_class, PROP_CERTIFICATE_PEM,
143
0
           g_param_spec_string ("certificate-pem",
144
0
              P_("Certificate (PEM)"),
145
0
              P_("The PEM representation of the certificate"),
146
0
              NULL,
147
0
              G_PARAM_READWRITE |
148
0
              G_PARAM_CONSTRUCT_ONLY |
149
0
              G_PARAM_STATIC_STRINGS));
150
  /**
151
   * GTlsCertificate:private-key:
152
   *
153
   * The DER (binary) encoded representation of the certificate's
154
   * private key, in either PKCS#1 format or unencrypted PKCS#8
155
   * format. This property (or the #GTlsCertificate:private-key-pem
156
   * property) can be set when constructing a key (eg, from a file),
157
   * but cannot be read.
158
   *
159
   * PKCS#8 format is supported since 2.32; earlier releases only
160
   * support PKCS#1. You can use the `openssl rsa`
161
   * tool to convert PKCS#8 keys to PKCS#1.
162
   *
163
   * Since: 2.28
164
   */
165
0
  g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY,
166
0
           g_param_spec_boxed ("private-key",
167
0
                   P_("Private key"),
168
0
                   P_("The DER representation of the certificate’s private key"),
169
0
                   G_TYPE_BYTE_ARRAY,
170
0
                   G_PARAM_WRITABLE |
171
0
                   G_PARAM_CONSTRUCT_ONLY |
172
0
                   G_PARAM_STATIC_STRINGS));
173
  /**
174
   * GTlsCertificate:private-key-pem:
175
   *
176
   * The PEM (ASCII) encoded representation of the certificate's
177
   * private key in either PKCS#1 format ("`BEGIN RSA PRIVATE
178
   * KEY`") or unencrypted PKCS#8 format ("`BEGIN
179
   * PRIVATE KEY`"). This property (or the
180
   * #GTlsCertificate:private-key property) can be set when
181
   * constructing a key (eg, from a file), but cannot be read.
182
   *
183
   * PKCS#8 format is supported since 2.32; earlier releases only
184
   * support PKCS#1. You can use the `openssl rsa`
185
   * tool to convert PKCS#8 keys to PKCS#1.
186
   *
187
   * Since: 2.28
188
   */
189
0
  g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY_PEM,
190
0
           g_param_spec_string ("private-key-pem",
191
0
              P_("Private key (PEM)"),
192
0
              P_("The PEM representation of the certificate’s private key"),
193
0
              NULL,
194
0
              G_PARAM_WRITABLE |
195
0
              G_PARAM_CONSTRUCT_ONLY |
196
0
              G_PARAM_STATIC_STRINGS));
197
  /**
198
   * GTlsCertificate:issuer:
199
   *
200
   * A #GTlsCertificate representing the entity that issued this
201
   * certificate. If %NULL, this means that the certificate is either
202
   * self-signed, or else the certificate of the issuer is not
203
   * available.
204
   *
205
   * Since: 2.28
206
   */
207
0
  g_object_class_install_property (gobject_class, PROP_ISSUER,
208
0
           g_param_spec_object ("issuer",
209
0
              P_("Issuer"),
210
0
              P_("The certificate for the issuing entity"),
211
0
              G_TYPE_TLS_CERTIFICATE,
212
0
              G_PARAM_READWRITE |
213
0
              G_PARAM_CONSTRUCT_ONLY |
214
0
              G_PARAM_STATIC_STRINGS));
215
216
  /**
217
   * GTlsCertificate:pkcs11-uri: (nullable)
218
   *
219
   * A URI referencing the PKCS \#11 objects containing an X.509 certificate
220
   * and optionally a private key.
221
   *
222
   * If %NULL the certificate is either not backed by PKCS \#11 or the
223
   * #GTlsBackend does not support PKCS \#11.
224
   *
225
   * Since: 2.68
226
   */
227
0
  g_object_class_install_property (gobject_class, PROP_PKCS11_URI,
228
0
                                   g_param_spec_string ("pkcs11-uri",
229
0
                                                        P_("PKCS #11 URI"),
230
0
                                                        P_("The PKCS #11 URI"),
231
0
                                                        NULL,
232
0
                                                        G_PARAM_READWRITE |
233
0
                                                          G_PARAM_CONSTRUCT_ONLY |
234
0
                                                          G_PARAM_STATIC_STRINGS));
235
236
  /**
237
   * GTlsCertificate:private-key-pkcs11-uri: (nullable)
238
   *
239
   * A URI referencing a PKCS \#11 object containing a private key.
240
   *
241
   * Since: 2.68
242
   */
243
0
  g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY_PKCS11_URI,
244
0
                                   g_param_spec_string ("private-key-pkcs11-uri",
245
0
                                                        P_("PKCS #11 URI"),
246
0
                                                        P_("The PKCS #11 URI for a private key"),
247
0
                                                        NULL,
248
0
                                                        G_PARAM_READWRITE |
249
0
                                                          G_PARAM_CONSTRUCT_ONLY |
250
0
                                                          G_PARAM_STATIC_STRINGS));
251
0
}
252
253
static GTlsCertificate *
254
g_tls_certificate_new_internal (const gchar      *certificate_pem,
255
        const gchar      *private_key_pem,
256
        GTlsCertificate  *issuer,
257
        GError          **error)
258
0
{
259
0
  GObject *cert;
260
0
  GTlsBackend *backend;
261
262
0
  backend = g_tls_backend_get_default ();
263
264
0
  cert = g_initable_new (g_tls_backend_get_certificate_type (backend),
265
0
       NULL, error,
266
0
       "certificate-pem", certificate_pem,
267
0
       "private-key-pem", private_key_pem,
268
0
       "issuer", issuer,
269
0
       NULL);
270
271
0
  return G_TLS_CERTIFICATE (cert);
272
0
}
273
274
0
#define PEM_CERTIFICATE_HEADER     "-----BEGIN CERTIFICATE-----"
275
0
#define PEM_CERTIFICATE_FOOTER     "-----END CERTIFICATE-----"
276
0
#define PEM_PRIVKEY_HEADER_BEGIN   "-----BEGIN "
277
0
#define PEM_PRIVKEY_HEADER_END     "PRIVATE KEY-----"
278
0
#define PEM_PRIVKEY_FOOTER_BEGIN   "-----END "
279
0
#define PEM_PRIVKEY_FOOTER_END     "PRIVATE KEY-----"
280
0
#define PEM_PKCS8_ENCRYPTED_HEADER "-----BEGIN ENCRYPTED PRIVATE KEY-----"
281
282
static gchar *
283
parse_private_key (const gchar *data,
284
       gsize data_len,
285
       gboolean required,
286
       GError **error)
287
0
{
288
0
  const gchar *header_start = NULL, *header_end, *footer_start = NULL, *footer_end;
289
0
  const gchar *data_end = data + data_len;
290
291
0
  header_end = g_strstr_len (data, data_len, PEM_PRIVKEY_HEADER_END);
292
0
  if (header_end)
293
0
    header_start = g_strrstr_len (data, header_end - data, PEM_PRIVKEY_HEADER_BEGIN);
294
295
0
  if (!header_start)
296
0
    {
297
0
      if (required)
298
0
  g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
299
0
           _("No PEM-encoded private key found"));
300
301
0
      return NULL;
302
0
    }
303
304
0
  header_end += strlen (PEM_PRIVKEY_HEADER_END);
305
306
0
  if (strncmp (header_start, PEM_PKCS8_ENCRYPTED_HEADER, header_end - header_start) == 0)
307
0
    {
308
0
      g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
309
0
         _("Cannot decrypt PEM-encoded private key"));
310
0
      return NULL;
311
0
    }
312
313
0
  footer_end = g_strstr_len (header_end, data_len - (header_end - data), PEM_PRIVKEY_FOOTER_END);
314
0
  if (footer_end)
315
0
    footer_start = g_strrstr_len (header_end, footer_end - header_end, PEM_PRIVKEY_FOOTER_BEGIN);
316
317
0
  if (!footer_start)
318
0
    {
319
0
      g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
320
0
         _("Could not parse PEM-encoded private key"));
321
0
      return NULL;
322
0
    }
323
324
0
  footer_end += strlen (PEM_PRIVKEY_FOOTER_END);
325
326
0
  while ((footer_end < data_end) && (*footer_end == '\r' || *footer_end == '\n'))
327
0
    footer_end++;
328
329
0
  return g_strndup (header_start, footer_end - header_start);
330
0
}
331
332
333
static gchar *
334
parse_next_pem_certificate (const gchar **data,
335
          const gchar  *data_end,
336
          gboolean      required,
337
          GError      **error)
338
0
{
339
0
  const gchar *start, *end;
340
341
0
  start = g_strstr_len (*data, data_end - *data, PEM_CERTIFICATE_HEADER);
342
0
  if (!start)
343
0
    {
344
0
      if (required)
345
0
  {
346
0
    g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
347
0
             _("No PEM-encoded certificate found"));
348
0
  }
349
0
      return NULL;
350
0
    }
351
352
0
  end = g_strstr_len (start, data_end - start, PEM_CERTIFICATE_FOOTER);
353
0
  if (!end)
354
0
    {
355
0
      g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
356
0
         _("Could not parse PEM-encoded certificate"));
357
0
      return NULL;
358
0
    }
359
0
  end += strlen (PEM_CERTIFICATE_FOOTER);
360
0
  while ((end < data_end) && (*end == '\r' || *end == '\n'))
361
0
    end++;
362
363
0
  *data = end;
364
365
0
  return g_strndup (start, end - start);
366
0
}
367
368
static GSList *
369
parse_and_create_certificate_list (const gchar  *data,
370
                                   gsize         data_len,
371
                                   GError      **error)
372
0
{
373
0
  GSList *first_pem_list = NULL, *pem_list = NULL;
374
0
  gchar *first_pem;
375
0
  const gchar *p, *end;
376
377
0
  p = data;
378
0
  end = p + data_len;
379
380
  /* Make sure we can load, at least, one certificate. */
381
0
  first_pem = parse_next_pem_certificate (&p, end, TRUE, error);
382
0
  if (!first_pem)
383
0
    return NULL;
384
385
  /* Create a list with a single element. If we load more certificates
386
   * below, we will concatenate the two lists at the end. */
387
0
  first_pem_list = g_slist_prepend (first_pem_list, first_pem);
388
389
  /* If we read one certificate successfully, let's see if we can read
390
   * some more. If not, we will simply return a list with the first one.
391
   */
392
0
  while (p < end && p && *p)
393
0
    {
394
0
      gchar *cert_pem;
395
0
      GError *error = NULL;
396
397
0
      cert_pem = parse_next_pem_certificate (&p, end, FALSE, &error);
398
0
      if (error)
399
0
        {
400
0
          g_slist_free_full (pem_list, g_free);
401
0
          g_error_free (error);
402
0
          return first_pem_list;
403
0
        }
404
0
      else if (!cert_pem)
405
0
        {
406
0
          break;
407
0
        }
408
409
0
      pem_list = g_slist_prepend (pem_list, cert_pem);
410
0
    }
411
412
0
  pem_list = g_slist_concat (pem_list, first_pem_list);
413
414
0
  return pem_list;
415
0
}
416
417
static GTlsCertificate *
418
create_certificate_chain_from_list (GSList       *pem_list,
419
                                    const gchar  *key_pem)
420
0
{
421
0
  GTlsCertificate *cert = NULL, *issuer = NULL, *root = NULL;
422
0
  GTlsCertificateFlags flags;
423
0
  GSList *pem;
424
425
0
  pem = pem_list;
426
0
  while (pem)
427
0
    {
428
0
      const gchar *key = NULL;
429
430
      /* Private key belongs only to the first certificate. */
431
0
      if (!pem->next)
432
0
        key = key_pem;
433
434
      /* We assume that the whole file is a certificate chain, so we use
435
       * each certificate as the issuer of the next one (list is in
436
       * reverse order).
437
       */
438
0
      issuer = cert;
439
0
      cert = g_tls_certificate_new_internal (pem->data, key, issuer, NULL);
440
0
      if (issuer)
441
0
        g_object_unref (issuer);
442
443
0
      if (!cert)
444
0
        return NULL;
445
446
      /* root will point to the last certificate in the file. */
447
0
      if (!root)
448
0
        root = cert;
449
450
0
      pem = g_slist_next (pem);
451
0
    }
452
453
  /* Verify that the certificates form a chain. (We don't care at this
454
   * point if there are other problems with it.)
455
   */
456
0
  flags = g_tls_certificate_verify (cert, NULL, root);
457
0
  if (flags & G_TLS_CERTIFICATE_UNKNOWN_CA)
458
0
    {
459
      /* It wasn't a chain, it's just a bunch of unrelated certs. */
460
0
      g_clear_object (&cert);
461
0
    }
462
463
0
  return cert;
464
0
}
465
466
static GTlsCertificate *
467
parse_and_create_certificate (const gchar  *data,
468
                              gsize         data_len,
469
                              const gchar  *key_pem,
470
                              GError      **error)
471
472
0
{
473
0
  GSList *pem_list;
474
0
  GTlsCertificate *cert;
475
476
0
  pem_list = parse_and_create_certificate_list (data, data_len, error);
477
0
  if (!pem_list)
478
0
    return NULL;
479
480
  /* We don't pass the error here because, if it fails, we still want to
481
   * load and return the first certificate.
482
   */
483
0
  cert = create_certificate_chain_from_list (pem_list, key_pem);
484
0
  if (!cert)
485
0
    {
486
0
      GSList *last = NULL;
487
488
      /* Get the first certificate (which is the last one as the list is
489
       * in reverse order).
490
       */
491
0
      last = g_slist_last (pem_list);
492
493
0
      cert = g_tls_certificate_new_internal (last->data, key_pem, NULL, error);
494
0
    }
495
496
0
  g_slist_free_full (pem_list, g_free);
497
498
0
  return cert;
499
0
}
500
501
/**
502
 * g_tls_certificate_new_from_pem:
503
 * @data: PEM-encoded certificate data
504
 * @length: the length of @data, or -1 if it's 0-terminated.
505
 * @error: #GError for error reporting, or %NULL to ignore.
506
 *
507
 * Creates a #GTlsCertificate from the PEM-encoded data in @data. If
508
 * @data includes both a certificate and a private key, then the
509
 * returned certificate will include the private key data as well. (See
510
 * the #GTlsCertificate:private-key-pem property for information about
511
 * supported formats.)
512
 *
513
 * The returned certificate will be the first certificate found in
514
 * @data. As of GLib 2.44, if @data contains more certificates it will
515
 * try to load a certificate chain. All certificates will be verified in
516
 * the order found (top-level certificate should be the last one in the
517
 * file) and the #GTlsCertificate:issuer property of each certificate
518
 * will be set accordingly if the verification succeeds. If any
519
 * certificate in the chain cannot be verified, the first certificate in
520
 * the file will still be returned.
521
 *
522
 * Returns: the new certificate, or %NULL if @data is invalid
523
 *
524
 * Since: 2.28
525
 */
526
GTlsCertificate *
527
g_tls_certificate_new_from_pem  (const gchar  *data,
528
         gssize        length,
529
         GError      **error)
530
0
{
531
0
  GError *child_error = NULL;
532
0
  gchar *key_pem;
533
0
  GTlsCertificate *cert;
534
535
0
  g_return_val_if_fail (data != NULL, NULL);
536
0
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
537
538
0
  if (length == -1)
539
0
    length = strlen (data);
540
541
0
  key_pem = parse_private_key (data, length, FALSE, &child_error);
542
0
  if (child_error != NULL)
543
0
    {
544
0
      g_propagate_error (error, child_error);
545
0
      return NULL;
546
0
    }
547
548
0
  cert = parse_and_create_certificate (data, length, key_pem, error);
549
0
  g_free (key_pem);
550
551
0
  return cert;
552
0
}
553
554
/**
555
 * g_tls_certificate_new_from_file:
556
 * @file: (type filename): file containing a PEM-encoded certificate to import
557
 * @error: #GError for error reporting, or %NULL to ignore.
558
 *
559
 * Creates a #GTlsCertificate from the PEM-encoded data in @file. The
560
 * returned certificate will be the first certificate found in @file. As
561
 * of GLib 2.44, if @file contains more certificates it will try to load
562
 * a certificate chain. All certificates will be verified in the order
563
 * found (top-level certificate should be the last one in the file) and
564
 * the #GTlsCertificate:issuer property of each certificate will be set
565
 * accordingly if the verification succeeds. If any certificate in the
566
 * chain cannot be verified, the first certificate in the file will
567
 * still be returned.
568
 *
569
 * If @file cannot be read or parsed, the function will return %NULL and
570
 * set @error. Otherwise, this behaves like
571
 * g_tls_certificate_new_from_pem().
572
 *
573
 * Returns: the new certificate, or %NULL on error
574
 *
575
 * Since: 2.28
576
 */
577
GTlsCertificate *
578
g_tls_certificate_new_from_file (const gchar  *file,
579
         GError      **error)
580
0
{
581
0
  GTlsCertificate *cert;
582
0
  gchar *contents;
583
0
  gsize length;
584
585
0
  if (!g_file_get_contents (file, &contents, &length, error))
586
0
    return NULL;
587
588
0
  cert = g_tls_certificate_new_from_pem (contents, length, error);
589
0
  g_free (contents);
590
0
  return cert;
591
0
}
592
593
/**
594
 * g_tls_certificate_new_from_files:
595
 * @cert_file: (type filename): file containing one or more PEM-encoded
596
 *     certificates to import
597
 * @key_file: (type filename): file containing a PEM-encoded private key
598
 *     to import
599
 * @error: #GError for error reporting, or %NULL to ignore.
600
 *
601
 * Creates a #GTlsCertificate from the PEM-encoded data in @cert_file
602
 * and @key_file. The returned certificate will be the first certificate
603
 * found in @cert_file. As of GLib 2.44, if @cert_file contains more
604
 * certificates it will try to load a certificate chain. All
605
 * certificates will be verified in the order found (top-level
606
 * certificate should be the last one in the file) and the
607
 * #GTlsCertificate:issuer property of each certificate will be set
608
 * accordingly if the verification succeeds. If any certificate in the
609
 * chain cannot be verified, the first certificate in the file will
610
 * still be returned.
611
 *
612
 * If either file cannot be read or parsed, the function will return
613
 * %NULL and set @error. Otherwise, this behaves like
614
 * g_tls_certificate_new_from_pem().
615
 *
616
 * Returns: the new certificate, or %NULL on error
617
 *
618
 * Since: 2.28
619
 */
620
GTlsCertificate *
621
g_tls_certificate_new_from_files (const gchar  *cert_file,
622
                                  const gchar  *key_file,
623
                                  GError      **error)
624
0
{
625
0
  GTlsCertificate *cert;
626
0
  gchar *cert_data, *key_data;
627
0
  gsize cert_len, key_len;
628
0
  gchar *key_pem;
629
630
0
  if (!g_file_get_contents (key_file, &key_data, &key_len, error))
631
0
    return NULL;
632
633
0
  key_pem = parse_private_key (key_data, key_len, TRUE, error);
634
0
  g_free (key_data);
635
0
  if (!key_pem)
636
0
    return NULL;
637
638
0
  if (!g_file_get_contents (cert_file, &cert_data, &cert_len, error))
639
0
    {
640
0
      g_free (key_pem);
641
0
      return NULL;
642
0
    }
643
644
0
  cert = parse_and_create_certificate (cert_data, cert_len, key_pem, error);
645
0
  g_free (cert_data);
646
0
  g_free (key_pem);
647
0
  return cert;
648
0
}
649
650
/**
651
 * g_tls_certificate_new_from_pkcs11_uris:
652
 * @pkcs11_uri: A PKCS \#11 URI
653
 * @private_key_pkcs11_uri: (nullable): A PKCS \#11 URI
654
 * @error: #GError for error reporting, or %NULL to ignore.
655
 *
656
 * Creates a #GTlsCertificate from a PKCS \#11 URI.
657
 *
658
 * An example @pkcs11_uri would be `pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01`
659
 *
660
 * Where the token’s layout is:
661
 *
662
 * ```
663
 * Object 0:
664
 *   URL: pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01;object=private%20key;type=private
665
 *   Type: Private key (RSA-2048)
666
 *   ID: 01
667
 *
668
 * Object 1:
669
 *   URL: pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01;object=Certificate%20for%20Authentication;type=cert
670
 *   Type: X.509 Certificate (RSA-2048)
671
 *   ID: 01
672
 * ```
673
 *
674
 * In this case the certificate and private key would both be detected and used as expected.
675
 * @pkcs_uri may also just reference an X.509 certificate object and then optionally
676
 * @private_key_pkcs11_uri allows using a private key exposed under a different URI.
677
 *
678
 * Note that the private key is not accessed until usage and may fail or require a PIN later.
679
 *
680
 * Returns: (transfer full): the new certificate, or %NULL on error
681
 *
682
 * Since: 2.68
683
 */
684
GTlsCertificate *
685
g_tls_certificate_new_from_pkcs11_uris (const gchar  *pkcs11_uri,
686
                                        const gchar  *private_key_pkcs11_uri,
687
                                        GError      **error)
688
0
{
689
0
  GObject *cert;
690
0
  GTlsBackend *backend;
691
692
0
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
693
0
  g_return_val_if_fail (pkcs11_uri, NULL);
694
695
0
  backend = g_tls_backend_get_default ();
696
697
0
  cert = g_initable_new (g_tls_backend_get_certificate_type (backend),
698
0
                         NULL, error,
699
0
                         "pkcs11-uri", pkcs11_uri,
700
0
                         "private-key-pkcs11-uri", private_key_pkcs11_uri,
701
0
                         NULL);
702
703
0
  if (cert != NULL)
704
0
    {
705
0
      gchar *objects_uri;
706
707
      /* Old implementations might not override this property */
708
0
      g_object_get (cert, "pkcs11-uri", &objects_uri, NULL);
709
0
      if (objects_uri == NULL)
710
0
        {
711
0
          g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("This GTlsBackend does not support creating PKCS #11 certificates"));
712
0
          g_object_unref (cert);
713
0
          return NULL;
714
0
        }
715
0
      g_free (objects_uri);
716
0
    }
717
718
0
  return G_TLS_CERTIFICATE (cert);
719
0
}
720
721
/**
722
 * g_tls_certificate_list_new_from_file:
723
 * @file: (type filename): file containing PEM-encoded certificates to import
724
 * @error: #GError for error reporting, or %NULL to ignore.
725
 *
726
 * Creates one or more #GTlsCertificates from the PEM-encoded
727
 * data in @file. If @file cannot be read or parsed, the function will
728
 * return %NULL and set @error. If @file does not contain any
729
 * PEM-encoded certificates, this will return an empty list and not
730
 * set @error.
731
 *
732
 * Returns: (element-type Gio.TlsCertificate) (transfer full): a
733
 * #GList containing #GTlsCertificate objects. You must free the list
734
 * and its contents when you are done with it.
735
 *
736
 * Since: 2.28
737
 */
738
GList *
739
g_tls_certificate_list_new_from_file (const gchar  *file,
740
              GError      **error)
741
0
{
742
0
  GQueue queue = G_QUEUE_INIT;
743
0
  gchar *contents, *end;
744
0
  const gchar *p;
745
0
  gsize length;
746
747
0
  if (!g_file_get_contents (file, &contents, &length, error))
748
0
    return NULL;
749
750
0
  end = contents + length;
751
0
  p = contents;
752
0
  while (p && *p)
753
0
    {
754
0
      gchar *cert_pem;
755
0
      GTlsCertificate *cert = NULL;
756
0
      GError *parse_error = NULL;
757
758
0
      cert_pem = parse_next_pem_certificate (&p, end, FALSE, &parse_error);
759
0
      if (cert_pem)
760
0
        {
761
0
          cert = g_tls_certificate_new_internal (cert_pem, NULL, NULL, &parse_error);
762
0
          g_free (cert_pem);
763
0
        }
764
0
      if (!cert)
765
0
        {
766
0
          if (parse_error)
767
0
            {
768
0
              g_propagate_error (error, parse_error);
769
0
              g_list_free_full (queue.head, g_object_unref);
770
0
              queue.head = NULL;
771
0
            }
772
0
          break;
773
0
        }
774
0
      g_queue_push_tail (&queue, cert);
775
0
    }
776
777
0
  g_free (contents);
778
0
  return queue.head;
779
0
}
780
781
782
/**
783
 * g_tls_certificate_get_issuer:
784
 * @cert: a #GTlsCertificate
785
 *
786
 * Gets the #GTlsCertificate representing @cert's issuer, if known
787
 *
788
 * Returns: (nullable) (transfer none): The certificate of @cert's issuer,
789
 * or %NULL if @cert is self-signed or signed with an unknown
790
 * certificate.
791
 *
792
 * Since: 2.28
793
 */
794
GTlsCertificate *
795
g_tls_certificate_get_issuer (GTlsCertificate  *cert)
796
0
{
797
0
  GTlsCertificate *issuer;
798
799
0
  g_object_get (G_OBJECT (cert), "issuer", &issuer, NULL);
800
0
  if (issuer)
801
0
    g_object_unref (issuer);
802
803
0
  return issuer;
804
0
}
805
806
/**
807
 * g_tls_certificate_verify:
808
 * @cert: a #GTlsCertificate
809
 * @identity: (nullable): the expected peer identity
810
 * @trusted_ca: (nullable): the certificate of a trusted authority
811
 *
812
 * This verifies @cert and returns a set of #GTlsCertificateFlags
813
 * indicating any problems found with it. This can be used to verify a
814
 * certificate outside the context of making a connection, or to
815
 * check a certificate against a CA that is not part of the system
816
 * CA database.
817
 *
818
 * If @identity is not %NULL, @cert's name(s) will be compared against
819
 * it, and %G_TLS_CERTIFICATE_BAD_IDENTITY will be set in the return
820
 * value if it does not match. If @identity is %NULL, that bit will
821
 * never be set in the return value.
822
 *
823
 * If @trusted_ca is not %NULL, then @cert (or one of the certificates
824
 * in its chain) must be signed by it, or else
825
 * %G_TLS_CERTIFICATE_UNKNOWN_CA will be set in the return value. If
826
 * @trusted_ca is %NULL, that bit will never be set in the return
827
 * value.
828
 *
829
 * (All other #GTlsCertificateFlags values will always be set or unset
830
 * as appropriate.)
831
 *
832
 * Returns: the appropriate #GTlsCertificateFlags
833
 *
834
 * Since: 2.28
835
 */
836
GTlsCertificateFlags
837
g_tls_certificate_verify (GTlsCertificate     *cert,
838
        GSocketConnectable  *identity,
839
        GTlsCertificate     *trusted_ca)
840
0
{
841
0
  return G_TLS_CERTIFICATE_GET_CLASS (cert)->verify (cert, identity, trusted_ca);
842
0
}
843
844
/**
845
 * g_tls_certificate_is_same:
846
 * @cert_one: first certificate to compare
847
 * @cert_two: second certificate to compare
848
 *
849
 * Check if two #GTlsCertificate objects represent the same certificate.
850
 * The raw DER byte data of the two certificates are checked for equality.
851
 * This has the effect that two certificates may compare equal even if
852
 * their #GTlsCertificate:issuer, #GTlsCertificate:private-key, or
853
 * #GTlsCertificate:private-key-pem properties differ.
854
 *
855
 * Returns: whether the same or not
856
 *
857
 * Since: 2.34
858
 */
859
gboolean
860
g_tls_certificate_is_same (GTlsCertificate     *cert_one,
861
                           GTlsCertificate     *cert_two)
862
0
{
863
0
  GByteArray *b1, *b2;
864
0
  gboolean equal;
865
866
0
  g_return_val_if_fail (G_IS_TLS_CERTIFICATE (cert_one), FALSE);
867
0
  g_return_val_if_fail (G_IS_TLS_CERTIFICATE (cert_two), FALSE);
868
869
0
  g_object_get (cert_one, "certificate", &b1, NULL);
870
0
  g_object_get (cert_two, "certificate", &b2, NULL);
871
872
0
  equal = (b1->len == b2->len &&
873
0
           memcmp (b1->data, b2->data, b1->len) == 0);
874
875
0
  g_byte_array_unref (b1);
876
0
  g_byte_array_unref (b2);
877
878
0
  return equal;
879
0
}