1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* gck-session.h - the GObject PKCS#11 wrapper library
3 
4    Copyright (C) 2008, Stefan Walter
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 <nielsen@memberwebs.com>
21 */
22 
23 #include "config.h"
24 
25 #include "gck.h"
26 #include "gck-private.h"
27 
28 #include "gck/gck-marshal.h"
29 
30 #include <string.h>
31 
32 #include <glib/gi18n-lib.h>
33 
34 /**
35  * SECTION:gck-session
36  * @title: GckSession
37  * @short_description: Represents an open PKCS11 session.
38  *
39  * Before performing any PKCS11 operations, a session must be opened. This is
40  * analogous to an open database handle, or a file handle.
41  */
42 
43 /**
44  * GckSession:
45  *
46  * Represents an open PKCS11 session.
47  */
48 
49 /**
50  * GckSessionOptions:
51  * @GCK_SESSION_READ_ONLY: Open session as read only
52  * @GCK_SESSION_READ_WRITE: Open sessions as read/write
53  * @GCK_SESSION_LOGIN_USER: Login as user on new sessions
54  * @GCK_SESSION_AUTHENTICATE: Authenticate as necessary
55  *
56  * Options for creating sessions.
57  */
58 
59 /**
60  * GckMechanism:
61  * @type: The mechanism type
62  * @parameter: Mechanism specific data.
63  * @n_parameter: Length of mechanism specific data.
64  *
65  * Represents a mechanism used with crypto operations.
66  */
67 
68 enum {
69 	DISCARD_HANDLE,
70 	LAST_SIGNAL
71 };
72 
73 enum {
74 	PROP_0,
75 	PROP_MODULE,
76 	PROP_HANDLE,
77 	PROP_INTERACTION,
78 	PROP_SLOT,
79 	PROP_OPTIONS,
80 	PROP_OPENING_FLAGS,
81 	PROP_APP_DATA
82 };
83 
84 struct _GckSessionPrivate {
85 	/* Not modified after construct/init */
86 	GckSlot *slot;
87 	CK_SESSION_HANDLE handle;
88 	GckSessionOptions options;
89 	gulong opening_flags;
90 	gpointer app_data;
91 
92 	/* Changable data locked by mutex */
93 	GMutex *mutex;
94 	GTlsInteraction *interaction;
95 	gboolean discarded;
96 };
97 
98 static void    gck_session_initable_iface        (GInitableIface *iface);
99 
100 static void    gck_session_async_initable_iface  (GAsyncInitableIface *iface);
101 
102 G_DEFINE_TYPE_WITH_CODE (GckSession, gck_session, G_TYPE_OBJECT,
103                          G_ADD_PRIVATE (GckSession);
104                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gck_session_initable_iface);
105                          G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, gck_session_async_initable_iface);
106 );
107 
108 static guint signals[LAST_SIGNAL] = { 0 };
109 
110 /* ----------------------------------------------------------------------------
111  * OBJECT
112  */
113 
114 static gboolean
gck_session_real_discard_handle(GckSession * self,CK_OBJECT_HANDLE handle)115 gck_session_real_discard_handle (GckSession *self, CK_OBJECT_HANDLE handle)
116 {
117 	CK_FUNCTION_LIST_PTR funcs;
118 	GckModule *module;
119 	CK_RV rv;
120 
121 	/* The default functionality, close the handle */
122 
123 	module = gck_session_get_module (self);
124 	g_return_val_if_fail (module != NULL, FALSE);
125 
126 	funcs = gck_module_get_functions (module);
127 	g_return_val_if_fail (funcs, FALSE);
128 
129 	rv = (funcs->C_CloseSession) (handle);
130 	if (rv != CKR_OK) {
131 		g_warning ("couldn't close session properly: %s",
132 		           gck_message_from_rv (rv));
133 	}
134 
135 	g_object_unref (module);
136 	return TRUE;
137 }
138 
139 static void
gck_session_init(GckSession * self)140 gck_session_init (GckSession *self)
141 {
142 	self->pv = gck_session_get_instance_private (self);
143 	self->pv->mutex = g_new0 (GMutex, 1);
144 	g_mutex_init (self->pv->mutex);
145 }
146 
147 static void
gck_session_get_property(GObject * obj,guint prop_id,GValue * value,GParamSpec * pspec)148 gck_session_get_property (GObject *obj, guint prop_id, GValue *value,
149                            GParamSpec *pspec)
150 {
151 	GckSession *self = GCK_SESSION (obj);
152 
153 	switch (prop_id) {
154 	case PROP_MODULE:
155 		g_value_take_object (value, gck_session_get_module (self));
156 		break;
157 	case PROP_HANDLE:
158 		g_value_set_ulong (value, gck_session_get_handle (self));
159 		break;
160 	case PROP_SLOT:
161 		g_value_take_object (value, gck_session_get_slot (self));
162 		break;
163 	case PROP_OPTIONS:
164 		g_value_set_uint (value, gck_session_get_options (self));
165 		break;
166 	case PROP_INTERACTION:
167 		g_value_take_object (value, gck_session_get_interaction (self));
168 		break;
169 	default:
170 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
171 		break;
172 	}
173 }
174 
175 static void
gck_session_set_property(GObject * obj,guint prop_id,const GValue * value,GParamSpec * pspec)176 gck_session_set_property (GObject *obj, guint prop_id, const GValue *value,
177                            GParamSpec *pspec)
178 {
179 	GckSession *self = GCK_SESSION (obj);
180 
181 	/* Only valid calls are from constructor */
182 
183 	switch (prop_id) {
184 	case PROP_HANDLE:
185 		g_return_if_fail (!self->pv->handle);
186 		self->pv->handle = g_value_get_ulong (value);
187 		break;
188 	case PROP_INTERACTION:
189 		gck_session_set_interaction (self, g_value_get_object (value));
190 		break;
191 	case PROP_SLOT:
192 		g_return_if_fail (!self->pv->slot);
193 		self->pv->slot = g_value_dup_object (value);
194 		g_return_if_fail (self->pv->slot);
195 		break;
196 	case PROP_OPTIONS:
197 		g_return_if_fail (!self->pv->options);
198 		self->pv->options = g_value_get_flags (value);
199 		break;
200 	case PROP_OPENING_FLAGS:
201 		self->pv->opening_flags = g_value_get_ulong (value);
202 		break;
203 	case PROP_APP_DATA:
204 		self->pv->app_data = g_value_get_pointer (value);
205 		break;
206 	default:
207 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
208 		break;
209 	}
210 }
211 
212 static void
gck_session_constructed(GObject * obj)213 gck_session_constructed (GObject *obj)
214 {
215 	GckSession *self = GCK_SESSION (obj);
216 
217 	G_OBJECT_CLASS (gck_session_parent_class)->constructed (obj);
218 
219 	self->pv->opening_flags |= CKF_SERIAL_SESSION;
220 	if (self->pv->options & GCK_SESSION_READ_WRITE)
221 		self->pv->opening_flags |= CKF_RW_SESSION;
222 }
223 
224 static void
gck_session_dispose(GObject * obj)225 gck_session_dispose (GObject *obj)
226 {
227 	GckSession *self = GCK_SESSION (obj);
228 	gboolean discard = FALSE;
229 	gboolean handled;
230 
231 	g_return_if_fail (GCK_IS_SESSION (self));
232 
233 	if (self->pv->handle != 0) {
234 		g_mutex_lock (self->pv->mutex);
235 			discard = !self->pv->discarded;
236 			self->pv->discarded = TRUE;
237 		g_mutex_unlock (self->pv->mutex);
238 	}
239 
240 	if (discard) {
241 		/*
242 		 * Let the world know that we're discarding the session
243 		 * handle. This allows any necessary session reuse to work.
244 		 */
245 
246 		g_signal_emit_by_name (self, "discard-handle", self->pv->handle, &handled);
247 		g_return_if_fail (handled);
248 	}
249 
250 	G_OBJECT_CLASS (gck_session_parent_class)->dispose (obj);
251 }
252 
253 static void
gck_session_finalize(GObject * obj)254 gck_session_finalize (GObject *obj)
255 {
256 	GckSession *self = GCK_SESSION (obj);
257 
258 	g_assert (self->pv->handle == 0 || self->pv->discarded);
259 
260 	g_clear_object (&self->pv->interaction);
261 	g_clear_object (&self->pv->slot);
262 
263 	g_mutex_clear (self->pv->mutex);
264 	g_free (self->pv->mutex);
265 
266 	G_OBJECT_CLASS (gck_session_parent_class)->finalize (obj);
267 }
268 
269 static void
gck_session_class_init(GckSessionClass * klass)270 gck_session_class_init (GckSessionClass *klass)
271 {
272 	GObjectClass *gobject_class = (GObjectClass*)klass;
273 	gck_session_parent_class = g_type_class_peek_parent (klass);
274 
275 	gobject_class->constructed = gck_session_constructed;
276 	gobject_class->get_property = gck_session_get_property;
277 	gobject_class->set_property = gck_session_set_property;
278 	gobject_class->dispose = gck_session_dispose;
279 	gobject_class->finalize = gck_session_finalize;
280 
281 	klass->discard_handle = gck_session_real_discard_handle;
282 
283 	/**
284 	 * GckSession:module:
285 	 *
286 	 * The GckModule that this session is opened on.
287 	 */
288 	g_object_class_install_property (gobject_class, PROP_MODULE,
289 		g_param_spec_object ("module", "Module", "PKCS11 Module",
290 		                     GCK_TYPE_MODULE,
291 		                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
292 
293 	/**
294 	 * GckSession:handle:
295 	 *
296 	 * The raw CK_SESSION_HANDLE handle of this session.
297 	 */
298 	g_object_class_install_property (gobject_class, PROP_HANDLE,
299 		g_param_spec_ulong ("handle", "Session Handle", "PKCS11 Session Handle",
300 		                    0, G_MAXULONG, 0,
301 		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
302 
303 	/**
304 	 * GckSession:slot:
305 	 *
306 	 * The GckSlot this session is opened on.
307 	 */
308 	g_object_class_install_property (gobject_class, PROP_SLOT,
309 		g_param_spec_object ("slot", "Slot that this session uses", "PKCS11 Slot",
310 		                     GCK_TYPE_SLOT,
311 		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
312 
313 	/**
314 	 * GckSession:options:
315 	 *
316 	 * The options this session was opened with.
317 	 */
318 	g_object_class_install_property (gobject_class, PROP_OPTIONS,
319 		g_param_spec_flags ("options", "Session Options", "Session Options",
320 		                    GCK_TYPE_SESSION_OPTIONS, GCK_SESSION_READ_ONLY,
321 		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
322 
323 	/**
324 	 * GckSession:interaction:
325 	 *
326 	 * Interaction object used to ask the user for pins when opening
327 	 * sessions. Used if the session_options of the enumerator have
328 	 * %GCK_SESSION_LOGIN_USER
329 	 */
330 	g_object_class_install_property (gobject_class, PROP_INTERACTION,
331 		g_param_spec_object ("interaction", "Interaction", "Interaction asking for pins",
332 		                     G_TYPE_TLS_INTERACTION,
333 		                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
334 
335 	/**
336 	 * GckSession:opening-flags:
337 	 *
338 	 * Raw PKCS\#11 flags used to open the PKCS\#11 session.
339 	 */
340 	g_object_class_install_property (gobject_class, PROP_OPENING_FLAGS,
341 		g_param_spec_ulong ("opening-flags", "Opening flags", "PKCS#11 open session flags",
342 		                    0, G_MAXULONG, 0,
343 		                    G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
344 
345 	/**
346 	 * GckSession:app-data:
347 	 *
348 	 * Raw PKCS\#11 application data used to open the PKCS\#11 session.
349 	 */
350 	g_object_class_install_property (gobject_class, PROP_APP_DATA,
351 		g_param_spec_pointer ("app-data", "App data", "PKCS#11 application data",
352 		                      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
353 
354 	/**
355 	 * GckSession::discard-handle:
356 	 * @session: The session.
357 	 * @handle: The handle being discarded.
358 	 *
359 	 * When a GckSession is being disposed of it emits this signal to allow
360 	 * a session pool to pick up the handle and keep it around.
361 	 *
362 	 * If no signal handler claims the handle, then it is closed.
363 	 *
364 	 * Returns: Whether or not this handle was claimed.
365 	 */
366 	signals[DISCARD_HANDLE] = g_signal_new ("discard-handle", GCK_TYPE_SESSION,
367 	                G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GckSessionClass, discard_handle),
368 			g_signal_accumulator_true_handled, NULL,
369 			_gck_marshal_BOOLEAN__ULONG, G_TYPE_BOOLEAN, 1, G_TYPE_ULONG);
370 }
371 
372 typedef struct OpenSession {
373 	GckArguments base;
374 	GTlsInteraction *interaction;
375 	GckSlot *slot;
376 	gulong flags;
377 	gpointer app_data;
378 	CK_NOTIFY notify;
379 	gboolean auto_login;
380 	CK_SESSION_HANDLE session;
381 } OpenSession;
382 
383 static void
free_open_session(OpenSession * args)384 free_open_session (OpenSession *args)
385 {
386 	g_clear_object (&args->interaction);
387 	g_clear_object (&args->slot);
388 	g_free (args);
389 }
390 
391 static CK_RV
perform_open_session(OpenSession * args)392 perform_open_session (OpenSession *args)
393 {
394 	GTlsInteraction *interaction;
395 	CK_RV rv = CKR_OK;
396 
397 	/* First step, open session */
398 	if (!args->session) {
399 		rv = (args->base.pkcs11->C_OpenSession) (args->base.handle, args->flags,
400 		                                         args->app_data, args->notify, &args->session);
401 	}
402 
403 	if (rv != CKR_OK || !args->auto_login)
404 		return rv;
405 
406 	/* Compatibility, hook into GckModule signals if no interaction set */
407 	if (args->interaction)
408 		interaction = g_object_ref (args->interaction);
409 	else
410 		interaction = _gck_interaction_new (args->slot);
411 
412 	rv = _gck_session_authenticate_token (args->base.pkcs11, args->session,
413 	                                      args->slot, interaction, NULL);
414 
415 	g_object_unref (interaction);
416 
417 	return rv;
418 }
419 
420 static gboolean
gck_session_initable_init(GInitable * initable,GCancellable * cancellable,GError ** error)421 gck_session_initable_init (GInitable *initable,
422                            GCancellable *cancellable,
423                            GError **error)
424 {
425 	GckSession *self = GCK_SESSION (initable);
426 	OpenSession args = { GCK_ARGUMENTS_INIT, 0,  };
427 	GckModule *module = NULL;
428 	gboolean ret = FALSE;
429 	gboolean want_login;
430 
431 	want_login = (self->pv->options & GCK_SESSION_LOGIN_USER) == GCK_SESSION_LOGIN_USER;
432 
433 	/* Already have a session setup? */
434 	if (self->pv->handle && !want_login)
435 		return TRUE;
436 
437 	g_object_ref (self);
438 	module = gck_session_get_module (self);
439 
440 	/* Open a new session */
441 	args.slot = self->pv->slot;
442 	args.app_data = self->pv->app_data;
443 	args.notify = NULL;
444 	args.session = self->pv->handle;
445 	args.flags = self->pv->opening_flags;
446 	args.interaction = self->pv->interaction ? g_object_ref (self->pv->interaction) : NULL;
447 	args.auto_login = want_login;
448 
449 	if (_gck_call_sync (self->pv->slot, perform_open_session, NULL, &args, cancellable, error)) {
450 		self->pv->handle = args.session;
451 		ret = TRUE;
452 	}
453 
454 	g_clear_object (&args.interaction);
455 	g_object_unref (module);
456 	g_object_unref (self);
457 
458 	return ret;
459 }
460 
461 static void
gck_session_initable_iface(GInitableIface * iface)462 gck_session_initable_iface (GInitableIface *iface)
463 {
464 	iface->init = gck_session_initable_init;
465 }
466 
467 static void
gck_session_initable_init_async(GAsyncInitable * initable,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)468 gck_session_initable_init_async (GAsyncInitable *initable,
469                                  int io_priority,
470                                  GCancellable *cancellable,
471                                  GAsyncReadyCallback callback,
472                                  gpointer user_data)
473 {
474 	GckSession *self = GCK_SESSION (initable);
475 	OpenSession *args;
476 	gboolean want_login;
477 	GckCall *call;
478 
479 	g_object_ref (self);
480 
481 	call =  _gck_call_async_prep (self->pv->slot, perform_open_session, NULL,
482 	                              sizeof (*args), free_open_session);
483 
484 	args = _gck_call_get_arguments (call);
485 	want_login = (self->pv->options & GCK_SESSION_LOGIN_USER) == GCK_SESSION_LOGIN_USER;
486 	args->session = self->pv->handle;
487 
488 	_gck_call_async_ready (call, self, cancellable, callback, user_data);
489 
490 	/* Already have a session setup? */
491 	if (self->pv->handle && !want_login) {
492 		_gck_call_async_short (call, CKR_OK);
493 		g_object_unref (self);
494 		return;
495 	}
496 
497 	args->app_data = self->pv->app_data;
498 	args->notify = NULL;
499 	args->slot = g_object_ref (self->pv->slot);
500 	args->interaction = self->pv->interaction ? g_object_ref (self->pv->interaction) : NULL;
501 	args->auto_login = want_login;
502 	args->flags = self->pv->opening_flags;
503 
504 	_gck_call_async_go (call);
505 	g_object_unref (self);
506 }
507 
508 static gboolean
gck_session_initable_init_finish(GAsyncInitable * initable,GAsyncResult * result,GError ** error)509 gck_session_initable_init_finish (GAsyncInitable *initable,
510                                   GAsyncResult *result,
511                                   GError **error)
512 {
513 	GckSession *self = GCK_SESSION (initable);
514 	gboolean ret = FALSE;
515 
516 	g_object_ref (self);
517 
518 	{
519 		OpenSession *args;
520 
521 		if (_gck_call_basic_finish (result, error)) {
522 			args = _gck_call_async_result_arguments (result, OpenSession);
523 			self->pv->handle = args->session;
524 			ret = TRUE;
525 		}
526 	}
527 
528 	g_object_unref (self);
529 
530 	return ret;
531 }
532 
533 static void
gck_session_async_initable_iface(GAsyncInitableIface * iface)534 gck_session_async_initable_iface (GAsyncInitableIface *iface)
535 {
536 	iface->init_async = gck_session_initable_init_async;
537 	iface->init_finish = gck_session_initable_init_finish;
538 }
539 
540 /* ----------------------------------------------------------------------------
541  * PUBLIC
542  */
543 
544 /**
545  * GckSessionInfo:
546  * @slot_id: The handle of the PKCS11 slot that this session is opened on.
547  * @state: The user login state of the session.
548  * @flags: Various PKCS11 flags.
549  * @device_error: The last device error that occurred from an operation on this session.
550  *
551  * Information about the session. This is analogous to a CK_SESSION_INFO structure.
552  *
553  * When done with this structure, release it using gck_session_info_free().
554  */
555 
G_DEFINE_BOXED_TYPE(GckSessionInfo,gck_session_info,gck_session_info_copy,gck_session_info_free)556 G_DEFINE_BOXED_TYPE (GckSessionInfo, gck_session_info,
557                      gck_session_info_copy, gck_session_info_free)
558 
559 /**
560  * gck_session_info_copy:
561  * @session_info: a session info structure
562  *
563  * Make a new copy of a session info structure.
564  *
565  * Returns: (transfer full): a new copy of the session info
566  */
567 GckSessionInfo *
568 gck_session_info_copy (GckSessionInfo *session_info)
569 {
570 	return g_memdup (session_info, sizeof (GckSessionInfo));
571 }
572 
573 /**
574  * gck_session_info_free:
575  * @session_info: Session info to free.
576  *
577  * Free the GckSessionInfo structure and all associated memory.
578  **/
579 void
gck_session_info_free(GckSessionInfo * session_info)580 gck_session_info_free (GckSessionInfo *session_info)
581 {
582 	if (!session_info)
583 		return;
584 	g_free (session_info);
585 }
586 
587 /**
588  * gck_session_from_handle:
589  * @slot: The slot which the session belongs to.
590  * @session_handle: the raw PKCS\#11 handle of the session
591  * @options: Session options. Those which are used during opening a session have no effect.
592  *
593  * Initialize a GckSession object from a raw PKCS\#11 session handle.
594  * Usually one would use the gck_slot_open_session() function to
595  * create a session.
596  *
597  * Returns: (transfer full): the new GckSession object
598  **/
599 GckSession *
gck_session_from_handle(GckSlot * slot,gulong session_handle,GckSessionOptions options)600 gck_session_from_handle (GckSlot *slot,
601                          gulong session_handle,
602                          GckSessionOptions options)
603 {
604 	GckSession *session;
605 
606 	g_return_val_if_fail (GCK_IS_SLOT (slot), NULL);
607 
608 	session = g_object_new (GCK_TYPE_SESSION,
609 	                        "handle", session_handle,
610 	                        "slot", slot,
611 	                        "options", options,
612 	                        NULL);
613 
614 	return session;
615 }
616 
617 /**
618  * gck_session_get_handle:
619  * @self: The session object.
620  *
621  * Get the raw PKCS\#11 session handle from a GckSession object.
622  *
623  * Return value: The raw session handle.
624  **/
625 gulong
gck_session_get_handle(GckSession * self)626 gck_session_get_handle (GckSession *self)
627 {
628 	g_return_val_if_fail (GCK_IS_SESSION (self), (CK_SESSION_HANDLE)-1);
629 	return self->pv->handle;
630 }
631 
632 /**
633  * gck_session_get_module:
634  * @self: The session object.
635  *
636  * Get the PKCS\#11 module to which this session belongs.
637  *
638  * Returns: (transfer full): the module, which should be unreffed after use
639  **/
640 GckModule *
gck_session_get_module(GckSession * self)641 gck_session_get_module (GckSession *self)
642 {
643 	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
644 	return gck_slot_get_module (self->pv->slot);
645 }
646 
647 /**
648  * gck_session_get_slot:
649  * @self: The session object.
650  *
651  * Get the PKCS\#11 slot to which this session belongs.
652  *
653  * Return value: (transfer full): The slot, which should be unreffed after use.
654  **/
655 GckSlot *
gck_session_get_slot(GckSession * self)656 gck_session_get_slot (GckSession *self)
657 {
658 	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
659 	g_return_val_if_fail (GCK_IS_SLOT (self->pv->slot), NULL);
660 	return g_object_ref (self->pv->slot);
661 }
662 
663 /**
664  * gck_session_get_info:
665  * @self: The session object.
666  *
667  * Get information about the session.
668  *
669  * Returns: (transfer full): the session info. Use the gck_session_info_free()
670  *          to release when done
671  **/
672 GckSessionInfo*
gck_session_get_info(GckSession * self)673 gck_session_get_info (GckSession *self)
674 {
675 	GckSessionInfo *sessioninfo;
676 	CK_FUNCTION_LIST_PTR funcs;
677 	CK_SESSION_INFO info;
678 	GckModule *module;
679 	CK_RV rv;
680 
681 	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
682 
683 	module = gck_session_get_module (self);
684 	g_return_val_if_fail (GCK_IS_MODULE (module), NULL);
685 
686 	funcs = gck_module_get_functions (module);
687 	g_return_val_if_fail (funcs, NULL);
688 
689 	memset (&info, 0, sizeof (info));
690 	rv = (funcs->C_GetSessionInfo) (self->pv->handle, &info);
691 
692 	g_object_unref (module);
693 
694 	if (rv != CKR_OK) {
695 		g_warning ("couldn't get session info: %s", gck_message_from_rv (rv));
696 		return NULL;
697 	}
698 
699 	sessioninfo = g_new0 (GckSessionInfo, 1);
700 	sessioninfo->flags = info.flags;
701 	sessioninfo->slot_id = info.slotID;
702 	sessioninfo->state = info.state;
703 	sessioninfo->device_error = info.ulDeviceError;
704 
705 	return sessioninfo;
706 }
707 
708 /**
709  * gck_session_get_state:
710  * @self: the session
711  *
712  * Get the session state. The state is the various PKCS\#11 CKS_XXX flags.
713  *
714  * Returns: the session state
715  */
716 gulong
gck_session_get_state(GckSession * self)717 gck_session_get_state (GckSession *self)
718 {
719 	CK_FUNCTION_LIST_PTR funcs;
720 	CK_SESSION_INFO info;
721 	GckModule *module;
722 	CK_RV rv;
723 
724 	g_return_val_if_fail (GCK_IS_SESSION (self), 0);
725 
726 	module = gck_session_get_module (self);
727 	g_return_val_if_fail (GCK_IS_MODULE (module), 0);
728 
729 	funcs = gck_module_get_functions (module);
730 	g_return_val_if_fail (funcs, 0);
731 
732 	memset (&info, 0, sizeof (info));
733 	rv = (funcs->C_GetSessionInfo) (self->pv->handle, &info);
734 
735 	g_object_unref (module);
736 
737 	if (rv != CKR_OK) {
738 		g_warning ("couldn't get session info: %s", gck_message_from_rv (rv));
739 		return 0;
740 	}
741 
742 	return info.state;
743 }
744 
745 /**
746  * gck_session_get_options:
747  * @self: The session to get options from.
748  *
749  * Get the options this session was opened with.
750  *
751  * Return value: The session options.
752  **/
753 GckSessionOptions
gck_session_get_options(GckSession * self)754 gck_session_get_options (GckSession *self)
755 {
756 	g_return_val_if_fail (GCK_IS_SESSION (self), 0);
757 	return self->pv->options;
758 }
759 
760 /**
761  * gck_session_get_interaction:
762  * @self: the session
763  *
764  * Get the interaction object set on this session, which is used to prompt
765  * for pins and the like.
766  *
767  * Returns: (transfer full) (nullable): the interaction object, or %NULL
768  */
769 GTlsInteraction *
gck_session_get_interaction(GckSession * self)770 gck_session_get_interaction (GckSession *self)
771 {
772 	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
773 
774 	if (self->pv->interaction)
775 		return g_object_ref (self->pv->interaction);
776 
777 	return NULL;
778 }
779 
780 /**
781  * gck_session_set_interaction:
782  * @self: the session
783  * @interaction: (nullable): the interaction or %NULL
784  *
785  * Set the interaction object on this session, which is used to prompt for
786  * pins and the like.
787  */
788 void
gck_session_set_interaction(GckSession * self,GTlsInteraction * interaction)789 gck_session_set_interaction (GckSession *self,
790                              GTlsInteraction *interaction)
791 {
792 	GTlsInteraction *previous;
793 	g_return_if_fail (GCK_IS_SESSION (self));
794 	g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));
795 
796 	if (interaction)
797 		g_object_ref (interaction);
798 
799 	g_mutex_lock (self->pv->mutex);
800 
801 		previous = self->pv->interaction;
802 		self->pv->interaction = interaction;
803 
804 	g_mutex_unlock (self->pv->mutex);
805 
806 	if (previous)
807 		g_object_unref (previous);
808 }
809 
810 /**
811  * gck_session_open:
812  * @slot: the slot to open session on
813  * @options: session options
814  * @interaction: (nullable): optional interaction for logins or object authentication
815  * @cancellable: optional cancellation object
816  * @error: location to place error or %NULL
817  *
818  * Open a session on the slot. This call may block for an indefinite period.
819  *
820  * Returns: (transfer full): the new session
821  */
822 GckSession *
gck_session_open(GckSlot * slot,GckSessionOptions options,GTlsInteraction * interaction,GCancellable * cancellable,GError ** error)823 gck_session_open (GckSlot *slot,
824                   GckSessionOptions options,
825                   GTlsInteraction *interaction,
826                   GCancellable *cancellable,
827                   GError **error)
828 {
829 	return g_initable_new (GCK_TYPE_SESSION, cancellable, error,
830 	                       "slot", slot,
831 	                       "interaction", interaction,
832 	                       "options", options,
833 	                       NULL);
834 }
835 
836 /**
837  * gck_session_open_async:
838  * @slot: the slot to open session on
839  * @options: session options
840  * @interaction: (nullable): optional interaction for logins or object authentication
841  * @cancellable: optional cancellation object
842  * @callback: called when the operation completes
843  * @user_data: data to pass to callback
844  *
845  * Open a session on the slot. This call will return immediately and complete
846  * asynchronously.
847  */
848 void
gck_session_open_async(GckSlot * slot,GckSessionOptions options,GTlsInteraction * interaction,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)849 gck_session_open_async (GckSlot *slot,
850                         GckSessionOptions options,
851                         GTlsInteraction *interaction,
852                         GCancellable *cancellable,
853                         GAsyncReadyCallback callback,
854                         gpointer user_data)
855 {
856 	g_async_initable_new_async (GCK_TYPE_SESSION, G_PRIORITY_DEFAULT,
857 	                            cancellable, callback, user_data,
858 	                            "slot", slot,
859 	                            "interaction", interaction,
860 	                            "options", options,
861 	                            NULL);
862 }
863 
864 /**
865  * gck_session_open_finish:
866  * @result: the result passed to the callback
867  * @error: location to return an error or %NULL
868  *
869  * Get the result of an open session operation.
870  *
871  * Returns: (transfer full): the new session
872  */
873 GckSession *
gck_session_open_finish(GAsyncResult * result,GError ** error)874 gck_session_open_finish (GAsyncResult *result,
875                          GError **error)
876 {
877 	GObject *ret;
878 	GObject *source;
879 
880 	source = g_async_result_get_source_object (result);
881 	ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, error);
882 	g_object_unref (source);
883 
884 	return ret ? GCK_SESSION (ret) : NULL;
885 }
886 
887 /* ---------------------------------------------------------------------------------------------
888  * INIT PIN
889  */
890 
891 typedef struct _InitPin {
892 	GckArguments base;
893 	guchar *pin;
894 	gsize n_pin;
895 } InitPin;
896 
897 
898 static void
free_init_pin(InitPin * args)899 free_init_pin (InitPin *args)
900 {
901 	g_free (args->pin);
902 	g_free (args);
903 }
904 
905 static CK_RV
perform_init_pin(InitPin * args)906 perform_init_pin (InitPin *args)
907 {
908 	return (args->base.pkcs11->C_InitPIN) (args->base.handle, (CK_BYTE_PTR)args->pin,
909 	                                       args->n_pin);
910 }
911 
912 /**
913  * gck_session_init_pin:
914  * @self: Initialize PIN for this session's slot.
915  * @pin: (nullable) (array length=n_pin): the user's PIN, or %NULL for
916  *       protected authentication path
917  * @n_pin: the length of the PIN
918  * @cancellable: Optional cancellation object, or %NULL.
919  * @error: A location to return an error.
920  *
921  * Initialize the user's pin on this slot that this session is opened on.
922  * According to the PKCS\#11 standards, the session must be logged in with
923  * the CKU_SO user type.
924  *
925  * This call may block for an indefinite period.
926  *
927  * Return value: Whether successful or not.
928  **/
929 gboolean
gck_session_init_pin(GckSession * self,const guchar * pin,gsize n_pin,GCancellable * cancellable,GError ** error)930 gck_session_init_pin (GckSession *self, const guchar *pin, gsize n_pin,
931                       GCancellable *cancellable, GError **error)
932 {
933 	InitPin args = { GCK_ARGUMENTS_INIT, (guchar*)pin, n_pin };
934 	return _gck_call_sync (self, perform_init_pin, NULL, &args, cancellable, error);
935 
936 }
937 
938 /**
939  * gck_session_init_pin_async:
940  * @self: Initialize PIN for this session's slot.
941  * @pin: (nullable) (array length=n_pin): the user's PIN, or %NULL for protected authentication path
942  * @n_pin: the length of the PIN
943  * @cancellable: Optional cancellation object, or %NULL.
944  * @callback: Called when the operation completes.
945  * @user_data: Data to pass to the callback.
946  *
947  * Initialize the user's pin on this slot that this session is opened on.
948  * According to the PKCS\#11 standards, the session must be logged in with
949  * the CKU_SO user type.
950  *
951  * This call will return immediately and completes asynchronously.
952  **/
953 void
gck_session_init_pin_async(GckSession * self,const guchar * pin,gsize n_pin,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)954 gck_session_init_pin_async (GckSession *self, const guchar *pin, gsize n_pin,
955                              GCancellable *cancellable, GAsyncReadyCallback callback,
956                              gpointer user_data)
957 {
958 	GckCall *call;
959 	InitPin* args;
960 
961 	call = _gck_call_async_prep (self, perform_init_pin, NULL, sizeof (*args), free_init_pin);
962 	args = _gck_call_get_arguments (call);
963 
964 	args->pin = pin && n_pin ? g_memdup (pin, n_pin) : NULL;
965 	args->n_pin = n_pin;
966 
967 	_gck_call_async_ready_go (call, self, cancellable, callback, user_data);
968 }
969 
970 /**
971  * gck_session_init_pin_finish:
972  * @self: The session.
973  * @result: The result passed to the callback.
974  * @error: A location to return an error.
975  *
976  * Get the result of initializing a user's PIN.
977  *
978  * Return value: Whether the operation was successful or not.
979  **/
980 gboolean
gck_session_init_pin_finish(GckSession * self,GAsyncResult * result,GError ** error)981 gck_session_init_pin_finish (GckSession *self, GAsyncResult *result, GError **error)
982 {
983 	return _gck_call_basic_finish (result, error);
984 }
985 
986 
987 /* ---------------------------------------------------------------------------------------------
988  * SET PIN
989  */
990 
991 typedef struct _SetPin {
992 	GckArguments base;
993 	guchar *old_pin;
994 	gsize n_old_pin;
995 	guchar *new_pin;
996 	gsize n_new_pin;
997 } SetPin;
998 
999 static void
free_set_pin(SetPin * args)1000 free_set_pin (SetPin *args)
1001 {
1002 	g_free (args->old_pin);
1003 	g_free (args->new_pin);
1004 	g_free (args);
1005 }
1006 
1007 static CK_RV
perform_set_pin(SetPin * args)1008 perform_set_pin (SetPin *args)
1009 {
1010 	return (args->base.pkcs11->C_SetPIN) (args->base.handle, (CK_BYTE_PTR)args->old_pin,
1011 	                                      args->n_old_pin, args->new_pin, args->n_new_pin);
1012 }
1013 
1014 /**
1015  * gck_session_set_pin:
1016  * @self: Change the PIN for this session's slot.
1017  * @old_pin: (nullable) (array length=n_old_pin): the user's old PIN, or %NULL
1018  *           for protected authentication path.
1019  * @n_old_pin: The length of the PIN.
1020  * @new_pin: (nullable) (array length=n_new_pin): the user's new PIN, or %NULL
1021  *           for protected authentication path
1022  * @n_new_pin: The length of the PIN.
1023  * @cancellable: Optional cancellation object, or %NULL.
1024  * @error: A location to return an error.
1025  *
1026  * Change the user's pin on this slot that this session is opened on.
1027  *
1028  * This call may block for an indefinite period.
1029  *
1030  * Return value: Whether successful or not.
1031  **/
1032 gboolean
gck_session_set_pin(GckSession * self,const guchar * old_pin,gsize n_old_pin,const guchar * new_pin,gsize n_new_pin,GCancellable * cancellable,GError ** error)1033 gck_session_set_pin (GckSession *self, const guchar *old_pin, gsize n_old_pin,
1034                      const guchar *new_pin, gsize n_new_pin, GCancellable *cancellable,
1035                      GError **error)
1036 {
1037 	SetPin args = { GCK_ARGUMENTS_INIT, (guchar*)old_pin, n_old_pin, (guchar*)new_pin, n_new_pin };
1038 	return _gck_call_sync (self, perform_set_pin, NULL, &args, cancellable, error);
1039 }
1040 
1041 /**
1042  * gck_session_set_pin_async:
1043  * @self: Change the PIN for this session's slot.
1044  * @old_pin: (nullable) (array length=n_new_pin): the user's old PIN, or %NULL
1045  *           for protected authentication path
1046  * @n_old_pin: the length of the old PIN
1047  * @new_pin: (nullable) (array length=n_new_pin): the user's new PIN, or %NULL
1048  *           for protected authentication path
1049  * @n_new_pin: the length of the new PIN
1050  * @cancellable: Optional cancellation object, or %NULL.
1051  * @callback: Called when the operation completes.
1052  * @user_data: Data to pass to the callback.
1053  *
1054  * Change the user's pin on this slot that this session is opened on.
1055  *
1056  * This call will return immediately and completes asynchronously.
1057  **/
1058 void
gck_session_set_pin_async(GckSession * self,const guchar * old_pin,gsize n_old_pin,const guchar * new_pin,gsize n_new_pin,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1059 gck_session_set_pin_async (GckSession *self, const guchar *old_pin, gsize n_old_pin,
1060                             const guchar *new_pin, gsize n_new_pin, GCancellable *cancellable,
1061                             GAsyncReadyCallback callback, gpointer user_data)
1062 {
1063 	SetPin* args;
1064 	GckCall *call;
1065 
1066 	call = _gck_call_async_prep (self, perform_set_pin, NULL, sizeof (*args), free_set_pin);
1067 	args = _gck_call_get_arguments (call);
1068 
1069 	args->old_pin = old_pin && n_old_pin ? g_memdup (old_pin, n_old_pin) : NULL;
1070 	args->n_old_pin = n_old_pin;
1071 	args->new_pin = new_pin && n_new_pin ? g_memdup (new_pin, n_new_pin) : NULL;
1072 	args->n_new_pin = n_new_pin;
1073 
1074 	_gck_call_async_ready_go (call, self, cancellable, callback, user_data);
1075 }
1076 
1077 /**
1078  * gck_session_set_pin_finish:
1079  * @self: The session.
1080  * @result: The result passed to the callback.
1081  * @error: A location to return an error.
1082  *
1083  * Get the result of changing a user's PIN.
1084  *
1085  * Return value: Whether the operation was successful or not.
1086  **/
1087 gboolean
gck_session_set_pin_finish(GckSession * self,GAsyncResult * result,GError ** error)1088 gck_session_set_pin_finish (GckSession *self, GAsyncResult *result, GError **error)
1089 {
1090 	return _gck_call_basic_finish (result, error);
1091 }
1092 
1093 
1094 /* ---------------------------------------------------------------------------------------------
1095  * LOGIN
1096  */
1097 
1098 typedef struct _Login {
1099 	GckArguments base;
1100 	gulong user_type;
1101 	guchar *pin;
1102 	gsize n_pin;
1103 } Login;
1104 
1105 static void
free_login(Login * args)1106 free_login (Login *args)
1107 {
1108 	g_free (args->pin);
1109 	g_free (args);
1110 }
1111 
1112 static CK_RV
perform_login(Login * args)1113 perform_login (Login *args)
1114 {
1115 	return (args->base.pkcs11->C_Login) (args->base.handle, args->user_type,
1116 	                                     (CK_BYTE_PTR)args->pin, args->n_pin);
1117 }
1118 
1119 /**
1120  * gck_session_login:
1121  * @self: Log in to this session.
1122  * @user_type: The type of login user.
1123  * @pin: (nullable) (array length=n_pin): the user's PIN, or %NULL for
1124  *       protected authentication path
1125  * @n_pin: The length of the PIN.
1126  * @cancellable: Optional cancellation object, or %NULL.
1127  * @error: A location to return an error.
1128  *
1129  * Login the user on the session. This call may block for
1130  * an indefinite period.
1131  *
1132  * Return value: Whether successful or not.
1133  **/
1134 gboolean
gck_session_login(GckSession * self,gulong user_type,const guchar * pin,gsize n_pin,GCancellable * cancellable,GError ** error)1135 gck_session_login (GckSession *self, gulong user_type, const guchar *pin,
1136                    gsize n_pin, GCancellable *cancellable, GError **error)
1137 {
1138 	Login args = { GCK_ARGUMENTS_INIT, user_type, (guchar*)pin, n_pin };
1139 	return _gck_call_sync (self, perform_login, NULL, &args, cancellable, error);
1140 
1141 }
1142 
1143 /**
1144  * gck_session_login_async:
1145  * @self: Log in to this session.
1146  * @user_type: The type of login user.
1147  * @pin: (nullable) (array length=n_pin): the user's PIN, or %NULL for
1148  *       protected authentication path
1149  * @n_pin: The length of the PIN.
1150  * @cancellable: Optional cancellation object, or %NULL.
1151  * @callback: Called when the operation completes.
1152  * @user_data: Data to pass to the callback.
1153  *
1154  * Login the user on the session. This call will return
1155  * immediately and completes asynchronously.
1156  **/
1157 void
gck_session_login_async(GckSession * self,gulong user_type,const guchar * pin,gsize n_pin,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1158 gck_session_login_async (GckSession *self, gulong user_type, const guchar *pin,
1159                           gsize n_pin, GCancellable *cancellable, GAsyncReadyCallback callback,
1160                           gpointer user_data)
1161 {
1162 	Login* args;
1163 	GckCall *call;
1164 
1165 	call = _gck_call_async_prep (self, perform_login, NULL, sizeof (*args), free_login);
1166 	args = _gck_call_get_arguments (call);
1167 
1168 	args->user_type = user_type;
1169 	args->pin = pin && n_pin ? g_memdup (pin, n_pin) : NULL;
1170 	args->n_pin = n_pin;
1171 
1172 	_gck_call_async_ready_go (call, self, cancellable, callback, user_data);
1173 }
1174 
1175 /**
1176  * gck_session_login_finish:
1177  * @self: The session logged into.
1178  * @result: The result passed to the callback.
1179  * @error: A location to return an error.
1180  *
1181  * Get the result of a login operation.
1182  *
1183  * Return value: Whether the operation was successful or not.
1184  **/
1185 gboolean
gck_session_login_finish(GckSession * self,GAsyncResult * result,GError ** error)1186 gck_session_login_finish (GckSession *self, GAsyncResult *result, GError **error)
1187 {
1188 	return _gck_call_basic_finish (result, error);
1189 }
1190 
1191 typedef struct _Interactive {
1192 	GckArguments base;
1193 	GTlsInteraction *interaction;
1194 	GCancellable *cancellable;
1195 	GckSlot *token;
1196 } Interactive;
1197 
1198 static void
free_interactive(Interactive * args)1199 free_interactive (Interactive *args)
1200 {
1201 	g_clear_object (&args->token);
1202 	g_clear_object (&args->cancellable);
1203 	g_clear_object (&args->interaction);
1204 	g_free (args);
1205 }
1206 
1207 static CK_RV
perform_interactive(Interactive * args)1208 perform_interactive (Interactive *args)
1209 {
1210 	return _gck_session_authenticate_token (args->base.pkcs11, args->base.handle,
1211 	                                        args->token, args->interaction, args->cancellable);
1212 }
1213 
1214 /**
1215  * gck_session_login_interactive:
1216  * @self: session to use for login
1217  * @user_type: the type of login user
1218  * @interaction: (nullable): interaction to request PIN when necessary
1219  * @cancellable: optional cancellation object, or %NULL
1220  * @error: location to return an error
1221  *
1222  * Login the user on the session requesting the password interactively
1223  * when necessary. This call may block for an indefinite period.
1224  *
1225  * Return value: Whether successful or not.
1226  */
1227 gboolean
gck_session_login_interactive(GckSession * self,gulong user_type,GTlsInteraction * interaction,GCancellable * cancellable,GError ** error)1228 gck_session_login_interactive (GckSession *self,
1229                                gulong user_type,
1230                                GTlsInteraction *interaction,
1231                                GCancellable *cancellable,
1232                                GError **error)
1233 {
1234 	Interactive args = { GCK_ARGUMENTS_INIT, interaction, cancellable, NULL, };
1235 
1236 	g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
1237 	g_return_val_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction), FALSE);
1238 	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1239 	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1240 
1241 	/* TODO: For now this is all we support */
1242 	g_return_val_if_fail (user_type == CKU_USER, FALSE);
1243 
1244 	args.token = self->pv->slot;
1245 
1246 	return _gck_call_sync (self, perform_interactive, NULL, &args, cancellable, error);
1247 }
1248 
1249 /**
1250  * gck_session_login_interactive_async:
1251  * @self: session to use for login
1252  * @user_type: the type of login user
1253  * @interaction: (nullable): interaction to request PIN when necessary
1254  * @cancellable: optional cancellation object, or %NULL
1255  * @callback: called when the operation completes
1256  * @user_data: data to pass to the callback
1257  *
1258  * Login the user on the session prompting for passwords interactively when
1259  * necessary. This call will return immediately and completes asynchronously.
1260  **/
1261 void
gck_session_login_interactive_async(GckSession * self,gulong user_type,GTlsInteraction * interaction,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1262 gck_session_login_interactive_async (GckSession *self,
1263                                      gulong user_type,
1264                                      GTlsInteraction *interaction,
1265                                      GCancellable *cancellable,
1266                                      GAsyncReadyCallback callback,
1267                                      gpointer user_data)
1268 {
1269 	Interactive* args;
1270 	GckCall *call;
1271 
1272 	call = _gck_call_async_prep (self, perform_interactive, NULL, sizeof (*args), free_interactive);
1273 	args = _gck_call_get_arguments (call);
1274 
1275 	g_return_if_fail (GCK_IS_SESSION (self));
1276 	g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));
1277 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1278 
1279 	/* TODO: For now this is all we support */
1280 	g_return_if_fail (user_type == CKU_USER);
1281 
1282 	args->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1283 	args->interaction = interaction ? g_object_ref (interaction) : NULL;
1284 	args->token = g_object_ref (self->pv->slot);
1285 
1286 	_gck_call_async_ready_go (call, self, cancellable, callback, user_data);
1287 }
1288 
1289 /**
1290  * gck_session_login_interactive_finish:
1291  * @self: the session logged into
1292  * @result: the result passed to the callback
1293  * @error: location to return an error
1294  *
1295  * Get the result of a login operation.
1296  *
1297  * Return value: Whether the operation was successful or not.
1298  **/
1299 gboolean
gck_session_login_interactive_finish(GckSession * self,GAsyncResult * result,GError ** error)1300 gck_session_login_interactive_finish (GckSession *self,
1301                                       GAsyncResult *result,
1302                                       GError **error)
1303 {
1304 	g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
1305 
1306 	return _gck_call_basic_finish (result, error);
1307 }
1308 
1309 /* LOGOUT */
1310 
1311 static CK_RV
perform_logout(GckArguments * args)1312 perform_logout (GckArguments *args)
1313 {
1314 	return (args->pkcs11->C_Logout) (args->handle);
1315 }
1316 
1317 /**
1318  * gck_session_logout:
1319  * @self: Logout of this session.
1320  * @cancellable: Optional cancellation object, or %NULL.
1321  * @error: A location to return an error.
1322  *
1323  * Log out of the session. This call may block for an indefinite period.
1324  *
1325  * Return value: Whether the logout was successful or not.
1326  **/
1327 gboolean
gck_session_logout(GckSession * self,GCancellable * cancellable,GError ** error)1328 gck_session_logout (GckSession *self, GCancellable *cancellable, GError **error)
1329 {
1330 	GckArguments args = GCK_ARGUMENTS_INIT;
1331 	return _gck_call_sync (self, perform_logout, NULL, &args, cancellable, error);
1332 }
1333 
1334 /**
1335  * gck_session_logout_async:
1336  * @self: Logout of this session.
1337  * @cancellable: Optional cancellation object, or %NULL.
1338  * @callback: Called when the operation completes.
1339  * @user_data: Data to pass to the callback.
1340  *
1341  * Log out of the session. This call returns immediately and completes
1342  * asynchronously.
1343  **/
1344 void
gck_session_logout_async(GckSession * self,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1345 gck_session_logout_async (GckSession *self, GCancellable *cancellable,
1346                            GAsyncReadyCallback callback, gpointer user_data)
1347 {
1348 	GckCall *call;
1349 
1350 	call = _gck_call_async_prep (self, perform_logout, NULL, 0, NULL);
1351 	_gck_call_async_ready_go (call, self, cancellable, callback, user_data);
1352 }
1353 
1354 /**
1355  * gck_session_logout_finish:
1356  * @self: Logout of this session.
1357  * @result: The result passed to the callback.
1358  * @error: A location to return an error.
1359  *
1360  * Get the result of logging out of a session.
1361  *
1362  * Return value: Whether the logout was successful or not.
1363  **/
1364 gboolean
gck_session_logout_finish(GckSession * self,GAsyncResult * result,GError ** error)1365 gck_session_logout_finish (GckSession *self, GAsyncResult *result, GError **error)
1366 {
1367 	return _gck_call_basic_finish (result, error);
1368 }
1369 
1370 
1371 
1372 
1373 /* CREATE OBJECT */
1374 
1375 typedef struct _CreateObject {
1376 	GckArguments base;
1377 	GckAttributes *attrs;
1378 	CK_OBJECT_HANDLE object;
1379 } CreateObject;
1380 
1381 static void
free_create_object(CreateObject * args)1382 free_create_object (CreateObject *args)
1383 {
1384 	gck_attributes_unref (args->attrs);
1385 	g_free (args);
1386 }
1387 
1388 static CK_RV
perform_create_object(CreateObject * args)1389 perform_create_object (CreateObject *args)
1390 {
1391 	CK_ATTRIBUTE_PTR attrs;
1392 	CK_ULONG n_attrs;
1393 	CK_RV rv;
1394 
1395 	attrs = _gck_attributes_commit_out (args->attrs, &n_attrs);
1396 
1397 	rv = (args->base.pkcs11->C_CreateObject) (args->base.handle,
1398 	                                          attrs, n_attrs,
1399 	                                          &args->object);
1400 
1401 	gchar *string = gck_attributes_to_string (args->attrs);
1402 	if (rv == CKR_OK)
1403 		g_debug ("created object: %s", string);
1404 	else
1405 		g_debug ("failed %s to create object: %s",
1406 		         _gck_stringize_rv (rv), string);
1407 	g_free (string);
1408 
1409 	return rv;
1410 }
1411 
1412 /**
1413  * gck_session_create_object:
1414  * @self: The session to create the object on.
1415  * @attrs: The attributes to create the object with.
1416  * @cancellable: Optional cancellation object, or %NULL.
1417  * @error: A location to return an error, or %NULL.
1418  *
1419  * Create a new PKCS\#11 object. This call may block for an
1420  * indefinite period.
1421  *
1422  * If the @attrs #GckAttributes is floating, it is consumed.
1423  *
1424  * Returns: (transfer full): the newly created object or %NULL if an error occurred
1425  **/
1426 GckObject *
gck_session_create_object(GckSession * self,GckAttributes * attrs,GCancellable * cancellable,GError ** error)1427 gck_session_create_object (GckSession *self, GckAttributes *attrs,
1428                            GCancellable *cancellable, GError **error)
1429 {
1430 	CreateObject args = { GCK_ARGUMENTS_INIT, attrs, 0 };
1431 	gboolean ret;
1432 
1433 	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
1434 	g_return_val_if_fail (attrs != NULL, NULL);
1435 
1436 	gck_attributes_ref_sink (attrs);
1437 	ret = _gck_call_sync (self, perform_create_object, NULL, &args, cancellable, error);
1438 	gck_attributes_unref (attrs);
1439 
1440 	if (!ret)
1441 		return NULL;
1442 
1443 	return gck_object_from_handle (self, args.object);
1444 }
1445 
1446 /**
1447  * gck_session_create_object_async:
1448  * @self: The session to create the object on.
1449  * @attrs: The attributes to create the object with.
1450  * @cancellable: Optional cancellation object or %NULL.
1451  * @callback: Called when the operation completes.
1452  * @user_data: Data to pass to the callback.
1453  *
1454  * Create a new PKCS\#11 object. This call will return immediately
1455  * and complete asynchronously.
1456  *
1457  * If the @attrs #GckAttributes is floating, it is consumed.
1458  **/
1459 void
gck_session_create_object_async(GckSession * self,GckAttributes * attrs,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1460 gck_session_create_object_async (GckSession *self, GckAttributes *attrs,
1461                                   GCancellable *cancellable, GAsyncReadyCallback callback,
1462                                   gpointer user_data)
1463 {
1464 	GckCall *call;
1465 	CreateObject *args;
1466 
1467 	call = _gck_call_async_prep (self, perform_create_object,
1468 	                              NULL, sizeof (*args), free_create_object);
1469 	args = _gck_call_get_arguments (call);
1470 
1471 	g_return_if_fail (attrs);
1472 
1473 	args->attrs = gck_attributes_ref_sink (attrs);
1474 
1475 	_gck_call_async_ready_go (call, self, cancellable, callback, user_data);
1476 }
1477 
1478 /**
1479  * gck_session_create_object_finish:
1480  * @self: The session to create the object on.
1481  * @result: The result passed to the callback.
1482  * @error: A location to return an error, or %NULL.
1483  *
1484  * Get the result of creating a new PKCS\#11 object.
1485  *
1486  * Return value: (transfer full): the newly created object or %NULL if an error occurred
1487  **/
1488 GckObject *
gck_session_create_object_finish(GckSession * self,GAsyncResult * result,GError ** error)1489 gck_session_create_object_finish (GckSession *self, GAsyncResult *result, GError **error)
1490 {
1491 	CreateObject *args;
1492 
1493 	args = _gck_call_async_result_arguments (result, CreateObject);
1494 
1495 	if (!_gck_call_basic_finish (result, error))
1496 		return NULL;
1497 	return gck_object_from_handle (self, args->object);
1498 }
1499 
1500 
1501 
1502 /* FIND OBJECTS */
1503 
1504 typedef struct _FindObjects {
1505 	GckArguments base;
1506 	GckAttributes *attrs;
1507 	CK_OBJECT_HANDLE_PTR objects;
1508 	CK_ULONG n_objects;
1509 } FindObjects;
1510 
1511 static void
free_find_objects(FindObjects * args)1512 free_find_objects (FindObjects *args)
1513 {
1514 	gck_attributes_unref (args->attrs);
1515 	g_free (args->objects);
1516 	g_free (args);
1517 }
1518 
1519 static CK_RV
perform_find_objects(FindObjects * args)1520 perform_find_objects (FindObjects *args)
1521 {
1522 	CK_OBJECT_HANDLE_PTR batch;
1523 	CK_ULONG n_batch, n_found;
1524 	CK_ATTRIBUTE_PTR attrs;
1525 	CK_ULONG n_attrs;
1526 	GArray *array;
1527 	CK_RV rv;
1528 
1529 	gchar *string = gck_attributes_to_string (args->attrs);
1530 	g_debug ("matching: %s", string);
1531 	g_free (string);
1532 
1533 	attrs = _gck_attributes_commit_out (args->attrs, &n_attrs);
1534 
1535 	rv = (args->base.pkcs11->C_FindObjectsInit) (args->base.handle,
1536 	                                             attrs, n_attrs);
1537 	if (rv != CKR_OK)
1538 		return rv;
1539 
1540 	batch = NULL;
1541 	n_found = n_batch = 4;
1542 	array = g_array_new (0, 1, sizeof (CK_OBJECT_HANDLE));
1543 
1544 	do {
1545 		/*
1546 		 * Reallocate and double in size:
1547 		 *  - First time.
1548 		 *  - Each time we found as many as batch
1549 		 */
1550 
1551 		if (n_found == n_batch) {
1552 			n_batch *= 2;
1553 			batch = g_realloc (batch, sizeof (CK_OBJECT_HANDLE) * n_batch);
1554 		}
1555 
1556 		rv = (args->base.pkcs11->C_FindObjects) (args->base.handle,
1557 		                                         batch, n_batch, &n_found);
1558 		if (rv != CKR_OK)
1559 			break;
1560 
1561 		g_array_append_vals (array, batch, n_found);
1562 
1563 	} while (n_found > 0);
1564 
1565 	g_free (batch);
1566 
1567 	if (rv == CKR_OK) {
1568 		args->n_objects = array->len;
1569 		args->objects = (CK_OBJECT_HANDLE_PTR)g_array_free (array, FALSE);
1570 		rv = (args->base.pkcs11->C_FindObjectsFinal) (args->base.handle);
1571 	} else {
1572 		args->objects = NULL;
1573 		args->n_objects = 0;
1574 		g_array_free (array, TRUE);
1575 	}
1576 
1577 	return rv;
1578 }
1579 
1580 /**
1581  * gck_session_find_handles:
1582  * @self: the session to find objects on
1583  * @match: the attributes to match against objects
1584  * @cancellable: optional cancellation object or %NULL
1585  * @n_handles: location to return number of handles
1586  * @error: a location to return an error or %NULL
1587  *
1588  * Find the objects matching the passed attributes. This call may
1589  * block for an indefinite period.
1590  *
1591  * If the @match #GckAttributes is floating, it is consumed.
1592  *
1593  * Returns: (transfer full) (array length=n_handles) (nullable): a list of
1594  *          the matching objects, which may be empty
1595  **/
1596 gulong *
gck_session_find_handles(GckSession * self,GckAttributes * match,GCancellable * cancellable,gulong * n_handles,GError ** error)1597 gck_session_find_handles (GckSession *self,
1598                           GckAttributes *match,
1599                           GCancellable *cancellable,
1600                           gulong *n_handles,
1601                           GError **error)
1602 {
1603 	FindObjects args = { GCK_ARGUMENTS_INIT, match, NULL, 0 };
1604 	gulong *results = NULL;
1605 
1606 	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
1607 	g_return_val_if_fail (match != NULL, NULL);
1608 	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1609 	g_return_val_if_fail (n_handles != NULL, NULL);
1610 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1611 
1612 	gck_attributes_ref_sink (match);
1613 	if (_gck_call_sync (self, perform_find_objects, NULL, &args, cancellable, error)) {
1614 		results = args.objects;
1615 		*n_handles = args.n_objects;
1616 		args.objects = NULL;
1617 	}
1618 	gck_attributes_unref (match);
1619 
1620 	g_free (args.objects);
1621 	return results;
1622 }
1623 
1624 /**
1625  * gck_session_find_handles_async:
1626  * @self: the session to find objects on
1627  * @match: the attributes to match against the objects
1628  * @cancellable: optional cancellation object or %NULL
1629  * @callback: called when the operation completes
1630  * @user_data: data to pass to the callback
1631  *
1632  * Find the objects matching the passed attributes. This call will
1633  * return immediately and complete asynchronously.
1634  *
1635  * If the @match #GckAttributes is floating, it is consumed.
1636  **/
1637 void
gck_session_find_handles_async(GckSession * self,GckAttributes * match,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1638 gck_session_find_handles_async (GckSession *self,
1639                                 GckAttributes *match,
1640                                 GCancellable *cancellable,
1641                                 GAsyncReadyCallback callback,
1642                                 gpointer user_data)
1643 {
1644 	GckCall *call;
1645 	FindObjects *args;
1646 
1647 	g_return_if_fail (GCK_IS_SESSION (self));
1648 	g_return_if_fail (match != NULL);
1649 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1650 
1651 	call = _gck_call_async_prep (self, perform_find_objects,
1652 	                             NULL, sizeof (*args), free_find_objects);
1653 	args = _gck_call_get_arguments (call);
1654 	args->attrs = gck_attributes_ref_sink (match);
1655 	_gck_call_async_ready_go (call, self, cancellable, callback, user_data);
1656 }
1657 
1658 /**
1659  * gck_session_find_handles_finish:
1660  * @self: the session
1661  * @result: the asynchronous result
1662  * @n_handles: location to store number of handles returned
1663  * @error: a location to return an error on failure
1664  *
1665  * Get the result of a find handles operation.
1666  *
1667  * Returns: (transfer full) (array length=n_handles) (nullable): an array of
1668  *          handles that matched, which may be empty, or %NULL on failure
1669  **/
1670 gulong *
gck_session_find_handles_finish(GckSession * self,GAsyncResult * result,gulong * n_handles,GError ** error)1671 gck_session_find_handles_finish (GckSession *self,
1672                                  GAsyncResult *result,
1673                                  gulong *n_handles,
1674                                  GError **error)
1675 {
1676 	gulong *results = NULL;
1677 	FindObjects *args;
1678 
1679 	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
1680 	g_return_val_if_fail (n_handles != NULL, NULL);
1681 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1682 
1683 	args = _gck_call_async_result_arguments (result, FindObjects);
1684 
1685 	if (!_gck_call_basic_finish (result, error))
1686 		return NULL;
1687 	*n_handles = args->n_objects;
1688 	results = args->objects;
1689 	args->objects = NULL;
1690 	return results;
1691 }
1692 
1693 /**
1694  * gck_session_find_objects:
1695  * @self: The session to find objects on.
1696  * @match: the attributes to match
1697  * @cancellable: Optional cancellation object or %NULL.
1698  * @error: A location to return an error or %NULL.
1699  *
1700  * Find the objects matching the passed attributes. This call may
1701  * block for an indefinite period.
1702  *
1703  * If the @match #GckAttributes is floating, it is consumed.
1704  *
1705  * Returns: (transfer full) (element-type Gck.Object): a list of the matching
1706  *          objects, which may be empty
1707  **/
1708 GList *
gck_session_find_objects(GckSession * self,GckAttributes * match,GCancellable * cancellable,GError ** error)1709 gck_session_find_objects (GckSession *self,
1710                           GckAttributes *match,
1711                           GCancellable *cancellable,
1712                           GError **error)
1713 {
1714 	GList *results = NULL;
1715 	gulong *handles;
1716 	gulong n_handles;
1717 
1718 	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
1719 	g_return_val_if_fail (match != NULL, NULL);
1720 	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1721 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1722 
1723 	handles = gck_session_find_handles (self, match, cancellable, &n_handles, error);
1724 	if (handles == NULL)
1725 		return NULL;
1726 
1727 	results = gck_objects_from_handle_array (self, handles, n_handles);
1728 	g_free (handles);
1729 	return results;
1730 }
1731 
1732 /**
1733  * gck_session_find_objects_async:
1734  * @self: The session to find objects on.
1735  * @match: The attributes to match.
1736  * @cancellable: Optional cancellation object or %NULL.
1737  * @callback: Called when the operation completes.
1738  * @user_data: Data to pass to the callback.
1739  *
1740  * Find the objects matching the passed attributes. This call will
1741  * return immediately and complete asynchronously.
1742  *
1743  * If the @match #GckAttributes is floating, it is consumed.
1744  **/
1745 void
gck_session_find_objects_async(GckSession * self,GckAttributes * match,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1746 gck_session_find_objects_async (GckSession *self,
1747                                 GckAttributes *match,
1748                                 GCancellable *cancellable,
1749                                 GAsyncReadyCallback callback,
1750                                 gpointer user_data)
1751 {
1752 	g_return_if_fail (GCK_IS_SESSION (self));
1753 	g_return_if_fail (match != NULL);
1754 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1755 
1756 	gck_session_find_handles_async (self, match, cancellable, callback, user_data);
1757 }
1758 
1759 /**
1760  * gck_session_find_objects_finish:
1761  * @self: The session to find objects on.
1762  * @result: The attributes to match.
1763  * @error: A location to return an error.
1764  *
1765  * Get the result of a find operation.
1766  *
1767  * Returns: (transfer full) (element-type Gck.Object): a list of the matching
1768  *          objects, which may be empty
1769  **/
1770 GList *
gck_session_find_objects_finish(GckSession * self,GAsyncResult * result,GError ** error)1771 gck_session_find_objects_finish (GckSession *self,
1772                                  GAsyncResult *result,
1773                                  GError **error)
1774 {
1775 	GList *results = NULL;
1776 	gulong *handles;
1777 	gulong n_handles;
1778 
1779 	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
1780 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1781 
1782 	handles = gck_session_find_handles_finish (self, result, &n_handles, error);
1783 	if (handles == NULL)
1784 		return NULL;
1785 
1786 	results = gck_objects_from_handle_array (self, handles, n_handles);
1787 	g_free (handles);
1788 	return results;
1789 
1790 }
1791 
1792 /**
1793  * gck_session_enumerate_objects:
1794  * @self: session to enumerate objects on
1795  * @match: attributes that the objects must match, or empty for all objects
1796  *
1797  * Setup an enumerator for listing matching objects available via this session.
1798  *
1799  * If the @match #GckAttributes is floating, it is consumed.
1800  *
1801  * This call will not block but will return an enumerator immediately.
1802  *
1803  * Returns: (transfer full): a new enumerator
1804  **/
1805 GckEnumerator *
gck_session_enumerate_objects(GckSession * session,GckAttributes * match)1806 gck_session_enumerate_objects (GckSession *session,
1807                                GckAttributes *match)
1808 {
1809 	GckUriData *uri_data;
1810 
1811 	g_return_val_if_fail (match != NULL, NULL);
1812 
1813 	uri_data = gck_uri_data_new ();
1814 	uri_data->attributes = gck_attributes_ref_sink (match);
1815 
1816 	return _gck_enumerator_new_for_session (session, uri_data);
1817 }
1818 
1819 /* -----------------------------------------------------------------------------
1820  * KEY PAIR GENERATION
1821  */
1822 
1823 typedef struct _GenerateKeyPair {
1824 	GckArguments base;
1825 	GckMechanism mechanism;
1826 	GckAttributes *public_attrs;
1827 	GckAttributes *private_attrs;
1828 	CK_OBJECT_HANDLE public_key;
1829 	CK_OBJECT_HANDLE private_key;
1830 } GenerateKeyPair;
1831 
1832 static void
free_generate_key_pair(GenerateKeyPair * args)1833 free_generate_key_pair (GenerateKeyPair *args)
1834 {
1835 	gck_attributes_unref (args->public_attrs);
1836 	gck_attributes_unref (args->private_attrs);
1837 	g_free (args);
1838 }
1839 
1840 static CK_RV
perform_generate_key_pair(GenerateKeyPair * args)1841 perform_generate_key_pair (GenerateKeyPair *args)
1842 {
1843 	CK_ATTRIBUTE_PTR pub_attrs, priv_attrs;
1844 	CK_ULONG n_pub_attrs, n_priv_attrs;
1845 
1846 	g_assert (sizeof (CK_MECHANISM) == sizeof (GckMechanism));
1847 
1848 	pub_attrs = _gck_attributes_commit_out (args->public_attrs, &n_pub_attrs);
1849 	priv_attrs = _gck_attributes_commit_out (args->private_attrs, &n_priv_attrs);
1850 
1851 	return (args->base.pkcs11->C_GenerateKeyPair) (args->base.handle,
1852 	                                               (CK_MECHANISM_PTR)&(args->mechanism),
1853 	                                               pub_attrs, n_pub_attrs,
1854 	                                               priv_attrs, n_priv_attrs,
1855 	                                               &args->public_key,
1856 	                                               &args->private_key);
1857 }
1858 
1859 /**
1860  * gck_session_generate_key_pair:
1861  * @self: The session to use.
1862  * @mech_type: The mechanism type to use for key generation.
1863  * @public_attrs: Additional attributes for the generated public key.
1864  * @private_attrs: Additional attributes for the generated private key.
1865  * @public_key: (optional) (out): location to return the resulting public key
1866  * @private_key: (optional) (out): location to return the resulting private key.
1867  * @cancellable: Optional cancellation object, or %NULL.
1868  * @error: A location to return an error, or %NULL.
1869  *
1870  * Generate a new key pair of public and private keys. This call may block for an
1871  * indefinite period.
1872  *
1873  * If the @public_attrs and/or @private_attrs #GckAttributes is floating, it is
1874  * consumed.
1875  *
1876  * Return value: %TRUE if the operation succeeded.
1877  **/
1878 gboolean
gck_session_generate_key_pair(GckSession * self,gulong mech_type,GckAttributes * public_attrs,GckAttributes * private_attrs,GckObject ** public_key,GckObject ** private_key,GCancellable * cancellable,GError ** error)1879 gck_session_generate_key_pair (GckSession *self, gulong mech_type,
1880                                GckAttributes *public_attrs, GckAttributes *private_attrs,
1881                                GckObject **public_key, GckObject **private_key,
1882                                GCancellable *cancellable, GError **error)
1883 {
1884 	GckMechanism mech = { mech_type, NULL, 0 };
1885 	return gck_session_generate_key_pair_full (self, &mech, public_attrs, private_attrs, public_key, private_key, cancellable, error);
1886 }
1887 
1888 /**
1889  * gck_session_generate_key_pair_full:
1890  * @self: The session to use.
1891  * @mechanism: The mechanism to use for key generation.
1892  * @public_attrs: Additional attributes for the generated public key.
1893  * @private_attrs: Additional attributes for the generated private key.
1894  * @public_key: (optional) (out): a location to return the resulting public key
1895  * @private_key: (optional) (out): a location to return the resulting private key
1896  * @cancellable: Optional cancellation object, or %NULL.
1897  * @error: A location to return an error, or %NULL.
1898  *
1899  * Generate a new key pair of public and private keys. This call may block for an
1900  * indefinite period.
1901  *
1902  * If the @public_attrs and/or @private_attrs #GckAttributes is floating, it is
1903  * consumed.
1904  *
1905  * Return value: %TRUE if the operation succeeded.
1906  **/
1907 gboolean
gck_session_generate_key_pair_full(GckSession * self,GckMechanism * mechanism,GckAttributes * public_attrs,GckAttributes * private_attrs,GckObject ** public_key,GckObject ** private_key,GCancellable * cancellable,GError ** error)1908 gck_session_generate_key_pair_full (GckSession *self,
1909                                     GckMechanism *mechanism,
1910                                     GckAttributes *public_attrs,
1911                                     GckAttributes *private_attrs,
1912                                     GckObject **public_key,
1913                                     GckObject **private_key,
1914                                     GCancellable *cancellable,
1915                                     GError **error)
1916 {
1917 	GenerateKeyPair args = { GCK_ARGUMENTS_INIT, GCK_MECHANISM_EMPTY, public_attrs, private_attrs, 0, 0 };
1918 	gboolean ret;
1919 
1920 	g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
1921 	g_return_val_if_fail (mechanism, FALSE);
1922 	g_return_val_if_fail (public_attrs, FALSE);
1923 	g_return_val_if_fail (private_attrs, FALSE);
1924 
1925 	/* Shallow copy of the mechanism structure */
1926 	memcpy (&args.mechanism, mechanism, sizeof (args.mechanism));
1927 
1928 	gck_attributes_ref_sink (public_attrs);
1929 	gck_attributes_ref_sink (private_attrs);
1930 
1931 	ret = _gck_call_sync (self, perform_generate_key_pair, NULL, &args, cancellable, error);
1932 
1933 	gck_attributes_unref (private_attrs);
1934 	gck_attributes_unref (public_attrs);
1935 
1936 	if (!ret)
1937 		return FALSE;
1938 
1939 	if (public_key)
1940 		*public_key = gck_object_from_handle (self, args.public_key);
1941 	if (private_key)
1942 		*private_key = gck_object_from_handle (self, args.private_key);
1943 	return TRUE;
1944 }
1945 
1946 /**
1947  * gck_session_generate_key_pair_async:
1948  * @self: The session to use.
1949  * @mechanism: The mechanism to use for key generation.
1950  * @public_attrs: Additional attributes for the generated public key.
1951  * @private_attrs: Additional attributes for the generated private key.
1952  * @cancellable: Optional cancellation object or %NULL.
1953  * @callback: Called when the operation completes.
1954  * @user_data: Data to pass to the callback.
1955  *
1956  * Generate a new key pair of public and private keys. This call will
1957  * return immediately and complete asynchronously.
1958  *
1959  * If the @public_attrs and/or @private_attrs #GckAttributes is floating, it is
1960  * consumed.
1961  **/
1962 void
gck_session_generate_key_pair_async(GckSession * self,GckMechanism * mechanism,GckAttributes * public_attrs,GckAttributes * private_attrs,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1963 gck_session_generate_key_pair_async (GckSession *self, GckMechanism *mechanism,
1964                                       GckAttributes *public_attrs, GckAttributes *private_attrs,
1965                                       GCancellable *cancellable, GAsyncReadyCallback callback,
1966                                       gpointer user_data)
1967 {
1968 	GckCall *call;
1969 	GenerateKeyPair *args;
1970 
1971 	call  = _gck_call_async_prep (self, perform_generate_key_pair,
1972 	                              NULL, sizeof (*args), free_generate_key_pair);
1973 	args = _gck_call_get_arguments (call);
1974 
1975 	g_return_if_fail (GCK_IS_SESSION (self));
1976 	g_return_if_fail (mechanism);
1977 	g_return_if_fail (public_attrs);
1978 	g_return_if_fail (private_attrs);
1979 
1980 	/* Shallow copy of the mechanism structure */
1981 	memcpy (&args->mechanism, mechanism, sizeof (args->mechanism));
1982 
1983 	args->public_attrs = gck_attributes_ref_sink (public_attrs);
1984 	args->private_attrs = gck_attributes_ref_sink (private_attrs);
1985 
1986 	_gck_call_async_ready_go (call, self, cancellable, callback, user_data);
1987 }
1988 
1989 /**
1990  * gck_session_generate_key_pair_finish:
1991  * @self: The session to use.
1992  * @result: The async result passed to the callback.
1993  * @public_key: (optional) (out): a location to return the resulting public key
1994  * @private_key: (optional) (out): a location to return the resulting private key
1995  * @error: A location to return an error.
1996  *
1997  * Get the result of a generate key pair operation.
1998  *
1999  * Return value: %TRUE if the operation succeeded.
2000  **/
2001 gboolean
gck_session_generate_key_pair_finish(GckSession * self,GAsyncResult * result,GckObject ** public_key,GckObject ** private_key,GError ** error)2002 gck_session_generate_key_pair_finish (GckSession *self,
2003                                       GAsyncResult *result,
2004                                       GckObject **public_key,
2005                                       GckObject **private_key,
2006                                       GError **error)
2007 {
2008 	GenerateKeyPair *args;
2009 
2010 	g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
2011 	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
2012 	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2013 
2014 	args = _gck_call_async_result_arguments (result, GenerateKeyPair);
2015 
2016 	if (!_gck_call_basic_finish (result, error))
2017 		return FALSE;
2018 
2019 	if (public_key)
2020 		*public_key = gck_object_from_handle (self, args->public_key);
2021 	if (private_key)
2022 		*private_key = gck_object_from_handle (self, args->private_key);
2023 	return TRUE;
2024 }
2025 
2026 /* -----------------------------------------------------------------------------
2027  * KEY WRAPPING
2028  */
2029 
2030 typedef struct _WrapKey {
2031 	GckArguments base;
2032 	GckMechanism mechanism;
2033 	CK_OBJECT_HANDLE wrapper;
2034 	CK_OBJECT_HANDLE wrapped;
2035 	gpointer result;
2036 	gulong n_result;
2037 } WrapKey;
2038 
2039 static void
free_wrap_key(WrapKey * args)2040 free_wrap_key (WrapKey *args)
2041 {
2042 	g_free (args->result);
2043 	g_free (args);
2044 }
2045 
2046 static CK_RV
perform_wrap_key(WrapKey * args)2047 perform_wrap_key (WrapKey *args)
2048 {
2049 	CK_RV rv;
2050 
2051 	g_assert (sizeof (CK_MECHANISM) == sizeof (GckMechanism));
2052 
2053 	/* Get the length of the result */
2054 	rv = (args->base.pkcs11->C_WrapKey) (args->base.handle,
2055 	                                     (CK_MECHANISM_PTR)&(args->mechanism),
2056 	                                     args->wrapper, args->wrapped,
2057 	                                     NULL, &args->n_result);
2058 	if (rv != CKR_OK)
2059 		return rv;
2060 
2061 	/* And try again with a real buffer */
2062 	args->result = g_malloc0 (args->n_result);
2063 	return (args->base.pkcs11->C_WrapKey) (args->base.handle,
2064 	                                       (CK_MECHANISM_PTR)&(args->mechanism),
2065 	                                       args->wrapper, args->wrapped,
2066 	                                       args->result, &args->n_result);
2067 }
2068 
2069 /**
2070  * gck_session_wrap_key:
2071  * @self: The session to use.
2072  * @wrapper: The key to use for wrapping.
2073  * @mech_type: The mechanism type to use for wrapping.
2074  * @wrapped: The key to wrap.
2075  * @n_result: A location in which to return the length of the wrapped data.
2076  * @cancellable: A #GCancellable or %NULL
2077  * @error: A location to return an error, or %NULL.
2078  *
2079  * Wrap a key into a byte stream. This call may block for an
2080  * indefinite period.
2081  *
2082  * Returns: (transfer full) (array length=n_result): the wrapped data or %NULL
2083  *          if the operation failed
2084  **/
2085 guchar *
gck_session_wrap_key(GckSession * self,GckObject * key,gulong mech_type,GckObject * wrapped,gsize * n_result,GCancellable * cancellable,GError ** error)2086 gck_session_wrap_key (GckSession *self, GckObject *key, gulong mech_type,
2087                       GckObject *wrapped, gsize *n_result, GCancellable *cancellable, GError **error)
2088 {
2089 	GckMechanism mech = { mech_type, NULL, 0 };
2090 	return gck_session_wrap_key_full (self, key, &mech, wrapped, n_result, cancellable, error);
2091 }
2092 
2093 /**
2094  * gck_session_wrap_key_full:
2095  * @self: The session to use.
2096  * @wrapper: The key to use for wrapping.
2097  * @mechanism: The mechanism to use for wrapping.
2098  * @wrapped: The key to wrap.
2099  * @n_result: A location in which to return the length of the wrapped data.
2100  * @cancellable: Optional cancellation object, or %NULL.
2101  * @error: A location to return an error, or %NULL.
2102  *
2103  * Wrap a key into a byte stream. This call may block for an
2104  * indefinite period.
2105  *
2106  * Returns: (transfer full) (array length=n_result): the wrapped data or %NULL
2107  *          if the operation failed
2108  **/
2109 guchar *
gck_session_wrap_key_full(GckSession * self,GckObject * wrapper,GckMechanism * mechanism,GckObject * wrapped,gsize * n_result,GCancellable * cancellable,GError ** error)2110 gck_session_wrap_key_full (GckSession *self, GckObject *wrapper, GckMechanism *mechanism,
2111                             GckObject *wrapped, gsize *n_result, GCancellable *cancellable,
2112                             GError **error)
2113 {
2114 	WrapKey args = { GCK_ARGUMENTS_INIT, GCK_MECHANISM_EMPTY, 0, 0, NULL, 0 };
2115 	gboolean ret;
2116 
2117 	g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
2118 	g_return_val_if_fail (mechanism, FALSE);
2119 	g_return_val_if_fail (GCK_IS_OBJECT (wrapped), FALSE);
2120 	g_return_val_if_fail (GCK_IS_OBJECT (wrapper), FALSE);
2121 	g_return_val_if_fail (n_result, FALSE);
2122 
2123 	/* Shallow copy of the mechanism structure */
2124 	memcpy (&args.mechanism, mechanism, sizeof (args.mechanism));
2125 
2126 	g_object_get (wrapper, "handle", &args.wrapper, NULL);
2127 	g_return_val_if_fail (args.wrapper != 0, NULL);
2128 	g_object_get (wrapped, "handle", &args.wrapped, NULL);
2129 	g_return_val_if_fail (args.wrapped != 0, NULL);
2130 
2131 	ret = _gck_call_sync (self, perform_wrap_key, NULL, &args, cancellable, error);
2132 
2133 	if (!ret)
2134 		return FALSE;
2135 
2136 	*n_result = args.n_result;
2137 	return args.result;
2138 }
2139 
2140 /**
2141  * gck_session_wrap_key_async:
2142  * @self: The session to use.
2143  * @wrapper: The key to use for wrapping.
2144  * @mechanism: The mechanism to use for wrapping.
2145  * @wrapped: The key to wrap.
2146  * @cancellable: Optional cancellation object or %NULL.
2147  * @callback: Called when the operation completes.
2148  * @user_data: Data to pass to the callback.
2149  *
2150  * Wrap a key into a byte stream. This call will
2151  * return immediately and complete asynchronously.
2152  **/
2153 void
gck_session_wrap_key_async(GckSession * self,GckObject * key,GckMechanism * mechanism,GckObject * wrapped,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2154 gck_session_wrap_key_async (GckSession *self, GckObject *key, GckMechanism *mechanism,
2155                              GckObject *wrapped, GCancellable *cancellable,
2156                              GAsyncReadyCallback callback, gpointer user_data)
2157 {
2158 	GckCall *call;
2159 	WrapKey *args;
2160 
2161 	call = _gck_call_async_prep (self, perform_wrap_key,
2162 	                              NULL, sizeof (*args), free_wrap_key);
2163 	args = _gck_call_get_arguments (call);
2164 
2165 	g_return_if_fail (GCK_IS_SESSION (self));
2166 	g_return_if_fail (mechanism);
2167 	g_return_if_fail (GCK_IS_OBJECT (wrapped));
2168 	g_return_if_fail (GCK_IS_OBJECT (key));
2169 
2170 	/* Shallow copy of the mechanism structure */
2171 	memcpy (&args->mechanism, mechanism, sizeof (args->mechanism));
2172 
2173 	g_object_get (key, "handle", &args->wrapper, NULL);
2174 	g_return_if_fail (args->wrapper != 0);
2175 	g_object_get (wrapped, "handle", &args->wrapped, NULL);
2176 	g_return_if_fail (args->wrapped != 0);
2177 
2178 	_gck_call_async_ready_go (call, self, cancellable, callback, user_data);
2179 }
2180 
2181 /**
2182  * gck_session_wrap_key_finish:
2183  * @self: The session to use.
2184  * @result: The async result passed to the callback.
2185  * @n_result: A location in which to return the length of the wrapped data.
2186  * @error: A location to return an error.
2187  *
2188  * Get the result of a wrap key operation.
2189  *
2190  * Returns: (transfer full) (array length=n_result): the wrapped data or %NULL
2191  *          if the operation failed
2192  **/
2193 guchar *
gck_session_wrap_key_finish(GckSession * self,GAsyncResult * result,gsize * n_result,GError ** error)2194 gck_session_wrap_key_finish (GckSession *self, GAsyncResult *result,
2195                               gsize *n_result, GError **error)
2196 {
2197 	WrapKey *args;
2198 	gpointer ret;
2199 
2200 	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
2201 	g_return_val_if_fail (n_result, NULL);
2202 
2203 	args = _gck_call_async_result_arguments (result, WrapKey);
2204 
2205 	if (!_gck_call_basic_finish (result, error))
2206 		return NULL;
2207 
2208 	*n_result = args->n_result;
2209 	args->n_result = 0;
2210 	ret = args->result;
2211 	args->result = NULL;
2212 
2213 	return ret;
2214 }
2215 
2216 /* -----------------------------------------------------------------------------
2217  * KEY UNWRAPPING
2218  */
2219 
2220 typedef struct _UnwrapKey {
2221 	GckArguments base;
2222 	GckMechanism mechanism;
2223 	GckAttributes *attrs;
2224 	CK_OBJECT_HANDLE wrapper;
2225 	gconstpointer input;
2226 	gulong n_input;
2227 	CK_OBJECT_HANDLE unwrapped;
2228 } UnwrapKey;
2229 
2230 static void
free_unwrap_key(UnwrapKey * args)2231 free_unwrap_key (UnwrapKey *args)
2232 {
2233 	gck_attributes_unref (args->attrs);
2234 	g_free (args);
2235 }
2236 
2237 static CK_RV
perform_unwrap_key(UnwrapKey * args)2238 perform_unwrap_key (UnwrapKey *args)
2239 {
2240 	CK_ATTRIBUTE_PTR attrs;
2241 	CK_ULONG n_attrs;
2242 
2243 	g_assert (sizeof (CK_MECHANISM) == sizeof (GckMechanism));
2244 
2245 	attrs = _gck_attributes_commit_out (args->attrs, &n_attrs);
2246 
2247 	return (args->base.pkcs11->C_UnwrapKey) (args->base.handle,
2248 	                                         (CK_MECHANISM_PTR)&(args->mechanism),
2249 	                                         args->wrapper, (CK_BYTE_PTR)args->input,
2250 	                                         args->n_input, attrs, n_attrs,
2251 	                                         &args->unwrapped);
2252 }
2253 
2254 /**
2255  * gck_session_unwrap_key:
2256  * @self: The session to use.
2257  * @wrapper: The key to use for unwrapping.
2258  * @mech_type: The mechanism to use for unwrapping.
2259  * @input: (array length=n_input): the wrapped data as a byte stream
2260  * @n_input: The length of the wrapped data.
2261  * @attrs: Additional attributes for the unwrapped key.
2262  * @cancellable: Optional cancellation object, or %NULL.
2263  * @error: A location to return an error, or %NULL.
2264  *
2265  * Unwrap a key from a byte stream. This call may block for an
2266  * indefinite period.
2267  *
2268  * If the @attrs #GckAttributes is floating, it is consumed.
2269  *
2270  * Returns: (transfer full): the new unwrapped key or %NULL if the
2271  *          operation failed
2272  **/
2273 GckObject *
gck_session_unwrap_key(GckSession * self,GckObject * wrapper,gulong mech_type,const guchar * input,gsize n_input,GckAttributes * attrs,GCancellable * cancellable,GError ** error)2274 gck_session_unwrap_key (GckSession *self,
2275                         GckObject *wrapper,
2276                         gulong mech_type,
2277                         const guchar *input,
2278                         gsize n_input,
2279                         GckAttributes *attrs,
2280                         GCancellable *cancellable,
2281                         GError **error)
2282 {
2283 	GckMechanism mech = { mech_type, NULL, 0 };
2284 	return gck_session_unwrap_key_full (self, wrapper, &mech, input, n_input, attrs, cancellable, error);
2285 }
2286 
2287 /**
2288  * gck_session_unwrap_key_full:
2289  * @self: The session to use.
2290  * @wrapper: The key to use for unwrapping.
2291  * @mechanism: The mechanism to use for unwrapping.
2292  * @input: (array length=n_input): the wrapped data as a byte stream
2293  * @n_input: The length of the wrapped data.
2294  * @attrs: Additional attributes for the unwrapped key.
2295  * @cancellable: Optional cancellation object, or %NULL.
2296  * @error: A location to return an error, or %NULL.
2297  *
2298  * Unwrap a key from a byte stream. This call may block for an
2299  * indefinite period.
2300  *
2301  * If the @attrs #GckAttributes is floating, it is consumed.
2302  *
2303  * Returns: (transfer full): the new unwrapped key or %NULL if the operation
2304  *          failed
2305  **/
2306 GckObject *
gck_session_unwrap_key_full(GckSession * self,GckObject * wrapper,GckMechanism * mechanism,const guchar * input,gsize n_input,GckAttributes * attrs,GCancellable * cancellable,GError ** error)2307 gck_session_unwrap_key_full (GckSession *self,
2308                              GckObject *wrapper,
2309                              GckMechanism *mechanism,
2310                              const guchar *input,
2311                              gsize n_input,
2312                              GckAttributes *attrs,
2313                              GCancellable *cancellable,
2314                              GError **error)
2315 {
2316 	UnwrapKey args = { GCK_ARGUMENTS_INIT, GCK_MECHANISM_EMPTY, attrs, 0, input, n_input, 0 };
2317 	gboolean ret;
2318 
2319 	g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
2320 	g_return_val_if_fail (GCK_IS_OBJECT (wrapper), FALSE);
2321 	g_return_val_if_fail (mechanism, FALSE);
2322 	g_return_val_if_fail (attrs, FALSE);
2323 
2324 	/* Shallow copy of the mechanism structure */
2325 	memcpy (&args.mechanism, mechanism, sizeof (args.mechanism));
2326 
2327 	g_object_get (wrapper, "handle", &args.wrapper, NULL);
2328 	g_return_val_if_fail (args.wrapper != 0, NULL);
2329 
2330 	gck_attributes_ref_sink (attrs);
2331 
2332 	ret = _gck_call_sync (self, perform_unwrap_key, NULL, &args, cancellable, error);
2333 
2334 	gck_attributes_unref (attrs);
2335 
2336 	if (!ret)
2337 		return NULL;
2338 
2339 	return gck_object_from_handle (self, args.unwrapped);
2340 }
2341 
2342 /**
2343  * gck_session_unwrap_key_async:
2344  * @self: The session to use.
2345  * @wrapper: The key to use for unwrapping.
2346  * @mechanism: The mechanism to use for unwrapping.
2347  * @input: (array length=n_input): the wrapped data as a byte stream
2348  * @n_input: The length of the wrapped data.
2349  * @attrs: Additional attributes for the unwrapped key.
2350  * @cancellable: Optional cancellation object or %NULL.
2351  * @callback: Called when the operation completes.
2352  * @user_data: Data to pass to the callback.
2353  *
2354  * Unwrap a key from a byte stream. This call will
2355  * return immediately and complete asynchronously.
2356  *
2357  * If the @attrs #GckAttributes is floating, it is consumed.
2358  **/
2359 void
gck_session_unwrap_key_async(GckSession * self,GckObject * wrapper,GckMechanism * mechanism,const guchar * input,gsize n_input,GckAttributes * attrs,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2360 gck_session_unwrap_key_async (GckSession *self,
2361                               GckObject *wrapper,
2362                               GckMechanism *mechanism,
2363                               const guchar *input,
2364                               gsize n_input,
2365                               GckAttributes *attrs,
2366                               GCancellable *cancellable,
2367                               GAsyncReadyCallback callback,
2368                               gpointer user_data)
2369 {
2370 	GckCall *call;
2371 	UnwrapKey *args;
2372 
2373 	call = _gck_call_async_prep (self, perform_unwrap_key,
2374 	                             NULL, sizeof (*args), free_unwrap_key);
2375 	args = _gck_call_get_arguments (call);
2376 
2377 	g_return_if_fail (GCK_IS_SESSION (self));
2378 	g_return_if_fail (GCK_IS_OBJECT (wrapper));
2379 	g_return_if_fail (attrs);
2380 
2381 	g_object_get (wrapper, "handle", &args->wrapper, NULL);
2382 	g_return_if_fail (args->wrapper != 0);
2383 
2384 	/* Shallow copy of the mechanism structure */
2385 	memcpy (&args->mechanism, mechanism, sizeof (args->mechanism));
2386 
2387 	args->attrs = gck_attributes_ref_sink (attrs);
2388 	args->input = input;
2389 	args->n_input = n_input;
2390 
2391 	_gck_call_async_ready_go (call, self, cancellable, callback, user_data);
2392 }
2393 
2394 /**
2395  * gck_session_unwrap_key_finish:
2396  * @self: The session to use.
2397  * @result: The async result passed to the callback.
2398  * @error: A location to return an error.
2399  *
2400  * Get the result of a unwrap key operation.
2401  *
2402  * Returns: (transfer full): the new unwrapped key or %NULL if the operation
2403  *          failed.
2404  **/
2405 GckObject *
gck_session_unwrap_key_finish(GckSession * self,GAsyncResult * result,GError ** error)2406 gck_session_unwrap_key_finish (GckSession *self, GAsyncResult *result, GError **error)
2407 {
2408 	UnwrapKey *args;
2409 
2410 	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
2411 
2412 	args = _gck_call_async_result_arguments (result, UnwrapKey);
2413 
2414 	if (!_gck_call_basic_finish (result, error))
2415 		return NULL;
2416 	return gck_object_from_handle (self, args->unwrapped);
2417 }
2418 
2419 /* -----------------------------------------------------------------------------
2420  * KEY DERIVATION
2421  */
2422 
2423 typedef struct _DeriveKey {
2424 	GckArguments base;
2425 	GckMechanism mechanism;
2426 	GckAttributes *attrs;
2427 	CK_OBJECT_HANDLE key;
2428 	CK_OBJECT_HANDLE derived;
2429 } DeriveKey;
2430 
2431 static void
free_derive_key(DeriveKey * args)2432 free_derive_key (DeriveKey *args)
2433 {
2434 	gck_attributes_unref (args->attrs);
2435 	g_free (args);
2436 }
2437 
2438 static CK_RV
perform_derive_key(DeriveKey * args)2439 perform_derive_key (DeriveKey *args)
2440 {
2441 	CK_ATTRIBUTE_PTR attrs;
2442 	CK_ULONG n_attrs;
2443 
2444 	g_assert (sizeof (CK_MECHANISM) == sizeof (GckMechanism));
2445 
2446 	attrs = _gck_attributes_commit_out (args->attrs, &n_attrs);
2447 
2448 	return (args->base.pkcs11->C_DeriveKey) (args->base.handle,
2449 	                                         (CK_MECHANISM_PTR)&(args->mechanism),
2450 	                                         args->key, attrs, n_attrs,
2451 	                                         &args->derived);
2452 }
2453 
2454 /**
2455  * gck_session_derive_key:
2456  * @self: The session to use.
2457  * @base: The key to derive from.
2458  * @mech_type: The mechanism to use for derivation.
2459  * @attrs: Additional attributes for the derived key.
2460  * @cancellable: Optional cancellation object, or %NULL.
2461  * @error: A location to return an error, or %NULL.
2462  *
2463  * Derive a key from another key. This call may block for an
2464  * indefinite period.
2465  *
2466  * If the @attrs #GckAttributes is floating, it is consumed.
2467  *
2468  * Returns: (transfer full): the new derived key or %NULL if the operation
2469  *          failed
2470  **/
2471 GckObject *
gck_session_derive_key(GckSession * self,GckObject * base,gulong mech_type,GckAttributes * attrs,GCancellable * cancellable,GError ** error)2472 gck_session_derive_key (GckSession *self, GckObject *base, gulong mech_type,
2473                         GckAttributes *attrs, GCancellable *cancellable, GError **error)
2474 {
2475 	GckMechanism mech = { mech_type, NULL, 0 };
2476 	return gck_session_derive_key_full (self, base, &mech, attrs, cancellable, error);
2477 }
2478 
2479 /**
2480  * gck_session_derive_key_full:
2481  * @self: The session to use.
2482  * @base: The key to derive from.
2483  * @mechanism: The mechanism to use for derivation.
2484  * @attrs: Additional attributes for the derived key.
2485  * @cancellable: Optional cancellation object, or %NULL.
2486  * @error: A location to return an error, or %NULL.
2487  *
2488  * Derive a key from another key. This call may block for an
2489  * indefinite period.
2490  *
2491  * If the @attrs #GckAttributes is floating, it is consumed.
2492  *
2493  * Returns: (transfer full): the new derived key or %NULL if the operation
2494  *          failed
2495  **/
2496 GckObject*
gck_session_derive_key_full(GckSession * self,GckObject * base,GckMechanism * mechanism,GckAttributes * attrs,GCancellable * cancellable,GError ** error)2497 gck_session_derive_key_full (GckSession *self, GckObject *base, GckMechanism *mechanism,
2498                              GckAttributes *attrs, GCancellable *cancellable, GError **error)
2499 {
2500 	DeriveKey args = { GCK_ARGUMENTS_INIT, GCK_MECHANISM_EMPTY, attrs, 0, 0 };
2501 	gboolean ret;
2502 
2503 	g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
2504 	g_return_val_if_fail (GCK_IS_OBJECT (base), FALSE);
2505 	g_return_val_if_fail (mechanism, FALSE);
2506 	g_return_val_if_fail (attrs, FALSE);
2507 
2508 	/* Shallow copy of the mechanism structure */
2509 	memcpy (&args.mechanism, mechanism, sizeof (args.mechanism));
2510 
2511 	g_object_get (base, "handle", &args.key, NULL);
2512 	g_return_val_if_fail (args.key != 0, NULL);
2513 
2514 	gck_attributes_ref_sink (attrs);
2515 
2516 	ret = _gck_call_sync (self, perform_derive_key, NULL, &args, cancellable, error);
2517 
2518 	gck_attributes_unref (attrs);
2519 
2520 	if (!ret)
2521 		return NULL;
2522 
2523 	return gck_object_from_handle (self, args.derived);
2524 }
2525 
2526 /**
2527  * gck_session_derive_key_async:
2528  * @self: The session to use.
2529  * @base: The key to derive from.
2530  * @mechanism: The mechanism to use for derivation.
2531  * @attrs: Additional attributes for the derived key.
2532  * @cancellable: Optional cancellation object or %NULL.
2533  * @callback: Called when the operation completes.
2534  * @user_data: Data to pass to the callback.
2535  *
2536  * Derive a key from another key. This call will
2537  * return immediately and complete asynchronously.
2538  *
2539  * If the @attrs #GckAttributes is floating, it is consumed.
2540  **/
2541 void
gck_session_derive_key_async(GckSession * self,GckObject * base,GckMechanism * mechanism,GckAttributes * attrs,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2542 gck_session_derive_key_async (GckSession *self, GckObject *base, GckMechanism *mechanism,
2543                                GckAttributes *attrs, GCancellable *cancellable,
2544                                GAsyncReadyCallback callback, gpointer user_data)
2545 {
2546 	GckCall *call;
2547 	DeriveKey *args;
2548 
2549 	call = _gck_call_async_prep (self, perform_derive_key,
2550 	                             NULL, sizeof (*args), free_derive_key);
2551 	args = _gck_call_get_arguments (call);
2552 
2553 	g_return_if_fail (GCK_IS_SESSION (self));
2554 	g_return_if_fail (GCK_IS_OBJECT (base));
2555 	g_return_if_fail (attrs);
2556 
2557 	g_object_get (base, "handle", &args->key, NULL);
2558 	g_return_if_fail (args->key != 0);
2559 
2560 	/* Shallow copy of the mechanism structure */
2561 	memcpy (&args->mechanism, mechanism, sizeof (args->mechanism));
2562 
2563 	args->attrs = gck_attributes_ref_sink (attrs);
2564 
2565 	_gck_call_async_ready_go (call, self, cancellable, callback, user_data);
2566 }
2567 
2568 /**
2569  * gck_session_derive_key_finish:
2570  * @self: The session to use.
2571  * @result: The async result passed to the callback.
2572  * @error: A location to return an error.
2573  *
2574  * Get the result of a derive key operation.
2575  *
2576  * Returns: (transfer full): the new derived key or %NULL if the operation
2577  *          failed
2578  **/
2579 GckObject *
gck_session_derive_key_finish(GckSession * self,GAsyncResult * result,GError ** error)2580 gck_session_derive_key_finish (GckSession *self, GAsyncResult *result, GError **error)
2581 {
2582 	DeriveKey *args;
2583 
2584 	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
2585 
2586 	args = _gck_call_async_result_arguments (result, DeriveKey);
2587 
2588 	if (!_gck_call_basic_finish (result, error))
2589 		return NULL;
2590 
2591 	return gck_object_from_handle (self, args->derived);
2592 }
2593 
2594 /* --------------------------------------------------------------------------------------------------
2595  * COMMON CRYPTO ROUTINES
2596  */
2597 
2598 typedef struct _Crypt {
2599 	GckArguments base;
2600 
2601 	/* Functions to call */
2602 	CK_C_EncryptInit init_func;
2603 	CK_C_Encrypt complete_func;
2604 
2605 	/* Interaction */
2606 	GckObject *key_object;
2607 	GTlsInteraction *interaction;
2608 
2609 	/* Input */
2610 	CK_OBJECT_HANDLE key;
2611 	GckMechanism mechanism;
2612 	guchar *input;
2613 	CK_ULONG n_input;
2614 
2615 	/* Output */
2616 	guchar *result;
2617 	CK_ULONG n_result;
2618 
2619 } Crypt;
2620 
2621 static CK_RV
perform_crypt(Crypt * args)2622 perform_crypt (Crypt *args)
2623 {
2624 	GTlsInteraction *interaction;
2625 	CK_RV rv;
2626 
2627 	g_assert (args);
2628 	g_assert (args->init_func);
2629 	g_assert (args->complete_func);
2630 	g_assert (!args->result);
2631 	g_assert (!args->n_result);
2632 
2633 	/* Initialize the crypt operation */
2634 	rv = (args->init_func) (args->base.handle, (CK_MECHANISM_PTR)&(args->mechanism), args->key);
2635 	if (rv != CKR_OK)
2636 		return rv;
2637 
2638 	/* Compatibility, hook into GckModule signals if no interaction set */
2639 	if (args->interaction)
2640 		interaction = g_object_ref (args->interaction);
2641 	else
2642 		interaction = _gck_interaction_new (args->key_object);
2643 
2644 	rv = _gck_session_authenticate_key (args->base.pkcs11, args->base.handle,
2645 	                                    args->key_object, interaction, NULL);
2646 
2647 	g_object_unref (interaction);
2648 
2649 	if (rv != CKR_OK)
2650 		return rv;
2651 
2652 	/* Get the length of the result */
2653 	rv = (args->complete_func) (args->base.handle, args->input, args->n_input, NULL, &args->n_result);
2654 	if (rv != CKR_OK)
2655 		return rv;
2656 
2657 	/* And try again with a real buffer */
2658 	args->result = g_malloc0 (args->n_result);
2659 	return (args->complete_func) (args->base.handle, args->input, args->n_input, args->result, &args->n_result);
2660 }
2661 
2662 static void
free_crypt(Crypt * args)2663 free_crypt (Crypt *args)
2664 {
2665 	g_clear_object (&args->interaction);
2666 	g_clear_object (&args->key_object);
2667 
2668 	g_free (args->input);
2669 	g_free (args->result);
2670 	g_free (args);
2671 }
2672 
2673 static guchar*
crypt_sync(GckSession * self,GckObject * key,GckMechanism * mechanism,const guchar * input,gsize n_input,gsize * n_result,GCancellable * cancellable,GError ** error,CK_C_EncryptInit init_func,CK_C_Encrypt complete_func)2674 crypt_sync (GckSession *self, GckObject *key, GckMechanism *mechanism, const guchar *input,
2675             gsize n_input, gsize *n_result, GCancellable *cancellable, GError **error,
2676             CK_C_EncryptInit init_func, CK_C_Encrypt complete_func)
2677 {
2678 	Crypt args;
2679 
2680 	g_return_val_if_fail (GCK_IS_OBJECT (key), NULL);
2681 	g_return_val_if_fail (mechanism, NULL);
2682 	g_return_val_if_fail (init_func, NULL);
2683 	g_return_val_if_fail (complete_func, NULL);
2684 
2685 	memset (&args, 0, sizeof (args));
2686 	g_object_get (key, "handle", &args.key, NULL);
2687 	g_return_val_if_fail (args.key != 0, NULL);
2688 
2689 	/* Shallow copy of the mechanism structure */
2690 	memcpy (&args.mechanism, mechanism, sizeof (args.mechanism));
2691 
2692 	/* No need to copy in this case */
2693 	args.input = (guchar*)input;
2694 	args.n_input = n_input;
2695 
2696 	args.init_func = init_func;
2697 	args.complete_func = complete_func;
2698 
2699 	args.key_object = key;
2700 	args.interaction = gck_session_get_interaction (self);
2701 
2702 	if (!_gck_call_sync (self, perform_crypt, NULL, &args, cancellable, error)) {
2703 		g_free (args.result);
2704 		args.result = NULL;
2705 	} else {
2706 		*n_result = args.n_result;
2707 	}
2708 
2709 	g_clear_object (&args.interaction);
2710 	return args.result;
2711 }
2712 
2713 static void
crypt_async(GckSession * self,GckObject * key,GckMechanism * mechanism,const guchar * input,gsize n_input,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data,CK_C_EncryptInit init_func,CK_C_Encrypt complete_func)2714 crypt_async (GckSession *self, GckObject *key, GckMechanism *mechanism, const guchar *input,
2715              gsize n_input, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data,
2716              CK_C_EncryptInit init_func, CK_C_Encrypt complete_func)
2717 {
2718 	GckCall *call;
2719 	Crypt *args;
2720 
2721 	call = _gck_call_async_prep (self, perform_crypt, NULL, sizeof (*args), free_crypt);
2722 	args = _gck_call_get_arguments (call);
2723 
2724 	g_return_if_fail (GCK_IS_OBJECT (key));
2725 	g_return_if_fail (mechanism);
2726 	g_return_if_fail (init_func);
2727 	g_return_if_fail (complete_func);
2728 
2729 	g_object_get (key, "handle", &args->key, NULL);
2730 	g_return_if_fail (args->key != 0);
2731 
2732 	/* Shallow copy of the mechanism structure */
2733 	memcpy (&args->mechanism, mechanism, sizeof (args->mechanism));
2734 
2735 	args->input = input && n_input ? g_memdup (input, n_input) : NULL;
2736 	args->n_input = n_input;
2737 
2738 	args->init_func = init_func;
2739 	args->complete_func = complete_func;
2740 
2741 	args->key_object = g_object_ref (key);
2742 	args->interaction = gck_session_get_interaction (self);
2743 
2744 	_gck_call_async_ready_go (call, self, cancellable, callback, user_data);
2745 }
2746 
2747 static guchar*
crypt_finish(GckSession * self,GAsyncResult * result,gsize * n_result,GError ** error)2748 crypt_finish (GckSession *self, GAsyncResult *result, gsize *n_result, GError **error)
2749 {
2750 	Crypt *args;
2751 	guchar *res;
2752 
2753 	if (!_gck_call_basic_finish (result, error))
2754 		return NULL;
2755 	args = _gck_call_async_result_arguments (result, Crypt);
2756 
2757 	/* Steal the values from the results */
2758 	res = args->result;
2759 	args->result = NULL;
2760 	*n_result = args->n_result;
2761 	args->n_result = 0;
2762 
2763 	return res;
2764 }
2765 
2766 /* --------------------------------------------------------------------------------------------------
2767  * ENCRYPT
2768  */
2769 
2770 /**
2771  * gck_session_encrypt:
2772  * @self: The session.
2773  * @key: The key to encrypt with.
2774  * @mech_type: The mechanism type to use for encryption.
2775  * @input: (array length=n_input): the data to encrypt
2776  * @n_input: the length of the data to encrypt
2777  * @n_result: location to store the length of the result data
2778  * @cancellable: Optional cancellation object, or %NULL
2779  * @error: A location to place error information.
2780  *
2781  * Encrypt data in a mechanism specific manner. This call may
2782  * block for an indefinite period.
2783  *
2784  * Returns: (transfer full) (array length=n_result): the data that was encrypted,
2785  *          or %NULL if an error occured.
2786  */
2787 guchar *
gck_session_encrypt(GckSession * self,GckObject * key,gulong mech_type,const guchar * input,gsize n_input,gsize * n_result,GCancellable * cancellable,GError ** error)2788 gck_session_encrypt (GckSession *self, GckObject *key, gulong mech_type, const guchar *input,
2789                       gsize n_input, gsize *n_result, GCancellable *cancellable, GError **error)
2790 {
2791 	GckMechanism mechanism = { mech_type, NULL, 0 };
2792 	return gck_session_encrypt_full (self, key, &mechanism, input, n_input, n_result, cancellable, error);
2793 }
2794 
2795 /**
2796  * gck_session_encrypt_full:
2797  * @self: The session.
2798  * @key: The key to encrypt with.
2799  * @mechanism: The mechanism type and parameters to use for encryption.
2800  * @input: (array length=n_input): the data to encrypt
2801  * @n_input: the length of the data to encrypt
2802  * @n_result: location to store the length of the result data
2803  * @cancellable: A GCancellable which can be used to cancel the operation.
2804  * @error: A location to place error information.
2805  *
2806  * Encrypt data in a mechanism specific manner. This call may
2807  * block for an indefinite period.
2808  *
2809  * Returns: (transfer full) (array length=n_result): the data that was encrypted,
2810  *          or %NULL if an error occured
2811  */
2812 guchar *
gck_session_encrypt_full(GckSession * self,GckObject * key,GckMechanism * mechanism,const guchar * input,gsize n_input,gsize * n_result,GCancellable * cancellable,GError ** error)2813 gck_session_encrypt_full (GckSession *self, GckObject *key, GckMechanism *mechanism,
2814                            const guchar *input, gsize n_input, gsize *n_result,
2815                            GCancellable *cancellable, GError **error)
2816 {
2817 	GckModule *module = NULL;
2818 	CK_FUNCTION_LIST_PTR funcs;
2819 	guchar *ret;
2820 
2821 	g_object_get (self, "module", &module, NULL);
2822 	g_return_val_if_fail (module != NULL, NULL);
2823 
2824 	funcs = gck_module_get_functions (module);
2825 	g_return_val_if_fail (module != NULL, NULL);
2826 
2827 	ret = crypt_sync (self, key, mechanism, input, n_input, n_result, cancellable, error,
2828 	                  funcs->C_EncryptInit, funcs->C_Encrypt);
2829 
2830 	g_object_unref (module);
2831 	return ret;
2832 }
2833 
2834 /**
2835  * gck_session_encrypt_async:
2836  * @self: The session.
2837  * @key: The key to encrypt with.
2838  * @mechanism: The mechanism type and parameters to use for encryption.
2839  * @input: (array length=n_input): the data to encrypt
2840  * @n_input: length of the data to encrypt
2841  * @cancellable: A GCancellable which can be used to cancel the operation.
2842  * @callback: Called when the operation completes.
2843  * @user_data: A pointer to pass to the callback.
2844  *
2845  * Encrypt data in a mechanism specific manner. This call will
2846  * return immediately and complete asynchronously.
2847  **/
2848 void
gck_session_encrypt_async(GckSession * self,GckObject * key,GckMechanism * mechanism,const guchar * input,gsize n_input,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2849 gck_session_encrypt_async (GckSession *self, GckObject *key, GckMechanism *mechanism,
2850                             const guchar *input, gsize n_input, GCancellable *cancellable,
2851                             GAsyncReadyCallback callback, gpointer user_data)
2852 {
2853 	GckModule *module = NULL;
2854 	CK_FUNCTION_LIST_PTR funcs;
2855 
2856 	g_object_get (self, "module", &module, NULL);
2857 	g_return_if_fail (module != NULL);
2858 
2859 	funcs = gck_module_get_functions (module);
2860 	g_return_if_fail (module != NULL);
2861 
2862 	crypt_async (self, key, mechanism, input, n_input, cancellable, callback, user_data,
2863 	             funcs->C_EncryptInit, funcs->C_Encrypt);
2864 
2865 	g_object_unref (module);
2866 }
2867 
2868 /**
2869  * gck_session_encrypt_finish:
2870  * @self: The session.
2871  * @result: The result object passed to the callback.
2872  * @n_result: A location to store the length of the result data.
2873  * @error: A location to place error information.
2874  *
2875  * Get the result of an encryption operation.
2876  *
2877  * Returns: (transfer full) (array length=n_result): the data that was encrypted,
2878  *          or %NULL if an error occurred.
2879  */
2880 guchar*
gck_session_encrypt_finish(GckSession * self,GAsyncResult * result,gsize * n_result,GError ** error)2881 gck_session_encrypt_finish (GckSession *self, GAsyncResult *result, gsize *n_result,
2882                              GError **error)
2883 {
2884 	return crypt_finish (self, result, n_result, error);
2885 }
2886 
2887 /* --------------------------------------------------------------------------------------------------
2888  * DECRYPT
2889  */
2890 
2891 /**
2892  * gck_session_decrypt:
2893  * @self: The session.
2894  * @key: The key to decrypt with.
2895  * @mech_type: The mechanism type to use for decryption.
2896  * @input: (array length=n_input): data to decrypt
2897  * @n_input: length of the data to decrypt
2898  * @n_result: location to store the length of the result data
2899  * @cancellable: Optional cancellation object, or %NULL
2900  * @error: A location to place an error.
2901  *
2902  * Decrypt data in a mechanism specific manner. This call may
2903  * block for an indefinite period.
2904  *
2905  * Returns: (transfer full) (array length=n_result): the data that was decrypted,
2906  *          or %NULL if an error occured
2907  */
2908 guchar *
gck_session_decrypt(GckSession * self,GckObject * key,gulong mech_type,const guchar * input,gsize n_input,gsize * n_result,GCancellable * cancellable,GError ** error)2909 gck_session_decrypt (GckSession *self, GckObject *key, gulong mech_type, const guchar *input,
2910                       gsize n_input, gsize *n_result, GCancellable *cancellable, GError **error)
2911 {
2912 	GckMechanism mechanism = { mech_type, NULL, 0 };
2913 	return gck_session_decrypt_full (self, key, &mechanism, input, n_input, n_result, cancellable, error);
2914 }
2915 
2916 /**
2917  * gck_session_decrypt_full:
2918  * @self: The session.
2919  * @key: The key to decrypt with.
2920  * @mechanism: The mechanism type and parameters to use for decryption.
2921  * @input: (array length=n_input): data to decrypt
2922  * @n_input: length of the data to decrypt
2923  * @n_result: location to store the length of the result data
2924  * @cancellable: A GCancellable which can be used to cancel the operation.
2925  * @error: A location to place error information.
2926  *
2927  * Decrypt data in a mechanism specific manner. This call may
2928  * block for an indefinite period.
2929  *
2930  * Returns: (transfer full) (array length=n_result): the data that was decrypted,
2931  *          or %NULL if an error occured
2932  */
2933 guchar *
gck_session_decrypt_full(GckSession * self,GckObject * key,GckMechanism * mechanism,const guchar * input,gsize n_input,gsize * n_result,GCancellable * cancellable,GError ** error)2934 gck_session_decrypt_full (GckSession *self, GckObject *key, GckMechanism *mechanism,
2935                            const guchar *input, gsize n_input, gsize *n_result,
2936                            GCancellable *cancellable, GError **error)
2937 {
2938 	GckModule *module = NULL;
2939 	CK_FUNCTION_LIST_PTR funcs;
2940 	guchar *ret;
2941 
2942 	g_object_get (self, "module", &module, NULL);
2943 	g_return_val_if_fail (module != NULL, NULL);
2944 
2945 	funcs = gck_module_get_functions (module);
2946 	g_return_val_if_fail (module != NULL, NULL);
2947 
2948 	ret = crypt_sync (self, key, mechanism, input, n_input, n_result, cancellable, error,
2949 	                  funcs->C_DecryptInit, funcs->C_Decrypt);
2950 	g_object_unref (module);
2951 	return ret;
2952 }
2953 
2954 /**
2955  * gck_session_decrypt_async:
2956  * @self: The session.
2957  * @key: The key to decrypt with.
2958  * @mechanism: The mechanism type and parameters to use for decryption.
2959  * @input: (array length=n_input): data to decrypt
2960  * @n_input: length of the data to decrypt
2961  * @cancellable: A GCancellable which can be used to cancel the operation.
2962  * @callback: Called when the operation completes.
2963  * @user_data: A pointer to pass to the callback.
2964  *
2965  * Decrypt data in a mechanism specific manner. This call will
2966  * return immediately and complete asynchronously.
2967  */
2968 void
gck_session_decrypt_async(GckSession * self,GckObject * key,GckMechanism * mechanism,const guchar * input,gsize n_input,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2969 gck_session_decrypt_async (GckSession *self, GckObject *key, GckMechanism *mechanism,
2970                             const guchar *input, gsize n_input, GCancellable *cancellable,
2971                             GAsyncReadyCallback callback, gpointer user_data)
2972 {
2973 	GckModule *module = NULL;
2974 	CK_FUNCTION_LIST_PTR funcs;
2975 
2976 	g_object_get (self, "module", &module, NULL);
2977 	g_return_if_fail (module != NULL);
2978 
2979 	funcs = gck_module_get_functions (module);
2980 	g_return_if_fail (module != NULL);
2981 
2982 	crypt_async (self, key, mechanism, input, n_input, cancellable, callback, user_data,
2983 	             funcs->C_DecryptInit, funcs->C_Decrypt);
2984 	g_object_unref (module);
2985 }
2986 
2987 /**
2988  * gck_session_decrypt_finish:
2989  * @self: The session.
2990  * @result: The result object passed to the callback.
2991  * @n_result: A location to store the length of the result data.
2992  * @error: A location to place error information.
2993  *
2994  * Get the result of an decryption operation.
2995  *
2996  * Returns: (transfer full) (array length=n_result): the data that was decrypted,
2997  *          or %NULL if an error occurred
2998  */
2999 guchar*
gck_session_decrypt_finish(GckSession * self,GAsyncResult * result,gsize * n_result,GError ** error)3000 gck_session_decrypt_finish (GckSession *self, GAsyncResult *result,
3001                              gsize *n_result, GError **error)
3002 {
3003 	return crypt_finish (self, result, n_result, error);
3004 }
3005 
3006 /* --------------------------------------------------------------------------------------------------
3007  * SIGN
3008  */
3009 
3010 /**
3011  * gck_session_sign:
3012  * @self: The session.
3013  * @key: The key to sign with.
3014  * @mech_type: The mechanism type to use for signing.
3015  * @input: (array length=n_input): data to sign
3016  * @n_input: length of the data to sign
3017  * @n_result: location to store the length of the result data
3018  * @cancellable: Optional cancellation object, or %NULL
3019  * @error: A location to place an error.
3020  *
3021  * Sign data in a mechanism specific manner. This call may
3022  * block for an indefinite period.
3023  *
3024  * Returns: (transfer full) (array length=n_result): the data that was signed,
3025  *          or %NULL if an error occured
3026  */
3027 guchar *
gck_session_sign(GckSession * self,GckObject * key,gulong mech_type,const guchar * input,gsize n_input,gsize * n_result,GCancellable * cancellable,GError ** error)3028 gck_session_sign (GckSession *self, GckObject *key, gulong mech_type, const guchar *input,
3029                    gsize n_input, gsize *n_result, GCancellable *cancellable, GError **error)
3030 {
3031 	GckMechanism mechanism = { mech_type, NULL, 0 };
3032 	return gck_session_sign_full (self, key, &mechanism, input, n_input, n_result, NULL, error);
3033 }
3034 
3035 /**
3036  * gck_session_sign_full:
3037  * @self: The session.
3038  * @key: The key to sign with.
3039  * @mechanism: The mechanism type and parameters to use for signing.
3040  * @input: (array length=n_input): data to sign
3041  * @n_input: length of the data to sign
3042  * @n_result: location to store the length of the result data
3043  * @cancellable: A GCancellable which can be used to cancel the operation.
3044  * @error: A location to place error information.
3045  *
3046  * Sign data in a mechanism specific manner. This call may
3047  * block for an indefinite period.
3048  *
3049  * Returns: The data that was signed, or %NULL if an error occured.
3050  */
3051 guchar*
gck_session_sign_full(GckSession * self,GckObject * key,GckMechanism * mechanism,const guchar * input,gsize n_input,gsize * n_result,GCancellable * cancellable,GError ** error)3052 gck_session_sign_full (GckSession *self, GckObject *key, GckMechanism *mechanism,
3053                         const guchar *input, gsize n_input, gsize *n_result,
3054                         GCancellable *cancellable, GError **error)
3055 {
3056 	GckModule *module = NULL;
3057 	CK_FUNCTION_LIST_PTR funcs;
3058 	guchar *ret;
3059 
3060 	g_object_get (self, "module", &module, NULL);
3061 	g_return_val_if_fail (module != NULL, NULL);
3062 
3063 	funcs = gck_module_get_functions (module);
3064 	g_return_val_if_fail (module != NULL, NULL);
3065 
3066 	ret = crypt_sync (self, key, mechanism, input, n_input, n_result, cancellable, error,
3067 	                  funcs->C_SignInit, funcs->C_Sign);
3068 	g_object_unref (module);
3069 	return ret;
3070 }
3071 
3072 /**
3073  * gck_session_sign_async:
3074  * @self: The session.
3075  * @key: The key to sign with.
3076  * @mechanism: The mechanism type and parameters to use for signing.
3077  * @input: (array length=n_input): data to sign
3078  * @n_input: length of the data to sign
3079  * @cancellable: A GCancellable which can be used to cancel the operation.
3080  * @callback: Called when the operation completes.
3081  * @user_data: A pointer to pass to the callback.
3082  *
3083  * Sign data in a mechanism specific manner. This call will
3084  * return immediately and complete asynchronously.
3085  */
3086 void
gck_session_sign_async(GckSession * self,GckObject * key,GckMechanism * mechanism,const guchar * input,gsize n_input,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)3087 gck_session_sign_async (GckSession *self, GckObject *key, GckMechanism *mechanism,
3088                          const guchar *input, gsize n_input, GCancellable *cancellable,
3089                          GAsyncReadyCallback callback, gpointer user_data)
3090 {
3091 	GckModule *module = NULL;
3092 	CK_FUNCTION_LIST_PTR funcs;
3093 
3094 	g_object_get (self, "module", &module, NULL);
3095 	g_return_if_fail (module != NULL);
3096 
3097 	funcs = gck_module_get_functions (module);
3098 	g_return_if_fail (module != NULL);
3099 
3100 	crypt_async (self, key, mechanism, input, n_input, cancellable, callback, user_data,
3101 	             funcs->C_SignInit, funcs->C_Sign);
3102 	g_object_unref (module);
3103 }
3104 
3105 /**
3106  * gck_session_sign_finish:
3107  * @self: The session.
3108  * @result: The result object passed to the callback.
3109  * @n_result: A location to store the length of the result data.
3110  * @error: A location to place error information.
3111  *
3112  * Get the result of an signing operation.
3113  *
3114  * Returns: (transfer full) (array length=n_result): the data that was signed,
3115  *          or %NULL if an error occurred
3116  */
3117 guchar *
gck_session_sign_finish(GckSession * self,GAsyncResult * result,gsize * n_result,GError ** error)3118 gck_session_sign_finish (GckSession *self, GAsyncResult *result,
3119                           gsize *n_result, GError **error)
3120 {
3121 	return crypt_finish (self, result, n_result, error);
3122 }
3123 
3124 /* --------------------------------------------------------------------------------------------------
3125  * VERIFY
3126  */
3127 
3128 typedef struct _Verify {
3129 	GckArguments base;
3130 
3131 	/* Interaction */
3132 	GckObject *key_object;
3133 	GTlsInteraction *interaction;
3134 
3135 	/* Input */
3136 	CK_OBJECT_HANDLE key;
3137 	GckMechanism mechanism;
3138 	guchar *input;
3139 	CK_ULONG n_input;
3140 	guchar *signature;
3141 	CK_ULONG n_signature;
3142 
3143 } Verify;
3144 
3145 static CK_RV
perform_verify(Verify * args)3146 perform_verify (Verify *args)
3147 {
3148 	GTlsInteraction *interaction;
3149 	CK_RV rv;
3150 
3151 	/* Initialize the crypt operation */
3152 	rv = (args->base.pkcs11->C_VerifyInit) (args->base.handle, (CK_MECHANISM_PTR)&(args->mechanism), args->key);
3153 	if (rv != CKR_OK)
3154 		return rv;
3155 
3156 	/* Compatibility, hook into GckModule signals if no interaction set */
3157 	if (args->interaction)
3158 		interaction = g_object_ref (args->interaction);
3159 	else
3160 		interaction = _gck_interaction_new (args->key_object);
3161 
3162 
3163 	rv = _gck_session_authenticate_key (args->base.pkcs11, args->base.handle,
3164 	                                    args->key_object, interaction, NULL);
3165 
3166 	g_object_unref (interaction);
3167 
3168 	if (rv != CKR_OK)
3169 		return rv;
3170 
3171 	/* Do the actual verify */
3172 	return (args->base.pkcs11->C_Verify) (args->base.handle, args->input, args->n_input,
3173 	                                      args->signature, args->n_signature);
3174 }
3175 
3176 static void
free_verify(Verify * args)3177 free_verify (Verify *args)
3178 {
3179 	g_clear_object (&args->interaction);
3180 	g_clear_object (&args->key_object);
3181 
3182 	g_free (args->input);
3183 	g_free (args->signature);
3184 	g_free (args);
3185 }
3186 
3187 /**
3188  * gck_session_verify:
3189  * @self: The session.
3190  * @key: The key to verify with.
3191  * @mech_type: The mechanism type to use for verifying.
3192  * @input: (array length=n_input): data to verify
3193  * @n_input: length of the data to verify
3194  * @signature: (array length=n_signature): the signature
3195  * @n_signature: length of the signature
3196  * @cancellable: Optional cancellation object, or %NULL
3197  * @error: A location to place an error.
3198  *
3199  * Verify data in a mechanism specific manner. This call may
3200  * block for an indefinite period.
3201  *
3202  * Returns: %TRUE if the data verified correctly, otherwise a failure or error occurred.
3203  */
3204 gboolean
gck_session_verify(GckSession * self,GckObject * key,gulong mech_type,const guchar * input,gsize n_input,const guchar * signature,gsize n_signature,GCancellable * cancellable,GError ** error)3205 gck_session_verify (GckSession *self, GckObject *key, gulong mech_type, const guchar *input,
3206                      gsize n_input, const guchar *signature, gsize n_signature, GCancellable *cancellable, GError **error)
3207 {
3208 	GckMechanism mechanism = { mech_type, NULL, 0 };
3209 	return gck_session_verify_full (self, key, &mechanism, input, n_input,
3210 	                                 signature, n_signature, NULL, error);
3211 }
3212 
3213 /**
3214  * gck_session_verify_full:
3215  * @self: The session.
3216  * @key: The key to verify with.
3217  * @mechanism: The mechanism type and parameters to use for signing.
3218  * @input: (array length=n_input): data to verify
3219  * @n_input: the length of the data to verify
3220  * @signature: (array length=n_signature): the signature
3221  * @n_signature: length of the signature
3222  * @cancellable: A GCancellable which can be used to cancel the operation.
3223  * @error: A location to place an error.
3224  *
3225  * Verify data in a mechanism specific manner. This call may
3226  * block for an indefinite period.
3227  *
3228  * Returns: %TRUE if the data verified correctly, otherwise a failure or error occurred.
3229  */
3230 gboolean
gck_session_verify_full(GckSession * self,GckObject * key,GckMechanism * mechanism,const guchar * input,gsize n_input,const guchar * signature,gsize n_signature,GCancellable * cancellable,GError ** error)3231 gck_session_verify_full (GckSession *self, GckObject *key, GckMechanism *mechanism,
3232                           const guchar *input, gsize n_input, const guchar *signature,
3233                           gsize n_signature, GCancellable *cancellable, GError **error)
3234 {
3235 	Verify args;
3236 	gboolean ret;
3237 
3238 	g_return_val_if_fail (GCK_IS_OBJECT (key), FALSE);
3239 	g_return_val_if_fail (mechanism, FALSE);
3240 
3241 	memset (&args, 0, sizeof (args));
3242 	g_object_get (key, "handle", &args.key, NULL);
3243 	g_return_val_if_fail (args.key != 0, FALSE);
3244 
3245 	/* Shallow copy of the mechanism structure */
3246 	memcpy (&args.mechanism, mechanism, sizeof (args.mechanism));
3247 
3248 	/* No need to copy in this case */
3249 	args.input = (guchar*)input;
3250 	args.n_input = n_input;
3251 	args.signature = (guchar*)signature;
3252 	args.n_signature = n_signature;
3253 
3254 	args.key_object = key;
3255 	args.interaction = gck_session_get_interaction (self);
3256 
3257 	ret = _gck_call_sync (self, perform_verify, NULL, &args, cancellable, error);
3258 
3259 	g_clear_object (&args.interaction);
3260 
3261 	return ret;
3262 }
3263 
3264 /**
3265  * gck_session_verify_async:
3266  * @self: The session.
3267  * @key: The key to verify with.
3268  * @mechanism: The mechanism type and parameters to use for signing.
3269  * @input: (array length=n_input): data to verify
3270  * @n_input: the length of the data to verify
3271  * @signature: (array length=n_signature): the signature
3272  * @n_signature: the length of the signature
3273  * @cancellable: A GCancellable which can be used to cancel the operation.
3274  * @callback: Called when the operation completes.
3275  * @user_data: A pointer to pass to the callback.
3276  *
3277  * Verify data in a mechanism specific manner. This call returns
3278  * immediately and completes asynchronously.
3279  */
3280 void
gck_session_verify_async(GckSession * self,GckObject * key,GckMechanism * mechanism,const guchar * input,gsize n_input,const guchar * signature,gsize n_signature,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)3281 gck_session_verify_async (GckSession *self, GckObject *key, GckMechanism *mechanism,
3282                            const guchar *input, gsize n_input, const guchar *signature,
3283                            gsize n_signature, GCancellable *cancellable,
3284                            GAsyncReadyCallback callback, gpointer user_data)
3285 {
3286 	GckCall *call;
3287 	Verify *args;
3288 
3289 	call = _gck_call_async_prep (self, perform_verify, NULL, sizeof (*args), free_verify);
3290 	args = _gck_call_get_arguments (call);
3291 
3292 	g_return_if_fail (GCK_IS_OBJECT (key));
3293 	g_return_if_fail (mechanism);
3294 
3295 	g_object_get (key, "handle", &args->key, NULL);
3296 	g_return_if_fail (args->key != 0);
3297 
3298 	/* Shallow copy of the mechanism structure */
3299 	memcpy (&args->mechanism, mechanism, sizeof (args->mechanism));
3300 
3301 	args->input = input && n_input ? g_memdup (input, n_input) : NULL;
3302 	args->n_input = n_input;
3303 	args->signature = signature && n_signature ? g_memdup (signature, n_signature) : NULL;
3304 	args->n_signature = n_signature;
3305 
3306 	args->key_object = g_object_ref (key);
3307 	args->interaction = gck_session_get_interaction (self);
3308 
3309 	_gck_call_async_ready_go (call, self, cancellable, callback, user_data);
3310 }
3311 
3312 /**
3313  * gck_session_verify_finish:
3314  * @self: The session.
3315  * @result: The result object passed to the callback.
3316  * @error: A location to place error information.
3317  *
3318  * Get the result of an verify operation.
3319  *
3320  * Returns: %TRUE if the data verified correctly, otherwise a failure or error occurred.
3321  */
3322 gboolean
gck_session_verify_finish(GckSession * self,GAsyncResult * result,GError ** error)3323 gck_session_verify_finish (GckSession *self, GAsyncResult *result, GError **error)
3324 {
3325 	return _gck_call_basic_finish (result, error);
3326 }
3327 
3328 static void
update_password_for_token(GTlsPassword * password,CK_TOKEN_INFO * token_info,gboolean request_retry)3329 update_password_for_token (GTlsPassword *password,
3330                            CK_TOKEN_INFO *token_info,
3331                            gboolean request_retry)
3332 {
3333 	GTlsPasswordFlags flags;
3334 	gchar *label;
3335 
3336 	label = gck_string_from_chars (token_info->label, sizeof (token_info->label));
3337 	g_tls_password_set_description (password, label);
3338 	g_free (label);
3339 
3340 	flags = 0;
3341 	if (request_retry)
3342 		flags |= G_TLS_PASSWORD_RETRY;
3343 	if (token_info && token_info->flags & CKF_USER_PIN_COUNT_LOW)
3344 		flags |= G_TLS_PASSWORD_MANY_TRIES;
3345 	if (token_info && token_info->flags & CKF_USER_PIN_FINAL_TRY)
3346 		flags |= G_TLS_PASSWORD_FINAL_TRY;
3347 	g_tls_password_set_flags (password, flags);
3348 }
3349 
3350 CK_RV
_gck_session_authenticate_token(CK_FUNCTION_LIST_PTR funcs,CK_SESSION_HANDLE session,GckSlot * token,GTlsInteraction * interaction,GCancellable * cancellable)3351 _gck_session_authenticate_token (CK_FUNCTION_LIST_PTR funcs,
3352                                  CK_SESSION_HANDLE session,
3353                                  GckSlot *token,
3354                                  GTlsInteraction *interaction,
3355                                  GCancellable *cancellable)
3356 {
3357 	CK_SESSION_INFO session_info;
3358 	GTlsPassword *password = NULL;
3359 	CK_TOKEN_INFO token_info;
3360 	GTlsInteractionResult res;
3361 	gboolean request_retry;
3362 	CK_SLOT_ID slot_id;
3363 	CK_BYTE_PTR pin;
3364 	gsize n_pin;
3365 	CK_RV rv = CKR_OK;
3366 	GError *error = NULL;
3367 
3368 	g_assert (funcs != NULL);
3369 	g_assert (GCK_IS_SLOT (token));
3370 
3371 	slot_id = gck_slot_get_handle (token);
3372 	request_retry = FALSE;
3373 
3374 	do {
3375 		if (g_cancellable_is_cancelled (cancellable)) {
3376 			rv = CKR_FUNCTION_CANCELED;
3377 			break;
3378 		}
3379 
3380 		rv = (funcs->C_GetTokenInfo) (slot_id, &token_info);
3381 		if (rv != CKR_OK) {
3382 			g_warning ("couldn't get token info when logging in: %s",
3383 			           gck_message_from_rv (rv));
3384 			break;
3385 		}
3386 
3387 		/* No login necessary? */
3388 		if ((token_info.flags & CKF_LOGIN_REQUIRED) == 0) {
3389 			g_debug ("no login required for token, skipping login");
3390 			rv = CKR_OK;
3391 			break;
3392 		}
3393 
3394 		/* Next check if session is logged in? */
3395 		rv = (funcs->C_GetSessionInfo) (session, &session_info);
3396 		if (rv != CKR_OK) {
3397 			g_warning ("couldn't get session info when logging in: %s",
3398 			           gck_message_from_rv (rv));
3399 			break;
3400 		}
3401 
3402 		/* Already logged in? */
3403 		if (session_info.state == CKS_RW_USER_FUNCTIONS ||
3404 		    session_info.state == CKS_RO_USER_FUNCTIONS ||
3405 		    session_info.state == CKS_RW_SO_FUNCTIONS) {
3406 			g_debug ("already logged in, skipping login");
3407 			rv = CKR_OK;
3408 			break;
3409 		}
3410 
3411 		if (token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
3412 			g_debug ("trying to log into session: protected authentication path, no password");
3413 
3414 			/* No password passed for PAP */
3415 			pin = NULL;
3416 			n_pin = 0;
3417 
3418 
3419 		/* Not protected auth path */
3420 		} else {
3421 			g_debug ("trying to log into session: want password %s",
3422 			            request_retry ? "login was incorrect" : "");
3423 
3424 			if (password == NULL)
3425 				password = g_object_new (GCK_TYPE_PASSWORD, "token", token, NULL);
3426 
3427 			update_password_for_token (password, &token_info, request_retry);
3428 
3429 			if (interaction == NULL)
3430 				res = G_TLS_INTERACTION_UNHANDLED;
3431 
3432 			else
3433 				res = g_tls_interaction_invoke_ask_password (interaction,
3434 				                                             G_TLS_PASSWORD (password),
3435 				                                             NULL, &error);
3436 
3437 			if (res == G_TLS_INTERACTION_FAILED) {
3438 				g_message ("interaction couldn't ask password: %s", error->message);
3439 				rv = _gck_rv_from_error (error, CKR_USER_NOT_LOGGED_IN);
3440 				g_clear_error (&error);
3441 				break;
3442 
3443 			} else if (res == G_TLS_INTERACTION_UNHANDLED) {
3444 				g_message ("couldn't authenticate: no interaction handler");
3445 				rv = CKR_USER_NOT_LOGGED_IN;
3446 				break;
3447 			}
3448 
3449 			pin = (CK_BYTE_PTR)g_tls_password_get_value (password, &n_pin);
3450 		}
3451 
3452 		/* Try to log in */
3453 		rv = (funcs->C_Login) (session, CKU_USER, (CK_BYTE_PTR)pin, (CK_ULONG)n_pin);
3454 
3455 		/* Only one C_Login call if protected auth path */
3456 		if (token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
3457 			break;
3458 
3459 		request_retry = TRUE;
3460 	} while (rv == CKR_PIN_INCORRECT);
3461 
3462 	g_clear_object (&password);
3463 
3464 	return rv;
3465 }
3466 
3467 static void
update_password_for_key(GTlsPassword * password,CK_TOKEN_INFO * token_info,gboolean request_retry)3468 update_password_for_key (GTlsPassword *password,
3469                          CK_TOKEN_INFO *token_info,
3470                          gboolean request_retry)
3471 {
3472 	GTlsPasswordFlags flags;
3473 
3474 	flags = 0;
3475 	if (request_retry)
3476 		flags |= G_TLS_PASSWORD_RETRY;
3477 	if (token_info && token_info->flags & CKF_USER_PIN_COUNT_LOW)
3478 		flags |= G_TLS_PASSWORD_MANY_TRIES;
3479 	if (token_info && token_info->flags & CKF_USER_PIN_FINAL_TRY)
3480 		flags |= G_TLS_PASSWORD_FINAL_TRY;
3481 	g_tls_password_set_flags (password, flags);
3482 }
3483 
3484 CK_RV
_gck_session_authenticate_key(CK_FUNCTION_LIST_PTR funcs,CK_SESSION_HANDLE session,GckObject * key,GTlsInteraction * interaction,GCancellable * cancellable)3485 _gck_session_authenticate_key (CK_FUNCTION_LIST_PTR funcs,
3486                                CK_SESSION_HANDLE session,
3487                                GckObject *key,
3488                                GTlsInteraction *interaction,
3489                                GCancellable *cancellable)
3490 {
3491 	CK_ATTRIBUTE attrs[2];
3492 	CK_SESSION_INFO session_info;
3493 	CK_TOKEN_INFO token_info;
3494 	GTlsPassword *password = NULL;
3495 	CK_OBJECT_HANDLE handle;
3496 	GTlsInteractionResult res;
3497 	gboolean request_retry;
3498 	GError *error = NULL;
3499 	CK_BYTE_PTR pin;
3500 	gsize pin_len;
3501 	CK_BBOOL bvalue;
3502 	gboolean got_label;
3503 	CK_RV rv;
3504 
3505 	g_assert (funcs != NULL);
3506 
3507 	handle = gck_object_get_handle (key);
3508 
3509 	attrs[0].type = CKA_LABEL;
3510 	attrs[0].pValue = NULL;
3511 	attrs[0].ulValueLen = 0;
3512 	attrs[1].type = CKA_ALWAYS_AUTHENTICATE;
3513 	attrs[1].pValue = &bvalue;
3514 	attrs[1].ulValueLen = sizeof (bvalue);
3515 
3516 	rv = (funcs->C_GetAttributeValue) (session, handle, attrs, 2);
3517 	if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
3518 		bvalue = CK_FALSE;
3519 
3520 	} else if (rv != CKR_OK) {
3521 		g_message ("couldn't check whether key requires authentication, assuming it doesn't: %s",
3522 		           gck_message_from_rv (rv));
3523 		return CKR_OK;
3524 	}
3525 
3526 	/* No authentication needed, on this object */
3527 	if (bvalue != CK_TRUE) {
3528 		g_debug ("key does not require authentication");
3529 		return CKR_OK;
3530 	}
3531 
3532 	got_label = FALSE;
3533 	request_retry = FALSE;
3534 
3535 	do {
3536 		if (g_cancellable_is_cancelled (cancellable)) {
3537 			rv = CKR_FUNCTION_CANCELED;
3538 			break;
3539 		}
3540 
3541 		rv = (funcs->C_GetSessionInfo) (session, &session_info);
3542 		if (rv != CKR_OK) {
3543 			g_warning ("couldn't get session info when authenticating key: %s",
3544 			           gck_message_from_rv (rv));
3545 			return rv;
3546 		}
3547 
3548 		rv = (funcs->C_GetTokenInfo) (session_info.slotID, &token_info);
3549 		if (rv != CKR_OK) {
3550 			g_warning ("couldn't get token info when authenticating key: %s",
3551 			           gck_message_from_rv (rv));
3552 			return rv;
3553 		}
3554 
3555 		/* Protected authentication path, just use NULL passwords */
3556 		if (token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
3557 
3558 			password = NULL;
3559 			pin = NULL;
3560 			pin_len = 0;
3561 
3562 		/* Need to prompt for a password */
3563 		} else {
3564 			g_debug ("trying to log into session: want password %s",
3565 			         request_retry ? "login was incorrect" : "");
3566 
3567 			if (password == NULL)
3568 				password = g_object_new (GCK_TYPE_PASSWORD, "key", key, NULL);
3569 
3570 			/* Set the password */
3571 			update_password_for_key (password, &token_info, request_retry);
3572 
3573 			/* Set the label properly */
3574 			if (!got_label) {
3575 				if (attrs[0].ulValueLen && attrs[0].ulValueLen != GCK_INVALID) {
3576 					attrs[0].pValue = g_malloc0 (attrs[0].ulValueLen + 1);
3577 					rv = (funcs->C_GetAttributeValue) (session, handle, attrs, 1);
3578 					if (rv == CKR_OK) {
3579 						((gchar *)attrs[0].pValue)[attrs[0].ulValueLen] = 0;
3580 						g_tls_password_set_description (password, attrs[0].pValue);
3581 					}
3582 					g_free (attrs[0].pValue);
3583 					attrs[0].pValue = NULL;
3584 				}
3585 
3586 				got_label = TRUE;
3587 			}
3588 
3589 			if (interaction == NULL)
3590 				res = G_TLS_INTERACTION_UNHANDLED;
3591 
3592 			else
3593 				res = g_tls_interaction_invoke_ask_password (interaction,
3594 				                                             G_TLS_PASSWORD (password),
3595 				                                             NULL, &error);
3596 
3597 			if (res == G_TLS_INTERACTION_FAILED) {
3598 				g_message ("interaction couldn't ask password: %s", error->message);
3599 				rv = _gck_rv_from_error (error, CKR_USER_NOT_LOGGED_IN);
3600 				g_clear_error (&error);
3601 				break;
3602 
3603 			} else if (res == G_TLS_INTERACTION_UNHANDLED) {
3604 				g_message ("couldn't authenticate: no interaction handler");
3605 				rv = CKR_USER_NOT_LOGGED_IN;
3606 				break;
3607 			}
3608 
3609 			pin = (CK_BYTE_PTR)g_tls_password_get_value (G_TLS_PASSWORD (password), &pin_len);
3610 		}
3611 
3612 		/* Try to log in */
3613 		rv = (funcs->C_Login) (session, CKU_CONTEXT_SPECIFIC, pin, pin_len);
3614 
3615 		/* Only one C_Login call if protected auth path */
3616 		if (token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
3617 			break;
3618 
3619 		request_retry = TRUE;
3620 	} while (rv == CKR_PIN_INCORRECT);
3621 
3622 	g_clear_object (&password);
3623 
3624 	return rv;
3625 }
3626