Coverage Report

Created: 2026-09-14 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/pkcs11/slot.c
Line
Count
Source
1
/*
2
 * slot.c: reader, smart card and slot related management functions
3
 *
4
 * Copyright (C) 2002  Timo Teräs <timo.teras@iki.fi>
5
 * Copyright (C) 2009 Martin Paljak <martin@martinpaljak.net>
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
#include "config.h"
23
#include "libopensc/opensc.h"
24
25
#include <string.h>
26
#include <stdlib.h>
27
28
#include "sc-pkcs11.h"
29
30
/* Print virtual_slots list. Called by DEBUG_VSS(S, C) */
31
void _debug_virtual_slots(sc_pkcs11_slot_t *p)
32
16.2k
{
33
16.2k
  int i, vs_size;
34
16.2k
  sc_pkcs11_slot_t * slot;
35
36
16.2k
  vs_size = list_size(&virtual_slots);
37
16.2k
  _sc_debug(context, 10,
38
16.2k
      "VSS size:%d", vs_size);
39
16.2k
  _sc_debug(context, 10,
40
16.2k
      "VSS  [i] id   flags LU events nsessions slot_info.flags reader p11card description");
41
32.4k
  for (i = 0; i < vs_size; i++) {
42
16.2k
    slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
43
16.2k
    if (slot) {
44
16.2k
      _sc_debug(context, 10,
45
16.2k
        "VSS %s[%d] 0x%2.2lx 0x%4.4x %d  %d  %d %4.4lx  %p %p %.64s",
46
16.2k
        ((slot == p) ? "*" : " "),
47
16.2k
        i, slot->id, slot->flags, slot->login_user, slot->events, slot->nsessions,
48
16.2k
        slot->slot_info.flags,
49
16.2k
        slot->reader, slot->p11card,
50
16.2k
        slot->slot_info.slotDescription);
51
16.2k
    }
52
16.2k
  }
53
16.2k
  _sc_debug(context, 10, "VSS END");
54
16.2k
}
55
56
static struct sc_pkcs11_framework_ops *frameworks[] = {
57
  &framework_pkcs15,
58
#ifdef USE_PKCS15_INIT
59
  /* This should be the last framework, because it
60
   * will assume the card is blank and try to initialize it */
61
  &framework_pkcs15init,
62
#endif
63
  NULL
64
};
65
66
static struct sc_pkcs11_slot * reader_reclaim_slot(sc_reader_t *reader)
67
16.2k
{
68
16.2k
  unsigned int i;
69
16.2k
  CK_UTF8CHAR slotDescription[64];
70
16.2k
  CK_UTF8CHAR manufacturerID[32];
71
72
16.2k
  if (reader == NULL)
73
0
    return NULL;
74
16.2k
  strcpy_bp(slotDescription, reader->name, 64);
75
16.2k
  strcpy_bp(manufacturerID, reader->vendor, 32);
76
77
  /* Locate a slot related to the reader */
78
16.2k
  for (i = 0; i<list_size(&virtual_slots); i++) {
79
0
    sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
80
0
    if (slot->reader == NULL
81
0
        && 0 == memcmp(slot->slot_info.slotDescription, slotDescription, 64)
82
0
        && 0 == memcmp(slot->slot_info.manufacturerID, manufacturerID, 32)
83
0
        && slot->slot_info.hardwareVersion.major == reader->version_major
84
0
        && slot->slot_info.hardwareVersion.minor == reader->version_minor) {
85
0
      return slot;
86
0
    }
87
0
  }
88
16.2k
  return NULL;
89
16.2k
}
90
91
void init_slot_info(CK_SLOT_INFO_PTR pInfo, sc_reader_t *reader)
92
29.3k
{
93
29.3k
  if (reader) {
94
29.3k
    strcpy_bp(pInfo->slotDescription, reader->name, 64);
95
29.3k
    strcpy_bp(pInfo->manufacturerID, reader->vendor, 32);
96
29.3k
    pInfo->hardwareVersion.major = reader->version_major;
97
29.3k
    pInfo->hardwareVersion.minor = reader->version_minor;
98
29.3k
  } else {
99
0
    strcpy_bp(pInfo->slotDescription, "Virtual hotplug slot", 64);
100
0
    strcpy_bp(pInfo->manufacturerID, OPENSC_VS_FF_COMPANY_NAME, 32);
101
0
    pInfo->hardwareVersion.major = OPENSC_VERSION_MAJOR;
102
0
    pInfo->hardwareVersion.minor = OPENSC_VERSION_MINOR;
103
0
  }
104
29.3k
  pInfo->flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;
105
29.3k
  pInfo->firmwareVersion.major = 0;
106
29.3k
  pInfo->firmwareVersion.minor = 0;
107
29.3k
}
108
109
/* simclist helpers to locate interesting objects by ID */
110
static int object_list_seeker(const void *el, const void *key)
111
1.90k
{
112
1.90k
  const struct sc_pkcs11_object *object = (struct sc_pkcs11_object *)el;
113
114
1.90k
  if ((el == NULL) || (key == NULL))
115
0
    return 0;
116
1.90k
  if (object->handle == *(CK_OBJECT_HANDLE*)key)
117
739
    return 1;
118
1.17k
  return 0;
119
1.90k
}
120
121
CK_RV create_slot(sc_reader_t *reader)
122
16.2k
{
123
16.2k
  unsigned int events;
124
16.2k
  sc_reader_t *found;
125
  /* find unused slots previously allocated for the same reader */
126
16.2k
  struct sc_pkcs11_slot *slot = reader_reclaim_slot(reader);
127
128
  /* create a new slot if no empty slot is available */
129
16.2k
  if (!slot) {
130
16.2k
    sc_log(context, "Creating new slot");
131
16.2k
    if (list_size(&virtual_slots) >= sc_pkcs11_conf.max_virtual_slots)
132
0
      return CKR_FUNCTION_FAILED;
133
134
16.2k
    slot = (struct sc_pkcs11_slot *)calloc(1, sizeof(struct sc_pkcs11_slot));
135
16.2k
    if (!slot)
136
0
      return CKR_HOST_MEMORY;
137
138
16.2k
    list_append(&virtual_slots, slot);
139
16.2k
    if (0 != list_init(&slot->objects)) {
140
0
      return CKR_HOST_MEMORY;
141
0
    }
142
16.2k
    list_attributes_seeker(&slot->objects, object_list_seeker);
143
144
16.2k
    if (0 != list_init(&slot->logins)) {
145
0
      return CKR_HOST_MEMORY;
146
0
    }
147
16.2k
  } else {
148
0
    DEBUG_VSS(slot, "Reusing this old slot");
149
150
    /* reuse the old list of logins/objects since they should be empty */
151
0
    list_t logins = slot->logins;
152
0
    list_t objects = slot->objects;
153
154
0
    memset(slot, 0, sizeof *slot);
155
156
0
    slot->logins = logins;
157
0
    slot->objects = objects;
158
0
  }
159
160
16.2k
  slot->login_user = -1;
161
16.2k
  slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot);
162
16.2k
  init_slot_info(&slot->slot_info, reader);
163
16.2k
  slot->reader = reader;
164
16.2k
  sc_wait_for_event(context, SC_EVENT_CARD_EVENTS | SC_EVENT_READER_EVENTS, &found, &events, 0, &slot->reader_events);
165
166
16.2k
  DEBUG_VSS(slot, "Finished initializing this slot");
167
168
16.2k
  return CKR_OK;
169
16.2k
}
170
171
void sc_pkcs11_card_free(struct sc_pkcs11_card *p11card)
172
21.6k
{
173
21.6k
  if (p11card) {
174
16.2k
    size_t i;
175
16.2k
    if (p11card->framework && p11card->framework->unbind)
176
13.1k
      p11card->framework->unbind(p11card);
177
16.2k
    sc_disconnect_card(p11card->card);
178
147k
    for (i=0; i < p11card->nmechanisms; ++i) {
179
131k
      if (p11card->mechanisms[i]->free_mech_data) {
180
99.4k
        p11card->mechanisms[i]->free_mech_data(p11card->mechanisms[i]->mech_data);
181
99.4k
      }
182
131k
      free(p11card->mechanisms[i]);
183
131k
    }
184
16.2k
    free(p11card->mechanisms);
185
16.2k
    free(p11card);
186
16.2k
  }
187
21.6k
}
188
189
CK_RV card_removed(sc_reader_t * reader)
190
16.2k
{
191
16.2k
  unsigned int i;
192
16.2k
  struct sc_pkcs11_card *p11card = NULL;
193
  /* Mark all slots as "token not present" */
194
16.2k
  sc_log(context, "%s: card removed", reader->name);
195
196
197
32.4k
  for (i=0; i < list_size(&virtual_slots); i++) {
198
16.2k
    sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
199
16.2k
    if (slot->reader == reader) {
200
      /* Save the "card" object */
201
16.2k
      if (slot->p11card)
202
10.7k
        p11card = slot->p11card;
203
16.2k
      slot_token_removed(slot->id);
204
16.2k
    }
205
16.2k
  }
206
207
16.2k
  sc_pkcs11_card_free(p11card);
208
209
16.2k
  return CKR_OK;
210
16.2k
}
211
212
CK_RV
213
card_detect(sc_reader_t *reader, void *reader_states)
214
1.23k
{
215
1.23k
  struct sc_pkcs11_card *p11card = NULL;
216
1.23k
  int free_p11card = 0;
217
1.23k
  int rc;
218
1.23k
  int no_change = 0;
219
1.23k
  CK_RV rv;
220
1.23k
  unsigned int i;
221
1.23k
  int j;
222
1.23k
  static int retry = 3;
223
224
1.23k
  sc_log(context, "%s: Detecting smart card", reader->name);
225
  /* Check if someone inserted a card */
226
227
1.23k
  if (reader_states != NULL) {
228
    /* check if any event has occurred since last invocation of `card_detect()` */
229
0
    unsigned int mask, events;
230
0
    sc_reader_t *event_reader;
231
    /* Detect card and reader events */
232
0
    mask = SC_EVENT_CARD_EVENTS | SC_EVENT_READER_EVENTS;
233
0
    int r = sc_wait_for_event(context, mask, &event_reader, &events, 0, &reader_states);
234
0
    if (r == SC_ERROR_EVENT_TIMEOUT || reader != event_reader)
235
      /* no change happened */
236
0
      no_change = 1;
237
0
    else
238
      /* if some error occurred or there actually was a change, continue with detection routine */
239
0
      no_change = 0;
240
0
  }
241
242
1.23k
again:
243
1.23k
  rc = sc_detect_card_presence(reader);
244
1.23k
  if (rc < 0) {
245
1.23k
    sc_log(context, "%s: failed, %s", reader->name, sc_strerror(rc));
246
1.23k
    return sc_to_cryptoki_error(rc, NULL);
247
1.23k
  }
248
0
  if (rc == 0) {
249
0
    sc_log(context, "%s: card absent", reader->name);
250
0
    card_removed(reader); /* Release all resources */
251
0
    return CKR_TOKEN_NOT_PRESENT;
252
0
  }
253
254
0
  if (no_change == 1) {
255
0
    sc_log(context, "%s: card present, no change detected", reader->name);
256
0
    return CKR_OK;
257
0
  }
258
259
  /* If the card was changed, disconnect the current one */
260
0
  if (rc & SC_READER_CARD_CHANGED) {
261
0
    sc_log(context, "%s: Card changed", reader->name);
262
    /* The following should never happen - but if it
263
     * does we'll be stuck in an endless loop.
264
     * So better be fussy.*/
265
0
    card_removed(reader);
266
0
    if (!retry--) {
267
0
      retry = 3;
268
0
      return CKR_TOKEN_NOT_PRESENT;
269
0
    }
270
0
    goto again;
271
0
  }
272
273
  /* Locate a slot related to the reader */
274
0
  for (i=0; i<list_size(&virtual_slots); i++) {
275
0
    sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
276
0
    if (slot->reader == reader) {
277
0
      p11card = slot->p11card;
278
0
      break;
279
0
    }
280
0
  }
281
282
  /* Detect the card if it's not known already */
283
0
  if (p11card == NULL) {
284
0
    sc_log(context, "%s: First seen the card ", reader->name);
285
0
    p11card = (struct sc_pkcs11_card *)calloc(1, sizeof(struct sc_pkcs11_card));
286
0
    if (!p11card)
287
0
      return CKR_HOST_MEMORY;
288
0
    free_p11card = 1;
289
0
    p11card->reader = reader;
290
0
  }
291
292
0
  if (p11card->card == NULL) {
293
0
    sc_log(context, "%s: Connecting ... ", reader->name);
294
0
    rc = sc_connect_card(reader, &p11card->card);
295
0
    if (rc != SC_SUCCESS) {
296
0
      sc_log(context, "%s: SC connect card error %i", reader->name, rc);
297
0
      rv = sc_to_cryptoki_error(rc, NULL);
298
0
      goto fail;
299
0
    }
300
301
    /* escape commands are only guaranteed to be working with a card
302
     * inserted. That's why by now, after sc_connect_card() the reader's
303
     * metadata may have changed. We re-initialize the metadata for every
304
     * slot of this reader here. */
305
0
    if (reader->flags & SC_READER_ENABLE_ESCAPE) {
306
0
      for (i = 0; i<list_size(&virtual_slots); i++) {
307
0
        sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
308
0
        if (slot->reader == reader)
309
0
          init_slot_info(&slot->slot_info, reader);
310
0
      }
311
0
    }
312
313
0
    sc_log(context, "%s: Connected SC card %p", reader->name, p11card->card);
314
0
  }
315
316
  /* Detect the framework */
317
0
  if (p11card->framework == NULL) {
318
0
    struct sc_app_info *app_generic = sc_pkcs15_get_application_by_type(p11card->card, "generic");
319
320
0
    sc_log(context, "%s: Detecting Framework. %i on-card applications", reader->name, p11card->card->app_count);
321
0
    sc_log(context, "%s: generic application %s", reader->name, app_generic ? app_generic->label : "<none>");
322
323
0
    for (i = 0; frameworks[i]; i++)
324
0
      if (frameworks[i]->bind != NULL)
325
0
        break;
326
    /*TODO: only first framework is used: pkcs15init framework is not reachable here */
327
0
    if (frameworks[i] == NULL) {
328
0
      rv = CKR_GENERAL_ERROR;
329
0
      goto fail;
330
0
    }
331
332
0
    p11card->framework = frameworks[i];
333
334
    /* Initialize framework */
335
0
    sc_log(context, "%s: Detected framework %d. Creating tokens.", reader->name, i);
336
    /* Bind 'generic' application or (emulated?) card without applications */
337
0
    if (app_generic || !p11card->card->app_count)   {
338
0
      scconf_block *conf_block = NULL;
339
0
      int enable_InitToken = 0;
340
341
0
      conf_block = sc_match_atr_block(p11card->card->ctx, NULL,
342
0
        &p11card->reader->atr);
343
0
      if (!conf_block) /* check default block */
344
0
        conf_block = sc_get_conf_block(context,
345
0
          "framework", "pkcs15", 1);
346
347
0
      enable_InitToken = scconf_get_bool(conf_block,
348
0
        "pkcs11_enable_InitToken", 0);
349
350
0
      sc_log(context, "%s: Try to bind 'generic' token.", reader->name);
351
0
      rv = frameworks[i]->bind(p11card, app_generic);
352
0
      if (rv == CKR_TOKEN_NOT_RECOGNIZED && enable_InitToken)   {
353
0
        sc_log(context, "%s: 'InitToken' enabled -- accept non-binded card", reader->name);
354
0
        rv = CKR_OK;
355
0
      }
356
0
      if (rv != CKR_OK)   {
357
0
        sc_log(context,
358
0
               "%s: cannot bind 'generic' token: rv 0x%lX",
359
0
               reader->name, rv);
360
0
        goto fail;
361
0
      }
362
363
0
      sc_log(context, "%s: Creating 'generic' token.", reader->name);
364
0
      rv = frameworks[i]->create_tokens(p11card, app_generic);
365
0
      if (rv != CKR_OK)   {
366
0
        sc_log(context,
367
0
               "%s: create 'generic' token error 0x%lX",
368
0
               reader->name, rv);
369
0
        goto fail;
370
0
      }
371
      /* p11card is now bound to some slot */
372
0
      free_p11card = 0;
373
0
    }
374
375
    /* Now bind the rest of applications that are not 'generic' */
376
0
    for (j = 0; j < p11card->card->app_count; j++)   {
377
0
      struct sc_app_info *app_info = p11card->card->app[j];
378
0
      char *app_name = app_info ? app_info->label : "<anonymous>";
379
380
0
      if (app_generic && app_generic == p11card->card->app[j])
381
0
        continue;
382
383
0
      sc_log(context, "%s: Binding %s token.", reader->name, app_name);
384
0
      rv = frameworks[i]->bind(p11card, app_info);
385
0
      if (rv != CKR_OK)   {
386
0
        sc_log(context, "%s: bind %s token error Ox%lX",
387
0
               reader->name, app_name, rv);
388
0
        continue;
389
0
      }
390
391
0
      sc_log(context, "%s: Creating %s token.", reader->name, app_name);
392
0
      rv = frameworks[i]->create_tokens(p11card, app_info);
393
0
      if (rv != CKR_OK)   {
394
0
        sc_log(context,
395
0
               "%s: create %s token error 0x%lX",
396
0
               reader->name, app_name, rv);
397
0
        goto fail;
398
0
      }
399
      /* p11card is now bound to some slot */
400
0
      free_p11card = 0;
401
0
    }
402
0
  }
403
404
0
  sc_log(context, "%s: Detection ended", reader->name);
405
0
  rv = CKR_OK;
406
407
0
fail:
408
0
  if (free_p11card) {
409
0
    sc_pkcs11_card_free(p11card);
410
0
  }
411
412
0
  return rv;
413
0
}
414
415
416
CK_RV
417
card_detect_all(void)
418
16.2k
{
419
16.2k
  unsigned int i, j;
420
421
16.2k
  sc_log(context, "Detect all cards");
422
  /* Detect cards in all initialized readers */
423
16.2k
  for (i=0; i< sc_ctx_get_reader_count(context); i++) {
424
0
    sc_reader_t *reader = sc_ctx_get_reader(context, i);
425
426
0
    if (reader->flags & SC_READER_REMOVED) {
427
0
      card_removed(reader);
428
      /* do not remove slots related to this reader which would be
429
       * possible according to PKCS#11 2.20 and later, because NSS can't
430
       * handle a shrinking slot list
431
       * https://bugzilla.mozilla.org/show_bug.cgi?id=1613632 */
432
433
      /* Instead, remove the relation between reader and slot */
434
0
      for (j = 0; j<list_size(&virtual_slots); j++) {
435
0
        sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, j);
436
0
        if (slot->reader == reader) {
437
0
          slot->reader = NULL;
438
0
          sc_wait_for_event(context, 0, NULL, NULL, 0, &slot->reader_events);
439
0
        }
440
0
      }
441
0
    } else {
442
      /* Locate a slot related to the reader */
443
0
      int found = 0;
444
0
      for (j = 0; j<list_size(&virtual_slots); j++) {
445
0
        sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, j);
446
0
        if (slot->reader == reader) {
447
0
          found = 1;
448
0
          card_detect(slot->reader, slot->reader_events);
449
0
          break;
450
0
        }
451
0
      }
452
0
      if (!found) {
453
0
        for (j = 0; j < sc_pkcs11_conf.slots_per_card; j++) {
454
0
          CK_RV rv = create_slot(reader);
455
0
          if (rv != CKR_OK)
456
0
            return rv;
457
0
        }
458
0
        card_detect(reader, NULL);
459
0
      }
460
0
    }
461
0
  }
462
16.2k
  sc_log(context, "All cards detected");
463
16.2k
  return CKR_OK;
464
16.2k
}
465
466
/* Allocates an existing slot to a card */
467
CK_RV slot_allocate(struct sc_pkcs11_slot ** slot, struct sc_pkcs11_card * p11card)
468
11.1k
{
469
11.1k
  unsigned int i;
470
11.1k
  struct sc_pkcs11_slot *tmp_slot = NULL;
471
472
  /* Locate a free slot for this reader */
473
11.5k
  for (i=0; i< list_size(&virtual_slots); i++) {
474
11.1k
    tmp_slot = (struct sc_pkcs11_slot *)list_get_at(&virtual_slots, i);
475
11.1k
    if (tmp_slot->reader == p11card->reader && tmp_slot->p11card == NULL)
476
10.7k
      break;
477
11.1k
  }
478
11.1k
  if (!tmp_slot || (i == list_size(&virtual_slots)))
479
426
    return CKR_FUNCTION_FAILED;
480
10.7k
  sc_log(context, "Allocated slot 0x%lx for card in reader %s", tmp_slot->id, p11card->reader->name);
481
10.7k
  tmp_slot->p11card = p11card;
482
10.7k
  tmp_slot->events = SC_EVENT_CARD_INSERTED;
483
10.7k
  *slot = tmp_slot;
484
10.7k
  return CKR_OK;
485
11.1k
}
486
487
CK_RV slot_get_slot(CK_SLOT_ID id, struct sc_pkcs11_slot ** slot)
488
30.0k
{
489
30.0k
  if (context == NULL)
490
0
    return CKR_CRYPTOKI_NOT_INITIALIZED;
491
492
30.0k
  *slot = list_seek(&virtual_slots, &id); /* FIXME: check for null? */
493
30.0k
  if (!*slot)
494
0
    return CKR_SLOT_ID_INVALID;
495
30.0k
  return CKR_OK;
496
30.0k
}
497
498
CK_RV slot_get_token(CK_SLOT_ID id, struct sc_pkcs11_slot ** slot)
499
13.8k
{
500
13.8k
  CK_RV rv;
501
502
13.8k
  sc_log(context, "Slot(id=0x%lX): get token", id);
503
13.8k
  rv = slot_get_slot(id, slot);
504
13.8k
  if (rv != CKR_OK)
505
0
    return rv;
506
507
13.8k
  if (!((*slot)->slot_info.flags & CKF_TOKEN_PRESENT)) {
508
1.23k
    if ((*slot)->reader == NULL)
509
0
      return CKR_TOKEN_NOT_PRESENT;
510
1.23k
    sc_log(context, "Slot(id=0x%lX): get token: now detect card", id);
511
1.23k
    rv = card_detect((*slot)->reader, (*slot)->reader_events);
512
1.23k
    if (rv != CKR_OK)
513
1.23k
      return rv;
514
1.23k
  }
515
516
12.5k
  if (!((*slot)->slot_info.flags & CKF_TOKEN_PRESENT)) {
517
0
    sc_log(context, "card detected, but slot not presenting token");
518
0
    return CKR_TOKEN_NOT_PRESENT;
519
0
  }
520
12.5k
  sc_log(context, "Slot-get-token returns OK");
521
12.5k
  return CKR_OK;
522
12.5k
}
523
524
CK_RV slot_token_removed(CK_SLOT_ID id)
525
16.2k
{
526
16.2k
  CK_RV rv;
527
16.2k
  int token_was_present;
528
16.2k
  struct sc_pkcs11_slot *slot;
529
16.2k
  struct sc_pkcs11_object *object;
530
531
16.2k
  sc_log(context, "slot_token_removed(0x%lx)", id);
532
16.2k
  rv = slot_get_slot(id, &slot);
533
16.2k
  if (rv != CKR_OK)
534
0
    return rv;
535
536
16.2k
  token_was_present = (slot->slot_info.flags & CKF_TOKEN_PRESENT);
537
538
  /* Terminate active sessions */
539
16.2k
  sc_pkcs11_close_all_sessions(id);
540
541
44.7k
  while ((object = list_fetch(&slot->objects))) {
542
28.5k
    if (object->ops->release)
543
28.5k
      object->ops->release(object);
544
28.5k
  }
545
546
  /* Release framework stuff */
547
16.2k
  if (slot->p11card != NULL) {
548
10.7k
    if (slot->fw_data != NULL && slot->p11card->framework != NULL
549
5.43k
        && slot->p11card->framework->release_token != NULL) {
550
5.43k
      slot->p11card->framework->release_token(slot->p11card, slot->fw_data);
551
5.43k
      slot->fw_data = NULL;
552
5.43k
    }
553
10.7k
    slot->p11card = NULL;
554
10.7k
  }
555
556
  /* Reset relevant slot properties */
557
16.2k
  slot->slot_info.flags &= ~CKF_TOKEN_PRESENT;
558
16.2k
  slot->login_user = -1;
559
16.2k
  slot->profile = NULL;
560
16.2k
  pop_all_login_states(slot);
561
562
16.2k
  if (token_was_present)
563
10.7k
    slot->events = SC_EVENT_CARD_REMOVED;
564
565
16.2k
  memset(&slot->token_info, 0, sizeof slot->token_info);
566
567
16.2k
  return CKR_OK;
568
16.2k
}
569
570
/* Called from C_WaitForSlotEvent */
571
CK_RV slot_find_changed(CK_SLOT_ID_PTR idp, int mask)
572
0
{
573
0
  unsigned int i;
574
0
  LOG_FUNC_CALLED(context);
575
576
0
  card_detect_all();
577
0
  for (i=0; i<list_size(&virtual_slots); i++) {
578
0
    sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
579
0
    sc_log(context, "slot 0x%lx token: %lu events: 0x%02X",
580
0
           slot->id, (slot->slot_info.flags & CKF_TOKEN_PRESENT),
581
0
           slot->events);
582
0
    if ((slot->events & SC_EVENT_CARD_INSERTED)
583
0
        && !(slot->slot_info.flags & CKF_TOKEN_PRESENT)) {
584
      /* If a token has not been initialized, clear the inserted event */
585
0
      slot->events &= ~SC_EVENT_CARD_INSERTED;
586
0
    }
587
0
    sc_log(context, "mask: 0x%02X events: 0x%02X result: %d", mask, slot->events, (slot->events & mask));
588
589
0
    if (slot->events & mask) {
590
0
      slot->events &= ~mask;
591
0
      *idp = slot->id;
592
0
      LOG_FUNC_RETURN(context, CKR_OK);
593
0
    }
594
0
  }
595
0
  LOG_FUNC_RETURN(context, CKR_NO_EVENT);
596
0
}