diff options
author | Daiki Ueno <dueno@src.gnome.org> | 2023-01-13 17:50:59 +0900 |
---|---|---|
committer | Daiki Ueno <dueno@src.gnome.org> | 2023-01-16 22:52:51 +0900 |
commit | 0c5b71b89e64fb0731aadc005643336f94058b7e (patch) | |
tree | 6580142c5b0aa9fb3ee077e32281f0a8dd2d7a98 | |
parent | 0f60ab659df1431481d8d68046bb5b461853f4b3 (diff) | |
download | gcr-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.c | 107 | ||||
-rw-r--r-- | gcr/gcr-pkcs11-certificate.h | 12 | ||||
-rw-r--r-- | gcr/test-pkcs11-certificate.c | 89 |
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 (); } |