Coverage Report

Created: 2025-10-10 06:27

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
15.4k
{
33
15.4k
  int i, vs_size;
34
15.4k
  sc_pkcs11_slot_t * slot;
35
36
15.4k
  vs_size = list_size(&virtual_slots);
37
15.4k
  _sc_debug(context, 10,
38
15.4k
      "VSS size:%d", vs_size);
39
15.4k
  _sc_debug(context, 10,
40
15.4k
      "VSS  [i] id   flags LU events nsessions slot_info.flags reader p11card description");
41
30.8k
  for (i = 0; i < vs_size; i++) {
42
15.4k
    slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
43
15.4k
    if (slot) {
44
15.4k
      _sc_debug(context, 10,
45
15.4k
        "VSS %s[%d] 0x%2.2lx 0x%4.4x %d  %d  %d %4.4lx  %p %p %.64s",
46
15.4k
        ((slot == p) ? "*" : " "),
47
15.4k
        i, slot->id, slot->flags, slot->login_user, slot->events, slot->nsessions,
48
15.4k
        slot->slot_info.flags,
49
15.4k
        slot->reader, slot->p11card,
50
15.4k
        slot->slot_info.slotDescription);
51
15.4k
    }
52
15.4k
  }
53
15.4k
  _sc_debug(context, 10, "VSS END");
54
15.4k
}
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
15.4k
{
68
15.4k
  unsigned int i;
69
15.4k
  CK_UTF8CHAR slotDescription[64];
70
15.4k
  CK_UTF8CHAR manufacturerID[32];
71
72
15.4k
  if (reader == NULL)
73
0
    return NULL;
74
15.4k
  strcpy_bp(slotDescription, reader->name, 64);
75
15.4k
  strcpy_bp(manufacturerID, reader->vendor, 32);
76
77
  /* Locate a slot related to the reader */
78
15.4k
  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
15.4k
  return NULL;
89
15.4k
}
90
91
void init_slot_info(CK_SLOT_INFO_PTR pInfo, sc_reader_t *reader)
92
27.7k
{
93
27.7k
  if (reader) {
94
27.7k
    strcpy_bp(pInfo->slotDescription, reader->name, 64);
95
27.7k
    strcpy_bp(pInfo->manufacturerID, reader->vendor, 32);
96
27.7k
    pInfo->hardwareVersion.major = reader->version_major;
97
27.7k
    pInfo->hardwareVersion.minor = reader->version_minor;
98
27.7k
  } 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
27.7k
  pInfo->flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;
105
27.7k
  pInfo->firmwareVersion.major = 0;
106
27.7k
  pInfo->firmwareVersion.minor = 0;
107
27.7k
}
108
109
/* simclist helpers to locate interesting objects by ID */
110
static int object_list_seeker(const void *el, const void *key)
111
1.44k
{
112
1.44k
  const struct sc_pkcs11_object *object = (struct sc_pkcs11_object *)el;
113
114
1.44k
  if ((el == NULL) || (key == NULL))
115
0
    return 0;
116
1.44k
  if (object->handle == *(CK_OBJECT_HANDLE*)key)
117
627
    return 1;
118
813
  return 0;
119
1.44k
}
120
121
CK_RV create_slot(sc_reader_t *reader)
122
15.4k
{
123
  /* find unused slots previously allocated for the same reader */
124
15.4k
  struct sc_pkcs11_slot *slot = reader_reclaim_slot(reader);
125
126
  /* create a new slot if no empty slot is available */
127
15.4k
  if (!slot) {
128
15.4k
    sc_log(context, "Creating new slot");
129
15.4k
    if (list_size(&virtual_slots) >= sc_pkcs11_conf.max_virtual_slots)
130
0
      return CKR_FUNCTION_FAILED;
131
132
15.4k
    slot = (struct sc_pkcs11_slot *)calloc(1, sizeof(struct sc_pkcs11_slot));
133
15.4k
    if (!slot)
134
0
      return CKR_HOST_MEMORY;
135
136
15.4k
    list_append(&virtual_slots, slot);
137
15.4k
    if (0 != list_init(&slot->objects)) {
138
0
      return CKR_HOST_MEMORY;
139
0
    }
140
15.4k
    list_attributes_seeker(&slot->objects, object_list_seeker);
141
142
15.4k
    if (0 != list_init(&slot->logins)) {
143
0
      return CKR_HOST_MEMORY;
144
0
    }
145
15.4k
  } else {
146
0
    DEBUG_VSS(slot, "Reusing this old slot");
147
148
    /* reuse the old list of logins/objects since they should be empty */
149
0
    list_t logins = slot->logins;
150
0
    list_t objects = slot->objects;
151
152
0
    memset(slot, 0, sizeof *slot);
153
154
0
    slot->logins = logins;
155
0
    slot->objects = objects;
156
0
  }
157
158
15.4k
  slot->login_user = -1;
159
15.4k
  slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot);
160
15.4k
  init_slot_info(&slot->slot_info, reader);
161
15.4k
  slot->reader = reader;
162
163
15.4k
  DEBUG_VSS(slot, "Finished initializing this slot");
164
165
15.4k
  return CKR_OK;
166
15.4k
}
167
168
void sc_pkcs11_card_free(struct sc_pkcs11_card *p11card)
169
20.6k
{
170
20.6k
  if (p11card) {
171
15.4k
    size_t i;
172
15.4k
    if (p11card->framework && p11card->framework->unbind)
173
12.3k
      p11card->framework->unbind(p11card);
174
15.4k
    sc_disconnect_card(p11card->card);
175
139k
    for (i=0; i < p11card->nmechanisms; ++i) {
176
124k
      if (p11card->mechanisms[i]->free_mech_data) {
177
93.7k
        p11card->mechanisms[i]->free_mech_data(p11card->mechanisms[i]->mech_data);
178
93.7k
      }
179
124k
      free(p11card->mechanisms[i]);
180
124k
    }
181
15.4k
    free(p11card->mechanisms);
182
15.4k
    free(p11card);
183
15.4k
  }
184
20.6k
}
185
186
CK_RV card_removed(sc_reader_t * reader)
187
15.4k
{
188
15.4k
  unsigned int i;
189
15.4k
  struct sc_pkcs11_card *p11card = NULL;
190
  /* Mark all slots as "token not present" */
191
15.4k
  sc_log(context, "%s: card removed", reader->name);
192
193
194
30.8k
  for (i=0; i < list_size(&virtual_slots); i++) {
195
15.4k
    sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
196
15.4k
    if (slot->reader == reader) {
197
      /* Save the "card" object */
198
15.4k
      if (slot->p11card)
199
10.1k
        p11card = slot->p11card;
200
15.4k
      slot_token_removed(slot->id);
201
15.4k
    }
202
15.4k
  }
203
204
15.4k
  sc_pkcs11_card_free(p11card);
205
206
15.4k
  return CKR_OK;
207
15.4k
}
208
209
210
CK_RV card_detect(sc_reader_t *reader)
211
1.13k
{
212
1.13k
  struct sc_pkcs11_card *p11card = NULL;
213
1.13k
  int free_p11card = 0;
214
1.13k
  int rc;
215
1.13k
  CK_RV rv;
216
1.13k
  unsigned int i;
217
1.13k
  int j;
218
1.13k
  static int retry = 3;
219
220
1.13k
  sc_log(context, "%s: Detecting smart card", reader->name);
221
  /* Check if someone inserted a card */
222
1.13k
again:
223
1.13k
  rc = sc_detect_card_presence(reader);
224
1.13k
  if (rc < 0) {
225
1.13k
    sc_log(context, "%s: failed, %s", reader->name, sc_strerror(rc));
226
1.13k
    return sc_to_cryptoki_error(rc, NULL);
227
1.13k
  }
228
0
  if (rc == 0) {
229
0
    sc_log(context, "%s: card absent", reader->name);
230
0
    card_removed(reader); /* Release all resources */
231
0
    return CKR_TOKEN_NOT_PRESENT;
232
0
  }
233
234
  /* If the card was changed, disconnect the current one */
235
0
  if (rc & SC_READER_CARD_CHANGED) {
236
0
    sc_log(context, "%s: Card changed", reader->name);
237
    /* The following should never happen - but if it
238
     * does we'll be stuck in an endless loop.
239
     * So better be fussy.*/
240
0
    card_removed(reader);
241
0
    if (!retry--) {
242
0
      retry = 3;
243
0
      return CKR_TOKEN_NOT_PRESENT;
244
0
    }
245
0
    goto again;
246
0
  }
247
248
  /* Locate a slot related to the reader */
249
0
  for (i=0; i<list_size(&virtual_slots); i++) {
250
0
    sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
251
0
    if (slot->reader == reader) {
252
0
      p11card = slot->p11card;
253
0
      break;
254
0
    }
255
0
  }
256
257
  /* Detect the card if it's not known already */
258
0
  if (p11card == NULL) {
259
0
    sc_log(context, "%s: First seen the card ", reader->name);
260
0
    p11card = (struct sc_pkcs11_card *)calloc(1, sizeof(struct sc_pkcs11_card));
261
0
    if (!p11card)
262
0
      return CKR_HOST_MEMORY;
263
0
    free_p11card = 1;
264
0
    p11card->reader = reader;
265
0
  }
266
267
0
  if (p11card->card == NULL) {
268
0
    sc_log(context, "%s: Connecting ... ", reader->name);
269
0
    rc = sc_connect_card(reader, &p11card->card);
270
0
    if (rc != SC_SUCCESS) {
271
0
      sc_log(context, "%s: SC connect card error %i", reader->name, rc);
272
0
      rv = sc_to_cryptoki_error(rc, NULL);
273
0
      goto fail;
274
0
    }
275
276
    /* escape commands are only guaranteed to be working with a card
277
     * inserted. That's why by now, after sc_connect_card() the reader's
278
     * metadata may have changed. We re-initialize the metadata for every
279
     * slot of this reader here. */
280
0
    if (reader->flags & SC_READER_ENABLE_ESCAPE) {
281
0
      for (i = 0; i<list_size(&virtual_slots); i++) {
282
0
        sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
283
0
        if (slot->reader == reader)
284
0
          init_slot_info(&slot->slot_info, reader);
285
0
      }
286
0
    }
287
288
0
    sc_log(context, "%s: Connected SC card %p", reader->name, p11card->card);
289
0
  }
290
291
  /* Detect the framework */
292
0
  if (p11card->framework == NULL) {
293
0
    struct sc_app_info *app_generic = sc_pkcs15_get_application_by_type(p11card->card, "generic");
294
295
0
    sc_log(context, "%s: Detecting Framework. %i on-card applications", reader->name, p11card->card->app_count);
296
0
    sc_log(context, "%s: generic application %s", reader->name, app_generic ? app_generic->label : "<none>");
297
298
0
    for (i = 0; frameworks[i]; i++)
299
0
      if (frameworks[i]->bind != NULL)
300
0
        break;
301
    /*TODO: only first framework is used: pkcs15init framework is not reachable here */
302
0
    if (frameworks[i] == NULL) {
303
0
      rv = CKR_GENERAL_ERROR;
304
0
      goto fail;
305
0
    }
306
307
0
    p11card->framework = frameworks[i];
308
309
    /* Initialize framework */
310
0
    sc_log(context, "%s: Detected framework %d. Creating tokens.", reader->name, i);
311
    /* Bind 'generic' application or (emulated?) card without applications */
312
0
    if (app_generic || !p11card->card->app_count)   {
313
0
      scconf_block *conf_block = NULL;
314
0
      int enable_InitToken = 0;
315
316
0
      conf_block = sc_match_atr_block(p11card->card->ctx, NULL,
317
0
        &p11card->reader->atr);
318
0
      if (!conf_block) /* check default block */
319
0
        conf_block = sc_get_conf_block(context,
320
0
          "framework", "pkcs15", 1);
321
322
0
      enable_InitToken = scconf_get_bool(conf_block,
323
0
        "pkcs11_enable_InitToken", 0);
324
325
0
      sc_log(context, "%s: Try to bind 'generic' token.", reader->name);
326
0
      rv = frameworks[i]->bind(p11card, app_generic);
327
0
      if (rv == CKR_TOKEN_NOT_RECOGNIZED && enable_InitToken)   {
328
0
        sc_log(context, "%s: 'InitToken' enabled -- accept non-binded card", reader->name);
329
0
        rv = CKR_OK;
330
0
      }
331
0
      if (rv != CKR_OK)   {
332
0
        sc_log(context,
333
0
               "%s: cannot bind 'generic' token: rv 0x%lX",
334
0
               reader->name, rv);
335
0
        goto fail;
336
0
      }
337
338
0
      sc_log(context, "%s: Creating 'generic' token.", reader->name);
339
0
      rv = frameworks[i]->create_tokens(p11card, app_generic);
340
0
      if (rv != CKR_OK)   {
341
0
        sc_log(context,
342
0
               "%s: create 'generic' token error 0x%lX",
343
0
               reader->name, rv);
344
0
        goto fail;
345
0
      }
346
      /* p11card is now bound to some slot */
347
0
      free_p11card = 0;
348
0
    }
349
350
    /* Now bind the rest of applications that are not 'generic' */
351
0
    for (j = 0; j < p11card->card->app_count; j++)   {
352
0
      struct sc_app_info *app_info = p11card->card->app[j];
353
0
      char *app_name = app_info ? app_info->label : "<anonymous>";
354
355
0
      if (app_generic && app_generic == p11card->card->app[j])
356
0
        continue;
357
358
0
      sc_log(context, "%s: Binding %s token.", reader->name, app_name);
359
0
      rv = frameworks[i]->bind(p11card, app_info);
360
0
      if (rv != CKR_OK)   {
361
0
        sc_log(context, "%s: bind %s token error Ox%lX",
362
0
               reader->name, app_name, rv);
363
0
        continue;
364
0
      }
365
366
0
      sc_log(context, "%s: Creating %s token.", reader->name, app_name);
367
0
      rv = frameworks[i]->create_tokens(p11card, app_info);
368
0
      if (rv != CKR_OK)   {
369
0
        sc_log(context,
370
0
               "%s: create %s token error 0x%lX",
371
0
               reader->name, app_name, rv);
372
0
        goto fail;
373
0
      }
374
      /* p11card is now bound to some slot */
375
0
      free_p11card = 0;
376
0
    }
377
0
  }
378
379
0
  sc_log(context, "%s: Detection ended", reader->name);
380
0
  rv = CKR_OK;
381
382
0
fail:
383
0
  if (free_p11card) {
384
0
    sc_pkcs11_card_free(p11card);
385
0
  }
386
387
0
  return rv;
388
0
}
389
390
391
CK_RV
392
card_detect_all(void)
393
15.4k
{
394
15.4k
  unsigned int i, j;
395
396
15.4k
  sc_log(context, "Detect all cards");
397
  /* Detect cards in all initialized readers */
398
15.4k
  for (i=0; i< sc_ctx_get_reader_count(context); i++) {
399
0
    sc_reader_t *reader = sc_ctx_get_reader(context, i);
400
401
0
    if (reader->flags & SC_READER_REMOVED) {
402
0
      card_removed(reader);
403
      /* do not remove slots related to this reader which would be
404
       * possible according to PKCS#11 2.20 and later, because NSS can't
405
       * handle a shrinking slot list
406
       * https://bugzilla.mozilla.org/show_bug.cgi?id=1613632 */
407
408
      /* Instead, remove the relation between reader and slot */
409
0
      for (j = 0; j<list_size(&virtual_slots); j++) {
410
0
        sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, j);
411
0
        if (slot->reader == reader) {
412
0
          slot->reader = NULL;
413
0
        }
414
0
      }
415
0
    } else {
416
      /* Locate a slot related to the reader */
417
0
      int found = 0;
418
0
      for (j = 0; j<list_size(&virtual_slots); j++) {
419
0
        sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, j);
420
0
        if (slot->reader == reader) {
421
0
          found = 1;
422
0
          break;
423
0
        }
424
0
      }
425
0
      if (!found) {
426
0
        for (j = 0; j < sc_pkcs11_conf.slots_per_card; j++) {
427
0
          CK_RV rv = create_slot(reader);
428
0
          if (rv != CKR_OK)
429
0
            return rv;
430
0
        }
431
0
      }
432
0
      card_detect(reader);
433
0
    }
434
0
  }
435
15.4k
  sc_log(context, "All cards detected");
436
15.4k
  return CKR_OK;
437
15.4k
}
438
439
/* Allocates an existing slot to a card */
440
CK_RV slot_allocate(struct sc_pkcs11_slot ** slot, struct sc_pkcs11_card * p11card)
441
10.5k
{
442
10.5k
  unsigned int i;
443
10.5k
  struct sc_pkcs11_slot *tmp_slot = NULL;
444
445
  /* Locate a free slot for this reader */
446
11.0k
  for (i=0; i< list_size(&virtual_slots); i++) {
447
10.5k
    tmp_slot = (struct sc_pkcs11_slot *)list_get_at(&virtual_slots, i);
448
10.5k
    if (tmp_slot->reader == p11card->reader && tmp_slot->p11card == NULL)
449
10.1k
      break;
450
10.5k
  }
451
10.5k
  if (!tmp_slot || (i == list_size(&virtual_slots)))
452
409
    return CKR_FUNCTION_FAILED;
453
10.1k
  sc_log(context, "Allocated slot 0x%lx for card in reader %s", tmp_slot->id, p11card->reader->name);
454
10.1k
  tmp_slot->p11card = p11card;
455
10.1k
  tmp_slot->events = SC_EVENT_CARD_INSERTED;
456
10.1k
  *slot = tmp_slot;
457
10.1k
  return CKR_OK;
458
10.5k
}
459
460
CK_RV slot_get_slot(CK_SLOT_ID id, struct sc_pkcs11_slot ** slot)
461
28.5k
{
462
28.5k
  if (context == NULL)
463
0
    return CKR_CRYPTOKI_NOT_INITIALIZED;
464
465
28.5k
  *slot = list_seek(&virtual_slots, &id); /* FIXME: check for null? */
466
28.5k
  if (!*slot)
467
0
    return CKR_SLOT_ID_INVALID;
468
28.5k
  return CKR_OK;
469
28.5k
}
470
471
CK_RV slot_get_token(CK_SLOT_ID id, struct sc_pkcs11_slot ** slot)
472
13.1k
{
473
13.1k
  CK_RV rv;
474
475
13.1k
  sc_log(context, "Slot(id=0x%lX): get token", id);
476
13.1k
  rv = slot_get_slot(id, slot);
477
13.1k
  if (rv != CKR_OK)
478
0
    return rv;
479
480
13.1k
  if (!((*slot)->slot_info.flags & CKF_TOKEN_PRESENT)) {
481
1.13k
    if ((*slot)->reader == NULL)
482
0
      return CKR_TOKEN_NOT_PRESENT;
483
1.13k
    sc_log(context, "Slot(id=0x%lX): get token: now detect card", id);
484
1.13k
    rv = card_detect((*slot)->reader);
485
1.13k
    if (rv != CKR_OK)
486
1.13k
      return rv;
487
1.13k
  }
488
489
11.9k
  if (!((*slot)->slot_info.flags & CKF_TOKEN_PRESENT)) {
490
0
    sc_log(context, "card detected, but slot not presenting token");
491
0
    return CKR_TOKEN_NOT_PRESENT;
492
0
  }
493
11.9k
  sc_log(context, "Slot-get-token returns OK");
494
11.9k
  return CKR_OK;
495
11.9k
}
496
497
CK_RV slot_token_removed(CK_SLOT_ID id)
498
15.4k
{
499
15.4k
  CK_RV rv;
500
15.4k
  int token_was_present;
501
15.4k
  struct sc_pkcs11_slot *slot;
502
15.4k
  struct sc_pkcs11_object *object;
503
504
15.4k
  sc_log(context, "slot_token_removed(0x%lx)", id);
505
15.4k
  rv = slot_get_slot(id, &slot);
506
15.4k
  if (rv != CKR_OK)
507
0
    return rv;
508
509
15.4k
  token_was_present = (slot->slot_info.flags & CKF_TOKEN_PRESENT);
510
511
  /* Terminate active sessions */
512
15.4k
  sc_pkcs11_close_all_sessions(id);
513
514
41.4k
  while ((object = list_fetch(&slot->objects))) {
515
26.0k
    if (object->ops->release)
516
26.0k
      object->ops->release(object);
517
26.0k
  }
518
519
  /* Release framework stuff */
520
15.4k
  if (slot->p11card != NULL) {
521
10.1k
    if (slot->fw_data != NULL && slot->p11card->framework != NULL
522
5.11k
        && slot->p11card->framework->release_token != NULL) {
523
5.11k
      slot->p11card->framework->release_token(slot->p11card, slot->fw_data);
524
5.11k
      slot->fw_data = NULL;
525
5.11k
    }
526
10.1k
    slot->p11card = NULL;
527
10.1k
  }
528
529
  /* Reset relevant slot properties */
530
15.4k
  slot->slot_info.flags &= ~CKF_TOKEN_PRESENT;
531
15.4k
  slot->login_user = -1;
532
15.4k
  slot->profile = NULL;
533
15.4k
  pop_all_login_states(slot);
534
535
15.4k
  if (token_was_present)
536
10.1k
    slot->events = SC_EVENT_CARD_REMOVED;
537
538
15.4k
  memset(&slot->token_info, 0, sizeof slot->token_info);
539
540
15.4k
  return CKR_OK;
541
15.4k
}
542
543
/* Called from C_WaitForSlotEvent */
544
CK_RV slot_find_changed(CK_SLOT_ID_PTR idp, int mask)
545
0
{
546
0
  unsigned int i;
547
0
  LOG_FUNC_CALLED(context);
548
549
0
  card_detect_all();
550
0
  for (i=0; i<list_size(&virtual_slots); i++) {
551
0
    sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
552
0
    sc_log(context, "slot 0x%lx token: %lu events: 0x%02X",
553
0
           slot->id, (slot->slot_info.flags & CKF_TOKEN_PRESENT),
554
0
           slot->events);
555
0
    if ((slot->events & SC_EVENT_CARD_INSERTED)
556
0
        && !(slot->slot_info.flags & CKF_TOKEN_PRESENT)) {
557
      /* If a token has not been initialized, clear the inserted event */
558
0
      slot->events &= ~SC_EVENT_CARD_INSERTED;
559
0
    }
560
0
    sc_log(context, "mask: 0x%02X events: 0x%02X result: %d", mask, slot->events, (slot->events & mask));
561
562
0
    if (slot->events & mask) {
563
0
      slot->events &= ~mask;
564
0
      *idp = slot->id;
565
0
      LOG_FUNC_RETURN(context, CKR_OK);
566
0
    }
567
0
  }
568
0
  LOG_FUNC_RETURN(context, CKR_NO_EVENT);
569
0
}