Line data Source code
1 : /*
2 : * gnome-keyring
3 : *
4 : * Copyright (C) 2008 Stefan Walter
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see
18 : * <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "config.h"
22 :
23 : #include "pkcs11/pkcs11.h"
24 : #include "pkcs11/pkcs11i.h"
25 :
26 : #include "gkm-attributes.h"
27 : #include "gkm-credential.h"
28 : #include "gkm-crypto.h"
29 : #include "gkm-factory.h"
30 : #include "gkm-manager.h"
31 : #include "gkm-memory-store.h"
32 : #include "gkm-session.h"
33 : #include "gkm-sexp.h"
34 : #include "gkm-sexp-key.h"
35 : #include "gkm-transaction.h"
36 : #include "gkm-util.h"
37 :
38 : enum {
39 : PROP_0,
40 : PROP_MODULE,
41 : PROP_SLOT_ID,
42 : PROP_APARTMENT,
43 : PROP_HANDLE,
44 : PROP_FLAGS,
45 : PROP_MANAGER,
46 : PROP_LOGGED_IN
47 : };
48 :
49 : struct _GkmSessionPrivate {
50 :
51 : CK_SESSION_HANDLE handle;
52 : CK_SLOT_ID slot_id;
53 : CK_ULONG apartment;
54 :
55 : GkmModule *module;
56 : GkmManager *manager;
57 : GkmStore *store;
58 :
59 : CK_USER_TYPE logged_in;
60 : CK_ULONG flags;
61 :
62 : CK_NOTIFY notify_callback;
63 : CK_VOID_PTR application_ptr;
64 :
65 : /* Objects owned by this session */
66 : GHashTable *objects;
67 :
68 : /* Used for operations */
69 : void (*current_operation) (GkmSession *self);
70 : GkmObject *current_object;
71 : GkmCredential *credential;
72 :
73 : /* Used for find operations */
74 : GArray *found_objects;
75 :
76 : /* Used for crypto operations */
77 : gpointer crypto_state;
78 : GDestroyNotify crypto_destroy;
79 : CK_MECHANISM_TYPE crypto_mechanism;
80 : CK_ATTRIBUTE_TYPE crypto_method;
81 : };
82 :
83 15211 : G_DEFINE_TYPE_WITH_PRIVATE (GkmSession, gkm_session, G_TYPE_OBJECT);
84 :
85 : static void add_object (GkmSession *self, GkmTransaction *transaction, GkmObject *object);
86 : static void remove_object (GkmSession *self, GkmTransaction *transaction, GkmObject *object);
87 :
88 : /* -----------------------------------------------------------------------------
89 : * INTERNAL
90 : */
91 :
92 : static void
93 0 : cleanup_crypto (GkmSession *self)
94 : {
95 0 : g_assert (self->pv->current_operation == cleanup_crypto);
96 :
97 0 : if (self->pv->crypto_state && self->pv->crypto_destroy)
98 0 : (self->pv->crypto_destroy) (self->pv->crypto_state);
99 0 : self->pv->crypto_state = NULL;
100 0 : self->pv->crypto_destroy = NULL;
101 0 : self->pv->crypto_mechanism = 0;
102 0 : self->pv->crypto_method = 0;
103 :
104 0 : g_assert (GKM_IS_OBJECT (self->pv->current_object));
105 0 : if (self->pv->current_object)
106 0 : g_object_unref (self->pv->current_object);
107 0 : self->pv->current_object = NULL;
108 :
109 0 : if (self->pv->credential) {
110 0 : g_object_set_data (G_OBJECT (self->pv->credential), "owned-by-session", NULL);
111 0 : g_object_unref (self->pv->credential);
112 0 : self->pv->credential = NULL;
113 : }
114 :
115 0 : self->pv->current_operation = NULL;
116 0 : }
117 :
118 : static CK_RV
119 0 : prepare_crypto (GkmSession *self, CK_MECHANISM_PTR mech,
120 : CK_ATTRIBUTE_TYPE method, CK_OBJECT_HANDLE handle)
121 : {
122 : GkmObject *object;
123 : CK_MECHANISM_TYPE_PTR mechanisms;
124 : CK_ULONG n_mechanisms, i;
125 : gsize n_data;
126 : gboolean have;
127 : gulong key_type;
128 : CK_RV rv;
129 :
130 0 : g_assert (GKM_IS_SESSION (self));
131 :
132 : /* Cancel any current operation */
133 0 : if (self->pv->current_operation) {
134 0 : (self->pv->current_operation) (self);
135 0 : g_assert (!self->pv->current_operation);
136 : }
137 :
138 0 : g_assert (!self->pv->crypto_state);
139 :
140 : /* First find the object */
141 0 : rv = gkm_session_lookup_readable_object (self, handle, &object);
142 0 : if (rv != CKR_OK)
143 0 : return rv;
144 :
145 : /* Make sure it's a key */
146 0 : if (!gkm_object_get_attribute_ulong (object, self, CKA_KEY_TYPE, &key_type))
147 0 : return CKR_KEY_HANDLE_INVALID;
148 :
149 : /* Lookup the mechanisms this object can do */
150 0 : mechanisms = gkm_object_get_attribute_data (object, self, CKA_ALLOWED_MECHANISMS, &n_data);
151 0 : if (mechanisms)
152 0 : n_mechanisms = n_data / sizeof (CK_MECHANISM_TYPE);
153 : else
154 0 : n_mechanisms = 0;
155 :
156 : /* See if ours is represented */
157 0 : have = FALSE;
158 0 : for (i = 0; !have && i < n_mechanisms; ++i) {
159 0 : if (mechanisms[i] == mech->mechanism)
160 0 : have = TRUE;
161 : }
162 :
163 0 : g_free (mechanisms);
164 :
165 0 : if (have == FALSE)
166 0 : return CKR_KEY_TYPE_INCONSISTENT;
167 :
168 : /* Check that the object can do this method */
169 0 : if (!gkm_object_get_attribute_boolean (object, self, method, &have) || !have)
170 0 : return CKR_KEY_FUNCTION_NOT_PERMITTED;
171 :
172 : /* Track the cyrpto object */
173 0 : self->pv->current_object = object;
174 0 : g_object_ref (object);
175 :
176 : /* And note what we're setup for */
177 0 : self->pv->current_operation = cleanup_crypto;
178 0 : self->pv->crypto_mechanism = mech->mechanism;
179 0 : self->pv->crypto_method = method;
180 :
181 0 : return CKR_OK;
182 : }
183 :
184 : static CK_RV
185 0 : process_crypto (GkmSession *self, CK_ATTRIBUTE_TYPE method, CK_BYTE_PTR bufone,
186 : CK_ULONG n_bufone, CK_BYTE_PTR buftwo, CK_ULONG_PTR n_buftwo)
187 : {
188 0 : CK_RV rv = CKR_OK;
189 :
190 0 : g_assert (GKM_IS_SESSION (self));
191 :
192 0 : if (self->pv->current_operation != cleanup_crypto)
193 0 : return CKR_OPERATION_NOT_INITIALIZED;
194 0 : if (method != self->pv->crypto_method)
195 0 : return CKR_OPERATION_NOT_INITIALIZED;
196 :
197 0 : if (!bufone || !n_buftwo)
198 0 : rv = CKR_ARGUMENTS_BAD;
199 :
200 0 : if (rv == CKR_OK) {
201 : /* Load up the actual sexp we're going to use */
202 0 : if (!self->pv->crypto_state) {
203 0 : g_return_val_if_fail (GKM_IS_OBJECT (self->pv->current_object), CKR_GENERAL_ERROR);
204 0 : rv = gkm_crypto_prepare (self, self->pv->crypto_mechanism, self->pv->current_object);
205 : }
206 : }
207 :
208 0 : if (rv == CKR_OK) {
209 0 : g_assert (self->pv->crypto_mechanism);
210 0 : rv = gkm_crypto_perform (self, self->pv->crypto_mechanism, method,
211 : bufone, n_bufone, buftwo, n_buftwo);
212 : }
213 :
214 : /* Under these conditions the operation isn't complete */
215 0 : if (rv == CKR_BUFFER_TOO_SMALL || rv == CKR_USER_NOT_LOGGED_IN ||
216 0 : (rv == CKR_OK && buftwo == NULL))
217 0 : return rv;
218 :
219 0 : cleanup_crypto (self);
220 0 : return rv;
221 : }
222 :
223 : static void
224 206 : cleanup_found (GkmSession *self)
225 : {
226 206 : g_assert (GKM_IS_SESSION (self));
227 :
228 206 : g_assert (self->pv->found_objects);
229 206 : g_array_free (self->pv->found_objects, TRUE);
230 206 : self->pv->found_objects = NULL;
231 :
232 206 : self->pv->current_operation = NULL;
233 206 : }
234 :
235 : static CK_RV
236 2664 : lookup_object_from_handle (GkmSession *self, CK_OBJECT_HANDLE handle,
237 : gboolean writable, GkmObject **result)
238 : {
239 : GkmManager *manager;
240 : GkmObject *object;
241 : gboolean is_private;
242 : gboolean is_token;
243 :
244 2664 : g_return_val_if_fail (result, CKR_GENERAL_ERROR);
245 2664 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_GENERAL_ERROR);
246 :
247 2664 : if (handle == 0)
248 1 : return CKR_OBJECT_HANDLE_INVALID;
249 :
250 : /* Try looking up in the token manager */
251 2663 : manager = gkm_module_get_manager (self->pv->module);
252 2663 : object = gkm_manager_find_by_handle (manager, handle);
253 2663 : is_token = TRUE;
254 :
255 : /* Try looking up in the session manager */
256 2663 : if (object == NULL) {
257 2104 : manager = gkm_session_get_manager (self);
258 2104 : object = gkm_manager_find_by_handle (manager, handle);
259 2104 : is_token = FALSE;
260 : }
261 :
262 2663 : if (object == NULL)
263 22 : return CKR_OBJECT_HANDLE_INVALID;
264 :
265 2641 : g_return_val_if_fail (manager, CKR_GENERAL_ERROR);
266 :
267 : /*
268 : * Check that we're not accessing private objects on a
269 : * non-logged in session
270 : */
271 2641 : if (self->pv->logged_in != CKU_USER) {
272 5 : if (!gkm_object_get_attribute_boolean (object, self, CKA_PRIVATE, &is_private))
273 0 : is_private = FALSE;
274 5 : if (is_private)
275 0 : return CKR_USER_NOT_LOGGED_IN;
276 : }
277 :
278 : /*
279 : * If we're going to write to this object check that we're in a
280 : * writable session and object is modifiable.
281 : */
282 2641 : if (writable) {
283 22 : if (is_token) {
284 14 : if (!gkm_object_is_transient (object))
285 8 : if (gkm_module_get_write_protected (self->pv->module))
286 0 : return CKR_TOKEN_WRITE_PROTECTED;
287 14 : if (gkm_session_is_read_only (self))
288 0 : return CKR_SESSION_READ_ONLY;
289 : }
290 : }
291 :
292 2641 : *result = object;
293 2641 : return CKR_OK;
294 : }
295 :
296 :
297 : static gboolean
298 29 : complete_remove (GkmTransaction *transaction, GkmSession *self, GkmObject *object)
299 : {
300 29 : if (gkm_transaction_get_failed (transaction))
301 0 : add_object (self, NULL, object);
302 29 : g_object_unref (object);
303 29 : return TRUE;
304 : }
305 :
306 : static void
307 29 : remove_object (GkmSession *self, GkmTransaction *transaction, GkmObject *object)
308 : {
309 29 : g_assert (GKM_IS_SESSION (self));
310 29 : g_assert (GKM_IS_OBJECT (object));
311 :
312 29 : g_object_ref (object);
313 :
314 29 : gkm_object_expose_full (object, transaction, FALSE);
315 29 : g_hash_table_remove (self->pv->objects, object);
316 29 : g_object_set (object, "store", NULL, NULL);
317 :
318 29 : if (transaction)
319 29 : gkm_transaction_add (transaction, self, (GkmTransactionFunc)complete_remove,
320 : g_object_ref (object));
321 :
322 29 : g_object_unref (object);
323 29 : }
324 :
325 : static gboolean
326 145 : complete_add (GkmTransaction *transaction, GkmSession *self, GkmObject *object)
327 : {
328 145 : if (gkm_transaction_get_failed (transaction))
329 0 : remove_object (self, NULL, object);
330 145 : g_object_unref (object);
331 145 : return TRUE;
332 : }
333 :
334 : static void
335 158 : add_object (GkmSession *self, GkmTransaction *transaction, GkmObject *object)
336 : {
337 158 : g_assert (GKM_IS_SESSION (self));
338 158 : g_assert (GKM_IS_OBJECT (object));
339 :
340 : /* Must not already be associated with a session or manager */
341 158 : g_return_if_fail (gkm_object_get_manager (object) == self->pv->manager);
342 158 : g_return_if_fail (g_object_get_data (G_OBJECT (object), "owned-by-session") == NULL);
343 158 : g_return_if_fail (g_hash_table_lookup (self->pv->objects, object) == NULL);
344 :
345 158 : g_hash_table_insert (self->pv->objects, object, g_object_ref (object));
346 158 : g_object_set_data (G_OBJECT (object), "owned-by-session", self);
347 158 : g_object_set (object, "store", self->pv->store, NULL);
348 158 : gkm_object_expose_full (object, transaction, TRUE);
349 :
350 158 : if (transaction)
351 145 : gkm_transaction_add (transaction, self, (GkmTransactionFunc)complete_add,
352 : g_object_ref (object));
353 : }
354 :
355 : /* -----------------------------------------------------------------------------
356 : * OBJECT
357 : */
358 :
359 :
360 : static GObject*
361 215 : gkm_session_constructor (GType type, guint n_props, GObjectConstructParam *props)
362 : {
363 215 : GkmSession *self = GKM_SESSION (G_OBJECT_CLASS (gkm_session_parent_class)->constructor(type, n_props, props));
364 : CK_ATTRIBUTE attr;
365 :
366 215 : g_return_val_if_fail (self, NULL);
367 :
368 : /* Register store attributes */
369 215 : attr.type = CKA_LABEL;
370 215 : attr.pValue = "";
371 215 : attr.ulValueLen = 0;
372 215 : gkm_store_register_schema (self->pv->store, &attr, NULL, 0);
373 :
374 215 : return G_OBJECT (self);
375 : }
376 :
377 : static void
378 215 : gkm_session_init (GkmSession *self)
379 : {
380 215 : self->pv = gkm_session_get_instance_private (self);
381 215 : self->pv->objects = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, gkm_util_dispose_unref);
382 215 : self->pv->flags = 0;
383 :
384 : /* Create the store and register attributes */
385 215 : self->pv->store = GKM_STORE (gkm_memory_store_new ());
386 215 : }
387 :
388 : static void
389 215 : gkm_session_dispose (GObject *obj)
390 : {
391 215 : GkmSession *self = GKM_SESSION (obj);
392 :
393 : /* Cleanup any current operation */
394 215 : if (self->pv->current_operation)
395 0 : (self->pv->current_operation) (self);
396 215 : g_assert (!self->pv->current_operation);
397 :
398 215 : if (self->pv->module)
399 215 : g_object_unref (self->pv->module);
400 215 : self->pv->module = NULL;
401 :
402 215 : if (self->pv->credential) {
403 0 : g_object_set_data (G_OBJECT (self->pv->credential), "owned-by-session", NULL);
404 0 : g_object_unref (self->pv->credential);
405 0 : self->pv->credential = NULL;
406 : }
407 :
408 215 : g_hash_table_remove_all (self->pv->objects);
409 :
410 215 : if (self->pv->manager)
411 215 : g_object_unref (self->pv->manager);
412 215 : self->pv->manager = NULL;
413 :
414 215 : G_OBJECT_CLASS (gkm_session_parent_class)->dispose (obj);
415 215 : }
416 :
417 : static void
418 215 : gkm_session_finalize (GObject *obj)
419 : {
420 215 : GkmSession *self = GKM_SESSION (obj);
421 :
422 215 : g_assert (self->pv->module == NULL);
423 215 : g_assert (self->pv->manager == NULL);
424 :
425 215 : g_hash_table_destroy (self->pv->objects);
426 215 : self->pv->objects = NULL;
427 :
428 215 : g_object_unref (self->pv->store);
429 215 : self->pv->store = NULL;
430 :
431 215 : G_OBJECT_CLASS (gkm_session_parent_class)->finalize (obj);
432 215 : }
433 :
434 : static void
435 1505 : gkm_session_set_property (GObject *obj, guint prop_id, const GValue *value,
436 : GParamSpec *pspec)
437 : {
438 1505 : GkmSession *self = GKM_SESSION (obj);
439 :
440 1505 : switch (prop_id) {
441 215 : case PROP_MODULE:
442 215 : g_return_if_fail (!self->pv->module);
443 215 : self->pv->module = g_value_get_object (value);
444 215 : g_return_if_fail (self->pv->module);
445 215 : g_object_ref (self->pv->module);
446 215 : break;
447 215 : case PROP_MANAGER:
448 215 : g_return_if_fail (!self->pv->manager);
449 215 : self->pv->manager = g_value_get_object (value);
450 215 : g_return_if_fail (self->pv->manager);
451 215 : g_object_ref (self->pv->manager);
452 215 : break;
453 215 : case PROP_SLOT_ID:
454 215 : self->pv->slot_id = g_value_get_ulong (value);
455 215 : break;
456 215 : case PROP_APARTMENT:
457 215 : self->pv->apartment = g_value_get_ulong (value);
458 215 : break;
459 215 : case PROP_HANDLE:
460 215 : self->pv->handle = g_value_get_ulong (value);
461 215 : g_return_if_fail (self->pv->handle != 0);
462 215 : break;
463 215 : case PROP_FLAGS:
464 215 : self->pv->flags = g_value_get_ulong (value);
465 215 : break;
466 215 : case PROP_LOGGED_IN:
467 215 : gkm_session_set_logged_in (self, g_value_get_ulong (value));
468 215 : break;
469 0 : default:
470 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
471 0 : break;
472 : }
473 : }
474 :
475 : static void
476 0 : gkm_session_get_property (GObject *obj, guint prop_id, GValue *value,
477 : GParamSpec *pspec)
478 : {
479 0 : GkmSession *self = GKM_SESSION (obj);
480 :
481 0 : switch (prop_id) {
482 0 : case PROP_MODULE:
483 0 : g_value_set_object (value, gkm_session_get_module (self));
484 0 : break;
485 0 : case PROP_MANAGER:
486 0 : g_value_set_object (value, gkm_session_get_manager (self));
487 0 : break;
488 0 : case PROP_SLOT_ID:
489 0 : g_value_set_ulong (value, gkm_session_get_slot_id (self));
490 0 : break;
491 0 : case PROP_APARTMENT:
492 0 : g_value_set_ulong (value, gkm_session_get_apartment (self));
493 0 : break;
494 0 : case PROP_HANDLE:
495 0 : g_value_set_ulong (value, gkm_session_get_handle (self));
496 0 : break;
497 0 : case PROP_FLAGS:
498 0 : g_value_set_ulong (value, self->pv->flags);
499 0 : break;
500 0 : case PROP_LOGGED_IN:
501 0 : g_value_set_ulong (value, gkm_session_get_logged_in (self));
502 0 : break;
503 0 : default:
504 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
505 0 : break;
506 : }
507 0 : }
508 :
509 : static void
510 41 : gkm_session_class_init (GkmSessionClass *klass)
511 : {
512 41 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
513 :
514 41 : gobject_class->constructor = gkm_session_constructor;
515 41 : gobject_class->dispose = gkm_session_dispose;
516 41 : gobject_class->finalize = gkm_session_finalize;
517 41 : gobject_class->set_property = gkm_session_set_property;
518 41 : gobject_class->get_property = gkm_session_get_property;
519 :
520 41 : g_object_class_install_property (gobject_class, PROP_MODULE,
521 : g_param_spec_object ("module", "Module", "Module this session belongs to",
522 : GKM_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
523 :
524 41 : g_object_class_install_property (gobject_class, PROP_MANAGER,
525 : g_param_spec_object ("manager", "Manager", "Object manager for this session",
526 : GKM_TYPE_MANAGER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
527 :
528 41 : g_object_class_install_property (gobject_class, PROP_HANDLE,
529 : g_param_spec_ulong ("handle", "Handle", "PKCS#11 session handle",
530 : 0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
531 :
532 41 : g_object_class_install_property (gobject_class, PROP_SLOT_ID,
533 : g_param_spec_ulong ("slot-id", "Slot ID", "Slot ID this session is opened on",
534 : 0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
535 :
536 41 : g_object_class_install_property (gobject_class, PROP_APARTMENT,
537 : g_param_spec_ulong ("apartment", "Apartment", "Apartment this session is opened on",
538 : 0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
539 :
540 41 : g_object_class_install_property(gobject_class, PROP_FLAGS,
541 : g_param_spec_ulong ("flags", "Flags", "Flags for the session",
542 : 0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
543 :
544 41 : g_object_class_install_property (gobject_class, PROP_LOGGED_IN,
545 : g_param_spec_ulong ("logged-in", "Logged in", "Whether this session is logged in or not",
546 : 0, G_MAXULONG, CKU_NONE, G_PARAM_READWRITE));
547 41 : }
548 :
549 : /* -----------------------------------------------------------------------------
550 : * PUBLIC
551 : */
552 :
553 : GkmSession*
554 89 : gkm_session_for_session_object (GkmObject *obj)
555 : {
556 89 : g_return_val_if_fail (GKM_IS_OBJECT (obj), NULL);
557 89 : return GKM_SESSION (g_object_get_data (G_OBJECT (obj), "owned-by-session"));
558 : }
559 :
560 : CK_SESSION_HANDLE
561 43 : gkm_session_get_handle (GkmSession *self)
562 : {
563 43 : g_return_val_if_fail (GKM_IS_SESSION (self), 0);
564 43 : return self->pv->handle;
565 : }
566 :
567 : CK_SLOT_ID
568 0 : gkm_session_get_slot_id (GkmSession *self)
569 : {
570 0 : g_return_val_if_fail (GKM_IS_SESSION (self), 0);
571 0 : return self->pv->slot_id;
572 : }
573 :
574 : CK_ULONG
575 405 : gkm_session_get_apartment (GkmSession *self)
576 : {
577 405 : g_return_val_if_fail (GKM_IS_SESSION (self), 0);
578 405 : return self->pv->apartment;
579 : }
580 :
581 : GkmModule*
582 546 : gkm_session_get_module (GkmSession *self)
583 : {
584 546 : g_return_val_if_fail (GKM_IS_SESSION (self), NULL);
585 546 : g_return_val_if_fail (GKM_IS_MODULE (self->pv->module), NULL);
586 546 : return self->pv->module;
587 : }
588 :
589 : GkmManager*
590 2628 : gkm_session_get_manager (GkmSession *self)
591 : {
592 2628 : g_return_val_if_fail (GKM_IS_SESSION (self), NULL);
593 2628 : g_return_val_if_fail (GKM_IS_MANAGER (self->pv->manager), NULL);
594 2628 : return self->pv->manager;
595 : }
596 :
597 : gulong
598 551 : gkm_session_get_logged_in (GkmSession *self)
599 : {
600 551 : g_return_val_if_fail (GKM_IS_SESSION (self), FALSE);
601 551 : return self->pv->logged_in;
602 : }
603 :
604 : void
605 398 : gkm_session_set_logged_in (GkmSession *self, gulong logged_in)
606 : {
607 398 : g_return_if_fail (GKM_IS_SESSION (self));
608 398 : self->pv->logged_in = logged_in;
609 398 : g_object_notify (G_OBJECT (self), "logged-in");
610 : }
611 :
612 : gpointer
613 0 : gkm_session_get_crypto_state (GkmSession *self)
614 : {
615 0 : g_return_val_if_fail (GKM_IS_SESSION (self), NULL);
616 0 : return self->pv->crypto_state;
617 : }
618 :
619 : void
620 0 : gkm_session_set_crypto_state (GkmSession *self, gpointer state,
621 : GDestroyNotify destroy)
622 : {
623 0 : g_return_if_fail (GKM_IS_SESSION (self));
624 0 : if (self->pv->crypto_state != state) {
625 0 : if (self->pv->crypto_state && self->pv->crypto_destroy)
626 0 : (self->pv->crypto_destroy) (self->pv->crypto_state);
627 : }
628 0 : self->pv->crypto_state = state;
629 0 : self->pv->crypto_destroy = destroy;
630 : }
631 :
632 : gboolean
633 129 : gkm_session_is_read_only (GkmSession *self)
634 : {
635 129 : g_return_val_if_fail (GKM_IS_SESSION (self), TRUE);
636 129 : return (self->pv->flags & CKF_RW_SESSION) ? FALSE : TRUE;
637 : }
638 :
639 : gboolean
640 2 : gkm_session_is_for_application (GkmSession *self)
641 : {
642 2 : g_return_val_if_fail (GKM_IS_SESSION (self), TRUE);
643 2 : return (self->pv->flags & CKF_G_APPLICATION_SESSION) ? TRUE : FALSE;
644 : }
645 :
646 : CK_RV
647 2640 : gkm_session_lookup_readable_object (GkmSession *self, CK_OBJECT_HANDLE handle,
648 : GkmObject **result)
649 : {
650 2640 : return lookup_object_from_handle (self, handle, FALSE, result);
651 : }
652 :
653 : CK_RV
654 24 : gkm_session_lookup_writable_object (GkmSession *self, CK_OBJECT_HANDLE handle,
655 : GkmObject **result)
656 : {
657 24 : return lookup_object_from_handle (self, handle, TRUE, result);
658 : }
659 :
660 : CK_RV
661 0 : gkm_session_login_context_specific (GkmSession *self, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
662 : {
663 : GkmCredential *cred;
664 : gboolean always_auth;
665 : gboolean is_private;
666 : GkmObject *object;
667 : CK_RV rv;
668 :
669 0 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_GENERAL_ERROR);
670 :
671 0 : if (!self->pv->current_object)
672 0 : return CKR_OPERATION_NOT_INITIALIZED;
673 :
674 0 : object = self->pv->current_object;
675 0 : g_return_val_if_fail (GKM_IS_OBJECT (object), CKR_GENERAL_ERROR);
676 :
677 0 : if (!gkm_object_get_attribute_boolean (object, self, CKA_ALWAYS_AUTHENTICATE, &always_auth))
678 0 : always_auth = FALSE;
679 0 : if (!gkm_object_get_attribute_boolean (object, self, CKA_PRIVATE, &is_private))
680 0 : is_private = FALSE;
681 :
682 : /* A strange code, but that's what the spec says */
683 0 : if (always_auth == FALSE)
684 0 : return CKR_OPERATION_NOT_INITIALIZED;
685 :
686 : /* Double check that the object has what it takes */
687 0 : g_return_val_if_fail (is_private == TRUE, CKR_GENERAL_ERROR);
688 :
689 : /* Now create the strange object */
690 0 : rv = gkm_credential_create (self->pv->module, self->pv->manager,
691 0 : self->pv->current_object, pin, n_pin, &cred);
692 0 : if (rv != CKR_OK)
693 0 : return rv;
694 :
695 0 : if (self->pv->credential)
696 0 : g_object_unref (self->pv->credential);
697 0 : g_object_set_data (G_OBJECT (cred), "owned-by-session", self);
698 0 : self->pv->credential = cred;
699 :
700 0 : return CKR_OK;
701 : }
702 :
703 : void
704 13 : gkm_session_add_session_object (GkmSession *self, GkmTransaction *transaction,
705 : GkmObject *obj)
706 : {
707 13 : g_return_if_fail (GKM_IS_SESSION (self));
708 13 : g_return_if_fail (gkm_session_for_session_object (obj) == NULL);
709 :
710 13 : if (transaction) {
711 0 : g_return_if_fail (GKM_IS_TRANSACTION (transaction));
712 0 : g_return_if_fail (!gkm_transaction_get_failed (transaction));
713 : }
714 :
715 13 : add_object (self, transaction, obj);
716 : }
717 :
718 : void
719 21 : gkm_session_destroy_session_object (GkmSession *self, GkmTransaction *transaction,
720 : GkmObject *obj)
721 : {
722 21 : g_return_if_fail (GKM_IS_SESSION (self));
723 21 : g_return_if_fail (gkm_session_for_session_object (obj) == self);
724 :
725 21 : if (transaction) {
726 21 : g_return_if_fail (GKM_IS_TRANSACTION (transaction));
727 21 : g_return_if_fail (!gkm_transaction_get_failed (transaction));
728 : }
729 :
730 : /* Don't actually destroy the credential */
731 21 : if (self->pv->credential && GKM_OBJECT (self->pv->credential) == obj)
732 0 : return;
733 :
734 21 : remove_object (self, transaction, obj);
735 : }
736 :
737 : GkmCredential*
738 183 : gkm_session_get_credential (GkmSession *self)
739 : {
740 183 : g_return_val_if_fail (GKM_IS_SESSION (self), NULL);
741 183 : return self->pv->credential;
742 : }
743 :
744 : GkmObject*
745 183 : gkm_session_create_object_for_factory (GkmSession *self, GkmFactory *factory,
746 : GkmTransaction *transaction,
747 : CK_ATTRIBUTE_PTR template, CK_ULONG count)
748 : {
749 183 : GkmTransaction *owned = NULL;
750 : GkmObject *object;
751 : gboolean token;
752 :
753 183 : g_return_val_if_fail (GKM_IS_SESSION (self), NULL);
754 183 : g_return_val_if_fail (factory && factory->func, NULL);
755 183 : g_return_val_if_fail (template || !count, NULL);
756 :
757 : /* The transaction for this whole dealio */
758 183 : if (!transaction)
759 65 : owned = transaction = gkm_transaction_new ();
760 :
761 183 : g_return_val_if_fail (GKM_IS_TRANSACTION (transaction), NULL);
762 :
763 : /* Refresh the module if storing on the token */
764 183 : if (gkm_attributes_find_boolean (template, count, CKA_TOKEN, &token) && token)
765 42 : gkm_module_refresh_token (self->pv->module);
766 :
767 : /*
768 : * Duplicate the memory for the attributes (but not values) so we
769 : * can 'consume' in the factory function
770 : */
771 183 : template = g_memdup (template, count * sizeof (CK_ATTRIBUTE));
772 :
773 : /* Actually create the object */
774 183 : object = (factory->func) (self, transaction, template, count);
775 :
776 : /* A NULL result without a failure code, bad */
777 183 : if (object == NULL && !gkm_transaction_get_failed (transaction)) {
778 0 : g_warn_if_reached ();
779 0 : gkm_transaction_fail (transaction, CKR_GENERAL_ERROR);
780 : }
781 :
782 183 : g_free (template);
783 :
784 183 : if (owned)
785 65 : gkm_transaction_complete (transaction);
786 :
787 : /* Object is owned by module or session */
788 183 : if (gkm_transaction_get_failed (transaction)) {
789 17 : if (object)
790 3 : g_object_unref (object);
791 17 : object = NULL;
792 : }
793 :
794 183 : if (owned)
795 65 : g_object_unref (owned);
796 :
797 183 : return object;
798 : }
799 :
800 : GkmObject*
801 115 : gkm_session_create_object_for_attributes (GkmSession *self, GkmTransaction *transaction,
802 : CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
803 : {
804 : GkmFactory *factory;
805 :
806 115 : g_return_val_if_fail (GKM_IS_SESSION (self), NULL);
807 :
808 : /* Find out if we can create such an object */
809 115 : factory = gkm_module_find_factory (gkm_session_get_module (self), attrs, n_attrs);
810 115 : if (factory == NULL) {
811 0 : if (transaction)
812 0 : gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
813 0 : return NULL;
814 : }
815 :
816 115 : return gkm_session_create_object_for_factory (self, factory, transaction, attrs, n_attrs);
817 : }
818 :
819 : void
820 193 : gkm_session_complete_object_creation (GkmSession *self, GkmTransaction *transaction, GkmObject *object,
821 : gboolean add, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
822 : {
823 : gboolean is_private;
824 : gulong i;
825 :
826 195 : g_return_if_fail (GKM_IS_SESSION (self));
827 193 : g_return_if_fail (GKM_IS_OBJECT (object));
828 193 : g_return_if_fail (GKM_IS_TRANSACTION (transaction));
829 193 : g_return_if_fail (!gkm_transaction_get_failed (transaction));
830 :
831 193 : gkm_object_create_attributes (object, self, transaction, attrs, n_attrs);
832 193 : if (gkm_transaction_get_failed (transaction))
833 2 : return;
834 :
835 : /* See if we can create due to read-only */
836 191 : if (gkm_object_is_token (object)) {
837 69 : if (!gkm_object_is_transient (object) &&
838 23 : gkm_module_get_write_protected (self->pv->module)) {
839 0 : gkm_transaction_fail (transaction, CKR_TOKEN_WRITE_PROTECTED);
840 0 : return;
841 : }
842 46 : else if (gkm_session_is_read_only (self)) {
843 0 : gkm_transaction_fail (transaction, CKR_SESSION_READ_ONLY);
844 0 : return;
845 : }
846 : }
847 :
848 : /* Can only create public objects unless logged in */
849 196 : if (gkm_session_get_logged_in (self) != CKU_USER &&
850 5 : gkm_object_get_attribute_boolean (object, self, CKA_PRIVATE, &is_private) &&
851 5 : is_private == TRUE) {
852 0 : gkm_transaction_fail (transaction, CKR_USER_NOT_LOGGED_IN);
853 0 : return;
854 : }
855 :
856 : /* Add the object to session or token */
857 191 : if (add && !gkm_transaction_get_failed (transaction)) {
858 189 : if (gkm_object_is_token (object))
859 44 : gkm_module_add_token_object (self->pv->module, transaction, object);
860 : else
861 145 : add_object (self, transaction, object);
862 : }
863 :
864 : /* Next go through and set all attributes that weren't used initially */
865 191 : gkm_attributes_consume (attrs, n_attrs, CKA_TOKEN, G_MAXULONG);
866 859 : for (i = 0; i < n_attrs && !gkm_transaction_get_failed (transaction); ++i) {
867 668 : if (!gkm_attribute_consumed (&attrs[i]))
868 257 : gkm_object_set_attribute (object, self, transaction, &attrs[i]);
869 : }
870 :
871 : /* Store the object */
872 191 : if (!gkm_transaction_get_failed (transaction)) {
873 190 : if (gkm_object_is_token (object))
874 45 : gkm_module_store_token_object (self->pv->module, transaction, object);
875 : }
876 : }
877 :
878 : /* -----------------------------------------------------------------------------
879 : * PKCS#11
880 : */
881 :
882 : CK_RV
883 0 : gkm_session_C_GetFunctionStatus (GkmSession *self)
884 : {
885 0 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
886 0 : return CKR_FUNCTION_NOT_PARALLEL;
887 : }
888 :
889 : CK_RV
890 0 : gkm_session_C_CancelFunction (GkmSession *self)
891 : {
892 0 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
893 0 : return CKR_FUNCTION_NOT_PARALLEL;
894 : }
895 :
896 : CK_RV
897 65 : gkm_session_C_GetSessionInfo(GkmSession* self, CK_SESSION_INFO_PTR info)
898 : {
899 65 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
900 65 : if (!info)
901 0 : return CKR_ARGUMENTS_BAD;
902 :
903 65 : info->slotID = self->pv->slot_id;
904 65 : if (self->pv->logged_in == CKU_USER)
905 12 : info->state = gkm_session_is_read_only (self) ? CKS_RO_USER_FUNCTIONS : CKS_RW_USER_FUNCTIONS;
906 53 : else if (self->pv->logged_in == CKU_SO)
907 0 : info->state = CKS_RW_SO_FUNCTIONS;
908 : else
909 53 : info->state = gkm_session_is_read_only (self) ? CKS_RO_PUBLIC_SESSION : CKS_RW_PUBLIC_SESSION;
910 65 : info->flags = CKF_SERIAL_SESSION | self->pv->flags;
911 65 : info->ulDeviceError = 0;
912 :
913 65 : return CKR_OK;
914 : }
915 :
916 : CK_RV
917 0 : gkm_session_C_GetOperationState (GkmSession* self, CK_BYTE_PTR operation_state,
918 : CK_ULONG_PTR operation_state_len)
919 : {
920 : /* Nope, We don't bend that way */
921 0 : return CKR_FUNCTION_NOT_SUPPORTED;
922 : }
923 :
924 : CK_RV
925 0 : gkm_session_C_SetOperationState (GkmSession* self, CK_BYTE_PTR operation_state,
926 : CK_ULONG operation_state_len, CK_OBJECT_HANDLE encryption_key,
927 : CK_OBJECT_HANDLE authentication_key)
928 : {
929 : /* Nope. We don't bend that way */
930 0 : return CKR_FUNCTION_NOT_SUPPORTED;
931 : }
932 :
933 : CK_RV
934 92 : gkm_session_C_CreateObject (GkmSession* self, CK_ATTRIBUTE_PTR template,
935 : CK_ULONG count, CK_OBJECT_HANDLE_PTR new_object)
936 : {
937 92 : GkmObject *object = NULL;
938 : CK_OBJECT_HANDLE handle;
939 : GkmTransaction *transaction;
940 : CK_RV rv;
941 :
942 92 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
943 92 : if (!new_object)
944 0 : return CKR_ARGUMENTS_BAD;
945 92 : if (!(!count || template))
946 0 : return CKR_ARGUMENTS_BAD;
947 :
948 92 : transaction = gkm_transaction_new ();
949 :
950 92 : object = gkm_session_create_object_for_attributes (self, transaction, template, count);
951 :
952 92 : rv = gkm_transaction_complete_and_unref (transaction);
953 :
954 92 : if (rv == CKR_OK) {
955 77 : g_assert (object);
956 77 : handle = gkm_object_get_handle (object);
957 77 : if (handle == 0) {
958 0 : g_warning ("an object was not properly exposed its owner");
959 0 : rv = CKR_GENERAL_ERROR;
960 : } else {
961 77 : *new_object = handle;
962 : }
963 77 : g_object_unref (object);
964 : }
965 :
966 92 : return rv;
967 : }
968 :
969 : CK_RV
970 0 : gkm_session_C_CopyObject (GkmSession* self, CK_OBJECT_HANDLE object,
971 : CK_ATTRIBUTE_PTR template, CK_ULONG count,
972 : CK_OBJECT_HANDLE_PTR new_object)
973 : {
974 : /*
975 : * TODO: We need to implement this, initially perhaps only
976 : * only for session objects.
977 : */
978 0 : return CKR_FUNCTION_NOT_SUPPORTED;
979 : }
980 :
981 : CK_RV
982 0 : gkm_session_C_GetObjectSize (GkmSession* self, CK_OBJECT_HANDLE object, CK_ULONG_PTR size)
983 : {
984 : /* TODO: Do we need to implement this? */
985 0 : return CKR_FUNCTION_NOT_SUPPORTED;
986 : }
987 :
988 : CK_RV
989 565 : gkm_session_C_GetAttributeValue (GkmSession* self, CK_OBJECT_HANDLE handle,
990 : CK_ATTRIBUTE_PTR template, CK_ULONG count)
991 : {
992 : GkmObject *object;
993 : CK_ULONG i;
994 : CK_RV code, rv;
995 :
996 565 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
997 565 : if (!(!count || template))
998 0 : return CKR_ARGUMENTS_BAD;
999 :
1000 565 : rv = gkm_session_lookup_readable_object (self, handle, &object);
1001 565 : if (rv != CKR_OK)
1002 2 : return rv;
1003 :
1004 563 : rv = CKR_OK;
1005 :
1006 1171 : for (i = 0; i < count; ++i) {
1007 608 : code = gkm_object_get_attribute (object, self, &template[i]);
1008 :
1009 : /* Not a true error, keep going */
1010 608 : if (code == CKR_ATTRIBUTE_SENSITIVE ||
1011 : code == CKR_ATTRIBUTE_TYPE_INVALID) {
1012 19 : template[i].ulValueLen = (CK_ULONG)-1;
1013 19 : rv = code;
1014 :
1015 589 : } else if(code == CKR_BUFFER_TOO_SMALL) {
1016 0 : rv = code;
1017 :
1018 : /* Any other error aborts */
1019 589 : } else if (code != CKR_OK) {
1020 0 : rv = code;
1021 0 : break;
1022 : }
1023 : }
1024 :
1025 563 : return rv;
1026 : }
1027 :
1028 : CK_RV
1029 4 : gkm_session_C_SetAttributeValue (GkmSession* self, CK_OBJECT_HANDLE handle,
1030 : CK_ATTRIBUTE_PTR template, CK_ULONG count)
1031 : {
1032 4 : GkmObject *object = NULL;
1033 : GkmTransaction *transaction;
1034 : CK_ULONG i;
1035 : CK_RV rv;
1036 :
1037 4 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1038 4 : if (!(!count || template))
1039 0 : return CKR_ARGUMENTS_BAD;
1040 :
1041 4 : rv = gkm_session_lookup_writable_object (self, handle, &object);
1042 4 : if (rv != CKR_OK)
1043 0 : return rv;
1044 :
1045 : /* The transaction for this whole dealio */
1046 4 : transaction = gkm_transaction_new ();
1047 :
1048 8 : for (i = 0; i < count && !gkm_transaction_get_failed (transaction); ++i)
1049 4 : gkm_object_set_attribute (object, self, transaction, &template[i]);
1050 :
1051 : /* Store the object */
1052 4 : if (!gkm_transaction_get_failed (transaction) && gkm_object_is_token (object))
1053 4 : gkm_module_store_token_object (self->pv->module, transaction, object);
1054 :
1055 4 : gkm_transaction_complete (transaction);
1056 4 : rv = gkm_transaction_get_result (transaction);
1057 4 : g_object_unref (transaction);
1058 :
1059 4 : return rv;
1060 : }
1061 :
1062 : CK_RV
1063 20 : gkm_session_C_DestroyObject (GkmSession* self, CK_OBJECT_HANDLE handle)
1064 : {
1065 : GkmObject *object;
1066 : GkmSession *session;
1067 : GkmTransaction *transaction;
1068 : CK_RV rv;
1069 :
1070 20 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1071 :
1072 20 : rv = gkm_session_lookup_writable_object (self, handle, &object);
1073 20 : if (rv != CKR_OK)
1074 2 : return rv;
1075 :
1076 18 : transaction = gkm_transaction_new ();
1077 :
1078 : /* Lookup the actual session that owns this object, if no session, then a token object */
1079 18 : session = gkm_session_for_session_object (object);
1080 18 : if (session != NULL)
1081 8 : remove_object (session, transaction, object);
1082 : else
1083 10 : gkm_module_remove_token_object (self->pv->module, transaction, object);
1084 :
1085 18 : gkm_transaction_complete (transaction);
1086 18 : rv = gkm_transaction_get_result (transaction);
1087 18 : g_object_unref (transaction);
1088 :
1089 18 : if (rv == CKR_OK) {
1090 : /* Check that it's really gone */
1091 18 : g_return_val_if_fail (gkm_session_lookup_readable_object (self, handle, &object) ==
1092 : CKR_OBJECT_HANDLE_INVALID, CKR_GENERAL_ERROR);
1093 : }
1094 :
1095 18 : return rv;
1096 : }
1097 :
1098 : CK_RV
1099 206 : gkm_session_C_FindObjectsInit (GkmSession* self, CK_ATTRIBUTE_PTR template,
1100 : CK_ULONG count)
1101 : {
1102 206 : gboolean token = FALSE;
1103 : gboolean also_private;
1104 206 : CK_RV rv = CKR_OK;
1105 : GArray *found;
1106 : gboolean all;
1107 :
1108 206 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1109 206 : if (!(template || !count))
1110 0 : return CKR_ARGUMENTS_BAD;
1111 :
1112 : /* Cancel any current operation */
1113 206 : if (self->pv->current_operation) {
1114 0 : (self->pv->current_operation) (self);
1115 0 : g_assert (!self->pv->current_operation);
1116 : }
1117 :
1118 : /* See whether this is token or not */
1119 206 : all = !gkm_attributes_find_boolean (template, count, CKA_TOKEN, &token);
1120 :
1121 : /* An array of object handles */
1122 206 : found = g_array_new (FALSE, TRUE, sizeof (CK_OBJECT_HANDLE));
1123 :
1124 : /* If not logged in, then skip private objects */
1125 206 : also_private = gkm_session_get_logged_in (self) == CKU_USER;
1126 :
1127 206 : if (all || token) {
1128 182 : rv = gkm_module_refresh_token (self->pv->module);
1129 182 : if (rv == CKR_OK)
1130 182 : rv = gkm_manager_find_handles (gkm_module_get_manager (self->pv->module),
1131 : self, also_private, template, count, found);
1132 : }
1133 :
1134 206 : if (rv == CKR_OK && (all || !token)) {
1135 184 : rv = gkm_manager_find_handles (self->pv->manager, self, also_private,
1136 : template, count, found);
1137 : }
1138 :
1139 206 : if (rv != CKR_OK) {
1140 0 : g_array_free (found, TRUE);
1141 0 : return rv;
1142 : }
1143 :
1144 206 : g_assert (!self->pv->current_operation);
1145 206 : g_assert (!self->pv->found_objects);
1146 :
1147 206 : self->pv->found_objects = found;
1148 206 : self->pv->current_operation = cleanup_found;
1149 :
1150 206 : return CKR_OK;
1151 : }
1152 :
1153 : CK_RV
1154 326 : gkm_session_C_FindObjects (GkmSession* self, CK_OBJECT_HANDLE_PTR objects,
1155 : CK_ULONG max_count, CK_ULONG_PTR count)
1156 : {
1157 : CK_ULONG n_objects, i;
1158 : GArray *found;
1159 :
1160 326 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1161 326 : if (!(objects || !max_count))
1162 0 : return CKR_ARGUMENTS_BAD;
1163 326 : if (!count)
1164 0 : return CKR_ARGUMENTS_BAD;
1165 :
1166 326 : if (self->pv->current_operation != cleanup_found)
1167 0 : return CKR_OPERATION_NOT_INITIALIZED;
1168 :
1169 326 : g_assert (self->pv->found_objects);
1170 326 : found = self->pv->found_objects;
1171 :
1172 326 : n_objects = MIN (max_count, found->len);
1173 326 : if (n_objects > 0) {
1174 353 : for (i = 0; i < n_objects; ++i)
1175 195 : objects[i] = g_array_index (found, CK_OBJECT_HANDLE, i);
1176 158 : g_array_remove_range (found, 0, n_objects);
1177 : }
1178 :
1179 326 : *count = n_objects;
1180 326 : return CKR_OK;
1181 :
1182 : }
1183 :
1184 : CK_RV
1185 206 : gkm_session_C_FindObjectsFinal (GkmSession* self)
1186 : {
1187 206 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1188 :
1189 206 : if (self->pv->current_operation != cleanup_found)
1190 0 : return CKR_OPERATION_NOT_INITIALIZED;
1191 :
1192 206 : cleanup_found (self);
1193 206 : return CKR_OK;
1194 : }
1195 :
1196 : CK_RV
1197 0 : gkm_session_C_EncryptInit (GkmSession *self, CK_MECHANISM_PTR mechanism,
1198 : CK_OBJECT_HANDLE key)
1199 : {
1200 0 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1201 0 : if (!mechanism)
1202 0 : return CKR_ARGUMENTS_BAD;
1203 0 : return prepare_crypto (self, mechanism, CKA_ENCRYPT, key);
1204 : }
1205 :
1206 : CK_RV
1207 0 : gkm_session_C_Encrypt (GkmSession *self, CK_BYTE_PTR data, CK_ULONG data_len,
1208 : CK_BYTE_PTR encrypted_data, CK_ULONG_PTR encrypted_data_len)
1209 : {
1210 0 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1211 0 : return process_crypto (self, CKA_ENCRYPT, data, data_len, encrypted_data, encrypted_data_len);
1212 : }
1213 :
1214 : CK_RV
1215 0 : gkm_session_C_EncryptUpdate (GkmSession *self, CK_BYTE_PTR part,
1216 : CK_ULONG part_len, CK_BYTE_PTR encrypted_part,
1217 : CK_ULONG_PTR encrypted_part_len)
1218 : {
1219 : /* Our keys don't support this incremental encryption */
1220 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1221 : }
1222 :
1223 : CK_RV
1224 0 : gkm_session_C_EncryptFinal (GkmSession *self, CK_BYTE_PTR last_part,
1225 : CK_ULONG_PTR last_part_len)
1226 : {
1227 : /* Our keys don't support this incremental encryption */
1228 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1229 : }
1230 :
1231 : CK_RV
1232 0 : gkm_session_C_DecryptInit (GkmSession *self, CK_MECHANISM_PTR mechanism,
1233 : CK_OBJECT_HANDLE key)
1234 : {
1235 0 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1236 0 : if (!mechanism)
1237 0 : return CKR_ARGUMENTS_BAD;
1238 0 : return prepare_crypto (self, mechanism, CKA_DECRYPT, key);
1239 : }
1240 :
1241 : CK_RV
1242 0 : gkm_session_C_Decrypt (GkmSession *self, CK_BYTE_PTR enc_data,
1243 : CK_ULONG enc_data_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len)
1244 : {
1245 0 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1246 0 : return process_crypto (self, CKA_DECRYPT, enc_data, enc_data_len, data, data_len);
1247 : }
1248 :
1249 : CK_RV
1250 0 : gkm_session_C_DecryptUpdate (GkmSession *self, CK_BYTE_PTR enc_part,
1251 : CK_ULONG enc_part_len, CK_BYTE_PTR part, CK_ULONG_PTR part_len)
1252 : {
1253 : /* Our keys don't support this incremental decryption */
1254 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1255 : }
1256 :
1257 : CK_RV
1258 0 : gkm_session_C_DecryptFinal (GkmSession *self, CK_BYTE_PTR last_part,
1259 : CK_ULONG_PTR last_part_len)
1260 : {
1261 : /* Our keys don't support this incremental decryption */
1262 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1263 : }
1264 :
1265 : CK_RV
1266 0 : gkm_session_C_DigestInit (GkmSession *self, CK_MECHANISM_PTR mechanism)
1267 : {
1268 : /* We don't do digests */
1269 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1270 : }
1271 :
1272 : CK_RV
1273 0 : gkm_session_C_Digest (GkmSession *self, CK_BYTE_PTR data, CK_ULONG data_len,
1274 : CK_BYTE_PTR digest, CK_ULONG_PTR digest_len)
1275 : {
1276 : /* We don't do digests */
1277 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1278 : }
1279 :
1280 : CK_RV
1281 0 : gkm_session_C_DigestUpdate (GkmSession *self, CK_BYTE_PTR part, CK_ULONG part_len)
1282 : {
1283 : /* We don't do digests */
1284 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1285 : }
1286 :
1287 : CK_RV
1288 0 : gkm_session_C_DigestKey (GkmSession *self, CK_OBJECT_HANDLE key)
1289 : {
1290 : /* We don't do digests */
1291 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1292 : }
1293 :
1294 : CK_RV
1295 0 : gkm_session_C_DigestFinal (GkmSession *self, CK_BYTE_PTR digest,
1296 : CK_ULONG_PTR digest_len)
1297 : {
1298 : /* We don't do digests */
1299 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1300 : }
1301 :
1302 : CK_RV
1303 0 : gkm_session_C_SignInit (GkmSession *self, CK_MECHANISM_PTR mechanism,
1304 : CK_OBJECT_HANDLE key)
1305 : {
1306 0 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1307 0 : if (!mechanism)
1308 0 : return CKR_ARGUMENTS_BAD;
1309 0 : return prepare_crypto (self, mechanism, CKA_SIGN, key);
1310 : }
1311 :
1312 : CK_RV
1313 0 : gkm_session_C_Sign (GkmSession *self, CK_BYTE_PTR data, CK_ULONG data_len,
1314 : CK_BYTE_PTR signature, CK_ULONG_PTR signature_len)
1315 : {
1316 0 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1317 0 : return process_crypto (self, CKA_SIGN, data, data_len, signature, signature_len);
1318 : }
1319 :
1320 : CK_RV
1321 0 : gkm_session_C_SignUpdate (GkmSession *self, CK_BYTE_PTR part, CK_ULONG part_len)
1322 : {
1323 : /* Our keys don't support incremental operations */
1324 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1325 : }
1326 :
1327 : CK_RV
1328 0 : gkm_session_C_SignFinal (GkmSession *self, CK_BYTE_PTR signature,
1329 : CK_ULONG_PTR signature_len)
1330 : {
1331 : /* Our keys don't support incremental operations */
1332 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1333 : }
1334 :
1335 : CK_RV
1336 0 : gkm_session_C_SignRecoverInit (GkmSession *self, CK_MECHANISM_PTR mechanism,
1337 : CK_OBJECT_HANDLE key)
1338 : {
1339 : /* TODO: Need to implement */
1340 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1341 : }
1342 :
1343 : CK_RV
1344 0 : gkm_session_C_SignRecover (GkmSession *self, CK_BYTE_PTR data, CK_ULONG data_len,
1345 : CK_BYTE_PTR signature, CK_ULONG_PTR signature_len)
1346 : {
1347 : /* TODO: Need to implement */
1348 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1349 : }
1350 :
1351 : CK_RV
1352 0 : gkm_session_C_VerifyInit (GkmSession *self, CK_MECHANISM_PTR mechanism,
1353 : CK_OBJECT_HANDLE key)
1354 : {
1355 0 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1356 0 : if (!mechanism)
1357 0 : return CKR_ARGUMENTS_BAD;
1358 0 : return prepare_crypto (self, mechanism, CKA_VERIFY, key);
1359 : }
1360 :
1361 : CK_RV
1362 0 : gkm_session_C_Verify (GkmSession *self, CK_BYTE_PTR data, CK_ULONG data_len,
1363 : CK_BYTE_PTR signature, CK_ULONG signature_len)
1364 : {
1365 0 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1366 0 : return process_crypto (self, CKA_VERIFY, data, data_len, signature, &signature_len);
1367 : }
1368 :
1369 : CK_RV
1370 0 : gkm_session_C_VerifyUpdate (GkmSession *self, CK_BYTE_PTR part, CK_ULONG part_len)
1371 : {
1372 : /* Our keys don't support incremental operations */
1373 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1374 : }
1375 :
1376 : CK_RV
1377 0 : gkm_session_C_VerifyFinal (GkmSession *self, CK_BYTE_PTR signature,
1378 : CK_ULONG signature_len)
1379 : {
1380 : /* Our keys don't support incremental operations */
1381 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1382 : }
1383 :
1384 : CK_RV
1385 0 : gkm_session_C_VerifyRecoverInit (GkmSession *self, CK_MECHANISM_PTR mechanism,
1386 : CK_OBJECT_HANDLE key)
1387 : {
1388 : /* TODO: Need to implement */
1389 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1390 : }
1391 :
1392 : CK_RV
1393 0 : gkm_session_C_VerifyRecover (GkmSession *self, CK_BYTE_PTR signature,
1394 : CK_ULONG signature_len, CK_BYTE_PTR data,
1395 : CK_ULONG_PTR data_len)
1396 : {
1397 : /* TODO: Need to implement */
1398 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1399 : }
1400 :
1401 : CK_RV
1402 0 : gkm_session_C_DigestEncryptUpdate (GkmSession *self, CK_BYTE_PTR part,
1403 : CK_ULONG part_len, CK_BYTE_PTR enc_part,
1404 : CK_ULONG_PTR enc_part_len)
1405 : {
1406 : /* We don't support double operations */
1407 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1408 : }
1409 :
1410 : CK_RV
1411 0 : gkm_session_C_DecryptDigestUpdate (GkmSession *self, CK_BYTE_PTR enc_part,
1412 : CK_ULONG enc_part_len, CK_BYTE_PTR part,
1413 : CK_ULONG_PTR part_len)
1414 : {
1415 : /* We don't support double operations */
1416 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1417 : }
1418 :
1419 : CK_RV
1420 0 : gkm_session_C_SignEncryptUpdate (GkmSession *self, CK_BYTE_PTR part,
1421 : CK_ULONG part_len, CK_BYTE_PTR enc_part,
1422 : CK_ULONG_PTR enc_part_len)
1423 : {
1424 : /* We don't support double operations */
1425 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1426 : }
1427 :
1428 : CK_RV
1429 0 : gkm_session_C_DecryptVerifyUpdate (GkmSession *self, CK_BYTE_PTR enc_part,
1430 : CK_ULONG enc_part_len, CK_BYTE_PTR part,
1431 : CK_ULONG_PTR part_len)
1432 : {
1433 : /* We don't support double operations */
1434 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1435 : }
1436 :
1437 : CK_RV
1438 0 : gkm_session_C_GenerateKey (GkmSession* self, CK_MECHANISM_PTR mechanism,
1439 : CK_ATTRIBUTE_PTR template, CK_ULONG count,
1440 : CK_OBJECT_HANDLE_PTR key)
1441 : {
1442 : /* TODO: We need to implement this */
1443 0 : return CKR_FUNCTION_NOT_SUPPORTED;
1444 : }
1445 :
1446 : CK_RV
1447 1 : gkm_session_C_GenerateKeyPair (GkmSession* self, CK_MECHANISM_PTR mechanism,
1448 : CK_ATTRIBUTE_PTR pub_template, CK_ULONG pub_count,
1449 : CK_ATTRIBUTE_PTR priv_template, CK_ULONG priv_count,
1450 : CK_OBJECT_HANDLE_PTR pub_key, CK_OBJECT_HANDLE_PTR priv_key)
1451 : {
1452 1 : GkmObject *pub = NULL;
1453 1 : GkmObject *priv = NULL;
1454 : GkmTransaction *transaction;
1455 : CK_RV rv;
1456 :
1457 1 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1458 1 : if (!mechanism)
1459 0 : return CKR_ARGUMENTS_BAD;
1460 1 : if (!(!pub_count || pub_template))
1461 0 : return CKR_ARGUMENTS_BAD;
1462 1 : if (!(!priv_count || priv_template))
1463 0 : return CKR_ARGUMENTS_BAD;
1464 1 : if (!pub_key || !priv_key)
1465 0 : return CKR_ARGUMENTS_BAD;
1466 :
1467 : /*
1468 : * Duplicate the memory for the attributes (but not values) so we
1469 : * can 'consume' in the generator and create object functions.
1470 : */
1471 1 : pub_template = g_memdup (pub_template, pub_count * sizeof (CK_ATTRIBUTE));
1472 1 : priv_template = g_memdup (priv_template, priv_count * sizeof (CK_ATTRIBUTE));
1473 1 : transaction = gkm_transaction_new ();
1474 :
1475 : /* Actually do the object creation */
1476 1 : rv = gkm_crypto_generate_key_pair (self, mechanism->mechanism, pub_template, pub_count,
1477 : priv_template, priv_count, &pub, &priv);
1478 1 : if (rv != CKR_OK)
1479 0 : gkm_transaction_fail (transaction, rv);
1480 :
1481 1 : g_free (pub_template);
1482 1 : g_free (priv_template);
1483 :
1484 1 : gkm_transaction_complete (transaction);
1485 1 : rv = gkm_transaction_get_result (transaction);
1486 1 : g_object_unref (transaction);
1487 :
1488 1 : if (rv == CKR_OK) {
1489 1 : *pub_key = gkm_object_get_handle (pub);
1490 1 : *priv_key = gkm_object_get_handle (priv);
1491 : }
1492 :
1493 : /* Objects are owned by storage */
1494 1 : if (pub != NULL)
1495 1 : g_object_unref (pub);
1496 1 : if (priv != NULL)
1497 1 : g_object_unref (priv);
1498 :
1499 1 : return rv;
1500 : }
1501 :
1502 : CK_RV
1503 0 : gkm_session_C_WrapKey (GkmSession* self, CK_MECHANISM_PTR mechanism,
1504 : CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key,
1505 : CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len)
1506 : {
1507 0 : GkmObject *wrapper = NULL;
1508 0 : GkmObject *wrapped = NULL;
1509 : CK_RV rv;
1510 :
1511 0 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1512 0 : if (!mechanism)
1513 0 : return CKR_ARGUMENTS_BAD;
1514 0 : if (!wrapped_key_len)
1515 0 : return CKR_ARGUMENTS_BAD;
1516 :
1517 0 : rv = gkm_session_lookup_readable_object (self, wrapping_key, &wrapper);
1518 0 : if (rv == CKR_OBJECT_HANDLE_INVALID)
1519 0 : return CKR_WRAPPING_KEY_HANDLE_INVALID;
1520 0 : else if (rv != CKR_OK)
1521 0 : return rv;
1522 :
1523 0 : rv = gkm_session_lookup_readable_object (self, key, &wrapped);
1524 0 : if (rv == CKR_OBJECT_HANDLE_INVALID)
1525 0 : return CKR_KEY_HANDLE_INVALID;
1526 0 : else if (rv != CKR_OK)
1527 0 : return rv;
1528 :
1529 0 : return gkm_crypto_wrap_key (self, mechanism, wrapper, wrapped,
1530 : wrapped_key, wrapped_key_len);
1531 : }
1532 :
1533 : CK_RV
1534 19 : gkm_session_C_UnwrapKey (GkmSession* self, CK_MECHANISM_PTR mechanism,
1535 : CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key,
1536 : CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR template,
1537 : CK_ULONG count, CK_OBJECT_HANDLE_PTR key)
1538 : {
1539 19 : GkmObject *wrapper = NULL;
1540 19 : GkmObject *unwrapped = NULL;
1541 : CK_RV rv;
1542 :
1543 19 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1544 19 : if (!mechanism)
1545 0 : return CKR_ARGUMENTS_BAD;
1546 19 : if (!(!count || template))
1547 0 : return CKR_ARGUMENTS_BAD;
1548 19 : if (!key)
1549 0 : return CKR_ARGUMENTS_BAD;
1550 :
1551 19 : rv = gkm_session_lookup_readable_object (self, unwrapping_key, &wrapper);
1552 19 : if (rv == CKR_OBJECT_HANDLE_INVALID)
1553 0 : return CKR_WRAPPING_KEY_HANDLE_INVALID;
1554 19 : else if (rv != CKR_OK)
1555 0 : return rv;
1556 :
1557 : /*
1558 : * Duplicate the memory for the attributes (but not values) so we
1559 : * can 'consume' in the generator and create object functions.
1560 : */
1561 19 : template = g_memdup (template, count * sizeof (CK_ATTRIBUTE));
1562 :
1563 19 : rv = gkm_crypto_unwrap_key (self, mechanism, wrapper, wrapped_key,
1564 : wrapped_key_len, template, count, &unwrapped);
1565 :
1566 19 : g_free (template);
1567 :
1568 19 : if (rv == CKR_OK) {
1569 19 : *key = gkm_object_get_handle (unwrapped);
1570 19 : g_object_unref (unwrapped);
1571 : }
1572 :
1573 19 : return rv;
1574 : }
1575 :
1576 : CK_RV
1577 2 : gkm_session_C_DeriveKey (GkmSession* self, CK_MECHANISM_PTR mechanism,
1578 : CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR template,
1579 : CK_ULONG count, CK_OBJECT_HANDLE_PTR key)
1580 : {
1581 2 : GkmObject *base = NULL;
1582 2 : GkmObject *derived = NULL;
1583 : CK_RV rv;
1584 :
1585 2 : g_return_val_if_fail (GKM_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
1586 2 : if (!mechanism)
1587 0 : return CKR_ARGUMENTS_BAD;
1588 2 : if (!(!count || template))
1589 0 : return CKR_ARGUMENTS_BAD;
1590 2 : if (!key)
1591 0 : return CKR_ARGUMENTS_BAD;
1592 :
1593 2 : rv = gkm_session_lookup_readable_object (self, base_key, &base);
1594 2 : if (rv != CKR_OK)
1595 0 : return rv;
1596 :
1597 : /*
1598 : * Duplicate the memory for the attributes (but not values) so we
1599 : * can 'consume' in the generator and create object functions.
1600 : */
1601 2 : template = g_memdup (template, count * sizeof (CK_ATTRIBUTE));
1602 :
1603 : /* Actually do the object creation */
1604 2 : rv = gkm_crypto_derive_key (self, mechanism, base, template, count, &derived);
1605 :
1606 2 : g_free (template);
1607 :
1608 2 : if (rv == CKR_OK) {
1609 2 : *key = gkm_object_get_handle (derived);
1610 2 : g_object_unref (derived);
1611 : }
1612 :
1613 2 : return rv;
1614 : }
1615 :
1616 : CK_RV
1617 0 : gkm_session_C_SeedRandom (GkmSession* self, CK_BYTE_PTR seed, CK_ULONG seed_len)
1618 : {
1619 : /* We don't have a RNG */
1620 0 : return CKR_RANDOM_NO_RNG;
1621 : }
1622 :
1623 : CK_RV
1624 0 : gkm_session_C_GenerateRandom (GkmSession* self, CK_BYTE_PTR random_data,
1625 : CK_ULONG random_len)
1626 : {
1627 : /* We don't have a RNG */
1628 0 : return CKR_RANDOM_NO_RNG;
1629 : }
|