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);
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;
206 * GcrCertificateRequest:private-key:
208 * The private key that this certificate request is for.
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));
215 * GcrCertificateRequest:format:
217 * The format of the certificate request.
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));
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
230 * Create a new certificate request, in the given format for the private key.
232 * Returns: (transfer full): a new #GcrCertificate request
234 GcrCertificateRequest *
235 gcr_certificate_request_prepare (GcrCertificateRequestFormat format,
236 GckObject *private_key)
238 g_return_val_if_fail (format == GCR_CERTIFICATE_REQUEST_PKCS10, NULL);
239 g_return_val_if_fail (GCK_IS_OBJECT (private_key), NULL);
241 return g_object_new (GCR_TYPE_CERTIFICATE_REQUEST,
243 "private-key", private_key,
248 * gcr_certificate_request_get_private_key:
249 * @self: the certificate request
251 * Get the private key this certificate request is for.
253 * Returns: (transfer none): the private key,
256 gcr_certificate_request_get_private_key (GcrCertificateRequest *self)
258 g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), NULL);
259 return self->private_key;
263 * gcr_certificate_request_get_format:
264 * @self: the certificate request
266 * Get the format of this certificate request.
268 * Returns: the format
270 GcrCertificateRequestFormat
271 gcr_certificate_request_get_format (GcrCertificateRequest *self)
273 g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), 0);
274 return GCR_CERTIFICATE_REQUEST_PKCS10;
278 * gcr_certificate_request_set_cn:
279 * @self: the certificate request
280 * @cn: common name to set on the request
282 * Set the common name encoded in the certificate request.
285 gcr_certificate_request_set_cn (GcrCertificateRequest *self,
291 g_return_if_fail (GCR_IS_CERTIFICATE_REQUEST (self));
292 g_return_if_fail (cn != NULL);
294 subject = egg_asn1x_node (self->asn, "certificationRequestInfo", "subject", NULL);
295 dn = egg_asn1x_node (subject, "rdnSequence", NULL);
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);
304 hash_sha1_pkcs1 (EggBytes *data)
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 };
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));
320 checksum = g_checksum_new (G_CHECKSUM_SHA1);
321 g_checksum_update (checksum, egg_bytes_get_data (data), egg_bytes_get_size (data));
322 g_checksum_get_digest (checksum, hash + sizeof (SHA1_ASN), &n_digest);
323 g_checksum_free (checksum);
325 return egg_bytes_new_take (hash, n_hash);
329 hash_sha1 (EggBytes *data)
335 n_hash = g_checksum_type_get_length (G_CHECKSUM_SHA1);
336 hash = g_malloc (n_hash);
338 checksum = g_checksum_new (G_CHECKSUM_SHA1);
339 g_checksum_update (checksum, egg_bytes_get_data (data), egg_bytes_get_size (data));
340 g_checksum_get_digest (checksum, hash, &n_hash);
341 g_checksum_free (checksum);
343 return egg_bytes_new_take (hash, n_hash);
347 prepare_to_be_signed (GcrCertificateRequest *self,
348 GckMechanism *mechanism)
354 g_assert (mechanism != NULL);
356 node = egg_asn1x_node (self->asn, "certificationRequestInfo", NULL);
357 data = egg_asn1x_encode (node, NULL);
359 mechanism->parameter = NULL;
360 mechanism->n_parameter = 0;
362 switch (mechanism->type) {
363 case CKM_SHA1_RSA_PKCS:
368 hash = hash_sha1_pkcs1 (data);
369 egg_bytes_unref (data);
373 hash = hash_sha1 (data);
374 egg_bytes_unref (data);
378 g_assert_not_reached ();
384 prepare_subject_public_key_and_mechanisms (GcrCertificateRequest *self,
385 GNode *subject_public_key,
387 const gulong **mechanisms,
395 g_assert (algorithm != NULL);
396 g_assert (mechanisms != NULL);
397 g_assert (n_mechanisms != NULL);
399 encoded = egg_asn1x_encode (subject_public_key, NULL);
400 g_return_val_if_fail (encoded != NULL, FALSE);
402 node = egg_asn1x_node (subject_public_key, "algorithm", "algorithm", NULL);
403 oid = egg_asn1x_get_oid_as_quark (node);
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;
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;
416 egg_bytes_unref (encoded);
417 g_set_error (error, GCR_DATA_ERROR, GCR_ERROR_UNRECOGNIZED,
418 _("Unsupported key type for certificate request"));
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);
426 egg_bytes_unref (encoded);
431 encode_take_signature_into_request (GcrCertificateRequest *self,
433 GNode *subject_public_key,
441 node = egg_asn1x_node (self->asn, "signature", NULL);
442 egg_asn1x_take_bits_as_raw (node, egg_bytes_new_take (result, n_result), n_result * 8);
444 node = egg_asn1x_node (self->asn, "signatureAlgorithm", "algorithm", NULL);
445 egg_asn1x_set_oid_as_quark (node, algorithm);
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 egg_bytes_unref (data);
455 * gcr_certificate_request_complete:
456 * @self: a certificate request
457 * @cancellable: a cancellation object
458 * @error: location to place an error on failure
460 * Complete and sign a certificate request, so that it can be encoded
461 * and sent to a certificate authority.
463 * This call may block as it signs the request using the private key.
465 * Returns: whether certificate request was successfully completed or not
468 gcr_certificate_request_complete (GcrCertificateRequest *self,
469 GCancellable *cancellable,
472 GNode *subject_public_key;
473 const gulong *mechanisms;
475 GckMechanism mechanism = { 0, };
476 GQuark algorithm = 0;
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);
487 subject_public_key = _gcr_subject_public_key_load (self->private_key,
489 if (subject_public_key == NULL)
492 ret = prepare_subject_public_key_and_mechanisms (self, subject_public_key,
493 &algorithm, &mechanisms,
494 &n_mechanisms, error);
497 egg_asn1x_destroy (subject_public_key);
501 /* Figure out which mechanism to use */
502 mechanism.type = _gcr_key_mechanisms_check (self->private_key, mechanisms,
503 n_mechanisms, CKA_SIGN,
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"));
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 egg_bytes_get_data (tbs),
516 egg_bytes_get_size (tbs),
517 &n_signature, cancellable, error);
518 g_object_unref (session);
519 egg_bytes_unref (tbs);
522 egg_asn1x_destroy (subject_public_key);
526 encode_take_signature_into_request (self, algorithm, subject_public_key,
527 signature, n_signature);
528 egg_asn1x_destroy (subject_public_key);
533 GcrCertificateRequest *request;
534 GCancellable *cancellable;
536 GNode *subject_public_key;
537 GckMechanism mechanism;
543 complete_closure_free (gpointer data)
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);
551 egg_bytes_unref (closure->tbs);
556 on_certificate_request_signed (GObject *source,
557 GAsyncResult *result,
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;
566 signature = gck_session_sign_finish (closure->session, result, &n_signature, &error);
568 encode_take_signature_into_request (closure->request,
570 closure->subject_public_key,
571 signature, n_signature);
574 g_simple_async_result_take_error (res, error);
577 g_simple_async_result_complete (res);
578 g_object_unref (res);
582 on_mechanism_check (GObject *source,
583 GAsyncResult *result,
586 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
587 CompleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
589 closure->mechanism.type = _gcr_key_mechanisms_check_finish (closure->request->private_key,
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);
597 closure->tbs = prepare_to_be_signed (closure->request, &closure->mechanism);
598 gck_session_sign_async (closure->session,
599 closure->request->private_key,
601 egg_bytes_get_data (closure->tbs),
602 egg_bytes_get_size (closure->tbs),
603 closure->cancellable,
604 on_certificate_request_signed,
608 g_object_unref (res);
612 on_subject_public_key_loaded (GObject *source,
613 GAsyncResult *result,
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;
620 GError *error = NULL;
622 closure->subject_public_key = _gcr_subject_public_key_load_finish (result, &error);
624 prepare_subject_public_key_and_mechanisms (closure->request,
625 closure->subject_public_key,
633 g_simple_async_result_take_error (res, error);
634 g_simple_async_result_complete (res);
637 _gcr_key_mechanisms_check_async (closure->request->private_key,
638 mechanisms, n_mechanisms, CKA_SIGN,
639 closure->cancellable, on_mechanism_check,
643 g_object_unref (res);
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
653 * Asynchronously complete and sign a certificate request, so that it can
654 * be encoded and sent to a certificate authority.
656 * This call will return immediately and complete later.
659 gcr_certificate_request_complete_async (GcrCertificateRequest *self,
660 GCancellable *cancellable,
661 GAsyncReadyCallback callback,
664 GSimpleAsyncResult *res;
665 CompleteClosure *closure;
667 g_return_if_fail (GCR_IS_CERTIFICATE_REQUEST (self));
668 g_return_if_fail (cancellable == NULL || G_CANCELLABLE (cancellable));
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);
678 _gcr_subject_public_key_load_async (self->private_key, cancellable,
679 on_subject_public_key_loaded,
682 g_object_unref (res);
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
691 * Finish an asynchronous operation to complete and sign a certificate
694 * Returns: whether certificate request was successfully completed or not
697 gcr_certificate_request_complete_finish (GcrCertificateRequest *self,
698 GAsyncResult *result,
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);
706 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
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
718 * Encode the certificate request. It must have been completed with
719 * gcr_certificate_request_complete() or gcr_certificate_request_complete_async()
721 * If @textual is %FALSE, the output is a DER encoded certificate request.
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.
726 * Returns: (transfer full) (array length=length): the encoded certificate request
729 gcr_certificate_request_encode (GcrCertificateRequest *self,
738 g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), NULL);
739 g_return_val_if_fail (length != NULL, NULL);
741 bytes = egg_asn1x_encode (self->asn, NULL);
743 g_warning ("couldn't encode certificate request: %s",
744 egg_asn1x_message (self->asn));
748 size = egg_bytes_get_size (bytes);
749 encoded = g_byte_array_free (egg_bytes_unref_to_array (bytes), FALSE);
752 data = egg_armor_write (encoded, size,
753 g_quark_from_static_string ("CERTIFICATE REQUEST"),
766 gcr_certificate_request_capable (GckObject *private_key,
767 GCancellable *cancellable,
770 g_return_val_if_fail (GCK_IS_OBJECT (private_key), FALSE);
771 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
772 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
774 return _gcr_key_mechanisms_check (private_key, ALL_MECHANISMS,
775 G_N_ELEMENTS (ALL_MECHANISMS),
776 CKA_SIGN, cancellable, error);
780 gcr_certificate_request_capable_async (GckObject *private_key,
781 GCancellable *cancellable,
782 GAsyncReadyCallback callback,
785 g_return_if_fail (GCK_IS_OBJECT (private_key));
786 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
788 _gcr_key_mechanisms_check_async (private_key, ALL_MECHANISMS,
789 G_N_ELEMENTS (ALL_MECHANISMS),
790 CKA_SIGN, cancellable,
791 callback, user_data);
795 gcr_certificate_request_capable_finish (GAsyncResult *result,
801 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
803 source = g_async_result_get_source_object (result);
804 mech = _gcr_key_mechanisms_check_finish (GCK_OBJECT (source), result, error);
805 g_object_unref (source);
807 return mech != GCK_INVALID;