3
#include "test-suite.h"
5
#include "egg/egg-asn1x.h"
6
#include "egg/egg-asn1-defs.h"
9
#include "gcr/gcr-internal.h"
11
#include "gck/gck-mock.h"
12
#include "gck/gck-test.h"
14
#include "pkcs11/pkcs11.h"
15
#include "pkcs11/pkcs11x.h"
21
/* ---------------------------------------------------------------------------
22
* A Mock certificate that checks that it's always called on the
23
* same thread. A GcrCertificate implemented on top of a non-thread-safe
24
* crypto library would require this behavior.
27
GType mock_certificate_get_type (void);
29
#define MOCK_CERTIFICATE(obj) \
30
(G_TYPE_CHECK_INSTANCE_CAST ((obj), mock_certificate_get_type (), MockCertificate))
32
typedef struct _MockCertificate {
39
typedef struct _MockCertificateClass {
40
GObjectClass parent_class;
41
} MockCertificateClass;
43
static void mock_certificate_iface (GcrCertificateIface *iface);
44
G_DEFINE_TYPE_WITH_CODE (MockCertificate, mock_certificate, G_TYPE_OBJECT,
45
G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, mock_certificate_iface));
48
mock_certificate_init (MockCertificate *self)
50
self->created_on = g_thread_self ();
54
mock_certificate_finalize (GObject *obj)
56
MockCertificate *self = MOCK_CERTIFICATE (obj);
57
g_assert (self->created_on == g_thread_self ());
59
G_OBJECT_CLASS (mock_certificate_parent_class)->finalize (obj);
63
mock_certificate_class_init (MockCertificateClass *klass)
65
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
66
gobject_class->finalize = mock_certificate_finalize;
70
mock_certificate_real_get_der_data (GcrCertificate *base, gsize *n_data)
72
MockCertificate *self = MOCK_CERTIFICATE (base);
73
g_assert (self->created_on == g_thread_self ());
74
*n_data = self->n_data;
79
mock_certificate_iface (GcrCertificateIface *iface)
81
iface->get_der_data = (gpointer)mock_certificate_real_get_der_data;
84
static GcrCertificate*
85
mock_certificate_new (gconstpointer data, gsize n_data)
87
MockCertificate *self = g_object_new (mock_certificate_get_type (), NULL);
88
self->data = g_memdup (data, n_data);
89
self->n_data = n_data;
90
g_assert (self->created_on == g_thread_self ());
91
return GCR_CERTIFICATE (self);
94
/* ----------------------------------------------------------------------------
98
static GcrCertificate *cert_self = NULL;
99
static GcrCertificate *cert_ca = NULL;
100
static GcrCertificate *cert_signed = NULL;
101
static CK_FUNCTION_LIST funcs;
103
TESTING_SETUP (certificate_chain)
105
GList *modules = NULL;
106
CK_FUNCTION_LIST_PTR f;
109
const gchar *uris[2];
113
rv = gck_mock_C_GetFunctionList (&f);
114
gck_assert_cmprv (rv, ==, CKR_OK);
115
memcpy (&funcs, f, sizeof (funcs));
118
rv = (funcs.C_Initialize) (NULL);
119
gck_assert_cmprv (rv, ==, CKR_OK);
122
module = gck_module_new (&funcs, 0);
123
modules = g_list_prepend (modules, module);
124
gcr_pkcs11_set_modules (modules);
125
uris[0] = GCK_MOCK_SLOT_ONE_URI;
127
gcr_pkcs11_set_trust_lookup_uris (uris);
128
gcr_pkcs11_set_trust_store_uri (GCK_MOCK_SLOT_ONE_URI);
129
gck_list_unref_free (modules);
131
/* A self-signed certificate */
132
contents = testing_data_read ("der-certificate.crt", &n_contents);
133
cert_self = gcr_simple_certificate_new (contents, n_contents);
136
/* A signed certificate */
137
contents = testing_data_read ("dhansak-collabora.cer", &n_contents);
138
cert_signed = mock_certificate_new (contents, n_contents);
141
/* The signer for the above certificate */
142
contents = testing_data_read ("collabora-ca.cer", &n_contents);
143
cert_ca = mock_certificate_new (contents, n_contents);
148
add_certificate_to_module (GcrCertificate *certificate)
150
GckAttributes *attrs;
152
gsize n_data, n_subject;
155
data = gcr_certificate_get_der_data (certificate, &n_data);
158
subject = gcr_certificate_get_subject_raw (certificate, &n_subject);
161
/* Add a certificate to the module */
162
attrs = gck_attributes_new ();
163
gck_attributes_add_data (attrs, CKA_VALUE, data, n_data);
164
gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_CERTIFICATE);
165
gck_attributes_add_ulong (attrs, CKA_CERTIFICATE_TYPE, CKC_X_509);
166
gck_attributes_add_data (attrs, CKA_SUBJECT, subject, n_subject);
167
gck_mock_module_take_object (attrs);
173
add_anchor_to_module (GcrCertificate *certificate, const gchar *purpose)
175
GckAttributes *attrs;
179
data = gcr_certificate_get_der_data (certificate, &n_data);
182
/* And add a pinned certificate for the signed certificate */
183
attrs = gck_attributes_new ();
184
gck_attributes_add_data (attrs, CKA_X_CERTIFICATE_VALUE, data, n_data);
185
gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_X_TRUST_ASSERTION);
186
gck_attributes_add_ulong (attrs, CKA_X_ASSERTION_TYPE, CKT_X_ANCHORED_CERTIFICATE);
187
gck_attributes_add_string (attrs, CKA_X_PURPOSE, purpose);
188
gck_mock_module_take_object (attrs);
192
add_pinned_to_module (GcrCertificate *certificate, const gchar *purpose, const gchar *host)
194
GckAttributes *attrs;
198
data = gcr_certificate_get_der_data (certificate, &n_data);
201
/* And add a pinned certificate for the signed certificate */
202
attrs = gck_attributes_new ();
203
gck_attributes_add_data (attrs, CKA_X_CERTIFICATE_VALUE, data, n_data);
204
gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_X_TRUST_ASSERTION);
205
gck_attributes_add_ulong (attrs, CKA_X_ASSERTION_TYPE, CKT_X_PINNED_CERTIFICATE);
206
gck_attributes_add_string (attrs, CKA_X_PURPOSE, purpose);
207
gck_attributes_add_string (attrs, CKA_X_PEER, host);
208
gck_mock_module_take_object (attrs);
211
TESTING_TEARDOWN (certificate_chain)
215
g_object_unref (cert_self);
218
g_object_unref (cert_signed);
221
g_object_unref (cert_ca);
224
rv = (funcs.C_Finalize) (NULL);
225
gck_assert_cmprv (rv, ==, CKR_OK);
228
TESTING_TEST (certificate_chain_new)
230
GcrCertificateChain *chain;
232
chain = gcr_certificate_chain_new ();
234
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
235
GCR_CERTIFICATE_CHAIN_UNKNOWN);
236
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 0);
238
g_assert (gcr_certificate_chain_get_endpoint (chain) == NULL);
240
g_object_unref (chain);
243
TESTING_TEST (certificate_chain_new_with_cert)
245
GcrCertificateChain *chain;
246
GcrCertificate *check;
247
guint status, length;
249
chain = gcr_certificate_chain_new ();
250
gcr_certificate_chain_add (chain, cert_signed);
251
gcr_certificate_chain_add (chain, cert_ca);
253
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
254
GCR_CERTIFICATE_CHAIN_UNKNOWN);
255
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
259
g_object_get (chain, "status", &status, "length", &length, NULL);
260
g_assert_cmpuint (status, ==, GCR_CERTIFICATE_CHAIN_UNKNOWN);
261
g_assert_cmpuint (length, ==, 2);
263
check = gcr_certificate_chain_get_certificate (chain, 1);
264
g_assert (check == cert_ca);
266
/* Not yet completed */
267
check = gcr_certificate_chain_get_anchor (chain);
268
g_assert (check == NULL);
270
check = gcr_certificate_chain_get_endpoint (chain);
271
g_assert (check == cert_signed);
273
g_object_unref (chain);
276
TESTING_TEST (certificate_chain_selfsigned)
278
GcrCertificateChain *chain;
279
GError *error = NULL;
281
chain = gcr_certificate_chain_new ();
283
/* Add a self-signed certificate */
284
gcr_certificate_chain_add (chain, cert_self);
286
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
287
NULL, 0, NULL, &error))
288
g_assert_not_reached ();
289
g_assert_no_error (error);
291
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
292
GCR_CERTIFICATE_CHAIN_SELFSIGNED);
294
g_object_unref (chain);
297
TESTING_TEST (certificate_chain_incomplete)
299
GcrCertificateChain *chain;
300
GError *error = NULL;
302
chain = gcr_certificate_chain_new ();
304
/* Add a signed certificate */
305
gcr_certificate_chain_add (chain, cert_signed);
307
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
308
NULL, 0, NULL, &error))
309
g_assert_not_reached ();
310
g_assert_no_error (error);
312
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
313
GCR_CERTIFICATE_CHAIN_INCOMPLETE);
315
g_object_unref (chain);
318
TESTING_TEST (certificate_chain_empty)
320
GcrCertificateChain *chain;
321
GError *error = NULL;
323
chain = gcr_certificate_chain_new ();
325
/* Add no certificate */
327
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
328
NULL, 0, NULL, &error))
329
g_assert_not_reached ();
330
g_assert_no_error (error);
332
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
333
GCR_CERTIFICATE_CHAIN_UNKNOWN);
335
g_object_unref (chain);
338
TESTING_TEST (certificate_chain_trim_extras)
340
GcrCertificateChain *chain;
341
GError *error = NULL;
343
chain = gcr_certificate_chain_new ();
345
/* Add two unrelated certificates */
346
gcr_certificate_chain_add (chain, cert_self);
347
gcr_certificate_chain_add (chain, cert_signed);
349
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
351
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
352
NULL, 0, NULL, &error))
353
g_assert_not_reached ();
354
g_assert_no_error (error);
356
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
357
GCR_CERTIFICATE_CHAIN_SELFSIGNED);
358
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
360
g_object_unref (chain);
364
fetch_async_result (GObject *source, GAsyncResult *result, gpointer user_data)
366
*((GAsyncResult**)user_data) = result;
367
g_object_ref (result);
368
testing_wait_stop ();
371
TESTING_TEST (certificate_chain_complete_async)
373
GcrCertificateChain *chain;
374
GError *error = NULL;
375
GAsyncResult *result = NULL;
377
chain = gcr_certificate_chain_new ();
379
/* Add a whole bunch of certificates */
380
gcr_certificate_chain_add (chain, cert_signed);
381
gcr_certificate_chain_add (chain, cert_ca);
382
gcr_certificate_chain_add (chain, cert_self);
384
gcr_certificate_chain_build_async (chain, GCR_PURPOSE_CLIENT_AUTH,
385
NULL, 0, NULL, fetch_async_result, &result);
386
testing_wait_until (500);
387
if (!gcr_certificate_chain_build_finish (chain, result, &error))
388
g_assert_not_reached ();
389
g_assert_no_error (error);
390
g_object_unref (result);
392
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
393
GCR_CERTIFICATE_CHAIN_SELFSIGNED);
394
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
396
g_object_unref (chain);
399
TESTING_TEST (certificate_chain_with_anchor)
401
GcrCertificateChain *chain;
402
GError *error = NULL;
404
chain = gcr_certificate_chain_new ();
406
/* Two certificates in chain with ca trust anchor */
407
gcr_certificate_chain_add (chain, cert_signed);
408
gcr_certificate_chain_add (chain, cert_ca);
409
add_anchor_to_module (cert_ca, GCR_PURPOSE_CLIENT_AUTH);
411
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
413
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
414
NULL, 0, NULL, &error))
415
g_assert_not_reached ();
416
g_assert_no_error (error);
418
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
419
GCR_CERTIFICATE_CHAIN_ANCHORED);
420
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
421
g_assert (gcr_certificate_chain_get_anchor (chain) == cert_ca);
423
g_object_unref (chain);
426
TESTING_TEST (certificate_chain_with_anchor_and_lookup_ca)
428
GcrCertificateChain *chain;
429
GError *error = NULL;
431
chain = gcr_certificate_chain_new ();
433
/* One signed certificate, with CA in pkcs11, and trust anchor */
434
gcr_certificate_chain_add (chain, cert_signed);
435
add_certificate_to_module (cert_ca);
436
add_anchor_to_module (cert_ca, GCR_PURPOSE_CLIENT_AUTH);
438
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
440
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
441
NULL, 0, NULL, &error))
442
g_assert_not_reached ();
443
g_assert_no_error (error);
445
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
446
GCR_CERTIFICATE_CHAIN_ANCHORED);
447
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
448
g_assert (gcr_certificate_chain_get_anchor (chain) != NULL);
450
g_object_unref (chain);
453
TESTING_TEST (certificate_chain_with_pinned)
455
GcrCertificateChain *chain;
456
GError *error = NULL;
458
chain = gcr_certificate_chain_new ();
460
/* One certificate, and add CA to pkcs11 */
461
gcr_certificate_chain_add (chain, cert_signed);
462
gcr_certificate_chain_add (chain, cert_ca);
463
add_pinned_to_module (cert_signed, GCR_PURPOSE_CLIENT_AUTH, "pinned.example.com");
465
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
467
/* But we don't allow the lookup to happen */
468
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
469
"pinned.example.com", 0, NULL, &error))
470
g_assert_not_reached ();
471
g_assert_no_error (error);
473
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
474
GCR_CERTIFICATE_CHAIN_PINNED);
475
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
476
g_assert (gcr_certificate_chain_get_anchor (chain) == NULL);
478
g_object_unref (chain);
481
TESTING_TEST (certificate_chain_without_lookups)
483
GcrCertificateChain *chain;
484
GError *error = NULL;
486
chain = gcr_certificate_chain_new ();
488
/* One certificate, and add CA to pkcs11 */
489
gcr_certificate_chain_add (chain, cert_signed);
490
add_certificate_to_module (cert_ca);
492
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
494
/* But we don't allow the lookup to happen */
495
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
496
NULL, GCR_CERTIFICATE_CHAIN_FLAG_NO_LOOKUPS,
498
g_assert_not_reached ();
499
g_assert_no_error (error);
501
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
502
GCR_CERTIFICATE_CHAIN_INCOMPLETE);
503
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
504
g_assert (gcr_certificate_chain_get_anchor (chain) == NULL);
506
g_object_unref (chain);
509
TESTING_TEST (certificate_chain_with_lookup_error)
511
GcrCertificateChain *chain;
512
GError *error = NULL;
514
/* Make the lookup fail */
515
funcs.C_GetAttributeValue = gck_mock_fail_C_GetAttributeValue;
517
chain = gcr_certificate_chain_new ();
519
/* Two certificates in chain with ca trust anchor */
520
gcr_certificate_chain_add (chain, cert_signed);
521
add_certificate_to_module (cert_ca);
523
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
525
if (gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
526
NULL, 0, NULL, &error))
527
g_assert_not_reached ();
528
g_assert_error (error, GCK_ERROR, CKR_FUNCTION_FAILED);
529
g_clear_error (&error);
531
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
532
GCR_CERTIFICATE_CHAIN_UNKNOWN);
534
g_object_unref (chain);
537
TESTING_TEST (certificate_chain_with_anchor_error)
539
GcrCertificateChain *chain;
540
GError *error = NULL;
542
/* Make the lookup fail */
543
funcs.C_GetAttributeValue = gck_mock_fail_C_GetAttributeValue;
545
chain = gcr_certificate_chain_new ();
547
/* Two certificates in chain with ca trust anchor */
548
gcr_certificate_chain_add (chain, cert_signed);
549
add_certificate_to_module (cert_ca);
551
if (gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
552
NULL, 0, NULL, &error))
553
g_assert_not_reached ();
554
g_assert_error (error, GCK_ERROR, CKR_FUNCTION_FAILED);
555
g_clear_error (&error);
557
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
558
GCR_CERTIFICATE_CHAIN_UNKNOWN);
560
g_object_unref (chain);
563
TESTING_TEST (certificate_chain_with_anchor_error_async)
565
GcrCertificateChain *chain;
566
GError *error = NULL;
567
GAsyncResult *result;
569
/* Make the lookup fail */
570
funcs.C_GetAttributeValue = gck_mock_fail_C_GetAttributeValue;
572
chain = gcr_certificate_chain_new ();
574
/* Two certificates in chain with ca trust anchor */
575
gcr_certificate_chain_add (chain, cert_signed);
576
add_certificate_to_module (cert_ca);
578
gcr_certificate_chain_build_async (chain, GCR_PURPOSE_CLIENT_AUTH,
579
NULL, 0, NULL, fetch_async_result, &result);
580
testing_wait_until (500);
581
if (gcr_certificate_chain_build_finish (chain, result, &error))
582
g_assert_not_reached ();
583
g_assert_error (error, GCK_ERROR, CKR_FUNCTION_FAILED);
584
g_clear_error (&error);
585
g_object_unref (result);
587
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
588
GCR_CERTIFICATE_CHAIN_UNKNOWN);
590
g_object_unref (chain);