LCOV - code coverage report
Current view: top level - src/libvalent/device - valent-certificate.c (source / functions) Coverage Total Hit
Test: Code Coverage Lines: 83.9 % 161 135
Test Date: 2025-04-25 03:07:01 Functions: 100.0 % 7 7
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 51.6 % 124 64

             Branch data     Line data    Source code
       1                 :             : // SPDX-License-Identifier: GPL-3.0-or-later
       2                 :             : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
       3                 :             : 
       4                 :             : #define G_LOG_DOMAIN "valent-certificate"
       5                 :             : 
       6                 :             : #include "config.h"
       7                 :             : 
       8                 :             : #include <time.h>
       9                 :             : 
      10                 :             : #include <gio/gio.h>
      11                 :             : #include <gnutls/gnutls.h>
      12                 :             : #include <gnutls/abstract.h>
      13                 :             : #include <gnutls/crypto.h>
      14                 :             : #include <gnutls/x509.h>
      15                 :             : 
      16                 :             : #include <libvalent-core.h>
      17                 :             : #include "valent-certificate.h"
      18                 :             : #include "valent-device.h"
      19                 :             : 
      20                 :             : #define ACTIVATION_TIMESPAN (60L*60L*24L*365L)
      21                 :             : #define EXPIRATION_TIMESPAN (60L*60L*24L*10L*365L)
      22                 :             : 
      23                 :             : /* < private >
      24                 :             :  * valent_certificate_generate:
      25                 :             :  * @common_name: common name for the certificate
      26                 :             :  * @error: (nullable): a `GError`
      27                 :             :  *
      28                 :             :  * Generate a private key and certificate for @common_name, saving them at
      29                 :             :  * @key_path and @cert_path respectively.
      30                 :             :  *
      31                 :             :  * Returns: (transfer full) (nullable): a new certificate,
      32                 :             :  *   or %NULL with @error set
      33                 :             :  */
      34                 :             : GTlsCertificate *
      35                 :         202 : valent_certificate_generate (const char  *common_name,
      36                 :             :                              GError     **error)
      37                 :             : {
      38                 :         202 :   gnutls_x509_crt_t crt = NULL;
      39                 :         202 :   gnutls_x509_privkey_t privkey = NULL;
      40                 :         202 :   gnutls_datum_t crt_out = { 0, };
      41                 :         202 :   gnutls_datum_t privkey_out = { 0, };
      42                 :         404 :   g_autofree char *dn = NULL;
      43                 :         202 :   time_t now;
      44                 :         202 :   unsigned char serial[20];
      45                 :         202 :   int rc;
      46                 :         202 :   char *combined_data = NULL;
      47                 :         202 :   size_t combined_size = 0;
      48                 :         202 :   GTlsCertificate *ret = NULL;
      49                 :             : 
      50                 :         202 :   VALENT_ENTRY;
      51                 :             : 
      52         [ -  + ]:         202 :   g_assert (common_name != NULL);
      53                 :             : 
      54                 :             :   /* The private key is a 256-bit ECC key. This is `NID_X9_62_prime256v1` in
      55                 :             :    * OpenSSL and `GNUTLS_ECC_CURVE_SECP256R1` in GnuTLS.
      56                 :             :    */
      57         [ +  - ]:         202 :   if ((rc = gnutls_x509_privkey_init (&privkey)) != GNUTLS_E_SUCCESS ||
      58         [ +  - ]:         202 :       (rc = gnutls_x509_privkey_generate (privkey,
      59                 :             :                                           GNUTLS_PK_ECDSA,
      60                 :             :                                           GNUTLS_CURVE_TO_BITS (GNUTLS_ECC_CURVE_SECP256R1),
      61                 :         202 :                                           0)) != GNUTLS_E_SUCCESS ||
      62         [ -  + ]:         202 :       (rc = gnutls_x509_privkey_export2 (privkey,
      63                 :             :                                          GNUTLS_X509_FMT_PEM,
      64                 :             :                                          &privkey_out)) != GNUTLS_E_SUCCESS)
      65                 :             :     {
      66                 :           0 :       g_set_error (error,
      67                 :             :                    G_IO_ERROR,
      68                 :             :                    G_IO_ERROR_FAILED,
      69                 :             :                    "Generating private key: %s",
      70                 :             :                    gnutls_strerror (rc));
      71                 :           0 :       VALENT_GOTO (out);
      72                 :             :     }
      73                 :             : 
      74         [ +  - ]:         202 :   if ((rc = gnutls_x509_crt_init (&crt)) != GNUTLS_E_SUCCESS ||
      75         [ +  - ]:         202 :       (rc = gnutls_x509_crt_set_key (crt, privkey)) != GNUTLS_E_SUCCESS ||
      76         [ -  + ]:         202 :       (rc = gnutls_x509_crt_set_version (crt, 3)) != GNUTLS_E_SUCCESS)
      77                 :             :     {
      78                 :           0 :       g_set_error (error,
      79                 :             :                    G_IO_ERROR,
      80                 :             :                    G_IO_ERROR_FAILED,
      81                 :             :                    "Generating certificate: %s",
      82                 :             :                    gnutls_strerror (rc));
      83                 :           0 :       VALENT_GOTO (out);
      84                 :             :     }
      85                 :             : 
      86                 :             :   /* The certificate is set to be activated 1 year in the past, with an
      87                 :             :    * expiration date 10 years in the future.
      88                 :             :    */
      89                 :         202 :   now = time (NULL);
      90         [ +  - ]:         202 :   if ((rc = gnutls_x509_crt_set_activation_time (crt, now - ACTIVATION_TIMESPAN)) != GNUTLS_E_SUCCESS ||
      91         [ -  + ]:         202 :       (rc = gnutls_x509_crt_set_expiration_time (crt, now + EXPIRATION_TIMESPAN)) != GNUTLS_E_SUCCESS)
      92                 :             :     {
      93                 :           0 :       g_set_error (error,
      94                 :             :                    G_IO_ERROR,
      95                 :             :                    G_IO_ERROR_FAILED,
      96                 :             :                    "Setting certificate activation and expiration: %s",
      97                 :             :                    gnutls_strerror (rc));
      98                 :           0 :       VALENT_GOTO (out);
      99                 :             :     }
     100                 :             : 
     101                 :             :   /* While kdeconnect-android uses the static serial `1`, kdeconnect-kde uses
     102                 :             :    * a randomized serial, which presumably has some obscure security benefit.
     103                 :             :    */
     104         [ +  - ]:         202 :   if ((rc = gnutls_rnd (GNUTLS_RND_RANDOM, serial, sizeof (serial))) != GNUTLS_E_SUCCESS ||
     105         [ -  + ]:         202 :       (rc = gnutls_x509_crt_set_serial (crt, &serial, sizeof (serial))) != GNUTLS_E_SUCCESS)
     106                 :             :     {
     107                 :           0 :       g_set_error (error,
     108                 :             :                    G_IO_ERROR,
     109                 :             :                    G_IO_ERROR_FAILED,
     110                 :             :                    "Setting certificate serial: %s",
     111                 :             :                    gnutls_strerror (rc));
     112                 :           0 :       VALENT_GOTO (out);
     113                 :             :     }
     114                 :             : 
     115                 :             :   /* KDE Connect sets this to `O=KDE,OU=KDE Connect,CN=<device-id>`, where
     116                 :             :    * `<device-id>` matches the pattern `/^[a-zA-Z0-9_]{32,38}$/`.
     117                 :             :    */
     118                 :         202 :   dn = g_strdup_printf ("O=%s,OU=%s,CN=%s", "Valent", "Valent", common_name);
     119         [ -  + ]:         202 :   if ((rc = gnutls_x509_crt_set_dn (crt, dn, NULL)) != GNUTLS_E_SUCCESS)
     120                 :             :     {
     121                 :           0 :       g_set_error (error,
     122                 :             :                    G_IO_ERROR,
     123                 :             :                    G_IO_ERROR_FAILED,
     124                 :             :                    "Setting certificate common name: %s",
     125                 :             :                    gnutls_strerror (rc));
     126                 :           0 :       VALENT_GOTO (out);
     127                 :             :     }
     128                 :             : 
     129                 :             :   /* The signature is a 512-bit SHA512 with ECDSA. This is `EVP_sha512` in
     130                 :             :    * OpenSSL and `GNUTLS_DIG_SHA512` in GnuTLS.
     131                 :             :    */
     132         [ +  - ]:         202 :   if ((rc = gnutls_x509_crt_sign2 (crt, crt, privkey, GNUTLS_DIG_SHA512, 0)) != GNUTLS_E_SUCCESS ||
     133         [ -  + ]:         202 :       (rc = gnutls_x509_crt_export2 (crt, GNUTLS_X509_FMT_PEM, &crt_out)) != GNUTLS_E_SUCCESS)
     134                 :             :     {
     135                 :           0 :       g_set_error (error,
     136                 :             :                    G_IO_ERROR,
     137                 :             :                    G_IO_ERROR_FAILED,
     138                 :             :                    "Signing certificate: %s",
     139                 :             :                    gnutls_strerror (rc));
     140                 :           0 :       VALENT_GOTO (out);
     141                 :             :     }
     142                 :             : 
     143                 :             :   /* Concatenate Private Key and Certificate
     144                 :             :    */
     145                 :         202 :   combined_size = privkey_out.size + crt_out.size;
     146                 :         202 :   combined_data = g_malloc0 (combined_size + 1);
     147                 :         202 :   memcpy (combined_data, privkey_out.data, privkey_out.size);
     148                 :         202 :   memcpy (combined_data + privkey_out.size, crt_out.data, crt_out.size);
     149                 :             : 
     150                 :         202 :   ret = g_tls_certificate_new_from_pem (combined_data,
     151                 :             :                                         combined_size,
     152                 :             :                                         error);
     153                 :             : 
     154                 :         202 : out:
     155         [ +  - ]:         202 :   g_clear_pointer (&crt, gnutls_x509_crt_deinit);
     156         [ +  - ]:         202 :   g_clear_pointer (&privkey, gnutls_x509_privkey_deinit);
     157         [ +  - ]:         202 :   g_clear_pointer (&crt_out.data, gnutls_free);
     158         [ +  - ]:         202 :   g_clear_pointer (&privkey_out.data, gnutls_free);
     159         [ +  - ]:         202 :   g_clear_pointer (&combined_data, g_free);
     160                 :             : 
     161                 :         202 :   VALENT_RETURN (ret);
     162                 :             : }
     163                 :             : 
     164                 :             : static void
     165                 :           3 : valent_certificate_new_task (GTask        *task,
     166                 :             :                              gpointer      source_object,
     167                 :             :                              gpointer      task_data,
     168                 :             :                              GCancellable *cancellable)
     169                 :             : {
     170                 :           3 :   g_autoptr (GTlsCertificate) certificate = NULL;
     171                 :           3 :   const char *path = task_data;
     172                 :           3 :   GError *error = NULL;
     173                 :             : 
     174                 :           3 :   certificate = valent_certificate_new_sync (path, &error);
     175         [ -  + ]:           3 :   if (certificate == NULL)
     176                 :             :     {
     177                 :           0 :       g_task_return_error (task, error);
     178                 :           0 :       return;
     179                 :             :     }
     180                 :             : 
     181                 :           3 :   g_task_return_pointer (task, g_steal_pointer (&certificate), g_object_unref);
     182                 :             : }
     183                 :             : 
     184                 :             : /**
     185                 :             :  * valent_certificate_new:
     186                 :             :  * @path: (type filename) (nullable): a directory path
     187                 :             :  * @cancellable: (nullable): `GCancellable`
     188                 :             :  * @callback: (scope async): a `GAsyncReadyCallback`
     189                 :             :  * @user_data: user supplied data
     190                 :             :  *
     191                 :             :  * Get a TLS certificate and private key pair.
     192                 :             :  *
     193                 :             :  * If @path is given, this function ensures a TLS certificate with the filename
     194                 :             :  * `certificate.pem` and private key with filename `private.pem` exist in a
     195                 :             :  * directory at @path.
     196                 :             :  *
     197                 :             :  * Get the result with [func@Valent.certificate_new_finish].
     198                 :             :  *
     199                 :             :  * Since: 1.0
     200                 :             :  */
     201                 :             : void
     202                 :           3 : valent_certificate_new (const char          *path,
     203                 :             :                         GCancellable        *cancellable,
     204                 :             :                         GAsyncReadyCallback  callback,
     205                 :             :                         gpointer             user_data)
     206                 :             : {
     207                 :           0 :   g_autoptr (GTask) task = NULL;
     208                 :             : 
     209   [ -  +  -  -  :           3 :   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
             -  -  -  - ]
     210                 :             : 
     211                 :           3 :   task = g_task_new (NULL, cancellable, callback, user_data);
     212         [ +  - ]:           3 :   g_task_set_source_tag (task, valent_certificate_new);
     213         [ -  + ]:           6 :   g_task_set_task_data (task, g_strdup (path), g_free);
     214         [ +  - ]:           3 :   g_task_run_in_thread (task, valent_certificate_new_task);
     215                 :             : }
     216                 :             : 
     217                 :             : /**
     218                 :             :  * valent_certificate_new_finish:
     219                 :             :  * @result: a `GAsyncResult` provided to callback
     220                 :             :  * @error: (nullable): a `GError`
     221                 :             :  *
     222                 :             :  * Finish an operation started by [func@Valent.certificate_new].
     223                 :             :  *
     224                 :             :  * If either generating or loading the certificate failed, %NULL will be
     225                 :             :  * returned with @error set.
     226                 :             :  *
     227                 :             :  * Returns: (transfer full) (nullable): a `GTlsCertificate`
     228                 :             :  *
     229                 :             :  * Since: 1.0
     230                 :             :  */
     231                 :             : GTlsCertificate *
     232                 :           3 : valent_certificate_new_finish (GAsyncResult  *result,
     233                 :             :                                GError       **error)
     234                 :             : {
     235         [ -  + ]:           3 :   g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
     236                 :             : 
     237                 :           3 :   return g_task_propagate_pointer (G_TASK (result), error);
     238                 :             : }
     239                 :             : 
     240                 :             : /**
     241                 :             :  * valent_certificate_new_sync:
     242                 :             :  * @path: (type filename) (nullable): a directory path
     243                 :             :  * @error: (nullable): a `GError`
     244                 :             :  *
     245                 :             :  * Get a TLS certificate.
     246                 :             :  *
     247                 :             :  * If @path is given, this function ensures a TLS certificate with the filename
     248                 :             :  * `certificate.pem` and private key with filename `private.pem` exist in a
     249                 :             :  * directory at @path.
     250                 :             :  *
     251                 :             :  * If either generating or loading the certificate fails, %NULL will be returned
     252                 :             :  * with @error set.
     253                 :             :  *
     254                 :             :  * Returns: (transfer full) (nullable): a `GTlsCertificate`
     255                 :             :  *
     256                 :             :  * Since: 1.0
     257                 :             :  */
     258                 :             : GTlsCertificate *
     259                 :         217 : valent_certificate_new_sync (const char  *path,
     260                 :             :                              GError     **error)
     261                 :             : {
     262                 :         434 :   g_autofree char *cert_path = NULL;
     263                 :         217 :   g_autofree char *key_path = NULL;
     264                 :             : 
     265   [ +  +  -  + ]:         217 :   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
     266                 :             : 
     267         [ +  + ]:         217 :   if (path == NULL)
     268                 :             :     {
     269                 :         179 :       g_autofree char *cn = NULL;
     270                 :             : 
     271                 :         179 :       cn = valent_device_generate_id ();
     272                 :         179 :       return valent_certificate_generate (cn, error);
     273                 :             :     }
     274                 :             : 
     275                 :          38 :   cert_path = g_build_filename (path, "certificate.pem", NULL);
     276                 :          38 :   key_path = g_build_filename (path, "private.pem", NULL);
     277                 :             : 
     278   [ +  +  -  + ]:          53 :   if (!g_file_test (cert_path, G_FILE_TEST_IS_REGULAR) ||
     279                 :          15 :       !g_file_test (key_path, G_FILE_TEST_IS_REGULAR))
     280                 :             :     {
     281                 :          23 :       g_autoptr (GTlsCertificate) ret = NULL;
     282         [ -  + ]:          23 :       g_autofree char *cn = NULL;
     283                 :          23 :       g_autofree char *certificate_pem = NULL;
     284                 :          23 :       g_autofree char *private_key_pem = NULL;
     285                 :          23 :       gboolean success;
     286                 :             : 
     287                 :          23 :       cn = valent_device_generate_id ();
     288                 :          23 :       ret = valent_certificate_generate (cn, error);
     289         [ +  - ]:          23 :       if (ret == NULL)
     290                 :             :         return NULL;
     291                 :             : 
     292                 :          23 :       g_object_get (ret,
     293                 :             :                     "certificate-pem", &certificate_pem,
     294                 :             :                     "private-key-pem", &private_key_pem,
     295                 :             :                     NULL);
     296                 :             : 
     297                 :          23 :       success = g_file_set_contents_full (cert_path,
     298                 :             :                                           certificate_pem,
     299                 :             :                                           -1,
     300                 :             :                                           G_FILE_SET_CONTENTS_DURABLE,
     301                 :             :                                           0600,
     302                 :             :                                           error);
     303         [ -  + ]:          23 :       if (!success)
     304                 :             :         return NULL;
     305                 :             : 
     306                 :          23 :       success = g_file_set_contents_full (key_path,
     307                 :             :                                           private_key_pem,
     308                 :             :                                           -1,
     309                 :             :                                           G_FILE_SET_CONTENTS_DURABLE,
     310                 :             :                                           0600,
     311                 :             :                                           error);
     312         [ -  + ]:          23 :       if (!success)
     313                 :             :         return NULL;
     314                 :             : 
     315                 :             :       return g_steal_pointer (&ret);
     316                 :             :     }
     317                 :             : 
     318                 :          15 :   return g_tls_certificate_new_from_files (cert_path, key_path, error);
     319                 :             : }
     320                 :             : 
     321                 :             : /**
     322                 :             :  * valent_certificate_get_common_name:
     323                 :             :  * @certificate: a `GTlsCertificate`
     324                 :             :  *
     325                 :             :  * Get the common name from @certificate, which by convention in KDE Connect is
     326                 :             :  * the single source of truth for a device's ID.
     327                 :             :  *
     328                 :             :  * Returns: (transfer none) (nullable): the certificate ID
     329                 :             :  *
     330                 :             :  * Since: 1.0
     331                 :             :  */
     332                 :             : const char *
     333                 :         307 : valent_certificate_get_common_name (GTlsCertificate *certificate)
     334                 :             : {
     335                 :         614 :   g_autoptr (GByteArray) certificate_der = NULL;
     336                 :         307 :   gnutls_x509_crt_t crt = NULL;
     337                 :         307 :   gnutls_datum_t crt_der = { 0, };
     338                 :         307 :   char buf[64] = { 0, };
     339                 :         307 :   size_t buf_size = 64;
     340                 :         307 :   const char *cn;
     341                 :         307 :   int rc;
     342                 :             : 
     343   [ +  -  +  -  :         307 :   g_return_val_if_fail (G_IS_TLS_CERTIFICATE (certificate), NULL);
             +  -  -  + ]
     344                 :             : 
     345                 :         307 :   cn = g_object_get_data (G_OBJECT (certificate), "valent-certificate-cn");
     346         [ +  + ]:         307 :   if (cn != NULL)
     347                 :             :     return cn;
     348                 :             : 
     349                 :         222 :   g_object_get (certificate, "certificate", &certificate_der, NULL);
     350                 :         222 :   crt_der.data = certificate_der->data;
     351                 :         222 :   crt_der.size = certificate_der->len;
     352                 :             : 
     353         [ +  - ]:         222 :   if ((rc = gnutls_x509_crt_init (&crt)) != GNUTLS_E_SUCCESS ||
     354         [ +  - ]:         222 :       (rc = gnutls_x509_crt_import (crt, &crt_der, GNUTLS_X509_FMT_DER)) != GNUTLS_E_SUCCESS ||
     355         [ -  + ]:         222 :       (rc = gnutls_x509_crt_get_dn_by_oid (crt,
     356                 :             :                                            GNUTLS_OID_X520_COMMON_NAME,
     357                 :             :                                            0,
     358                 :             :                                            0,
     359                 :             :                                            &buf,
     360                 :             :                                            &buf_size)) != GNUTLS_E_SUCCESS)
     361                 :             :     {
     362                 :           0 :       g_warning ("%s(): %s", G_STRFUNC, gnutls_strerror (rc));
     363         [ #  # ]:           0 :       g_clear_pointer (&crt, gnutls_x509_crt_deinit);
     364                 :             : 
     365                 :           0 :       return NULL;
     366                 :             :     }
     367                 :             : 
     368                 :             :   /* Intern the common name as private data
     369                 :             :    */
     370                 :         222 :   g_object_set_data_full (G_OBJECT (certificate),
     371                 :             :                           "valent-certificate-cn",
     372                 :         222 :                           g_strndup (buf, buf_size),
     373                 :             :                           g_free);
     374         [ +  - ]:         222 :   g_clear_pointer (&crt, gnutls_x509_crt_deinit);
     375                 :             : 
     376                 :         222 :   return g_object_get_data (G_OBJECT (certificate), "valent-certificate-cn");
     377                 :             : }
     378                 :             : 
     379                 :             : /**
     380                 :             :  * valent_certificate_get_public_key:
     381                 :             :  * @certificate: a `GTlsCertificate`
     382                 :             :  *
     383                 :             :  * Get the public key of @certificate.
     384                 :             :  *
     385                 :             :  * Returns: (transfer none): a DER-encoded public key
     386                 :             :  *
     387                 :             :  * Since: 1.0
     388                 :             :  */
     389                 :             : GByteArray *
     390                 :           5 : valent_certificate_get_public_key (GTlsCertificate *certificate)
     391                 :             : {
     392                 :          10 :   g_autoptr (GByteArray) certificate_der = NULL;
     393         [ +  + ]:           5 :   g_autoptr (GByteArray) pk = NULL;
     394                 :           5 :   gnutls_x509_crt_t crt = NULL;
     395                 :           5 :   gnutls_datum_t crt_der = { 0, };
     396                 :           5 :   gnutls_pubkey_t pubkey = NULL;
     397                 :           5 :   size_t size;
     398                 :           5 :   int rc;
     399                 :             : 
     400   [ +  -  +  -  :           5 :   g_return_val_if_fail (G_IS_TLS_CERTIFICATE (certificate), NULL);
             +  -  -  + ]
     401                 :             : 
     402                 :           5 :   pk = g_object_get_data (G_OBJECT (certificate), "valent-certificate-pk");
     403         [ +  + ]:           5 :   if (pk != NULL)
     404                 :             :     return g_steal_pointer (&pk);
     405                 :             : 
     406                 :           3 :   g_object_get (certificate, "certificate", &certificate_der, NULL);
     407                 :           3 :   crt_der.data = certificate_der->data;
     408                 :           3 :   crt_der.size = certificate_der->len;
     409                 :             : 
     410         [ +  - ]:           3 :   if ((rc = gnutls_x509_crt_init (&crt)) != GNUTLS_E_SUCCESS ||
     411         [ -  + ]:           3 :       (rc = gnutls_x509_crt_import (crt, &crt_der, GNUTLS_X509_FMT_DER)) != GNUTLS_E_SUCCESS)
     412                 :             :     {
     413                 :           0 :       g_warning ("%s(): %s", G_STRFUNC, gnutls_strerror (rc));
     414                 :           0 :       VALENT_GOTO (out);
     415                 :             :     }
     416                 :             : 
     417         [ +  - ]:           3 :   if ((rc = gnutls_pubkey_init (&pubkey)) != GNUTLS_E_SUCCESS ||
     418         [ -  + ]:           3 :       (rc = gnutls_pubkey_import_x509 (pubkey, crt, 0)) != GNUTLS_E_SUCCESS)
     419                 :             :     {
     420                 :           0 :       g_warning ("%s(): %s", G_STRFUNC, gnutls_strerror (rc));
     421                 :           0 :       VALENT_GOTO (out);
     422                 :             :     }
     423                 :             : 
     424                 :             :   /* First call to get the size, since GByteArray.len is an `unsigned int`,
     425                 :             :    * while the output is a `size_t`.
     426                 :             :    */
     427                 :           3 :   rc = gnutls_pubkey_export (pubkey, GNUTLS_X509_FMT_DER, NULL, &size);
     428         [ -  + ]:           3 :   if (rc != GNUTLS_E_SUCCESS && rc != GNUTLS_E_SHORT_MEMORY_BUFFER)
     429                 :             :     {
     430                 :           0 :       g_warning ("%s(): %s", G_STRFUNC, gnutls_strerror (rc));
     431                 :           0 :       VALENT_GOTO (out);
     432                 :             :     }
     433                 :             : 
     434         [ +  - ]:           3 :   g_assert (size <= (size_t)UINT_MAX);
     435                 :           3 :   pk = g_byte_array_sized_new (size);
     436                 :           3 :   pk->len = (unsigned int)size;
     437         [ -  + ]:           3 :   if ((rc = gnutls_pubkey_export (pubkey,
     438                 :             :                                   GNUTLS_X509_FMT_DER,
     439                 :           3 :                                   pk->data, &size)) != GNUTLS_E_SUCCESS)
     440                 :             :     {
     441                 :           0 :       g_warning ("%s(): %s", G_STRFUNC, gnutls_strerror (rc));
     442                 :           0 :       VALENT_GOTO (out);
     443                 :             :     }
     444                 :             : 
     445                 :             :   /* Intern the DER as private data
     446                 :             :    */
     447                 :           3 :   g_object_set_data_full (G_OBJECT (certificate),
     448                 :             :                           "valent-certificate-pk",
     449                 :             :                           g_steal_pointer (&pk),
     450                 :             :                           (GDestroyNotify)g_byte_array_unref);
     451                 :             : 
     452                 :           3 : out:
     453         [ +  - ]:           3 :   g_clear_pointer (&crt, gnutls_x509_crt_deinit);
     454         [ +  - ]:           3 :   g_clear_pointer (&pubkey, gnutls_pubkey_deinit);
     455                 :             : 
     456                 :           3 :   return g_object_get_data (G_OBJECT (certificate), "valent-certificate-pk");
     457                 :             : }
     458                 :             : 
        

Generated by: LCOV version 2.0-1