Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PKCS11 changes CK_SLOT_IDs between calls to C_GetSlotList when devices are added or removed #1945

Closed
dengert opened this issue Feb 13, 2020 · 5 comments · Fixed by #1970
Closed

Comments

@dengert
Copy link
Member

dengert commented Feb 13, 2020

Problem Description

While addressing issue #1935 it appears OpenSC whill changed the CK_SLOT_IDs between calls to C_GetSlotList when devices are inserted or removed.

One would except the CK_SLOT_ID for a slot that has not changed to remain the same.

pkcs11-tool --test-hotplug -v with different tokens and readers can be used to show what happens.

@dengert
Copy link
Member Author

dengert commented Feb 13, 2020

For with a Fedian reader empty , SCM reader woth PIV, Smartcard-HSM and Yubikey produces this output (You may have to press "Please press return to continue, x to exit:" twice as the test shows what is there currently then does the refresh to get changes.)

pkcs11-tool --test-hotplug -v
Testing card detection using C_GetSlotList()
Please press return to continue, x to exit: 
Available slots:
Slot 0 (0x0): Feitian SCR301 00 00
  manufacturer:  Feitian
  hardware ver:  0.0
  firmware ver:  0.0
  flags:         removable device, hardware slot
Slot 1 (0x4): SCM Microsystems Inc. SCR 355 [CCID Interface] 01 00
  manufacturer:  SCM Microsystems
  hardware ver:  0.0
  firmware ver:  0.0
  flags:         token present, removable device, hardware slot
  token label        : SmartCard-HSM (UserPIN)
  token manufacturer : www.CardContact.de
  token model        : PKCS#15 emulated
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 24.13
  firmware version   : 1.2
  serial num         : DECC0100248
  pin min/max        : 6/15
Slot 2 (0x8): SCM Microsystems Inc. SCR 355 [CCID Interface] 02 00
  manufacturer:  SCM Microsystems Inc.
  hardware ver:  0.0
  firmware ver:  0.0
  flags:         token present, removable device, hardware slot
  token label        : deengert
  token manufacturer : piv_II
  token model        : PKCS#15 emulated
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 0.0
  firmware version   : 0.0
  serial num         : b8c3080027dbba7c
  pin min/max        : 4/8
Slot 3 (0xc): Yubico Yubikey NEO OTP+CCID 03 00
  manufacturer:  Yubico
  hardware ver:  0.0
  firmware ver:  0.0
  flags:         token present, removable device, hardware slot
  token label        : PIV_II
  token manufacturer : piv_II
  token model        : PKCS#15 emulated
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 0.0
  firmware version   : 0.0
  serial num         : 5447671bca3e0ba6
  pin min/max        : 4/8
Please press return to continue, x to exit: 

Removing the Smartcard-HSM:

Slot 0 (0x0): Feitian SCR301 00 00
  manufacturer:  Feitian
  hardware ver:  0.0
  firmware ver:  0.0
  flags:         removable device, hardware slot
Slot 1 (0x4): SCM Microsystems Inc. SCR 355 [CCID Interface] 02 00
  manufacturer:  SCM Microsystems Inc.
  hardware ver:  0.0
  firmware ver:  0.0
  flags:         token present, removable device, hardware slot
  token label        : deengert
  token manufacturer : piv_II
  token model        : PKCS#15 emulated
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 0.0
  firmware version   : 0.0
  serial num         : b8c3080027dbba7c
  pin min/max        : 4/8
Slot 2 (0x8): Yubico Yubikey NEO OTP+CCID 03 00
  manufacturer:  Yubico
  hardware ver:  0.0
  firmware ver:  0.0
  flags:         token present, removable device, hardware slot
  token label        : PIV_II
  token manufacturer : piv_II
  token model        : PKCS#15 emulated
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 0.0
  firmware version   : 0.0
  serial num         : 5447671bca3e0ba6
  pin min/max        : 4/8
Please press return to continue, x to exit: 

Note the PIV and Yubico slot numbers have changed. and any application comparing the new slot list may assume it was Slot 3 (CK_SLOT_ID 0xc) that was removed, and that the Slot 1 (CK_SLOT_ID 0x4) now has the PIV card which used to be in Slot 2 (CK)SLOT_ID 0x8).

Reinserting the smartcard-HSM
(pressing Please press return to continue, x to exit:) twice gets to:

Please press return to continue, x to exit: 
Available slots:
Slot 0 (0x0): Feitian SCR301 00 00
  manufacturer:  Feitian
  hardware ver:  0.0
  firmware ver:  0.0
  flags:         removable device, hardware slot
Slot 1 (0x4): SCM Microsystems Inc. SCR 355 [CCID Interface] 02 00
  manufacturer:  SCM Microsystems Inc.
  hardware ver:  0.0
  firmware ver:  0.0
  flags:         token present, removable device, hardware slot
  token label        : deengert
  token manufacturer : piv_II
  token model        : PKCS#15 emulated
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 0.0
  firmware version   : 0.0
  serial num         : b8c3080027dbba7c
  pin min/max        : 4/8
Slot 2 (0x8): Yubico Yubikey NEO OTP+CCID 03 00
  manufacturer:  Yubico
  hardware ver:  0.0
  firmware ver:  0.0
  flags:         token present, removable device, hardware slot
  token label        : PIV_II
  token manufacturer : piv_II
  token model        : PKCS#15 emulated
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 0.0
  firmware version   : 0.0
  serial num         : 5447671bca3e0ba6
  pin min/max        : 4/8
Slot 3 (0xc): SCM Microsystems Inc. SCR 355 [CCID Interface] 01 00
  manufacturer:  SCM Microsystems
  hardware ver:  0.0
  firmware ver:  0.0
  flags:         token present, removable device, hardware slot
  token label        : SmartCard-HSM (UserPIN)
  token manufacturer : www.CardContact.de
  token model        : PKCS#15 emulated
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 24.13
  firmware version   : 1.2
  serial num         : DECC0100248
  pin min/max        : 6/15
Please press return to continue, x to exit: 

As expected, it added it on the end.

@frankmorgner
Copy link
Member

There's a TODO here:

if (pSlotList == NULL_PTR) {
/* slot->id is derived from its location in the list virtual_slots.
* When the slot list changes, so does slot->id, so we reindex the
* slots here the same way it is done in `create_slot()`
*
* TODO use a persistent CK_SLOT_ID, e.g. by using something like
* `slot->id = sc_crc32(slot, sizeof *slot);` (this example, however,
* is currently not thread safe). */
for (i=0; i<list_size(&virtual_slots); i++) {
slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot);
}
}

I'm not sure if the slot ids actually need to stay the same, because C_GetSlotList is called with NULL, which means that the list of slot is allowed to change...

Anyway, token-based ids are surely useful to have. So fixing sc_crc32 to be thread safe should be simple enought to use for the ids.

@dengert
Copy link
Member Author

dengert commented Feb 13, 2020

I have been looking at that TODO. The problem is not the order of the number is the response to C_GetSlotList, but the face that we change the CK_SLOT_ID after every removed device, because it is based on slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot);

Its not a token based ID. but is a way for the application to find the same slot each time based on the CK_SLOT_ID.

I have an idea how to keep the same numbers for programs that don't hot plug a card, and make sure any the SLOT_IDs don't get repeated.

@frankmorgner
Copy link
Member

An example of creating a somewhat unique slot ID is given in the comment:
slot->id = sc_crc32(slot, sizeof *slot);. Yes, this is based on some temporary data and some token specific data, but since we create new slots if a new card gets inserted into the same or some different reader, the CRC-based slot ID will be unique throughout the lifetime of the process.

Actually it would be nice to have a static slot ID across different processes. This would allow the application to directly access the card with a pre-known ID without additionial commands...

@dengert
Copy link
Member Author

dengert commented Feb 14, 2020

The PKCS11 slot ids are really handles between PKCS11 module. and the application.

Notice that #1947 has the same slot structure as current code. This is because the current code bases the slot ID based on the ordering of the virtual_slot list. With one reader C_GetSlotList will return a list of length = 1, and the slot ID will be slot 0.

If there are two or more readers the ordering of the readers depends on order of the list of readers returned by PCSC. It also depends on the "slots-per-card" which defaults to 4, or 1 if onepin-pkcs11 is used. If running in a VM, the ordering of the readers may depend on which was attached first to the VM too. VM may may also changing the reader name between the host and VM.

You said:
"Actually it would be nice to have a static slot ID across different processes. This would allow the application to directly access the card with a pre-known ID without additionial commands..."

I don't see how that is going to happen. The slot ID is actually a handle to reader and is used to get token info from the reader if the token is present. I user may have more then one reader.

At C_Initialize invocation, the reader may be present without the token, and a slot ID needs to be presented to the application before the token is inserted. Thus you really cannot base the slot id on the token.

It is further complicated if p11-kit is used and it will map the slot id from multiple modules to present to the application.

The best we can do is keep the handles unique between one module and the application. #1947 can do that, and retains some compatibility with the current code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants