~ubuntu-branches/ubuntu/trusty/gcr/trusty-proposed

« back to all changes in this revision

Viewing changes to gck/gck-mock.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach
  • Date: 2012-05-03 10:18:39 UTC
  • Revision ID: package-import@ubuntu.com-20120503101839-wuvloldm7gmdsnij
Tags: upstream-3.4.1
ImportĀ upstreamĀ versionĀ 3.4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * gnome-keyring
 
3
 *
 
4
 * Copyright (C) 2010 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, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
19
 * 02111-1307, USA.
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include "gck.h"
 
25
#include "gck-mock.h"
 
26
 
 
27
#include "pkcs11.h"
 
28
#include "pkcs11i.h"
 
29
 
 
30
#include <glib.h>
 
31
 
 
32
#include <string.h>
 
33
 
 
34
/*
 
35
 * This is *NOT* how you'd want to implement a PKCS#11 module. This
 
36
 * fake module simply provides enough for gck library to test against.
 
37
 * It doesn't pass any tests, or behave as expected from a PKCS#11 module.
 
38
 */
 
39
 
 
40
 
 
41
static gboolean initialized = FALSE;
 
42
static gchar *the_pin = NULL;
 
43
static gulong n_the_pin = 0;
 
44
 
 
45
static gboolean logged_in = FALSE;
 
46
static CK_USER_TYPE user_type = 0;
 
47
static CK_FUNCTION_LIST functionList;
 
48
 
 
49
typedef enum _Operation {
 
50
        OP_FIND = 1,
 
51
        OP_CRYPTO
 
52
} Operation;
 
53
 
 
54
typedef struct _Session {
 
55
        CK_SESSION_HANDLE handle;
 
56
        CK_SESSION_INFO info;
 
57
        GHashTable *objects;
 
58
 
 
59
        Operation operation;
 
60
 
 
61
        /* For find operations */
 
62
        GList *matches;
 
63
 
 
64
        /* For crypto operations */
 
65
        CK_OBJECT_HANDLE crypto_key;
 
66
        CK_ATTRIBUTE_TYPE crypto_method;
 
67
        CK_MECHANISM_TYPE crypto_mechanism;
 
68
        CK_BBOOL want_context_login;
 
69
 
 
70
        /* For 'signing' with CKM_MOCK_PREFIX */
 
71
        CK_BYTE sign_prefix[128];
 
72
        CK_ULONG n_sign_prefix;
 
73
} Session;
 
74
 
 
75
static guint unique_identifier = 100;
 
76
static GHashTable *the_sessions = NULL;
 
77
static GHashTable *the_objects = NULL;
 
78
 
 
79
enum {
 
80
        PRIVATE_KEY_CAPITALIZE = 3,
 
81
        PUBLIC_KEY_CAPITALIZE = 4,
 
82
        PRIVATE_KEY_PREFIX = 5,
 
83
        PUBLIC_KEY_PREFIX = 6
 
84
};
 
85
 
 
86
#define SIGNED_PREFIX "signed-prefix:"
 
87
 
 
88
static void
 
89
free_session (gpointer data)
 
90
{
 
91
        Session *sess = (Session*)data;
 
92
        if (sess)
 
93
                g_hash_table_destroy (sess->objects);
 
94
        g_free (sess);
 
95
}
 
96
 
 
97
static GckAttributes *
 
98
lookup_object (Session *session,
 
99
               CK_OBJECT_HANDLE hObject,
 
100
               GHashTable **table)
 
101
{
 
102
        GckAttributes *attrs;
 
103
 
 
104
        attrs = g_hash_table_lookup (the_objects, GUINT_TO_POINTER (hObject));
 
105
        if (attrs) {
 
106
                if (table)
 
107
                        *table = the_objects;
 
108
                return attrs;
 
109
        }
 
110
 
 
111
        attrs = g_hash_table_lookup (session->objects, GUINT_TO_POINTER (hObject));
 
112
        if (attrs) {
 
113
                if (table)
 
114
                        *table = session->objects;
 
115
                return attrs;
 
116
        }
 
117
 
 
118
        return NULL;
 
119
}
 
120
 
 
121
CK_OBJECT_HANDLE
 
122
gck_mock_module_add_object (GckAttributes *attrs)
 
123
{
 
124
        GckBuilder builder;
 
125
        gboolean token;
 
126
        guint handle;
 
127
 
 
128
        g_return_val_if_fail (the_objects, 0);
 
129
 
 
130
 
 
131
        handle = ++unique_identifier;
 
132
        if (gck_attributes_find_boolean (attrs, CKA_TOKEN, &token)) {
 
133
                g_return_val_if_fail (token == TRUE, 0);
 
134
                gck_attributes_ref_sink (attrs);
 
135
        } else {
 
136
                gck_builder_init (&builder);
 
137
                gck_builder_add_except (&builder, attrs, CKA_TOKEN, GCK_INVALID);
 
138
                gck_builder_add_boolean (&builder, CKA_TOKEN, TRUE);
 
139
                gck_attributes_unref (attrs);
 
140
                attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 
141
        }
 
142
        g_hash_table_insert (the_objects, GUINT_TO_POINTER (handle), attrs);
 
143
 
 
144
        return handle;
 
145
}
 
146
 
 
147
void
 
148
gck_mock_module_enumerate_objects (CK_SESSION_HANDLE handle, GckMockEnumerator func,
 
149
                                   gpointer user_data)
 
150
{
 
151
        GHashTableIter iter;
 
152
        gpointer key;
 
153
        gpointer value;
 
154
        Session *session;
 
155
 
 
156
        g_assert (the_objects);
 
157
        g_assert (func);
 
158
 
 
159
        /* Token objects */
 
160
        g_hash_table_iter_init (&iter, the_objects);
 
161
        while (g_hash_table_iter_next (&iter, &key, &value)) {
 
162
                if (!(func) (GPOINTER_TO_UINT (key), value, user_data))
 
163
                        return;
 
164
        }
 
165
 
 
166
        /* session objects */
 
167
        if (handle) {
 
168
                session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (handle));
 
169
                if (session) {
 
170
                        g_hash_table_iter_init (&iter, session->objects);
 
171
                        while (g_hash_table_iter_next (&iter, &key, &value)) {
 
172
                                if (!(func) (GPOINTER_TO_UINT (key), value, user_data))
 
173
                                        return;
 
174
                        }
 
175
                }
 
176
        }
 
177
}
 
178
 
 
179
typedef struct _FindObject {
 
180
        CK_ATTRIBUTE_PTR attrs;
 
181
        CK_ULONG n_attrs;
 
182
        CK_OBJECT_HANDLE object;
 
183
} FindObject;
 
184
 
 
185
static gboolean
 
186
enumerate_and_find_object (CK_OBJECT_HANDLE object, GckAttributes *attrs, gpointer user_data)
 
187
{
 
188
        FindObject *ctx = user_data;
 
189
        CK_ATTRIBUTE_PTR match;
 
190
        const GckAttribute *attr;
 
191
        CK_ULONG i;
 
192
 
 
193
        for (i = 0; i < ctx->n_attrs; ++i) {
 
194
                match = ctx->attrs + i;
 
195
                attr = gck_attributes_find (attrs, match->type);
 
196
                if (!attr)
 
197
                        return TRUE; /* Continue */
 
198
 
 
199
                if (attr->length != match->ulValueLen ||
 
200
                    memcmp (attr->value, match->pValue, attr->length) != 0)
 
201
                        return TRUE; /* Continue */
 
202
        }
 
203
 
 
204
        ctx->object = object;
 
205
        return FALSE; /* Stop iteration */
 
206
}
 
207
 
 
208
CK_OBJECT_HANDLE
 
209
gck_mock_module_find_object (CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
 
210
{
 
211
        FindObject ctx;
 
212
 
 
213
        ctx.attrs = attrs;
 
214
        ctx.n_attrs = n_attrs;
 
215
        ctx.object = 0;
 
216
 
 
217
        gck_mock_module_enumerate_objects (session, enumerate_and_find_object, &ctx);
 
218
 
 
219
        return ctx.object;
 
220
}
 
221
 
 
222
static gboolean
 
223
enumerate_and_count_objects (CK_OBJECT_HANDLE object, GckAttributes *attrs, gpointer user_data)
 
224
{
 
225
        guint *n_objects = user_data;
 
226
        ++(*n_objects);
 
227
        return TRUE; /* Continue */
 
228
}
 
229
 
 
230
guint
 
231
gck_mock_module_count_objects (CK_SESSION_HANDLE session)
 
232
{
 
233
        guint n_objects = 0;
 
234
        gck_mock_module_enumerate_objects (session, enumerate_and_count_objects, &n_objects);
 
235
        return n_objects;
 
236
}
 
237
 
 
238
static GckAttributes *
 
239
replace_attributes (GckAttributes *atts,
 
240
                    CK_ATTRIBUTE_PTR attrs,
 
241
                    CK_ULONG n_attrs)
 
242
{
 
243
        GckBuilder builder;
 
244
        CK_ULONG i;
 
245
        CK_ATTRIBUTE_PTR set;
 
246
        gulong *types;
 
247
 
 
248
        if (!n_attrs)
 
249
                return gck_attributes_ref_sink (atts);
 
250
 
 
251
        gck_builder_init (&builder);
 
252
        types = g_new0 (gulong, n_attrs);
 
253
        for (i = 0; i < n_attrs; ++i) {
 
254
                set = attrs + i;
 
255
                types[i] = set->type;
 
256
                gck_builder_add_data (&builder, set->type, set->pValue, set->ulValueLen);
 
257
        }
 
258
        gck_builder_add_exceptv (&builder, atts, types, n_attrs);
 
259
        g_free (types);
 
260
        return gck_attributes_ref_sink (gck_builder_end (&builder));
 
261
}
 
262
 
 
263
void
 
264
gck_mock_module_set_object (CK_OBJECT_HANDLE object, CK_ATTRIBUTE_PTR attrs,
 
265
                            CK_ULONG n_attrs)
 
266
{
 
267
        GckAttributes *atts;
 
268
        GckAttributes *replaced;
 
269
 
 
270
        g_return_if_fail (object != 0);
 
271
        g_return_if_fail (the_objects);
 
272
 
 
273
        atts = g_hash_table_lookup (the_objects, GUINT_TO_POINTER (object));
 
274
        g_return_if_fail (atts);
 
275
 
 
276
        if (!n_attrs)
 
277
                return;
 
278
 
 
279
        replaced = replace_attributes (atts, attrs, n_attrs);
 
280
        g_hash_table_replace (the_objects, GUINT_TO_POINTER (object), replaced);
 
281
}
 
282
 
 
283
void
 
284
gck_mock_module_set_pin (const gchar *password)
 
285
{
 
286
        g_free (the_pin);
 
287
        the_pin = g_strdup (password);
 
288
        n_the_pin = strlen (password);
 
289
}
 
290
 
 
291
CK_RV
 
292
gck_mock_C_Initialize (CK_VOID_PTR pInitArgs)
 
293
{
 
294
        GckBuilder builder;
 
295
        CK_ULONG value;
 
296
        CK_C_INITIALIZE_ARGS_PTR args;
 
297
 
 
298
        g_return_val_if_fail (initialized == FALSE, CKR_CRYPTOKI_ALREADY_INITIALIZED);
 
299
 
 
300
        args = (CK_C_INITIALIZE_ARGS_PTR)pInitArgs;
 
301
        if (args) {
 
302
                g_return_val_if_fail(
 
303
                              (args->CreateMutex == NULL && args->DestroyMutex == NULL &&
 
304
                               args->LockMutex == NULL && args->UnlockMutex == NULL) ||
 
305
                              (args->CreateMutex != NULL && args->DestroyMutex != NULL &&
 
306
                               args->LockMutex != NULL && args->UnlockMutex != NULL),
 
307
                               CKR_ARGUMENTS_BAD);
 
308
 
 
309
                /* Flags should allow OS locking and os threads */
 
310
                g_return_val_if_fail ((args->flags & CKF_OS_LOCKING_OK), CKR_CANT_LOCK);
 
311
                g_return_val_if_fail ((args->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) == 0, CKR_NEED_TO_CREATE_THREADS);
 
312
        }
 
313
 
 
314
        the_pin = g_strdup ("booo");
 
315
        n_the_pin = strlen (the_pin);
 
316
        the_sessions = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, free_session);
 
317
        the_objects = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)gck_attributes_unref);
 
318
 
 
319
        /* Our token object */
 
320
        gck_builder_init (&builder);
 
321
        gck_builder_add_ulong (&builder, CKA_CLASS, CKO_DATA);
 
322
        gck_builder_add_string (&builder, CKA_LABEL, "TEST LABEL");
 
323
        g_hash_table_insert (the_objects, GUINT_TO_POINTER (2),
 
324
                             gck_attributes_ref_sink (gck_builder_end (&builder)));
 
325
 
 
326
        /* Private capitalize key */
 
327
        value = CKM_MOCK_CAPITALIZE;
 
328
        gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PRIVATE_KEY);
 
329
        gck_builder_add_string (&builder, CKA_LABEL, "Private Capitalize Key");
 
330
        gck_builder_add_data (&builder, CKA_ALLOWED_MECHANISMS, (const guchar *)&value, sizeof (value));
 
331
        gck_builder_add_boolean (&builder, CKA_DECRYPT, CK_TRUE);
 
332
        gck_builder_add_boolean (&builder, CKA_PRIVATE, CK_TRUE);
 
333
        gck_builder_add_boolean (&builder, CKA_WRAP, CK_TRUE);
 
334
        gck_builder_add_boolean (&builder, CKA_UNWRAP, CK_TRUE);
 
335
        gck_builder_add_boolean (&builder, CKA_DERIVE, CK_TRUE);
 
336
        gck_builder_add_string (&builder, CKA_VALUE, "value");
 
337
        gck_builder_add_string (&builder, CKA_GNOME_UNIQUE, "unique1");
 
338
        g_hash_table_insert (the_objects, GUINT_TO_POINTER (PRIVATE_KEY_CAPITALIZE),
 
339
                             gck_attributes_ref_sink (gck_builder_end (&builder)));
 
340
 
 
341
        /* Public capitalize key */
 
342
        value = CKM_MOCK_CAPITALIZE;
 
343
        gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PUBLIC_KEY);
 
344
        gck_builder_add_string (&builder, CKA_LABEL, "Public Capitalize Key");
 
345
        gck_builder_add_data (&builder, CKA_ALLOWED_MECHANISMS, (const guchar *)&value, sizeof (value));
 
346
        gck_builder_add_boolean (&builder, CKA_ENCRYPT, CK_TRUE);
 
347
        gck_builder_add_boolean (&builder, CKA_PRIVATE, CK_FALSE);
 
348
        gck_builder_add_string (&builder, CKA_VALUE, "value");
 
349
        gck_builder_add_string (&builder, CKA_GNOME_UNIQUE, "unique2");
 
350
        g_hash_table_insert (the_objects, GUINT_TO_POINTER (PUBLIC_KEY_CAPITALIZE), gck_builder_end (&builder));
 
351
 
 
352
        /* Private prefix key */
 
353
        value = CKM_MOCK_PREFIX;
 
354
        gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PRIVATE_KEY);
 
355
        gck_builder_add_string (&builder, CKA_LABEL, "Private prefix key");
 
356
        gck_builder_add_data (&builder, CKA_ALLOWED_MECHANISMS, (const guchar *)&value, sizeof (value));
 
357
        gck_builder_add_boolean (&builder, CKA_SIGN, CK_TRUE);
 
358
        gck_builder_add_boolean (&builder, CKA_PRIVATE, CK_TRUE);
 
359
        gck_builder_add_boolean (&builder, CKA_ALWAYS_AUTHENTICATE, CK_TRUE);
 
360
        gck_builder_add_string (&builder, CKA_VALUE, "value");
 
361
        gck_builder_add_string (&builder, CKA_GNOME_UNIQUE, "unique3");
 
362
        g_hash_table_insert (the_objects, GUINT_TO_POINTER (PRIVATE_KEY_PREFIX),
 
363
                             gck_attributes_ref_sink (gck_builder_end (&builder)));
 
364
 
 
365
        /* Private prefix key */
 
366
        value = CKM_MOCK_PREFIX;
 
367
        gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PUBLIC_KEY);
 
368
        gck_builder_add_string (&builder, CKA_LABEL, "Public prefix key");
 
369
        gck_builder_add_data (&builder, CKA_ALLOWED_MECHANISMS, (const guchar *)&value, sizeof (value));
 
370
        gck_builder_add_boolean (&builder, CKA_VERIFY, CK_TRUE);
 
371
        gck_builder_add_boolean (&builder, CKA_PRIVATE, CK_FALSE);
 
372
        gck_builder_add_string (&builder, CKA_VALUE, "value");
 
373
        gck_builder_add_string (&builder, CKA_GNOME_UNIQUE, "unique4");
 
374
        g_hash_table_insert (the_objects, GUINT_TO_POINTER (PUBLIC_KEY_PREFIX),
 
375
                             gck_attributes_ref_sink (gck_builder_end (&builder)));
 
376
 
 
377
        logged_in = FALSE;
 
378
        initialized = TRUE;
 
379
        return CKR_OK;
 
380
}
 
381
 
 
382
CK_RV
 
383
gck_mock_validate_and_C_Initialize (CK_VOID_PTR pInitArgs)
 
384
{
 
385
        CK_C_INITIALIZE_ARGS_PTR args;
 
386
        void *mutex;
 
387
        CK_RV rv;
 
388
 
 
389
        args = (CK_C_INITIALIZE_ARGS_PTR)pInitArgs;
 
390
        if (args) {
 
391
                g_assert ((args->CreateMutex) (NULL) == CKR_ARGUMENTS_BAD && "CreateMutex succeeded wrong");
 
392
                g_assert ((args->DestroyMutex) (NULL) == CKR_MUTEX_BAD && "DestroyMutex succeeded wrong");
 
393
                g_assert ((args->LockMutex) (NULL) == CKR_MUTEX_BAD && "LockMutex succeeded wrong");
 
394
                g_assert ((args->UnlockMutex) (NULL) == CKR_MUTEX_BAD && "UnlockMutex succeeded wrong");
 
395
 
 
396
                /* Try to create an actual mutex */
 
397
                rv = (args->CreateMutex) (&mutex);
 
398
                g_assert (rv == CKR_OK && "CreateMutex g_assert_not_reacheded");
 
399
                g_assert (mutex != NULL && "CreateMutex created null mutex");
 
400
 
 
401
                /* Try and lock the mutex */
 
402
                rv = (args->LockMutex) (mutex);
 
403
                g_assert (rv == CKR_OK && "LockMutex g_assert_not_reacheded");
 
404
 
 
405
                /* Try and unlock the mutex */
 
406
                rv = (args->UnlockMutex) (mutex);
 
407
                g_assert (rv == CKR_OK && "UnlockMutex g_assert_not_reacheded");
 
408
 
 
409
                /* Try and destroy the mutex */
 
410
                rv = (args->DestroyMutex) (mutex);
 
411
                g_assert (rv == CKR_OK && "DestroyMutex g_assert_not_reacheded");
 
412
        }
 
413
 
 
414
        return gck_mock_C_Initialize (pInitArgs);
 
415
}
 
416
 
 
417
CK_RV
 
418
gck_mock_C_Finalize (CK_VOID_PTR pReserved)
 
419
{
 
420
        g_return_val_if_fail (pReserved == NULL, CKR_ARGUMENTS_BAD);
 
421
        g_return_val_if_fail (initialized == TRUE, CKR_CRYPTOKI_NOT_INITIALIZED);
 
422
 
 
423
        initialized = FALSE;
 
424
        logged_in = FALSE;
 
425
        g_hash_table_destroy (the_objects);
 
426
        the_objects = NULL;
 
427
 
 
428
        g_hash_table_destroy (the_sessions);
 
429
        the_sessions = NULL;
 
430
 
 
431
        g_free (the_pin);
 
432
        return CKR_OK;
 
433
}
 
434
 
 
435
static const CK_INFO TEST_INFO = {
 
436
        { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },
 
437
        "TEST MANUFACTURER              ",
 
438
        0,
 
439
        "TEST LIBRARY                   ",
 
440
        { 45, 145 }
 
441
};
 
442
 
 
443
CK_RV
 
444
gck_mock_C_GetInfo (CK_INFO_PTR pInfo)
 
445
{
 
446
        g_return_val_if_fail (pInfo, CKR_ARGUMENTS_BAD);
 
447
        memcpy (pInfo, &TEST_INFO, sizeof (*pInfo));
 
448
        return CKR_OK;
 
449
}
 
450
 
 
451
CK_RV
 
452
gck_mock_C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
 
453
{
 
454
        g_return_val_if_fail (list, CKR_ARGUMENTS_BAD);
 
455
        *list = &functionList;
 
456
        return CKR_OK;
 
457
}
 
458
 
 
459
/*
 
460
 * Two slots
 
461
 *  ONE: token present
 
462
 *  TWO: token not present
 
463
 */
 
464
 
 
465
CK_RV
 
466
gck_mock_C_GetSlotList (CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
 
467
{
 
468
        CK_ULONG count;
 
469
 
 
470
        g_return_val_if_fail (pulCount, CKR_ARGUMENTS_BAD);
 
471
 
 
472
        count = tokenPresent ? 1 : 2;
 
473
 
 
474
        /* Application only wants to know the number of slots. */
 
475
        if (pSlotList == NULL) {
 
476
                *pulCount = count;
 
477
                return CKR_OK;
 
478
        }
 
479
 
 
480
        if (*pulCount < count)
 
481
                g_return_val_if_reached (CKR_BUFFER_TOO_SMALL);
 
482
 
 
483
        *pulCount = count;
 
484
        pSlotList[0] = GCK_MOCK_SLOT_ONE_ID;
 
485
        if (!tokenPresent)
 
486
                pSlotList[1] = GCK_MOCK_SLOT_TWO_ID;
 
487
 
 
488
        return CKR_OK;
 
489
}
 
490
 
 
491
/* Update gck-mock.h URIs when updating this */
 
492
 
 
493
static const CK_SLOT_INFO TEST_INFO_ONE = {
 
494
        "TEST SLOT                                                       ",
 
495
        "TEST MANUFACTURER              ",
 
496
        CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE,
 
497
        { 55, 155 },
 
498
        { 65, 165 },
 
499
};
 
500
 
 
501
/* Update gck-mock.h URIs when updating this */
 
502
 
 
503
static const CK_SLOT_INFO TEST_INFO_TWO = {
 
504
        "TEST SLOT                                                       ",
 
505
        "TEST MANUFACTURER              ",
 
506
        CKF_REMOVABLE_DEVICE,
 
507
        { 55, 155 },
 
508
        { 65, 165 },
 
509
};
 
510
 
 
511
CK_RV
 
512
gck_mock_C_GetSlotInfo (CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
 
513
{
 
514
        g_return_val_if_fail (pInfo, CKR_ARGUMENTS_BAD);
 
515
 
 
516
        if (slotID == GCK_MOCK_SLOT_ONE_ID) {
 
517
                memcpy (pInfo, &TEST_INFO_ONE, sizeof (*pInfo));
 
518
                return CKR_OK;
 
519
        } else if (slotID == GCK_MOCK_SLOT_TWO_ID) {
 
520
                memcpy (pInfo, &TEST_INFO_TWO, sizeof (*pInfo));
 
521
                return CKR_OK;
 
522
        } else {
 
523
                g_return_val_if_reached (CKR_SLOT_ID_INVALID);
 
524
        }
 
525
}
 
526
 
 
527
/* Update gck-mock.h URIs when updating this */
 
528
 
 
529
static const CK_TOKEN_INFO TEST_TOKEN_ONE = {
 
530
        "TEST LABEL                      ",
 
531
        "TEST MANUFACTURER               ",
 
532
        "TEST MODEL      ",
 
533
        "TEST SERIAL     ",
 
534
        CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_CLOCK_ON_TOKEN | CKF_TOKEN_INITIALIZED,
 
535
        1,
 
536
        2,
 
537
        3,
 
538
        4,
 
539
        5,
 
540
        6,
 
541
        7,
 
542
        8,
 
543
        9,
 
544
        10,
 
545
        { 75, 175 },
 
546
        { 85, 185 },
 
547
        { '1', '9', '9', '9', '0', '5', '2', '5', '0', '9', '1', '9', '5', '9', '0', '0' }
 
548
};
 
549
 
 
550
CK_RV
 
551
gck_mock_C_GetTokenInfo (CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
 
552
{
 
553
        g_return_val_if_fail (pInfo != NULL, CKR_ARGUMENTS_BAD);
 
554
 
 
555
        if (slotID == GCK_MOCK_SLOT_ONE_ID) {
 
556
                memcpy (pInfo, &TEST_TOKEN_ONE, sizeof (*pInfo));
 
557
                return CKR_OK;
 
558
        } else if (slotID == GCK_MOCK_SLOT_TWO_ID) {
 
559
                return CKR_TOKEN_NOT_PRESENT;
 
560
        } else {
 
561
                g_return_val_if_reached (CKR_SLOT_ID_INVALID);
 
562
        }
 
563
}
 
564
 
 
565
CK_RV
 
566
gck_mock_fail_C_GetTokenInfo (CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
 
567
{
 
568
        return CKR_GENERAL_ERROR;
 
569
}
 
570
 
 
571
/*
 
572
 * TWO mechanisms:
 
573
 *  CKM_MOCK_CAPITALIZE
 
574
 *  CKM_MOCK_PREFIX
 
575
 */
 
576
 
 
577
CK_RV
 
578
gck_mock_C_GetMechanismList (CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList,
 
579
                             CK_ULONG_PTR pulCount)
 
580
{
 
581
        g_return_val_if_fail (slotID == GCK_MOCK_SLOT_ONE_ID, CKR_SLOT_ID_INVALID);
 
582
        g_return_val_if_fail (pulCount, CKR_ARGUMENTS_BAD);
 
583
 
 
584
        /* Application only wants to know the number of slots. */
 
585
        if (pMechanismList == NULL) {
 
586
                *pulCount = 2;
 
587
                return CKR_OK;
 
588
        }
 
589
 
 
590
        if (*pulCount != 2)
 
591
                g_return_val_if_reached (CKR_BUFFER_TOO_SMALL);
 
592
 
 
593
        pMechanismList[0] = CKM_MOCK_CAPITALIZE;
 
594
        pMechanismList[1] = CKM_MOCK_PREFIX;
 
595
        return CKR_OK;
 
596
}
 
597
 
 
598
static const CK_MECHANISM_INFO TEST_MECH_CAPITALIZE = {
 
599
        512, 4096, 0
 
600
};
 
601
 
 
602
static const CK_MECHANISM_INFO TEST_MECH_PREFIX = {
 
603
        2048, 2048, 0
 
604
};
 
605
 
 
606
CK_RV
 
607
gck_mock_C_GetMechanismInfo (CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
 
608
                             CK_MECHANISM_INFO_PTR pInfo)
 
609
{
 
610
        g_return_val_if_fail (slotID == GCK_MOCK_SLOT_ONE_ID, CKR_SLOT_ID_INVALID);
 
611
        g_return_val_if_fail (pInfo, CKR_ARGUMENTS_BAD);
 
612
 
 
613
        if (type == CKM_MOCK_CAPITALIZE) {
 
614
                memcpy (pInfo, &TEST_MECH_CAPITALIZE, sizeof (*pInfo));
 
615
                return CKR_OK;
 
616
        } else if (type == CKM_MOCK_PREFIX) {
 
617
                memcpy (pInfo, &TEST_MECH_PREFIX, sizeof (*pInfo));
 
618
                return CKR_OK;
 
619
        } else {
 
620
                g_return_val_if_reached (CKR_MECHANISM_INVALID);
 
621
        }
 
622
}
 
623
 
 
624
CK_RV
 
625
gck_mock_specific_args_C_InitToken (CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen,
 
626
                                    CK_UTF8CHAR_PTR pLabel)
 
627
{
 
628
        g_return_val_if_fail (slotID == GCK_MOCK_SLOT_ONE_ID, CKR_SLOT_ID_INVALID);
 
629
 
 
630
        g_return_val_if_fail (pPin, CKR_PIN_INVALID);
 
631
        g_return_val_if_fail (strlen ("TEST PIN") == ulPinLen, CKR_PIN_INVALID);
 
632
        g_return_val_if_fail (strncmp ((gchar*)pPin, "TEST PIN", ulPinLen) == 0, CKR_PIN_INVALID);
 
633
        g_return_val_if_fail (pLabel != NULL, CKR_PIN_INVALID);
 
634
        g_return_val_if_fail (strcmp ((gchar*)pPin, "TEST LABEL") == 0, CKR_PIN_INVALID);
 
635
 
 
636
        g_free (the_pin);
 
637
        the_pin = g_strndup ((gchar*)pPin, ulPinLen);
 
638
        n_the_pin = ulPinLen;
 
639
        return CKR_OK;
 
640
}
 
641
 
 
642
CK_RV
 
643
gck_mock_unsupported_C_WaitForSlotEvent (CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
 
644
{
 
645
        return CKR_FUNCTION_NOT_SUPPORTED;
 
646
}
 
647
 
 
648
CK_RV
 
649
gck_mock_C_OpenSession (CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication,
 
650
                        CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession)
 
651
{
 
652
        Session *sess;
 
653
 
 
654
        g_return_val_if_fail (slotID == GCK_MOCK_SLOT_ONE_ID || slotID == GCK_MOCK_SLOT_TWO_ID, CKR_SLOT_ID_INVALID);
 
655
        g_return_val_if_fail (phSession != NULL, CKR_ARGUMENTS_BAD);
 
656
        g_return_val_if_fail ((flags & CKF_SERIAL_SESSION) == CKF_SERIAL_SESSION, CKR_SESSION_PARALLEL_NOT_SUPPORTED);
 
657
 
 
658
        sess = g_new0 (Session, 1);
 
659
        sess->handle = ++unique_identifier;
 
660
        sess->info.flags = flags;
 
661
        sess->info.slotID = slotID;
 
662
        sess->info.state = 0;
 
663
        sess->info.ulDeviceError = 1414;
 
664
        sess->objects = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)gck_attributes_unref);
 
665
        *phSession = sess->handle;
 
666
 
 
667
        g_hash_table_replace (the_sessions, GUINT_TO_POINTER (sess->handle), sess);
 
668
        return CKR_OK;
 
669
}
 
670
 
 
671
CK_RV
 
672
gck_mock_fail_C_OpenSession (CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication,
 
673
                             CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession)
 
674
{
 
675
        return CKR_GENERAL_ERROR;
 
676
}
 
677
 
 
678
CK_RV
 
679
gck_mock_C_CloseSession (CK_SESSION_HANDLE hSession)
 
680
{
 
681
        Session *session;
 
682
 
 
683
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
684
        g_return_val_if_fail (session, CKR_SESSION_HANDLE_INVALID);
 
685
 
 
686
        g_hash_table_remove (the_sessions, GUINT_TO_POINTER (hSession));
 
687
        return CKR_OK;
 
688
}
 
689
 
 
690
CK_RV
 
691
gck_mock_C_CloseAllSessions (CK_SLOT_ID slotID)
 
692
{
 
693
        g_return_val_if_fail (slotID == GCK_MOCK_SLOT_ONE_ID, CKR_SLOT_ID_INVALID);
 
694
 
 
695
        g_hash_table_remove_all (the_sessions);
 
696
        return CKR_OK;
 
697
}
 
698
 
 
699
CK_RV
 
700
gck_mock_C_GetFunctionStatus (CK_SESSION_HANDLE hSession)
 
701
{
 
702
        return CKR_FUNCTION_NOT_PARALLEL;
 
703
}
 
704
 
 
705
CK_RV
 
706
gck_mock_C_CancelFunction (CK_SESSION_HANDLE hSession)
 
707
{
 
708
        return CKR_FUNCTION_NOT_PARALLEL;
 
709
}
 
710
 
 
711
CK_RV
 
712
gck_mock_C_GetSessionInfo (CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
 
713
{
 
714
        Session *session;
 
715
 
 
716
        g_return_val_if_fail (pInfo != NULL, CKR_ARGUMENTS_BAD);
 
717
 
 
718
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
719
        g_assert (session != NULL && "No such session found");
 
720
        if (!session)
 
721
                return CKR_SESSION_HANDLE_INVALID;
 
722
 
 
723
        if (logged_in) {
 
724
                if (session->info.flags & CKF_RW_SESSION)
 
725
                        session->info.state = CKS_RW_USER_FUNCTIONS;
 
726
                else
 
727
                        session->info.state = CKS_RO_USER_FUNCTIONS;
 
728
        } else {
 
729
                if (session->info.flags & CKF_RW_SESSION)
 
730
                        session->info.state = CKS_RW_PUBLIC_SESSION;
 
731
                else
 
732
                        session->info.state = CKS_RO_PUBLIC_SESSION;
 
733
        }
 
734
 
 
735
        memcpy (pInfo, &session->info, sizeof (*pInfo));
 
736
        return CKR_OK;
 
737
}
 
738
 
 
739
CK_RV
 
740
gck_mock_fail_C_GetSessionInfo (CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
 
741
{
 
742
        return CKR_GENERAL_ERROR;
 
743
}
 
744
 
 
745
CK_RV
 
746
gck_mock_C_InitPIN (CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin,
 
747
                    CK_ULONG ulPinLen)
 
748
{
 
749
        Session *session;
 
750
 
 
751
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
752
        g_return_val_if_fail (session, CKR_SESSION_HANDLE_INVALID);
 
753
 
 
754
        g_free (the_pin);
 
755
        the_pin = g_strndup ((gchar*)pPin, ulPinLen);
 
756
        n_the_pin = ulPinLen;
 
757
        return CKR_OK;
 
758
}
 
759
 
 
760
CK_RV
 
761
gck_mock_C_SetPIN (CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin,
 
762
                   CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
 
763
{
 
764
        Session *session;
 
765
        gboolean match;
 
766
        gchar *old;
 
767
 
 
768
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
769
        g_return_val_if_fail (session, CKR_SESSION_HANDLE_INVALID);
 
770
 
 
771
        old = g_strndup ((gchar*)pOldPin, ulOldLen);
 
772
        match = old && g_str_equal (old, the_pin);
 
773
        g_free (old);
 
774
 
 
775
        if (!match)
 
776
                return CKR_PIN_INCORRECT;
 
777
 
 
778
        g_free (the_pin);
 
779
        the_pin = g_strndup ((gchar*)pNewPin, ulNewLen);
 
780
        n_the_pin = ulNewLen;
 
781
        return CKR_OK;
 
782
}
 
783
 
 
784
CK_RV
 
785
gck_mock_unsupported_C_GetOperationState (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState,
 
786
                                          CK_ULONG_PTR pulOperationStateLen)
 
787
{
 
788
        return CKR_FUNCTION_NOT_SUPPORTED;
 
789
}
 
790
 
 
791
CK_RV
 
792
gck_mock_unsupported_C_SetOperationState (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState,
 
793
                                          CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey,
 
794
                                          CK_OBJECT_HANDLE hAuthenticationKey)
 
795
{
 
796
        return CKR_FUNCTION_NOT_SUPPORTED;
 
797
}
 
798
 
 
799
CK_RV
 
800
gck_mock_C_Login (CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
 
801
                  CK_UTF8CHAR_PTR pPin, CK_ULONG pPinLen)
 
802
{
 
803
        Session *session;
 
804
 
 
805
        g_return_val_if_fail (userType == CKU_SO ||
 
806
                              userType == CKU_USER ||
 
807
                              userType == CKU_CONTEXT_SPECIFIC,
 
808
                              CKR_USER_TYPE_INVALID);
 
809
 
 
810
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
811
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
812
        g_return_val_if_fail (logged_in == FALSE, CKR_USER_ALREADY_LOGGED_IN);
 
813
 
 
814
        if (!pPin)
 
815
                return CKR_PIN_INCORRECT;
 
816
 
 
817
        if (pPinLen != strlen (the_pin))
 
818
                return CKR_PIN_INCORRECT;
 
819
        if (strncmp ((gchar*)pPin, the_pin, pPinLen) != 0)
 
820
                return CKR_PIN_INCORRECT;
 
821
 
 
822
        if (userType == CKU_CONTEXT_SPECIFIC) {
 
823
                g_return_val_if_fail (session->want_context_login == TRUE, CKR_OPERATION_NOT_INITIALIZED);
 
824
                session->want_context_login = CK_FALSE;
 
825
        } else {
 
826
                logged_in = TRUE;
 
827
                user_type = userType;
 
828
        }
 
829
 
 
830
        return CKR_OK;
 
831
}
 
832
 
 
833
CK_RV
 
834
gck_mock_C_Logout (CK_SESSION_HANDLE hSession)
 
835
{
 
836
        Session *session;
 
837
 
 
838
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
839
        g_assert (session != NULL && "No such session found");
 
840
        if (!session)
 
841
                return CKR_SESSION_HANDLE_INVALID;
 
842
 
 
843
        g_assert (logged_in && "Not logged in");
 
844
        logged_in = FALSE;
 
845
        user_type = 0;
 
846
        return CKR_OK;
 
847
}
 
848
 
 
849
CK_RV
 
850
gck_mock_C_CreateObject (CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
 
851
                         CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
 
852
{
 
853
        GckBuilder builder;
 
854
        GckAttributes *attrs;
 
855
        Session *session;
 
856
        gboolean token, priv;
 
857
        CK_OBJECT_CLASS klass;
 
858
        CK_OBJECT_HANDLE object;
 
859
        const GckAttribute *attr;
 
860
        CK_ULONG i;
 
861
 
 
862
        g_return_val_if_fail (phObject, CKR_ARGUMENTS_BAD);
 
863
 
 
864
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
865
        g_return_val_if_fail (session, CKR_SESSION_HANDLE_INVALID);
 
866
 
 
867
        gck_builder_init (&builder);
 
868
        for (i = 0; i < ulCount; ++i)
 
869
                gck_builder_add_data (&builder, pTemplate[i].type, pTemplate[i].pValue, pTemplate[i].ulValueLen);
 
870
 
 
871
        attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 
872
        if (gck_attributes_find_boolean (attrs, CKA_PRIVATE, &priv) && priv) {
 
873
                if (!logged_in) {
 
874
                        gck_attributes_unref (attrs);
 
875
                        return CKR_USER_NOT_LOGGED_IN;
 
876
                }
 
877
        }
 
878
 
 
879
        /* In order to create a credential we must check CK_VALUE */
 
880
        if (gck_attributes_find_ulong (attrs, CKA_CLASS, &klass) && klass == CKO_G_CREDENTIAL) {
 
881
                if (gck_attributes_find_ulong (attrs, CKA_G_OBJECT, &object)) {
 
882
                        attr = gck_attributes_find (attrs, CKA_VALUE);
 
883
                        if (!attr || attr->length != n_the_pin ||
 
884
                            memcmp (attr->value, the_pin, attr->length) != 0) {
 
885
                                gck_attributes_unref (attrs);
 
886
                                return CKR_PIN_INCORRECT;
 
887
                        }
 
888
                }
 
889
        }
 
890
 
 
891
        *phObject = ++unique_identifier;
 
892
        if (gck_attributes_find_boolean (attrs, CKA_TOKEN, &token) && token)
 
893
                g_hash_table_insert (the_objects, GUINT_TO_POINTER (*phObject), attrs);
 
894
        else
 
895
                g_hash_table_insert (session->objects, GUINT_TO_POINTER (*phObject), attrs);
 
896
 
 
897
        return CKR_OK;
 
898
}
 
899
 
 
900
CK_RV
 
901
gck_mock_fail_C_CreateObject (CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
 
902
                              CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
 
903
{
 
904
        /* Always fails */
 
905
        return CKR_FUNCTION_FAILED;
 
906
}
 
907
 
 
908
CK_RV
 
909
gck_mock_unsupported_C_CopyObject (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
 
910
                                   CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
 
911
                                   CK_OBJECT_HANDLE_PTR phNewObject)
 
912
{
 
913
        return CKR_FUNCTION_NOT_SUPPORTED;
 
914
}
 
915
 
 
916
CK_RV
 
917
gck_mock_C_DestroyObject (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
 
918
{
 
919
        GckAttributes *attrs;
 
920
        Session *session;
 
921
        gboolean priv;
 
922
 
 
923
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
924
        g_return_val_if_fail (session, CKR_SESSION_HANDLE_INVALID);
 
925
 
 
926
        attrs = lookup_object (session, hObject, NULL);
 
927
        g_return_val_if_fail (attrs, CKR_OBJECT_HANDLE_INVALID);
 
928
 
 
929
        if (gck_attributes_find_boolean (attrs, CKA_PRIVATE, &priv) && priv) {
 
930
                if (!logged_in)
 
931
                        return CKR_USER_NOT_LOGGED_IN;
 
932
        }
 
933
 
 
934
        g_hash_table_remove (the_objects, GUINT_TO_POINTER (hObject));
 
935
        g_hash_table_remove (session->objects, GUINT_TO_POINTER (hObject));
 
936
 
 
937
        return CKR_OK;
 
938
}
 
939
 
 
940
CK_RV
 
941
gck_mock_unsupported_C_GetObjectSize (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
 
942
                                      CK_ULONG_PTR pulSize)
 
943
{
 
944
        return CKR_FUNCTION_NOT_SUPPORTED;
 
945
}
 
946
 
 
947
CK_RV
 
948
gck_mock_C_GetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
 
949
                              CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
 
950
{
 
951
        CK_ATTRIBUTE_PTR result;
 
952
        CK_RV ret = CKR_OK;
 
953
        GckAttributes *attrs;
 
954
        const GckAttribute *attr;
 
955
        Session *session;
 
956
        CK_ULONG i;
 
957
 
 
958
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
959
        if (session == NULL)
 
960
                return CKR_SESSION_HANDLE_INVALID;
 
961
 
 
962
        attrs = lookup_object (session, hObject, NULL);
 
963
        if (!attrs)
 
964
                return CKR_OBJECT_HANDLE_INVALID;
 
965
 
 
966
        for (i = 0; i < ulCount; ++i) {
 
967
                result = pTemplate + i;
 
968
                attr = gck_attributes_find (attrs, result->type);
 
969
                if (!attr) {
 
970
                        result->ulValueLen = (CK_ULONG)-1;
 
971
                        ret = CKR_ATTRIBUTE_TYPE_INVALID;
 
972
                        continue;
 
973
                }
 
974
 
 
975
                if (!result->pValue) {
 
976
                        result->ulValueLen = attr->length;
 
977
                        continue;
 
978
                }
 
979
 
 
980
                if (result->ulValueLen >= attr->length) {
 
981
                        memcpy (result->pValue, attr->value, attr->length);
 
982
                        continue;
 
983
                }
 
984
 
 
985
                result->ulValueLen = (CK_ULONG)-1;
 
986
                ret = CKR_BUFFER_TOO_SMALL;
 
987
        }
 
988
 
 
989
        return ret;
 
990
}
 
991
 
 
992
CK_RV
 
993
gck_mock_fail_C_GetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
 
994
                                   CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
 
995
{
 
996
        return CKR_FUNCTION_FAILED;
 
997
}
 
998
 
 
999
CK_RV
 
1000
gck_mock_C_SetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
 
1001
                              CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
 
1002
{
 
1003
        Session *session;
 
1004
        GckAttributes *attrs;
 
1005
        GckAttributes *replaced;
 
1006
        GHashTable *table;
 
1007
 
 
1008
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1009
        g_return_val_if_fail (session, CKR_SESSION_HANDLE_INVALID);
 
1010
 
 
1011
        attrs = lookup_object (session, hObject, &table);
 
1012
        g_return_val_if_fail (attrs, CKR_OBJECT_HANDLE_INVALID);
 
1013
 
 
1014
        replaced = replace_attributes (attrs, pTemplate, ulCount);
 
1015
        g_hash_table_replace (table, GUINT_TO_POINTER (hObject), replaced);
 
1016
 
 
1017
        return CKR_OK;
 
1018
}
 
1019
 
 
1020
typedef struct _FindObjects {
 
1021
        CK_ATTRIBUTE_PTR template;
 
1022
        CK_ULONG count;
 
1023
        Session *session;
 
1024
} FindObjects;
 
1025
 
 
1026
static gboolean
 
1027
enumerate_and_find_objects (CK_OBJECT_HANDLE object, GckAttributes *attrs, gpointer user_data)
 
1028
{
 
1029
        FindObjects *ctx = user_data;
 
1030
        CK_ATTRIBUTE_PTR match;
 
1031
        const GckAttribute *attr;
 
1032
        CK_ULONG i;
 
1033
 
 
1034
        for (i = 0; i < ctx->count; ++i) {
 
1035
                match = ctx->template + i;
 
1036
                attr = gck_attributes_find (attrs, match->type);
 
1037
                if (!attr)
 
1038
                        return TRUE; /* Continue */
 
1039
 
 
1040
                if (attr->length != match->ulValueLen ||
 
1041
                    memcmp (attr->value, match->pValue, attr->length) != 0)
 
1042
                        return TRUE; /* Continue */
 
1043
        }
 
1044
 
 
1045
        ctx->session->matches = g_list_prepend (ctx->session->matches, GUINT_TO_POINTER (object));
 
1046
        return TRUE; /* Continue */
 
1047
}
 
1048
 
 
1049
CK_RV
 
1050
gck_mock_C_FindObjectsInit (CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
 
1051
                            CK_ULONG ulCount)
 
1052
{
 
1053
        Session *session;
 
1054
        FindObjects ctx;
 
1055
 
 
1056
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1057
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1058
 
 
1059
        /* Starting an operation, cancels any previous one */
 
1060
        if (session->operation != 0)
 
1061
                session->operation = 0;
 
1062
 
 
1063
        session->operation = OP_FIND;
 
1064
 
 
1065
        ctx.template = pTemplate;
 
1066
        ctx.count = ulCount;
 
1067
        ctx.session = session;
 
1068
 
 
1069
        gck_mock_module_enumerate_objects (hSession, enumerate_and_find_objects, &ctx);
 
1070
        return CKR_OK;
 
1071
}
 
1072
 
 
1073
CK_RV
 
1074
gck_mock_fail_C_FindObjects (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
 
1075
                             CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
 
1076
{
 
1077
        /* Always fails */
 
1078
        return CKR_FUNCTION_FAILED;
 
1079
}
 
1080
 
 
1081
CK_RV
 
1082
gck_mock_C_FindObjects (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
 
1083
                        CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
 
1084
{
 
1085
        Session *session;
 
1086
 
 
1087
        g_return_val_if_fail (phObject, CKR_ARGUMENTS_BAD);
 
1088
        g_return_val_if_fail (pulObjectCount, CKR_ARGUMENTS_BAD);
 
1089
        g_return_val_if_fail (ulMaxObjectCount != 0, CKR_ARGUMENTS_BAD);
 
1090
 
 
1091
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1092
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1093
        g_return_val_if_fail (session->operation == OP_FIND, CKR_OPERATION_NOT_INITIALIZED);
 
1094
 
 
1095
        *pulObjectCount = 0;
 
1096
        while (ulMaxObjectCount > 0 && session->matches) {
 
1097
                *phObject = GPOINTER_TO_UINT (session->matches->data);
 
1098
                ++phObject;
 
1099
                --ulMaxObjectCount;
 
1100
                ++(*pulObjectCount);
 
1101
                session->matches = g_list_remove (session->matches, session->matches->data);
 
1102
        }
 
1103
 
 
1104
        return CKR_OK;
 
1105
}
 
1106
 
 
1107
CK_RV
 
1108
gck_mock_C_FindObjectsFinal (CK_SESSION_HANDLE hSession)
 
1109
{
 
1110
 
 
1111
        Session *session;
 
1112
 
 
1113
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1114
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1115
        g_return_val_if_fail (session->operation == OP_FIND, CKR_OPERATION_NOT_INITIALIZED);
 
1116
 
 
1117
        session->operation = 0;
 
1118
        g_list_free (session->matches);
 
1119
        session->matches = NULL;
 
1120
 
 
1121
        return CKR_OK;
 
1122
}
 
1123
 
 
1124
CK_RV
 
1125
gck_mock_C_EncryptInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
 
1126
                        CK_OBJECT_HANDLE hKey)
 
1127
{
 
1128
        Session *session;
 
1129
 
 
1130
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1131
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1132
 
 
1133
        /* Starting an operation, cancels any previous one */
 
1134
        if (session->operation != 0)
 
1135
                session->operation = 0;
 
1136
 
 
1137
        g_assert (pMechanism);
 
1138
        g_assert (pMechanism->mechanism == CKM_MOCK_CAPITALIZE);
 
1139
        g_assert (hKey == PUBLIC_KEY_CAPITALIZE);
 
1140
 
 
1141
        session->operation = OP_CRYPTO;
 
1142
        session->crypto_method = CKA_ENCRYPT;
 
1143
        session->crypto_mechanism = CKM_MOCK_CAPITALIZE;
 
1144
        session->crypto_key = hKey;
 
1145
        return CKR_OK;
 
1146
}
 
1147
 
 
1148
CK_RV
 
1149
gck_mock_C_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
 
1150
                    CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
 
1151
{
 
1152
        Session *session;
 
1153
        CK_ULONG i;
 
1154
 
 
1155
        g_return_val_if_fail (pData, CKR_DATA_INVALID);
 
1156
        g_return_val_if_fail (pulEncryptedDataLen, CKR_ARGUMENTS_BAD);
 
1157
 
 
1158
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1159
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1160
        g_return_val_if_fail (session->operation == OP_CRYPTO, CKR_OPERATION_NOT_INITIALIZED);
 
1161
        g_return_val_if_fail (session->crypto_method == CKA_ENCRYPT, CKR_OPERATION_NOT_INITIALIZED);
 
1162
 
 
1163
        g_assert (session->crypto_mechanism == CKM_MOCK_CAPITALIZE);
 
1164
        g_assert (session->crypto_key == PUBLIC_KEY_CAPITALIZE);
 
1165
 
 
1166
        if (!pEncryptedData) {
 
1167
                *pulEncryptedDataLen = ulDataLen;
 
1168
                return CKR_OK;
 
1169
        }
 
1170
 
 
1171
        if (*pulEncryptedDataLen < ulDataLen) {
 
1172
                *pulEncryptedDataLen = ulDataLen;
 
1173
                return CKR_BUFFER_TOO_SMALL;
 
1174
        }
 
1175
 
 
1176
        for (i = 0; i < ulDataLen; ++i)
 
1177
                pEncryptedData[i] = g_ascii_toupper (pData[i]);
 
1178
        *pulEncryptedDataLen = ulDataLen;
 
1179
 
 
1180
        session->operation = 0;
 
1181
        session->crypto_method = 0;
 
1182
        session->crypto_mechanism = 0;
 
1183
        session->crypto_key = 0;
 
1184
 
 
1185
        return CKR_OK;
 
1186
}
 
1187
 
 
1188
CK_RV
 
1189
gck_mock_unsupported_C_EncryptUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
 
1190
                                      CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
 
1191
                                      CK_ULONG_PTR pulEncryptedPartLen)
 
1192
{
 
1193
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1194
}
 
1195
 
 
1196
CK_RV
 
1197
gck_mock_unsupported_C_EncryptFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart,
 
1198
                                     CK_ULONG_PTR pulLastEncryptedPartLen)
 
1199
{
 
1200
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1201
}
 
1202
 
 
1203
CK_RV
 
1204
gck_mock_C_DecryptInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
 
1205
                        CK_OBJECT_HANDLE hKey)
 
1206
{
 
1207
        Session *session;
 
1208
 
 
1209
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1210
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1211
 
 
1212
        /* Starting an operation, cancels any previous one */
 
1213
        if (session->operation != 0)
 
1214
                session->operation = 0;
 
1215
 
 
1216
        g_assert (pMechanism);
 
1217
        g_assert (pMechanism->mechanism == CKM_MOCK_CAPITALIZE);
 
1218
        g_assert (hKey == PRIVATE_KEY_CAPITALIZE);
 
1219
 
 
1220
        session->operation = OP_CRYPTO;
 
1221
        session->crypto_method = CKA_DECRYPT;
 
1222
        session->crypto_mechanism = CKM_MOCK_CAPITALIZE;
 
1223
        session->crypto_key = hKey;
 
1224
        return CKR_OK;
 
1225
}
 
1226
 
 
1227
CK_RV
 
1228
gck_mock_C_Decrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData,
 
1229
                    CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
 
1230
{
 
1231
        Session *session;
 
1232
        CK_ULONG i;
 
1233
 
 
1234
        g_return_val_if_fail (pEncryptedData, CKR_ENCRYPTED_DATA_INVALID);
 
1235
        g_return_val_if_fail (pulDataLen, CKR_ARGUMENTS_BAD);
 
1236
 
 
1237
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1238
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1239
        g_return_val_if_fail (session->operation == OP_CRYPTO, CKR_OPERATION_NOT_INITIALIZED);
 
1240
        g_return_val_if_fail (session->crypto_method == CKA_DECRYPT, CKR_OPERATION_NOT_INITIALIZED);
 
1241
 
 
1242
        g_assert (session->crypto_method == CKA_DECRYPT);
 
1243
        g_assert (session->crypto_mechanism == CKM_MOCK_CAPITALIZE);
 
1244
        g_assert (session->crypto_key == PRIVATE_KEY_CAPITALIZE);
 
1245
 
 
1246
        if (!pData) {
 
1247
                *pulDataLen = ulEncryptedDataLen;
 
1248
                return CKR_OK;
 
1249
        }
 
1250
 
 
1251
        if (*pulDataLen < ulEncryptedDataLen) {
 
1252
                *pulDataLen = ulEncryptedDataLen;
 
1253
                return CKR_BUFFER_TOO_SMALL;
 
1254
        }
 
1255
 
 
1256
        for (i = 0; i < ulEncryptedDataLen; ++i)
 
1257
                pData[i] = g_ascii_tolower (pEncryptedData[i]);
 
1258
        *pulDataLen = ulEncryptedDataLen;
 
1259
 
 
1260
        session->operation = 0;
 
1261
        session->crypto_method = 0;
 
1262
        session->crypto_mechanism = 0;
 
1263
        session->crypto_key = 0;
 
1264
 
 
1265
        return CKR_OK;
 
1266
}
 
1267
 
 
1268
CK_RV
 
1269
gck_mock_unsupported_C_DecryptUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart,
 
1270
                                      CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
 
1271
{
 
1272
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1273
}
 
1274
 
 
1275
CK_RV
 
1276
gck_mock_unsupported_C_DecryptFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart,
 
1277
                                     CK_ULONG_PTR pulLastPartLen)
 
1278
{
 
1279
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1280
}
 
1281
 
 
1282
CK_RV
 
1283
gck_mock_unsupported_C_DigestInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
 
1284
{
 
1285
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1286
}
 
1287
 
 
1288
CK_RV
 
1289
gck_mock_unsupported_C_Digest (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
 
1290
                               CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
 
1291
{
 
1292
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1293
}
 
1294
 
 
1295
CK_RV
 
1296
gck_mock_unsupported_C_DigestUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
 
1297
{
 
1298
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1299
}
 
1300
 
 
1301
CK_RV
 
1302
gck_mock_unsupported_C_DigestKey (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
 
1303
{
 
1304
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1305
}
 
1306
 
 
1307
CK_RV
 
1308
gck_mock_unsupported_C_DigestFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
 
1309
                                    CK_ULONG_PTR pulDigestLen)
 
1310
{
 
1311
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1312
}
 
1313
 
 
1314
CK_RV
 
1315
gck_mock_C_SignInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
 
1316
                     CK_OBJECT_HANDLE hKey)
 
1317
{
 
1318
        Session *session;
 
1319
 
 
1320
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1321
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1322
 
 
1323
        /* Starting an operation, cancels any previous one */
 
1324
        if (session->operation != 0)
 
1325
                session->operation = 0;
 
1326
 
 
1327
        g_assert (pMechanism);
 
1328
        g_assert (pMechanism->mechanism == CKM_MOCK_PREFIX);
 
1329
        g_assert (hKey == PRIVATE_KEY_PREFIX);
 
1330
 
 
1331
        session->operation = OP_CRYPTO;
 
1332
        session->crypto_method = CKA_SIGN;
 
1333
        session->crypto_mechanism = CKM_MOCK_PREFIX;
 
1334
        session->crypto_key = hKey;
 
1335
 
 
1336
        if (pMechanism->pParameter) {
 
1337
                g_assert (pMechanism->ulParameterLen < sizeof (session->sign_prefix));
 
1338
                memcpy (session->sign_prefix, pMechanism->pParameter, pMechanism->ulParameterLen);
 
1339
                session->n_sign_prefix = pMechanism->ulParameterLen;
 
1340
        } else {
 
1341
                g_assert (strlen (SIGNED_PREFIX) + 1 < sizeof (session->sign_prefix));
 
1342
                strcpy ((gchar*)session->sign_prefix, SIGNED_PREFIX);
 
1343
                session->n_sign_prefix = strlen (SIGNED_PREFIX);
 
1344
        }
 
1345
 
 
1346
        /* The private key has CKA_ALWAYS_AUTHENTICATE above */
 
1347
        session->want_context_login = CK_TRUE;
 
1348
 
 
1349
        return CKR_OK;
 
1350
}
 
1351
 
 
1352
CK_RV
 
1353
gck_mock_C_Sign (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
 
1354
                 CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
 
1355
{
 
1356
        Session *session;
 
1357
        CK_ULONG length;
 
1358
 
 
1359
        g_return_val_if_fail (pData, CKR_DATA_INVALID);
 
1360
        g_return_val_if_fail (pulSignatureLen, CKR_ARGUMENTS_BAD);
 
1361
 
 
1362
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1363
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1364
        g_return_val_if_fail (session->operation == OP_CRYPTO, CKR_OPERATION_NOT_INITIALIZED);
 
1365
        g_return_val_if_fail (session->crypto_method == CKA_SIGN, CKR_OPERATION_NOT_INITIALIZED);
 
1366
 
 
1367
        if (session->want_context_login)
 
1368
                return CKR_USER_NOT_LOGGED_IN;
 
1369
 
 
1370
        g_assert (session->crypto_method == CKA_SIGN);
 
1371
        g_assert (session->crypto_mechanism == CKM_MOCK_PREFIX);
 
1372
        g_assert (session->crypto_key == PRIVATE_KEY_PREFIX);
 
1373
 
 
1374
        length = session->n_sign_prefix + ulDataLen;
 
1375
 
 
1376
        if (!pSignature) {
 
1377
                *pulSignatureLen = length;
 
1378
                return CKR_OK;
 
1379
        }
 
1380
 
 
1381
        if (*pulSignatureLen < length) {
 
1382
                *pulSignatureLen = length;
 
1383
                return CKR_BUFFER_TOO_SMALL;
 
1384
        }
 
1385
 
 
1386
        memcpy (pSignature, session->sign_prefix, session->n_sign_prefix);
 
1387
        memcpy (pSignature + session->n_sign_prefix, pData, ulDataLen);
 
1388
        *pulSignatureLen = length;
 
1389
 
 
1390
        session->operation = 0;
 
1391
        session->crypto_method = 0;
 
1392
        session->crypto_mechanism = 0;
 
1393
        session->crypto_key = 0;
 
1394
 
 
1395
        return CKR_OK;
 
1396
}
 
1397
 
 
1398
CK_RV
 
1399
gck_mock_unsupported_C_SignUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
 
1400
{
 
1401
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1402
}
 
1403
 
 
1404
CK_RV
 
1405
gck_mock_unsupported_C_SignFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
 
1406
                                  CK_ULONG_PTR pulSignatureLen)
 
1407
{
 
1408
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1409
}
 
1410
 
 
1411
CK_RV
 
1412
gck_mock_unsupported_C_SignRecoverInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
 
1413
                                        CK_OBJECT_HANDLE hKey)
 
1414
{
 
1415
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1416
}
 
1417
 
 
1418
CK_RV
 
1419
gck_mock_unsupported_C_SignRecover (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
 
1420
                                    CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
 
1421
{
 
1422
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1423
}
 
1424
 
 
1425
CK_RV
 
1426
gck_mock_C_VerifyInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
 
1427
                       CK_OBJECT_HANDLE hKey)
 
1428
{
 
1429
        Session *session;
 
1430
 
 
1431
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1432
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1433
 
 
1434
        /* Starting an operation, cancels any previous one */
 
1435
        if (session->operation != 0)
 
1436
                session->operation = 0;
 
1437
 
 
1438
        g_assert (pMechanism);
 
1439
        g_assert (pMechanism->mechanism == CKM_MOCK_PREFIX);
 
1440
        g_assert (hKey == PUBLIC_KEY_PREFIX);
 
1441
 
 
1442
        session->operation = OP_CRYPTO;
 
1443
        session->crypto_method = CKA_VERIFY;
 
1444
        session->crypto_mechanism = CKM_MOCK_PREFIX;
 
1445
        session->crypto_key = hKey;
 
1446
 
 
1447
        if (pMechanism->pParameter) {
 
1448
                g_assert (pMechanism->ulParameterLen < sizeof (session->sign_prefix));
 
1449
                memcpy (session->sign_prefix, pMechanism->pParameter, pMechanism->ulParameterLen);
 
1450
                session->n_sign_prefix = pMechanism->ulParameterLen;
 
1451
        } else {
 
1452
                g_assert (strlen (SIGNED_PREFIX) + 1 < sizeof (session->sign_prefix));
 
1453
                strcpy ((gchar*)session->sign_prefix, SIGNED_PREFIX);
 
1454
                session->n_sign_prefix = strlen (SIGNED_PREFIX);
 
1455
        }
 
1456
 
 
1457
        return CKR_OK;
 
1458
}
 
1459
 
 
1460
CK_RV
 
1461
gck_mock_C_Verify (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
 
1462
                   CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
 
1463
{
 
1464
        Session *session;
 
1465
        CK_ULONG length;
 
1466
 
 
1467
        g_return_val_if_fail (pData, CKR_DATA_INVALID);
 
1468
        g_return_val_if_fail (pSignature, CKR_ARGUMENTS_BAD);
 
1469
 
 
1470
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1471
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1472
        g_return_val_if_fail (session->operation == OP_CRYPTO, CKR_OPERATION_NOT_INITIALIZED);
 
1473
        g_return_val_if_fail (session->crypto_method == CKA_VERIFY, CKR_OPERATION_NOT_INITIALIZED);
 
1474
 
 
1475
        g_assert (session->crypto_method == CKA_VERIFY);
 
1476
        g_assert (session->crypto_mechanism == CKM_MOCK_PREFIX);
 
1477
        g_assert (session->crypto_key == PUBLIC_KEY_PREFIX);
 
1478
 
 
1479
        length = session->n_sign_prefix + ulDataLen;
 
1480
 
 
1481
        if (ulSignatureLen < length) {
 
1482
                g_assert (FALSE);
 
1483
                return CKR_SIGNATURE_LEN_RANGE;
 
1484
        }
 
1485
 
 
1486
        if (memcmp (pSignature, session->sign_prefix, session->n_sign_prefix) == 0 &&
 
1487
            memcmp (pSignature + session->n_sign_prefix, pData, ulDataLen) == 0)
 
1488
                return CKR_OK;
 
1489
 
 
1490
        return CKR_SIGNATURE_INVALID;
 
1491
}
 
1492
 
 
1493
CK_RV
 
1494
gck_mock_unsupported_C_VerifyUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
 
1495
{
 
1496
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1497
}
 
1498
 
 
1499
CK_RV
 
1500
gck_mock_unsupported_C_VerifyFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
 
1501
                                    CK_ULONG pulSignatureLen)
 
1502
{
 
1503
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1504
}
 
1505
 
 
1506
CK_RV
 
1507
gck_mock_unsupported_C_VerifyRecoverInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
 
1508
                                          CK_OBJECT_HANDLE hKey)
 
1509
{
 
1510
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1511
}
 
1512
 
 
1513
CK_RV
 
1514
gck_mock_unsupported_C_VerifyRecover (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
 
1515
                                      CK_ULONG pulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
 
1516
{
 
1517
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1518
}
 
1519
 
 
1520
CK_RV
 
1521
gck_mock_unsupported_C_DigestEncryptUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
 
1522
                                            CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
 
1523
                                            CK_ULONG_PTR ulEncryptedPartLen)
 
1524
{
 
1525
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1526
}
 
1527
 
 
1528
CK_RV
 
1529
gck_mock_unsupported_C_DecryptDigestUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart,
 
1530
                                            CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
 
1531
                                            CK_ULONG_PTR pulPartLen)
 
1532
{
 
1533
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1534
}
 
1535
 
 
1536
CK_RV
 
1537
gck_mock_unsupported_C_SignEncryptUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
 
1538
                                          CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
 
1539
                                          CK_ULONG_PTR ulEncryptedPartLen)
 
1540
{
 
1541
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1542
}
 
1543
 
 
1544
CK_RV
 
1545
gck_mock_unsupported_C_DecryptVerifyUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart,
 
1546
                                            CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
 
1547
                                            CK_ULONG_PTR pulPartLen)
 
1548
{
 
1549
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1550
}
 
1551
 
 
1552
CK_RV
 
1553
gck_mock_unsupported_C_GenerateKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
 
1554
                                    CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
 
1555
                                    CK_OBJECT_HANDLE_PTR phKey)
 
1556
{
 
1557
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1558
}
 
1559
 
 
1560
CK_RV
 
1561
gck_mock_unsupported_C_GenerateKeyPair (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
 
1562
                                        CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
 
1563
                                        CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
 
1564
                                        CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
 
1565
{
 
1566
        GckBuilder builder;
 
1567
        GckAttributes *attrs;
 
1568
        Session *session;
 
1569
        gboolean token;
 
1570
        CK_ULONG i;
 
1571
 
 
1572
        g_return_val_if_fail (pMechanism, CKR_MECHANISM_INVALID);
 
1573
        g_return_val_if_fail (pPublicKeyTemplate, CKR_TEMPLATE_INCOMPLETE);
 
1574
        g_return_val_if_fail (ulPublicKeyAttributeCount, CKR_TEMPLATE_INCOMPLETE);
 
1575
        g_return_val_if_fail (pPrivateKeyTemplate, CKR_TEMPLATE_INCOMPLETE);
 
1576
        g_return_val_if_fail (ulPrivateKeyAttributeCount, CKR_TEMPLATE_INCOMPLETE);
 
1577
        g_return_val_if_fail (phPublicKey, CKR_ARGUMENTS_BAD);
 
1578
        g_return_val_if_fail (phPrivateKey, CKR_ARGUMENTS_BAD);
 
1579
 
 
1580
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1581
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1582
 
 
1583
        if (pMechanism->mechanism != CKM_MOCK_GENERATE)
 
1584
                return CKR_MECHANISM_INVALID;
 
1585
 
 
1586
        if (!pMechanism->pParameter || pMechanism->ulParameterLen != 9 ||
 
1587
            memcmp (pMechanism->pParameter, "generate", 9) != 0)
 
1588
                g_return_val_if_reached (CKR_MECHANISM_PARAM_INVALID);
 
1589
 
 
1590
        gck_builder_init (&builder);
 
1591
        gck_builder_add_string (&builder, CKA_VALUE, "generated");
 
1592
        for (i = 0; i < ulPublicKeyAttributeCount; ++i)
 
1593
                gck_builder_add_data (&builder, pPublicKeyTemplate[i].type,
 
1594
                                         pPublicKeyTemplate[i].pValue,
 
1595
                                         pPublicKeyTemplate[i].ulValueLen);
 
1596
        *phPublicKey = ++unique_identifier;
 
1597
        attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 
1598
        if (gck_attributes_find_boolean (attrs, CKA_TOKEN, &token) && token)
 
1599
                g_hash_table_insert (the_objects, GUINT_TO_POINTER (*phPublicKey), attrs);
 
1600
        else
 
1601
                g_hash_table_insert (session->objects, GUINT_TO_POINTER (*phPublicKey), attrs);
 
1602
 
 
1603
        gck_builder_init (&builder);
 
1604
        gck_builder_add_string (&builder, CKA_VALUE, "generated");
 
1605
        for (i = 0; i < ulPrivateKeyAttributeCount; ++i)
 
1606
                gck_builder_add_data (&builder, pPrivateKeyTemplate[i].type,
 
1607
                                         pPrivateKeyTemplate[i].pValue,
 
1608
                                         pPrivateKeyTemplate[i].ulValueLen);
 
1609
        *phPrivateKey = ++unique_identifier;
 
1610
        attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 
1611
        if (gck_attributes_find_boolean (attrs, CKA_TOKEN, &token) && token)
 
1612
                g_hash_table_insert (the_objects, GUINT_TO_POINTER (*phPrivateKey), attrs);
 
1613
        else
 
1614
                g_hash_table_insert (session->objects, GUINT_TO_POINTER (*phPrivateKey), attrs);
 
1615
        return CKR_OK;
 
1616
}
 
1617
 
 
1618
CK_RV
 
1619
gck_mock_unsupported_C_WrapKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
 
1620
                                CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey,
 
1621
                                CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen)
 
1622
{
 
1623
        GckAttributes *attrs;
 
1624
        const GckAttribute *attr;
 
1625
        Session *session;
 
1626
 
 
1627
        g_return_val_if_fail (pMechanism, CKR_MECHANISM_INVALID);
 
1628
        g_return_val_if_fail (hWrappingKey, CKR_OBJECT_HANDLE_INVALID);
 
1629
        g_return_val_if_fail (hKey, CKR_OBJECT_HANDLE_INVALID);
 
1630
        g_return_val_if_fail (pulWrappedKeyLen, CKR_WRAPPED_KEY_LEN_RANGE);
 
1631
 
 
1632
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1633
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1634
 
 
1635
        attrs = lookup_object (session, hWrappingKey, NULL);
 
1636
        g_return_val_if_fail (attrs, CKR_WRAPPING_KEY_HANDLE_INVALID);
 
1637
 
 
1638
        attrs = lookup_object (session, hKey, NULL);
 
1639
        g_return_val_if_fail (attrs, CKR_WRAPPED_KEY_INVALID);
 
1640
 
 
1641
        if (pMechanism->mechanism != CKM_MOCK_WRAP)
 
1642
                return CKR_MECHANISM_INVALID;
 
1643
 
 
1644
        if (pMechanism->pParameter) {
 
1645
                if (pMechanism->ulParameterLen != 4 ||
 
1646
                    memcmp (pMechanism->pParameter, "wrap", 4) != 0)
 
1647
                        g_return_val_if_reached (CKR_MECHANISM_PARAM_INVALID);
 
1648
        }
 
1649
 
 
1650
        attr = gck_attributes_find (attrs, CKA_VALUE);
 
1651
        if (attr == NULL)
 
1652
                return CKR_WRAPPED_KEY_INVALID;
 
1653
 
 
1654
        if (!pWrappedKey) {
 
1655
                *pulWrappedKeyLen = attr->length;
 
1656
                return CKR_OK;
 
1657
        }
 
1658
 
 
1659
        if (*pulWrappedKeyLen < attr->length) {
 
1660
                *pulWrappedKeyLen = attr->length;
 
1661
                return CKR_BUFFER_TOO_SMALL;
 
1662
        }
 
1663
 
 
1664
        memcpy (pWrappedKey, attr->value, attr->length);
 
1665
        *pulWrappedKeyLen = attr->length;
 
1666
 
 
1667
        return CKR_OK;
 
1668
}
 
1669
 
 
1670
CK_RV
 
1671
gck_mock_unsupported_C_UnwrapKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
 
1672
                                  CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey,
 
1673
                                  CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate,
 
1674
                                  CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
 
1675
{
 
1676
        GckBuilder builder;
 
1677
        GckAttributes *attrs;
 
1678
        Session *session;
 
1679
        gboolean token;
 
1680
        CK_ULONG i;
 
1681
 
 
1682
        g_return_val_if_fail (pMechanism, CKR_MECHANISM_INVALID);
 
1683
        g_return_val_if_fail (hUnwrappingKey, CKR_WRAPPING_KEY_HANDLE_INVALID);
 
1684
        g_return_val_if_fail (pWrappedKey, CKR_WRAPPED_KEY_INVALID);
 
1685
        g_return_val_if_fail (ulWrappedKeyLen, CKR_WRAPPED_KEY_LEN_RANGE);
 
1686
        g_return_val_if_fail (phKey, CKR_ARGUMENTS_BAD);
 
1687
        g_return_val_if_fail (pTemplate, CKR_TEMPLATE_INCOMPLETE);
 
1688
        g_return_val_if_fail (ulCount, CKR_TEMPLATE_INCONSISTENT);
 
1689
 
 
1690
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1691
        g_return_val_if_fail (session != NULL, CKR_SESSION_HANDLE_INVALID);
 
1692
 
 
1693
        attrs = lookup_object (session, hUnwrappingKey, NULL);
 
1694
        g_return_val_if_fail (attrs, CKR_WRAPPING_KEY_HANDLE_INVALID);
 
1695
 
 
1696
        if (pMechanism->mechanism != CKM_MOCK_WRAP)
 
1697
                return CKR_MECHANISM_INVALID;
 
1698
 
 
1699
        if (pMechanism->pParameter) {
 
1700
                if (pMechanism->ulParameterLen != 4 ||
 
1701
                    memcmp (pMechanism->pParameter, "wrap", 4) != 0)
 
1702
                        g_return_val_if_reached (CKR_MECHANISM_PARAM_INVALID);
 
1703
        }
 
1704
 
 
1705
        gck_builder_init (&builder);
 
1706
        gck_builder_add_data (&builder, CKA_VALUE, pWrappedKey, ulWrappedKeyLen);
 
1707
        for (i = 0; i < ulCount; ++i)
 
1708
                gck_builder_add_data (&builder, pTemplate[i].type,
 
1709
                                         pTemplate[i].pValue,
 
1710
                                         pTemplate[i].ulValueLen);
 
1711
        *phKey = ++unique_identifier;
 
1712
        attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 
1713
        if (gck_attributes_find_boolean (attrs, CKA_TOKEN, &token) && token)
 
1714
                g_hash_table_insert (the_objects, GUINT_TO_POINTER (*phKey), attrs);
 
1715
        else
 
1716
                g_hash_table_insert (session->objects, GUINT_TO_POINTER (*phKey), attrs);
 
1717
 
 
1718
        return CKR_OK;
 
1719
}
 
1720
 
 
1721
CK_RV
 
1722
gck_mock_unsupported_C_DeriveKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
 
1723
                                  CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
 
1724
                                  CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
 
1725
{
 
1726
        GckBuilder builder;
 
1727
        GckAttributes *attrs, *copy;
 
1728
        Session *session;
 
1729
        gboolean token;
 
1730
        CK_ULONG i;
 
1731
 
 
1732
        g_return_val_if_fail (pMechanism, CKR_MECHANISM_INVALID);
 
1733
        g_return_val_if_fail (ulCount, CKR_TEMPLATE_INCOMPLETE);
 
1734
        g_return_val_if_fail (pTemplate, CKR_TEMPLATE_INCOMPLETE);
 
1735
        g_return_val_if_fail (phKey, CKR_ARGUMENTS_BAD);
 
1736
 
 
1737
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 
1738
        g_return_val_if_fail (session, CKR_SESSION_HANDLE_INVALID);
 
1739
 
 
1740
        attrs = lookup_object (session, hBaseKey, NULL);
 
1741
        g_return_val_if_fail (attrs, CKR_KEY_HANDLE_INVALID);
 
1742
 
 
1743
        if (pMechanism->mechanism != CKM_MOCK_DERIVE)
 
1744
                return CKR_MECHANISM_INVALID;
 
1745
 
 
1746
        if (pMechanism->pParameter) {
 
1747
                if (pMechanism->ulParameterLen != 6 ||
 
1748
                    memcmp (pMechanism->pParameter, "derive", 6) != 0)
 
1749
                        g_return_val_if_reached (CKR_MECHANISM_PARAM_INVALID);
 
1750
        }
 
1751
 
 
1752
        gck_builder_init (&builder);
 
1753
        gck_builder_add_string (&builder, CKA_VALUE, "derived");
 
1754
        for (i = 0; i < ulCount; ++i)
 
1755
                gck_builder_add_data (&builder, pTemplate[i].type,
 
1756
                                      pTemplate[i].pValue,
 
1757
                                      pTemplate[i].ulValueLen);
 
1758
        gck_builder_add_all (&builder, attrs);
 
1759
        *phKey = ++unique_identifier;
 
1760
        copy = gck_attributes_ref_sink (gck_builder_end (&builder));
 
1761
        if (gck_attributes_find_boolean (copy, CKA_TOKEN, &token) && token)
 
1762
                g_hash_table_insert (the_objects, GUINT_TO_POINTER (*phKey), copy);
 
1763
        else
 
1764
                g_hash_table_insert (session->objects, GUINT_TO_POINTER (*phKey), copy);
 
1765
 
 
1766
        return CKR_OK;
 
1767
}
 
1768
 
 
1769
CK_RV
 
1770
gck_mock_unsupported_C_SeedRandom (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
 
1771
{
 
1772
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1773
}
 
1774
 
 
1775
CK_RV
 
1776
gck_mock_unsupported_C_GenerateRandom (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData,
 
1777
                           CK_ULONG ulRandomLen)
 
1778
{
 
1779
        return CKR_FUNCTION_NOT_SUPPORTED;
 
1780
}
 
1781
 
 
1782
static CK_FUNCTION_LIST functionList = {
 
1783
        { 2, 11 },      /* version */
 
1784
        gck_mock_validate_and_C_Initialize,
 
1785
        gck_mock_C_Finalize,
 
1786
        gck_mock_C_GetInfo,
 
1787
        gck_mock_C_GetFunctionList,
 
1788
        gck_mock_C_GetSlotList,
 
1789
        gck_mock_C_GetSlotInfo,
 
1790
        gck_mock_C_GetTokenInfo,
 
1791
        gck_mock_C_GetMechanismList,
 
1792
        gck_mock_C_GetMechanismInfo,
 
1793
        gck_mock_specific_args_C_InitToken,
 
1794
        gck_mock_C_InitPIN,
 
1795
        gck_mock_C_SetPIN,
 
1796
        gck_mock_C_OpenSession,
 
1797
        gck_mock_C_CloseSession,
 
1798
        gck_mock_C_CloseAllSessions,
 
1799
        gck_mock_C_GetSessionInfo,
 
1800
        gck_mock_unsupported_C_GetOperationState,
 
1801
        gck_mock_unsupported_C_SetOperationState,
 
1802
        gck_mock_C_Login,
 
1803
        gck_mock_C_Logout,
 
1804
        gck_mock_C_CreateObject,
 
1805
        gck_mock_unsupported_C_CopyObject,
 
1806
        gck_mock_C_DestroyObject,
 
1807
        gck_mock_unsupported_C_GetObjectSize,
 
1808
        gck_mock_C_GetAttributeValue,
 
1809
        gck_mock_C_SetAttributeValue,
 
1810
        gck_mock_C_FindObjectsInit,
 
1811
        gck_mock_C_FindObjects,
 
1812
        gck_mock_C_FindObjectsFinal,
 
1813
        gck_mock_C_EncryptInit,
 
1814
        gck_mock_C_Encrypt,
 
1815
        gck_mock_unsupported_C_EncryptUpdate,
 
1816
        gck_mock_unsupported_C_EncryptFinal,
 
1817
        gck_mock_C_DecryptInit,
 
1818
        gck_mock_C_Decrypt,
 
1819
        gck_mock_unsupported_C_DecryptUpdate,
 
1820
        gck_mock_unsupported_C_DecryptFinal,
 
1821
        gck_mock_unsupported_C_DigestInit,
 
1822
        gck_mock_unsupported_C_Digest,
 
1823
        gck_mock_unsupported_C_DigestUpdate,
 
1824
        gck_mock_unsupported_C_DigestKey,
 
1825
        gck_mock_unsupported_C_DigestFinal,
 
1826
        gck_mock_C_SignInit,
 
1827
        gck_mock_C_Sign,
 
1828
        gck_mock_unsupported_C_SignUpdate,
 
1829
        gck_mock_unsupported_C_SignFinal,
 
1830
        gck_mock_unsupported_C_SignRecoverInit,
 
1831
        gck_mock_unsupported_C_SignRecover,
 
1832
        gck_mock_C_VerifyInit,
 
1833
        gck_mock_C_Verify,
 
1834
        gck_mock_unsupported_C_VerifyUpdate,
 
1835
        gck_mock_unsupported_C_VerifyFinal,
 
1836
        gck_mock_unsupported_C_VerifyRecoverInit,
 
1837
        gck_mock_unsupported_C_VerifyRecover,
 
1838
        gck_mock_unsupported_C_DigestEncryptUpdate,
 
1839
        gck_mock_unsupported_C_DecryptDigestUpdate,
 
1840
        gck_mock_unsupported_C_SignEncryptUpdate,
 
1841
        gck_mock_unsupported_C_DecryptVerifyUpdate,
 
1842
        gck_mock_unsupported_C_GenerateKey,
 
1843
        gck_mock_unsupported_C_GenerateKeyPair,
 
1844
        gck_mock_unsupported_C_WrapKey,
 
1845
        gck_mock_unsupported_C_UnwrapKey,
 
1846
        gck_mock_unsupported_C_DeriveKey,
 
1847
        gck_mock_unsupported_C_SeedRandom,
 
1848
        gck_mock_unsupported_C_GenerateRandom,
 
1849
        gck_mock_C_GetFunctionStatus,
 
1850
        gck_mock_C_CancelFunction,
 
1851
        gck_mock_unsupported_C_WaitForSlotEvent
 
1852
};