]> granicus.if.org Git - p11-kit/blob - trust/module.c
trust: Ignore unreadable content in anchors
[p11-kit] / trust / module.c
1 /*
2  * Copyright (C) 2012 Red Hat Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  *     * Redistributions of source code must retain the above
9  *       copyright notice, this list of conditions and the
10  *       following disclaimer.
11  *     * Redistributions in binary form must reproduce the
12  *       above copyright notice, this list of conditions and
13  *       the following disclaimer in the documentation and/or
14  *       other materials provided with the distribution.
15  *     * The names of contributors to this software may not be
16  *       used to endorse or promote products derived from this
17  *       software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
29  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30  * DAMAGE.
31  *
32  * Author: Stef Walter <stefw@redhat.com>
33  */
34
35 #include "config.h"
36
37 #define CRYPTOKI_EXPORTS
38
39 #include "argv.h"
40 #include "array.h"
41 #include "attrs.h"
42 #define P11_DEBUG_FLAG P11_DEBUG_TRUST
43 #include "debug.h"
44 #include "dict.h"
45 #include "library.h"
46 #include "message.h"
47 #include "module.h"
48 #include "oid.h"
49 #include "parser.h"
50 #include "path.h"
51 #include "pkcs11.h"
52 #include "pkcs11x.h"
53 #include "session.h"
54 #include "token.h"
55
56 #include <assert.h>
57 #include <ctype.h>
58 #include <stdlib.h>
59 #include <string.h>
60
61 #define MANUFACTURER_ID         "PKCS#11 Kit                     "
62 #define LIBRARY_DESCRIPTION     "PKCS#11 Kit Trust Module        "
63 #define TOKEN_MODEL             "p11-kit-trust    "
64 #define TOKEN_SERIAL_NUMBER     "1                "
65
66 /* Initial slot id: non-zero and non-one */
67 #define BASE_SLOT_ID   18UL
68
69 static struct _Shared {
70         int initialized;
71         p11_dict *sessions;
72         p11_array *tokens;
73         char *paths;
74 } gl = { 0, NULL, NULL, NULL };
75
76 /* Used during FindObjects */
77 typedef struct _FindObjects {
78         CK_ATTRIBUTE *match;
79         CK_OBJECT_HANDLE *snapshot;
80         CK_ULONG iterator;
81         CK_ATTRIBUTE *public_key;
82         p11_dict *extensions;
83 } FindObjects;
84
85 static CK_FUNCTION_LIST sys_function_list;
86
87 static void
88 find_objects_free (void *data)
89 {
90         FindObjects *find = data;
91         p11_attrs_free (find->match);
92         free (find->snapshot);
93         p11_dict_free (find->extensions);
94         free (find);
95 }
96
97 static CK_RV
98 lookup_session (CK_SESSION_HANDLE handle,
99                 p11_session **session)
100 {
101         p11_session *sess;
102
103         if (!gl.sessions)
104                 return CKR_CRYPTOKI_NOT_INITIALIZED;
105
106         sess = p11_dict_get (gl.sessions, &handle);
107         if (!sess)
108                 return CKR_SESSION_HANDLE_INVALID;
109
110         if (sess && session)
111                 *session = sess;
112         return CKR_OK;
113 }
114
115 static CK_ATTRIBUTE *
116 lookup_object_inlock (p11_session *session,
117                       CK_OBJECT_HANDLE handle,
118                       p11_index **index)
119 {
120         CK_ATTRIBUTE *attrs;
121
122         assert (session != NULL);
123
124         attrs = p11_index_lookup (session->index, handle);
125         if (attrs) {
126                 if (index)
127                         *index = session->index;
128                 return attrs;
129         }
130
131         attrs = p11_index_lookup (p11_token_index (session->token), handle);
132         if (attrs) {
133                 if (index)
134                         *index = p11_token_index (session->token);
135                 return attrs;
136         }
137
138         return NULL;
139 }
140
141 static CK_RV
142 check_index_writable (p11_session *session,
143                       p11_index *index)
144 {
145         if (index == p11_token_index (session->token)) {
146                 if (!p11_token_is_writable (session->token))
147                         return CKR_TOKEN_WRITE_PROTECTED;
148                 else if (!session->read_write)
149                         return CKR_SESSION_READ_ONLY;
150         }
151
152         return CKR_OK;
153 }
154
155 static CK_RV
156 lookup_slot_inlock (CK_SLOT_ID id,
157                     p11_token **token)
158 {
159         /*
160          * These are invalid inputs, that well behaved callers should
161          * not produce, so have them fail precondations
162          */
163
164         return_val_if_fail (gl.tokens != NULL,
165                             CKR_CRYPTOKI_NOT_INITIALIZED);
166
167         return_val_if_fail (id >= BASE_SLOT_ID && id - BASE_SLOT_ID < gl.tokens->num,
168                             CKR_SLOT_ID_INVALID);
169
170         if (token)
171                 *token = gl.tokens->elem[id - BASE_SLOT_ID];
172         return CKR_OK;
173 }
174
175 static bool
176 check_slot (CK_SLOT_ID id)
177 {
178         bool ret;
179
180         p11_lock ();
181         ret = lookup_slot_inlock (id, NULL) == CKR_OK;
182         p11_unlock ();
183
184         return ret;
185 }
186
187 static bool
188 create_tokens_inlock (p11_array *tokens,
189                       const char *paths)
190 {
191         /*
192          * TRANSLATORS: These label strings are used in PKCS#11 URIs and
193          * unfortunately cannot be marked translatable. If localization is
194          * desired they should be translated in GUI applications. These
195          * strings will not change arbitrarily.
196          */
197
198         struct {
199                 const char *prefix;
200                 const char *label;
201                 int flags;
202         } labels[] = {
203                 { "~/", "User Trust", P11_TOKEN_FLAG_NONE },
204                 { P11_DEFAULT_TRUST_PREFIX, "Default Trust", P11_TOKEN_FLAG_WRITE_PROTECTED },
205                 { P11_SYSTEM_TRUST_PREFIX, "System Trust", P11_TOKEN_FLAG_NONE },
206                 { NULL },
207         };
208
209         p11_token *token;
210         p11_token *check;
211         CK_SLOT_ID slot;
212         const char *path;
213         const char *label;
214         int flags;
215         char *alloc;
216         char *remaining;
217         char *base;
218         char *pos;
219         int i;
220
221         p11_debug ("using paths: %s", paths);
222
223         alloc = remaining = strdup (paths);
224         return_val_if_fail (remaining != NULL, false);
225
226         while (remaining) {
227                 path = remaining;
228                 pos = strchr (remaining, P11_PATH_SEP_C);
229                 if (pos == NULL) {
230                         remaining = NULL;
231                 } else {
232                         pos[0] = '\0';
233                         remaining = pos + 1;
234                 }
235
236                 if (path[0] != '\0') {
237                         /* The slot for the new token */
238                         slot = BASE_SLOT_ID + tokens->num;
239
240                         label = NULL;
241                         flags = P11_TOKEN_FLAG_NONE;
242                         base = NULL;
243
244                         /* Claim the various labels based on prefix */
245                         for (i = 0; label == NULL && labels[i].prefix != NULL; i++) {
246                                 if (strncmp (path, labels[i].prefix, strlen (labels[i].prefix)) == 0) {
247                                         label = labels[i].label;
248                                         flags = labels[i].flags;
249                                         labels[i].label = NULL;
250                                 }
251                         }
252
253                         /* Didn't find a label above, then make one based on the path */
254                         if (!label) {
255                                 label = base = p11_path_base (path);
256                                 return_val_if_fail (base != NULL, false);
257                         }
258
259                         token = p11_token_new (slot, path, label, flags);
260                         return_val_if_fail (token != NULL, false);
261
262                         if (!p11_array_push (tokens, token))
263                                 return_val_if_reached (false);
264
265                         free (base);
266                         assert (lookup_slot_inlock (slot, &check) == CKR_OK && check == token);
267                 }
268         }
269
270         free (alloc);
271         return true;
272 }
273
274 static void
275 parse_argument (char *arg,
276                 void *unused)
277 {
278         char *value;
279
280         value = arg + strcspn (arg, ":=");
281         if (!*value)
282                 value = NULL;
283         else
284                 *(value++) = 0;
285
286         if (strcmp (arg, "paths") == 0) {
287                 free (gl.paths);
288                 gl.paths = value ? strdup (value) : NULL;
289
290         } else if (strcmp (arg, "verbose") == 0) {
291                 if (strcmp (value, "yes") == 0)
292                         p11_message_loud ();
293                 else if (strcmp (value, "no") == 0)
294                         p11_message_quiet ();
295         } else {
296                 p11_message ("unrecognized module argument: %s", arg);
297         }
298 }
299
300 static CK_RV
301 sys_C_Finalize (CK_VOID_PTR reserved)
302 {
303         CK_RV rv = CKR_OK;
304
305         p11_debug ("in");
306
307         /* WARNING: This function must be reentrant */
308
309         if (reserved) {
310                 rv = CKR_ARGUMENTS_BAD;
311
312         } else {
313                 p11_lock ();
314
315                         if (gl.initialized == 0) {
316                                 p11_debug ("trust module is not initialized");
317                                 rv = CKR_CRYPTOKI_NOT_INITIALIZED;
318
319                         } else if (gl.initialized == 1) {
320                                 p11_debug ("doing finalization");
321
322                                 free (gl.paths);
323                                 gl.paths = NULL;
324
325                                 p11_dict_free (gl.sessions);
326                                 gl.sessions = NULL;
327
328                                 p11_array_free (gl.tokens);
329                                 gl.tokens = NULL;
330
331                                 rv = CKR_OK;
332                                 gl.initialized = 0;
333
334                         } else {
335                                 gl.initialized--;
336                                 p11_debug ("trust module still initialized %d times", gl.initialized);
337                         }
338
339                 p11_unlock ();
340         }
341
342         p11_debug ("out: 0x%lx", rv);
343         return rv;
344 }
345
346 static CK_RV
347 sys_C_Initialize (CK_VOID_PTR init_args)
348 {
349         static const CK_C_INITIALIZE_ARGS def_args =
350                 { NULL, NULL, NULL, NULL, CKF_OS_LOCKING_OK, NULL, };
351         const CK_C_INITIALIZE_ARGS *args = NULL;
352         int supplied_ok;
353         CK_RV rv;
354
355         p11_library_init_once ();
356
357         /* WARNING: This function must be reentrant */
358
359         p11_debug ("in");
360
361         p11_lock ();
362
363                 rv = CKR_OK;
364
365                 args = init_args;
366                 if (args == NULL)
367                         args = &def_args;
368
369                 /* ALL supplied function pointers need to have the value either NULL or non-NULL. */
370                 supplied_ok = (args->CreateMutex == NULL && args->DestroyMutex == NULL &&
371                                args->LockMutex == NULL && args->UnlockMutex == NULL) ||
372                               (args->CreateMutex != NULL && args->DestroyMutex != NULL &&
373                                args->LockMutex != NULL && args->UnlockMutex != NULL);
374                 if (!supplied_ok) {
375                         p11_message ("invalid set of mutex calls supplied");
376                         rv = CKR_ARGUMENTS_BAD;
377                 }
378
379                 /*
380                  * When the CKF_OS_LOCKING_OK flag isn't set return an error.
381                  * We must be able to use our pthread functionality.
382                  */
383                 if (!(args->flags & CKF_OS_LOCKING_OK)) {
384                         p11_message ("can't do without os locking");
385                         rv = CKR_CANT_LOCK;
386                 }
387
388                 if (rv == CKR_OK && gl.initialized != 0) {
389                         p11_debug ("trust module already initialized %d times",
390                                    gl.initialized);
391
392                 /*
393                  * We support setting the socket path and other arguments from from the
394                  * pReserved pointer, similar to how NSS PKCS#11 components are initialized.
395                  */
396                 } else if (rv == CKR_OK) {
397                         p11_debug ("doing initialization");
398
399                         if (args->pReserved)
400                                 p11_argv_parse ((const char*)args->pReserved, parse_argument, NULL);
401
402                         gl.sessions = p11_dict_new (p11_dict_ulongptr_hash,
403                                                     p11_dict_ulongptr_equal,
404                                                     NULL, p11_session_free);
405
406                         gl.tokens = p11_array_new ((p11_destroyer)p11_token_free);
407                         if (gl.tokens && !create_tokens_inlock (gl.tokens, gl.paths ? gl.paths : TRUST_PATHS))
408                                 gl.tokens = NULL;
409
410                         if (gl.sessions == NULL || gl.tokens == NULL) {
411                                 warn_if_reached ();
412                                 rv = CKR_GENERAL_ERROR;
413                         }
414                 }
415
416                 gl.initialized++;
417
418         p11_unlock ();
419
420         if (rv != CKR_OK)
421                 sys_C_Finalize (NULL);
422
423         p11_debug ("out: 0x%lx", rv);
424         return rv;
425 }
426
427 static CK_RV
428 sys_C_GetInfo (CK_INFO_PTR info)
429 {
430         CK_RV rv = CKR_OK;
431
432         p11_library_init_once ();
433
434         p11_debug ("in");
435
436         return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
437
438         p11_lock ();
439
440                 if (!gl.sessions)
441                         rv = CKR_CRYPTOKI_NOT_INITIALIZED;
442
443         p11_unlock ();
444
445         if (rv == CKR_OK) {
446                 memset (info, 0, sizeof (*info));
447                 info->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
448                 info->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
449                 info->libraryVersion.major = PACKAGE_MAJOR;
450                 info->libraryVersion.minor = PACKAGE_MINOR;
451                 info->flags = 0;
452                 memcpy ((char*)info->manufacturerID, MANUFACTURER_ID, 32);
453                 memcpy ((char*)info->libraryDescription, LIBRARY_DESCRIPTION, 32);
454         }
455
456         p11_debug ("out: 0x%lx", rv);
457
458         return rv;
459 }
460
461 static CK_RV
462 sys_C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
463 {
464         /* Can be called before C_Initialize */
465         return_val_if_fail (list != NULL, CKR_ARGUMENTS_BAD);
466
467         *list = &sys_function_list;
468         return CKR_OK;
469 }
470
471 static CK_RV
472 sys_C_GetSlotList (CK_BBOOL token_present,
473                    CK_SLOT_ID_PTR slot_list,
474                    CK_ULONG_PTR count)
475 {
476         CK_RV rv = CKR_OK;
477         int i;
478
479         return_val_if_fail (count != NULL, CKR_ARGUMENTS_BAD);
480
481         p11_debug ("in");
482
483         p11_lock ();
484
485                 if (!gl.sessions)
486                         rv = CKR_CRYPTOKI_NOT_INITIALIZED;
487
488         p11_unlock ();
489
490         if (rv != CKR_OK) {
491                 /* already failed */
492
493         } else if (!slot_list) {
494                 *count = gl.tokens->num;
495                 rv = CKR_OK;
496
497         } else if (*count < gl.tokens->num) {
498                 *count = gl.tokens->num;
499                 rv = CKR_BUFFER_TOO_SMALL;
500
501         } else {
502                 for (i = 0; i < gl.tokens->num; i++)
503                         slot_list[i] = BASE_SLOT_ID + i;
504                 *count = gl.tokens->num;
505                 rv = CKR_OK;
506         }
507
508         p11_debug ("out: 0x%lx", rv);
509
510         return rv;
511 }
512
513 static CK_RV
514 sys_C_GetSlotInfo (CK_SLOT_ID id,
515                    CK_SLOT_INFO_PTR info)
516 {
517         CK_RV rv = CKR_OK;
518         p11_token *token;
519         const char *path;
520         size_t length;
521
522         return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
523
524         p11_debug ("in");
525         p11_lock ();
526
527         rv = lookup_slot_inlock (id, &token);
528         if (rv == CKR_OK) {
529                 memset (info, 0, sizeof (*info));
530                 info->firmwareVersion.major = 0;
531                 info->firmwareVersion.minor = 0;
532                 info->hardwareVersion.major = PACKAGE_MAJOR;
533                 info->hardwareVersion.minor = PACKAGE_MINOR;
534                 info->flags = CKF_TOKEN_PRESENT;
535                 memcpy ((char*)info->manufacturerID, MANUFACTURER_ID, 32);
536
537                 /* If too long, copy the first 64 characters into buffer */
538                 path = p11_token_get_path (token);
539                 length = strlen (path);
540                 if (length > sizeof (info->slotDescription))
541                         length = sizeof (info->slotDescription);
542                 memset (info->slotDescription, ' ', sizeof (info->slotDescription));
543                 memcpy (info->slotDescription, path, length);
544         }
545
546         p11_unlock ();
547         p11_debug ("out: 0x%lx", rv);
548
549         return rv;
550 }
551
552 static CK_RV
553 sys_C_GetTokenInfo (CK_SLOT_ID id,
554                     CK_TOKEN_INFO_PTR info)
555 {
556         CK_RV rv = CKR_OK;
557         p11_token *token;
558         const char *label;
559         size_t length;
560
561         return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
562
563         p11_debug ("in");
564
565         p11_lock ();
566
567         rv = lookup_slot_inlock (id, &token);
568         if (rv == CKR_OK) {
569                 memset (info, 0, sizeof (*info));
570                 info->firmwareVersion.major = 0;
571                 info->firmwareVersion.minor = 0;
572                 info->hardwareVersion.major = PACKAGE_MAJOR;
573                 info->hardwareVersion.minor = PACKAGE_MINOR;
574                 info->flags = CKF_TOKEN_INITIALIZED;
575                 memcpy ((char*)info->manufacturerID, MANUFACTURER_ID, 32);
576                 memcpy ((char*)info->model, TOKEN_MODEL, 16);
577                 memcpy ((char*)info->serialNumber, TOKEN_SERIAL_NUMBER, 16);
578                 info->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
579                 info->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
580                 info->ulMaxRwSessionCount = 0;
581                 info->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
582                 info->ulMaxPinLen = 0;
583                 info->ulMinPinLen = 0;
584                 info->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
585                 info->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
586                 info->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
587                 info->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
588
589                 /* If too long, copy the first 32 characters into buffer */
590                 label = p11_token_get_label (token);
591                 length = strlen (label);
592                 if (length > sizeof (info->label))
593                         length = sizeof (info->label);
594                 memset (info->label, ' ', sizeof (info->label));
595                 memcpy (info->label, label, length);
596
597                 if (!p11_token_is_writable (token))
598                         info->flags |= CKF_WRITE_PROTECTED;
599         }
600
601         p11_unlock ();
602         p11_debug ("out: 0x%lx", rv);
603
604         return rv;
605 }
606
607 static CK_RV
608 sys_C_GetMechanismList (CK_SLOT_ID id,
609                         CK_MECHANISM_TYPE_PTR mechanism_list,
610                         CK_ULONG_PTR count)
611 {
612         CK_RV rv = CKR_OK;
613
614         return_val_if_fail (count != NULL, CKR_ARGUMENTS_BAD);
615
616         p11_debug ("in");
617
618         *count = 0;
619
620         p11_debug ("out: 0x%lx", rv);
621         return rv;
622 }
623
624 static CK_RV
625 sys_C_GetMechanismInfo (CK_SLOT_ID id,
626                         CK_MECHANISM_TYPE type,
627                         CK_MECHANISM_INFO_PTR info)
628 {
629         return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
630         return_val_if_fail (check_slot (id), CKR_SLOT_ID_INVALID);
631         return_val_if_reached (CKR_MECHANISM_INVALID);
632 }
633
634 static CK_RV
635 sys_C_InitToken (CK_SLOT_ID id,
636                  CK_UTF8CHAR_PTR pin,
637                  CK_ULONG pin_len,
638                  CK_UTF8CHAR_PTR label)
639 {
640         p11_debug ("not supported");
641         return CKR_FUNCTION_NOT_SUPPORTED;
642 }
643
644 static CK_RV
645 sys_C_WaitForSlotEvent (CK_FLAGS flags,
646                         CK_SLOT_ID_PTR slot,
647                         CK_VOID_PTR reserved)
648 {
649         p11_debug ("not supported");
650         return CKR_FUNCTION_NOT_SUPPORTED;
651 }
652
653 static CK_RV
654 sys_C_OpenSession (CK_SLOT_ID id,
655                    CK_FLAGS flags,
656                    CK_VOID_PTR user_data,
657                    CK_NOTIFY callback,
658                    CK_SESSION_HANDLE_PTR handle)
659 {
660         p11_session *session;
661         p11_token *token;
662         CK_RV rv = CKR_OK;
663
664         return_val_if_fail (check_slot (id), CKR_SLOT_ID_INVALID);
665         return_val_if_fail (handle != NULL, CKR_ARGUMENTS_BAD);
666
667         p11_debug ("in");
668
669         p11_lock ();
670
671                 rv = lookup_slot_inlock (id, &token);
672                 if (rv != CKR_OK) {
673                         /* fail below */;
674
675                 } else if (!(flags & CKF_SERIAL_SESSION)) {
676                         rv = CKR_SESSION_PARALLEL_NOT_SUPPORTED;
677
678                 } else if ((flags & CKF_RW_SESSION) &&
679                            !p11_token_is_writable (token)) {
680                         rv = CKR_TOKEN_WRITE_PROTECTED;
681
682                 } else {
683                         session = p11_session_new (token);
684                         if (p11_dict_set (gl.sessions, &session->handle, session)) {
685                                 rv = CKR_OK;
686                                 if (flags & CKF_RW_SESSION)
687                                         session->read_write = true;
688                                 *handle = session->handle;
689                                 p11_debug ("session: %lu", *handle);
690                         } else {
691                                 warn_if_reached ();
692                                 rv = CKR_GENERAL_ERROR;
693                         }
694                 }
695
696         p11_unlock ();
697
698         p11_debug ("out: 0x%lx", rv);
699
700         return rv;
701 }
702
703 static CK_RV
704 sys_C_CloseSession (CK_SESSION_HANDLE handle)
705 {
706         CK_RV rv = CKR_OK;
707
708         p11_debug ("in");
709
710         p11_lock ();
711
712                 if (!gl.sessions) {
713                         rv = CKR_CRYPTOKI_NOT_INITIALIZED;
714
715                 } else if (p11_dict_remove (gl.sessions, &handle)) {
716                         rv = CKR_OK;
717
718                 } else {
719                         rv = CKR_SESSION_HANDLE_INVALID;
720                 }
721
722         p11_unlock ();
723
724         p11_debug ("out: 0x%lx", rv);
725
726         return rv;
727 }
728
729 static CK_RV
730 sys_C_CloseAllSessions (CK_SLOT_ID id)
731 {
732         CK_SESSION_HANDLE *handle;
733         p11_session *session;
734         p11_token *token;
735         p11_dictiter iter;
736         CK_RV rv;
737
738         p11_debug ("in");
739
740         p11_lock ();
741
742                 rv = lookup_slot_inlock (id, &token);
743                 if (rv == CKR_OK) {
744                         p11_dict_iterate (gl.sessions, &iter);
745                         while (p11_dict_next (&iter, (void **)&handle, (void **)&session)) {
746                                 if (session->token == token)
747                                         p11_dict_remove (gl.sessions, handle);
748                         }
749                 }
750
751         p11_unlock ();
752
753         p11_debug ("out: 0x%lx", rv);
754
755         return rv;
756 }
757
758 static CK_RV
759 sys_C_GetFunctionStatus (CK_SESSION_HANDLE handle)
760 {
761         return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
762 }
763
764 static CK_RV
765 sys_C_CancelFunction (CK_SESSION_HANDLE handle)
766 {
767         return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
768 }
769
770 static CK_RV
771 sys_C_GetSessionInfo (CK_SESSION_HANDLE handle,
772                       CK_SESSION_INFO_PTR info)
773 {
774         p11_session *session;
775         CK_RV rv;
776
777         return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
778
779         p11_debug ("in");
780
781         p11_lock ();
782
783                 rv = lookup_session (handle, &session);
784                 if (rv == CKR_OK) {
785                         info->flags = CKF_SERIAL_SESSION;
786                         info->state = CKS_RO_PUBLIC_SESSION;
787                         info->slotID = p11_token_get_slot (session->token);
788                         info->ulDeviceError = 0;
789                 }
790
791
792         p11_unlock ();
793
794         p11_debug ("out: 0x%lx", rv);
795
796         return rv;
797 }
798
799 static CK_RV
800 sys_C_InitPIN (CK_SESSION_HANDLE handle,
801                CK_UTF8CHAR_PTR pin,
802                CK_ULONG pin_len)
803 {
804         p11_debug ("not supported");
805         return CKR_FUNCTION_NOT_SUPPORTED;
806 }
807
808 static CK_RV
809 sys_C_SetPIN (CK_SESSION_HANDLE handle,
810               CK_UTF8CHAR_PTR old_pin,
811               CK_ULONG old_pin_len,
812               CK_UTF8CHAR_PTR new_pin,
813               CK_ULONG new_pin_len)
814 {
815         p11_debug ("not supported");
816         return CKR_FUNCTION_NOT_SUPPORTED;
817 }
818
819 static CK_RV
820 sys_C_GetOperationState (CK_SESSION_HANDLE handle,
821                          CK_BYTE_PTR operation_state,
822                          CK_ULONG_PTR operation_state_len)
823 {
824         p11_debug ("not supported");
825         return CKR_FUNCTION_NOT_SUPPORTED;
826 }
827
828 static CK_RV
829 sys_C_SetOperationState (CK_SESSION_HANDLE handle,
830                          CK_BYTE_PTR operation_state,
831                          CK_ULONG operation_state_len,
832                          CK_OBJECT_HANDLE encryption_key,
833                          CK_OBJECT_HANDLE authentication_key)
834 {
835         p11_debug ("not supported");
836         return CKR_FUNCTION_NOT_SUPPORTED;
837 }
838
839 static CK_RV
840 sys_C_Login (CK_SESSION_HANDLE handle,
841              CK_USER_TYPE user_type,
842              CK_UTF8CHAR_PTR pin,
843              CK_ULONG pin_len)
844 {
845         CK_RV rv;
846
847         p11_debug ("in");
848
849         p11_lock ();
850
851                 rv = lookup_session (handle, NULL);
852                 /* Since the trust module is designed as a replacement
853                  * of nssckbi, it works as a general access device as
854                  * described in the table 1.1 of:
855                  * <https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/PKCS11_Implement>.
856                  *
857                  * That means that the tokens provided by this module
858                  * shall be accessed without login, and if the caller
859                  * tries to login, the attempt should fail with an
860                  * explicit error (otherwise, the caller cannot
861                  * distinguish the user's login status, see also
862                  * C_Logout below). */
863                 if (rv == CKR_OK)
864                         rv = CKR_USER_TYPE_INVALID;
865
866         p11_unlock ();
867
868         p11_debug ("out: 0x%lx", rv);
869
870         return rv;
871 }
872
873 static CK_RV
874 sys_C_Logout (CK_SESSION_HANDLE handle)
875 {
876         CK_RV rv;
877
878         p11_debug ("in");
879
880         p11_lock ();
881
882                 rv = lookup_session (handle, NULL);
883                 if (rv == CKR_OK)
884                         rv = CKR_USER_NOT_LOGGED_IN;
885
886         p11_unlock ();
887
888         p11_debug ("out: 0x%lx", rv);
889
890         return rv;
891 }
892
893 static CK_RV
894 sys_C_CreateObject (CK_SESSION_HANDLE handle,
895                     CK_ATTRIBUTE_PTR template,
896                     CK_ULONG count,
897                     CK_OBJECT_HANDLE_PTR new_object)
898 {
899         p11_session *session;
900         p11_index *index;
901         CK_BBOOL val;
902         CK_RV rv;
903
904         return_val_if_fail (new_object != NULL, CKR_ARGUMENTS_BAD);
905
906         p11_debug ("in");
907
908         p11_lock ();
909
910                 rv = lookup_session (handle, &session);
911                 if (rv == CKR_OK) {
912                         if (p11_attrs_findn_bool (template, count, CKA_TOKEN, &val) && val)
913                                 index = p11_token_index (session->token);
914                         else
915                                 index = session->index;
916                         rv = check_index_writable (session, index);
917                 }
918
919                 if (rv == CKR_OK)
920                         rv = p11_index_add (index, template, count, new_object);
921
922         p11_unlock ();
923
924         p11_debug ("out: 0x%lx", rv);
925
926         return rv;
927 }
928
929 static CK_RV
930 sys_C_CopyObject (CK_SESSION_HANDLE handle,
931                   CK_OBJECT_HANDLE object,
932                   CK_ATTRIBUTE_PTR template,
933                   CK_ULONG count,
934                   CK_OBJECT_HANDLE_PTR new_object)
935 {
936         CK_BBOOL vfalse = CK_FALSE;
937         CK_ATTRIBUTE token = { CKA_TOKEN, &vfalse, sizeof (vfalse) };
938         p11_session *session;
939         CK_ATTRIBUTE *original;
940         CK_ATTRIBUTE *attrs;
941         p11_index *index;
942         CK_BBOOL val;
943         CK_RV rv;
944
945         return_val_if_fail (new_object != NULL, CKR_ARGUMENTS_BAD);
946
947         p11_debug ("in");
948
949         p11_lock ();
950
951                 rv = lookup_session (handle, &session);
952                 if (rv == CKR_OK) {
953                         original = lookup_object_inlock (session, object, &index);
954                         if (original == NULL)
955                                 rv = CKR_OBJECT_HANDLE_INVALID;
956                 }
957
958                 if (rv == CKR_OK) {
959                         if (p11_attrs_findn_bool (template, count, CKA_TOKEN, &val))
960                                 index = val ? p11_token_index (session->token) : session->index;
961                         rv = check_index_writable (session, index);
962                 }
963
964                 if (rv == CKR_OK) {
965                         attrs = p11_attrs_dup (original);
966                         attrs = p11_attrs_buildn (attrs, template, count);
967                         attrs = p11_attrs_build (attrs, &token, NULL);
968                         rv = p11_index_take (index, attrs, new_object);
969                 }
970
971         p11_unlock ();
972
973         p11_debug ("out: 0x%lx", rv);
974
975         return rv;
976 }
977
978 static CK_RV
979 sys_C_DestroyObject (CK_SESSION_HANDLE handle,
980                      CK_OBJECT_HANDLE object)
981 {
982         p11_session *session;
983         CK_ATTRIBUTE *attrs;
984         p11_index *index;
985         CK_BBOOL val;
986         CK_RV rv;
987
988         p11_debug ("in");
989
990         p11_lock ();
991
992                 rv = lookup_session (handle, &session);
993                 if (rv == CKR_OK) {
994                         attrs = lookup_object_inlock (session, object, &index);
995                         if (attrs == NULL)
996                                 rv = CKR_OBJECT_HANDLE_INVALID;
997                         else
998                                 rv = check_index_writable (session, index);
999
1000                         if (rv == CKR_OK && p11_attrs_find_bool (attrs, CKA_MODIFIABLE, &val) && !val) {
1001                                 /* TODO: This should be replaced with CKR_ACTION_PROHIBITED */
1002                                 rv = CKR_ATTRIBUTE_READ_ONLY;
1003                         }
1004
1005                         if (rv == CKR_OK)
1006                                 rv = p11_index_remove (index, object);
1007                 }
1008
1009         p11_unlock ();
1010
1011         p11_debug ("out: 0x%lx", rv);
1012
1013         return rv;
1014 }
1015
1016 static CK_RV
1017 sys_C_GetObjectSize (CK_SESSION_HANDLE handle,
1018                      CK_OBJECT_HANDLE object,
1019                      CK_ULONG_PTR size)
1020 {
1021         p11_session *session;
1022         CK_RV rv;
1023
1024         return_val_if_fail (size != NULL, CKR_ARGUMENTS_BAD);
1025
1026         p11_debug ("in");
1027
1028         p11_lock ();
1029
1030                 rv = lookup_session (handle, &session);
1031                 if (rv == CKR_OK) {
1032                         if (lookup_object_inlock (session, object, NULL)) {
1033                                 *size = CK_UNAVAILABLE_INFORMATION;
1034                                 rv = CKR_OK;
1035                         } else {
1036                                 rv = CKR_OBJECT_HANDLE_INVALID;
1037                         }
1038                 }
1039
1040         p11_unlock ();
1041
1042         p11_debug ("out: 0x%lx", rv);
1043
1044         return rv;
1045 }
1046
1047 static CK_RV
1048 sys_C_GetAttributeValue (CK_SESSION_HANDLE handle,
1049                          CK_OBJECT_HANDLE object,
1050                          CK_ATTRIBUTE_PTR template,
1051                          CK_ULONG count)
1052 {
1053         CK_ATTRIBUTE *attrs;
1054         CK_ATTRIBUTE *result;
1055         CK_ATTRIBUTE *attr;
1056         p11_session *session;
1057         char *string;
1058         CK_ULONG i;
1059         CK_RV rv;
1060
1061         p11_debug ("in: %lu, %lu", handle, object);
1062
1063         p11_lock ();
1064
1065                 rv = lookup_session (handle, &session);
1066                 if (rv == CKR_OK) {
1067                         attrs = lookup_object_inlock (session, object, NULL);
1068                         if (attrs == NULL)
1069                                 rv = CKR_OBJECT_HANDLE_INVALID;
1070                 }
1071
1072                 if (rv == CKR_OK) {
1073                         for (i = 0; i < count; i++) {
1074                                 result = template + i;
1075                                 attr = p11_attrs_find (attrs, result->type);
1076                                 if (!attr) {
1077                                         result->ulValueLen = (CK_ULONG)-1;
1078                                         rv = CKR_ATTRIBUTE_TYPE_INVALID;
1079                                         continue;
1080                                 }
1081
1082                                 if (!result->pValue) {
1083                                         result->ulValueLen = attr->ulValueLen;
1084                                         continue;
1085                                 }
1086
1087                                 if (result->ulValueLen >= attr->ulValueLen) {
1088                                         memcpy (result->pValue, attr->pValue, attr->ulValueLen);
1089                                         result->ulValueLen = attr->ulValueLen;
1090                                         continue;
1091                                 }
1092
1093                                 result->ulValueLen = (CK_ULONG)-1;
1094                                 rv = CKR_BUFFER_TOO_SMALL;
1095                         }
1096                 }
1097
1098         p11_unlock ();
1099
1100         if (p11_debugging) {
1101                 string = p11_attrs_to_string (template, count);
1102                 p11_debug ("out: 0x%lx %s", rv, string);
1103                 free (string);
1104         }
1105
1106         return rv;
1107 }
1108
1109 static CK_RV
1110 sys_C_SetAttributeValue (CK_SESSION_HANDLE handle,
1111                          CK_OBJECT_HANDLE object,
1112                          CK_ATTRIBUTE_PTR template,
1113                          CK_ULONG count)
1114 {
1115         p11_session *session;
1116         CK_ATTRIBUTE *attrs;
1117         p11_index *index;
1118         CK_BBOOL val;
1119         CK_RV rv;
1120
1121         p11_debug ("in");
1122
1123         p11_lock ();
1124
1125                 rv = lookup_session (handle, &session);
1126                 if (rv == CKR_OK) {
1127                         attrs = lookup_object_inlock (session, object, &index);
1128                         if (attrs == NULL) {
1129                                 rv = CKR_OBJECT_HANDLE_INVALID;
1130                         } else if (p11_attrs_find_bool (attrs, CKA_MODIFIABLE, &val) && !val) {
1131                                 /* TODO: This should be replaced with CKR_ACTION_PROHIBITED */
1132                                 rv = CKR_ATTRIBUTE_READ_ONLY;
1133                         }
1134
1135                         if (rv == CKR_OK)
1136                                 rv = check_index_writable (session, index);
1137
1138                         /* Reload the item if applicable */
1139                         if (rv == CKR_OK && index == p11_token_index (session->token)) {
1140                                 if (p11_token_reload (session->token, attrs)) {
1141                                         attrs = p11_index_lookup (index, object);
1142                                         if (p11_attrs_find_bool (attrs, CKA_MODIFIABLE, &val) && !val) {
1143                                                 /* TODO: This should be replaced with CKR_ACTION_PROHIBITED */
1144                                                 rv = CKR_ATTRIBUTE_READ_ONLY;
1145                                         }
1146                                 }
1147                         }
1148
1149                         if (rv == CKR_OK)
1150                                 rv = p11_index_set (index, object, template, count);
1151                 }
1152
1153         p11_unlock ();
1154
1155         p11_debug ("out: 0x%lx", rv);
1156
1157         return rv;
1158 }
1159
1160 static CK_RV
1161 sys_C_FindObjectsInit (CK_SESSION_HANDLE handle,
1162                        CK_ATTRIBUTE_PTR template,
1163                        CK_ULONG count)
1164 {
1165         p11_index *indices[2] = { NULL, NULL };
1166         CK_BBOOL want_token_objects;
1167         CK_BBOOL want_session_objects;
1168         CK_BBOOL token;
1169         FindObjects *find;
1170         p11_session *session;
1171         char *string;
1172         CK_RV rv;
1173         int n = 0;
1174         CK_OBJECT_CLASS klass;
1175
1176         if (p11_debugging) {
1177                 string = p11_attrs_to_string (template, count);
1178                 p11_debug ("in: %lu, %s", handle, string);
1179                 free (string);
1180         }
1181
1182         p11_lock ();
1183
1184                 /* Are we searching for token objects? */
1185                 if (p11_attrs_findn_bool (template, count, CKA_TOKEN, &token)) {
1186                         want_token_objects = token;
1187                         want_session_objects = !token;
1188                 } else {
1189                         want_token_objects = CK_TRUE;
1190                         want_session_objects = CK_TRUE;
1191                 }
1192
1193                 rv = lookup_session (handle, &session);
1194
1195                 /* Refresh from disk if this session hasn't yet */
1196                 if (rv == CKR_OK) {
1197                         if (want_session_objects)
1198                                 indices[n++] = session->index;
1199                         if (want_token_objects) {
1200                                 if (!session->loaded)
1201                                         p11_token_load (session->token);
1202                                 if (rv == CKR_OK) {
1203                                         session->loaded = CK_TRUE;
1204                                         indices[n++] = p11_token_index (session->token);
1205                                 }
1206                         }
1207                 }
1208
1209                 if (rv == CKR_OK) {
1210                         find = calloc (1, sizeof (FindObjects));
1211                         warn_if_fail (find != NULL);
1212
1213                         /* Make a snapshot of what we're matching */
1214                         if (find) {
1215                                 find->match = p11_attrs_buildn (NULL, template, count);
1216                                 warn_if_fail (find->match != NULL);
1217
1218                                 /* Build a session snapshot of all objects */
1219                                 find->iterator = 0;
1220                                 find->snapshot = p11_index_snapshot (indices[0], indices[1], template, count);
1221                                 warn_if_fail (find->snapshot != NULL);
1222
1223                                 if (p11_attrs_find_ulong (find->match, CKA_CLASS, &klass) &&
1224                                     klass == CKO_X_CERTIFICATE_EXTENSION) {
1225                                         find->public_key = p11_attrs_find (find->match, CKA_PUBLIC_KEY_INFO);
1226                                         find->extensions = p11_dict_new (p11_oid_hash,
1227                                                                          p11_oid_equal,
1228                                                                          free, NULL);
1229                                 }
1230                         }
1231
1232                         if (!find || !find->snapshot || !find->match)
1233                                 rv = CKR_HOST_MEMORY;
1234                         else
1235                                 p11_session_set_operation (session, find_objects_free, find);
1236                 }
1237
1238         p11_unlock ();
1239
1240         p11_debug ("out: 0x%lx", rv);
1241
1242         return rv;
1243 }
1244
1245 static bool
1246 match_for_broken_nss_serial_number_lookups (CK_ATTRIBUTE *attr,
1247                                             CK_ATTRIBUTE *match)
1248 {
1249         unsigned char der[32];
1250         unsigned char *val_val;
1251         size_t der_len;
1252         size_t val_len;
1253         int len_len;
1254
1255         if (!match->pValue || !match->ulValueLen ||
1256             match->ulValueLen == CKA_INVALID ||
1257             attr->ulValueLen == CKA_INVALID)
1258                 return false;
1259
1260         der_len = sizeof (der);
1261         der[0] = ASN1_TAG_INTEGER | ASN1_CLASS_UNIVERSAL;
1262         len_len = der_len - 1;
1263         asn1_length_der (match->ulValueLen, der + 1, &len_len);
1264         assert (len_len < (der_len - 1));
1265         der_len = 1 + len_len;
1266
1267         val_val = attr->pValue;
1268         val_len = attr->ulValueLen;
1269
1270         if (der_len + match->ulValueLen != val_len)
1271                 return false;
1272
1273         if (memcmp (der, val_val, der_len) != 0 ||
1274             memcmp (match->pValue, val_val + der_len, match->ulValueLen) != 0)
1275                 return false;
1276
1277         p11_debug ("worked around serial number lookup that's not DER encoded");
1278         return true;
1279 }
1280
1281 static bool
1282 find_objects_match (CK_ATTRIBUTE *attrs,
1283                     FindObjects *find)
1284 {
1285         CK_OBJECT_CLASS klass;
1286         CK_ATTRIBUTE *attr, *match = find->match;
1287
1288         for (; !p11_attrs_terminator (match); match++) {
1289                 attr = p11_attrs_find ((CK_ATTRIBUTE *)attrs, match->type);
1290                 if (!attr)
1291                         return false;
1292                 if (p11_attr_equal (attr, match))
1293                         continue;
1294
1295                 /*
1296                  * WORKAROUND: NSS calls us asking for CKA_SERIAL_NUMBER items that are
1297                  * not DER encoded. It shouldn't be doing this. We never return any certificate
1298                  * serial numbers that are not DER encoded.
1299                  *
1300                  * So work around the issue here while the NSS guys fix this issue.
1301                  * This code should be removed in future versions.
1302                  */
1303
1304                 if (attr->type == CKA_SERIAL_NUMBER &&
1305                     p11_attrs_find_ulong (attrs, CKA_CLASS, &klass) &&
1306                     klass == CKO_NSS_TRUST) {
1307                         if (match_for_broken_nss_serial_number_lookups (attr, match))
1308                                 continue;
1309                 }
1310
1311                 return false;
1312         }
1313
1314         /*
1315          * WORKAROUND: We keep all objects in the database, while PKIX
1316          * doesn't allow multiple extensions identified by the same
1317          * OID can be attached to a certificate.  Check any duplicate
1318          * and only return the first matching object.
1319          */
1320         if (find->public_key &&
1321             p11_attrs_find_ulong (attrs, CKA_CLASS, &klass) &&
1322             klass == CKO_X_CERTIFICATE_EXTENSION) {
1323                 CK_ATTRIBUTE *oid = p11_attrs_find (attrs, CKA_OBJECT_ID);
1324                 if (oid) {
1325                         void *value;
1326                         if (p11_oid_simple (oid->pValue, oid->ulValueLen) &&
1327                             p11_dict_get (find->extensions, oid->pValue)) {
1328                                 p11_debug ("duplicate extension object");
1329                                 return false;
1330                         }
1331                         value = memdup (oid->pValue, oid->ulValueLen);
1332                         return_val_if_fail (value != NULL, false);
1333                         if (!p11_dict_set (find->extensions, value, value))
1334                                 warn_if_reached ();
1335                 }
1336         }
1337
1338         return true;
1339 }
1340
1341 static CK_RV
1342 sys_C_FindObjects (CK_SESSION_HANDLE handle,
1343                    CK_OBJECT_HANDLE_PTR objects,
1344                    CK_ULONG max_count,
1345                    CK_ULONG_PTR count)
1346 {
1347         CK_OBJECT_HANDLE object;
1348         CK_ATTRIBUTE *attrs;
1349         FindObjects *find = NULL;
1350         p11_session *session;
1351         CK_ULONG matched;
1352         p11_index *index;
1353         CK_RV rv;
1354
1355         return_val_if_fail (count != NULL, CKR_ARGUMENTS_BAD);
1356
1357         p11_debug ("in: %lu, %lu", handle, max_count);
1358
1359         p11_lock ();
1360
1361                 rv = lookup_session (handle, &session);
1362                 if (rv == CKR_OK) {
1363                         if (session->cleanup != find_objects_free)
1364                                 rv = CKR_OPERATION_NOT_INITIALIZED;
1365                         find = session->operation;
1366                 }
1367
1368                 if (rv == CKR_OK) {
1369                         matched = 0;
1370                         while (matched < max_count) {
1371                                 object = find->snapshot[find->iterator];
1372                                 if (!object)
1373                                         break;
1374
1375                                 find->iterator++;
1376
1377                                 attrs = lookup_object_inlock (session, object, &index);
1378                                 if (attrs == NULL)
1379                                         continue;
1380
1381                                 if (find_objects_match (attrs, find)) {
1382                                         objects[matched] = object;
1383                                         matched++;
1384                                 }
1385                         }
1386
1387                         *count = matched;
1388                 }
1389
1390         p11_unlock ();
1391
1392         p11_debug ("out: 0x%lx, %lu", handle, *count);
1393
1394         return rv;
1395 }
1396
1397 static CK_RV
1398 sys_C_FindObjectsFinal (CK_SESSION_HANDLE handle)
1399 {
1400         p11_session *session;
1401         CK_RV rv;
1402
1403         p11_debug ("in");
1404
1405         p11_lock ();
1406
1407                 rv = lookup_session (handle, &session);
1408                 if (rv == CKR_OK) {
1409                         if (session->cleanup != find_objects_free)
1410                                 rv = CKR_OPERATION_NOT_INITIALIZED;
1411                         else
1412                                 p11_session_set_operation (session, NULL, NULL);
1413                 }
1414
1415         p11_unlock ();
1416
1417         p11_debug ("out: 0x%lx", rv);
1418
1419         return rv;
1420 }
1421
1422 static CK_RV
1423 sys_C_EncryptInit (CK_SESSION_HANDLE handle,
1424                    CK_MECHANISM_PTR mechanism,
1425                    CK_OBJECT_HANDLE key)
1426 {
1427         return_val_if_reached (CKR_MECHANISM_INVALID);
1428 }
1429
1430 static CK_RV
1431 sys_C_Encrypt (CK_SESSION_HANDLE handle,
1432                CK_BYTE_PTR data,
1433                CK_ULONG data_len,
1434                CK_BYTE_PTR encrypted_data,
1435                CK_ULONG_PTR encrypted_data_len)
1436 {
1437         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1438 }
1439
1440 static CK_RV
1441 sys_C_EncryptUpdate (CK_SESSION_HANDLE handle,
1442                      CK_BYTE_PTR part,
1443                      CK_ULONG part_len,
1444                      CK_BYTE_PTR encrypted_part,
1445                      CK_ULONG_PTR encrypted_part_len)
1446 {
1447         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1448 }
1449
1450 static CK_RV
1451 sys_C_EncryptFinal (CK_SESSION_HANDLE handle,
1452                     CK_BYTE_PTR last_part,
1453                     CK_ULONG_PTR last_part_len)
1454 {
1455         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1456 }
1457
1458 static CK_RV
1459 sys_C_DecryptInit (CK_SESSION_HANDLE handle,
1460                    CK_MECHANISM_PTR mechanism,
1461                    CK_OBJECT_HANDLE key)
1462 {
1463         return_val_if_reached (CKR_MECHANISM_INVALID);
1464 }
1465
1466 static CK_RV
1467 sys_C_Decrypt (CK_SESSION_HANDLE handle,
1468                CK_BYTE_PTR enc_data,
1469                CK_ULONG enc_data_len,
1470                CK_BYTE_PTR data,
1471                CK_ULONG_PTR data_len)
1472 {
1473         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1474 }
1475
1476 static CK_RV
1477 sys_C_DecryptUpdate (CK_SESSION_HANDLE handle,
1478                      CK_BYTE_PTR enc_part,
1479                      CK_ULONG enc_part_len,
1480                      CK_BYTE_PTR part,
1481                      CK_ULONG_PTR part_len)
1482 {
1483         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1484 }
1485
1486 static CK_RV
1487 sys_C_DecryptFinal (CK_SESSION_HANDLE handle,
1488                     CK_BYTE_PTR last_part,
1489                     CK_ULONG_PTR last_part_len)
1490 {
1491         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1492 }
1493
1494 static CK_RV
1495 sys_C_DigestInit (CK_SESSION_HANDLE handle,
1496                   CK_MECHANISM_PTR mechanism)
1497 {
1498         return_val_if_reached (CKR_MECHANISM_INVALID);
1499 }
1500
1501 static CK_RV
1502 sys_C_Digest (CK_SESSION_HANDLE handle,
1503               CK_BYTE_PTR data,
1504               CK_ULONG data_len,
1505               CK_BYTE_PTR digest,
1506               CK_ULONG_PTR digest_len)
1507 {
1508         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1509 }
1510
1511 static CK_RV
1512 sys_C_DigestUpdate (CK_SESSION_HANDLE handle,
1513                     CK_BYTE_PTR part,
1514                     CK_ULONG part_len)
1515 {
1516         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1517 }
1518
1519 static CK_RV
1520 sys_C_DigestKey (CK_SESSION_HANDLE handle,
1521                  CK_OBJECT_HANDLE key)
1522 {
1523         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1524 }
1525
1526 static CK_RV
1527 sys_C_DigestFinal (CK_SESSION_HANDLE handle,
1528                    CK_BYTE_PTR digest,
1529                    CK_ULONG_PTR digest_len)
1530 {
1531         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1532 }
1533
1534 static CK_RV
1535 sys_C_SignInit (CK_SESSION_HANDLE handle,
1536                 CK_MECHANISM_PTR mechanism,
1537                 CK_OBJECT_HANDLE key)
1538 {
1539         return_val_if_reached (CKR_MECHANISM_INVALID);
1540 }
1541
1542 static CK_RV
1543 sys_C_Sign (CK_SESSION_HANDLE handle,
1544             CK_BYTE_PTR data,
1545             CK_ULONG data_len,
1546             CK_BYTE_PTR signature,
1547             CK_ULONG_PTR signature_len)
1548 {
1549         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1550 }
1551
1552 static CK_RV
1553 sys_C_SignUpdate (CK_SESSION_HANDLE handle,
1554                   CK_BYTE_PTR part,
1555                   CK_ULONG part_len)
1556 {
1557         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1558 }
1559
1560 static CK_RV
1561 sys_C_SignFinal (CK_SESSION_HANDLE handle,
1562                  CK_BYTE_PTR signature,
1563                  CK_ULONG_PTR signature_len)
1564 {
1565         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1566 }
1567
1568 static CK_RV
1569 sys_C_SignRecoverInit (CK_SESSION_HANDLE handle,
1570                        CK_MECHANISM_PTR mechanism,
1571                        CK_OBJECT_HANDLE key)
1572 {
1573         return_val_if_reached (CKR_MECHANISM_INVALID);
1574 }
1575
1576 static CK_RV
1577 sys_C_SignRecover (CK_SESSION_HANDLE handle,
1578                    CK_BYTE_PTR data,
1579                    CK_ULONG data_len,
1580                    CK_BYTE_PTR signature,
1581                    CK_ULONG_PTR signature_len)
1582 {
1583         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1584 }
1585
1586 static CK_RV
1587 sys_C_VerifyInit (CK_SESSION_HANDLE handle,
1588                   CK_MECHANISM_PTR mechanism,
1589                   CK_OBJECT_HANDLE key)
1590 {
1591         return_val_if_reached (CKR_MECHANISM_INVALID);
1592 }
1593
1594 static CK_RV
1595 sys_C_Verify (CK_SESSION_HANDLE handle,
1596               CK_BYTE_PTR data,
1597               CK_ULONG data_len,
1598               CK_BYTE_PTR signature,
1599               CK_ULONG signature_len)
1600 {
1601         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1602 }
1603
1604 static CK_RV
1605 sys_C_VerifyUpdate (CK_SESSION_HANDLE handle,
1606                     CK_BYTE_PTR part,
1607                     CK_ULONG part_len)
1608 {
1609         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1610 }
1611
1612 static CK_RV
1613 sys_C_VerifyFinal (CK_SESSION_HANDLE handle,
1614                    CK_BYTE_PTR signature,
1615                    CK_ULONG signature_len)
1616 {
1617         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1618 }
1619
1620 static CK_RV
1621 sys_C_VerifyRecoverInit (CK_SESSION_HANDLE handle,
1622                          CK_MECHANISM_PTR mechanism,
1623                          CK_OBJECT_HANDLE key)
1624 {
1625         return_val_if_reached (CKR_MECHANISM_INVALID);
1626 }
1627
1628 static CK_RV
1629 sys_C_VerifyRecover (CK_SESSION_HANDLE handle,
1630                      CK_BYTE_PTR signature,
1631                      CK_ULONG signature_len,
1632                      CK_BYTE_PTR data,
1633                      CK_ULONG_PTR data_len)
1634 {
1635         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1636 }
1637
1638 static CK_RV
1639 sys_C_DigestEncryptUpdate (CK_SESSION_HANDLE handle,
1640                            CK_BYTE_PTR part,
1641                            CK_ULONG part_len,
1642                            CK_BYTE_PTR enc_part,
1643                            CK_ULONG_PTR enc_part_len)
1644 {
1645         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1646 }
1647
1648 static CK_RV
1649 sys_C_DecryptDigestUpdate (CK_SESSION_HANDLE handle,
1650                            CK_BYTE_PTR enc_part,
1651                            CK_ULONG enc_part_len,
1652                            CK_BYTE_PTR part,
1653                            CK_ULONG_PTR part_len)
1654 {
1655         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1656 }
1657
1658 static CK_RV
1659 sys_C_SignEncryptUpdate (CK_SESSION_HANDLE handle,
1660                          CK_BYTE_PTR part,
1661                          CK_ULONG part_len,
1662                          CK_BYTE_PTR enc_part,
1663                          CK_ULONG_PTR enc_part_len)
1664 {
1665         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1666 }
1667
1668 static CK_RV
1669 sys_C_DecryptVerifyUpdate (CK_SESSION_HANDLE handle,
1670                            CK_BYTE_PTR enc_part,
1671                            CK_ULONG enc_part_len,
1672                            CK_BYTE_PTR part,
1673                            CK_ULONG_PTR part_len)
1674 {
1675         return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
1676 }
1677
1678 static CK_RV
1679 sys_C_GenerateKey (CK_SESSION_HANDLE handle,
1680                    CK_MECHANISM_PTR mechanism,
1681                    CK_ATTRIBUTE_PTR template,
1682                    CK_ULONG count,
1683                    CK_OBJECT_HANDLE_PTR key)
1684 {
1685         return_val_if_reached (CKR_MECHANISM_INVALID);
1686 }
1687
1688 static CK_RV
1689 sys_C_GenerateKeyPair (CK_SESSION_HANDLE handle,
1690                        CK_MECHANISM_PTR mechanism,
1691                        CK_ATTRIBUTE_PTR pub_template,
1692                        CK_ULONG pub_count,
1693                        CK_ATTRIBUTE_PTR priv_template,
1694                        CK_ULONG priv_count,
1695                        CK_OBJECT_HANDLE_PTR pub_key,
1696                        CK_OBJECT_HANDLE_PTR priv_key)
1697 {
1698         return_val_if_reached (CKR_MECHANISM_INVALID);
1699 }
1700
1701 static CK_RV
1702 sys_C_WrapKey (CK_SESSION_HANDLE handle,
1703                CK_MECHANISM_PTR mechanism,
1704                CK_OBJECT_HANDLE wrapping_key,
1705                CK_OBJECT_HANDLE key,
1706                CK_BYTE_PTR wrapped_key,
1707                CK_ULONG_PTR wrapped_key_len)
1708 {
1709         return_val_if_reached (CKR_MECHANISM_INVALID);
1710 }
1711
1712 static CK_RV
1713 sys_C_UnwrapKey (CK_SESSION_HANDLE handle,
1714                  CK_MECHANISM_PTR mechanism,
1715                  CK_OBJECT_HANDLE unwrapping_key,
1716                  CK_BYTE_PTR wrapped_key,
1717                  CK_ULONG wrapped_key_len,
1718                  CK_ATTRIBUTE_PTR template,
1719                  CK_ULONG count,
1720                  CK_OBJECT_HANDLE_PTR key)
1721 {
1722         return_val_if_reached (CKR_MECHANISM_INVALID);
1723 }
1724
1725 static CK_RV
1726 sys_C_DeriveKey (CK_SESSION_HANDLE handle,
1727                  CK_MECHANISM_PTR mechanism,
1728                  CK_OBJECT_HANDLE base_key,
1729                  CK_ATTRIBUTE_PTR template,
1730                  CK_ULONG count,
1731                  CK_OBJECT_HANDLE_PTR key)
1732 {
1733         return_val_if_reached (CKR_MECHANISM_INVALID);
1734 }
1735
1736 static CK_RV
1737 sys_C_SeedRandom (CK_SESSION_HANDLE handle,
1738                   CK_BYTE_PTR seed,
1739                   CK_ULONG seed_len)
1740 {
1741         return_val_if_reached (CKR_RANDOM_NO_RNG);
1742 }
1743
1744 static CK_RV
1745 sys_C_GenerateRandom (CK_SESSION_HANDLE handle,
1746                       CK_BYTE_PTR random_data,
1747                       CK_ULONG random_len)
1748 {
1749         return_val_if_reached (CKR_RANDOM_NO_RNG);
1750 }
1751
1752 /* --------------------------------------------------------------------
1753  * MODULE ENTRY POINT
1754  */
1755
1756 static CK_FUNCTION_LIST sys_function_list = {
1757         { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },  /* version */
1758         sys_C_Initialize,
1759         sys_C_Finalize,
1760         sys_C_GetInfo,
1761         sys_C_GetFunctionList,
1762         sys_C_GetSlotList,
1763         sys_C_GetSlotInfo,
1764         sys_C_GetTokenInfo,
1765         sys_C_GetMechanismList,
1766         sys_C_GetMechanismInfo,
1767         sys_C_InitToken,
1768         sys_C_InitPIN,
1769         sys_C_SetPIN,
1770         sys_C_OpenSession,
1771         sys_C_CloseSession,
1772         sys_C_CloseAllSessions,
1773         sys_C_GetSessionInfo,
1774         sys_C_GetOperationState,
1775         sys_C_SetOperationState,
1776         sys_C_Login,
1777         sys_C_Logout,
1778         sys_C_CreateObject,
1779         sys_C_CopyObject,
1780         sys_C_DestroyObject,
1781         sys_C_GetObjectSize,
1782         sys_C_GetAttributeValue,
1783         sys_C_SetAttributeValue,
1784         sys_C_FindObjectsInit,
1785         sys_C_FindObjects,
1786         sys_C_FindObjectsFinal,
1787         sys_C_EncryptInit,
1788         sys_C_Encrypt,
1789         sys_C_EncryptUpdate,
1790         sys_C_EncryptFinal,
1791         sys_C_DecryptInit,
1792         sys_C_Decrypt,
1793         sys_C_DecryptUpdate,
1794         sys_C_DecryptFinal,
1795         sys_C_DigestInit,
1796         sys_C_Digest,
1797         sys_C_DigestUpdate,
1798         sys_C_DigestKey,
1799         sys_C_DigestFinal,
1800         sys_C_SignInit,
1801         sys_C_Sign,
1802         sys_C_SignUpdate,
1803         sys_C_SignFinal,
1804         sys_C_SignRecoverInit,
1805         sys_C_SignRecover,
1806         sys_C_VerifyInit,
1807         sys_C_Verify,
1808         sys_C_VerifyUpdate,
1809         sys_C_VerifyFinal,
1810         sys_C_VerifyRecoverInit,
1811         sys_C_VerifyRecover,
1812         sys_C_DigestEncryptUpdate,
1813         sys_C_DecryptDigestUpdate,
1814         sys_C_SignEncryptUpdate,
1815         sys_C_DecryptVerifyUpdate,
1816         sys_C_GenerateKey,
1817         sys_C_GenerateKeyPair,
1818         sys_C_WrapKey,
1819         sys_C_UnwrapKey,
1820         sys_C_DeriveKey,
1821         sys_C_SeedRandom,
1822         sys_C_GenerateRandom,
1823         sys_C_GetFunctionStatus,
1824         sys_C_CancelFunction,
1825         sys_C_WaitForSlotEvent
1826 };
1827
1828 #ifdef OS_WIN32
1829 __declspec(dllexport)
1830 #endif
1831
1832 CK_RV
1833 C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
1834 {
1835         p11_library_init_once ();
1836         return sys_C_GetFunctionList (list);
1837 }
1838
1839 CK_ULONG
1840 p11_module_next_id (void)
1841 {
1842         static CK_ULONG unique = 0x10;
1843         return (unique)++;
1844 }