Coverage Report

Created: 2025-08-29 06:26

/src/opensc/src/pkcs11/pkcs11-global.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * pkcs11-global.c: PKCS#11 module level functions and function table
3
 *
4
 * Copyright (C) 2002  Timo Teräs <timo.teras@iki.fi>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * 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 library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#include "config.h"
22
23
#include <stdlib.h>
24
#include <string.h>
25
#ifdef HAVE_SYS_TIME_H
26
#include <sys/time.h>
27
#endif
28
29
#ifdef PKCS11_THREAD_LOCKING
30
#if defined(HAVE_PTHREAD)
31
#include <pthread.h>
32
#elif defined(_WIN32)
33
#include <windows.h>
34
#endif
35
#endif /* PKCS11_THREAD_LOCKING */
36
37
#include "sc-pkcs11.h"
38
#include "ui/notify.h"
39
40
#ifdef ENABLE_OPENSSL
41
#include <openssl/crypto.h>
42
#include "libopensc/sc-ossl-compat.h"
43
#endif
44
#ifdef ENABLE_OPENPACE
45
#include <eac/eac.h>
46
#endif
47
48
#ifndef MODULE_APP_NAME
49
15.4k
#define MODULE_APP_NAME "opensc-pkcs11"
50
#endif
51
52
sc_context_t *context = NULL;
53
struct sc_pkcs11_config sc_pkcs11_conf;
54
list_t sessions;
55
list_t virtual_slots;
56
#if !defined(_WIN32)
57
pid_t initialized_pid = (pid_t)-1;
58
#endif
59
static int in_finalize = 0;
60
extern CK_FUNCTION_LIST pkcs11_function_list;
61
extern CK_FUNCTION_LIST_3_0 pkcs11_function_list_3_0;
62
int nesting = 0;
63
64
#ifdef PKCS11_THREAD_LOCKING
65
66
#if defined(HAVE_PTHREAD)
67
68
/* mutex used to control C_Initilize creation of mutexes */
69
static pthread_mutex_t c_initialize_m = PTHREAD_MUTEX_INITIALIZER;
70
46.4k
#define C_INITIALIZE_M_LOCK  pthread_mutex_lock(&c_initialize_m);
71
46.4k
#define C_INITIALIZE_M_UNLOCK pthread_mutex_unlock(&c_initialize_m);
72
73
CK_RV mutex_create(void **mutex)
74
0
{
75
0
  pthread_mutex_t *m;
76
77
0
  m = calloc(1, sizeof(*m));
78
0
  if (m == NULL)
79
0
    return CKR_GENERAL_ERROR;
80
0
  pthread_mutex_init(m, NULL);
81
0
  *mutex = m;
82
0
  return CKR_OK;
83
0
}
84
85
CK_RV mutex_lock(void *p)
86
0
{
87
0
  if (pthread_mutex_lock((pthread_mutex_t *) p) == 0)
88
0
    return CKR_OK;
89
0
  else
90
0
    return CKR_GENERAL_ERROR;
91
0
}
92
93
CK_RV mutex_unlock(void *p)
94
0
{
95
0
  if (pthread_mutex_unlock((pthread_mutex_t *) p) == 0)
96
0
    return CKR_OK;
97
0
  else
98
0
    return CKR_GENERAL_ERROR;
99
0
}
100
101
CK_RV mutex_destroy(void *p)
102
0
{
103
0
  pthread_mutex_destroy((pthread_mutex_t *) p);
104
0
  free(p);
105
0
  return CKR_OK;
106
0
}
107
108
static CK_C_INITIALIZE_ARGS _def_locks = {
109
  mutex_create, mutex_destroy, mutex_lock, mutex_unlock, 0, NULL };
110
#define HAVE_OS_LOCKING
111
112
#elif defined(_WIN32)
113
CRITICAL_SECTION c_initialize_cs = {0};
114
#define C_INITIALIZE_M_LOCK EnterCriticalSection(&c_initialize_cs);
115
#define C_INITIALIZE_M_UNLOCK LeaveCriticalSection(&c_initialize_cs);
116
117
CK_RV mutex_create(void **mutex)
118
{
119
  CRITICAL_SECTION *m;
120
121
  m = calloc(1, sizeof(*m));
122
  if (m == NULL)
123
    return CKR_GENERAL_ERROR;
124
  InitializeCriticalSection(m);
125
  *mutex = m;
126
  return CKR_OK;
127
}
128
129
CK_RV mutex_lock(void *p)
130
{
131
  EnterCriticalSection((CRITICAL_SECTION *) p);
132
  return CKR_OK;
133
}
134
135
136
CK_RV mutex_unlock(void *p)
137
{
138
  LeaveCriticalSection((CRITICAL_SECTION *) p);
139
  return CKR_OK;
140
}
141
142
143
CK_RV mutex_destroy(void *p)
144
{
145
  DeleteCriticalSection((CRITICAL_SECTION *) p);
146
  free(p);
147
  return CKR_OK;
148
}
149
150
static CK_C_INITIALIZE_ARGS _def_locks = {
151
  mutex_create, mutex_destroy, mutex_lock, mutex_unlock, 0, NULL };
152
#define HAVE_OS_LOCKING
153
154
#endif
155
156
#else /* PKCS11_THREAD_LOCKING */
157
#define C_INITIALIZE_M_LOCK
158
#define C_INITIALIZE_M_UNLOCK
159
160
#endif /* PKCS11_THREAD_LOCKING */
161
162
static CK_C_INITIALIZE_ARGS_PTR global_locking;
163
static CK_C_INITIALIZE_ARGS app_locking = {
164
  NULL, NULL, NULL, NULL, 0, NULL };
165
static void *global_lock = NULL;
166
#ifdef HAVE_OS_LOCKING
167
static CK_C_INITIALIZE_ARGS_PTR default_mutex_funcs = &_def_locks;
168
#else
169
static CK_C_INITIALIZE_ARGS_PTR default_mutex_funcs = NULL;
170
#endif
171
172
/* wrapper for the locking functions for libopensc */
173
static int sc_create_mutex(void **m)
174
30.9k
{
175
30.9k
  if (global_locking == NULL)
176
30.9k
    return SC_SUCCESS;
177
0
  if (global_locking->CreateMutex(m) == CKR_OK)
178
0
    return SC_SUCCESS;
179
0
  else
180
0
    return SC_ERROR_INTERNAL;
181
0
}
182
183
static int sc_lock_mutex(void *m)
184
1.12M
{
185
1.12M
  if (global_locking == NULL)
186
1.12M
    return SC_SUCCESS;
187
0
  if (global_locking->LockMutex(m) == CKR_OK)
188
0
    return SC_SUCCESS;
189
0
  else
190
0
    return SC_ERROR_INTERNAL;
191
0
}
192
193
static int sc_unlock_mutex(void *m)
194
1.12M
{
195
1.12M
  if (global_locking == NULL)
196
1.12M
    return SC_SUCCESS;
197
0
  if (global_locking->UnlockMutex(m) == CKR_OK)
198
0
    return SC_SUCCESS;
199
0
  else
200
0
    return SC_ERROR_INTERNAL;
201
202
0
}
203
204
static int sc_destroy_mutex(void *m)
205
0
{
206
0
  if (global_locking == NULL)
207
0
    return SC_SUCCESS;
208
0
  if (global_locking->DestroyMutex(m) == CKR_OK)
209
0
    return SC_SUCCESS;
210
0
  else
211
0
    return SC_ERROR_INTERNAL;
212
0
}
213
214
static sc_thread_context_t sc_thread_ctx = {
215
  0, sc_create_mutex, sc_lock_mutex,
216
  sc_unlock_mutex, sc_destroy_mutex, NULL
217
};
218
219
/* simclist helpers to locate interesting objects by ID */
220
25.2k
static int session_list_seeker(const void *el, const void *key) {
221
25.2k
  const struct sc_pkcs11_session *session = (struct sc_pkcs11_session *)el;
222
25.2k
  if ((el == NULL) || (key == NULL))
223
0
    return 0;
224
25.2k
  if (session->handle == *(CK_SESSION_HANDLE*)key)
225
25.2k
    return 1;
226
0
  return 0;
227
25.2k
}
228
28.6k
static int slot_list_seeker(const void *el, const void *key) {
229
28.6k
  const struct sc_pkcs11_slot *slot = (struct sc_pkcs11_slot *)el;
230
28.6k
  if ((el == NULL) || (key == NULL))
231
0
    return 0;
232
28.6k
  if (slot->id == *(CK_SLOT_ID *)key)
233
28.6k
    return 1;
234
0
  return 0;
235
28.6k
}
236
237
#ifndef _WIN32
238
__attribute__((constructor))
239
#endif
240
int module_init()
241
2
{
242
#ifdef _WIN32
243
  InitializeCriticalSection(&c_initialize_cs);
244
#endif
245
2
  sc_notify_init();
246
2
  return 1;
247
2
}
248
249
#ifndef _WIN32
250
__attribute__((destructor))
251
#endif
252
int module_close()
253
0
{
254
0
  sc_notify_close();
255
#if defined(ENABLE_OPENSSL) && defined(OPENSSL_SECURE_MALLOC_SIZE) && !defined(LIBRESSL_VERSION_NUMBER)
256
  CRYPTO_secure_malloc_done();
257
#endif
258
#ifdef ENABLE_OPENPACE
259
  EAC_cleanup();
260
#endif
261
#ifdef _WIN32
262
  DeleteCriticalSection(&c_initialize_cs);
263
#endif
264
0
  return 1;
265
0
}
266
267
#ifdef _WIN32
268
BOOL APIENTRY DllMain( HINSTANCE hinstDLL,
269
  DWORD  ul_reason_for_call,
270
  LPVOID lpReserved
271
)
272
{
273
  switch (ul_reason_for_call)
274
  {
275
  case DLL_PROCESS_ATTACH:
276
    if (!module_init())
277
      return FALSE;
278
    break;
279
  case DLL_PROCESS_DETACH:
280
    if (lpReserved == NULL) {
281
      if (!module_close())
282
        return FALSE;
283
    }
284
    break;
285
  }
286
  return TRUE;
287
}
288
#endif
289
290
CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
291
15.4k
{
292
15.4k
  CK_RV rv;
293
15.4k
#if !defined(_WIN32)
294
15.4k
  pid_t current_pid;
295
15.4k
#endif
296
15.4k
  int rc;
297
15.4k
  sc_context_param_t ctx_opts;
298
299
15.4k
#if !defined(_WIN32)
300
  /* Handle fork() exception */
301
15.4k
  C_INITIALIZE_M_LOCK
302
15.4k
  current_pid = getpid();
303
15.4k
  if (current_pid != initialized_pid) {
304
1
    if (context && CKR_OK == sc_pkcs11_lock()) {
305
0
      context->flags |= SC_CTX_FLAG_TERMINATE;
306
0
      sc_pkcs11_unlock();
307
0
    }
308
1
    C_Finalize(NULL_PTR);
309
1
  }
310
15.4k
  initialized_pid = current_pid;
311
15.4k
  in_finalize = 0;
312
15.4k
  C_INITIALIZE_M_UNLOCK
313
15.4k
#endif
314
315
  /* protect from nesting */
316
15.4k
  C_INITIALIZE_M_LOCK
317
15.4k
  nesting++;
318
15.4k
  if (nesting > 1) {
319
0
    nesting--;
320
0
    C_INITIALIZE_M_UNLOCK
321
0
    return CKR_GENERAL_ERROR;
322
0
  }
323
15.4k
  C_INITIALIZE_M_UNLOCK
324
  /* protect from nesting */
325
326
  /* protect from multiple threads tryng to setup locking */
327
15.4k
  C_INITIALIZE_M_LOCK
328
329
15.4k
  if (context != NULL) {
330
0
    if (CKR_OK == sc_pkcs11_lock()) {
331
0
      sc_log(context, "C_Initialize(): Cryptoki already initialized\n");
332
0
      sc_pkcs11_unlock();
333
0
    }
334
0
    nesting--;
335
0
    C_INITIALIZE_M_UNLOCK
336
0
    return CKR_CRYPTOKI_ALREADY_INITIALIZED;
337
0
  }
338
339
15.4k
  rv = sc_pkcs11_init_lock((CK_C_INITIALIZE_ARGS_PTR) pInitArgs);
340
15.4k
  if (rv != CKR_OK)
341
0
    goto out;
342
343
  /* set context options */
344
15.4k
  memset(&ctx_opts, 0, sizeof(sc_context_param_t));
345
15.4k
  ctx_opts.ver        = 0;
346
15.4k
  ctx_opts.app_name   = MODULE_APP_NAME;
347
15.4k
  ctx_opts.thread_ctx = &sc_thread_ctx;
348
349
15.4k
  rc = sc_context_create(&context, &ctx_opts);
350
15.4k
  if (rc != SC_SUCCESS) {
351
0
    rv = CKR_GENERAL_ERROR;
352
0
    goto out;
353
0
  }
354
355
  /* Load configuration */
356
15.4k
  load_pkcs11_parameters(&sc_pkcs11_conf, context);
357
358
  /* List of sessions */
359
15.4k
  if (0 != list_init(&sessions)) {
360
0
    rv = CKR_HOST_MEMORY;
361
0
    goto out;
362
0
  }
363
15.4k
  list_attributes_seeker(&sessions, session_list_seeker);
364
365
  /* List of slots */
366
15.4k
  if (0 != list_init(&virtual_slots)) {
367
0
    rv = CKR_HOST_MEMORY;
368
0
    goto out;
369
0
  }
370
15.4k
  list_attributes_seeker(&virtual_slots, slot_list_seeker);
371
372
15.4k
  card_detect_all();
373
374
15.4k
out:
375
15.4k
  if (context != NULL)
376
15.4k
    SC_LOG_RV("C_Initialize() = %s", rv);
377
378
15.4k
  if (rv != CKR_OK) {
379
0
    if (context != NULL) {
380
0
      sc_release_context(context);
381
0
      context = NULL;
382
0
    }
383
    /* Release and destroy the mutex */
384
0
    sc_pkcs11_free_lock();
385
0
  }
386
387
  /* protect from multiple threads tryng to setup locking */
388
15.4k
  nesting--;
389
15.4k
  C_INITIALIZE_M_UNLOCK
390
391
15.4k
  return rv;
392
15.4k
}
393
394
CK_RV C_Finalize(CK_VOID_PTR pReserved)
395
15.4k
{
396
15.4k
  int i;
397
15.4k
  void *p;
398
15.4k
  sc_pkcs11_slot_t *slot;
399
15.4k
  CK_RV rv;
400
401
15.4k
  if (pReserved != NULL_PTR)
402
0
    return CKR_ARGUMENTS_BAD;
403
404
15.4k
#if !defined(_WIN32)
405
15.4k
  sc_notify_close();
406
15.4k
#endif
407
408
15.4k
  if (context == NULL)
409
1
    return CKR_CRYPTOKI_NOT_INITIALIZED;
410
411
15.4k
  rv = sc_pkcs11_lock();
412
15.4k
  if (rv != CKR_OK)
413
0
    return rv;
414
415
15.4k
  sc_log(context, "C_Finalize()");
416
417
  /* cancel pending calls */
418
15.4k
  in_finalize = 1;
419
15.4k
  sc_cancel(context);
420
  /* remove all cards from readers */
421
30.9k
  for (i=0; i < (int)sc_ctx_get_reader_count(context); i++)
422
15.4k
    card_removed(sc_ctx_get_reader(context, i));
423
424
15.4k
  while ((p = list_fetch(&sessions)))
425
0
    free(p);
426
15.4k
  list_destroy(&sessions);
427
428
30.9k
  while ((slot = list_fetch(&virtual_slots))) {
429
15.4k
    list_destroy(&slot->objects);
430
15.4k
    list_destroy(&slot->logins);
431
15.4k
    free(slot);
432
15.4k
  }
433
15.4k
  list_destroy(&virtual_slots);
434
435
15.4k
  sc_release_context(context);
436
15.4k
  context = NULL;
437
438
  /* Release and destroy the mutex */
439
15.4k
  sc_pkcs11_free_lock();
440
441
15.4k
  return rv;
442
15.4k
}
443
444
CK_RV get_info_version(CK_INFO_PTR pInfo, CK_VERSION version)
445
0
{
446
0
  CK_RV rv = CKR_OK;
447
448
0
  if (pInfo == NULL_PTR)
449
0
    return CKR_ARGUMENTS_BAD;
450
451
0
  rv = sc_pkcs11_lock();
452
0
  if (rv != CKR_OK)
453
0
    return rv;
454
455
0
  sc_log(context, "C_GetInfo()");
456
457
0
  memset(pInfo, 0, sizeof(CK_INFO));
458
0
  pInfo->cryptokiVersion.major = version.major;
459
0
  pInfo->cryptokiVersion.minor = version.minor;
460
0
  strcpy_bp(pInfo->manufacturerID,
461
0
      OPENSC_VS_FF_COMPANY_NAME,
462
0
      sizeof(pInfo->manufacturerID));
463
0
  strcpy_bp(pInfo->libraryDescription,
464
0
      OPENSC_VS_FF_PRODUCT_NAME,
465
0
      sizeof(pInfo->libraryDescription));
466
0
  pInfo->libraryVersion.major = OPENSC_VERSION_MAJOR;
467
0
  pInfo->libraryVersion.minor = OPENSC_VERSION_MINOR;
468
469
0
  sc_pkcs11_unlock();
470
0
  return rv;
471
0
}
472
473
CK_RV C_GetInfoV2(CK_INFO_PTR pInfo)
474
0
{
475
0
  CK_VERSION v = {2, 20};
476
477
0
  return get_info_version(pInfo, v);
478
0
}
479
480
CK_RV C_GetInfo(CK_INFO_PTR pInfo)
481
0
{
482
0
  CK_VERSION v = {3, 0};
483
484
0
  return get_info_version(pInfo, v);
485
0
}
486
487
CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
488
0
{
489
0
  if (ppFunctionList == NULL_PTR)
490
0
    return CKR_ARGUMENTS_BAD;
491
492
0
  *ppFunctionList = &pkcs11_function_list;
493
0
  return CKR_OK;
494
0
}
495
496
CK_RV C_GetSlotList(CK_BBOOL       tokenPresent,  /* only slots with token present */
497
        CK_SLOT_ID_PTR pSlotList,     /* receives the array of slot IDs */
498
        CK_ULONG_PTR   pulCount)      /* receives the number of slots */
499
0
{
500
0
  CK_SLOT_ID_PTR found = NULL;
501
0
  unsigned int i;
502
0
  CK_ULONG numMatches;
503
0
  sc_pkcs11_slot_t *slot;
504
0
  sc_reader_t *prev_reader = NULL;
505
0
  CK_RV rv;
506
507
0
  if (pulCount == NULL_PTR)
508
0
    return CKR_ARGUMENTS_BAD;
509
510
0
  rv = sc_pkcs11_lock();
511
0
  if (rv != CKR_OK)
512
0
    return rv;
513
514
0
  sc_log(context, "C_GetSlotList(token=%d, %s)", tokenPresent,
515
0
      pSlotList==NULL_PTR? "plug-n-play":"refresh");
516
0
  DEBUG_VSS(NULL, "C_GetSlotList before ctx_detect_detect");
517
518
  /* Slot list can only change in v2.20 */
519
0
  if (pSlotList == NULL_PTR)
520
0
    sc_ctx_detect_readers(context);
521
522
0
  DEBUG_VSS(NULL, "C_GetSlotList after ctx_detect_readers");
523
524
0
  card_detect_all();
525
526
0
  if (list_empty(&virtual_slots)) {
527
0
    sc_log(context, "returned 0 slots\n");
528
0
    *pulCount = 0;
529
0
    rv = CKR_OK;
530
0
    goto out;
531
0
  }
532
533
0
  found = calloc(list_size(&virtual_slots), sizeof(CK_SLOT_ID));
534
535
0
  if (found == NULL) {
536
0
    rv = CKR_HOST_MEMORY;
537
0
    goto out;
538
0
  }
539
540
0
  prev_reader = NULL;
541
0
  numMatches = 0;
542
0
  for (i=0; i<list_size(&virtual_slots); i++) {
543
0
    slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
544
    /* the list of available slots contains:
545
     * - without token(s), at least one empty slot per reader;
546
     * - any slot with token;
547
     * - any slot that has already been seen;
548
     */
549
0
    if ((!tokenPresent &&
550
0
        (slot->reader != prev_reader ||
551
0
         slot->flags & SC_PKCS11_SLOT_FLAG_SEEN))
552
0
        || slot->slot_info.flags & CKF_TOKEN_PRESENT) {
553
0
      found[numMatches++] = slot->id;
554
0
      slot->flags |= SC_PKCS11_SLOT_FLAG_SEEN;
555
0
    }
556
0
    prev_reader = slot->reader;
557
0
  }
558
0
  DEBUG_VSS(NULL, "C_GetSlotList after card_detect_all");
559
560
0
  if (pSlotList == NULL_PTR) {
561
0
    sc_log(context, "was only a size inquiry (%lu)\n", numMatches);
562
0
    *pulCount = numMatches;
563
0
    rv = CKR_OK;
564
0
    goto out;
565
0
  }
566
0
  DEBUG_VSS(NULL, "C_GetSlotList after slot->id reassigned");
567
568
0
  if (*pulCount < numMatches) {
569
0
    sc_log(context, "buffer was too small (needed %lu)\n", numMatches);
570
0
    *pulCount = numMatches;
571
0
    rv = CKR_BUFFER_TOO_SMALL;
572
0
    goto out;
573
0
  }
574
575
0
  memcpy(pSlotList, found, numMatches * sizeof(CK_SLOT_ID));
576
0
  *pulCount = numMatches;
577
0
  rv = CKR_OK;
578
579
0
  sc_log(context, "returned %lu slots\n", numMatches);
580
0
  DEBUG_VSS(NULL, "Returning a new slot list");
581
582
0
out:
583
0
  free (found);
584
0
  sc_pkcs11_unlock();
585
0
  return rv;
586
0
}
587
588
static sc_timestamp_t get_current_time(void)
589
0
{
590
0
#if HAVE_GETTIMEOFDAY
591
0
  struct timeval tv;
592
0
  struct timezone tz;
593
0
  sc_timestamp_t curr;
594
595
0
  if (gettimeofday(&tv, &tz) != 0)
596
0
    return 0;
597
598
0
  curr = tv.tv_sec;
599
0
  curr *= 1000;
600
0
  curr += tv.tv_usec / 1000;
601
#else
602
  struct _timeb time_buf;
603
  sc_timestamp_t curr;
604
605
  _ftime(&time_buf);
606
607
  curr = time_buf.time;
608
  curr *= 1000;
609
  curr += time_buf.millitm;
610
#endif
611
612
0
  return curr;
613
0
}
614
615
CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
616
0
{
617
0
  struct sc_pkcs11_slot *slot = NULL;
618
0
  sc_timestamp_t now;
619
0
  const char *name;
620
0
  CK_RV rv;
621
622
0
  if (pInfo == NULL_PTR)
623
0
    return CKR_ARGUMENTS_BAD;
624
625
0
  rv = sc_pkcs11_lock();
626
0
  if (rv != CKR_OK)
627
0
    return rv;
628
629
0
  sc_log(context, "C_GetSlotInfo(0x%lx)", slotID);
630
631
0
  if (sc_pkcs11_conf.init_sloppy) {
632
    /* Most likely virtual_slots is empty and has not
633
     * been initialized because the caller has *not* called C_GetSlotList
634
     * before C_GetSlotInfo, as required by PKCS#11.  Initialize
635
     * virtual_slots to make things work and hope the caller knows what
636
     * it's doing... */
637
0
    card_detect_all();
638
0
  }
639
640
0
  rv = slot_get_slot(slotID, &slot);
641
0
  DEBUG_VSS(slot, "C_GetSlotInfo found");
642
0
  SC_LOG_RV("C_GetSlotInfo() get slot rv %s", rv);
643
0
  if (rv == CKR_OK) {
644
0
    if (slot->reader == NULL) {
645
0
      rv = CKR_TOKEN_NOT_PRESENT;
646
0
    } else {
647
0
      now = get_current_time();
648
0
      if (now >= slot->slot_state_expires || now == 0) {
649
        /* Update slot status */
650
0
        rv = card_detect(slot->reader);
651
0
        sc_log(context, "C_GetSlotInfo() card detect rv 0x%lX", rv);
652
653
0
        if (rv == CKR_TOKEN_NOT_RECOGNIZED || rv == CKR_OK)
654
0
          slot->slot_info.flags |= CKF_TOKEN_PRESENT;
655
656
        /* Don't ask again within the next second */
657
0
        slot->slot_state_expires = now + 1000;
658
0
      }
659
0
    }
660
0
  }
661
662
0
  if (rv == CKR_TOKEN_NOT_PRESENT || rv == CKR_TOKEN_NOT_RECOGNIZED)
663
0
    rv = CKR_OK;
664
665
0
  if (rv == CKR_OK)
666
0
    memcpy(pInfo, &slot->slot_info, sizeof(CK_SLOT_INFO));
667
668
0
  sc_log(context, "C_GetSlotInfo() flags 0x%lX", pInfo->flags);
669
670
0
  name = lookup_enum(RV_T, rv);
671
0
  if (name)
672
0
    sc_log(context, "C_GetSlotInfo(0x%lx) = %s", slotID, name);
673
0
  else
674
0
    sc_log(context, "C_GetSlotInfo(0x%lx) = 0x%08lX", slotID, rv);
675
0
  sc_pkcs11_unlock();
676
0
  return rv;
677
0
}
678
679
CK_RV C_GetMechanismList(CK_SLOT_ID slotID,
680
       CK_MECHANISM_TYPE_PTR pMechanismList,
681
                         CK_ULONG_PTR pulCount)
682
0
{
683
0
  struct sc_pkcs11_slot *slot;
684
0
  CK_RV rv;
685
686
0
  if (pulCount == NULL_PTR)
687
0
    return CKR_ARGUMENTS_BAD;
688
689
0
  rv = sc_pkcs11_lock();
690
0
  if (rv != CKR_OK)
691
0
    return rv;
692
693
0
  rv = slot_get_token(slotID, &slot);
694
0
  if (rv == CKR_OK)
695
0
    rv = sc_pkcs11_get_mechanism_list(slot->p11card, pMechanismList, pulCount);
696
697
0
  sc_pkcs11_unlock();
698
0
  return rv;
699
0
}
700
701
CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
702
       CK_MECHANISM_TYPE type,
703
       CK_MECHANISM_INFO_PTR pInfo)
704
0
{
705
0
  struct sc_pkcs11_slot *slot;
706
0
  CK_RV rv;
707
708
0
  if (pInfo == NULL_PTR)
709
0
    return CKR_ARGUMENTS_BAD;
710
711
0
  rv = sc_pkcs11_lock();
712
0
  if (rv != CKR_OK)
713
0
    return rv;
714
715
0
  rv = slot_get_token(slotID, &slot);
716
0
  if (rv == CKR_OK)
717
0
    rv = sc_pkcs11_get_mechanism_info(slot->p11card, type, pInfo);
718
719
0
  sc_pkcs11_unlock();
720
0
  return rv;
721
0
}
722
723
CK_RV C_InitToken(CK_SLOT_ID slotID,
724
      CK_CHAR_PTR pPin,
725
      CK_ULONG ulPinLen,
726
      CK_CHAR_PTR pLabel)
727
271
{
728
271
  struct sc_pkcs11_session *session;
729
271
  struct sc_pkcs11_slot *slot;
730
271
  unsigned char *label, *cpo;
731
271
  CK_RV rv;
732
271
  unsigned int i;
733
734
  /* Strip trailing whitespace and null terminate the label.
735
   * Keep the fixed-length buffer though as some other layers or drivers (SC-HSM)
736
   * might expect the length is fixed! */
737
271
  label = malloc(33);
738
271
  if (label == NULL) {
739
0
    sc_log(context, "Failed to allocate label memory");
740
0
    return CKR_HOST_MEMORY;
741
0
  }
742
271
  memcpy(label, pLabel, 32);
743
271
  label[32] = 0;
744
271
  cpo = label + 31;
745
8.30k
  while ((cpo >= label) && (*cpo == ' ')) {
746
8.03k
    *cpo = 0;
747
8.03k
    cpo--;
748
8.03k
  }
749
750
271
  sc_log(context, "C_InitToken(pLabel='%s') called", label);
751
271
  rv = sc_pkcs11_lock();
752
271
  if (rv != CKR_OK) {
753
0
    free(label);
754
0
    return rv;
755
0
  }
756
757
271
  rv = slot_get_token(slotID, &slot);
758
271
  if (rv != CKR_OK)   {
759
0
    sc_log(context, "C_InitToken() get token error 0x%lX", rv);
760
0
    goto out;
761
0
  }
762
763
271
  if (!slot->p11card || !slot->p11card->framework
764
271
       || !slot->p11card->framework->init_token) {
765
0
    sc_log(context, "C_InitToken() not supported by framework");
766
0
    rv = CKR_FUNCTION_NOT_SUPPORTED;
767
0
    goto out;
768
0
  }
769
770
  /* Make sure there's no open session for this token */
771
271
  for (i=0; i<list_size(&sessions); i++) {
772
271
    session = (struct sc_pkcs11_session*)list_get_at(&sessions, i);
773
271
    if (session->slot == slot) {
774
271
      rv = CKR_SESSION_EXISTS;
775
271
      goto out;
776
271
    }
777
271
  }
778
779
0
  rv = slot->p11card->framework->init_token(slot, slot->fw_data, pPin, ulPinLen, label);
780
0
  if (rv == CKR_OK) {
781
    /* Now we should re-bind all tokens so they get the
782
     * corresponding function vector and flags */
783
0
  }
784
785
271
out:
786
271
  sc_pkcs11_unlock();
787
271
  sc_log(context, "C_InitToken(pLabel='%s') returns 0x%lX", label, rv);
788
271
  free(label);
789
271
  return rv;
790
0
}
791
792
CK_RV C_WaitForSlotEvent(CK_FLAGS flags,   /* blocking/nonblocking flag */
793
       CK_SLOT_ID_PTR pSlot,  /* location that receives the slot ID */
794
       CK_VOID_PTR pReserved) /* reserved.  Should be NULL_PTR */
795
0
{
796
0
  sc_reader_t *found;
797
0
  unsigned int mask, events;
798
0
  void *reader_states = NULL;
799
0
  CK_SLOT_ID slot_id;
800
0
  CK_RV rv;
801
0
  int r;
802
803
0
  if (pReserved != NULL_PTR)
804
0
    return  CKR_ARGUMENTS_BAD;
805
806
0
  sc_log(context, "C_WaitForSlotEvent(block=%d)", !(flags & CKF_DONT_BLOCK));
807
0
#ifndef PCSCLITE_GOOD
808
  /* Not all pcsc-lite versions implement consistently used functions as they are */
809
0
  if (!(flags & CKF_DONT_BLOCK))
810
0
    return CKR_FUNCTION_NOT_SUPPORTED;
811
0
#endif /* PCSCLITE_GOOD */
812
0
  rv = sc_pkcs11_lock();
813
0
  if (rv != CKR_OK)
814
0
    return rv;
815
816
0
  mask = SC_EVENT_CARD_EVENTS | SC_EVENT_READER_EVENTS;
817
  /* Detect and add new slots for added readers v2.20 */
818
819
0
  rv = slot_find_changed(&slot_id, mask);
820
0
  if ((rv == CKR_OK) || (flags & CKF_DONT_BLOCK))
821
0
    goto out;
822
823
0
again:
824
0
  sc_log(context, "C_WaitForSlotEvent() reader_states:%p", reader_states);
825
0
  sc_pkcs11_unlock();
826
0
  r = sc_wait_for_event(context, mask, &found, &events, -1, &reader_states);
827
  /* Was C_Finalize called ? */
828
0
  if (in_finalize == 1)
829
0
    return CKR_CRYPTOKI_NOT_INITIALIZED;
830
831
0
  if ((rv = sc_pkcs11_lock()) != CKR_OK)
832
0
    return rv;
833
834
0
  if (r != SC_SUCCESS) {
835
0
    sc_log(context, "sc_wait_for_event() returned %d\n",  r);
836
0
    rv = sc_to_cryptoki_error(r, "C_WaitForSlotEvent");
837
0
    goto out;
838
0
  }
839
840
  /* If no changed slot was found (maybe an unsupported card
841
   * was inserted/removed) then go waiting again */
842
0
  rv = slot_find_changed(&slot_id, mask);
843
0
  if (rv != CKR_OK)
844
0
    goto again;
845
846
0
out:
847
0
  if (pSlot)
848
0
    *pSlot = slot_id;
849
850
  /* Free allocated readers states holder */
851
0
  if (reader_states)   {
852
0
    sc_log(context, "free reader states");
853
0
    sc_wait_for_event(context, 0, NULL, NULL, -1, &reader_states);
854
0
  }
855
856
0
  SC_LOG_RV("C_WaitForSlotEvent() = %s", rv);
857
0
  sc_pkcs11_unlock();
858
0
  return rv;
859
0
}
860
861
/*
862
 * Interfaces
863
 */
864
0
#define NUM_INTERFACES 2
865
0
#define DEFAULT_INTERFACE 0
866
// clang-format off
867
CK_INTERFACE interfaces[NUM_INTERFACES] = {
868
  {"PKCS 11", (void *)&pkcs11_function_list_3_0, 0},
869
  {"PKCS 11", (void *)&pkcs11_function_list, 0}
870
};
871
// clang-format on
872
873
CK_RV C_GetInterfaceList(CK_INTERFACE_PTR pInterfacesList,  /* returned interfaces */
874
       CK_ULONG_PTR pulCount)         /* number of interfaces returned */
875
0
{
876
0
  sc_log(context, "C_GetInterfaceList()");
877
878
0
  if (pulCount == NULL_PTR)
879
0
    return CKR_ARGUMENTS_BAD;
880
881
0
  if (pInterfacesList == NULL_PTR) {
882
0
    *pulCount = NUM_INTERFACES;
883
0
    sc_log(context, "was only a size inquiry (%lu)\n", *pulCount);
884
0
    return CKR_OK;
885
0
  }
886
887
0
  if (*pulCount < NUM_INTERFACES) {
888
0
    sc_log(context, "buffer was too small (needed %d)\n", NUM_INTERFACES);
889
0
    *pulCount = NUM_INTERFACES;
890
0
    return CKR_BUFFER_TOO_SMALL;
891
0
  }
892
893
0
  memcpy(pInterfacesList, interfaces, NUM_INTERFACES * sizeof(CK_INTERFACE));
894
0
  *pulCount = NUM_INTERFACES;
895
896
0
  sc_log(context, "returned %lu interfaces\n", *pulCount);
897
0
  return CKR_OK;
898
0
}
899
900
CK_RV C_GetInterface(CK_UTF8CHAR_PTR pInterfaceName, /* name of the interface */
901
                     CK_VERSION_PTR pVersion,       /* version of the interface */
902
                     CK_INTERFACE_PTR_PTR ppInterface,    /* returned interface */
903
                     CK_FLAGS flags)           /* flags controlling the semantics
904
            * of the interface */
905
0
{
906
0
  int i;
907
908
0
  sc_log(context, "C_GetInterface(%s)",
909
0
    pInterfaceName == NULL_PTR ? "<default>" : (char *)pInterfaceName);
910
911
0
  if (ppInterface == NULL) {
912
0
    return CKR_ARGUMENTS_BAD;
913
0
  }
914
915
0
  if (pInterfaceName == NULL_PTR) {
916
    /* return default interface */
917
0
    *ppInterface = &interfaces[DEFAULT_INTERFACE];
918
0
    sc_log(context, "Returning default interface\n");
919
0
    return CKR_OK;
920
0
  }
921
922
0
  for (i = 0; i < NUM_INTERFACES; i++) {
923
0
    CK_VERSION_PTR interface_version = (CK_VERSION_PTR)interfaces[i].pFunctionList;
924
925
    /* The interface name is not null here */
926
0
    if (strcmp((char *)pInterfaceName, interfaces[i].pInterfaceName) != 0) {
927
0
      continue;
928
0
    }
929
    /* If version is not null, it must match */
930
0
    if (pVersion != NULL_PTR && (pVersion->major != interface_version->major ||
931
0
        pVersion->minor != interface_version->minor)) {
932
0
      continue;
933
0
    }
934
    /* If any flags specified, it must be supported by the interface */
935
0
    if ((flags & interfaces[i].flags) != flags) {
936
0
      continue;
937
0
    }
938
0
    *ppInterface = &interfaces[i];
939
0
    sc_log(context, "Returning interface %s\n", (*ppInterface)->pInterfaceName);
940
0
    return CKR_OK;
941
0
  }
942
0
  sc_log(context, "Interface not found: %s, version=%d.%d, flags=%lu\n",
943
0
    pInterfaceName ? (char *)pInterfaceName : "<null>",
944
0
    pVersion ? (*pVersion).major : 0,
945
0
    pVersion ? (*pVersion).minor : 0,
946
0
    flags);
947
948
0
  return CKR_ARGUMENTS_BAD;
949
0
}
950
951
/*
952
 * Locking functions
953
 */
954
955
CK_RV
956
sc_pkcs11_init_lock(CK_C_INITIALIZE_ARGS_PTR args)
957
15.4k
{
958
15.4k
  CK_RV rv = CKR_OK;
959
960
15.4k
  int applock = 0;
961
15.4k
  int oslock = 0;
962
15.4k
  if (global_lock)
963
0
    return CKR_OK;
964
965
  /* No CK_C_INITIALIZE_ARGS pointer, no locking */
966
15.4k
  if (!args)
967
15.4k
    return CKR_OK;
968
969
0
  if (args->pReserved != NULL_PTR)
970
0
    return CKR_ARGUMENTS_BAD;
971
972
0
  app_locking = *args;
973
974
  /* If the app tells us OS locking is okay,
975
   * use that. Otherwise use the supplied functions.
976
   */
977
0
  global_locking = NULL;
978
0
  if (args->CreateMutex && args->DestroyMutex &&
979
0
       args->LockMutex   && args->UnlockMutex) {
980
0
      applock = 1;
981
0
  }
982
0
  if ((args->flags & CKF_OS_LOCKING_OK)) {
983
0
    oslock = 1;
984
0
  }
985
986
  /* Based on PKCS#11 v2.11 11.4 */
987
0
  if (applock && oslock) {
988
    /* Shall be used in threaded environment, prefer app provided locking */
989
0
    global_locking = &app_locking;
990
0
  } else if (!applock && oslock) {
991
    /* Shall be used in threaded environment, must use operating system locking */
992
0
    global_locking = default_mutex_funcs;
993
0
  } else if (applock && !oslock) {
994
    /* Shall be used in threaded environment, must use app provided locking */
995
0
    global_locking = &app_locking;
996
0
  } else if (!applock && !oslock) {
997
    /* Shall not be used in threaded environment, use operating system locking */
998
0
    global_locking = default_mutex_funcs;
999
0
  }
1000
1001
0
  if (global_locking != NULL) {
1002
    /* create mutex */
1003
0
    rv = global_locking->CreateMutex(&global_lock);
1004
0
  }
1005
1006
0
  return rv;
1007
0
}
1008
1009
CK_RV sc_pkcs11_lock(void)
1010
55.1k
{
1011
55.1k
  if (context == NULL)
1012
0
    return CKR_CRYPTOKI_NOT_INITIALIZED;
1013
1014
55.1k
  if (!global_lock)
1015
55.1k
    return CKR_OK;
1016
0
  if (global_locking)  {
1017
0
    while (global_locking->LockMutex(global_lock) != CKR_OK)
1018
0
      ;
1019
0
  }
1020
1021
0
  return CKR_OK;
1022
55.1k
}
1023
1024
static void
1025
__sc_pkcs11_unlock(void *lock)
1026
39.6k
{
1027
39.6k
  if (!lock)
1028
39.6k
    return;
1029
0
  if (global_locking) {
1030
0
    while (global_locking->UnlockMutex(lock) != CKR_OK)
1031
0
      ;
1032
0
  }
1033
0
}
1034
1035
void sc_pkcs11_unlock(void)
1036
39.6k
{
1037
39.6k
  __sc_pkcs11_unlock(global_lock);
1038
39.6k
}
1039
1040
/*
1041
 * Free the lock - note the lock must be held when
1042
 * you come here
1043
 */
1044
void sc_pkcs11_free_lock(void)
1045
15.4k
{
1046
15.4k
  void  *tempLock;
1047
1048
15.4k
  if (!(tempLock = global_lock))
1049
15.4k
    return;
1050
1051
  /* Clear the global lock pointer - once we've
1052
   * unlocked the mutex it's as good as gone */
1053
0
  global_lock = NULL;
1054
1055
  /* Now unlock. On SMP machines the synchronization
1056
   * primitives should take care of flushing out
1057
   * all changed data to RAM */
1058
0
  __sc_pkcs11_unlock(tempLock);
1059
1060
0
  if (global_locking)
1061
0
    global_locking->DestroyMutex(tempLock);
1062
0
  global_locking = NULL;
1063
0
}
1064
1065
CK_FUNCTION_LIST pkcs11_function_list = {
1066
  { 2, 20 }, /* Note: NSS/Firefox ignores this version number and uses C_GetInfo() */
1067
  C_Initialize,
1068
  C_Finalize,
1069
  C_GetInfoV2,
1070
  C_GetFunctionList,
1071
  C_GetSlotList,
1072
  C_GetSlotInfo,
1073
  C_GetTokenInfo,
1074
  C_GetMechanismList,
1075
  C_GetMechanismInfo,
1076
  C_InitToken,
1077
  C_InitPIN,
1078
  C_SetPIN,
1079
  C_OpenSession,
1080
  C_CloseSession,
1081
  C_CloseAllSessions,
1082
  C_GetSessionInfo,
1083
  C_GetOperationState,
1084
  C_SetOperationState,
1085
  C_Login,
1086
  C_Logout,
1087
  C_CreateObject,
1088
  C_CopyObject,
1089
  C_DestroyObject,
1090
  C_GetObjectSize,
1091
  C_GetAttributeValue,
1092
  C_SetAttributeValue,
1093
  C_FindObjectsInit,
1094
  C_FindObjects,
1095
  C_FindObjectsFinal,
1096
  C_EncryptInit,
1097
  C_Encrypt,
1098
  C_EncryptUpdate,
1099
  C_EncryptFinal,
1100
  C_DecryptInit,
1101
  C_Decrypt,
1102
  C_DecryptUpdate,
1103
  C_DecryptFinal,
1104
  C_DigestInit,
1105
  C_Digest,
1106
  C_DigestUpdate,
1107
  C_DigestKey,
1108
  C_DigestFinal,
1109
  C_SignInit,
1110
  C_Sign,
1111
  C_SignUpdate,
1112
  C_SignFinal,
1113
  C_SignRecoverInit,
1114
  C_SignRecover,
1115
  C_VerifyInit,
1116
  C_Verify,
1117
  C_VerifyUpdate,
1118
  C_VerifyFinal,
1119
  C_VerifyRecoverInit,
1120
  C_VerifyRecover,
1121
  C_DigestEncryptUpdate,
1122
  C_DecryptDigestUpdate,
1123
  C_SignEncryptUpdate,
1124
  C_DecryptVerifyUpdate,
1125
  C_GenerateKey,
1126
  C_GenerateKeyPair,
1127
  C_WrapKey,
1128
  C_UnwrapKey,
1129
  C_DeriveKey,
1130
  C_SeedRandom,
1131
  C_GenerateRandom,
1132
  C_GetFunctionStatus,
1133
  C_CancelFunction,
1134
  C_WaitForSlotEvent
1135
};
1136
1137
/* Returned from getInterface */
1138
CK_FUNCTION_LIST_3_0 pkcs11_function_list_3_0 = {
1139
  { 3, 0 },
1140
  C_Initialize,
1141
  C_Finalize,
1142
  C_GetInfo,
1143
  C_GetFunctionList,
1144
  C_GetSlotList,
1145
  C_GetSlotInfo,
1146
  C_GetTokenInfo,
1147
  C_GetMechanismList,
1148
  C_GetMechanismInfo,
1149
  C_InitToken,
1150
  C_InitPIN,
1151
  C_SetPIN,
1152
  C_OpenSession,
1153
  C_CloseSession,
1154
  C_CloseAllSessions,
1155
  C_GetSessionInfo,
1156
  C_GetOperationState,
1157
  C_SetOperationState,
1158
  C_Login,
1159
  C_Logout,
1160
  C_CreateObject,
1161
  C_CopyObject,
1162
  C_DestroyObject,
1163
  C_GetObjectSize,
1164
  C_GetAttributeValue,
1165
  C_SetAttributeValue,
1166
  C_FindObjectsInit,
1167
  C_FindObjects,
1168
  C_FindObjectsFinal,
1169
  C_EncryptInit,
1170
  C_Encrypt,
1171
  C_EncryptUpdate,
1172
  C_EncryptFinal,
1173
  C_DecryptInit,
1174
  C_Decrypt,
1175
  C_DecryptUpdate,
1176
  C_DecryptFinal,
1177
  C_DigestInit,
1178
  C_Digest,
1179
  C_DigestUpdate,
1180
  C_DigestKey,
1181
  C_DigestFinal,
1182
  C_SignInit,
1183
  C_Sign,
1184
  C_SignUpdate,
1185
  C_SignFinal,
1186
  C_SignRecoverInit,
1187
  C_SignRecover,
1188
  C_VerifyInit,
1189
  C_Verify,
1190
  C_VerifyUpdate,
1191
  C_VerifyFinal,
1192
  C_VerifyRecoverInit,
1193
  C_VerifyRecover,
1194
  C_DigestEncryptUpdate,
1195
  C_DecryptDigestUpdate,
1196
  C_SignEncryptUpdate,
1197
  C_DecryptVerifyUpdate,
1198
  C_GenerateKey,
1199
  C_GenerateKeyPair,
1200
  C_WrapKey,
1201
  C_UnwrapKey,
1202
  C_DeriveKey,
1203
  C_SeedRandom,
1204
  C_GenerateRandom,
1205
  C_GetFunctionStatus,
1206
  C_CancelFunction,
1207
  C_WaitForSlotEvent,
1208
  C_GetInterfaceList,
1209
  C_GetInterface,
1210
  C_LoginUser,
1211
  C_SessionCancel,
1212
  C_MessageEncryptInit,
1213
  C_EncryptMessage,
1214
  C_EncryptMessageBegin,
1215
  C_EncryptMessageNext,
1216
  C_MessageEncryptFinal,
1217
  C_MessageDecryptInit,
1218
  C_DecryptMessage,
1219
  C_DecryptMessageBegin,
1220
  C_DecryptMessageNext,
1221
  C_MessageDecryptFinal,
1222
  C_MessageSignInit,
1223
  C_SignMessage,
1224
  C_SignMessageBegin,
1225
  C_SignMessageNext,
1226
  C_MessageSignFinal,
1227
  C_MessageVerifyInit,
1228
  C_VerifyMessage,
1229
  C_VerifyMessageBegin,
1230
  C_VerifyMessageNext,
1231
  C_MessageVerifyFinal
1232
};