2 * Copyright (C) 2011 Collabora Ltd.
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.
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.
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
19 * Author: Stef Walter <stefw@collabora.co.uk>
24 #include "gcr-certificate-request.h"
25 #include "gcr-key-mechanisms.h"
26 #include "gcr-enum-types-base.h"
28 #include "gcr-subject-public-key.h"
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>
35 #include <glib/gi18n-lib.h>
38 * SECTION:gcr-certificate-request
39 * @title: GcrCertificateRequest
40 * @short_description: Represents a certificate request
42 * This is an object that allows creation of certificate requests. A
43 * certificate request is sent to a certificate authority to request an
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().
53 * GcrCertificateRequest:
55 * Represents a certificate request.
59 * GcrCertificateRequestFormat:
60 * @GCR_CERTIFICATE_REQUEST_PKCS10: certificate request is in PKCS\#10 format
62 * The format of a certificate request. Currently only PKCS\#10 is supported.
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))
69 typedef struct _GcrCertificateRequestClass GcrCertificateRequestClass;
71 struct _GcrCertificateRequest {
74 GckObject *private_key;
80 struct _GcrCertificateRequestClass {
81 GObjectClass parent_class;
90 /* Forward declarations */
91 G_DEFINE_TYPE (GcrCertificateRequest, gcr_certificate_request, G_TYPE_OBJECT);
93 /* When updating here, update prepare_to_be_signed() */
94 static const gulong RSA_MECHANISMS[] = {
99 /* When updating here, update prepare_to_be_signed() */
100 static const gulong DSA_MECHANISMS[] = {
105 static const gulong ALL_MECHANISMS[] = {
112 G_STATIC_ASSERT (sizeof (ALL_MECHANISMS) == sizeof (RSA_MECHANISMS) + sizeof (DSA_MECHANISMS));
115 gcr_certificate_request_init (GcrCertificateRequest *self)
121 gcr_certificate_request_constructed (GObject *obj)
123 GcrCertificateRequest *self = GCR_CERTIFICATE_REQUEST (obj);
126 G_OBJECT_CLASS (gcr_certificate_request_parent_class)->constructed (obj);
128 self->asn = egg_asn1x_create (pkix_asn1_tab, "pkcs-10-CertificationRequest");
129 g_return_if_fail (self->asn != NULL);
131 /* Setup the version */
132 version = egg_asn1x_node (self->asn, "certificationRequestInfo", "version", NULL);
133 egg_asn1x_set_integer_as_ulong (version, 0);
137 gcr_certificate_request_finalize (GObject *obj)
139 GcrCertificateRequest *self = GCR_CERTIFICATE_REQUEST (obj);
141 egg_asn1x_destroy (self->asn);
142 g_free (self->mechanisms);
144 G_OBJECT_CLASS (gcr_certificate_request_parent_class)->finalize (obj);
148 gcr_certificate_request_set_property (GObject *obj,
153 GcrCertificateRequest *self = GCR_CERTIFICATE_REQUEST (obj);
154 GcrCertificateRequestFormat format;
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));
163 format = g_value_get_enum (value);
164 g_return_if_fail (format == GCR_CERTIFICATE_REQUEST_PKCS10);
167 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
173 gcr_certificate_request_get_property (GObject *obj,
178 GcrCertificateRequest *self = GCR_CERTIFICATE_REQUEST (obj);
181 case PROP_PRIVATE_KEY:
182 g_value_set_object (value, gcr_certificate_request_get_private_key (self));
185 g_value_set_enum (value, gcr_certificate_request_get_format (self));
188 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
194 gcr_certificate_request_class_init (GcrCertificateRequestClass *klass)
196 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
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;
204 * GcrCertificateRequest:private-key:
206 * The private key that this certificate request is for.
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));
213 * GcrCertificateRequest:format:
215 * The format of the certificate request.
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));
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
228 * Create a new certificate request, in the given format for the private key.
230 * Returns: (transfer full): a new #GcrCertificate request
232 GcrCertificateRequest *
233 gcr_certificate_request_prepare (GcrCertificateRequestFormat format,
234 GckObject *private_key)
236 g_return_val_if_fail (format == GCR_CERTIFICATE_REQUEST_PKCS10, NULL);
237 g_return_val_if_fail (GCK_IS_OBJECT (private_key), NULL);
239 return g_object_new (GCR_TYPE_CERTIFICATE_REQUEST,
241 "private-key", private_key,
246 * gcr_certificate_request_get_private_key:
247 * @self: the certificate request
249 * Get the private key this certificate request is for.
251 * Returns: (transfer none): the private key,
254 gcr_certificate_request_get_private_key (GcrCertificateRequest *self)
256 g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), NULL);
257 return self->private_key;
261 * gcr_certificate_request_get_format:
262 * @self: the certificate request
264 * Get the format of this certificate request.
266 * Returns: the format
268 GcrCertificateRequestFormat
269 gcr_certificate_request_get_format (GcrCertificateRequest *self)
271 g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), 0);
272 return GCR_CERTIFICATE_REQUEST_PKCS10;
276 * gcr_certificate_request_set_cn:
277 * @self: the certificate request
278 * @cn: common name to set on the request
280 * Set the common name encoded in the certificate request.
283 gcr_certificate_request_set_cn (GcrCertificateRequest *self,
289 g_return_if_fail (GCR_IS_CERTIFICATE_REQUEST (self));
290 g_return_if_fail (cn != NULL);
292 subject = egg_asn1x_node (self->asn, "certificationRequestInfo", "subject", NULL);
293 dn = egg_asn1x_node (subject, "rdnSequence", NULL);
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);
302 hash_sha1_pkcs1 (GBytes *data)
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 };
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));
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);
323 return g_bytes_new_take (hash, n_hash);
327 hash_sha1 (GBytes *data)
333 n_hash = g_checksum_type_get_length (G_CHECKSUM_SHA1);
334 hash = g_malloc (n_hash);
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);
341 return g_bytes_new_take (hash, n_hash);
345 prepare_to_be_signed (GcrCertificateRequest *self,
346 GckMechanism *mechanism)
352 g_assert (mechanism != NULL);
354 node = egg_asn1x_node (self->asn, "certificationRequestInfo", NULL);
355 data = egg_asn1x_encode (node, NULL);
357 mechanism->parameter = NULL;
358 mechanism->n_parameter = 0;
360 switch (mechanism->type) {
361 case CKM_SHA1_RSA_PKCS:
366 hash = hash_sha1_pkcs1 (data);
367 g_bytes_unref (data);
371 hash = hash_sha1 (data);
372 g_bytes_unref (data);
376 g_assert_not_reached ();
382 prepare_subject_public_key_and_mechanisms (GcrCertificateRequest *self,
383 GNode *subject_public_key,
385 const gulong **mechanisms,
393 g_assert (algorithm != NULL);
394 g_assert (mechanisms != NULL);
395 g_assert (n_mechanisms != NULL);
397 encoded = egg_asn1x_encode (subject_public_key, NULL);
398 g_return_val_if_fail (encoded != NULL, FALSE);
400 node = egg_asn1x_node (subject_public_key, "algorithm", "algorithm", NULL);
401 oid = egg_asn1x_get_oid_as_quark (node);
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;
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;
414 g_bytes_unref (encoded);
415 g_set_error (error, GCR_DATA_ERROR, GCR_ERROR_UNRECOGNIZED,
416 _("Unsupported key type for certificate request"));
420 node = egg_asn1x_node (self->asn, "certificationRequestInfo", "subjectPKInfo", NULL);
421 if (!egg_asn1x_decode (node, encoded))
422 g_return_val_if_reached (FALSE);
424 g_bytes_unref (encoded);
429 encode_take_signature_into_request (GcrCertificateRequest *self,
431 GNode *subject_public_key,
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);
441 node = egg_asn1x_node (self->asn, "signatureAlgorithm", "algorithm", NULL);
442 egg_asn1x_set_oid_as_quark (node, algorithm);
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);
450 * gcr_certificate_request_complete:
451 * @self: a certificate request
452 * @cancellable: a cancellation object
453 * @error: location to place an error on failure
455 * Complete and sign a certificate request, so that it can be encoded
456 * and sent to a certificate authority.
458 * This call may block as it signs the request using the private key.
460 * Returns: whether certificate request was successfully completed or not
463 gcr_certificate_request_complete (GcrCertificateRequest *self,
464 GCancellable *cancellable,
467 GNode *subject_public_key;
468 const gulong *mechanisms;
470 GckMechanism mechanism = { 0, };
471 GQuark algorithm = 0;
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);
482 subject_public_key = _gcr_subject_public_key_load (self->private_key,
484 if (subject_public_key == NULL)
487 ret = prepare_subject_public_key_and_mechanisms (self, subject_public_key,
488 &algorithm, &mechanisms,
489 &n_mechanisms, error);
492 egg_asn1x_destroy (subject_public_key);
496 /* Figure out which mechanism to use */
497 mechanism.type = _gcr_key_mechanisms_check (self->private_key, mechanisms,
498 n_mechanisms, CKA_SIGN,
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"));
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);
517 egg_asn1x_destroy (subject_public_key);
521 encode_take_signature_into_request (self, algorithm, subject_public_key,
522 signature, n_signature);
523 egg_asn1x_destroy (subject_public_key);
528 GcrCertificateRequest *request;
529 GCancellable *cancellable;
531 GNode *subject_public_key;
532 GckMechanism mechanism;
538 complete_closure_free (gpointer data)
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);
546 g_bytes_unref (closure->tbs);
551 on_certificate_request_signed (GObject *source,
552 GAsyncResult *result,
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;
561 signature = gck_session_sign_finish (closure->session, result, &n_signature, &error);
563 encode_take_signature_into_request (closure->request,
565 closure->subject_public_key,
566 signature, n_signature);
569 g_simple_async_result_take_error (res, error);
572 g_simple_async_result_complete (res);
573 g_object_unref (res);
577 on_mechanism_check (GObject *source,
578 GAsyncResult *result,
581 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
582 CompleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
584 closure->mechanism.type = _gcr_key_mechanisms_check_finish (closure->request->private_key,
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);
592 closure->tbs = prepare_to_be_signed (closure->request, &closure->mechanism);
593 gck_session_sign_async (closure->session,
594 closure->request->private_key,
596 g_bytes_get_data (closure->tbs, NULL),
597 g_bytes_get_size (closure->tbs),
598 closure->cancellable,
599 on_certificate_request_signed,
603 g_object_unref (res);
607 on_subject_public_key_loaded (GObject *source,
608 GAsyncResult *result,
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;
615 GError *error = NULL;
617 closure->subject_public_key = _gcr_subject_public_key_load_finish (result, &error);
619 prepare_subject_public_key_and_mechanisms (closure->request,
620 closure->subject_public_key,
628 g_simple_async_result_take_error (res, error);
629 g_simple_async_result_complete (res);
632 _gcr_key_mechanisms_check_async (closure->request->private_key,
633 mechanisms, n_mechanisms, CKA_SIGN,
634 closure->cancellable, on_mechanism_check,
638 g_object_unref (res);
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
648 * Asynchronously complete and sign a certificate request, so that it can
649 * be encoded and sent to a certificate authority.
651 * This call will return immediately and complete later.
654 gcr_certificate_request_complete_async (GcrCertificateRequest *self,
655 GCancellable *cancellable,
656 GAsyncReadyCallback callback,
659 GSimpleAsyncResult *res;
660 CompleteClosure *closure;
662 g_return_if_fail (GCR_IS_CERTIFICATE_REQUEST (self));
663 g_return_if_fail (cancellable == NULL || G_CANCELLABLE (cancellable));
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);
673 _gcr_subject_public_key_load_async (self->private_key, cancellable,
674 on_subject_public_key_loaded,
677 g_object_unref (res);
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
686 * Finish an asynchronous operation to complete and sign a certificate
689 * Returns: whether certificate request was successfully completed or not
692 gcr_certificate_request_complete_finish (GcrCertificateRequest *self,
693 GAsyncResult *result,
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);
701 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
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
713 * Encode the certificate request. It must have been completed with
714 * gcr_certificate_request_complete() or gcr_certificate_request_complete_async()
716 * If @textual is %FALSE, the output is a DER encoded certificate request.
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.
721 * Returns: (transfer full) (array length=length): the encoded certificate request
724 gcr_certificate_request_encode (GcrCertificateRequest *self,
733 g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), NULL);
734 g_return_val_if_fail (length != NULL, NULL);
736 bytes = egg_asn1x_encode (self->asn, NULL);
738 g_warning ("couldn't encode certificate request: %s",
739 egg_asn1x_message (self->asn));
743 size = g_bytes_get_size (bytes);
744 encoded = g_byte_array_free (g_bytes_unref_to_array (bytes), FALSE);
747 data = egg_armor_write (encoded, size,
748 g_quark_from_static_string ("CERTIFICATE REQUEST"),
761 * gcr_certificate_request_capable:
762 * @private_key: a private key
763 * @cancellable: cancellation object
764 * @error: location to place an error
766 * Check whether #GcrCertificateRequest is capable of creating a request
767 * for the given @private_key.
769 * Returns: whether a request can be created
772 gcr_certificate_request_capable (GckObject *private_key,
773 GCancellable *cancellable,
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);
780 return _gcr_key_mechanisms_check (private_key, ALL_MECHANISMS,
781 G_N_ELEMENTS (ALL_MECHANISMS),
782 CKA_SIGN, cancellable, error);
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
792 * Asynchronously check whether #GcrCertificateRequest is capable of creating
793 * a request for the given @private_key.
796 gcr_certificate_request_capable_async (GckObject *private_key,
797 GCancellable *cancellable,
798 GAsyncReadyCallback callback,
801 g_return_if_fail (GCK_IS_OBJECT (private_key));
802 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
804 _gcr_key_mechanisms_check_async (private_key, ALL_MECHANISMS,
805 G_N_ELEMENTS (ALL_MECHANISMS),
806 CKA_SIGN, cancellable,
807 callback, user_data);
811 * gcr_certificate_request_capable_finish:
812 * @result: asynchronous result
813 * @error: location to place an error
815 * Get the result for asynchronously check whether #GcrCertificateRequest is
816 * capable of creating a request for the given @private_key.
818 * Returns: whether a request can be created
821 gcr_certificate_request_capable_finish (GAsyncResult *result,
827 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
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);
833 return mech != GCK_INVALID;