summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@src.gnome.org>2023-01-13 17:50:59 +0900
committerDaiki Ueno <dueno@src.gnome.org>2023-01-16 22:52:51 +0900
commit0c5b71b89e64fb0731aadc005643336f94058b7e (patch)
tree6580142c5b0aa9fb3ee077e32281f0a8dd2d7a98
parent0f60ab659df1431481d8d68046bb5b461853f4b3 (diff)
downloadgcr-0c5b71b89e64fb0731aadc005643336f94058b7e.tar.gz
gcr: Add means to construct GcrCertificate from PKCS #11 URI
This adds an alternative constructor for GcrPkcs11Certificate, namely gcr_pkcs11_certificate_new_from_uri and its async variant, which would allow applications to handle PKCS #11 certificates more easily.
-rw-r--r--gcr/gcr-pkcs11-certificate.c107
-rw-r--r--gcr/gcr-pkcs11-certificate.h12
-rw-r--r--gcr/test-pkcs11-certificate.c89
3 files changed, 188 insertions, 20 deletions
diff --git a/gcr/gcr-pkcs11-certificate.c b/gcr/gcr-pkcs11-certificate.c
index f5f798b..d441cfc 100644
--- a/gcr/gcr-pkcs11-certificate.c
+++ b/gcr/gcr-pkcs11-certificate.c
@@ -409,3 +409,110 @@ gcr_pkcs11_certificate_lookup_issuer_finish (GAsyncResult *result, GError **erro
return g_task_propagate_pointer (G_TASK (result), error);
}
+
+/**
+ * gcr_pkcs11_certificate_new_from_uri:
+ * @pkcs11_uri: a A PKCS \#11 URI
+ * @cancellable: (nullable): a #GCancellable
+ * @error: a #GError, or %NULL
+ *
+ * Lookup a certificate in the PKCS#11 storage by the given URI.
+ *
+ * This call may block, see gcr_pkcs11_certificate_new_from_uri_async() for the
+ * non-blocking version.
+ *
+ * Will return %NULL if no certificate is found. Use @error to determine
+ * if an error occurred.
+ *
+ * Returns: (transfer full) (nullable): a new #GcrCertificate, or %NULL
+ */
+GcrCertificate *
+gcr_pkcs11_certificate_new_from_uri (const gchar *pkcs11_uri,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GckUriData *data;
+ GcrCertificate *cert;
+
+ g_return_val_if_fail (pkcs11_uri != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ data = gck_uri_data_parse (pkcs11_uri, GCK_URI_FOR_OBJECT, error);
+ g_return_val_if_fail (data != NULL, NULL);
+
+ cert = perform_lookup_certificate (data->attributes, cancellable, error);
+ gck_uri_data_free (data);
+
+ return cert;
+}
+
+/**
+ * gcr_pkcs11_certificate_new_from_uri_async:
+ * @pkcs11_uri: a A PKCS \#11 URI
+ * @cancellable: (nullable): a #GCancellable
+ * @callback: a #GAsyncReadyCallback to call when the operation completes
+ * @user_data: the data to pass to callback function
+ *
+ * Lookup a certificate in the PKCS#11 storage by the given URI.
+ *
+ * When the operation is finished, callback will be called. You can then call
+ * gcr_pkcs11_certificate_new_from_uri_finish() to get the result of the
+ * operation.
+ */
+void
+gcr_pkcs11_certificate_new_from_uri_async (const gchar *pkcs11_uri,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ GckUriData *data;
+ GError *error = NULL;
+
+ g_return_if_fail (pkcs11_uri != NULL);
+ g_return_if_fail (cancellable == NULL || G_CANCELLABLE (cancellable));
+
+ task = g_task_new (NULL, cancellable, callback, user_data);
+ g_task_set_source_tag (task, gcr_pkcs11_certificate_new_from_uri_async);
+
+ data = gck_uri_data_parse (pkcs11_uri, GCK_URI_FOR_OBJECT, &error);
+ if (data == NULL) {
+ g_task_return_error (task, error);
+ return;
+ }
+
+ g_task_set_task_data (task, g_steal_pointer (&data->attributes), gck_attributes_unref);
+ gck_uri_data_free (data);
+
+ g_task_run_in_thread (task, thread_lookup_certificate);
+
+ g_object_unref (task);
+}
+
+/**
+ * gcr_pkcs11_certificate_new_from_uri_finish:
+ * @result: the #GAsyncResult passed to the callback
+ * @error: a #GError, or %NULL
+ *
+ * Finishes an asynchronous operation started by
+ * gcr_pkcs11_certificate_new_from_uri_async().
+ *
+ * Will return %NULL if no certificate is found. Use @error to determine
+ * if an error occurred.
+ *
+ * Returns: (transfer full) (nullable): a new #GcrCertificate, or %NULL
+ */
+GcrCertificate *
+gcr_pkcs11_certificate_new_from_uri_finish (GAsyncResult *result,
+ GError **error)
+{
+ GObject *source;
+
+ g_return_val_if_fail (G_IS_TASK (result), NULL);
+
+ source = g_task_get_source_object (G_TASK (result));
+ g_return_val_if_fail (g_task_is_valid (result, source), NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
diff --git a/gcr/gcr-pkcs11-certificate.h b/gcr/gcr-pkcs11-certificate.h
index 2ed2085..43d1764 100644
--- a/gcr/gcr-pkcs11-certificate.h
+++ b/gcr/gcr-pkcs11-certificate.h
@@ -72,6 +72,18 @@ void gcr_pkcs11_certificate_lookup_issuer_async (GcrCertif
GcrCertificate* gcr_pkcs11_certificate_lookup_issuer_finish (GAsyncResult *result,
GError **error);
+GcrCertificate* gcr_pkcs11_certificate_new_from_uri (const gchar *pkcs11_uri,
+ GCancellable *cancellable,
+ GError **error);
+
+void gcr_pkcs11_certificate_new_from_uri_async (const gchar *pkcs11_uri,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GcrCertificate* gcr_pkcs11_certificate_new_from_uri_finish (GAsyncResult *result,
+ GError **error);
+
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GcrPkcs11Certificate, g_object_unref)
G_END_DECLS
diff --git a/gcr/test-pkcs11-certificate.c b/gcr/test-pkcs11-certificate.c
index fab1b45..d4eb483 100644
--- a/gcr/test-pkcs11-certificate.c
+++ b/gcr/test-pkcs11-certificate.c
@@ -94,6 +94,7 @@ setup (Test *test, gconstpointer unused)
gck_builder_add_data (&builder, CKA_SUBJECT,
g_bytes_get_data (subject, NULL),
g_bytes_get_size (subject));
+ gck_builder_add_string (&builder, CKA_ID, "test-issuer");
gck_mock_module_add_object (gck_builder_end (&builder));
g_bytes_unref (bytes);
@@ -116,30 +117,20 @@ teardown (Test *test, gconstpointer unused)
}
static void
-test_lookup_certificate_issuer (Test *test, gconstpointer unused)
+assert_pkcs11_certificates_matches (Test *test, GcrCertificate *cert)
{
- GcrCertificate *cert, *issuer;
- GError *error = NULL;
GckAttributes *attrs;
const GckAttribute *attr;
gconstpointer der;
gsize n_der;
- cert = gcr_simple_certificate_new_static (test->cert_data, test->n_cert_data);
- g_assert (cert);
-
- /* Should be self-signed, so should find itself (added in setup) */
- issuer = gcr_pkcs11_certificate_lookup_issuer (cert, NULL, &error);
- g_assert (GCR_IS_PKCS11_CERTIFICATE (issuer));
- g_assert (error == NULL);
-
/* Should be the same certificate */
- der = gcr_certificate_get_der_data (issuer, &n_der);
+ der = gcr_certificate_get_der_data (cert, &n_der);
egg_assert_cmpsize (n_der, ==, test->n_cert_data);
g_assert (memcmp (der, test->cert_data, test->n_cert_data) == 0);
/* Should return the same certificate here too */
- attrs = gcr_pkcs11_certificate_get_attributes (GCR_PKCS11_CERTIFICATE (issuer));
+ attrs = gcr_pkcs11_certificate_get_attributes (GCR_PKCS11_CERTIFICATE (cert));
g_assert (attrs);
attr = gck_attributes_find (attrs, CKA_VALUE);
g_assert (attr);
@@ -148,13 +139,30 @@ test_lookup_certificate_issuer (Test *test, gconstpointer unused)
/* Should return the same certificate here too */
attrs = NULL;
- g_object_get (issuer, "attributes", &attrs, NULL);
+ g_object_get (cert, "attributes", &attrs, NULL);
g_assert (attrs);
attr = gck_attributes_find (attrs, CKA_VALUE);
g_assert (attr);
egg_assert_cmpsize (attr->length, ==, test->n_cert_data);
g_assert (memcmp (attr->value, test->cert_data, test->n_cert_data) == 0);
gck_attributes_unref (attrs);
+}
+
+static void
+test_lookup_certificate_issuer (Test *test, gconstpointer unused)
+{
+ GcrCertificate *cert, *issuer;
+ GError *error = NULL;
+
+ cert = gcr_simple_certificate_new_static (test->cert_data, test->n_cert_data);
+ g_assert (cert);
+
+ /* Should be self-signed, so should find itself (added in setup) */
+ issuer = gcr_pkcs11_certificate_lookup_issuer (cert, NULL, &error);
+ g_assert (GCR_IS_PKCS11_CERTIFICATE (issuer));
+ g_assert (error == NULL);
+
+ assert_pkcs11_certificates_matches (test, issuer);
g_object_unref (cert);
g_object_unref (issuer);
@@ -191,8 +199,6 @@ test_lookup_certificate_issuer_async (Test *test, gconstpointer unused)
GAsyncResult *result = NULL;
GcrCertificate *cert, *issuer;
GError *error = NULL;
- gconstpointer der;
- gsize n_der;
cert = gcr_simple_certificate_new_static (test->cert_data, test->n_cert_data);
g_assert (cert);
@@ -207,10 +213,7 @@ test_lookup_certificate_issuer_async (Test *test, gconstpointer unused)
g_object_unref (result);
result = NULL;
- /* Should be the same certificate */
- der = gcr_certificate_get_der_data (issuer, &n_der);
- egg_assert_cmpsize (n_der, ==, test->n_cert_data);
- g_assert (memcmp (der, test->cert_data, test->n_cert_data) == 0);
+ assert_pkcs11_certificates_matches (test, issuer);
g_object_unref (cert);
g_object_unref (issuer);
@@ -265,6 +268,50 @@ test_lookup_certificate_issuer_fail_async (Test *test, gconstpointer unused)
g_object_unref (cert);
}
+static void
+test_new_from_uri (Test *test, gconstpointer unused)
+{
+ GcrCertificate *cert, *issuer;
+ GError *error = NULL;
+
+ cert = gcr_simple_certificate_new_static (test->cert_data, test->n_cert_data);
+ g_assert (cert);
+
+ issuer = gcr_pkcs11_certificate_new_from_uri ("pkcs11:id=test-issuer", NULL, &error);
+ g_assert (GCR_IS_PKCS11_CERTIFICATE (issuer));
+ g_assert (error == NULL);
+
+ assert_pkcs11_certificates_matches (test, issuer);
+
+ g_object_unref (cert);
+ g_object_unref (issuer);
+}
+
+static void
+test_new_from_uri_async (Test *test, gconstpointer unused)
+{
+ GAsyncResult *result = NULL;
+ GcrCertificate *cert, *issuer;
+ GError *error = NULL;
+
+ cert = gcr_simple_certificate_new_static (test->cert_data, test->n_cert_data);
+ g_assert (cert);
+
+ gcr_pkcs11_certificate_new_from_uri_async ("pkcs11:id=test-issuer", NULL, fetch_async_result, &result);
+ egg_test_wait_until (500);
+ g_assert (result);
+ issuer = gcr_pkcs11_certificate_new_from_uri_finish (result, &error);
+ g_assert (GCR_IS_PKCS11_CERTIFICATE (issuer));
+ g_assert (error == NULL);
+ g_object_unref (result);
+ result = NULL;
+
+ assert_pkcs11_certificates_matches (test, issuer);
+
+ g_object_unref (cert);
+ g_object_unref (issuer);
+}
+
int
main (int argc, char **argv)
{
@@ -276,6 +323,8 @@ main (int argc, char **argv)
g_test_add ("/gcr/pkcs11-certificate/lookup_certificate_issuer_async", Test, NULL, setup, test_lookup_certificate_issuer_async, teardown);
g_test_add ("/gcr/pkcs11-certificate/lookup_certificate_issuer_failure", Test, NULL, setup, test_lookup_certificate_issuer_failure, teardown);
g_test_add ("/gcr/pkcs11-certificate/lookup_certificate_issuer_fail_async", Test, NULL, setup, test_lookup_certificate_issuer_fail_async, teardown);
+ g_test_add ("/gcr/pkcs11-certificate/new_from_uri", Test, NULL, setup, test_new_from_uri, teardown);
+ g_test_add ("/gcr/pkcs11-certificate/new_from_uri_async", Test, NULL, setup, test_new_from_uri_async, teardown);
return egg_tests_run_with_loop ();
}