LCOV - code coverage report
Current view: top level - pkcs11/gkm - gkm-session.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 57.9 % 730 423
Test Date: 2024-04-08 13:24:42 Functions: 48.4 % 91 44

            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              : }
        

Generated by: LCOV version 2.0-1