minimal build
[platform/upstream/gcr.git] / gcr / tests / test-certificate-chain.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3    Copyright (C) 2010 Collabora Ltd
4
5    The Gnome Keyring Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    The Gnome Keyring Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the Gnome Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.
19
20    Author: Stef Walter <stefw@collabora.co.uk>
21 */
22
23 #include "config.h"
24
25 #include "gcr/gcr-base.h"
26 #include "gcr/gcr-internal.h"
27
28 #include "egg/egg-asn1x.h"
29 #include "egg/egg-asn1-defs.h"
30 #include "egg/egg-testing.h"
31
32 #include "gck/gck-mock.h"
33 #include "gck/gck-test.h"
34 #include <p11-kit/pkcs11.h>
35 #include "gck/pkcs11x.h"
36
37 #include <glib.h>
38
39 #include <errno.h>
40 #include <string.h>
41
42 /* ---------------------------------------------------------------------------
43  * A Mock certificate that checks that it's always called on the
44  * same thread. A GcrCertificate implemented on top of a non-thread-safe
45  * crypto library would require this behavior.
46  */
47
48 GType               mock_certificate_get_type               (void);
49
50 #define MOCK_CERTIFICATE(obj) \
51         (G_TYPE_CHECK_INSTANCE_CAST ((obj), mock_certificate_get_type (), MockCertificate))
52
53 typedef struct _MockCertificate {
54         GObject parent;
55         GThread *created_on;
56         gpointer data;
57         gsize n_data;
58 } MockCertificate;
59
60 typedef struct _MockCertificateClass {
61         GObjectClass parent_class;
62 } MockCertificateClass;
63
64 static void mock_certificate_iface (GcrCertificateIface *iface);
65 G_DEFINE_TYPE_WITH_CODE (MockCertificate, mock_certificate, G_TYPE_OBJECT,
66         GCR_CERTIFICATE_MIXIN_IMPLEMENT_COMPARABLE ();
67         G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, mock_certificate_iface);
68 );
69
70 static void
71 mock_certificate_init (MockCertificate *self)
72 {
73         self->created_on = g_thread_self ();
74 }
75
76 static void
77 mock_certificate_finalize (GObject *obj)
78 {
79         MockCertificate *self = MOCK_CERTIFICATE (obj);
80         g_assert (self->created_on == g_thread_self ());
81         g_free (self->data);
82         G_OBJECT_CLASS (mock_certificate_parent_class)->finalize (obj);
83 }
84
85 static void
86 mock_certificate_class_init (MockCertificateClass *klass)
87 {
88         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
89         gobject_class->finalize = mock_certificate_finalize;
90         gobject_class->get_property = gcr_certificate_mixin_get_property;
91         gcr_certificate_mixin_class_init (gobject_class);
92 }
93
94 static gconstpointer
95 mock_certificate_real_get_der_data (GcrCertificate *base, gsize *n_data)
96 {
97         MockCertificate *self = MOCK_CERTIFICATE (base);
98         g_assert (self->created_on == g_thread_self ());
99         *n_data = self->n_data;
100         return self->data;
101 }
102
103 static void
104 mock_certificate_iface (GcrCertificateIface *iface)
105 {
106         iface->get_der_data = (gpointer)mock_certificate_real_get_der_data;
107 }
108
109 static GcrCertificate*
110 mock_certificate_new (gconstpointer data, gsize n_data)
111 {
112         MockCertificate *self = g_object_new (mock_certificate_get_type (), NULL);
113         self->data = g_memdup (data, n_data);
114         self->n_data = n_data;
115         g_assert (self->created_on == g_thread_self ());
116         return GCR_CERTIFICATE (self);
117 }
118
119 /* ----------------------------------------------------------------------------
120  * TESTS
121  */
122
123 typedef struct {
124         /* A self signed certificate */
125         GcrCertificate *cert_self;
126
127         /* Simple CA + issued */
128         GcrCertificate *cert_ca;
129         GcrCertificate *cert_signed;
130
131         /* Root + intermediate + issued */
132         GcrCertificate *cert_root;
133         GcrCertificate *cert_inter;
134         GcrCertificate *cert_host;
135
136         CK_FUNCTION_LIST funcs;
137 } Test;
138
139 static void
140 setup (Test *test, gconstpointer unused)
141 {
142         GList *modules = NULL;
143         CK_FUNCTION_LIST_PTR f;
144         gchar *contents;
145         gsize n_contents;
146         const gchar *uris[2];
147         CK_RV rv;
148         GckModule *module;
149
150         rv = gck_mock_C_GetFunctionList (&f);
151         gck_assert_cmprv (rv, ==, CKR_OK);
152         memcpy (&test->funcs, f, sizeof (test->funcs));
153
154         /* Open a session */
155         rv = (test->funcs.C_Initialize) (NULL);
156         gck_assert_cmprv (rv, ==, CKR_OK);
157
158         g_assert (!modules);
159         module = gck_module_new (&test->funcs);
160         modules = g_list_prepend (modules, module);
161         gcr_pkcs11_set_modules (modules);
162         uris[0] = GCK_MOCK_SLOT_ONE_URI;
163         uris[1] = NULL;
164         gcr_pkcs11_set_trust_lookup_uris (uris);
165         gcr_pkcs11_set_trust_store_uri (GCK_MOCK_SLOT_ONE_URI);
166         gck_list_unref_free (modules);
167
168         /* A self-signed certificate */
169         if (!g_file_get_contents (SRCDIR "/files/der-certificate.crt", &contents, &n_contents, NULL))
170                 g_assert_not_reached ();
171         test->cert_self = gcr_simple_certificate_new ((const guchar *)contents, n_contents);
172         g_free (contents);
173
174         /* A signed certificate */
175         if (!g_file_get_contents (SRCDIR "/files/dhansak-collabora.cer", &contents, &n_contents, NULL))
176                 g_assert_not_reached ();
177         test->cert_signed = mock_certificate_new (contents, n_contents);
178         g_free (contents);
179
180         /* The signer for the above certificate */
181         if (!g_file_get_contents (SRCDIR "/files/collabora-ca.cer", &contents, &n_contents, NULL))
182                 g_assert_not_reached ();
183         test->cert_ca = mock_certificate_new (contents, n_contents);
184         g_free (contents);
185
186         /* A root CA */
187         if (!g_file_get_contents (SRCDIR "/files/startcom-ca.cer", &contents, &n_contents, NULL))
188                 g_assert_not_reached ();
189         test->cert_root = mock_certificate_new (contents, n_contents);
190         g_free (contents);
191
192         /* An intermediate */
193         if (!g_file_get_contents (SRCDIR "/files/startcom-intermediate.cer", &contents, &n_contents, NULL))
194                 g_assert_not_reached ();
195         test->cert_inter = mock_certificate_new (contents, n_contents);
196         g_free (contents);
197
198         /* Signed by above intermediate */
199         if (!g_file_get_contents (SRCDIR "/files/jabber-server.cer", &contents, &n_contents, NULL))
200                 g_assert_not_reached ();
201         test->cert_host = mock_certificate_new (contents, n_contents);
202         g_free (contents);
203 }
204
205 static void
206 add_certificate_to_module (GcrCertificate *certificate)
207 {
208         GckBuilder builder = GCK_BUILDER_INIT;
209         gconstpointer data;
210         gsize n_data, n_subject;
211         gpointer subject;
212
213         data = gcr_certificate_get_der_data (certificate, &n_data);
214         g_assert (data);
215
216         subject = gcr_certificate_get_subject_raw (certificate, &n_subject);
217         g_assert (subject);
218
219         /* Add a certificate to the module */
220         gck_builder_add_data (&builder, CKA_VALUE, data, n_data);
221         gck_builder_add_ulong (&builder, CKA_CLASS, CKO_CERTIFICATE);
222         gck_builder_add_ulong (&builder, CKA_CERTIFICATE_TYPE, CKC_X_509);
223         gck_builder_add_data (&builder, CKA_SUBJECT, subject, n_subject);
224         gck_mock_module_add_object (gck_builder_end (&builder));
225
226         g_free (subject);
227 }
228
229 static void
230 add_anchor_to_module (GcrCertificate *certificate, const gchar *purpose)
231 {
232         GckBuilder builder = GCK_BUILDER_INIT;
233         gconstpointer data;
234         gsize n_data;
235
236         data = gcr_certificate_get_der_data (certificate, &n_data);
237         g_assert (data);
238
239         /* And add a pinned certificate for the signed certificate */
240         gck_builder_add_data (&builder, CKA_X_CERTIFICATE_VALUE, data, n_data);
241         gck_builder_add_ulong (&builder, CKA_CLASS, CKO_X_TRUST_ASSERTION);
242         gck_builder_add_ulong (&builder, CKA_X_ASSERTION_TYPE, CKT_X_ANCHORED_CERTIFICATE);
243         gck_builder_add_string (&builder, CKA_X_PURPOSE, purpose);
244         gck_mock_module_add_object (gck_builder_end (&builder));
245 }
246
247 static void
248 add_pinned_to_module (GcrCertificate *certificate, const gchar *purpose, const gchar *host)
249 {
250         GckBuilder builder = GCK_BUILDER_INIT;
251         gconstpointer data;
252         gsize n_data;
253
254         data = gcr_certificate_get_der_data (certificate, &n_data);
255         g_assert (data);
256
257         /* And add a pinned certificate for the signed certificate */
258         gck_builder_add_data (&builder, CKA_X_CERTIFICATE_VALUE, data, n_data);
259         gck_builder_add_ulong (&builder, CKA_CLASS, CKO_X_TRUST_ASSERTION);
260         gck_builder_add_ulong (&builder, CKA_X_ASSERTION_TYPE, CKT_X_PINNED_CERTIFICATE);
261         gck_builder_add_string (&builder, CKA_X_PURPOSE, purpose);
262         gck_builder_add_string (&builder, CKA_X_PEER, host);
263         gck_mock_module_add_object (gck_builder_end (&builder));
264 }
265
266 static void
267 teardown (Test *test, gconstpointer unused)
268 {
269         CK_RV rv;
270
271         g_object_unref (test->cert_self);
272         g_object_unref (test->cert_signed);
273         g_object_unref (test->cert_ca);
274
275         rv = (test->funcs.C_Finalize) (NULL);
276         gck_assert_cmprv (rv, ==, CKR_OK);
277
278         _gcr_uninitialize_library ();
279 }
280
281 static void
282 test_new (Test *test, gconstpointer unused)
283 {
284         GcrCertificateChain *chain;
285
286         chain = gcr_certificate_chain_new ();
287
288         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
289                           GCR_CERTIFICATE_CHAIN_UNKNOWN);
290         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 0);
291
292         g_assert (gcr_certificate_chain_get_endpoint (chain) == NULL);
293
294         g_object_unref (chain);
295 }
296
297 static void
298 test_new_with_cert (Test *test, gconstpointer unused)
299 {
300         GcrCertificateChain *chain;
301         GcrCertificate *check;
302         guint status, length;
303
304         chain = gcr_certificate_chain_new ();
305         gcr_certificate_chain_add (chain, test->cert_signed);
306         gcr_certificate_chain_add (chain, test->cert_ca);
307
308         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
309                           GCR_CERTIFICATE_CHAIN_UNKNOWN);
310         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
311
312         status = G_MAXUINT;
313         length = 0;
314         g_object_get (chain, "status", &status, "length", &length, NULL);
315         g_assert_cmpuint (status, ==, GCR_CERTIFICATE_CHAIN_UNKNOWN);
316         g_assert_cmpuint (length, ==, 2);
317
318         check = gcr_certificate_chain_get_certificate (chain, 1);
319         g_assert (check == test->cert_ca);
320
321         /* Not yet completed */
322         check = gcr_certificate_chain_get_anchor (chain);
323         g_assert (check == NULL);
324
325         check = gcr_certificate_chain_get_endpoint (chain);
326         g_assert (check == test->cert_signed);
327
328         g_object_unref (chain);
329 }
330
331 static void
332 test_selfsigned (Test *test, gconstpointer unused)
333 {
334         GcrCertificateChain *chain;
335         GError *error = NULL;
336
337         chain = gcr_certificate_chain_new ();
338
339         /* Add a self-signed certificate */
340         gcr_certificate_chain_add (chain, test->cert_self);
341
342         if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
343                                           NULL, 0, NULL, &error))
344                 g_assert_not_reached ();
345         g_assert_no_error (error);
346
347         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
348                           GCR_CERTIFICATE_CHAIN_SELFSIGNED);
349
350         g_object_unref (chain);
351 }
352
353 static void
354 test_incomplete (Test *test, gconstpointer unused)
355 {
356         GcrCertificateChain *chain;
357         GError *error = NULL;
358
359         chain = gcr_certificate_chain_new ();
360
361         /* Add a signed certificate */
362         gcr_certificate_chain_add (chain, test->cert_signed);
363
364         if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
365                                           NULL, 0, NULL, &error))
366                 g_assert_not_reached ();
367         g_assert_no_error (error);
368
369         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
370                           GCR_CERTIFICATE_CHAIN_INCOMPLETE);
371
372         g_object_unref (chain);
373 }
374
375 static void
376 test_empty (Test *test, gconstpointer unused)
377 {
378         GcrCertificateChain *chain;
379         GError *error = NULL;
380
381         chain = gcr_certificate_chain_new ();
382
383         /* Add no certificate */
384
385         if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
386                                           NULL, 0, NULL, &error))
387                 g_assert_not_reached ();
388         g_assert_no_error (error);
389
390         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
391                           GCR_CERTIFICATE_CHAIN_UNKNOWN);
392
393         g_object_unref (chain);
394 }
395
396 static void
397 test_trim_extras (Test *test, gconstpointer unused)
398 {
399         GcrCertificateChain *chain;
400         GError *error = NULL;
401
402         chain = gcr_certificate_chain_new ();
403
404         /* Add two unrelated certificates */
405         gcr_certificate_chain_add (chain, test->cert_self);
406         gcr_certificate_chain_add (chain, test->cert_signed);
407
408         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
409
410         if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
411                                           NULL, 0, NULL, &error))
412                 g_assert_not_reached ();
413         g_assert_no_error (error);
414
415         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
416                           GCR_CERTIFICATE_CHAIN_SELFSIGNED);
417         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
418
419         g_object_unref (chain);
420 }
421
422 static void
423 fetch_async_result (GObject *source, GAsyncResult *result, gpointer user_data)
424 {
425         *((GAsyncResult**)user_data) = result;
426         g_object_ref (result);
427         egg_test_wait_stop ();
428 }
429
430 static void
431 test_complete_async (Test *test, gconstpointer unused)
432 {
433         GcrCertificateChain *chain;
434         GError *error = NULL;
435         GAsyncResult *result = NULL;
436
437         chain = gcr_certificate_chain_new ();
438
439         /* Add a whole bunch of certificates */
440         gcr_certificate_chain_add (chain, test->cert_signed);
441         gcr_certificate_chain_add (chain, test->cert_ca);
442         gcr_certificate_chain_add (chain, test->cert_self);
443
444         gcr_certificate_chain_build_async (chain, GCR_PURPOSE_CLIENT_AUTH,
445                                            NULL, 0, NULL, fetch_async_result, &result);
446         egg_test_wait_until (500);
447         if (!gcr_certificate_chain_build_finish (chain, result, &error))
448                 g_assert_not_reached ();
449         g_assert_no_error (error);
450         g_object_unref (result);
451
452         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
453                           GCR_CERTIFICATE_CHAIN_SELFSIGNED);
454         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
455
456         g_object_unref (chain);
457 }
458
459 static void
460 test_with_anchor (Test *test, gconstpointer unused)
461 {
462         GcrCertificateChain *chain;
463         GError *error = NULL;
464
465         chain = gcr_certificate_chain_new ();
466
467         /* Two certificates in chain with ca trust anchor */
468         gcr_certificate_chain_add (chain, test->cert_signed);
469         gcr_certificate_chain_add (chain, test->cert_ca);
470         add_anchor_to_module (test->cert_ca, GCR_PURPOSE_CLIENT_AUTH);
471
472         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
473
474         if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
475                                           NULL, 0, NULL, &error))
476                 g_assert_not_reached ();
477         g_assert_no_error (error);
478
479         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
480                           GCR_CERTIFICATE_CHAIN_ANCHORED);
481         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
482         g_assert (gcr_certificate_chain_get_anchor (chain) == test->cert_ca);
483
484         g_object_unref (chain);
485 }
486
487 static void
488 test_with_anchor_and_lookup_ca (Test *test, gconstpointer unused)
489 {
490         GcrCertificateChain *chain;
491         GError *error = NULL;
492
493         chain = gcr_certificate_chain_new ();
494
495         /* One signed certificate, with CA in pkcs11, and trust anchor */
496         gcr_certificate_chain_add (chain, test->cert_signed);
497         add_certificate_to_module (test->cert_ca);
498         add_anchor_to_module (test->cert_ca, GCR_PURPOSE_CLIENT_AUTH);
499
500         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
501
502         if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
503                                           NULL, 0, NULL, &error))
504                 g_assert_not_reached ();
505         g_assert_no_error (error);
506
507         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
508                           GCR_CERTIFICATE_CHAIN_ANCHORED);
509         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
510         g_assert (gcr_certificate_chain_get_anchor (chain) != NULL);
511
512         g_object_unref (chain);
513 }
514
515 static void
516 test_with_pinned (Test *test, gconstpointer unused)
517 {
518         GcrCertificateChain *chain;
519         GError *error = NULL;
520
521         chain = gcr_certificate_chain_new ();
522
523         /* One certificate, and add CA to pkcs11 */
524         gcr_certificate_chain_add (chain, test->cert_signed);
525         gcr_certificate_chain_add (chain, test->cert_ca);
526         add_pinned_to_module (test->cert_signed, GCR_PURPOSE_CLIENT_AUTH, "pinned.example.com");
527
528         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
529
530         /* But we don't allow the lookup to happen */
531         if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
532                                           "pinned.example.com", 0, NULL, &error))
533                 g_assert_not_reached ();
534         g_assert_no_error (error);
535
536         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
537                           GCR_CERTIFICATE_CHAIN_PINNED);
538         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
539         g_assert (gcr_certificate_chain_get_anchor (chain) == NULL);
540
541         g_object_unref (chain);
542 }
543
544 static void
545 test_without_lookups (Test *test, gconstpointer unused)
546 {
547         GcrCertificateChain *chain;
548         GError *error = NULL;
549
550         chain = gcr_certificate_chain_new ();
551
552         /* One certificate, and add CA to pkcs11 */
553         gcr_certificate_chain_add (chain, test->cert_signed);
554         add_certificate_to_module (test->cert_ca);
555
556         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
557
558         /* But we don't allow the lookup to happen */
559         if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
560                                           NULL, GCR_CERTIFICATE_CHAIN_NO_LOOKUPS,
561                                           NULL, &error))
562                 g_assert_not_reached ();
563         g_assert_no_error (error);
564
565         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
566                           GCR_CERTIFICATE_CHAIN_INCOMPLETE);
567         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
568         g_assert (gcr_certificate_chain_get_anchor (chain) == NULL);
569
570         g_object_unref (chain);
571 }
572
573 static void
574 test_with_lookup_error (Test *test, gconstpointer unused)
575 {
576         GcrCertificateChain *chain;
577         GError *error = NULL;
578
579         /* Make the lookup fail */
580         test->funcs.C_GetAttributeValue = gck_mock_fail_C_GetAttributeValue;
581
582         chain = gcr_certificate_chain_new ();
583
584         /* Two certificates in chain with ca trust anchor */
585         gcr_certificate_chain_add (chain, test->cert_signed);
586         add_certificate_to_module (test->cert_ca);
587
588         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
589
590         if (gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
591                                          NULL, 0, NULL, &error))
592                 g_assert_not_reached ();
593         g_assert_error (error, GCK_ERROR, CKR_FUNCTION_FAILED);
594         g_clear_error (&error);
595
596         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
597                           GCR_CERTIFICATE_CHAIN_UNKNOWN);
598
599         g_object_unref (chain);
600 }
601
602 static void
603 test_wrong_order_anchor (Test *test, gconstpointer unused)
604 {
605         GcrCertificateChain *chain;
606         GError *error = NULL;
607
608         chain = gcr_certificate_chain_new ();
609
610         /* Two certificates in chain with ca trust anchor */
611         gcr_certificate_chain_add (chain, test->cert_host);
612         gcr_certificate_chain_add (chain, test->cert_root);
613         gcr_certificate_chain_add (chain, test->cert_inter);
614         add_anchor_to_module (test->cert_root, GCR_PURPOSE_CLIENT_AUTH);
615
616         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 3);
617
618         if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
619                                           NULL, 0, NULL, &error))
620                 g_assert_not_reached ();
621         g_assert_no_error (error);
622
623         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
624                           GCR_CERTIFICATE_CHAIN_ANCHORED);
625         g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 3);
626         g_assert (gcr_certificate_chain_get_anchor (chain) == test->cert_root);
627
628         g_object_unref (chain);
629 }
630
631 static void
632 test_with_anchor_error (Test *test, gconstpointer unused)
633 {
634         GcrCertificateChain *chain;
635         GError *error = NULL;
636
637         /* Make the lookup fail */
638         test->funcs.C_GetAttributeValue = gck_mock_fail_C_GetAttributeValue;
639
640         chain = gcr_certificate_chain_new ();
641
642         /* Two certificates in chain with ca trust anchor */
643         gcr_certificate_chain_add (chain, test->cert_signed);
644         add_certificate_to_module (test->cert_ca);
645
646         if (gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
647                                          NULL, 0, NULL, &error))
648                 g_assert_not_reached ();
649         g_assert_error (error, GCK_ERROR, CKR_FUNCTION_FAILED);
650         g_clear_error (&error);
651
652         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
653                           GCR_CERTIFICATE_CHAIN_UNKNOWN);
654
655         g_object_unref (chain);
656 }
657
658 static void
659 test_with_anchor_error_async (Test *test, gconstpointer unused)
660 {
661         GcrCertificateChain *chain;
662         GError *error = NULL;
663         GAsyncResult *result;
664
665         /* Make the lookup fail */
666         test->funcs.C_GetAttributeValue = gck_mock_fail_C_GetAttributeValue;
667
668         chain = gcr_certificate_chain_new ();
669
670         /* Two certificates in chain with ca trust anchor */
671         gcr_certificate_chain_add (chain, test->cert_signed);
672         add_certificate_to_module (test->cert_ca);
673
674         gcr_certificate_chain_build_async (chain, GCR_PURPOSE_CLIENT_AUTH,
675                                            NULL, 0, NULL, fetch_async_result, &result);
676         egg_test_wait_until (500);
677         if (gcr_certificate_chain_build_finish (chain, result, &error))
678                 g_assert_not_reached ();
679         g_assert_error (error, GCK_ERROR, CKR_FUNCTION_FAILED);
680         g_clear_error (&error);
681         g_object_unref (result);
682
683         g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
684                           GCR_CERTIFICATE_CHAIN_UNKNOWN);
685
686         g_object_unref (chain);
687 }
688
689 int
690 main (int argc, char **argv)
691 {
692 #if !GLIB_CHECK_VERSION(2,35,0)
693         g_type_init ();
694 #endif
695         g_test_init (&argc, &argv, NULL);
696         g_set_prgname ("test-certificate-chain");
697
698         g_test_add ("/gcr/certificate-chain/new", Test, NULL, setup, test_new, teardown);
699         g_test_add ("/gcr/certificate-chain/new_with_cert", Test, NULL, setup, test_new_with_cert, teardown);
700         g_test_add ("/gcr/certificate-chain/selfsigned", Test, NULL, setup, test_selfsigned, teardown);
701         g_test_add ("/gcr/certificate-chain/incomplete", Test, NULL, setup, test_incomplete, teardown);
702         g_test_add ("/gcr/certificate-chain/empty", Test, NULL, setup, test_empty, teardown);
703         g_test_add ("/gcr/certificate-chain/trim_extras", Test, NULL, setup, test_trim_extras, teardown);
704         g_test_add ("/gcr/certificate-chain/complete_async", Test, NULL, setup, test_complete_async, teardown);
705         g_test_add ("/gcr/certificate-chain/with_anchor", Test, NULL, setup, test_with_anchor, teardown);
706         g_test_add ("/gcr/certificate-chain/with_anchor_and_lookup_ca", Test, NULL, setup, test_with_anchor_and_lookup_ca, teardown);
707         g_test_add ("/gcr/certificate-chain/with_pinned", Test, NULL, setup, test_with_pinned, teardown);
708         g_test_add ("/gcr/certificate-chain/without_lookups", Test, NULL, setup, test_without_lookups, teardown);
709         g_test_add ("/gcr/certificate-chain/wrong_order_anchor", Test, NULL, setup, test_wrong_order_anchor, teardown);
710         g_test_add ("/gcr/certificate-chain/with_lookup_error", Test, NULL, setup, test_with_lookup_error, teardown);
711         g_test_add ("/gcr/certificate-chain/with_anchor_error", Test, NULL, setup, test_with_anchor_error, teardown);
712         g_test_add ("/gcr/certificate-chain/with_anchor_error_async", Test, NULL, setup, test_with_anchor_error_async, teardown);
713
714         return egg_tests_run_with_loop ();
715 }