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

Avoid non SELECT(AID) commands for probing #3108

Open
CardContact opened this issue Apr 10, 2024 · 28 comments
Open

Avoid non SELECT(AID) commands for probing #3108

CardContact opened this issue Apr 10, 2024 · 28 comments

Comments

@CardContact
Copy link
Member

Further digging into #3107 I've extracted probing APDUs that are not SELECT(AID) APDUs:

00000010 [140479840638656] APDU: 00 CA DF 30 05
00008056 [140479840638656] SW: 6A 80
00000018 [140479840638656] APDU: 00 CB 3F FF 03 5C 01 7E 00
00005369 [140479840638656] SW: 6E 00
00000020 [140479840638656] APDU: 00 A4 00 0C 02 3F 00
00005586 [140479840638656] SW: 6A 86
00000011 [140479840638656] APDU: 00 A4 00 00 02 3F 00
00004883 [140479840638656] SW: 6A 86

The INS CA seems to be issued by the setcos driver.
The INS CB comes from the PIV driver.
The INS A4 seems to be related to the JPKI driver.

The issue with these APDUs is, that they potentially interfere with an application that is not supported by OpenSC.

In our case, the probing APDUs end up in a running applet that has an establish secure messaging channel. That channel is interrupted at plain APDUs for security reasons. SELECT(AID) for probing is fine, as those APDUs are handled by the JCVM and don't reach the applet. But all other APDUs are passed to the applet that uses the card in non-exclusive mode.

To have better coexistence with other card aware applications, we should avoid sending non SELECT(AID) APDUs for probing, unless we match the ATR on a white list. And that whitelist should be specific enough and not catch just all JavaCards.

@dengert
Copy link
Member

dengert commented Apr 10, 2024

We live in a smart card jungle:

  • applets that can be loaded on almost any card, so the way to identify the applet is not by ATR, but by select AID.
  • cards or card vendors that support multiple applets on the same card. PIV and OpenPGP for example.
  • applets that treat any select AID as just a select file and trick a card driver that did not check the response to select AID for the AID in the response, Muscle card for example.
  • cards that will allow non-APDUs to be done in between SM protected APDUs without requiring reestablishment of SM. NIST PIV SM for example.
  • cards that are not supported (yet) by OpenSC, that if they were, would not have the problem in OpenSC in Firefox constantly sending SELECT(AID) APDUs for probing #3107 or Avoid non SELECT(AID) commands for probing #3108.

Some remedies to the above:

  • provide OpenSC support for the device. (I assume you will be doing that?)
  • ignore, treat as error or allow non-SM APDU while in a the middle of a SM session
  • card driver can lock the card to avoid interference from other applications during some critical sequences of APDUs.
  • whitelists or blacklists
  • Use opensc.conf or OPENSC_DRIVER= to only use selected driver or drivers or change the order of driver selection.

card-piv.c uses 00 CB 3F FF 03 5C 01 7E 00 to detect if card has DISCOVERY object and PIV applet is selected. It does this because some early Yubikey devices would lose the login state if a SELECT AID for PIV applet was sent. Other cards just treat this GET DATA as unknown object, and it has not caused any other issues.

There is no good solution that applies all.

This is not an OpenSC only issue. p11-kit and FireFox can load multiple PKCS11 modules which may cause the same problems.

I would suggest you consider allowing non-APDUs to be done in between SM protected APDUs without requiring reestablishment of SM.

@CardContact
Copy link
Member Author

I agree with the smart card jungle, but that is also the reason we should be careful not to interfere with other applications in the same system.

And IMHO sending APDUs to unknown cards is not the right way to probe. If we need probing with non SELECT(AID) APDUs, then we should us a white list of ATRs to limit that effect.

Allowing plain APDUs in an established secure messaging context is of course a bad idea, as it defeats the purpose of such a channel: Protect the integrity, authenticity and confidentiality of an APDU sequence and it's content.

We have two well established mechanism to detect a card: The ATR and the AID. We can also use the VID/PID of USB devices to detect the device type. I don't see a need to just blindly send probing APDUs.

I understand the mechanism implemented in Yubikey to reset the authentication state during a SELECT(AID), as we use the same. But we only probe with a VERIFY, if the ATR matches one of our cards.

Probing adds a major complication for our customers that personalize SmartCard-HSMs. As this process is browser based, they need to disable OpenSC whenever they want to manage devices via the PKI-as-a-Service portal.

We usually recommend to uninstall OpenSC and use our own PKCS#11 module, that does not show this kind of behavior. But I guess this is not what we won't.

So yes, this is an OpenSC problem.

And no, the card will never be integrated in OpenSC, as there are other smartcard applications outside the PKCS#11 space.

@dengert
Copy link
Member

dengert commented Apr 12, 2024

I agree with the smart card jungle, but that is also the reason we should be careful not to interfere with other applications in the same system.

And IMHO sending APDUs to unknown cards is not the right way to probe. If we need probing with non SELECT(AID) APDUs, then we should us a white list of ATRs to limit that effect.

Allowing plain APDUs in an established secure messaging context is of course a bad idea, as it defeats the purpose of such a channel: Protect the integrity, authenticity and confidentiality of an APDU sequence and it's content.

OK I understand, and have tested a fix for card-piv.c to not try and read the interindustry DO '7E' using GET DATA, before doing a SELECT AID unless the user forced the card type, or the ATR matched a known PIV type card. This changed slipped in during a rewrite of the PIV selection process as there are too many "PIV-like" implementations:

diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c
index d7e3a4865..98d31cfed 100644
--- a/src/libopensc/card-piv.c
+++ b/src/libopensc/card-piv.c
@@ -5468,9 +5468,16 @@ static int piv_match_card_continued(sc_card_t *card)
         * Will fail for other reasons if wrong applet is selected or bad PIV implementation.
         */
 
-       /* first test if PIV is active applet without using AID If fails use the AID */
+       /*
+       * if ATR matched or user forced card type 
+       * test if PIV is active applet without using AID If fails use the AID 
+       */
+
+       if (card->type != SC_CARD_TYPE_PIV_II_BASE)
+               r = piv_find_discovery(card);
+       else
+               r = SC_CARD_TYPE_UNKNOWN;
 
-       r = piv_find_discovery(card);
        if (r < 0) {
                piv_obj_cache_free_entry(card, PIV_OBJ_DISCOVERY, 0); /* don't cache  on failure */
                r = piv_find_aid(card);

I hope to look at the other card driver you mentioned.

I tested this using a "Card Contact - SmartCard-HSM" token you had provided many years ago. Having such a device has helped debug issues over the years. A newer token would be very helpful. In order to simulate an unknown ATR, I commented out the ATR for this device in card-sc-hsm.c.

OpenSC has a list: internal_card_drivers of card drivers with the drivers that only use ATRs, then drivers which send APDUs to help identify the device. You will note line 150 has { "sc-hsm", (void *(*)(void)) sc_get_sc_hsm_driver }, and the 3 drivers causing the problems are in lines 152, 153, and 161. So if the "sc-hsm" driver supported the token with a new ATR, the other drivers would never be called.

But if using an older version of OpenSC, without the latest "sc-hsm" could still cause a problem.
I will still look at the other drivers to see if if they could do SELECT AID test first.

We have two well established mechanism to detect a card: The ATR and the AID. We can also use the VID/PID of USB devices to detect the device type. I don't see a need to just blindly send probing APDUs.

I understand the mechanism implemented in Yubikey to reset the authentication state during a SELECT(AID), as we use the same. But we only probe with a VERIFY, if the ATR matches one of our cards.

Probing adds a major complication for our customers that personalize SmartCard-HSMs. As this process is browser based, they need to disable OpenSC whenever they want to manage devices via the PKI-as-a-Service portal.

We usually recommend to uninstall OpenSC and use our own PKCS#11 module, that does not show this kind of behavior. But I guess this is not what we won't.

So yes, this is an OpenSC problem.

And no, the card will never be integrated in OpenSC, as there are other smartcard applications outside the PKCS#11 space.

Sorry to hear that, as the original driver in 2012 was form CardContact: "Copyright (C) 2012 Andreas Schwier, CardContact, Minden, Germany, and others" and "Andreas Schwier" has provided patches in 2023 too.
@CardContact is listed as an OpenSC maintainer.

@CardContact
Copy link
Member Author

Sorry to hear that, as the original driver in 2012 was form CardContact: "Copyright (C) 2012 Andreas Schwier, CardContact, Minden, Germany, and others" and "Andreas Schwier" has provided patches in 2023 too.
@CardContact is listed as an OpenSC maintainer.

This is not a SmartCard-HSM card, but a different applet we developed for a customer. This is unrelated to the SmartCard-HSM as a product. That other card does not have PKI functions exposed by a PKCS#11 interface.

@CardContact
Copy link
Member Author

I tested this using a "Card Contact - SmartCard-HSM" token you had provided many years ago. Having such a device has helped debug issues over the years. A newer token would be very helpful. In order to simulate an unknown ATR, I commented out the ATR for this device in card-sc-hsm.c.

We are currently in the process to establish SmartCard-HSM production in the US. Once that is up and running, I'll ask them to provide you with fresh SmartCard-HSMs for testing.

The samples from from 2013 were send to ANL, so I guess I need an updated shipping address. Let me know at web@cardcontact.de.

@dengert
Copy link
Member

dengert commented Apr 12, 2024

Some additional information on OpenSC Select AID commands.

With the card that is failing and running this with OpenSC 0.25.0
./opensc-tool -v -v -v --serial 2>&1 | grep -n "sc_connect_card: trying driver\|^00 A4 04 0\|^6A 8" would show what your card does not like.

The command will produce a list of card drivers being selected and all possible "SELECT AID" type commands that are sent to the card and responses of 6A 8x

ISO7816-4 says for Select AID P1 = 04 and P2 = 00, but OpenSC drivers in some cases are sending P2 = 0C which is not a proper SELECT AID and the card OS may be passing this to the applet.

I proper SELECT AID sequence should not use P2 = 0C to indicate it does not want a response, as a proper response will have the AID and it should be tested for a match.

In my case "driver 'cac'" sends APDUs with 00 A4 04 0C followed by a 00 A4 04 00. The first fails with 6A 82 "File or application not found" then second failing with 6A 86 "Incorrect parameters P1-P2" (Looks like a bad implementation of Select AID on 'cac' cards.)

I don't see and for "driver 'setcos'" was this really the cac driver?

"driver 'jpki'" sends once00 A4 04 0C 0A D3 92 F0 00 26 01 00 00 00 01 which fails. (I will look for a fix for this But I can't test it.)

"driver 'cac1'" sends out 15 proper APDUs all fail with 6A 82 "File or application not found" which should not cause any problems, but why 15?

Also note that an AID can start with 0-9 reserved for backward compatibility, A - International, B - RFU, C - RFU, D - National, E - Standard, and F - Proprietary.

My TODO list is fix PIV to not use 7E before SELECT AID and look at jpki.

@Jakuje any idea what the cac and cac1 cards are doing? Do they have to use the 0C?

@dengert
Copy link
Member

dengert commented Apr 12, 2024

This is not a SmartCard-HSM card, but a different applet we developed for a customer. This is unrelated to the SmartCard-HSM as a product. That other card does not have PKI functions exposed by a PKCS#11 interface.

But it does respond to ISO-7816 commands. May be it could use some extra hardening code to reject any commands it does not understand while not losing the SM connection?

OpenSC is not the only smart card middleware that the card might run into.

@CardContact
Copy link
Member Author

But it does respond to ISO-7816 commands. May be it could use some extra hardening code to reject any commands it does not understand while not losing the SM connection?

Unfortunately the card does understand the GET DATA command, but does no have the object requested. So there is no real good mechanism to differ legitimate GET DATA commands from the once that do probing.

All of this would be no problem, if OpenSC inspects the card only once and then leaves it alone. But that does not seem to happen with the latest integration in Firefox. What I see, is that for an unknown card, the sequence of sending SELECT(AID) commands takes a couple of seconds, during which the browser blocks. And that happens over and over again.

I'm pretty sure that behavior is new.

dengert added a commit to dengert/OpenSC that referenced this issue Apr 12, 2024
During card matching, only use GET DATA of Discovery object before
or in place of SELECT AID, if the ATR matches a known card or user
has forced the card type or forced the use of a PIV driver.

This avoids possible state change in the unknown card if used by other processes.

partial fox for OpenSC#3108

 On branch piv-fix-OpenSC#3108
 Changes to be committed:
	modified:   card-piv.c
@dengert
Copy link
Member

dengert commented Apr 12, 2024

Unfortunately the card does understand the GET DATA command, but does no have the object requested. So there is no real good mechanism to differ legitimate GET DATA commands from the once that do probing.

good point. But the object requested is an interindustry 7E command that is expected to return the AID, so even if it returned it would not have the PIV AID.

See #3112 that avoids using the GET DATA 7E if the ATR does not match known PIV cards, or the user forced the use of PIV driver or user forced the card type. This is only PIV part of problem.

Also see #3111 which is possible fix for JPKI and needs to be tested with a JPKI card.

@Jakuje knows about the CAC cards.

All of this would be no problem, if OpenSC inspects the card only once and then leaves it alone. But that does not seem to happen with the latest integration in Firefox. What I see, is that for an unknown card, the sequence of sending SELECT(AID) commands takes a couple of seconds, during which the browser blocks. And that happens over and over again.

An OpenSC debug log may show why.

@frankmorgner
Copy link
Member

We already had quite some debate about piv_match_card_continued() where I argued that the match_card callback should only be used to check IF we can handle the card, whereas init expresses the intent to actually use the card. As consequence, match_card should only set the card name and type, but leave the private data alone (as this has also been causing memory leaks in the past). The compromise back then was that the piv driver still initialized the private data in match_card(), but deleted it at the end of the function (only to re-initialize it in init()). Now we are seeing that this extensive matching causes problems to the outside world as well and I think we should simplify this part finally in match_card and only do the complex initialization in init.

That being said, I don't believe a simple matching function of the PIV driver will actually solve the problem. Selecting the AID (non-SM APDU) should cause an SM channel to collaps as well. We also need to find out why match_card is called over and over again, although no new card has been entered...

@dengert
Copy link
Member

dengert commented Apr 13, 2024

We already had quite some debate about piv_match_card_continued() where I argued that the match_card callback should only be used to check IF we can handle the card, whereas init expresses the intent to actually use the card.

And that is what current code it is doing. piv_match_card_continued is called from piv_match_card. piv_match_card_continued will allocate card->drv_data as this is needed to do some of the APDUs. And it expects card->drv_data to be set when piv_init is called. If card->drv_data is not set piv_match_card_continued will be called again https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card-piv.c#L5701
(The current master and for many version is passing card->drv_data. )

Here are two opensc-debug logs. Both from testing with #3111 and #3112 with ./opensc-tool --serial

opensc-debug-22-unknown-card.txt This uses a CardContact token with the card-sc-hsm.c modified to not recognize it, so all other drivers including PIV and JPKI will try and match. piv-init is never called as piv_match_card_continued issued one SELECT AID which fails as token is not PIV and piv_finish was called to cleanup.

opensc-debug-22-piv-card-found.txt This is using the same code with a PIV card to show how it is matched. piv-init is called and card->drv_data was passed, and serial number was found.

Now we are seeing that this extensive matching causes problems to the outside world.

Yes there was a bug and PR #3112 has been submitted to fix that problem.

The extensive matching is needed because there are so many versions of PIV and "PIV-like" cards and applets all with their own issues. We even added the SwissBit feature to that list. (but so far has not had an issue.)

@CardContact
Copy link
Member Author

opensc-firefox.log

Looks to me, as if after the

sc_connect_card: returning with: -1210 (Card is invalid or cannot be handled)

the unknown card is disconnected and then the loop starts over with a fresh probing.

Do we store somewhere the result of unsuccessful probing ?

P:120772; T:0x140541282104512 10:44:44.279 [opensc-pkcs11] card-eoi.c:239:eoi_match_card: returning with: 0 (Success)
P:120772; T:0x140541282104512 10:44:44.279 [opensc-pkcs11] card.c:341:sc_connect_card: trying driver 'default'
P:120772; T:0x140541282104512 10:44:44.279 [opensc-pkcs11] card.c:347:sc_connect_card: ignore 'default' card driver
P:120772; T:0x140541282104512 10:44:44.280 [opensc-pkcs11] card.c:371:sc_connect_card: unable to find driver for inserted card
P:120772; T:0x140541282104512 10:44:44.282 [opensc-pkcs11] reader-pcsc.c:674:pcsc_disconnect: Identive CLOUD 2700 R Smart Card Reader [CCID Interface] (53692026211881) 02 00:SCardDisconnect returned: 0x00000000
P:120772; T:0x140541282104512 10:44:44.282 [opensc-pkcs11] card.c:403:sc_connect_card: returning with: -1210 (Card is invalid or cannot be handled)
P:120772; T:0x140541282104512 10:44:44.282 [opensc-pkcs11] slot.c:268:card_detect: Identive CLOUD 2700 R Smart Card Reader [CCID Interface] (53692026211881) 02 00: SC connect card error -1210
P:120772; T:0x140541282104512 10:44:44.282 [opensc-pkcs11] misc.c:72:sc_to_cryptoki_error_common: libopensc return value: -1210 (Card is invalid or cannot be handled)
P:120772; T:0x140541282104512 10:44:44.282 [opensc-pkcs11] slot.c:128:create_slot: Creating new slot
P:120772; T:0x140541282104512 10:44:44.282 [opensc-pkcs11] slot.c:163:create_slot: VSS Finished initializing this slot
P:120772; T:0x140541282104512 10:44:44.282 [opensc-pkcs11] slot.c:219:card_detect: Identive CLOUD 2700 R Smart Card Reader [CCID Interface] (53692026211893) 03 00: Detecting smart card
P:120772; T:0x140541282104512 10:44:44.282 [opensc-pkcs11] sc.c:340:sc_detect_card_presence: called
P:120772; T:0x140541282104512 10:44:44.282 [opensc-pkcs11] reader-pcsc.c:471:pcsc_detect_card_presence: called
P:120772; T:0x140541282104512 10:44:44.282 [opensc-pkcs11] reader-pcsc.c:361:refresh_attributes: Identive CLOUD 2700 R Smart Card Reader [CCID Interface] (53692026211893) 03 00 check
P:120772; T:0x140541282104512 10:44:44.284 [opensc-pkcs11] reader-pcsc.c:386:refresh_attributes: returning with: 0 (Success)
P:120772; T:0x140541282104512 10:44:44.284 [opensc-pkcs11] reader-pcsc.c:481:pcsc_detect_card_presence: returning with: 0 (Success)
P:120772; T:0x140541282104512 10:44:44.284 [opensc-pkcs11] sc.c:351:sc_detect_card_presence: returning with: 0 (Success)
P:120772; T:0x140541282104512 10:44:44.284 [opensc-pkcs11] slot.c:228:card_detect: Identive CLOUD 2700 R Smart Card Reader [CCID Interface] (53692026211893) 03 00: card absent
P:120772; T:0x140541282104512 10:44:44.284 [opensc-pkcs11] slot.c:191:card_removed: Identive CLOUD 2700 R Smart Card Reader [CCID Interface] (53692026211893) 03 00: card removed
P:120772; T:0x140541282104512 10:44:44.284 [opensc-pkcs11] slot.c:501:slot_token_removed: slot_token_removed(0x3)
P:120772; T:0x140541282104512 10:44:44.284 [opensc-pkcs11] pkcs11-session.c:145:sc_pkcs11_close_all_sessions: real C_CloseAllSessions(0x3) 0
P:120772; T:0x140541282104512 10:44:44.284 [opensc-pkcs11] slot.c:128:create_slot: Creating new slot
P:120772; T:0x140541282104512 10:44:44.284 [opensc-pkcs11] slot.c:163:create_slot: VSS Finished initializing this slot
P:120772; T:0x140541282104512 10:44:44.284 [opensc-pkcs11] slot.c:219:card_detect: Identive CLOUD 2700 R Smart Card Reader [CCID Interface] (53692026211901) 04 00: Detecting smart card
P:120772; T:0x140541282104512 10:44:44.284 [opensc-pkcs11] sc.c:340:sc_detect_card_presence: called

@dengert
Copy link
Member

dengert commented Apr 13, 2024

Do we store somewhere the result of unsuccessful probing ?

Not as far as I know, but we do have a default driver card-default.c which sets card->name = "Unsupported card";
but it was designed to support the minimal ISO-7816-4.

Which could be enabled for pkcs11:
https://github.com/OpenSC/OpenSC/blob/master/etc/opensc.conf.example.in#L35-L39
also have a way to ignore selected readers, but many cards/tokens use the same readers.

We could have a list of unknow unsupported ATRs in opensc.conf.

Or if card is not supported to have a PKCS11 slot that that is allocated (to avoid probing it again) but does not allow any pkcs11 operations, i.e. may look like empty slot? but still has PCSC connection. That could be the default driver which can be detected by the card_>name = "Unsupported card". So it would get probed once when application OpenSC pkcs11 module is loaded and does initial setup of PKCS11 slots.

@dengert
Copy link
Member

dengert commented Apr 13, 2024

Using pkcs11-tool --test --login with an unknown card will get to:
https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card.c#L370-L373 then
https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card.c#L398-L403
where it disconnects from PCSC, so the next time it will try and match all the drivers again. card->atr has the ATR of the card that is failing.

(gdb) x/24xb &card->atr
0x5555555aa1e0:	0x3b	0xfe	0x18	0x00	0x00	0x81	0x31	0xfe
0x5555555aa1e8:	0x45	0x80	0x31	0x81	0x54	0x48	0x53	0x4d
0x5555555aa1f0:	0x31	0x73	0x80	0x21	0x40	0x81	0x07	0xfa

The disconnect is done 4 times with the above command before it ends. With FireFox it may be many more times,
and FireFox may call C_Finalize followed by C_Initialize multiple times with or without unloading the PKCS11 module.

The minimum that could be done is to save the ATR (but where especially if PKCS11 module is unloaded) and next time skip this ATR before searching for a driver.

Trying with enable_default_driver = true; makes it worse, as the default driver is used from https://github.com/OpenSC/OpenSC/blob/master/src/pkcs11/framework-pkcs15.c#L335-L339
which tries to bind as pkcs15 card and issues several more APDUs before failing and disconnecting.

So this is a serious problem.

With both unsupported card and supported card, pkcs11 still fails as the unsupported card fails so sc_disconnect_card
is called on failure.

OpenSC will face this problem with other unsupported cards too and need a better solution then to uninstall OpenSC.

@frankmorgner
Copy link
Member

@CardContact what's the reason you don't have an exclusive (or locked) connection to the card? If you don't want some other process to interfere with your connection, this is what you should do...

@dengert
Copy link
Member

dengert commented Apr 15, 2024

I have started to look at using opensc.conf with card_atr xx:xx:xx { driver = "blacklist"; } i.e. force using a dummy driver that would in effect mark the reader with this card as no card present, thus not allowing OpenSC to do any commands to the card. The only command to the card was to read the ATR in the first place.

Note that the "default" driver is used if no other driver matched the card. But the "default" driver is not enabled for PKCS11.

The original complain was the probing by many drivers was a problem as will as the "default" driver trying PKCS15 commands.

So if default driver is not used any ATR not matched could be added to the current context, so next time the card ATR is read, it would be treated as if it was blacklisted. This would keep OpenSC from only casing some issue once rather then repeatedly as was seen. in this issue. It might be possible to save this as long as the PKCS11 module is loaded. or maybe for the login session if stored in tmp.

@Jakuje
Copy link
Member

Jakuje commented Apr 16, 2024

@Jakuje any idea what the cac and cac1 cards are doing? Do they have to use the 0C?

According to the GSC-IS 2.1 the CAC should accept P2=0x0C as well as 0x00. I think the 0x0C was used just for simplicity as we did not want to bother with replies.

That being said, I don't believe a simple matching function of the PIV driver will actually solve the problem. Selecting the AID (non-SM APDU) should cause an SM channel to collaps as well. We also need to find out why match_card is called over and over again, although no new card has been entered...

Is the OpenSC added to the Firefox directly or through p11-kit? If the other, the p11-kit does not support proxying C_WaitForSlotEvent(), which might cause this behavior.

@CardContact
Copy link
Member Author

OpenSC is installed without p11-kit. This is vanilla Debian testing.

@frankmorgner Using exclusive access has a lot of other issues, as one can see with the exclusive locking used by scdaemon in GnuPG. And there is no way to detect in an application, that some other processes is using exclusive access or SCardBeginTransaction. The call to SCardConnect just blocks and the user does not get a clue why.

And if memory serves me right, then Windows will kill long running transactions on a smart card. But we have exactly those long running session, when SmartCard-HSM are connected to the PKIaaS portal.

@frankmorgner
Copy link
Member

We have frequent probing of an unsupported card, even though no new card event has happened. This, I think, is a real problem that should be fixed and it is considered in #3107.

The request in this issue, however, is that we should only use SELECT AID for probing, but not any other command, because the other commands may interfere with some other process. This issue is invalid, I think:

  • If you do not want that some other process interrupts your connection to the card, you should use some (temporary) exclusive connection, e.g. by using SCardReconnect(...SCARD_SHARE_EXCLUSIVE...) or SCardBeginTransaction(). SCardTransmit will be aborted by Windows after a couple of seconds, which is not related to this. I don't think it is true that you cannot detect an exclusively locked card, because pcsc_scan shows exclusive access even without having access to the card.
  • There are cards known to OpenSC, which respond 9000 to any Select AID, which means that this command is not useful to detect the card type. In this case, we need to send other commands to detect the correct type of card.

That being said, I agree that we should be very deliberate in what commands we are sending, because it may leave the card in some undefined or unwanted state. So #1549 is definately a step in the right direction. Your request, @CardContact , however, has an SM channel in mind, which will break with any unencrypted command. In particular it will break with any unencrypted SELECT AID. Even though only using SELECT AID for card detection is in general a good idea, it doesn't actually solve your problem.

@CardContact
Copy link
Member Author

Limiting to SELECT(AID) for probing cards that are not identified by the ATR does solve the problem for JavaCards. The SELECT(AID) is handled by the JCVM and does not reach the applet. So it does not break SM.

My point is, that we should not issue other commands than SELECT(AID) to cards we don't know, meaning cards whose ATR is not recognized any on of the driver. This is what causes the issue.

If have a banking card sitting the reader, then you should not just send probing APDUs. This might even block the card.

@dengert
Copy link
Member

dengert commented Apr 16, 2024

My point is, that we should not issue other commands than SELECT(AID) to cards we don't know, meaning cards whose ATR is not recognized any on of the driver. This is what causes the issue.

The corollary to this statement is if a card responds to Select AID, and returns in the response the AID then the card is claiming it it has the applet and it is now the selected applet. Returning just 90 00 could be mistaken for just a file or an non ISO 7816-4 compliant card.

Sending 00 A4 04 0C ... is not a select AID command, just a select file command. The card OS would most likely pass this to the currently active applet. The CAC card drivers are doing this and is sounds like they could be fixed.

I have not heard back from anyone with a JPKI card, But #3111 has a possible untested fix.

PIV bug has PR #3112.

I am close to submitting a PR to allow blacklisting ATRs in opensc.conf and when PKCS11 application calls C_GetTokenInfo: the response would be CKR_TOKEN_NOT_RECOGNIZED

example with a PIV and a Card Contact token where the ATR for the token was added to the blacklist:

doug@XUbuntu-22-4:/opt/ossl-3.1.2/bin$ ./pkcs11-tool -L
Available slots:
Slot 0 (0x0): Identiv SCR3500 A Contact Reader [CCID Interface] (5430214060...
  token label        : SDK TEST CARD 1 PIV Authentic...
  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         : 108619813810c3e7
  pin min/max        : 4/8
Slot 1 (0x4): SCM Microsystems Inc. SCR 355 [CCID Interface] 01 00
  (token not recognized)

The ATR is obtained from the reader then no APDUs issued to the blacklisted device.

The last part is if an ATR is blacklisted ATR, but no driver matches the card and the default driver is not enabled, which is the case for PKCS11, the ATR will be blacklisted for any additional PKCS11 probs from the current process.

dengert added a commit to dengert/OpenSC that referenced this issue Apr 16, 2024
A "card atr" entry with "driver = blacklist ;" can be added to opensc.conf
which will cause OpenSC to not match any card driver to the card.
When used with PKCS11 a A C_GetTokenInfo for the slot with teh card
will return CKR_TOKEN_NOT_RECOGNIZED.

s is in response to OpenSC#3108

 On branch blacklist
 Changes to be committed:
	new file:   src/libopensc/card-blacklist.c
@CardContact
Copy link
Member Author

Sending 00 A4 04 0C ... is not a select AID command, just a select file command. The card OS would most likely pass this to the currently active applet. The CAC card drivers are doing this and is sounds like they could be fixed.

Ahhh, no. P1=04 means Select by DF Name, which means SELECT(AID). And that command is always processed by the JCRE to eventually switch the applet context. The applet only sees a deselect() in case that AID matched another application instance (which is then the selected applet). See chapter 4.6.2 in the JavaCard Runtime Spec.

Of course non JavaCards could do whatever they want with a SELECT(AID). But I doubt, that any serious implementation will just respond 9000 for an unknown AID.

@dengert
Copy link
Member

dengert commented Apr 16, 2024

Ahhh, no. P1=04 means Select by DF Name, which means SELECT(AID)

Disagree. IOS 7816-4 says: "A multi-application card shall support the SELECT command with P1='04', P2='00' and..."
The point being "select AID" is telling card OS to select a specific application and make it the active application too
using a subset of the SELECT file by DF.

In your tokens the card OS is JCRE. Does it look at P2 or not?

The CAC cards where sending P2 = 0C saying no response. Does that affect you card?
You could test using something like OPENSC_DRIVER=cac pkcs11-tool -L while you have your card being used in another process. There is also a cac1 driver that should be tested.

Of course non JavaCards could do whatever they want with a SELECT(AID). But I doubt, that any serious implementation will just respond 9000 for an unknown AID.

Muscle did. And that is why PIV card driver requires a response to SELECT AID which contains AID in a DO4F

dengert added a commit to dengert/OpenSC that referenced this issue Apr 17, 2024
A "card atr" entry with "driver = blacklist ;" can be added to opensc.conf
which will cause OpenSC to not match any card driver to the card.
When used with PKCS11 a A C_GetTokenInfo for the slot with teh card
will return CKR_TOKEN_NOT_RECOGNIZED.

s is in response to OpenSC#3108

 On branch blacklist
 Changes to be committed:
	new file:   src/libopensc/card-blacklist.c
@CardContact
Copy link
Member Author

Ahhh, no. P1=04 means Select by DF Name, which means SELECT(AID)

Disagree. IOS 7816-4 says: "A multi-application card shall support the SELECT command with P1='04', P2='00' and..." The point being "select AID" is telling card OS to select a specific application and make it the active application too using a subset of the SELECT file by DF.

I don't see the contradiction to my statement. P2 doesn't matter here. In a JavaCard that is passed to the applet in the process() method and the applet can decide whether to return an FCI, FCP or nothing (based on P2).

In a JavaCard applet you typically see

public void process(APDU apdu) {

    if (selectingApplet()) {
        return;
    }
    
    // Process other APDUs

which is the code called for all APDUs. A SELECT with P1=04 will the pre-processed by the JCRE to
determine, if a context change between two applets must occur, because the user wants to switch from the currently selected applet to a different one on the card.

When the applet is currently selected and you send a SELECT with P1=04 and an AID that does not match the instance AID of the currently selected applet, than that APDU will not be passed into the applet code via process(). In other words, on a JavaCard the applet will not see the SELECT(AID) APDU, unless AID is it's own AID.

The applet API also has the select() and deselect() methods, which get called from the JCRE if the actual context switch happens. This does not happen, if the applet is already the currently select applet. The selectingApplet() query therefore allows the applet code to determine, if a re-select occurs, which is typically used to set the security environment (i.e. authentication state, processing state, secure messaging state) to a secure default.

In your tokens the card OS is JCRE. Does it look at P2 or not?

Any JavaCard Runtime Environment does that, because it's the JavaCard and ISO 7816-4 standard.

@dengert
Copy link
Member

dengert commented Apr 17, 2024

The version of ISO 7816-4 from 2013 says P2=00 for SELECT AID. How JavaCard interprets this is up to them. There are other cards that may use different OS on the card. The title of this issue: "Avoid non SELECT(AID) commands for probing"
is also addressing what is a SELECT AID.

Anyone have a newer version?

When the applet is currently selected and you send a SELECT with P1=04 and an AID that does not match the instance AID ...

This does not say if P2=00 is tested or not, but imply that the value of the DF i.e. path is assumed to be an AID. But does not say why it assume the path is a AID and not just an ordinary DF. It could be looking for "Categories of application identifiers": 'A', 'D', 'E' and 'F' where the path is an AID and command is SELECT for AID.

So I am arguing, OpenSC should only prob with a "SELECT" command that uses "00 A4 04 00 Lc path Le" and expect a response. (And check the the response as best is possible.) It is yet to be determined if any cards that do not set Le would have a problem if Le was set.

So not only does this issue affect your card, if could affect other cards. And thus the issue of P2=0C could be in play with other cards and applets.

The CAC drivers need to be addressed. @Jakuje said they really don't need to use P2 == 0C. So I leave it up to him. The 2013 version also says P2 == 02 can be used to select the first applet using a partial AID, which might be useful for the CAC if it supports that it and does not cause other problems.


Of the three drivers you listed as causing problems: PR #3112 fixes PIV, Issue #3111 has an untested fix awaiting someone to test it, and no one has looked at the setcos get data command issue.

I understand processing the applet has to do if it is deselected, having delt with PIV applets with CAC applet on same card as well as PIV and OpenPGP applets on others, and what happens to login state on reselect vs deselect. And having a working version of PIV with Secure Messaging on of the side Selecting another applet, is SM is also reset. (I don't have a PIV card that has both PIV and some other useful applet to test this, but the PIV card driver at the start of SCardBeginTransaction does check if login and SM states are still OK just in case, and reestablish SM of needed.

@CardContact
Copy link
Member Author

OK, now I understand your point: By "non SELECT(AID) commands" I mean all APDUs that are not SELECT APDUs with INS other than A4, like GET DATA or other proprietary commands.

If we issue SELECT with P1=04 and P2 being either 00 (= return FCI), 04 (return FCP), 08 (return FMD) or 0C (no response data) doesn't matter.

This does not say if P2=00 is tested or not, but imply that the value of the DF i.e. path is assumed to be an AID. But does not say why it assume the path is a AID and not just an ordinary DF. It could be looking for "Categories of application identifiers": 'A', 'D', 'E' and 'F' where the path is an AID and command is SELECT for AID.

P1 == 04 means "Selection by DF name", if you put a path in C-Data, then P1 must be 08 for a path from the MF or 09 for a path from the currently selected DF.

So I am arguing, OpenSC should only prob with a "SELECT" command that uses "00 A4 04 00 Lc path Le" and expect a response. (And check the the response as best is possible.) It is yet to be determined if any cards that do not set Le would have a problem if Le was set.

That is exactly what I recommend. P1 == 04 is the important parameter.

@dengert
Copy link
Member

dengert commented Apr 17, 2024

Looking at card-setcos.c the get data command is issued here: https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card-setcos.c#L119-L143

It was added by 462cd0d in 2006. Although the driver tries to match 13 known ATRs and looks at ATR history byes for "FinEID" or "FISE" and not matching any, it then does the GET DATA to tell the difference between two cards: SC_CARD_TYPE_SETCOS_EID_V2_0 and SC_CARD_TYPE_SETCOS_EID_V2_1 also known as: SETCOS_IS_EID_APPLET(card) at: https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card-setcos.c#L66

The last update of any ATRs was added in 2011 in 2757253 and 17bc2c8 by @martinpaljak

For some known ATRs the driver will do a SELECT AID for PKCS15 AID:
https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card-setcos.c#L145-L155
But this is not done for the SC_CARD_TYPE_SETCOS_EID_V2_0 and SC_CARD_TYPE_SETCOS_EID_V2_1

Looks like the ATR of these cards should be known before doing the GET DATA which is to generic of a test to match a card as setcos.

Does anyone know the ATR for these cards?
Are these cards still in use?
Can we drop these to cards?

Just selecting the PKCS15 AID could be problematic as there are may PKCS15 cards each with its own issues which might be mis identified.

@metsma
Copy link
Contributor

metsma commented Apr 18, 2024

It was added by 462cd0d in 2006. Although the driver tries to match 13 known ATRs and looks at ATR history byes for "FinEID" or "FISE" and not matching any, it then does the GET DATA to tell the difference between two cards: SC_CARD_TYPE_SETCOS_EID_V2_0 and SC_CARD_TYPE_SETCOS_EID_V2_1 also known as: SETCOS_IS_EID_APPLET(card) at: https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card-setcos.c#L66

Not related to this thicket but I think the FinEID cards are all expired for now.
https://dvv.fi/en/fineid-specifications

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

No branches or pull requests

5 participants