Use GBytes instead of our own EggBytes
[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         _gcr_oids_init ();
199
200         gobject_class->constructed = gcr_certificate_request_constructed;
201         gobject_class->finalize = gcr_certificate_request_finalize;
202         gobject_class->set_property = gcr_certificate_request_set_property;
203         gobject_class->get_property = gcr_certificate_request_get_property;
204
205         /**
206          * GcrCertificateRequest:private-key:
207          *
208          * The private key that this certificate request is for.
209          */
210         g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY,
211                     g_param_spec_object ("private-key", "Private key", "Private key for request",
212                                          GCK_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
213
214         /**
215          * GcrCertificateRequest:format:
216          *
217          * The format of the certificate request.
218          */
219         g_object_class_install_property (gobject_class, PROP_FORMAT,
220                       g_param_spec_enum ("format", "Format", "Format of certificate request",
221                                          GCR_TYPE_CERTIFICATE_REQUEST_FORMAT, GCR_CERTIFICATE_REQUEST_PKCS10,
222                                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
223 }
224
225 /**
226  * gcr_certificate_request_prepare:
227  * @format: the format for the certificate request
228  * @private_key: the private key the the certificate is being requested for
229  *
230  * Create a new certificate request, in the given format for the private key.
231  *
232  * Returns: (transfer full): a new #GcrCertificate request
233  */
234 GcrCertificateRequest *
235 gcr_certificate_request_prepare (GcrCertificateRequestFormat format,
236                                  GckObject *private_key)
237 {
238         g_return_val_if_fail (format == GCR_CERTIFICATE_REQUEST_PKCS10, NULL);
239         g_return_val_if_fail (GCK_IS_OBJECT (private_key), NULL);
240
241         return g_object_new (GCR_TYPE_CERTIFICATE_REQUEST,
242                              "format", format,
243                              "private-key", private_key,
244                              NULL);
245 }
246
247 /**
248  * gcr_certificate_request_get_private_key:
249  * @self: the certificate request
250  *
251  * Get the private key this certificate request is for.
252  *
253  * Returns: (transfer none): the private key,
254  */
255 GckObject *
256 gcr_certificate_request_get_private_key (GcrCertificateRequest *self)
257 {
258         g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), NULL);
259         return self->private_key;
260 }
261
262 /**
263  * gcr_certificate_request_get_format:
264  * @self: the certificate request
265  *
266  * Get the format of this certificate request.
267  *
268  * Returns: the format
269  */
270 GcrCertificateRequestFormat
271 gcr_certificate_request_get_format (GcrCertificateRequest *self)
272 {
273         g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), 0);
274         return GCR_CERTIFICATE_REQUEST_PKCS10;
275 }
276
277 /**
278  * gcr_certificate_request_set_cn:
279  * @self: the certificate request
280  * @cn: common name to set on the request
281  *
282  * Set the common name encoded in the certificate request.
283  */
284 void
285 gcr_certificate_request_set_cn (GcrCertificateRequest *self,
286                                 const gchar *cn)
287 {
288         GNode *subject;
289         GNode *dn;
290
291         g_return_if_fail (GCR_IS_CERTIFICATE_REQUEST (self));
292         g_return_if_fail (cn != NULL);
293
294         subject = egg_asn1x_node (self->asn, "certificationRequestInfo", "subject", NULL);
295         dn = egg_asn1x_node (subject, "rdnSequence", NULL);
296
297         /* TODO: we shouldn't really be clearing this, but replacing CN */
298         egg_asn1x_set_choice (subject, dn);
299         egg_asn1x_clear (dn);
300         egg_dn_add_string_part (dn, GCR_OID_NAME_CN, cn);
301 }
302
303 static GBytes *
304 hash_sha1_pkcs1 (GBytes *data)
305 {
306         const guchar SHA1_ASN[15] = /* Object ID is 1.3.14.3.2.26 */
307                 { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
308                   0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
309
310         GChecksum *checksum;
311         guchar *hash;
312         gsize n_hash;
313         gsize n_digest;
314
315         n_digest = g_checksum_type_get_length (G_CHECKSUM_SHA1);
316         n_hash = n_digest + sizeof (SHA1_ASN);
317         hash = g_malloc (n_hash);
318         memcpy (hash, SHA1_ASN, sizeof (SHA1_ASN));
319
320         checksum = g_checksum_new (G_CHECKSUM_SHA1);
321         g_checksum_update (checksum, g_bytes_get_data (data, NULL), g_bytes_get_size (data));
322         g_checksum_get_digest (checksum, hash + sizeof (SHA1_ASN), &n_digest);
323         g_checksum_free (checksum);
324
325         return g_bytes_new_take (hash, n_hash);
326 }
327
328 static GBytes *
329 hash_sha1 (GBytes *data)
330 {
331         GChecksum *checksum;
332         guchar *hash;
333         gsize n_hash;
334
335         n_hash = g_checksum_type_get_length (G_CHECKSUM_SHA1);
336         hash = g_malloc (n_hash);
337
338         checksum = g_checksum_new (G_CHECKSUM_SHA1);
339         g_checksum_update (checksum, g_bytes_get_data (data, NULL), g_bytes_get_size (data));
340         g_checksum_get_digest (checksum, hash, &n_hash);
341         g_checksum_free (checksum);
342
343         return g_bytes_new_take (hash, n_hash);
344 }
345
346 static GBytes *
347 prepare_to_be_signed (GcrCertificateRequest *self,
348                       GckMechanism *mechanism)
349 {
350         GNode *node;
351         GBytes *data;
352         GBytes *hash;
353
354         g_assert (mechanism != NULL);
355
356         node = egg_asn1x_node (self->asn, "certificationRequestInfo", NULL);
357         data = egg_asn1x_encode (node, NULL);
358
359         mechanism->parameter = NULL;
360         mechanism->n_parameter = 0;
361
362         switch (mechanism->type) {
363         case CKM_SHA1_RSA_PKCS:
364         case CKM_DSA_SHA1:
365                 return data;
366
367         case CKM_RSA_PKCS:
368                 hash = hash_sha1_pkcs1 (data);
369                 g_bytes_unref (data);
370                 return hash;
371
372         case CKM_DSA:
373                 hash = hash_sha1 (data);
374                 g_bytes_unref (data);
375                 return hash;
376
377         default:
378                 g_assert_not_reached ();
379                 return NULL;
380         }
381 }
382
383 static gboolean
384 prepare_subject_public_key_and_mechanisms (GcrCertificateRequest *self,
385                                            GNode *subject_public_key,
386                                            GQuark *algorithm,
387                                            const gulong **mechanisms,
388                                            gsize *n_mechanisms,
389                                            GError **error)
390 {
391         GBytes *encoded;
392         GNode *node;
393         GQuark oid;
394
395         g_assert (algorithm != NULL);
396         g_assert (mechanisms != NULL);
397         g_assert (n_mechanisms != NULL);
398
399         encoded = egg_asn1x_encode (subject_public_key, NULL);
400         g_return_val_if_fail (encoded != NULL, FALSE);
401
402         node = egg_asn1x_node (subject_public_key, "algorithm", "algorithm", NULL);
403         oid = egg_asn1x_get_oid_as_quark (node);
404
405         if (oid == GCR_OID_PKIX1_RSA) {
406                 *mechanisms = RSA_MECHANISMS;
407                 *n_mechanisms = G_N_ELEMENTS (RSA_MECHANISMS);
408                 *algorithm = GCR_OID_PKIX1_SHA1_WITH_RSA;
409
410         } else if (oid == GCR_OID_PKIX1_DSA) {
411                 *mechanisms = DSA_MECHANISMS;
412                 *n_mechanisms = G_N_ELEMENTS (DSA_MECHANISMS);
413                 *algorithm = GCR_OID_PKIX1_SHA1_WITH_DSA;
414
415         } else {
416                 g_bytes_unref (encoded);
417                 g_set_error (error, GCR_DATA_ERROR, GCR_ERROR_UNRECOGNIZED,
418                              _("Unsupported key type for certificate request"));
419                 return FALSE;
420         }
421
422         node = egg_asn1x_node (self->asn, "certificationRequestInfo", "subjectPKInfo", NULL);
423         if (!egg_asn1x_set_element_raw (node, encoded))
424                 g_return_val_if_reached (FALSE);
425
426         g_bytes_unref (encoded);
427         return TRUE;
428 }
429
430 static void
431 encode_take_signature_into_request (GcrCertificateRequest *self,
432                                     GQuark algorithm,
433                                     GNode *subject_public_key,
434                                     guchar *result,
435                                     gsize n_result)
436 {
437         GBytes *data;
438         GNode *params;
439         GNode *node;
440
441         node = egg_asn1x_node (self->asn, "signature", NULL);
442         egg_asn1x_take_bits_as_raw (node, g_bytes_new_take (result, n_result), n_result * 8);
443
444         node = egg_asn1x_node (self->asn, "signatureAlgorithm", "algorithm", NULL);
445         egg_asn1x_set_oid_as_quark (node, algorithm);
446
447         node = egg_asn1x_node (self->asn, "signatureAlgorithm", "parameters", NULL);
448         params = egg_asn1x_node (subject_public_key, "algorithm", "parameters", NULL);
449         data = egg_asn1x_encode (params, NULL);
450         egg_asn1x_set_element_raw (node, data);
451         g_bytes_unref (data);
452 }
453
454 /**
455  * gcr_certificate_request_complete:
456  * @self: a certificate request
457  * @cancellable: a cancellation object
458  * @error: location to place an error on failure
459  *
460  * Complete and sign a certificate request, so that it can be encoded
461  * and sent to a certificate authority.
462  *
463  * This call may block as it signs the request using the private key.
464  *
465  * Returns: whether certificate request was successfully completed or not
466  */
467 gboolean
468 gcr_certificate_request_complete (GcrCertificateRequest *self,
469                                   GCancellable *cancellable,
470                                   GError **error)
471 {
472         GNode *subject_public_key;
473         const gulong *mechanisms;
474         gsize n_mechanisms;
475         GckMechanism mechanism = { 0, };
476         GQuark algorithm = 0;
477         GBytes *tbs;
478         GckSession *session;
479         guchar *signature;
480         gsize n_signature;
481         gboolean ret;
482
483         g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), FALSE);
484         g_return_val_if_fail (cancellable == NULL || G_CANCELLABLE (cancellable), FALSE);
485         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
486
487         subject_public_key = _gcr_subject_public_key_load (self->private_key,
488                                                            cancellable, error);
489         if (subject_public_key == NULL)
490                 return FALSE;
491
492         ret = prepare_subject_public_key_and_mechanisms (self, subject_public_key,
493                                                          &algorithm, &mechanisms,
494                                                          &n_mechanisms, error);
495
496         if (!ret) {
497                 egg_asn1x_destroy (subject_public_key);
498                 return FALSE;
499         }
500
501         /* Figure out which mechanism to use */
502         mechanism.type = _gcr_key_mechanisms_check (self->private_key, mechanisms,
503                                                     n_mechanisms, CKA_SIGN,
504                                                     cancellable, NULL);
505         if (mechanism.type == GCK_INVALID) {
506                 egg_asn1x_destroy (subject_public_key);
507                 g_set_error (error, GCK_ERROR, CKR_KEY_TYPE_INCONSISTENT,
508                              _("The key cannot be used to sign the request"));
509                 return FALSE;
510         }
511
512         tbs = prepare_to_be_signed (self, &mechanism);
513         session = gck_object_get_session (self->private_key);
514         signature = gck_session_sign_full (session, self->private_key, &mechanism,
515                                            g_bytes_get_data (tbs, NULL),
516                                            g_bytes_get_size (tbs),
517                                            &n_signature, cancellable, error);
518         g_object_unref (session);
519         g_bytes_unref (tbs);
520
521         if (!signature) {
522                 egg_asn1x_destroy (subject_public_key);
523                 return FALSE;
524         }
525
526         encode_take_signature_into_request (self, algorithm, subject_public_key,
527                                             signature, n_signature);
528         egg_asn1x_destroy (subject_public_key);
529         return TRUE;
530 }
531
532 typedef struct {
533         GcrCertificateRequest *request;
534         GCancellable *cancellable;
535         GQuark algorithm;
536         GNode *subject_public_key;
537         GckMechanism mechanism;
538         GckSession *session;
539         GBytes *tbs;
540 } CompleteClosure;
541
542 static void
543 complete_closure_free (gpointer data)
544 {
545         CompleteClosure *closure = data;
546         egg_asn1x_destroy (closure->subject_public_key);
547         g_clear_object (&closure->request);
548         g_clear_object (&closure->cancellable);
549         g_clear_object (&closure->session);
550         if (closure->tbs)
551                 g_bytes_unref (closure->tbs);
552         g_free (closure);
553 }
554
555 static void
556 on_certificate_request_signed (GObject *source,
557                                GAsyncResult *result,
558                                gpointer user_data)
559 {
560         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
561         CompleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
562         GError *error = NULL;
563         guchar *signature;
564         gsize n_signature;
565
566         signature = gck_session_sign_finish (closure->session, result, &n_signature, &error);
567         if (error == NULL) {
568                 encode_take_signature_into_request (closure->request,
569                                                     closure->algorithm,
570                                                     closure->subject_public_key,
571                                                     signature, n_signature);
572
573         } else {
574                 g_simple_async_result_take_error (res, error);
575         }
576
577         g_simple_async_result_complete (res);
578         g_object_unref (res);
579 }
580
581 static void
582 on_mechanism_check (GObject *source,
583                     GAsyncResult *result,
584                     gpointer user_data)
585 {
586         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
587         CompleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
588
589         closure->mechanism.type =  _gcr_key_mechanisms_check_finish (closure->request->private_key,
590                                                                      result, NULL);
591         if (closure->mechanism.type == GCK_INVALID) {
592                 g_simple_async_result_set_error (res, GCK_ERROR, CKR_KEY_TYPE_INCONSISTENT,
593                                                  _("The key cannot be used to sign the request"));
594                 g_simple_async_result_complete (res);
595
596         } else {
597                 closure->tbs = prepare_to_be_signed (closure->request, &closure->mechanism);
598                 gck_session_sign_async (closure->session,
599                                         closure->request->private_key,
600                                         &closure->mechanism,
601                                         g_bytes_get_data (closure->tbs, NULL),
602                                         g_bytes_get_size (closure->tbs),
603                                         closure->cancellable,
604                                         on_certificate_request_signed,
605                                         g_object_ref (res));
606         }
607
608         g_object_unref (res);
609 }
610
611 static void
612 on_subject_public_key_loaded (GObject *source,
613                               GAsyncResult *result,
614                               gpointer user_data)
615 {
616         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
617         CompleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
618         const gulong *mechanisms;
619         gsize n_mechanisms;
620         GError *error = NULL;
621
622         closure->subject_public_key = _gcr_subject_public_key_load_finish (result, &error);
623         if (error == NULL) {
624                 prepare_subject_public_key_and_mechanisms (closure->request,
625                                                            closure->subject_public_key,
626                                                            &closure->algorithm,
627                                                            &mechanisms,
628                                                            &n_mechanisms,
629                                                            &error);
630         }
631
632         if (error != NULL) {
633                 g_simple_async_result_take_error (res, error);
634                 g_simple_async_result_complete (res);
635
636         } else {
637                 _gcr_key_mechanisms_check_async (closure->request->private_key,
638                                                  mechanisms, n_mechanisms, CKA_SIGN,
639                                                  closure->cancellable, on_mechanism_check,
640                                                  g_object_ref (res));
641         }
642
643         g_object_unref (res);
644 }
645
646 /**
647  * gcr_certificate_request_complete_async:
648  * @self: a certificate request
649  * @cancellable: a cancellation object
650  * @callback: called when the operation completes
651  * @user_data: data to pass to the callback
652  *
653  * Asynchronously complete and sign a certificate request, so that it can
654  * be encoded and sent to a certificate authority.
655  *
656  * This call will return immediately and complete later.
657  */
658 void
659 gcr_certificate_request_complete_async (GcrCertificateRequest *self,
660                                         GCancellable *cancellable,
661                                         GAsyncReadyCallback callback,
662                                         gpointer user_data)
663 {
664         GSimpleAsyncResult *res;
665         CompleteClosure *closure;
666
667         g_return_if_fail (GCR_IS_CERTIFICATE_REQUEST (self));
668         g_return_if_fail (cancellable == NULL || G_CANCELLABLE (cancellable));
669
670         res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
671                                          gcr_certificate_request_complete_async);
672         closure = g_new0 (CompleteClosure, 1);
673         closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
674         closure->session = gck_object_get_session (self->private_key);
675         closure->request = g_object_ref (self);
676         g_simple_async_result_set_op_res_gpointer (res, closure, complete_closure_free);
677
678         _gcr_subject_public_key_load_async (self->private_key, cancellable,
679                                             on_subject_public_key_loaded,
680                                             g_object_ref (res));
681
682         g_object_unref (res);
683 }
684
685 /**
686  * gcr_certificate_request_complete_finish:
687  * @self: a certificate request
688  * @result: result of the asynchronous operation
689  * @error: location to place an error on failure
690  *
691  * Finish an asynchronous operation to complete and sign a certificate
692  * request.
693  *
694  * Returns: whether certificate request was successfully completed or not
695  */
696 gboolean
697 gcr_certificate_request_complete_finish (GcrCertificateRequest *self,
698                                          GAsyncResult *result,
699                                          GError **error)
700 {
701         g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), FALSE);
702         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
703         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
704                               gcr_certificate_request_complete_async), FALSE);
705
706         if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
707                 return FALSE;
708
709         return TRUE;
710 }
711
712 /**
713  * gcr_certificate_request_encode:
714  * @self: a certificate request
715  * @textual: whether to encode output as text
716  * @length: location to place length of returned data
717  *
718  * Encode the certificate request. It must have been completed with
719  * gcr_certificate_request_complete() or gcr_certificate_request_complete_async()
720  *
721  * If @textual is %FALSE, the output is a DER encoded certificate request.
722  *
723  * If @textual is %TRUE, the output is encoded as text. For PKCS\#10 requests this
724  * is done using the OpenSSL style PEM encoding.
725  *
726  * Returns: (transfer full) (array length=length): the encoded certificate request
727  */
728 guchar *
729 gcr_certificate_request_encode (GcrCertificateRequest *self,
730                                 gboolean textual,
731                                 gsize *length)
732 {
733         GBytes *bytes;
734         gpointer encoded;
735         gpointer data;
736         gsize size;
737
738         g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), NULL);
739         g_return_val_if_fail (length != NULL, NULL);
740
741         bytes = egg_asn1x_encode (self->asn, NULL);
742         if (bytes == NULL) {
743                 g_warning ("couldn't encode certificate request: %s",
744                            egg_asn1x_message (self->asn));
745                 return NULL;
746         }
747
748         size = g_bytes_get_size (bytes);
749         encoded = g_byte_array_free (g_bytes_unref_to_array (bytes), FALSE);
750
751         if (textual) {
752                 data = egg_armor_write (encoded, size,
753                                         g_quark_from_static_string ("CERTIFICATE REQUEST"),
754                                         NULL, length);
755                 g_free (encoded);
756                 encoded = data;
757
758         } else {
759                 *length = size;
760         }
761
762         return encoded;
763 }
764
765 /**
766  * gcr_certificate_request_capable:
767  * @private_key: a private key
768  * @cancellable: cancellation object
769  * @error: location to place an error
770  *
771  * Check whether #GcrCertificateRequest is capable of creating a request
772  * for the given @private_key.
773  *
774  * Returns: whether a request can be created
775  */
776 gboolean
777 gcr_certificate_request_capable (GckObject *private_key,
778                                  GCancellable *cancellable,
779                                  GError **error)
780 {
781         g_return_val_if_fail (GCK_IS_OBJECT (private_key), FALSE);
782         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
783         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
784
785         return _gcr_key_mechanisms_check (private_key, ALL_MECHANISMS,
786                                           G_N_ELEMENTS (ALL_MECHANISMS),
787                                          CKA_SIGN, cancellable, error);
788 }
789
790 /**
791  * gcr_certificate_request_capable_async:
792  * @private_key: a private key
793  * @cancellable: cancellation object
794  * @callback: will be called when the operation completes
795  * @user_data: data to be passed to callback
796  *
797  * Asynchronously check whether #GcrCertificateRequest is capable of creating
798  * a request for the given @private_key.
799  */
800 void
801 gcr_certificate_request_capable_async (GckObject *private_key,
802                                        GCancellable *cancellable,
803                                        GAsyncReadyCallback callback,
804                                        gpointer user_data)
805 {
806         g_return_if_fail (GCK_IS_OBJECT (private_key));
807         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
808
809         _gcr_key_mechanisms_check_async (private_key, ALL_MECHANISMS,
810                                          G_N_ELEMENTS (ALL_MECHANISMS),
811                                          CKA_SIGN, cancellable,
812                                          callback, user_data);
813 }
814
815 /**
816  * gcr_certificate_request_capable_finish:
817  * @result: asynchronous result
818  * @error: location to place an error
819  *
820  * Get the result for asynchronously check whether #GcrCertificateRequest is
821  * capable of creating a request for the given @private_key.
822  *
823  * Returns: whether a request can be created
824  */
825 gboolean
826 gcr_certificate_request_capable_finish (GAsyncResult *result,
827                                         GError **error)
828 {
829         GObject *source;
830         gulong mech;
831
832         g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
833
834         source = g_async_result_get_source_object (result);
835         mech = _gcr_key_mechanisms_check_finish (GCK_OBJECT (source), result, error);
836         g_object_unref (source);
837
838         return mech != GCK_INVALID;
839 }