LCOV - code coverage report
Current view: top level - gcr - gcr-certificate-request.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 264 0.0 %
Date: 2022-09-04 10:20:22 Functions: 0 29 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 152 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2011 Collabora Ltd.
       3                 :            :  *
       4                 :            :  * This program is free software; you can redistribute it and/or modify
       5                 :            :  * it under the terms of the GNU Lesser General Public License as
       6                 :            :  * published by the Free Software Foundation; either version 2.1 of
       7                 :            :  * the License, or (at your option) any later version.
       8                 :            :  *
       9                 :            :  * This program is distributed in the hope that it will be useful, but
      10                 :            :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      11                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12                 :            :  * Lesser General Public License for more details.
      13                 :            :  *
      14                 :            :  * You should have received a copy of the GNU Lesser General Public
      15                 :            :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      16                 :            :  *
      17                 :            :  * Author: Stef Walter <stefw@collabora.co.uk>
      18                 :            :  */
      19                 :            : 
      20                 :            : #include "config.h"
      21                 :            : 
      22                 :            : #include "gcr-certificate-request.h"
      23                 :            : #include "gcr-key-mechanisms.h"
      24                 :            : #include "gcr-subject-public-key.h"
      25                 :            : 
      26                 :            : #include "gcr/gcr-enum-types.h"
      27                 :            : #include "gcr/gcr-oids.h"
      28                 :            : 
      29                 :            : #include <egg/egg-armor.h>
      30                 :            : #include <egg/egg-asn1x.h>
      31                 :            : #include <egg/egg-asn1-defs.h>
      32                 :            : #include <egg/egg-dn.h>
      33                 :            : 
      34                 :            : #include <glib/gi18n-lib.h>
      35                 :            : 
      36                 :            : /**
      37                 :            :  * GcrCertificateRequest:
      38                 :            :  *
      39                 :            :  * An object that allows creation of certificate requests. A certificate
      40                 :            :  * request is sent to a certificate authority to request an X.509 certificate.
      41                 :            :  *
      42                 :            :  * Use [func@CertificateRequest.prepare] to create a blank certificate
      43                 :            :  * request for a given private key. Set the common name on the certificate
      44                 :            :  * request with [method@CertificateRequest.set_cn], and then sign the request
      45                 :            :  * with [method@CertificateRequest.complete_async].
      46                 :            :  */
      47                 :            : 
      48                 :            : /**
      49                 :            :  * GcrCertificateRequestFormat:
      50                 :            :  * @GCR_CERTIFICATE_REQUEST_PKCS10: certificate request is in PKCS#10 format
      51                 :            :  *
      52                 :            :  * The format of a certificate request. Currently only PKCS#10 is supported.
      53                 :            :  */
      54                 :            : 
      55                 :            : struct _GcrCertificateRequest {
      56                 :            :         GObject parent;
      57                 :            : 
      58                 :            :         GckObject *private_key;
      59                 :            :         GNode *asn;
      60                 :            :         gulong *mechanisms;
      61                 :            :         gulong n_mechanisms;
      62                 :            : };
      63                 :            : 
      64                 :            : enum {
      65                 :            :         PROP_0,
      66                 :            :         PROP_FORMAT,
      67                 :            :         PROP_PRIVATE_KEY
      68                 :            : };
      69                 :            : 
      70                 :            : /* Forward declarations */
      71   [ #  #  #  #  :          0 : G_DEFINE_TYPE (GcrCertificateRequest, gcr_certificate_request, G_TYPE_OBJECT);
                   #  # ]
      72                 :            : 
      73                 :            : /* When updating here, update prepare_to_be_signed() */
      74                 :            : static const gulong RSA_MECHANISMS[] = {
      75                 :            :         CKM_SHA1_RSA_PKCS,
      76                 :            :         CKM_RSA_PKCS,
      77                 :            : };
      78                 :            : 
      79                 :            : /* When updating here, update prepare_to_be_signed() */
      80                 :            : static const gulong DSA_MECHANISMS[] = {
      81                 :            :         CKM_DSA_SHA1,
      82                 :            :         CKM_DSA,
      83                 :            : };
      84                 :            : 
      85                 :            : static const gulong ALL_MECHANISMS[] = {
      86                 :            :         CKM_SHA1_RSA_PKCS,
      87                 :            :         CKM_DSA_SHA1,
      88                 :            :         CKM_RSA_PKCS,
      89                 :            :         CKM_DSA,
      90                 :            : };
      91                 :            : 
      92                 :            : G_STATIC_ASSERT (sizeof (ALL_MECHANISMS) == sizeof (RSA_MECHANISMS) + sizeof (DSA_MECHANISMS));
      93                 :            : 
      94                 :            : static void
      95                 :          0 : gcr_certificate_request_init (GcrCertificateRequest *self)
      96                 :            : {
      97                 :            : 
      98                 :          0 : }
      99                 :            : 
     100                 :            : static void
     101                 :          0 : gcr_certificate_request_constructed (GObject *obj)
     102                 :            : {
     103                 :          0 :         GcrCertificateRequest *self = GCR_CERTIFICATE_REQUEST (obj);
     104                 :            :         GNode *version;
     105                 :            : 
     106                 :          0 :         G_OBJECT_CLASS (gcr_certificate_request_parent_class)->constructed (obj);
     107                 :            : 
     108                 :          0 :         self->asn = egg_asn1x_create (pkix_asn1_tab, "pkcs-10-CertificationRequest");
     109         [ #  # ]:          0 :         g_return_if_fail (self->asn != NULL);
     110                 :            : 
     111                 :            :         /* Setup the version */
     112                 :          0 :         version = egg_asn1x_node (self->asn, "certificationRequestInfo", "version", NULL);
     113                 :          0 :         egg_asn1x_set_integer_as_ulong (version, 0);
     114                 :            : }
     115                 :            : 
     116                 :            : static void
     117                 :          0 : gcr_certificate_request_finalize (GObject *obj)
     118                 :            : {
     119                 :          0 :         GcrCertificateRequest *self = GCR_CERTIFICATE_REQUEST (obj);
     120                 :            : 
     121                 :          0 :         egg_asn1x_destroy (self->asn);
     122                 :          0 :         g_free (self->mechanisms);
     123                 :            : 
     124                 :          0 :         G_OBJECT_CLASS (gcr_certificate_request_parent_class)->finalize (obj);
     125                 :          0 : }
     126                 :            : 
     127                 :            : static void
     128                 :          0 : gcr_certificate_request_set_property (GObject *obj,
     129                 :            :                                       guint prop_id,
     130                 :            :                                       const GValue *value,
     131                 :            :                                       GParamSpec *pspec)
     132                 :            : {
     133                 :          0 :         GcrCertificateRequest *self = GCR_CERTIFICATE_REQUEST (obj);
     134                 :            :         GcrCertificateRequestFormat format;
     135                 :            : 
     136      [ #  #  # ]:          0 :         switch (prop_id) {
     137                 :          0 :         case PROP_PRIVATE_KEY:
     138         [ #  # ]:          0 :                 g_return_if_fail (self->private_key == NULL);
     139                 :          0 :                 self->private_key = g_value_dup_object (value);
     140         [ #  # ]:          0 :                 g_return_if_fail (GCK_IS_OBJECT (self->private_key));
     141                 :          0 :                 break;
     142                 :          0 :         case PROP_FORMAT:
     143                 :          0 :                 format = g_value_get_enum (value);
     144         [ #  # ]:          0 :                 g_return_if_fail (format == GCR_CERTIFICATE_REQUEST_PKCS10);
     145                 :          0 :                 break;
     146                 :          0 :         default:
     147                 :          0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     148                 :          0 :                 break;
     149                 :            :         }
     150                 :            : }
     151                 :            : 
     152                 :            : static void
     153                 :          0 : gcr_certificate_request_get_property (GObject *obj,
     154                 :            :                                       guint prop_id,
     155                 :            :                                       GValue *value,
     156                 :            :                                       GParamSpec *pspec)
     157                 :            : {
     158                 :          0 :         GcrCertificateRequest *self = GCR_CERTIFICATE_REQUEST (obj);
     159                 :            : 
     160      [ #  #  # ]:          0 :         switch (prop_id) {
     161                 :          0 :         case PROP_PRIVATE_KEY:
     162                 :          0 :                 g_value_set_object (value, gcr_certificate_request_get_private_key (self));
     163                 :          0 :                 break;
     164                 :          0 :         case PROP_FORMAT:
     165                 :          0 :                 g_value_set_enum (value, gcr_certificate_request_get_format (self));
     166                 :          0 :                 break;
     167                 :          0 :         default:
     168                 :          0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     169                 :          0 :                 break;
     170                 :            :         }
     171                 :          0 : }
     172                 :            : 
     173                 :            : static void
     174                 :          0 : gcr_certificate_request_class_init (GcrCertificateRequestClass *klass)
     175                 :            : {
     176                 :          0 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     177                 :            : 
     178                 :          0 :         gobject_class->constructed = gcr_certificate_request_constructed;
     179                 :          0 :         gobject_class->finalize = gcr_certificate_request_finalize;
     180                 :          0 :         gobject_class->set_property = gcr_certificate_request_set_property;
     181                 :          0 :         gobject_class->get_property = gcr_certificate_request_get_property;
     182                 :            : 
     183                 :            :         /**
     184                 :            :          * GcrCertificateRequest:private-key:
     185                 :            :          *
     186                 :            :          * The private key that this certificate request is for.
     187                 :            :          */
     188                 :          0 :         g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY,
     189                 :            :                 g_param_spec_object ("private-key", "Private key", "Private key for request",
     190                 :            :                                      GCK_TYPE_OBJECT,
     191                 :            :                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
     192                 :            : 
     193                 :            :         /**
     194                 :            :          * GcrCertificateRequest:format:
     195                 :            :          *
     196                 :            :          * The format of the certificate request.
     197                 :            :          */
     198                 :          0 :         g_object_class_install_property (gobject_class, PROP_FORMAT,
     199                 :            :                 g_param_spec_enum ("format", "Format", "Format of certificate request",
     200                 :            :                                    GCR_TYPE_CERTIFICATE_REQUEST_FORMAT, GCR_CERTIFICATE_REQUEST_PKCS10,
     201                 :            :                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
     202                 :          0 : }
     203                 :            : 
     204                 :            : /**
     205                 :            :  * gcr_certificate_request_prepare:
     206                 :            :  * @format: the format for the certificate request
     207                 :            :  * @private_key: the private key the the certificate is being requested for
     208                 :            :  *
     209                 :            :  * Create a new certificate request, in the given format for the private key.
     210                 :            :  *
     211                 :            :  * Returns: (transfer full): a new #GcrCertificate request
     212                 :            :  */
     213                 :            : GcrCertificateRequest *
     214                 :          0 : gcr_certificate_request_prepare (GcrCertificateRequestFormat format,
     215                 :            :                                  GckObject *private_key)
     216                 :            : {
     217         [ #  # ]:          0 :         g_return_val_if_fail (format == GCR_CERTIFICATE_REQUEST_PKCS10, NULL);
     218         [ #  # ]:          0 :         g_return_val_if_fail (GCK_IS_OBJECT (private_key), NULL);
     219                 :            : 
     220                 :          0 :         return g_object_new (GCR_TYPE_CERTIFICATE_REQUEST,
     221                 :            :                              "format", format,
     222                 :            :                              "private-key", private_key,
     223                 :            :                              NULL);
     224                 :            : }
     225                 :            : 
     226                 :            : /**
     227                 :            :  * gcr_certificate_request_get_private_key:
     228                 :            :  * @self: the certificate request
     229                 :            :  *
     230                 :            :  * Get the private key this certificate request is for.
     231                 :            :  *
     232                 :            :  * Returns: (transfer none): the private key,
     233                 :            :  */
     234                 :            : GckObject *
     235                 :          0 : gcr_certificate_request_get_private_key (GcrCertificateRequest *self)
     236                 :            : {
     237         [ #  # ]:          0 :         g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), NULL);
     238                 :          0 :         return self->private_key;
     239                 :            : }
     240                 :            : 
     241                 :            : /**
     242                 :            :  * gcr_certificate_request_get_format:
     243                 :            :  * @self: the certificate request
     244                 :            :  *
     245                 :            :  * Get the format of this certificate request.
     246                 :            :  *
     247                 :            :  * Returns: the format
     248                 :            :  */
     249                 :            : GcrCertificateRequestFormat
     250                 :          0 : gcr_certificate_request_get_format (GcrCertificateRequest *self)
     251                 :            : {
     252         [ #  # ]:          0 :         g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), 0);
     253                 :          0 :         return GCR_CERTIFICATE_REQUEST_PKCS10;
     254                 :            : }
     255                 :            : 
     256                 :            : /**
     257                 :            :  * gcr_certificate_request_set_cn:
     258                 :            :  * @self: the certificate request
     259                 :            :  * @cn: common name to set on the request
     260                 :            :  *
     261                 :            :  * Set the common name encoded in the certificate request.
     262                 :            :  */
     263                 :            : void
     264                 :          0 : gcr_certificate_request_set_cn (GcrCertificateRequest *self,
     265                 :            :                                 const gchar *cn)
     266                 :            : {
     267                 :            :         GNode *subject;
     268                 :            :         GNode *dn;
     269                 :            : 
     270         [ #  # ]:          0 :         g_return_if_fail (GCR_IS_CERTIFICATE_REQUEST (self));
     271         [ #  # ]:          0 :         g_return_if_fail (cn != NULL);
     272                 :            : 
     273                 :          0 :         subject = egg_asn1x_node (self->asn, "certificationRequestInfo", "subject", NULL);
     274                 :          0 :         dn = egg_asn1x_node (subject, "rdnSequence", NULL);
     275                 :            : 
     276                 :            :         /* TODO: we shouldn't really be clearing this, but replacing CN */
     277                 :          0 :         egg_asn1x_set_choice (subject, dn);
     278                 :          0 :         egg_asn1x_clear (dn);
     279                 :          0 :         egg_dn_add_string_part (dn, GCR_OID_NAME_CN, cn);
     280                 :            : }
     281                 :            : 
     282                 :            : static GBytes *
     283                 :          0 : hash_sha1_pkcs1 (GBytes *data)
     284                 :            : {
     285                 :          0 :         const guchar SHA1_ASN[15] = /* Object ID is 1.3.14.3.2.26 */
     286                 :            :                 { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
     287                 :            :                   0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
     288                 :            : 
     289                 :            :         GChecksum *checksum;
     290                 :            :         guchar *hash;
     291                 :            :         gsize n_hash;
     292                 :            :         gsize n_digest;
     293                 :            : 
     294                 :          0 :         n_digest = g_checksum_type_get_length (G_CHECKSUM_SHA1);
     295                 :          0 :         n_hash = n_digest + sizeof (SHA1_ASN);
     296                 :          0 :         hash = g_malloc (n_hash);
     297                 :          0 :         memcpy (hash, SHA1_ASN, sizeof (SHA1_ASN));
     298                 :            : 
     299                 :          0 :         checksum = g_checksum_new (G_CHECKSUM_SHA1);
     300                 :          0 :         g_checksum_update (checksum, g_bytes_get_data (data, NULL), g_bytes_get_size (data));
     301                 :          0 :         g_checksum_get_digest (checksum, hash + sizeof (SHA1_ASN), &n_digest);
     302                 :          0 :         g_checksum_free (checksum);
     303                 :            : 
     304                 :          0 :         return g_bytes_new_take (hash, n_hash);
     305                 :            : }
     306                 :            : 
     307                 :            : static GBytes *
     308                 :          0 : hash_sha1 (GBytes *data)
     309                 :            : {
     310                 :            :         GChecksum *checksum;
     311                 :            :         guchar *hash;
     312                 :            :         gsize n_hash;
     313                 :            : 
     314                 :          0 :         n_hash = g_checksum_type_get_length (G_CHECKSUM_SHA1);
     315                 :          0 :         hash = g_malloc (n_hash);
     316                 :            : 
     317                 :          0 :         checksum = g_checksum_new (G_CHECKSUM_SHA1);
     318                 :          0 :         g_checksum_update (checksum, g_bytes_get_data (data, NULL), g_bytes_get_size (data));
     319                 :          0 :         g_checksum_get_digest (checksum, hash, &n_hash);
     320                 :          0 :         g_checksum_free (checksum);
     321                 :            : 
     322                 :          0 :         return g_bytes_new_take (hash, n_hash);
     323                 :            : }
     324                 :            : 
     325                 :            : static GBytes *
     326                 :          0 : prepare_to_be_signed (GcrCertificateRequest *self,
     327                 :            :                       GckMechanism *mechanism)
     328                 :            : {
     329                 :            :         GNode *node;
     330                 :            :         GBytes *data;
     331                 :            :         GBytes *hash;
     332                 :            : 
     333         [ #  # ]:          0 :         g_assert (mechanism != NULL);
     334                 :            : 
     335                 :          0 :         node = egg_asn1x_node (self->asn, "certificationRequestInfo", NULL);
     336                 :          0 :         data = egg_asn1x_encode (node, NULL);
     337                 :            : 
     338                 :          0 :         mechanism->parameter = NULL;
     339                 :          0 :         mechanism->n_parameter = 0;
     340                 :            : 
     341   [ #  #  #  # ]:          0 :         switch (mechanism->type) {
     342                 :          0 :         case CKM_SHA1_RSA_PKCS:
     343                 :            :         case CKM_DSA_SHA1:
     344                 :          0 :                 return data;
     345                 :            : 
     346                 :          0 :         case CKM_RSA_PKCS:
     347                 :          0 :                 hash = hash_sha1_pkcs1 (data);
     348                 :          0 :                 g_bytes_unref (data);
     349                 :          0 :                 return hash;
     350                 :            : 
     351                 :          0 :         case CKM_DSA:
     352                 :          0 :                 hash = hash_sha1 (data);
     353                 :          0 :                 g_bytes_unref (data);
     354                 :          0 :                 return hash;
     355                 :            : 
     356                 :          0 :         default:
     357                 :          0 :                 g_assert_not_reached ();
     358                 :            :                 return NULL;
     359                 :            :         }
     360                 :            : }
     361                 :            : 
     362                 :            : static gboolean
     363                 :          0 : prepare_subject_public_key_and_mechanisms (GcrCertificateRequest *self,
     364                 :            :                                            GNode *subject_public_key,
     365                 :            :                                            GQuark *algorithm,
     366                 :            :                                            const gulong **mechanisms,
     367                 :            :                                            gsize *n_mechanisms,
     368                 :            :                                            GError **error)
     369                 :            : {
     370                 :            :         GBytes *encoded;
     371                 :            :         GNode *node;
     372                 :            :         GQuark oid;
     373                 :            : 
     374         [ #  # ]:          0 :         g_assert (algorithm != NULL);
     375         [ #  # ]:          0 :         g_assert (mechanisms != NULL);
     376         [ #  # ]:          0 :         g_assert (n_mechanisms != NULL);
     377                 :            : 
     378                 :          0 :         encoded = egg_asn1x_encode (subject_public_key, NULL);
     379         [ #  # ]:          0 :         g_return_val_if_fail (encoded != NULL, FALSE);
     380                 :            : 
     381                 :          0 :         node = egg_asn1x_node (subject_public_key, "algorithm", "algorithm", NULL);
     382                 :          0 :         oid = egg_asn1x_get_oid_as_quark (node);
     383                 :            : 
     384         [ #  # ]:          0 :         if (oid == GCR_OID_PKIX1_RSA) {
     385                 :          0 :                 *mechanisms = RSA_MECHANISMS;
     386                 :          0 :                 *n_mechanisms = G_N_ELEMENTS (RSA_MECHANISMS);
     387                 :          0 :                 *algorithm = GCR_OID_PKIX1_SHA1_WITH_RSA;
     388                 :            : 
     389         [ #  # ]:          0 :         } else if (oid == GCR_OID_PKIX1_DSA) {
     390                 :          0 :                 *mechanisms = DSA_MECHANISMS;
     391                 :          0 :                 *n_mechanisms = G_N_ELEMENTS (DSA_MECHANISMS);
     392                 :          0 :                 *algorithm = GCR_OID_PKIX1_SHA1_WITH_DSA;
     393                 :            : 
     394                 :            :         } else {
     395                 :          0 :                 g_bytes_unref (encoded);
     396                 :          0 :                 g_set_error (error, GCR_DATA_ERROR, GCR_ERROR_UNRECOGNIZED,
     397                 :            :                              _("Unsupported key type for certificate request"));
     398                 :          0 :                 return FALSE;
     399                 :            :         }
     400                 :            : 
     401                 :          0 :         node = egg_asn1x_node (self->asn, "certificationRequestInfo", "subjectPKInfo", NULL);
     402         [ #  # ]:          0 :         if (!egg_asn1x_decode (node, encoded))
     403                 :          0 :                 g_return_val_if_reached (FALSE);
     404                 :            : 
     405                 :          0 :         g_bytes_unref (encoded);
     406                 :          0 :         return TRUE;
     407                 :            : }
     408                 :            : 
     409                 :            : static void
     410                 :          0 : encode_take_signature_into_request (GcrCertificateRequest *self,
     411                 :            :                                     GQuark algorithm,
     412                 :            :                                     GNode *subject_public_key,
     413                 :            :                                     guchar *result,
     414                 :            :                                     gsize n_result)
     415                 :            : {
     416                 :            :         GNode *params;
     417                 :            :         GNode *node;
     418                 :            : 
     419                 :          0 :         node = egg_asn1x_node (self->asn, "signature", NULL);
     420                 :          0 :         egg_asn1x_take_bits_as_raw (node, g_bytes_new_take (result, n_result), n_result * 8);
     421                 :            : 
     422                 :          0 :         node = egg_asn1x_node (self->asn, "signatureAlgorithm", "algorithm", NULL);
     423                 :          0 :         egg_asn1x_set_oid_as_quark (node, algorithm);
     424                 :            : 
     425                 :          0 :         node = egg_asn1x_node (self->asn, "signatureAlgorithm", "parameters", NULL);
     426                 :          0 :         params = egg_asn1x_node (subject_public_key, "algorithm", "parameters", NULL);
     427                 :          0 :         egg_asn1x_set_any_from (node, params);
     428                 :          0 : }
     429                 :            : 
     430                 :            : /**
     431                 :            :  * gcr_certificate_request_complete:
     432                 :            :  * @self: a certificate request
     433                 :            :  * @cancellable: a cancellation object
     434                 :            :  * @error: location to place an error on failure
     435                 :            :  *
     436                 :            :  * Complete and sign a certificate request, so that it can be encoded
     437                 :            :  * and sent to a certificate authority.
     438                 :            :  *
     439                 :            :  * This call may block as it signs the request using the private key.
     440                 :            :  *
     441                 :            :  * Returns: whether certificate request was successfully completed or not
     442                 :            :  */
     443                 :            : gboolean
     444                 :          0 : gcr_certificate_request_complete (GcrCertificateRequest *self,
     445                 :            :                                   GCancellable *cancellable,
     446                 :            :                                   GError **error)
     447                 :            : {
     448                 :            :         GNode *subject_public_key;
     449                 :            :         const gulong *mechanisms;
     450                 :            :         gsize n_mechanisms;
     451                 :          0 :         GckMechanism mechanism = { 0, };
     452                 :          0 :         GQuark algorithm = 0;
     453                 :            :         GBytes *tbs;
     454                 :            :         GckSession *session;
     455                 :            :         guchar *signature;
     456                 :            :         gsize n_signature;
     457                 :            :         gboolean ret;
     458                 :            : 
     459         [ #  # ]:          0 :         g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), FALSE);
     460   [ #  #  #  # ]:          0 :         g_return_val_if_fail (cancellable == NULL || G_CANCELLABLE (cancellable), FALSE);
     461   [ #  #  #  # ]:          0 :         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
     462                 :            : 
     463                 :          0 :         subject_public_key = _gcr_subject_public_key_load (self->private_key,
     464                 :            :                                                            cancellable, error);
     465         [ #  # ]:          0 :         if (subject_public_key == NULL)
     466                 :          0 :                 return FALSE;
     467                 :            : 
     468                 :          0 :         ret = prepare_subject_public_key_and_mechanisms (self, subject_public_key,
     469                 :            :                                                          &algorithm, &mechanisms,
     470                 :            :                                                          &n_mechanisms, error);
     471                 :            : 
     472         [ #  # ]:          0 :         if (!ret) {
     473                 :          0 :                 egg_asn1x_destroy (subject_public_key);
     474                 :          0 :                 return FALSE;
     475                 :            :         }
     476                 :            : 
     477                 :            :         /* Figure out which mechanism to use */
     478                 :          0 :         mechanism.type = _gcr_key_mechanisms_check (self->private_key, mechanisms,
     479                 :            :                                                     n_mechanisms, CKA_SIGN,
     480                 :            :                                                     cancellable, NULL);
     481         [ #  # ]:          0 :         if (mechanism.type == GCK_INVALID) {
     482                 :          0 :                 egg_asn1x_destroy (subject_public_key);
     483                 :          0 :                 g_set_error (error, GCK_ERROR, CKR_KEY_TYPE_INCONSISTENT,
     484                 :            :                              _("The key cannot be used to sign the request"));
     485                 :          0 :                 return FALSE;
     486                 :            :         }
     487                 :            : 
     488                 :          0 :         tbs = prepare_to_be_signed (self, &mechanism);
     489                 :          0 :         session = gck_object_get_session (self->private_key);
     490                 :          0 :         signature = gck_session_sign_full (session, self->private_key, &mechanism,
     491                 :          0 :                                            g_bytes_get_data (tbs, NULL),
     492                 :            :                                            g_bytes_get_size (tbs),
     493                 :            :                                            &n_signature, cancellable, error);
     494                 :          0 :         g_object_unref (session);
     495                 :          0 :         g_bytes_unref (tbs);
     496                 :            : 
     497         [ #  # ]:          0 :         if (!signature) {
     498                 :          0 :                 egg_asn1x_destroy (subject_public_key);
     499                 :          0 :                 return FALSE;
     500                 :            :         }
     501                 :            : 
     502                 :          0 :         encode_take_signature_into_request (self, algorithm, subject_public_key,
     503                 :            :                                             signature, n_signature);
     504                 :          0 :         egg_asn1x_destroy (subject_public_key);
     505                 :          0 :         return TRUE;
     506                 :            : }
     507                 :            : 
     508                 :            : typedef struct {
     509                 :            :         GcrCertificateRequest *request;
     510                 :            :         GQuark algorithm;
     511                 :            :         GNode *subject_public_key;
     512                 :            :         GckMechanism mechanism;
     513                 :            :         GckSession *session;
     514                 :            :         GBytes *tbs;
     515                 :            : } CompleteClosure;
     516                 :            : 
     517                 :            : static void
     518                 :          0 : complete_closure_free (gpointer data)
     519                 :            : {
     520                 :          0 :         CompleteClosure *closure = data;
     521                 :          0 :         egg_asn1x_destroy (closure->subject_public_key);
     522         [ #  # ]:          0 :         g_clear_object (&closure->request);
     523         [ #  # ]:          0 :         g_clear_object (&closure->session);
     524         [ #  # ]:          0 :         if (closure->tbs)
     525                 :          0 :                 g_bytes_unref (closure->tbs);
     526                 :          0 :         g_free (closure);
     527                 :          0 : }
     528                 :            : 
     529                 :            : static void
     530                 :          0 : on_certificate_request_signed (GObject *source,
     531                 :            :                                GAsyncResult *result,
     532                 :            :                                gpointer user_data)
     533                 :            : {
     534                 :          0 :         GTask *task = G_TASK (user_data);
     535                 :          0 :         CompleteClosure *closure = g_task_get_task_data (task);
     536                 :          0 :         GError *error = NULL;
     537                 :            :         guchar *signature;
     538                 :            :         gsize n_signature;
     539                 :            : 
     540                 :          0 :         signature = gck_session_sign_finish (closure->session, result, &n_signature, &error);
     541         [ #  # ]:          0 :         if (error == NULL) {
     542                 :          0 :                 encode_take_signature_into_request (closure->request,
     543                 :            :                                                     closure->algorithm,
     544                 :            :                                                     closure->subject_public_key,
     545                 :            :                                                     signature, n_signature);
     546                 :            : 
     547                 :          0 :                 g_task_return_boolean (task, TRUE);
     548                 :            :         } else {
     549                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
     550                 :            :         }
     551                 :            : 
     552         [ #  # ]:          0 :         g_clear_object (&task);
     553                 :          0 : }
     554                 :            : 
     555                 :            : static void
     556                 :          0 : on_mechanism_check (GObject *source,
     557                 :            :                     GAsyncResult *result,
     558                 :            :                     gpointer user_data)
     559                 :            : {
     560                 :          0 :         GTask *task = G_TASK (user_data);
     561                 :          0 :         CompleteClosure *closure = g_task_get_task_data (task);
     562                 :          0 :         GCancellable *cancellable = g_task_get_cancellable (task);
     563                 :            : 
     564                 :          0 :         closure->mechanism.type =  _gcr_key_mechanisms_check_finish (closure->request->private_key,
     565                 :            :                                                                      result, NULL);
     566         [ #  # ]:          0 :         if (closure->mechanism.type == GCK_INVALID) {
     567                 :          0 :                 g_task_return_new_error (task, GCK_ERROR, CKR_KEY_TYPE_INCONSISTENT,
     568                 :          0 :                                          _("The key cannot be used to sign the request"));
     569                 :            : 
     570                 :            :         } else {
     571                 :          0 :                 closure->tbs = prepare_to_be_signed (closure->request, &closure->mechanism);
     572                 :          0 :                 gck_session_sign_async (closure->session,
     573                 :          0 :                                         closure->request->private_key,
     574                 :            :                                         &closure->mechanism,
     575                 :          0 :                                         g_bytes_get_data (closure->tbs, NULL),
     576                 :            :                                         g_bytes_get_size (closure->tbs),
     577                 :            :                                         cancellable,
     578                 :            :                                         on_certificate_request_signed,
     579                 :            :                                         g_steal_pointer (&task));
     580                 :            :         }
     581                 :            : 
     582         [ #  # ]:          0 :         g_clear_object (&task);
     583                 :          0 : }
     584                 :            : 
     585                 :            : static void
     586                 :          0 : on_subject_public_key_loaded (GObject *source,
     587                 :            :                               GAsyncResult *result,
     588                 :            :                               gpointer user_data)
     589                 :            : {
     590                 :          0 :         GTask *task = G_TASK (user_data);
     591                 :          0 :         CompleteClosure *closure = g_task_get_task_data (task);
     592                 :          0 :         GCancellable *cancellable = g_task_get_cancellable (task);
     593                 :            :         const gulong *mechanisms;
     594                 :            :         gsize n_mechanisms;
     595                 :          0 :         GError *error = NULL;
     596                 :            : 
     597                 :          0 :         closure->subject_public_key = _gcr_subject_public_key_load_finish (result, &error);
     598         [ #  # ]:          0 :         if (error == NULL) {
     599                 :          0 :                 prepare_subject_public_key_and_mechanisms (closure->request,
     600                 :            :                                                            closure->subject_public_key,
     601                 :            :                                                            &closure->algorithm,
     602                 :            :                                                            &mechanisms,
     603                 :            :                                                            &n_mechanisms,
     604                 :            :                                                            &error);
     605                 :            :         }
     606                 :            : 
     607         [ #  # ]:          0 :         if (error != NULL) {
     608                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
     609         [ #  # ]:          0 :                 g_clear_object (&task);
     610                 :          0 :                 return;
     611                 :            :         }
     612                 :            : 
     613                 :          0 :         _gcr_key_mechanisms_check_async (closure->request->private_key,
     614                 :            :                                          mechanisms, n_mechanisms, CKA_SIGN,
     615                 :            :                                          cancellable, on_mechanism_check,
     616                 :            :                                          g_steal_pointer (&task));
     617                 :            : }
     618                 :            : 
     619                 :            : /**
     620                 :            :  * gcr_certificate_request_complete_async:
     621                 :            :  * @self: a certificate request
     622                 :            :  * @cancellable: (nullable): a cancellation object
     623                 :            :  * @callback: called when the operation completes
     624                 :            :  * @user_data: data to pass to the callback
     625                 :            :  *
     626                 :            :  * Asynchronously complete and sign a certificate request, so that it can
     627                 :            :  * be encoded and sent to a certificate authority.
     628                 :            :  *
     629                 :            :  * This call will return immediately and complete later.
     630                 :            :  */
     631                 :            : void
     632                 :          0 : gcr_certificate_request_complete_async (GcrCertificateRequest *self,
     633                 :            :                                         GCancellable *cancellable,
     634                 :            :                                         GAsyncReadyCallback callback,
     635                 :            :                                         gpointer user_data)
     636                 :            : {
     637                 :            :         GTask *task;
     638                 :            :         CompleteClosure *closure;
     639                 :            : 
     640         [ #  # ]:          0 :         g_return_if_fail (GCR_IS_CERTIFICATE_REQUEST (self));
     641   [ #  #  #  # ]:          0 :         g_return_if_fail (cancellable == NULL || G_CANCELLABLE (cancellable));
     642                 :            : 
     643                 :          0 :         task = g_task_new (self, cancellable, callback, user_data);
     644         [ #  # ]:          0 :         g_task_set_source_tag (task, gcr_certificate_request_complete_async);
     645                 :          0 :         closure = g_new0 (CompleteClosure, 1);
     646                 :          0 :         closure->session = gck_object_get_session (self->private_key);
     647                 :          0 :         closure->request = g_object_ref (self);
     648                 :          0 :         g_task_set_task_data (task, closure, complete_closure_free);
     649                 :            : 
     650                 :          0 :         _gcr_subject_public_key_load_async (self->private_key, cancellable,
     651                 :            :                                             on_subject_public_key_loaded,
     652                 :            :                                             g_steal_pointer (&task));
     653                 :            : 
     654         [ #  # ]:          0 :         g_clear_object (&task);
     655                 :            : }
     656                 :            : 
     657                 :            : /**
     658                 :            :  * gcr_certificate_request_complete_finish:
     659                 :            :  * @self: a certificate request
     660                 :            :  * @result: result of the asynchronous operation
     661                 :            :  * @error: location to place an error on failure
     662                 :            :  *
     663                 :            :  * Finish an asynchronous operation to complete and sign a certificate
     664                 :            :  * request.
     665                 :            :  *
     666                 :            :  * Returns: whether certificate request was successfully completed or not
     667                 :            :  */
     668                 :            : gboolean
     669                 :          0 : gcr_certificate_request_complete_finish (GcrCertificateRequest *self,
     670                 :            :                                          GAsyncResult *result,
     671                 :            :                                          GError **error)
     672                 :            : {
     673         [ #  # ]:          0 :         g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), FALSE);
     674   [ #  #  #  # ]:          0 :         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
     675         [ #  # ]:          0 :         g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
     676                 :            : 
     677                 :          0 :         return g_task_propagate_boolean (G_TASK (result), error);
     678                 :            : }
     679                 :            : 
     680                 :            : /**
     681                 :            :  * gcr_certificate_request_encode:
     682                 :            :  * @self: a certificate request
     683                 :            :  * @textual: whether to encode output as text
     684                 :            :  * @length: (out): location to place length of returned data
     685                 :            :  *
     686                 :            :  * Encode the certificate request. It must have been completed with
     687                 :            :  * [method@CertificateRequest.complete] or
     688                 :            :  * [method@CertificateRequest.complete_async].
     689                 :            :  *
     690                 :            :  * If @textual is %FALSE, the output is a DER encoded certificate request.
     691                 :            :  *
     692                 :            :  * If @textual is %TRUE, the output is encoded as text. For PKCS#10 requests
     693                 :            :  * this is done using the OpenSSL style PEM encoding.
     694                 :            :  *
     695                 :            :  * Returns: (transfer full) (array length=length): the encoded certificate request
     696                 :            :  */
     697                 :            : guchar *
     698                 :          0 : gcr_certificate_request_encode (GcrCertificateRequest *self,
     699                 :            :                                 gboolean textual,
     700                 :            :                                 gsize *length)
     701                 :            : {
     702                 :            :         GBytes *bytes;
     703                 :            :         gpointer encoded;
     704                 :            :         gpointer data;
     705                 :            :         gsize size;
     706                 :            : 
     707         [ #  # ]:          0 :         g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), NULL);
     708         [ #  # ]:          0 :         g_return_val_if_fail (length != NULL, NULL);
     709                 :            : 
     710                 :          0 :         bytes = egg_asn1x_encode (self->asn, NULL);
     711         [ #  # ]:          0 :         if (bytes == NULL) {
     712                 :          0 :                 g_warning ("couldn't encode certificate request: %s",
     713                 :            :                            egg_asn1x_message (self->asn));
     714                 :          0 :                 return NULL;
     715                 :            :         }
     716                 :            : 
     717                 :          0 :         encoded = g_bytes_unref_to_data (bytes, &size);
     718         [ #  # ]:          0 :         if (textual) {
     719                 :          0 :                 data = egg_armor_write (encoded, size,
     720                 :            :                                         g_quark_from_static_string ("CERTIFICATE REQUEST"),
     721                 :            :                                         NULL, length);
     722                 :          0 :                 g_free (encoded);
     723                 :          0 :                 encoded = data;
     724                 :            : 
     725                 :            :         } else {
     726                 :          0 :                 *length = size;
     727                 :            :         }
     728                 :            : 
     729                 :          0 :         return encoded;
     730                 :            : }
     731                 :            : 
     732                 :            : /**
     733                 :            :  * gcr_certificate_request_capable:
     734                 :            :  * @private_key: a private key
     735                 :            :  * @cancellable: (nullable): cancellation object
     736                 :            :  * @error: location to place an error
     737                 :            :  *
     738                 :            :  * Check whether [class@CertificateRequest] is capable of creating a request
     739                 :            :  * for the given @private_key.
     740                 :            :  *
     741                 :            :  * Returns: whether a request can be created
     742                 :            :  */
     743                 :            : gboolean
     744                 :          0 : gcr_certificate_request_capable (GckObject *private_key,
     745                 :            :                                  GCancellable *cancellable,
     746                 :            :                                  GError **error)
     747                 :            : {
     748         [ #  # ]:          0 :         g_return_val_if_fail (GCK_IS_OBJECT (private_key), FALSE);
     749   [ #  #  #  #  :          0 :         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
          #  #  #  #  #  
                      # ]
     750   [ #  #  #  # ]:          0 :         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
     751                 :            : 
     752                 :          0 :         return _gcr_key_mechanisms_check (private_key, ALL_MECHANISMS,
     753                 :            :                                           G_N_ELEMENTS (ALL_MECHANISMS),
     754                 :            :                                          CKA_SIGN, cancellable, error);
     755                 :            : }
     756                 :            : 
     757                 :            : /**
     758                 :            :  * gcr_certificate_request_capable_async:
     759                 :            :  * @private_key: a private key
     760                 :            :  * @cancellable: (nullable): cancellation object
     761                 :            :  * @callback: will be called when the operation completes
     762                 :            :  * @user_data: data to be passed to callback
     763                 :            :  *
     764                 :            :  * Asynchronously check whether [class@CertificateRequest] is capable of
     765                 :            :  * creating a request for the given @private_key.
     766                 :            :  */
     767                 :            : void
     768                 :          0 : gcr_certificate_request_capable_async (GckObject *private_key,
     769                 :            :                                        GCancellable *cancellable,
     770                 :            :                                        GAsyncReadyCallback callback,
     771                 :            :                                        gpointer user_data)
     772                 :            : {
     773         [ #  # ]:          0 :         g_return_if_fail (GCK_IS_OBJECT (private_key));
     774   [ #  #  #  #  :          0 :         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
          #  #  #  #  #  
                      # ]
     775                 :            : 
     776                 :          0 :         _gcr_key_mechanisms_check_async (private_key, ALL_MECHANISMS,
     777                 :            :                                          G_N_ELEMENTS (ALL_MECHANISMS),
     778                 :            :                                          CKA_SIGN, cancellable,
     779                 :            :                                          callback, user_data);
     780                 :            : }
     781                 :            : 
     782                 :            : /**
     783                 :            :  * gcr_certificate_request_capable_finish:
     784                 :            :  * @result: asynchronous result
     785                 :            :  * @error: location to place an error
     786                 :            :  *
     787                 :            :  * Get the result for asynchronously check whether [class@CertificateRequest] is
     788                 :            :  * capable of creating a request for the given @private_key.
     789                 :            :  *
     790                 :            :  * Returns: whether a request can be created
     791                 :            :  */
     792                 :            : gboolean
     793                 :          0 : gcr_certificate_request_capable_finish (GAsyncResult *result,
     794                 :            :                                         GError **error)
     795                 :            : {
     796                 :            :         GObject *source;
     797                 :            :         gulong mech;
     798                 :            : 
     799   [ #  #  #  #  :          0 :         g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
             #  #  #  # ]
     800                 :            : 
     801                 :          0 :         source = g_async_result_get_source_object (result);
     802                 :          0 :         mech = _gcr_key_mechanisms_check_finish (GCK_OBJECT (source), result, error);
     803                 :          0 :         g_object_unref (source);
     804                 :            : 
     805                 :          0 :         return mech != GCK_INVALID;
     806                 :            : }

Generated by: LCOV version 1.14