4 * Copyright (C) 2010 Collabora Ltd
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 * Author: Stef Walter <stefw@collabora.co.uk>
26 #include "gcr-pkcs11-certificate.h"
28 #include "gcr-certificate.h"
29 #include "gcr-internal.h"
30 #include "gcr-library.h"
37 * SECTION:gcr-pkcs11-certificate
38 * @title: GcrPkcs11Certificate
39 * @short_description: A certificate loaded from PKCS\#11 storage
41 * A #GcrPkcs11Certificate is a certificate loaded from a PKCS\#11 storage.
42 * It is also a valid #GckObject and can be used as such.
44 * Use gcr_pkcs11_certificate_lookup_issuer() to lookup the issuer of a given
45 * certificate in the PKCS\#11 store.
47 * Various common PKCS\#11 certificate attributes are automatically loaded and
48 * are available via gcr_pkcs11_certificate_get_attributes().
52 * GcrPkcs11Certificate:
54 * A certificate loaded from PKCS\#11 storage.
58 * GcrPkcs11CertificateClass:
60 * The class for #GcrPkcs11Certificate.
68 struct _GcrPkcs11CertificatePrivate {
72 static void gcr_certificate_iface (GcrCertificateIface *iface);
73 G_DEFINE_TYPE_WITH_CODE (GcrPkcs11Certificate, gcr_pkcs11_certificate, GCK_TYPE_OBJECT,
74 GCR_CERTIFICATE_MIXIN_IMPLEMENT_COMPARABLE ();
75 G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, gcr_certificate_iface);
79 GckAttributes *search;
80 GcrCertificate *result;
81 } lookup_issuer_closure;
84 lookup_issuer_free (gpointer data)
86 lookup_issuer_closure *closure = data;
87 gck_attributes_unref (closure->search);
88 g_clear_object (&closure->result);
92 static GckAttributes *
93 prepare_lookup_certificate_issuer (GcrCertificate *cert)
95 GckBuilder builder = GCK_BUILDER_INIT;
99 gck_builder_add_ulong (&builder, CKA_CLASS, CKO_CERTIFICATE);
100 gck_builder_add_ulong (&builder, CKA_CERTIFICATE_TYPE, CKC_X_509);
102 data = gcr_certificate_get_issuer_raw (cert, &n_data);
103 gck_builder_add_data (&builder, CKA_SUBJECT, data, n_data);
106 return gck_attributes_ref_sink (gck_builder_end (&builder));
109 static GcrCertificate*
110 perform_lookup_certificate (GckAttributes *search,
111 GCancellable *cancellable,
114 GcrCertificate *cert;
116 GckAttributes *attrs;
122 if (!gcr_pkcs11_initialize (cancellable, error))
125 modules = gcr_pkcs11_get_modules ();
126 en = gck_modules_enumerate_objects (modules, search, 0);
127 gck_list_unref_free (modules);
129 object = gck_enumerator_next (en, cancellable, error);
136 * Only the CKA_VALUE, CKA_CLASS and CKA_CERTIFICATE_TYPE
137 * is strictly necessary here, but we get more attrs.
139 attrs = gck_object_get (object, cancellable, error,
140 CKA_VALUE, CKA_LABEL,
142 CKA_CERTIFICATE_TYPE,
148 g_object_unref (object);
152 module = gck_object_get_module (object);
153 session = gck_object_get_session (object);
155 cert = g_object_new (GCR_TYPE_PKCS11_CERTIFICATE,
157 "handle", gck_object_get_handle (object),
162 g_object_unref (module);
163 g_object_unref (session);
164 g_object_unref (object);
166 gck_attributes_unref (attrs);
172 thread_lookup_certificate (GSimpleAsyncResult *res, GObject *object, GCancellable *cancel)
174 lookup_issuer_closure *closure;
175 GError *error = NULL;
177 closure = g_simple_async_result_get_op_res_gpointer (res);
178 closure->result = perform_lookup_certificate (closure->search, cancel, &error);
181 g_simple_async_result_set_from_error (res, error);
182 g_clear_error (&error);
186 /* ----------------------------------------------------------------------------
191 gcr_pkcs11_certificate_constructor (GType type, guint n_props, GObjectConstructParam *props)
193 gpointer obj = G_OBJECT_CLASS (gcr_pkcs11_certificate_parent_class)->constructor (type, n_props, props);
194 GckAttributes *attrs;
195 const GckAttribute *attr;
198 attrs = gcr_pkcs11_certificate_get_attributes (obj);
199 g_return_val_if_fail (attrs, NULL);
201 if (!gck_attributes_find_ulong (attrs, CKA_CLASS, &value) ||
202 value != CKO_CERTIFICATE) {
203 g_warning ("attributes don't contain a certificate with: %s",
204 "CKA_CLASS == CKO_CERTIFICATE");
208 if (!gck_attributes_find_ulong (attrs, CKA_CERTIFICATE_TYPE, &value) ||
209 value != CKC_X_509) {
210 g_warning ("attributes don't contain a certificate with: %s",
211 "CKA_CERTIFICATE_TYPE == CKC_X_509");
215 attr = gck_attributes_find (attrs, CKA_VALUE);
216 if (!attr || !attr->value || attr->length == 0 || attr->length == G_MAXULONG) {
217 g_warning ("attributes don't contain a valid: CKA_VALUE");
225 gcr_pkcs11_certificate_init (GcrPkcs11Certificate *self)
227 self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_PKCS11_CERTIFICATE, GcrPkcs11CertificatePrivate);
231 gcr_pkcs11_certificate_set_property (GObject *obj, guint prop_id, const GValue *value,
234 GcrPkcs11Certificate *self = GCR_PKCS11_CERTIFICATE (obj);
237 case PROP_ATTRIBUTES:
238 g_return_if_fail (self->pv->attrs == NULL);
239 self->pv->attrs = g_value_dup_boxed (value);
240 g_return_if_fail (self->pv->attrs != NULL);
243 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
249 gcr_pkcs11_certificate_get_property (GObject *obj, guint prop_id, GValue *value,
252 GcrPkcs11Certificate *self = GCR_PKCS11_CERTIFICATE (obj);
255 case PROP_ATTRIBUTES:
256 g_value_set_boxed (value, gcr_pkcs11_certificate_get_attributes (self));
259 gcr_certificate_mixin_get_property (obj, prop_id, value, pspec);
265 gcr_pkcs11_certificate_finalize (GObject *obj)
267 GcrPkcs11Certificate *self = GCR_PKCS11_CERTIFICATE (obj);
269 gck_attributes_unref (self->pv->attrs);
271 G_OBJECT_CLASS (gcr_pkcs11_certificate_parent_class)->finalize (obj);
275 gcr_pkcs11_certificate_class_init (GcrPkcs11CertificateClass *klass)
277 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
279 gobject_class->constructor = gcr_pkcs11_certificate_constructor;
280 gobject_class->get_property = gcr_pkcs11_certificate_get_property;
281 gobject_class->set_property = gcr_pkcs11_certificate_set_property;
282 gobject_class->finalize = gcr_pkcs11_certificate_finalize;
285 * GcrPkcs11Certificate:attributes:
287 * Automatically loaded attributes for this certificate.
289 g_object_class_install_property (gobject_class, PROP_ATTRIBUTES,
290 g_param_spec_boxed ("attributes", "Attributes", "The data displayed in the renderer",
291 GCK_TYPE_ATTRIBUTES, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
293 g_type_class_add_private (gobject_class, sizeof (GcrPkcs11CertificatePrivate));
295 gcr_certificate_mixin_class_init (gobject_class);
296 _gcr_initialize_library ();
299 static const guchar *
300 gcr_pkcs11_certificate_get_der_data (GcrCertificate *cert,
303 GcrPkcs11Certificate *self = GCR_PKCS11_CERTIFICATE (cert);
304 const GckAttribute *attr;
306 g_return_val_if_fail (GCR_IS_CERTIFICATE (self), NULL);
307 g_return_val_if_fail (n_data, NULL);
308 g_return_val_if_fail (self->pv->attrs, NULL);
310 attr = gck_attributes_find (self->pv->attrs, CKA_VALUE);
311 g_return_val_if_fail (attr && attr->length != 0 && attr->length != G_MAXULONG, NULL);
312 *n_data = attr->length;
317 gcr_certificate_iface (GcrCertificateIface *iface)
319 iface->get_der_data = gcr_pkcs11_certificate_get_der_data;
322 /* -----------------------------------------------------------------------------
327 * gcr_pkcs11_certificate_get_attributes:
328 * @self: A #GcrPkcs11Certificate
330 * Access the automatically loaded attributes for this certificate.
332 * Returns: (transfer none): the certificate attributes
335 gcr_pkcs11_certificate_get_attributes (GcrPkcs11Certificate *self)
337 g_return_val_if_fail (GCR_IS_PKCS11_CERTIFICATE (self), NULL);
338 return self->pv->attrs;
342 * gcr_pkcs11_certificate_lookup_issuer:
343 * @certificate: a #GcrCertificate
344 * @cancellable: a #GCancellable
345 * @error: a #GError, or NULL
347 * Lookup a the issuer of a @certificate in the PKCS\#11 storage. The
348 * lookup is done using the issuer DN of the certificate. No certificate chain
349 * verification is done. Use a crypto library to make trust decisions.
351 * This call may block, see gcr_pkcs11_certificate_lookup_issuer() for the
352 * non-blocking version.
354 * Will return %NULL if no issuer certificate is found. Use @error to determine
355 * if an error occurred.
357 * Returns: (transfer full): a new #GcrPkcs11Certificate, or %NULL
360 gcr_pkcs11_certificate_lookup_issuer (GcrCertificate *certificate, GCancellable *cancellable,
363 GckAttributes *search;
364 GcrCertificate *issuer;
366 g_return_val_if_fail (GCR_IS_CERTIFICATE (certificate), NULL);
368 if (!gcr_pkcs11_initialize (cancellable, error))
371 search = prepare_lookup_certificate_issuer (certificate);
372 g_return_val_if_fail (search, FALSE);
374 issuer = perform_lookup_certificate (search, cancellable, error);
375 gck_attributes_unref (search);
381 * gcr_pkcs11_certificate_lookup_issuer_async:
382 * @certificate: a #GcrCertificate
383 * @cancellable: a #GCancellable
384 * @callback: a #GAsyncReadyCallback to call when the operation completes
385 * @user_data: the data to pass to callback function
387 * Lookup a the issuer of a @certificate in the PKCS\#11 storage. The
388 * lookup is done using the issuer DN of the certificate. No certificate chain
389 * verification is done. Use a crypto library to make trust decisions.
391 * When the operation is finished, callback will be called. You can then call
392 * gcr_pkcs11_certificate_lookup_issuer_finish() to get the result of the
396 gcr_pkcs11_certificate_lookup_issuer_async (GcrCertificate *certificate, GCancellable *cancellable,
397 GAsyncReadyCallback callback, gpointer user_data)
399 GSimpleAsyncResult *async;
400 lookup_issuer_closure *closure;
402 g_return_if_fail (GCR_IS_CERTIFICATE (certificate));
404 async = g_simple_async_result_new (G_OBJECT (certificate), callback, user_data,
405 gcr_pkcs11_certificate_lookup_issuer_async);
406 closure = g_new0 (lookup_issuer_closure, 1);
407 closure->search = prepare_lookup_certificate_issuer (certificate);
408 g_return_if_fail (closure->search);
409 g_simple_async_result_set_op_res_gpointer (async, closure, lookup_issuer_free);
411 g_simple_async_result_run_in_thread (async, thread_lookup_certificate,
412 G_PRIORITY_DEFAULT, cancellable);
414 g_object_unref (async);
418 * gcr_pkcs11_certificate_lookup_issuer_finish:
419 * @result: the #GAsyncResult passed to the callback
420 * @error: a #GError, or NULL
422 * Finishes an asynchronous operation started by
423 * gcr_pkcs11_certificate_lookup_issuer_async().
425 * Will return %NULL if no issuer certificate is found. Use @error to determine
426 * if an error occurred.
428 * Returns: (transfer full): a new #GcrPkcs11Certificate, or %NULL
431 gcr_pkcs11_certificate_lookup_issuer_finish (GAsyncResult *result, GError **error)
433 lookup_issuer_closure *closure;
436 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
438 source = g_async_result_get_source_object (result);
439 g_return_val_if_fail (g_simple_async_result_is_valid (result, source,
440 gcr_pkcs11_certificate_lookup_issuer_async), NULL);
441 g_object_unref (source);
443 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
446 closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
447 if (closure->result != NULL)
448 g_object_ref (closure->result);
449 return closure->result;