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    see <http://www.gnu.org/licenses/>.
18 
19    Author: Stef Walter <stefw@collabora.co.uk>
20 */
21 
22 #include "config.h"
23 
24 #include "egg/egg-asn1x.h"
25 #include "egg/egg-asn1-defs.h"
26 
27 #include "gcr/gcr-base.h"
28 #include "gcr/gcr-internal.h"
29 
30 #include "egg/egg-testing.h"
31 
32 #include "gck/gck-mock.h"
33 #include "gck/gck-test.h"
34 #include "gck/pkcs11n.h"
35 
36 #include <glib.h>
37 
38 #include <errno.h>
39 
40 typedef struct {
41 	gpointer cert_data;
42 	gsize n_cert_data;
43 	gpointer cert2_data;
44 	gsize n_cert2_data;
45 	CK_FUNCTION_LIST funcs;
46 } Test;
47 
48 static void
setup(Test * test,gconstpointer unused)49 setup (Test *test, gconstpointer unused)
50 {
51 	GckBuilder builder = GCK_BUILDER_INIT;
52 	GList *modules = NULL;
53 	CK_FUNCTION_LIST_PTR f;
54 	GckModule *module;
55 	GBytes *subject;
56 	GBytes *bytes;
57 	GNode *asn, *node;
58 	CK_RV rv;
59 
60 	if (!g_file_get_contents (SRCDIR "/gcr/fixtures/der-certificate.crt", (gchar**)&test->cert_data,
61 	                          &test->n_cert_data, NULL))
62 		g_assert_not_reached ();
63 	g_assert (test->cert_data);
64 
65 	if (!g_file_get_contents (SRCDIR "/gcr/fixtures/der-certificate-dsa.cer", (gchar**)&test->cert2_data,
66 	                          &test->n_cert2_data, NULL))
67 		g_assert_not_reached ();
68 	g_assert (test->cert2_data);
69 
70 	rv = gck_mock_C_GetFunctionList (&f);
71 	gck_assert_cmprv (rv, ==, CKR_OK);
72 	memcpy (&test->funcs, f, sizeof (test->funcs));
73 
74 	/* Open a session */
75 	rv = (test->funcs.C_Initialize) (NULL);
76 	gck_assert_cmprv (rv, ==, CKR_OK);
77 
78 	g_assert (!modules);
79 	module = gck_module_new (&test->funcs);
80 	modules = g_list_prepend (modules, module);
81 	gcr_pkcs11_set_modules (modules);
82 	gck_list_unref_free (modules);
83 
84 	bytes = g_bytes_new_static (test->cert_data, test->n_cert_data);
85 	asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", bytes);
86 	g_assert (asn);
87 	node = egg_asn1x_node (asn, "tbsCertificate", "subject", NULL);
88 	subject = egg_asn1x_get_element_raw (node);
89 
90 	/* Add a certificate to the module */
91 	gck_builder_add_data (&builder, CKA_VALUE, test->cert_data, test->n_cert_data);
92 	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_CERTIFICATE);
93 	gck_builder_add_ulong (&builder, CKA_CERTIFICATE_TYPE, CKC_X_509);
94 	gck_builder_add_data (&builder, CKA_SUBJECT,
95 	                      g_bytes_get_data (subject, NULL),
96 	                      g_bytes_get_size (subject));
97 	gck_mock_module_add_object (gck_builder_end (&builder));
98 
99 	g_bytes_unref (bytes);
100 	g_bytes_unref (subject);
101 	egg_asn1x_destroy (asn);
102 }
103 
104 static void
teardown(Test * test,gconstpointer unused)105 teardown (Test *test, gconstpointer unused)
106 {
107 	CK_RV rv;
108 
109 	g_free (test->cert_data);
110 	g_free (test->cert2_data);
111 
112 	rv = (test->funcs.C_Finalize) (NULL);
113 	gck_assert_cmprv (rv, ==, CKR_OK);
114 
115 	_gcr_uninitialize_library ();
116 }
117 
118 static void
test_lookup_certificate_issuer(Test * test,gconstpointer unused)119 test_lookup_certificate_issuer (Test *test, gconstpointer unused)
120 {
121 	GcrCertificate *cert, *issuer;
122 	GError *error = NULL;
123 	GckAttributes *attrs;
124 	const GckAttribute *attr;
125 	gconstpointer der;
126 	gsize n_der;
127 
128 	cert = gcr_simple_certificate_new_static (test->cert_data, test->n_cert_data);
129 	g_assert (cert);
130 
131 	/* Should be self-signed, so should find itself (added in setup) */
132 	issuer = gcr_pkcs11_certificate_lookup_issuer (cert, NULL, &error);
133 	g_assert (GCR_IS_PKCS11_CERTIFICATE (issuer));
134 	g_assert (error == NULL);
135 
136 	/* Should be the same certificate */
137 	der = gcr_certificate_get_der_data (issuer, &n_der);
138 	egg_assert_cmpsize (n_der, ==, test->n_cert_data);
139 	g_assert (memcmp (der, test->cert_data, test->n_cert_data) == 0);
140 
141 	/* Should return the same certificate here too */
142 	attrs = gcr_pkcs11_certificate_get_attributes (GCR_PKCS11_CERTIFICATE (issuer));
143 	g_assert (attrs);
144 	attr = gck_attributes_find (attrs, CKA_VALUE);
145 	g_assert (attr);
146 	egg_assert_cmpsize (attr->length, ==, test->n_cert_data);
147 	g_assert (memcmp (attr->value, test->cert_data, test->n_cert_data) == 0);
148 
149 	/* Should return the same certificate here too */
150 	attrs = NULL;
151 	g_object_get (issuer, "attributes", &attrs, NULL);
152 	g_assert (attrs);
153 	attr = gck_attributes_find (attrs, CKA_VALUE);
154 	g_assert (attr);
155 	egg_assert_cmpsize (attr->length, ==, test->n_cert_data);
156 	g_assert (memcmp (attr->value, test->cert_data, test->n_cert_data) == 0);
157 	gck_attributes_unref (attrs);
158 
159 	g_object_unref (cert);
160 	g_object_unref (issuer);
161 }
162 
163 static void
test_lookup_certificate_issuer_not_found(Test * test,gconstpointer unused)164 test_lookup_certificate_issuer_not_found (Test *test, gconstpointer unused)
165 {
166 	GcrCertificate *cert, *issuer;
167 	GError *error = NULL;
168 
169 	cert = gcr_simple_certificate_new_static (test->cert2_data, test->n_cert2_data);
170 	g_assert (cert);
171 
172 	/* Issuer shouldn't be found */
173 	issuer = gcr_pkcs11_certificate_lookup_issuer (cert, NULL, &error);
174 	g_assert (issuer == NULL);
175 	g_assert (error == NULL);
176 
177 	g_object_unref (cert);
178 }
179 
180 static void
fetch_async_result(GObject * source,GAsyncResult * result,gpointer user_data)181 fetch_async_result (GObject *source, GAsyncResult *result, gpointer user_data)
182 {
183 	*((GAsyncResult**)user_data) = result;
184 	g_object_ref (result);
185 	egg_test_wait_stop ();
186 }
187 
188 static void
test_lookup_certificate_issuer_async(Test * test,gconstpointer unused)189 test_lookup_certificate_issuer_async (Test *test, gconstpointer unused)
190 {
191 	GAsyncResult *result = NULL;
192 	GcrCertificate *cert, *issuer;
193 	GError *error = NULL;
194 	gconstpointer der;
195 	gsize n_der;
196 
197 	cert = gcr_simple_certificate_new_static (test->cert_data, test->n_cert_data);
198 	g_assert (cert);
199 
200 	/* Should be self-signed, so should find itself (added in setup) */
201 	gcr_pkcs11_certificate_lookup_issuer_async (cert, NULL, fetch_async_result, &result);
202 	egg_test_wait_until (500);
203 	g_assert (result);
204 	issuer = gcr_pkcs11_certificate_lookup_issuer_finish (result, &error);
205 	g_assert (GCR_IS_PKCS11_CERTIFICATE (issuer));
206 	g_assert (error == NULL);
207 	g_object_unref (result);
208 	result = NULL;
209 
210 	/* Should be the same certificate */
211 	der = gcr_certificate_get_der_data (issuer, &n_der);
212 	egg_assert_cmpsize (n_der, ==, test->n_cert_data);
213 	g_assert (memcmp (der, test->cert_data, test->n_cert_data) == 0);
214 
215 	g_object_unref (cert);
216 	g_object_unref (issuer);
217 }
218 
219 static void
test_lookup_certificate_issuer_failure(Test * test,gconstpointer unused)220 test_lookup_certificate_issuer_failure (Test *test, gconstpointer unused)
221 {
222 	GcrCertificate *cert, *issuer;
223 	GError *error = NULL;
224 
225 	cert = gcr_simple_certificate_new_static (test->cert_data, test->n_cert_data);
226 	g_assert (cert);
227 
228 	/* Make the lookup fail */
229 	test->funcs.C_GetAttributeValue = gck_mock_fail_C_GetAttributeValue;
230 
231 	issuer = gcr_pkcs11_certificate_lookup_issuer (cert, NULL, &error);
232 	g_assert (issuer == NULL);
233 	g_assert_error (error, GCK_ERROR, CKR_FUNCTION_FAILED);
234 	g_assert (error->message);
235 	g_clear_error (&error);
236 
237 	g_object_unref (cert);
238 }
239 
240 static void
test_lookup_certificate_issuer_fail_async(Test * test,gconstpointer unused)241 test_lookup_certificate_issuer_fail_async (Test *test, gconstpointer unused)
242 {
243 	GAsyncResult *result = NULL;
244 	GcrCertificate *cert, *issuer;
245 	GError *error = NULL;
246 
247 	cert = gcr_simple_certificate_new_static (test->cert_data, test->n_cert_data);
248 	g_assert (cert);
249 
250 	/* Make the lookup fail */
251 	test->funcs.C_GetAttributeValue = gck_mock_fail_C_GetAttributeValue;
252 
253 	/* Should be self-signed, so should find itself (added in setup) */
254 	gcr_pkcs11_certificate_lookup_issuer_async (cert, NULL, fetch_async_result, &result);
255 	egg_test_wait_until (500);
256 	g_assert (result);
257 	issuer = gcr_pkcs11_certificate_lookup_issuer_finish (result, &error);
258 	g_assert (issuer == NULL);
259 	g_assert_error (error, GCK_ERROR, CKR_FUNCTION_FAILED);
260 	g_assert (error->message);
261 	g_clear_error (&error);
262 	g_object_unref (result);
263 	result = NULL;
264 
265 	g_object_unref (cert);
266 }
267 
268 int
main(int argc,char ** argv)269 main (int argc, char **argv)
270 {
271 	g_test_init (&argc, &argv, NULL);
272 	g_set_prgname ("test-pkcs11-certificate");
273 
274 	g_test_add ("/gcr/pkcs11-certificate/lookup_certificate_issuer", Test, NULL, setup, test_lookup_certificate_issuer, teardown);
275 	g_test_add ("/gcr/pkcs11-certificate/lookup_certificate_issuer_not_found", Test, NULL, setup, test_lookup_certificate_issuer_not_found, teardown);
276 	g_test_add ("/gcr/pkcs11-certificate/lookup_certificate_issuer_async", Test, NULL, setup, test_lookup_certificate_issuer_async, teardown);
277 	g_test_add ("/gcr/pkcs11-certificate/lookup_certificate_issuer_failure", Test, NULL, setup, test_lookup_certificate_issuer_failure, teardown);
278 	g_test_add ("/gcr/pkcs11-certificate/lookup_certificate_issuer_fail_async", Test, NULL, setup, test_lookup_certificate_issuer_fail_async, teardown);
279 
280 	return egg_tests_run_with_loop ();
281 }
282