1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* test-gck-crypto.c - the GObject PKCS#11 wrapper library
3 
4    Copyright (C) 2011 Collabora Ltd.
5 
6    The Gnome Keyring Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10 
11    The Gnome Keyring Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15 
16    You should have received a copy of the GNU Library General Public
17    License along with the Gnome Library; see the file COPYING.LIB.  If not,
18    see <http://www.gnu.org/licenses/>.
19 
20    Author: Stef Walter <stefw@collabora.co.uk>
21 */
22 
23 #include "config.h"
24 
25 #include "gck/gck.h"
26 #include "gck/gck-mock.h"
27 #include "gck/gck-test.h"
28 
29 #include "egg/egg-testing.h"
30 
31 #include <glib.h>
32 
33 #include <errno.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37 
38 typedef struct {
39 	GckModule *module;
40 	GckSession *session;
41 	GckSession *session_with_auth;
42 } Test;
43 
44 static gboolean
on_discard_handle_ignore(GckSession * self,CK_OBJECT_HANDLE handle,gpointer unused)45 on_discard_handle_ignore (GckSession *self, CK_OBJECT_HANDLE handle, gpointer unused)
46 {
47 	/* Don't close the handle for this session, since it's a duplicate */
48 	return TRUE;
49 }
50 
51 static void
setup(Test * test,gconstpointer unused)52 setup (Test *test, gconstpointer unused)
53 {
54 	GError *err = NULL;
55 	GList *slots;
56 	GckSlot *slot;
57 
58 	/* Successful load */
59 	test->module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
60 	g_assert_no_error (err);
61 	g_assert_true (GCK_IS_MODULE (test->module));
62 	g_object_add_weak_pointer (G_OBJECT (test->module), (gpointer *)&test->module);
63 
64 	slots = gck_module_get_slots (test->module, TRUE);
65 	g_assert_nonnull (slots);
66 
67 	test->session = gck_slot_open_session (slots->data, 0, NULL, &err);
68 	g_assert_no_error (err);
69 	g_assert_true (GCK_IS_SESSION (test->session));
70 	g_object_add_weak_pointer (G_OBJECT (test->session), (gpointer *)&test->session);
71 
72 	slot = gck_session_get_slot (test->session);
73 	g_assert_nonnull (slot);
74 
75 	test->session_with_auth = gck_session_from_handle (slot, gck_session_get_handle (test->session), GCK_SESSION_AUTHENTICATE);
76 	g_signal_connect (test->session_with_auth, "discard-handle", G_CALLBACK (on_discard_handle_ignore), NULL);
77 	g_assert_nonnull (test->session_with_auth);
78 	g_object_add_weak_pointer (G_OBJECT (test->session_with_auth), (gpointer *)&test->session_with_auth);
79 
80 	g_object_unref (slot);
81 	gck_list_unref_free (slots);
82 }
83 
84 static void
teardown(Test * test,gconstpointer unused)85 teardown (Test *test, gconstpointer unused)
86 {
87 	g_object_unref (test->session);
88 	g_object_unref (test->module);
89 	g_object_unref (test->session_with_auth);
90 
91 	egg_test_wait_for_gtask_thread (test->session || test->session_with_auth || test->module);
92 
93 	g_assert_null (test->session);
94 	g_assert_null (test->session_with_auth);
95 	g_assert_null (test->module);
96 }
97 
98 static void
fetch_async_result(GObject * source,GAsyncResult * result,gpointer user_data)99 fetch_async_result (GObject *source, GAsyncResult *result, gpointer user_data)
100 {
101 	*((GAsyncResult**)user_data) = result;
102 	g_object_ref (result);
103 	egg_test_wait_stop ();
104 }
105 
106 static GckObject*
find_key(GckSession * session,CK_ATTRIBUTE_TYPE method,CK_MECHANISM_TYPE mech)107 find_key (GckSession *session, CK_ATTRIBUTE_TYPE method, CK_MECHANISM_TYPE mech)
108 {
109 	GckBuilder builder = GCK_BUILDER_INIT;
110 	GList *objects, *l;
111 	GckObject *object = NULL;
112 	CK_MECHANISM_TYPE_PTR mechs;
113 	gboolean match;
114 	gsize n_mechs;
115 
116 	gck_builder_add_boolean (&builder, method, TRUE);
117 	objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, NULL);
118 	g_assert_nonnull (objects);
119 
120 	for (l = objects; l; l = g_list_next (l)) {
121 		if (mech) {
122 			mechs = (gulong *)gck_object_get_data (l->data, CKA_ALLOWED_MECHANISMS,
123 			                                       NULL, &n_mechs, NULL);
124 			g_assert_nonnull (mechs);
125 			g_assert_cmpuint (n_mechs, ==, sizeof (CK_MECHANISM_TYPE));
126 
127 			/* We know all of them only have one allowed mech */
128 			match = (*mechs != mech);
129 			g_free (mechs);
130 
131 			if (match)
132 				continue;
133 		}
134 		object = l->data;
135 		g_object_ref (object);
136 		break;
137 	}
138 
139 	gck_list_unref_free (objects);
140 	return object;
141 }
142 
143 static GckObject*
find_key_with_value(GckSession * session,const gchar * value)144 find_key_with_value (GckSession *session, const gchar *value)
145 {
146 	GckBuilder builder = GCK_BUILDER_INIT;
147 	GList *objects;
148 	GckObject *object;
149 
150 	gck_builder_add_string (&builder, CKA_VALUE, value);
151 	objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, NULL);
152 	g_assert_nonnull (objects);
153 
154 	object = g_object_ref (objects->data);
155 	gck_list_unref_free (objects);
156 	return object;
157 }
158 
159 static void
check_key_with_value(GckSession * session,GckObject * key,CK_OBJECT_CLASS klass,const gchar * value)160 check_key_with_value (GckSession *session, GckObject *key, CK_OBJECT_CLASS klass, const gchar *value)
161 {
162 	GckAttributes *attrs;
163 	const GckAttribute *attr;
164 	gulong check;
165 
166 	attrs = gck_object_get (key, NULL, NULL, CKA_CLASS, CKA_VALUE, GCK_INVALID);
167 	g_assert_nonnull (attrs);
168 
169 	if (!gck_attributes_find_ulong (attrs, CKA_CLASS, &check))
170 		g_assert_not_reached ();
171 	g_assert_cmpuint (check, ==, klass);
172 
173 	attr = gck_attributes_find (attrs, CKA_VALUE);
174 	g_assert_nonnull (attr);
175 	g_assert_false (gck_attribute_is_invalid (attr));
176 	g_assert_cmpmem (attr->value, attr->length, value, strlen (value));
177 
178 	gck_attributes_unref (attrs);
179 }
180 
181 static gboolean
authenticate_object(GckSlot * module,GckObject * object,gchar * label,gchar ** password)182 authenticate_object (GckSlot *module, GckObject *object, gchar *label, gchar **password)
183 {
184 	g_assert_true (GCK_IS_MODULE (module));
185 	g_assert_true (GCK_IS_OBJECT (object));
186 	g_assert_nonnull (password);
187 	g_assert_null (*password);
188 
189 	*password = g_strdup ("booo");
190 	return TRUE;
191 }
192 
193 static void
test_encrypt(Test * test,gconstpointer unused)194 test_encrypt (Test *test, gconstpointer unused)
195 {
196 	GckMechanism mech = { CKM_MOCK_CAPITALIZE, NULL, 0 };
197 	GError *error = NULL;
198 	GAsyncResult *result = NULL;
199 	GckObject *key;
200 	guchar *output;
201 	gsize n_output;
202 
203 	/* Find the right key */
204 	key = find_key (test->session, CKA_ENCRYPT, CKM_MOCK_CAPITALIZE);
205 	g_assert_nonnull (key);
206 
207 	/* Simple one */
208 	output = gck_session_encrypt (test->session, key, CKM_MOCK_CAPITALIZE, (const guchar*)"blah blah", 10, &n_output, NULL, &error);
209 	g_assert_no_error (error);
210 	g_assert_nonnull (output);
211 	g_assert_cmpuint (n_output, ==, 10);
212 	g_assert_cmpstr ((gchar*)output, ==, "BLAH BLAH");
213 	g_free (output);
214 
215 	/* Asynchronous one */
216 	gck_session_encrypt_async (test->session, key, &mech, (const guchar*)"second chance", 14, NULL, fetch_async_result, &result);
217 
218 	egg_test_wait_until (500);
219 	g_assert_nonnull (result);
220 
221 	/* Get the result */
222 	output = gck_session_encrypt_finish (test->session, result, &n_output, &error);
223 	g_assert_no_error (error);
224 	g_assert_nonnull (output);
225 	g_assert_cmpuint (n_output, ==, 14);
226 	g_assert_cmpstr ((gchar*)output, ==, "SECOND CHANCE");
227 	g_free (output);
228 
229 	g_object_unref (result);
230 	g_object_unref (key);
231 }
232 
233 static void
test_decrypt(Test * test,gconstpointer unused)234 test_decrypt (Test *test, gconstpointer unused)
235 {
236 	GckMechanism mech = { CKM_MOCK_CAPITALIZE, NULL, 0 };
237 	GError *error = NULL;
238 	GAsyncResult *result = NULL;
239 	GckObject *key;
240 	guchar *output;
241 	gsize n_output;
242 
243 	/* Find the right key */
244 	key = find_key (test->session, CKA_DECRYPT, CKM_MOCK_CAPITALIZE);
245 	g_assert_nonnull (key);
246 
247 	/* Simple one */
248 	output = gck_session_decrypt (test->session, key, CKM_MOCK_CAPITALIZE, (const guchar*)"FRY???", 7, &n_output, NULL, &error);
249 	g_assert_no_error (error);
250 	g_assert_nonnull (output);
251 	g_assert_cmpuint (n_output, ==, 7);
252 	g_assert_cmpstr ((gchar*)output, ==, "fry???");
253 	g_free (output);
254 
255 	/* Asynchronous one */
256 	gck_session_decrypt_async (test->session, key, &mech, (const guchar*)"FAT CHANCE", 11, NULL, fetch_async_result, &result);
257 
258 	egg_test_wait_until (500);
259 	g_assert_nonnull (result);
260 
261 	/* Get the result */
262 	output = gck_session_decrypt_finish (test->session, result, &n_output, &error);
263 	g_assert_no_error (error);
264 	g_assert_nonnull (output);
265 	g_assert_cmpuint (n_output, ==, 11);
266 	g_assert_cmpstr ((gchar*)output, ==, "fat chance");
267 	g_free (output);
268 
269 	g_object_unref (result);
270 	g_object_unref (key);
271 }
272 
273 static void
test_login_context_specific(Test * test,gconstpointer unused)274 test_login_context_specific (Test *test, gconstpointer unused)
275 {
276 	/* The test module won't let us sign without doing a login, check that */
277 
278 	GError *error = NULL;
279 	GckObject *key;
280 	guchar *output;
281 	gsize n_output;
282 
283 	/* Find the right key */
284 	key = find_key (test->session, CKA_SIGN, CKM_MOCK_PREFIX);
285 	g_assert_true (GCK_IS_OBJECT (key));
286 	g_object_add_weak_pointer (G_OBJECT (key), (gpointer *)&key);
287 
288 	/* Simple one */
289 	output = gck_session_sign (test->session, key, CKM_MOCK_PREFIX, (const guchar*)"TV Monster", 11, &n_output, NULL, &error);
290 	g_assert_error (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN);
291 	g_assert_null (output);
292 	g_error_free (error);
293 
294 	g_object_unref (key);
295 	egg_test_wait_for_gtask_thread (key);
296 	g_assert_null (key);
297 }
298 
299 static void
test_sign(Test * test,gconstpointer unused)300 test_sign (Test *test, gconstpointer unused)
301 {
302 	GckMechanism mech = { CKM_MOCK_PREFIX, (guchar *)"my-prefix:", 10 };
303 	GError *error = NULL;
304 	GAsyncResult *result = NULL;
305 	GckObject *key;
306 	guchar *output;
307 	gsize n_output;
308 
309 	/* Enable auto-login on this test->session, see previous test */
310 	g_signal_connect (test->module, "authenticate-object", G_CALLBACK (authenticate_object), NULL);
311 
312 	/* Find the right key */
313 	key = find_key (test->session_with_auth, CKA_SIGN, CKM_MOCK_PREFIX);
314 	g_assert_nonnull (key);
315 
316 	/* Simple one */
317 	output = gck_session_sign (test->session_with_auth, key, CKM_MOCK_PREFIX, (const guchar*)"Labarbara", 10, &n_output, NULL, &error);
318 	g_assert_no_error (error);
319 	g_assert_nonnull (output);
320 	g_assert_cmpuint (n_output, ==, 24);
321 	g_assert_cmpstr ((gchar*)output, ==, "signed-prefix:Labarbara");
322 	g_free (output);
323 
324 	/* Asynchronous one */
325 	gck_session_sign_async (test->session_with_auth, key, &mech, (const guchar*)"Conrad", 7, NULL, fetch_async_result, &result);
326 
327 	egg_test_wait_until (500);
328 	g_assert_nonnull (result);
329 
330 	/* Get the result */
331 	output = gck_session_sign_finish (test->session_with_auth, result, &n_output, &error);
332 	g_assert_no_error (error);
333 	g_assert_nonnull (output);
334 	g_assert_cmpuint (n_output, ==, 17);
335 	g_assert_cmpstr ((gchar*)output, ==, "my-prefix:Conrad");
336 	g_free (output);
337 
338 	g_object_unref (result);
339 	g_object_unref (key);
340 }
341 
342 static void
test_verify(Test * test,gconstpointer unused)343 test_verify (Test *test, gconstpointer unused)
344 {
345 	GckMechanism mech = { CKM_MOCK_PREFIX, (guchar *)"my-prefix:", 10 };
346 	GError *error = NULL;
347 	GAsyncResult *result = NULL;
348 	GckObject *key;
349 	gboolean ret;
350 
351 	/* Enable auto-login on this session, shouldn't be needed */
352 	g_signal_connect (test->module, "authenticate-object", G_CALLBACK (authenticate_object), NULL);
353 
354 	/* Find the right key */
355 	key = find_key (test->session, CKA_VERIFY, CKM_MOCK_PREFIX);
356 	g_assert_true (GCK_IS_OBJECT (key));
357 	g_object_add_weak_pointer (G_OBJECT (key), (gpointer *)&key);
358 
359 	/* Simple one */
360 	ret = gck_session_verify (test->session, key, CKM_MOCK_PREFIX, (const guchar*)"Labarbara", 10,
361 	                           (const guchar*)"signed-prefix:Labarbara", 24, NULL, &error);
362 	g_assert_no_error (error);
363 	g_assert_true (ret);
364 
365 	/* Failure one */
366 	ret = gck_session_verify_full (test->session, key, &mech, (const guchar*)"Labarbara", 10,
367 	                                (const guchar*)"my-prefix:Loborboro", 20, NULL, &error);
368 	g_assert_nonnull (error);
369 	g_assert_false (ret);
370 	g_clear_error (&error);
371 
372 	/* Asynchronous one */
373 	gck_session_verify_async (test->session, key, &mech, (const guchar*)"Labarbara", 10,
374 	                           (const guchar*)"my-prefix:Labarbara", 20, NULL, fetch_async_result, &result);
375 	egg_test_wait_until (500);
376 	g_assert_nonnull (result);
377 	ret = gck_session_verify_finish (test->session, result, &error);
378 	g_assert_no_error (error);
379 	g_assert_true (ret);
380 	g_object_unref (result);
381 
382 	/* Asynchronous failure */
383 	result = NULL;
384 	gck_session_verify_async (test->session, key, &mech, (const guchar*)"Labarbara", 10,
385 	                           (const guchar*)"my-prefix:Labarxoro", 20, NULL, fetch_async_result, &result);
386 	egg_test_wait_until (500);
387 	g_assert_nonnull (result);
388 	ret = gck_session_verify_finish (test->session, result, &error);
389 	g_assert_nonnull (error);
390 	g_assert_false (ret);
391 	g_clear_error (&error);
392 	g_object_unref (result);
393 
394 	g_object_unref (key);
395 	egg_test_wait_for_gtask_thread (key);
396 	g_assert_null (key);
397 }
398 
399 static void
test_generate_key_pair(Test * test,gconstpointer unused)400 test_generate_key_pair (Test *test, gconstpointer unused)
401 {
402 	GckMechanism mech = { CKM_MOCK_GENERATE, (guchar *)"generate", 9 };
403 	GckBuilder builder = GCK_BUILDER_INIT;
404 	GckAttributes *pub_attrs, *prv_attrs;
405 	GError *error = NULL;
406 	GAsyncResult *result = NULL;
407 	GckObject *pub_key, *prv_key;
408 	gboolean ret;
409 
410 	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PUBLIC_KEY);
411 	pub_attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
412 	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PRIVATE_KEY);
413 	prv_attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
414 
415 	/* Full One*/
416 	ret = gck_session_generate_key_pair_full (test->session, &mech, pub_attrs, prv_attrs,
417 	                                           &pub_key, &prv_key, NULL, &error);
418 	g_assert_no_error (error);
419 	g_assert_true (ret);
420 	g_object_unref (pub_key);
421 	g_object_unref (prv_key);
422 
423 	/* Failure one */
424 	mech.type = 0;
425 	pub_key = prv_key = NULL;
426 	ret = gck_session_generate_key_pair_full (test->session, &mech, pub_attrs, prv_attrs,
427 	                                           &pub_key, &prv_key, NULL, &error);
428 	g_assert_nonnull (error);
429 	g_assert_false (ret);
430 	g_clear_error (&error);
431 	g_assert_null (pub_key);
432 	g_assert_null (prv_key);
433 
434 	/* Asynchronous one */
435 	mech.type = CKM_MOCK_GENERATE;
436 	gck_session_generate_key_pair_async (test->session, &mech, pub_attrs, prv_attrs, NULL, fetch_async_result, &result);
437 	egg_test_wait_until (500);
438 	g_assert_nonnull (result);
439 	ret = gck_session_generate_key_pair_finish (test->session, result, &pub_key, &prv_key, &error);
440 	g_assert_no_error (error);
441 	g_assert_true (ret);
442 	g_object_unref (result);
443 	g_object_unref (pub_key);
444 	g_object_unref (prv_key);
445 
446 	/* Asynchronous failure */
447 	result = NULL;
448 	mech.type = 0;
449 	pub_key = prv_key = NULL;
450 	gck_session_generate_key_pair_async (test->session, &mech, pub_attrs, prv_attrs, NULL, fetch_async_result, &result);
451 	egg_test_wait_until (500);
452 	g_assert_nonnull (result);
453 	ret = gck_session_generate_key_pair_finish (test->session, result, &pub_key, &prv_key, &error);
454 	g_assert_nonnull (error);
455 	g_assert_false (ret);
456 	g_clear_error (&error);
457 	g_object_unref (result);
458 	g_assert_null (pub_key);
459 	g_assert_null (prv_key);
460 
461 	gck_attributes_unref (pub_attrs);
462 	gck_attributes_unref (prv_attrs);
463 }
464 
465 static void
test_wrap_key(Test * test,gconstpointer unused)466 test_wrap_key (Test *test, gconstpointer unused)
467 {
468 	GckMechanism mech = { CKM_MOCK_WRAP, (guchar *)"wrap", 4 };
469 	GError *error = NULL;
470 	GAsyncResult *result = NULL;
471 	GckObject *wrapper, *wrapped;
472 	gpointer output;
473 	gsize n_output;
474 
475 	wrapper = find_key (test->session, CKA_WRAP, 0);
476 	wrapped = find_key_with_value (test->session, "value");
477 
478 	/* Simple One */
479 	output = gck_session_wrap_key (test->session, wrapper, CKM_MOCK_WRAP, wrapped, &n_output, NULL, &error);
480 	g_assert_no_error (error);
481 	g_assert_nonnull (output);
482     g_assert_cmpmem (output, n_output, "value", 5);
483 	g_free (output);
484 
485 	/* Full One*/
486 	output = gck_session_wrap_key_full (test->session, wrapper, &mech, wrapped, &n_output, NULL, &error);
487 	g_assert_no_error (error);
488 	g_assert_nonnull (output);
489     g_assert_cmpmem (output, n_output, "value", 5);
490 	g_free (output);
491 
492 	/* Failure one */
493 	mech.type = 0;
494 	n_output = 0;
495 	output = gck_session_wrap_key_full (test->session, wrapper, &mech, wrapped, &n_output, NULL, &error);
496 	g_assert_nonnull (error);
497 	g_assert_null (output);
498 	g_clear_error (&error);
499 	egg_assert_cmpsize (n_output, ==, 0);
500 
501 	/* Asynchronous one */
502 	mech.type = CKM_MOCK_WRAP;
503 	gck_session_wrap_key_async (test->session, wrapper, &mech, wrapped, NULL, fetch_async_result, &result);
504 	egg_test_wait_until (500);
505 	g_assert_nonnull (result);
506 	output = gck_session_wrap_key_finish (test->session, result, &n_output, &error);
507 	g_assert_no_error (error);
508 	g_assert_nonnull (output);
509     g_assert_cmpmem (output, n_output, "value", 5);
510 	g_object_unref (result);
511 	g_free (output);
512 
513 	/* Asynchronous failure */
514 	result = NULL;
515 	mech.type = 0;
516 	n_output = 0;
517 	gck_session_wrap_key_async (test->session, wrapper, &mech, wrapped, NULL, fetch_async_result, &result);
518 	egg_test_wait_until (500);
519 	g_assert_nonnull (result);
520 	output = gck_session_wrap_key_finish (test->session, result, &n_output, &error);
521 	g_assert_nonnull (error);
522 	g_assert_null (output);
523 	g_clear_error (&error);
524 	egg_assert_cmpsize (n_output, ==, 0);
525 	g_object_unref (result);
526 
527 	g_object_unref (wrapper);
528 	g_object_unref (wrapped);
529 }
530 
531 static void
test_unwrap_key(Test * test,gconstpointer unused)532 test_unwrap_key (Test *test, gconstpointer unused)
533 {
534 	GckMechanism mech = { CKM_MOCK_WRAP, (guchar *)"wrap", 4 };
535 	GckBuilder builder = GCK_BUILDER_INIT;
536 	GError *error = NULL;
537 	GAsyncResult *result = NULL;
538 	GckObject *wrapper, *unwrapped;
539 	GckAttributes *attrs;
540 
541 	wrapper = find_key (test->session, CKA_UNWRAP, 0);
542 	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
543 	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
544 
545 	/* Full One*/
546 	unwrapped = gck_session_unwrap_key_full (test->session, wrapper, &mech, (const guchar *)"special", 7, attrs, NULL, &error);
547 	g_assert_no_error (error);
548 	g_assert_true (GCK_IS_OBJECT (unwrapped));
549 	check_key_with_value (test->session, unwrapped, CKO_SECRET_KEY, "special");
550 	g_object_unref (unwrapped);
551 
552 	/* Failure one */
553 	mech.type = 0;
554 	unwrapped = gck_session_unwrap_key_full (test->session, wrapper, &mech, (const guchar *)"special", 7, attrs, NULL, &error);
555 	g_assert_nonnull (error);
556 	g_assert_null (unwrapped);
557 	g_clear_error (&error);
558 
559 	/* Asynchronous one */
560 	mech.type = CKM_MOCK_WRAP;
561 	gck_session_unwrap_key_async (test->session, wrapper, &mech, (const guchar *)"special", 7, attrs, NULL, fetch_async_result, &result);
562 	egg_test_wait_until (500);
563 	g_assert_nonnull (result);
564 	unwrapped = gck_session_unwrap_key_finish (test->session, result, &error);
565 	g_assert_no_error (error);
566 	g_assert_true (GCK_IS_OBJECT (unwrapped));
567 	check_key_with_value (test->session, unwrapped, CKO_SECRET_KEY, "special");
568 	g_object_unref (unwrapped);
569 	g_object_unref (result);
570 
571 	/* Asynchronous failure */
572 	result = NULL;
573 	mech.type = 0;
574 	gck_session_unwrap_key_async (test->session, wrapper, &mech, (const guchar *)"special", 6, attrs, NULL, fetch_async_result, &result);
575 	egg_test_wait_until (500);
576 	g_assert_nonnull (result);
577 	unwrapped = gck_session_unwrap_key_finish (test->session, result, &error);
578 	g_assert_nonnull (error);
579 	g_assert_null (unwrapped);
580 	g_clear_error (&error);
581 	g_object_unref (result);
582 
583 	g_object_unref (wrapper);
584 	gck_attributes_unref (attrs);
585 }
586 
587 static void
test_derive_key(Test * test,gconstpointer unused)588 test_derive_key (Test *test, gconstpointer unused)
589 {
590 	GckMechanism mech = { CKM_MOCK_DERIVE, (guchar *)"derive", 6 };
591 	GckBuilder builder = GCK_BUILDER_INIT;
592 	GError *error = NULL;
593 	GAsyncResult *result = NULL;
594 	GckObject *wrapper, *derived;
595 	GckAttributes *attrs;
596 
597 	wrapper = find_key (test->session, CKA_DERIVE, 0);
598 	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
599 	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
600 
601 	/* Full One*/
602 	derived = gck_session_derive_key_full (test->session, wrapper, &mech, attrs, NULL, &error);
603 	g_assert_no_error (error);
604 	g_assert_true (GCK_IS_OBJECT (derived));
605 	check_key_with_value (test->session, derived, CKO_SECRET_KEY, "derived");
606 	g_object_unref (derived);
607 
608 	/* Failure one */
609 	mech.type = 0;
610 	derived = gck_session_derive_key_full (test->session, wrapper, &mech, attrs, NULL, &error);
611 	g_assert_nonnull (error);
612 	g_assert_null (derived);
613 	g_clear_error (&error);
614 
615 	/* Asynchronous one */
616 	mech.type = CKM_MOCK_DERIVE;
617 	gck_session_derive_key_async (test->session, wrapper, &mech, attrs, NULL, fetch_async_result, &result);
618 	egg_test_wait_until (500);
619 	g_assert_nonnull (result);
620 	derived = gck_session_derive_key_finish (test->session, result, &error);
621 	g_assert_no_error (error);
622 	g_assert_true (GCK_IS_OBJECT (derived));
623 	check_key_with_value (test->session, derived, CKO_SECRET_KEY, "derived");
624 	g_object_unref (derived);
625 	g_object_unref (result);
626 
627 	/* Asynchronous failure */
628 	result = NULL;
629 	mech.type = 0;
630 	gck_session_derive_key_async (test->session, wrapper, &mech, attrs, NULL, fetch_async_result, &result);
631 	egg_test_wait_until (500);
632 	g_assert_nonnull (result);
633 	derived = gck_session_derive_key_finish (test->session, result, &error);
634 	g_assert_nonnull (error);
635 	g_assert_null (derived);
636 	g_clear_error (&error);
637 	g_object_unref (result);
638 
639 	g_object_unref (wrapper);
640 	gck_attributes_unref (attrs);
641 }
642 
643 static void
null_log_handler(const gchar * log_domain,GLogLevelFlags log_level,const gchar * message,gpointer user_data)644 null_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
645                   const gchar *message, gpointer user_data)
646 {
647 
648 }
649 
650 int
main(int argc,char ** argv)651 main (int argc, char **argv)
652 {
653 	g_test_init (&argc, &argv, NULL);
654 
655 	g_set_prgname ("test-gck-crypto");
656 
657 	/* Suppress these messages in tests */
658 	g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG,
659 	                   null_log_handler, NULL);
660 
661 	g_test_add ("/gck/crypto/encrypt", Test, NULL, setup, test_encrypt, teardown);
662 	g_test_add ("/gck/crypto/decrypt", Test, NULL, setup, test_decrypt, teardown);
663 	g_test_add ("/gck/crypto/login_context_specific", Test, NULL, setup, test_login_context_specific, teardown);
664 	g_test_add ("/gck/crypto/sign", Test, NULL, setup, test_sign, teardown);
665 	g_test_add ("/gck/crypto/verify", Test, NULL, setup, test_verify, teardown);
666 	g_test_add ("/gck/crypto/generate_key_pair", Test, NULL, setup, test_generate_key_pair, teardown);
667 	g_test_add ("/gck/crypto/wrap_key", Test, NULL, setup, test_wrap_key, teardown);
668 	g_test_add ("/gck/crypto/unwrap_key", Test, NULL, setup, test_unwrap_key, teardown);
669 	g_test_add ("/gck/crypto/derive_key", Test, NULL, setup, test_derive_key, teardown);
670 
671 	return egg_tests_run_with_loop ();
672 }
673