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