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

Reselect PKI-Applets after card reset #1243

Merged
merged 3 commits into from
Feb 7, 2018

Conversation

frankmorgner
Copy link
Member

@frankmorgner frankmorgner commented Jan 17, 2018

PKI-Applets may not be active if the card has been reset or unpowered.
The SELECT command used to activate the applet, is identical to the one
used during card matching or initialization.

Checklist
  • Documentation is added or updated
  • Tested with the following card: Yubikey 4 (OpenPGP)
    • tested PKCS#11
    • tested Windows Minidriver
    • tested macOS Tokend

@frankmorgner
Copy link
Member Author

@Jakuje @dengert I think this PR fixes #962 in the case of card resets...

I implemented this for the obvious card drivers. Though, I cannot test all of the card drivers, I think the changes are fairly simple so that they are likely to work.

@dengert
Copy link
Member

dengert commented Jan 17, 2018

Yes these look reasonable for the reset case.
But it does not address the situation where two different processes are trying to use different card drivers that use different AIDs on the same card. One process may have set OPENSC_DRIVER=openpgp
and the other OPENSC_DRIVER=PIV_II (or used two different opensc.conf files and used OPENSC_CONF=)

@mouse07410 mouse07410 mentioned this pull request Jan 19, 2018
5 tasks
@frankmorgner
Copy link
Member Author

I've added a global option to send a "keep alive" command that is to be implemented by the card driver. This should make the OpenPGP driver work even if the applet got deselected. The global card flag essentially replaces CI_OTHER_AID_LOSE_STATE flag in the PIV driver. I hope to test the changes next week. (But since some people are eagerly waiting, I'm already publishing it here 😉 )

Note that this should fix concurrent access between different applications. But it does not allow accessing two different applets (card drivers) at the same time in a single application. That would require bigger refactoring, which I'll leave for future research.

# name = "PIV-II";
# driver = "piv";
# }
# Yubikey NEO is known to have the PIV applet and the OpenPGP applet
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not only Yubikey Neo anymore. This functionality is present in the recent Yubikey 4. Mine is Yubico Yubikey 4 OTP+U2F+CCID with ATR 3B F8 13 00 00 81 31 FE 15 59 75 62 69 6B 65 79 34 D4.
Not sure if it matters to have this ATR in default configuration, or there should be both/all we will be able to gather.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually I've extracted this information from the OpenPGP driver. There are ATRs here https://github.com/Yubico/yubico-piv-tool/blob/3aaa525efc678f9bca1fb08716e282eb00536356/lib/ykpiv.h#L672-L673 and here https://ludovic.rousseau.free.fr/softwares/pcsc-tools/smartcard_list.txt. I'll integrate them later, thanks for the pointer.

# Default: "piv"
#driver = "openpgp";
#
# Make sure that we can recover from different applications that may access the Yibikey
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo Yibikey -> Yubikey

@Jakuje
Copy link
Member

Jakuje commented Jan 22, 2018

Thank you for the changes. I found some minor issues that are outlined in the above comments.

I tested now with Firefox (PIV-II applet) and OpenPGP (pkcs11-tool --test) and after getting back to Firefox and trying to use the card, I got an error:

An error occurred during a connection to localhost:5556. A PKCS #11 module returned CKR_GENERAL_ERROR, indicating that an unrecoverable error has occurred. Error code: SEC_ERROR_PKCS11_GENERAL_ERROR

After the failure, the OpenPGP is still able to pass most of the pkcs11-tool --test (sign&verify -- fails with decryption)

It looks like there will still be something to work on, probably in the PIV side. I am not sure if I will be able to debug this further this week.

@frankmorgner
Copy link
Member Author

I've added a commit that should work for PIV (according to the NIST.SP.800-73-4.pdf)

@Jakuje
Copy link
Member

Jakuje commented Jan 23, 2018

I tested again with the new commits and collecting the debug information, but I am still getting the same results. After accessing the OpenPGP applet from pkcs11-tool, I see failures in Firefox.

From the pkcs11-spy, we can notice that I am using the signature key (RSA), which requires pin verification, but already this one fails:

470: C_SignInit
2018-01-23 10:52:33.945
[in] hSession = 0x7f6be5a71ca0
pMechanism->type=CKM_RSA_PKCS                 
[in] hKey = 0x7f6be1386ac0
Returned:  0 CKR_OK

471: C_GetAttributeValue
2018-01-23 10:52:33.946
[in] hSession = 0x7f6be1395760
[in] hObject = 0x7f6be1386ac0
[in] pTemplate[1]: 
    CKA_ALWAYS_AUTHENTICATE  00007f6db38a47bf / 1
[out] pTemplate[1]: 
    CKA_ALWAYS_AUTHENTICATE  True
Returned:  0 CKR_OK

472: C_Login
2018-01-23 10:52:36.311
[in] hSession = 0x7f6be5a71ca0
[in] userType = CKU_CONTEXT_SPECIFIC
[in] pPin[ulPinLen] 00007f6be15d20b8 / 6
    [...]
Returned:  32 CKR_DATA_INVALID

473: C_Sign
2018-01-23 10:52:36.330
[in] hSession = 0x7f6be5a71ca0
[in] pData[ulDataLen] 00007f6be2c1c820 / 51
    00000000  30 31 30 0D 06 09 60 86 48 01 65 03 04 02 01 05  010...`.H.e.....
    00000010  00 04 20 20 10 CE 23 0D F6 A5 65 68 1C 4D C3 65  ..  ..#...eh.M.e
    00000020  52 4C B5 50 D6 AC 79 9B 85 87 C2 57 D7 5D D0 91  RL.P..y....W.]..
    00000030  1F 05 65                                         ..e             
Returned:  5 CKR_GENERAL_ERROR

The non-always authenticate does not work either:

345: C_SignInit
2018-01-23 11:07:45.709
[in] hSession = 0x7f646eccf160
pMechanism->type=CKM_ECDSA                    
[in] hKey = 0x7f6472bdb8e0
Returned:  0 CKR_OK

346: C_GetAttributeValue
2018-01-23 11:07:45.710
[in] hSession = 0x7f64735e4280
[in] hObject = 0x7f6472bdb8e0
[in] pTemplate[1]: 
    CKA_ALWAYS_AUTHENTICATE  00007f663baa47bf / 1
[out] pTemplate[1]: 
    CKA_ALWAYS_AUTHENTICATE  False
Returned:  0 CKR_OK

347: C_Sign
2018-01-23 11:07:45.710
[in] hSession = 0x7f646eccf160
[in] pData[ulDataLen] 00007f663baa49e8 / 32
    00000000  D2 1A 49 E6 B3 07 80 90 9C 8A 7F 71 14 ED F2 98  ..I.......^?q....
    00000010  31 53 1E 2A DD 86 81 F1 1C 7B 39 13 59 EB 6C 0E  1S.*.....{9.Y.l.
Returned:  5 CKR_GENERAL_ERROR

There is snapshot of the last lines while doing the Sign operation. Let me know if you would need some more log data:

0x7f663baa5700 11:07:45.712 [opensc-pkcs11] pkcs15-sec.c:419:sc_pkcs15_compute_signature: DEE flags:0x00000010 alg_info->flags:0x00030010 pad:0x00000000 sec:0x00010000
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card.c:407:sc_lock: called
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card.c:449:sc_lock: returning with: 0 (Success)
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] sec.c:75:sc_set_security_env: called
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card-piv.c:2279:piv_set_security_env: called
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card-piv.c:2284:piv_set_security_env: flags=00000015 op=2 alg=2 algf=00010000 algr=00000100 kr0=9a, krfl=1
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card-piv.c:2311:piv_set_security_env: returning with: 0 (Success)
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] sec.c:79:sc_set_security_env: returning with: 0 (Success)
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] sec.c:59:sc_compute_signature: called
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card-piv.c:2412:piv_compute_signature: called
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card-piv.c:2340:piv_validate_general_authentication: called
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card-piv.c:486:piv_general_io: called
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card-piv.c:491:piv_general_io: 87 11 9a 38 : 255 256
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card.c:407:sc_lock: called
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card.c:449:sc_lock: returning with: 0 (Success)
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card-piv.c:532:piv_general_io: calling sc_transmit_apdu flags=1 le=256, resplen=4096, resp=0x7f663baa1b70
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] apdu.c:554:sc_transmit_apdu: called
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card.c:407:sc_lock: called
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] card.c:449:sc_lock: returning with: 0 (Success)
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] apdu.c:521:sc_transmit: called
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] apdu.c:371:sc_single_transmit: called
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] apdu.c:378:sc_single_transmit: CLA:0, INS:87, P1:11, P2:9A, data(38) 0x7f663baa2bf0
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] reader-pcsc.c:283:pcsc_transmit: reader 'Yubico Yubikey 4 OTP+U2F+CCID 01 00'
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] reader-pcsc.c:284:pcsc_transmit: 
Outgoing APDU (44 bytes):
00 87 11 9A 26 7C 24 82 00 81 20 D2 1A 49 E6 B3 ....&|$... ..I..
07 80 90 9C 8A 7F 71 14 ED F2 98 31 53 1E 2A DD ......q....1S.*.
86 81 F1 1C 7B 39 13 59 EB 6C 0E 00             ....{9.Y.l..
0x7f663baa5700 11:07:45.712 [opensc-pkcs11] reader-pcsc.c:212:pcsc_internal_transmit: called
0x7f663baa5700 11:07:45.718 [opensc-pkcs11] reader-pcsc.c:293:pcsc_transmit: 
Incoming APDU (2 bytes):
6D 00 m.
0x7f663baa5700 11:07:45.718 [opensc-pkcs11] apdu.c:390:sc_single_transmit: returning with: 0 (Success)
0x7f663baa5700 11:07:45.718 [opensc-pkcs11] apdu.c:543:sc_transmit: returning with: 0 (Success)
0x7f663baa5700 11:07:45.718 [opensc-pkcs11] card.c:459:sc_unlock: called
0x7f663baa5700 11:07:45.718 [opensc-pkcs11] card-piv.c:539:piv_general_io: DEE r=0 apdu.resplen=0 sw1=6d sw2=00
0x7f663baa5700 11:07:45.718 [opensc-pkcs11] iso7816.c:124:iso7816_check_sw: Instruction code not supported or invalid
0x7f663baa5700 11:07:45.718 [opensc-pkcs11] card-piv.c:550:piv_general_io: Card returned error 
0x7f663baa5700 11:07:45.718 [opensc-pkcs11] card.c:459:sc_unlock: called
0x7f663baa5700 11:07:45.718 [opensc-pkcs11] card-piv.c:600:piv_general_io: returning with: -1204 (Unsupported INS byte in APDU)
0x7f663baa5700 11:07:45.718 [opensc-pkcs11] card-piv.c:2393:piv_validate_general_authentication: returning with: -1204 (Unsupported INS byte in APDU)
0x7f663baa5700 11:07:45.718 [opensc-pkcs11] card-piv.c:2472:piv_compute_signature: returning with: -1204 (Unsupported INS byte in APDU)
0x7f663baa5700 11:07:45.719 [opensc-pkcs11] sec.c:63:sc_compute_signature: returning with: -1204 (Unsupported INS byte in APDU)
0x7f663baa5700 11:07:45.719 [opensc-pkcs11] card.c:459:sc_unlock: called
0x7f663baa5700 11:07:45.719 [opensc-pkcs11] pkcs15-sec.c:454:sc_pkcs15_compute_signature: use_key() failed: -1204 (Unsupported INS byte in APDU)
0x7f663baa5700 11:07:45.719 [opensc-pkcs11] card.c:459:sc_unlock: called
0x7f663baa5700 11:07:45.719 [opensc-pkcs11] reader-pcsc.c:662:pcsc_unlock: called
0x7f663baa5700 11:07:45.721 [opensc-pkcs11] framework-pkcs15.c:3767:pkcs15_prkey_sign: Sign complete. Result -1204.
0x7f663baa5700 11:07:45.721 [opensc-pkcs11] misc.c:61:sc_to_cryptoki_error_common: libopensc return value: -1204 (Unsupported INS byte in APDU)
0x7f663baa5700 11:07:45.721 [opensc-pkcs11] mechanism.c:462:sc_pkcs11_signature_final: returning with: 5
0x7f663baa5700 11:07:45.721 [opensc-pkcs11] mechanism.c:327:sc_pkcs11_sign_final: returning with: 5
0x7f663baa5700 11:07:45.721 [opensc-pkcs11] pkcs11-object.c:701:C_Sign: C_Sign() = CKR_GENERAL_ERROR

@dengert
Copy link
Member

dengert commented Jan 23, 2018

Looks like the OpenPGP AID was still selected, so the PIV apdu fails in the OpenPGP applet.
I had started looking at adding a SELECT_AID to *_card_reader_lock_obtained so each SCardBeginTransaction would issue a SELECT AID and a VERIFY Lc=empty to check the login state.

The test script I sent to @Jakuje, @frankmorgner and @mouse07410 shows that a Yubikey 4 can not handle the SELECT AID (it loses login state even when selecting the current AID) and the VERIFY Lc=empty never returns 9000 to show the user is logged in.

Even if they could, in the case of CKA_ALWAYS_AUTHENTICATE the VERIFY PIN and the signing command must not have any other card commands between them. A SELECT_AID or VERIFY Lc=empty are commands can not be between the VERIFY PIN and the crypto signing command.

In the CKA_ALWAYS_AUTHENTICATE case the best approach is to make sure the VERIFY PIN and the signing command are in the same transaction. But the way OpenSC is setup, the VERIFY PIN is in one transaction and the the signing command is in a separate command. (This would also keep other processes from interfering at this point too.) I started working on this and it gets complicated, because the framework-pkcs11. c needs to pass this info in to the pkcs15 layer so an sc_lock is done at the verify and unlocked after the signing command, or if this never happens the lock need to be released.

I see that the sign command failed with 6D00. @frankmorgner suggested this could trigger a SELECT AID and a retry. The PIV PIN code tries to do this. But in the more general case, if both card applications happen to support the same command, you won't get a 6D00 and the command would be done against the wrong application with unforeseen consequences.

So in my option the only way to address this to make sure every transaction selects the AID as the first command. And for the CKA_ALWAYS_AUTHENTICATE the vrify must be in the same transaction.

As users want to use multiple applications on the same card this gets much more complicated. Look at the CAC card which may also have a PIV application. card-cac.c is actually using multiple AID internally,
as it looks like the design of the CAC card stores different objects under different AIDs. They even added a macro CAC_TO_AID, and it looks like they use the sc_select_file to do both a SELECT AID and a SELECT FILE.

@frankmorgner
Copy link
Member Author

I've implemented a "keep alive" command in the PIV driver based on the CHUI. @Jakuje This command should have preceded the error, which is not shown in your log. Does this work; is the re-applet selected? (It may also be a problem with parsing the flag from opensc.conf if the "keep alive" command is not sent...)

However, I did not have the limitation in mind that EXTERNAL AUTHENTICATE must immediately follow the VERIFY.

If deselection is possible, we, indeed, need to put both commands into a single transaction. NIST.IR.7863.pdf has a section 4.2 Explicit User Action with PIN Caching, which says that the application is allowed to cache the PIN if there are other mechanisms in place to enforce "PIN always". These are already implemented in OpenSC, I think. So what I'd like to suggest is that the PIV driver caches the PIN and performs an additional verification right before EXTERNAL AUTHENTICATE if needed. So OpenSC may verify the PIN twice to the card, but the user still sees only a single prompt.

@Jakuje
Copy link
Member

Jakuje commented Jan 23, 2018

I've implemented a "keep alive" command in the PIV driver based on the CHUI. @Jakuje This command should have preceded the error, which is not shown in your log. Does this work; is the re-applet selected? (It may also be a problem with parsing the flag from opensc.conf if the "keep alive" command is not sent...)

I used the master + this branch and I copied the opensc.conf to /usr/local/etc/opensc.conf which gets used by default. I do not see any logging in the added code, so I am not sure what to look for in the logs. Only thing I can see is that piv_card_reader_lock_obtained returned success in all the cases during the session:

0x7f663baa5700 11:07:25.251 [opensc-pkcs11] card-piv.c:3372:piv_card_reader_lock_obtained: called
0x7f663baa5700 11:07:25.251 [opensc-pkcs11] card-piv.c:3400:piv_card_reader_lock_obtained: returning with: 0 (Success)

Searching for CHUI, I am getting several failures like this (even the first call ends this way):

0x7f665f62c740 11:06:48.494 [opensc-pkcs11] card-piv.c:2080:piv_get_serial_nr_from_CHUI: called
0x7f665f62c740 11:06:48.494 [opensc-pkcs11] card-piv.c:725:piv_select_aid: called
0x7f665f62c740 11:06:48.494 [opensc-pkcs11] card-piv.c:728:piv_select_aid: Got args: aid=0x7f648bd54660, aidlen=9, response=0x7ffe1ba28c00, responselen=2000
0x7f665f62c740 11:06:48.494 [opensc-pkcs11] apdu.c:554:sc_transmit_apdu: called
0x7f665f62c740 11:06:48.494 [opensc-pkcs11] card.c:407:sc_lock: called
0x7f665f62c740 11:06:48.494 [opensc-pkcs11] card.c:449:sc_lock: returning with: 0 (Success)
0x7f665f62c740 11:06:48.494 [opensc-pkcs11] apdu.c:521:sc_transmit: called
0x7f665f62c740 11:06:48.494 [opensc-pkcs11] apdu.c:371:sc_single_transmit: called
0x7f665f62c740 11:06:48.494 [opensc-pkcs11] apdu.c:378:sc_single_transmit: CLA:0, INS:A4, P1:4, P2:0, data(9) 0x7f648bd54660
0x7f665f62c740 11:06:48.494 [opensc-pkcs11] reader-pcsc.c:283:pcsc_transmit: reader 'Yubico Yubikey 4 OTP+U2F+CCID 01 00'
0x7f665f62c740 11:06:48.494 [opensc-pkcs11] reader-pcsc.c:284:pcsc_transmit: 
Outgoing APDU (15 bytes):
00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 00 ...............
0x7f665f62c740 11:06:48.494 [opensc-pkcs11] reader-pcsc.c:212:pcsc_internal_transmit: called
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] reader-pcsc.c:293:pcsc_transmit: 
Incoming APDU (21 bytes):
61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 a.O.......y.O...
00 03 08 90 00                                  .....
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] apdu.c:390:sc_single_transmit: returning with: 0 (Success)
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] apdu.c:543:sc_transmit: returning with: 0 (Success)
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card.c:459:sc_unlock: called
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card-piv.c:744:piv_select_aid: returning with: 0 (Success)
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card-piv.c:981:piv_get_cached_data: called
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card-piv.c:982:piv_get_cached_data: #1
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card-piv.c:1022:piv_get_cached_data: get #1
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card-piv.c:914:piv_get_data: called
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card-piv.c:915:piv_get_data: #1
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card-piv.c:934:piv_get_data: get len of #1
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card-piv.c:486:piv_general_io: called
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card-piv.c:491:piv_general_io: cb 3f ff 5 : 255 256
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card.c:407:sc_lock: called
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card.c:449:sc_lock: returning with: 0 (Success)
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card-piv.c:532:piv_general_io: calling sc_transmit_apdu flags=3 le=8, resplen=8, resp=0x7ffe1ba28b18
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] apdu.c:554:sc_transmit_apdu: called
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card.c:407:sc_lock: called
0x7f665f62c740 11:06:48.495 [opensc-pkcs11] card.c:449:sc_lock: returning with: 0 (Success)
0x7f665f62c740 11:06:48.496 [opensc-pkcs11] apdu.c:521:sc_transmit: called
0x7f665f62c740 11:06:48.496 [opensc-pkcs11] apdu.c:371:sc_single_transmit: called
0x7f665f62c740 11:06:48.496 [opensc-pkcs11] apdu.c:378:sc_single_transmit: CLA:0, INS:CB, P1:3F, P2:FF, data(5) 0x7ffe1ba28b10
0x7f665f62c740 11:06:48.496 [opensc-pkcs11] reader-pcsc.c:283:pcsc_transmit: reader 'Yubico Yubikey 4 OTP+U2F+CCID 01 00'
0x7f665f62c740 11:06:48.496 [opensc-pkcs11] reader-pcsc.c:284:pcsc_transmit: 
Outgoing APDU (11 bytes):
00 CB 3F FF 05 5C 03 5F C1 02 08 ..?..\._...
0x7f665f62c740 11:06:48.496 [opensc-pkcs11] reader-pcsc.c:212:pcsc_internal_transmit: called
0x7f665f62c740 11:06:48.497 [opensc-pkcs11] reader-pcsc.c:293:pcsc_transmit: 
Incoming APDU (2 bytes):
6A 82 j.
0x7f665f62c740 11:06:48.497 [opensc-pkcs11] apdu.c:390:sc_single_transmit: returning with: 0 (Success)
0x7f665f62c740 11:06:48.497 [opensc-pkcs11] apdu.c:543:sc_transmit: returning with: 0 (Success)
0x7f665f62c740 11:06:48.497 [opensc-pkcs11] card.c:459:sc_unlock: called
0x7f665f62c740 11:06:48.497 [opensc-pkcs11] card-piv.c:539:piv_general_io: DEE r=0 apdu.resplen=0 sw1=6a sw2=82
0x7f665f62c740 11:06:48.497 [opensc-pkcs11] iso7816.c:124:iso7816_check_sw: File not found
0x7f665f62c740 11:06:48.497 [opensc-pkcs11] card-piv.c:550:piv_general_io: Card returned error 
0x7f665f62c740 11:06:48.497 [opensc-pkcs11] card.c:459:sc_unlock: called
0x7f665f62c740 11:06:48.497 [opensc-pkcs11] card-piv.c:600:piv_general_io: returning with: -1201 (File not found)
0x7f665f62c740 11:06:48.497 [opensc-pkcs11] card-piv.c:968:piv_get_data: returning with: -1201 (File not found)
0x7f665f62c740 11:06:48.497 [opensc-pkcs11] card-piv.c:1050:piv_get_cached_data: returning with: -1201 (File not found)
0x7f665f62c740 11:06:48.497 [opensc-pkcs11] card-piv.c:2097:piv_get_serial_nr_from_CHUI: Failure retrieving CHUI: -1201 (File not found)
0x7f665f62c740 11:06:48.497 [opensc-pkcs11] card.c:930:sc_card_ctl: returning with: -1201 (File not found)

@dengert
Copy link
Member

dengert commented Jan 23, 2018

Only problem with PIN caching is a PIN PAD reader can not be used without the user having to type the pin twice. Card with builtin readers like Yubico don't have a PIN PAD reader so ti would work for Yubikey.

For a PIN PAD reader, could the verify be postponed and be part of the transaction that does the sign command? For a non PIN PAD reader, could the pin be prompted for as it does today, and held (cached) to do the verify just before the sign operation?

Or make sure the VERIFY with or without a PIN PAD reader, starts a transaction that is only completed after the sign operation. Sort of what I proposed.

@mouse07410
Copy link
Contributor

What currently worked for me:

  • Applied the current PRs.
  • Inserted my PIV+OpenPGP Yubikey, started Apple Mail.
  • Signed a few emails using S/MIME (PIV applet).
  • Signed a few emails using OpenPGP (OpenPGP applet) - smooth transition, no extra operations needed.
  • Tried to sign using S/MIME - failed.
  • Without restarting, ran yubico-piv-tool -a status to re-select PIV applet.
  • Signed email using S/MIME - everything was OK.

Need to test more: repeat the above steps several times.

Preliminary conclusion: PIV driver does not re-select the applet.

  1. What drivers should be involved in this? I think the answer is - only OpenPGP and PIV (with no PIN PAD reader). Simply because the only two applets that we know co-exist together on the same physical token are those.

  2. What seems to be missing? Right now - the ability of PIV driver to "re-acquire" the token after OpenPGP applet was selected and performed an operation.

Or make sure the VERIFY with or without a PIN PAD reader, starts a transaction that is only completed after the sign operation. Sort of what I proposed.

That would be nice.

@dengert
Copy link
Member

dengert commented Jan 23, 2018

@Jakuje looks like the PIV applet does not have a CHUI. thus the file not found. The code uses this to generate a serial number using either the FASN-N in teh CHUI for gov issued cards, or the UUID in the CHUI. (Microsoft Windows driver expects a CHUI.)

The yubico-piv-tool can generate a CHUI for you . The OpenSC can write a CHUI if you have one in a file.

@dengert
Copy link
Member

dengert commented Jan 23, 2018

If you are interested, I was working on having framework.c signal lower levels so verify PIN wold so a lock and sent that when the next command is done, it could release the lock. This is not finished but if you want it might be a start.
opensc.h defines the flags
framework-pkcs15.c says we are doing a CONTEXT_SPECIFIC login.
pkcs15-pin.c gets the extra lock before the verify.
pkcs15-sec.c uses the flag that says the lock has already been held and should unlock when done. Needs to be tested.

verify_CKA_ALWAYS_AUTHENTIC.diff.txt

@mouse07410
Copy link
Contributor

The patch https://github.com/OpenSC/OpenSC/files/1656931/verify_CKA_ALWAYS_AUTHENTIC.diff.txt doesn't apply cleanly on top of this PR. :-(

@frankmorgner
Copy link
Member Author

I've added a new commit that uses GENERAL AUTHENTICATE instead of CHUI, that might work, too...

Only problem with PIN caching is a PIN PAD reader can not be used without the user having to type the pin twice.

I don't think we need to catch all corner cases. If you want to, we can disable the detection mechanism with a PIN pad reader.

Or make sure the VERIFY with or without a PIN PAD reader, starts a transaction that is only completed after the sign operation. Sort of what I proposed.

Yes, that would be possible, but card-dependant and a lot of work. If people should use those tokens, it's time for some corporate engagement. Up to now it seemed that Yubiko is content with what we've got...

@frankmorgner
Copy link
Member Author

@dengert in your patch you could also try to call sc_lock() in piv_pin_cmd() without releasing it with sc_unlock(). OpenSC will hold the lock until you release it in piv_compute_signature(). Interference can be avoided, but of course you should limit this to "PIN always" conditions and you need to release the lock also in various other circumstances...

@mouse07410
Copy link
Contributor

I've added a new commit that uses GENERAL AUTHENTICATE instead of CHUI, that might work, too...

For a token to be a useful PIV, it has to have CHUID. YubiKey tokens come without it, but one can (and should) provision CHUID via yubico-piv-tool. So IMHO it is not important to support PIV tokens without CHUID, because most of the other software that deals with PIV expects CHUID anyway.

I don't think we need to catch all corner cases.

I agree.

And as I said above - I'm not aware of any card with more than one applet that also supports PIN PAD reader. And the only multi-applet token I know of is Yubikey (NEO and 4).

@mouse07410
Copy link
Contributor

Tried again this PR with the current master.

@mouse07410 Ideal would be some concurrent test -- load the pkcs11 module into Firefox, verify the functionality here, then try some signatures with the openPGP applet from pkcs11-tool and than again the Firefox (without loading and unloading).

@Jakuje I don't know how to use pkcs11-tool with OpenPGP applet. Would appreciate an example that I can cut-and-paste (replacing key ID with mine, of course).

When I try to do anything with pkcs11-tool (or openpgp-tool) using openpgp driver, I get SEGFAULT:

Process:               pkcs11-tool [52069]
Path:                  /Library/OpenSC/*/pkcs11-tool
Identifier:            pkcs11-tool
Version:               0
Code Type:             X86-64 (Native)
Parent Process:        bash [1702]
Responsible:           pkcs11-tool [52069]
User ID:               1638356520

Date/Time:             2018-01-23 17:04:33.496 -0500
OS Version:            Mac OS X 10.12.6 (16G1114)
Report Version:        12
Anonymous UUID:        D58BE991-6D4C-06A9-EF6E-900F603E8F18


Time Awake Since Boot: 9600 seconds

System Integrity Protection: enabled

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [0]

VM Regions Near 0:
--> 
    __TEXT                 0000000108baa000-0000000108bc4000 [  104K] r-x/rwx SM=COW  /Library/OpenSC/*

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libopensc.5.dylib             	0x0000000108c2a403 pgp_card_reader_lock_obtained + 131
1   libopensc.5.dylib             	0x0000000108bde974 sc_lock + 244
2   libopensc.5.dylib             	0x0000000108be96f5 sc_transmit_apdu + 197
3   libopensc.5.dylib             	0x0000000108be3471 iso7816_select_file + 977
4   libopensc.5.dylib             	0x0000000108c25372 pgp_match_card + 162
5   libopensc.5.dylib             	0x0000000108bdd384 sc_connect_card + 580
6   opensc-pkcs11.so              	0x000000010905a201 card_detect + 737
7   opensc-pkcs11.so              	0x0000000109059ea4 initialize_reader + 292
8   opensc-pkcs11.so              	0x0000000109054476 C_Initialize + 534
9   pkcs11-tool                   	0x0000000108babfd8 main + 2824
10  libdyld.dylib                 	0x00007fff8f32f235 start + 1

When I try the current master without this PR, it works:

OPENSC_CONF=/Library/OpenSC/etc/opensc-pgp.conf openpgp-tool -U
Using reader with a card: Yubico Yubikey 4 OTP+U2F+CCID
Account:   xxxxxxxx
Name:      xxxxxxxxxxx
Language:  en
Gender:    male
$ OPENSC_CONF=/Library/OpenSC/etc/opensc-pgp.conf pkcs11-tool -s -i ~/src/t256.dat -o t256.dat-sig
Using slot 1 with a present token (0x4)
Logging in to "User PIN (OpenPGP card)".
Please enter User PIN: 
Using signature algorithm RSA-PKCS
error: PKCS11 function C_SignInit failed: rv = CKR_KEY_TYPE_INCONSISTENT (0x63)
Aborting.
$ OPENSC_CONF=/Library/OpenSC/etc/opensc-pgp.conf pkcs11-tool --test
Using slot 1 with a present token (0x4)
C_SeedRandom() and C_GenerateRandom():
  seeding (C_SeedRandom) not supported
  ERR: C_GenerateRandom failed: CKR_FUNCTION_NOT_SUPPORTED (0x54)
Digests:
  all 4 digest functions seem to work
  MD5: OK
  SHA-1: OK
  RIPEMD160: OK
Signature: not a R/W session, skipping signature tests
Verify: not a R/W session, skipping verify tests
Key unwrap: not a R/W session, skipping key unwrap tests
Decryption: not a R/W session, skipping decryption tests
1 errors
$

@dengert
Copy link
Member

dengert commented Jan 23, 2018

Rather then looking at the CHUI or doing a general authenticate, using a VERIFY Lc=empty for P2=80 could be used on Yubikey to test what AID is selected. PIV can uses P2=80 for the normal PIV PIN, or p2=00 for the global pin. OpenPGP appears to use only P2=81, 82 or 83.

The output of that script I sent the 3 of you shows how the responses differs depending on the which AID is active when 00 20 00 80 is sent.

Sending: 00 A4 04 00 06 D2 76 00 01 24 01 00 (Select OpenPGP AID)
Received (SW1=0x90, SW2=0x00) (It selected it )
Sending: 00 20 00 80 (Test PIV pin )
Received (SW1=0x6B, SW2=0x00) (Fails must not be the PIV application)

Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 00 (Select PIV AID)
Received (SW1=0x90, SW2=0x00):
61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 a.O.......y.O...
00 03 08 ... It was selected
Sending:00 20 00 80 (Test PIV pin)
Received (SW1=0x63, SW2=0xC3) (It must be PIV application. but cant tell login state)

From the other test in that output I set you:
Sending: 00 A4 04 00 06 D2 76 00 01 24 01 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 20 00 82
Received (SW1=0x6A, SW2=0x80)
Sending: 00 20 00 82 06 32 32 32 32 32 32 (login to OpenPGP using P2=82)
Received (SW1=0x90, SW2=0x00)
Sending: 00 20 00 82
Received (SW1=0x6A, SW2=0x80) (It should have returned 9000 not 6A80
Sending: 00 A4 04 00 06 D2 76 00 01 24 01 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 20 00 82
Received (SW1=0x6A, SW2=0x80)
Sending: 00 A4 04 00 06 A0 00 00 00 01 01 00 (Selecting Muscle applet which should be ignore)
Received (SW1=0x6A, SW2=0x82)
Sending: 00 20 00 82
Received (SW1=0x6D, SW2=0x00) (It should have ignored the Muscle AID)
Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 00 (Select PIV AID)
Received (SW1=0x90, SW2=0x00):
61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 a.O.......y.O...
00 03 08 ...
Sending: 00 20 00 82
Received (SW1=0x6A, SW2=0x80) (Same response as if OpenPGP applet selected
Sending: 00 A4 04 00 06 D2 76 00 01 24 01 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 20 00 82
Received (SW1=0x6A, SW2=0x80) (Same response :-(

So by just using the 00 20 00 80 The either driver could tell if the PIV or OpenPGP applet is selected.

But this only works between these 2 applications because they don't use the same P2. ANd only on Yubikey. It is not general solution. (A CAC card may have a PIV application too, and may have the problems distinguishing which application is active.)

If Yubico ever fixes the command to returns 9000 when logged in that could help too.

Not sure what the bad command does to the OpenPGP login state. Hopefully nothing.

@mouse07410
Copy link
Contributor

The output of that script I sent the 3 of you ...

@dengert could you please re-send this script? Ideally - to my email, but you can post it here too if you wish.

@frankmorgner
Copy link
Member Author

So by just using the 00 20 00 80 The either driver could tell if the PIV or OpenPGP applet is selected.

As you pointed out, that's true for this token. But command and response codes are standardized by ISO/IEC, there's only little deviation. The interpretation of GENERAL AUTHENTICATE, however, is proprietary (specific to PIV), so it's a better indicator.

@Jakuje
Copy link
Member

Jakuje commented Jan 24, 2018

@mouse07410 thanks for the pointer. I probably skipped the part of initializing CHUID. I will give it one more shot later.

I was using the following command to test the OpenPGP applet with pkcs11-tool from the src/tools build directory (which was only partially successful):

OPENSC_DRIVER=openpgp ./pkcs11-tool --test --module ../pkcs11/.libs/opensc-pkcs11.so --login

There is some problem if you try to load pkcs11 module into pkcs11-tool of different version for some reason, if I remember well.

@dengert
Copy link
Member

dengert commented Jan 24, 2018

The PIV interpretation of GENERAL AUTHENTICATE, is not proprietary. NIST 800-73 appears to be following ISO/IEC 7816-4:2013(E) Section 11.5.5 GENERAL AUTHENTICATE command Tables 99 and 100. But it also says:
"The result (yes or no) of a control performed by the card may conditionally update the security status. The card may record the number of times the function is issued, in order to limit the number of further uses of the relevant secret or the algorithm. The card may record unsuccessful authentications, e.g. to limit the number of further uses of the reference data."

So not only may it be a time consuming command to run, it may have unexpected consequences.
( I don't see any current OpenSC drivers that use 87 so it maybe safe to use today.)

In general we would like to solve the problem of any combination of applications on any card, and our application drivers need to detect if their application is running and what is the security status without causing any additional interference. But today, without PCSC help (tracking any SELECT AID commands) and no common ISO command to tell what is the active application we have to resort to other tricks.
(Do Java or Global Platform cards provide any command?)

Today we are trying to address two applications: PIV and OpenPGP running on the Yubikey.

The ATR of Yubico devices say it is from Yubico and a version number can be read too. So any driver can detect if it using a Yubico card. The PIV sets the card type to SC_CARD_TYPE_PIV_II_NEO or SC_CARD_TYPE_PIV_II_YUBIKEY4. The OpenPGP could do something similar to handle Yuibico as special.

We are also hindered by Yubico's broken SELECT AID handling, (It loses the security state even when selecting the active application) and its broken VERIFY Lc=empty (Never returns '9000'). That is the question at hand. Because we are dealing with only PIV and OpenPGP on Yubikey I favor the use of the VERIFY Lc=empty to test for PIV pin state, in both PIV and OpenPGP drivers. (This may only work for the two applications, so if Yubico adds another application, we may have to add more tests.)

So we need to do special handling for any Yubico devices. The PIV driver currently does some of this. See card-piv.c the CI_CANT_USE_GETDATA_FOR_STATE flag and piv_check_protected_objects comments. It is not clear to me on how to detect the state in the OpenPGP driver for Yubikey.
Maybe trying to access some protected file/object much like toe PIV does.

@mouse07410 has been adding a dummy image file as it is a protected object and is tested by the piv_check_protected_objects

@Jakuje Have you added a dummy Image file? If not the PIV driver can not tell the login state.

For the general case what is still missing is how to tell what application is currently active. Until that can be solved I think we are stuck with solving specific combinations of applications on specific card.
i.e. PIV and OpenPGP on Yubikey.

And we need to look at CAC and PIV on CAC cards. See #1164

@frankmorgner
Copy link
Member Author

The PIV interpretation of GENERAL AUTHENTICATE, is not proprietary. NIST 800-73 appears to be following ISO/IEC 7816-4:2013(E) Section 11.5.5 GENERAL AUTHENTICATE command Tables 99 and 100.

I agree. However, the Data Objects in the Dynamic Authentication Template, especially the one to retrieve a challenge (with a context specific tag), is not defined by any other standard that I know. Hence, it is specific to PIV. (I should not have used the word "proprietary", because it's simply undefined, sorry.)

So not only may it be a time consuming command to run, it may have unexpected consequences.

If using multiple on-card-application is a valid use case and CHUI is not available and VERIFY looks exactly as defined in ISO 7816-4, then I think GENERAL AUTHENTICATE is the only choice, even if it may be slower.

What kind of unexpected consequences are you thinking of? The command is already used today as generic mechanism to gather random data...

My PR should not introduce unnecessary selections of any applet and it should be generic enough, that it doesn't depend on any property of the Yubikey. The problem with the CKA_ALWAYS_AUTHENTICATE PIN needs to be handled with an additional trick (e.g. see my suggestions above). What's missing is the testing, but unfortunately, I cannot aid you guys any further since I don't have such a token...

@dengert
Copy link
Member

dengert commented Jan 24, 2018

@mouse07410 Here is the test script. It uses opensc-tool -c default with a list of -s "xxxx" parameters to send a sequence of APDUs to the card. You will need to edit at least the two VERIFY commands with your PINs for the PIV and OpenPGP applets. And edit the CMD to match your path.

opensc-tool -c default was chosen because it does not introduce any commands from the current PIV or OpenPGP code.
You can add your own tests if you want. Use the script as an example.

To run: test-aid-ef.sh followed by the name of the selected set of command(s). like
test-aid-ef.sh piv.login.state pgp.login.state

The Muscle AID is used to simulate some interference from some other process while trying to set an AID that is not supported by the card. I real PIV card ignores the command. The Yubikey does not.
The default list of drivers in opensc.conf contains a number of drivers that try and select an AID.

test-aid-ef.sh.txt

@dengert
Copy link
Member

dengert commented Jan 24, 2018

You said VERIFY looks exactly as defined in ISO 7816-4" If 00 20 00 80is sent to a Yubikey, If some non existent AID was selected last (on the Yubikey because it has a bug) it will respond6D00`

If PIV application is active it will respond with 63CX (and if Yubico fixes it it could also respond with 9000)

If OpenPGP application is active it will respond with 6B00
The OpenPGP ifonly supports Ps=81, 82, and 83

The test script in #1243 (comment)
can show or be modified to show any behaviour you would like to test.

We are trying to address OpenPGP vs PIV on Yubikey.

@dengert
Copy link
Member

dengert commented Jan 24, 2018

Modifying the script to add:

#use General AUthenticate Challenge to test card
GAC=(-s "00 87 00 9B 04 7C 02 81 00 00")

and

    gac)
        echo test how General Authenticate works
        $CMD "${PIV[@]}" "${GAC[@]}" \
             "${PGP[@]}" "${GAC[@]}" \
             "${MUSCLE[@]}" "${GAC[@]}"
        ;;

Shows:
Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 00
Received (SW1=0x90, SW2=0x00):
61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 a.O.......y.O...
00 03 08 ...
Sending: 00 87 00 9B 04 7C 02 81 00 00
Received (SW1=0x90, SW2=0x00):
7C 0A 81 08 53 53 EE EB 2C A4 55 71 |...SS..,.Uq
Sending: 00 A4 04 00 06 D2 76 00 01 24 01 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 87 00 9B 04 7C 02 81 00 00
Received (SW1=0x6D, SW2=0x00)
Sending: 00 A4 04 00 06 A0 00 00 00 01 01 00
Received (SW1=0x6A, SW2=0x82)
Sending: 00 87 00 9B 04 7C 02 81 00 00
Received (SW1=0x6D, SW2=0x00)

If PIV is active 00 87 00 9B 04 7C 02 81 00 00 returns 9000 20 ms
If PGP is active 00 87 00 9B 04 7C 02 81 00 00 returns 6D00 12 ms
If some other AID was last selected Muscle in this case returns 6D00 11ms

So you can not tell if OpenPGP is active or not. A Yubikey bug that selecting an AID not on the card leaves no AID selected could be the cause. This type of interference could pop up from some other process that was trying to use a different card and causes interference with the Yubikey.

And opensc-debug.log shows when it works it takes 20ms, and when fails 11 ms

@mouse07410
Copy link
Contributor

@frankmorgner I think this PR is OK.
@Jakuje what's your opinion? @dengert I assume you're OK with this PR?

If we're all in agreement, perhaps this PR could be merged, so we can proceed with other improvements like #1256?

@frankmorgner frankmorgner added this to In progress in Release 0.18.0 Feb 2, 2018
@frankmorgner frankmorgner merged commit 88175e3 into OpenSC:master Feb 7, 2018
Release 0.18.0 automation moved this from In progress to Done Feb 7, 2018
@Jakuje
Copy link
Member

Jakuje commented Feb 7, 2018

I reread this PR several times, but I was not able to get back to this because of all the conferences circus of recent two weeks. The changes look good.

I especially like the new naming of PIV cards :) Also the progress with the way of detection of the selected applet is a good way to go if it will actually work. But it was not the case for me unfortunately. Can you recommend some test case for this?

I was trying with openpgp card in ssh-agent, but this failed to provide any signature at all (failing with 6D 00 -- unsupported APDU) from the ssh-agent session for unknown reason (probably different issue -- I will try to dig into that during afternoon. It fails the same way also with current master). I can, on the other hand authenticate directly with ssh and openpgp card or do any other RSA signature from pkcs11-tool ... weird.

@frankmorgner
Copy link
Member Author

You can connect with opensc-explorer and run some card commands. On a second console, use opensc-tool --reset. Everytime the card is reset, opensc-explorer should reselect the OpenPGP applet.

@frankmorgner frankmorgner deleted the applets branch February 7, 2018 13:00
@Jakuje
Copy link
Member

Jakuje commented Feb 7, 2018

Hmm .. both the private keys (signature, authentication) on openpgp applet have non-repudiation flags so this might be the reason why it does not work in ssh-agent either.
Thank you for clarification. I will give it a try with the opensc-explorer, though I would rather see some real-world test case.

@Jakuje
Copy link
Member

Jakuje commented Feb 7, 2018

OK, I just put together simple program that is doing signatures every 10 seconds with the OpenPGP applet and if I start interfering with pkcs11-tool, the signatures and logins start to fail.

Correct me, if I am testing something else than you or if there is some trick that needs to be configured so the keep_alive function is effective. My reproducer:

  1. terminal:
  1. Terminal:
  • OPENSC_DRIVER=PIV-II ./src/tools/pkcs11-tool -O

I would expect that both of the sessions should work, if the keep_alive is effective and the OpenPGP driver has a way to check that it is selected before going into sending APDUs that are going to fail because other applet is selected.

@frankmorgner
Copy link
Member Author

Going through the testing again, I've discovered some more problems (see #1264). Anyway, these problems should not touch your use case. Have you updated your opensc.conf to contain keep_alive for your ATR (can you post the excerpt)?

@frankmorgner
Copy link
Member Author

Note that keep_alive doesn't revalidate the PIN if the applet is deselected, which should cause your test to fail.

@Jakuje
Copy link
Member

Jakuje commented Feb 7, 2018

I was updating the opensc.conf before to have the new ATRs and flags. Now, I tried with the one in master:

$ sudo cp etc/opensc.conf /usr/local/etc/
$ pcsc_scan 
[...]
ATR: 3B F8 13 00 00 81 31 FE 15 59 75 62 69 6B 65 79 34 D4
[...]
$ grep -C 3 -i 3B:F8:13:00:00:81:31:FE:15:59:75:62:69:6B:65:79:34:D4 /usr/local/etc/opensc.conf
	# Yubikey is known to have the PIV applet and the OpenPGP applet. OpenSC
	# can handle both to access keys and certificates, but only one at a time.
	card_atr 3b:f8:13:00:00:81:31:fe:15:59:75:62:69:6b:65:79:34:d4 {
		name = "Yubikey 4";
		# Select the PKI applet to use ("PIV-II" or "openpgp")
		driver = "PIV-II";

Then running the repetitive signatures (fisrt two are not interrupted, third one is):

$ OPENSC_DRIVER=openpgp ./sign_repeat 2> /dev/null
C_Login() done, rv = 0
C_SignInit() done, rv = 0
C_Login(CKU_CONTEXT_SPECIFIC) done, rv = 0
C_Sign() done, rv = 0
C_Verify() done, rv = 0
C_SignInit() done, rv = 0
C_Login(CKU_CONTEXT_SPECIFIC) done, rv = 0
C_Sign() done, rv = 0
C_Verify() done, rv = 0
C_SignInit() done, rv = 0
C_Login(CKU_CONTEXT_SPECIFIC) done, rv = 32 (CKR_DATA_INVALID)
C_Sign() done, rv = 5 (CKR_GENERAL_ERROR)
C_Verify() done, rv = 0

And before the last attempt I used the PIV driver:

$ OPENSC_DRIVER=PIV-II ./src/tools/pkcs11-tool --sign --id 02 --mechanism RSA-PKCS --input-file data.ssh1 --output-file data.ssh.sig

This is making it fail with current master (with keepalive PR merged).

Note that keep_alive doesn't revalidate the PIN if the applet is deselected, which should cause your test to fail.

What you mean by this? The other process deselected the applet. But was not this what we were trying to solve? Or we are solving the deselection only from single thread/process?

@dengert
Copy link
Member

dengert commented Feb 7, 2018

The PIV-II driver does not use the keep-alive. You need #1256 which is its version of all the interference and detection of AIDs. It does its own version of keep alive based on the ATR history bytes.

@frankmorgner
Copy link
Member Author

Passing OPENSC_DRIVER=openpgp will disable parsing of opensc.conf, which will not enable keep_alive. I think passing a different configuration via OPENSC_CONF should work.

I didn't notice that your test program is performing C_Login() every time (which is something keep_alive is not doing). In this case, your program should work as expected if keep_alive for OpenPGP is enabled and a different applet gets selected.

@Jakuje
Copy link
Member

Jakuje commented Feb 8, 2018

Sigh ... I missed that part. It is indeed very confusing that setting environment variables prevent parsing the whole configuration file. Do you think, there is anything we can do about it? For example parse everything except the drivers selection in that file? Do we have an issue for that? If not, I will open one.

Thanks for the pointers. I will try that without OPENSC_DRIVER. But I will need to configure this Yubikey, since I left mine at home.

@frankmorgner
Copy link
Member Author

Yes, it's confusing; I've been in that dead end, too. Feel free to open an issue.

@Jakuje
Copy link
Member

Jakuje commented Feb 9, 2018

Ok, now I finally have the Yubikey with me and I performed the same test as in previous comments with more surprising results.

While the sign_repeat test is running, the other process is blocked in pcsc_detect_readers() function until the first process disconnects:

(gdb) bt
#0  0x00007f05ba1aa2c7 in select () at /lib64/libc.so.6
#1  0x00007f05b845c265 in MessageReceive () at /lib64/libpcsclite.so.1
#2  0x00007f05b8457a30 in SCardConnect () at /lib64/libpcsclite.so.1
#3  0x00007f05bb892c07 in pcsc_detect_readers (ctx=0x1765e70) at reader-pcsc.c:1403
#4  0x00007f05bb8622de in sc_ctx_detect_readers (ctx=ctx@entry=0x1765e70) at ctx.c:727
#5  0x00007f05bb862c13 in sc_context_create (ctx_out=0x7f05b8892e88, parm=<optimized out>) at ctx.c:857
#6  0x00007f05b866b0cc in C_Initialize () at /lib64/opensc-pkcs11.so
#7  0x000000000040414d in main (argc=<optimized out>, argv=0x7ffd894ee348) at pkcs11-tool.c:894

Only after that I was able to get the result of the pkcs11-tool from PIV applet. Given that, concurrent access is resolved be preventing the concurrent access. Or I have some flaw in my sign_repeat program, or there is some flaw in the reader-locking logic of the keep_alive functionality?

What do you think? Attaching the debug log from the sign_repeat run:
opensc-debug.log

@dengert
Copy link
Member

dengert commented Feb 9, 2018

looking at https://github.com/OpenSC/OpenSC/files/1710677/opensc-debug.log
shows that in lines:
166 reader-pcsc.c:612:pcsc_lock: called
167 card-openpgp.c:2876:pgp_card_reader_lock_obtained: called

It then shows the '4F' object returned with 16 bytes,

190 card-openpgp.c:2902:pgp_card_reader_lock_obtained: returning with: 16
191 card.c:449:sc_lock: returning with: 16
192 apdu.c:566:sc_transmit_apdu: unable to acquire lock

But the lock was obtained, its that pgp_card_reader_lock_obtained should have returned 0 even if it failed. The pgp_card_reader_lock_obtained is in effect inserting command just after the sCardBeginTransaction has been obtained. It should return 0 if it works, and could return < 0 of there
is a bad error.

(TODO need to look closer at sc_lock to see if *_card_reader_lock_obtained returns
a real error. Should it release the lock? )

Since the sc_lock that caused the pcsc_lock and pgp_card_reader_lock_obtained was from
138 apdu.c:554:sc_transmit_apdu: called
it did not finish the command, and did not release the lock in line 192 above but returned 16

Try adding to openpgp_card_reader_obtained:
2902 if (r > 0)
2903 r = 0;
2904

@frankmorgner
Copy link
Member Author

@Jakuje you need to apply #1264, the locking problem is fixed there.

@Jakuje
Copy link
Member

Jakuje commented Feb 9, 2018

@frankmorgner Thank you for having a look into that. Yes, with #1264 I can see it finally works as expected. Good job!

dengert added a commit to dengert/OpenSC that referenced this pull request Feb 19, 2018
Experimental: PKCS#11 Support for Multiple Applications on One Card

Prior to this modification  there has been a 1-to-1 relationship between
the list of readers returned by PCSC and a card driver. With this mod
each reader returned by PCSC may have  more then one card driver.
This gives each card driver its own PCSC handle and lock, and allows
OpenSC PKCS#11 to support more then one applet on a card
For example OpenPGP and PIV or PIV and CAC.

sc_reader_t now has name (as seen by users and applications) and
pname the name used by PCSC.

when a card is first found, the name and pname are the for the first
or only card driver. if another card driver can support this card,
its reader name with be teh pname followed by [N] where N starts with 1.

reader or a cloned/virtual reader can each have 4 virtual slots.

Minimal tseting has been done.

No testing with threads. It may need some mutexs as weach card driver
gets its oen PCSP lock and pkcs11 session. So this code depends on OpenSC#1243 and OpenSC#1256

It is a change from  current OpenSC, and maybe should be off by  default
and turned on in opensc.conf.

It is only active with PCSC whe used from  PKCS#11.

On branch pkcs11-multi-application
 Changes to be committed:
	modified:   src/libopensc/card.c
	modified:   src/libopensc/ctx.c
	modified:   src/libopensc/libopensc.exports
	modified:   src/libopensc/opensc.h
	modified:   src/libopensc/reader-pcsc.c
	modified:   src/pkcs11/slot.c
frankmorgner added a commit that referenced this pull request Mar 16, 2018
PIV detection of AID using Discovery Object before doing select AID - Partial 
 #1243
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

4 participants