Unplugging USB Smartcard/Yubikey causes problems with scdaemon
Closed, ResolvedPublic

Description

I've installed GPG4WIN on Windows 10 (Build 1511) and had the Problem that my Yubikey 4
(USB smartcard with OpenPGP Applet) doesn't work/react anymore after unplugged the usb
key and plugged it back in. This only could be solved by restarting scdaemon (SCD
KILLSCD).

I could reproduce this behaviour with GnuPG 2.0.29 (included in GPG4WIN 2.3.0) and the
newest modern version 2.1.9.

I've enabled the debug log for scdaemon and when I plugged the Yubikey scdaemon started
complaining about a stopped service / status change failed.

Even more problematic was the fact that even after unplugging the Smartcard the
scdaemon/gpg-agent was reporting the old (cached) card informations due to the fact that
after unplugging the card status wasn't fully removed in scdaemon.

I've attached the full debug log of my test session. Maybe you can find a place where
something is broken or the scdaemon isn't resetting when the usb smartcard reader is
getting unplugged.

dhoffend set Version to 2.1.9.
dhoffend added a subscriber: dhoffend.

guilhem set External Link to https://lists.gnupg.org/pipermail/gnupg-users/2010-September/039502.html.Dec 3 2015, 1:33 PM

In the meantime, a workaround is to add an udev rule to scdaemon whenever the
Yubikey is plugged in:
https://github.com/Yubico/yubikey-personalization/issues/36 . I guess it doesn't
work on Windows, though.

Well ... the udev can only be a workaround. Killing the scdaemon from the
outside is not the correct way to handle this issue.

scdaemon should realize it itself that it's connection to the smartcard has
been stopped/killed/canceled/disconnected (whatever) and kill/reset and
restart it's internal process leading to removing the previously loaded card
from the memory.

There should be no need for an outside trigger.

I tested this with a fresh windows10 (which has never seen a yubikey
before). I installed gnupg 2.1.9 binaries and gnupg was able to speak with
the card with no additional drivers needed. (the problem with disconnecting
the card still occours).

And without the need of special drivers there should be no need for any
special rules to be applied.

I was looking a bit deeper into the gnupg code and debug messages. As soon as I
plug out the yubikey the usb smartcard reader including the internal smartcard
is no longer available. GnuPG is sending the following messages:

  1. this call is still okay 2015-12-06 23:20:31 scdaemon[10940] DBG: enter: apdu_get_status: slot=0

hang=0

2015-12-06 23:20:31 scdaemon[10940] DBG: leave: apdu_get_status => sw=0x0

status=7 changecnt=1

  1. here the card is no longer available 2015-12-06 23:20:31 scdaemon[10940] DBG: enter: apdu_get_status: slot=0

hang=0

2015-12-06 23:20:31 scdaemon[10940] pcsc_get_status_change failed: no

service (0x8010001d)

2015-12-06 23:20:31 scdaemon[10940] DBG: leave: apdu_get_status =>

sw=0x1000b status=7 changecnt=1

Error Message 0x8010001d == SCARD_E_NO_SERVICE (The Smart card resource manager
is not running.)
https://pcsclite.alioth.debian.org/api/group__ErrorCodes.html#gad4729ab109ff490
285d2ad881c04bee8

Now there's an internal mapping happing from 0x8010001d to sw=0x1000b
http://git.gnupg.org/cgi-bin/gitweb.cgi?
p=gnupg.git;a=blob;f=scd/apdu.c;h=95a25611b7ff46c87e2e888643bec0a10454f894;hb=H
EAD#l899

The SCD internal resulting error is 0x1000b means SW_HOST_GENERAL_ERROR which
is the default error if nothing else has matched yet.

The next lines in the logfiles are showing a different pcsc error code.

2015-12-06 23:20:32 scdaemon[10940] DBG: enter: apdu_get_status: slot=0

hang=0

2015-12-06 23:20:32 scdaemon[10940] pcsc_get_status_change failed: service

stopped (0x8010001e)

2015-12-06 23:20:32 scdaemon[10940] DBG: leave: apdu_get_status =>

sw=0x1000b status=7 changecnt=1

Error Message 0x8010001d == SCARD_E_SERVICE_STOPPED (The Smart card resource
manager has shut down.)
https://pcsclite.alioth.debian.org/api/group__ErrorCodes.html#ga262c34297ab1b65
db1c9516ccc0dd9a0

The pcsc error code is still mapped to the generic error code (0x1000b)

--

possible resolution: I've no clue if the error codes 0x8010001d or 0x8010001e
are thrown in different scenarios. But if we would map those 2 messages to the
internal SW_HOST_NO_READER error the scdaemon would like remove the (likely
disconnected usb) reader from the current list, resulting in freeing up the
used card.

I can't verify this idea cause I'm not able to compile gnupg under windows but
I've attached a solution patch in this ticket

After looking at the gnupg 2.0 branch I would say the patch could be applied
to the 2.0 and 2.1 branch to fix the issue in both branches stable/modern
since both version are affected (tested with 2.1.9 and 2.0.29 from gpg2win)

gniibe added a subscriber: gniibe.Dec 10 2015, 12:39 AM

Thank you for the bug report with log.

It could be related to the bug which was just fixed:
http://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=commitdiff;h=f42c50dbf00c2e6298ca6830cbe6d36805fa54a3

I'm backporting this to 2.0.x.

gniibe claimed this task.Dec 10 2015, 12:39 AM

No, I just installed version 2.1.10 (which included your mentioned fix). But the
error still applies.

In my case the smartcard reader never gets closed, cause the error thrown by the
pcsc/scd gets only mapped to a general_error which does not result in
removing/closing the reader interface.

I've the feeling that we've to take a closer look at the errors thrown (at least
those 2 in my patch). Maybe there're even more possible events.

If you like I can upload the debug log of scdaemon 2.1.10 ... (if that helps).

Somehow I don't have any issues when running linux, this bug applies to windows
only atm. Maybe it's just that windows is throwing different errors or events
compared to linux.

dhoffend changed Version from 2.1.9 to 2.1.10.Dec 10 2015, 12:54 AM

Thank you again.

I think that Windows 8 (and later) changed the PC/SC service. The service is
only available when smartcard is there, and after the removal, it returns
PCSC_E_NO_SERVICE error. This is not expected for current code.

I'm applying your patch with my comment like above. Do you agree to put the
line in the commit log?:

   Signed-off-by: Daniel Hoffend <dh@dotlan.net>

I don't have Windows 8 machine. So, I leave this issue as testing.

I'm okay with signing off the commit. I can test this for Windows 8.1 or 10,
my only problem is that I'm not able to compile gpg for windows right now. Or
are there instructions somewhere on how to achieve this?

After some time spending fighting with the build tools of gnupg (cross compile
for windows under debian) I managed to build the installer with my patched
file.

Most important: The most common error thrown is the 0x8010001e
(E_SERVICE_STOPPED) This is the important one. The other error 0x8010001d
(E_NO_SERVICE) is only thrown in the transition from ok to stopped. So only
sometimes.

This was my process:

git clone git://git.gnupg.org/gnupg.git
cd gnupg
git checkout tags/gnupg-2.1.10
./autogen.sh
cat ../0001-scd-Fix-removal-of-unplugged-usb-readers.patch | patch -p1
sed -i -e 's/^SELFCHECK=1/SELFCHECK=0/' build-aux/speedo.mk
make -f build-aux/speedo.mk w32-installer

I've created new logfiles (vanilla 2.1.10 und patched 2.1.10) to show the
difference and confirm that it'S actually working now :-)

Here's the logfile with all the errors (guru debug level) vanilla 2.1.10

Thank you for your testing.

Your change is pushed with my comment:
http://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=commit;h=d1a97585c5e73fbc7d4cf90e38f76ffc5aea305f

I'll backport this to GnuPG 2.0.

I found another problem with the smartcard service under windows. Putting
the system into sleep mode and waking it up again creates an 0x80100068
error code (aka PCSC_W_RESET_CARD).

I'll test if it helps to map the RESET_CARD event to the same REMOVE_CARD
event to get the card reactivated after sleep mode.

Logfile:
2015-12-21 22:16:57 scdaemon[10040] DBG: send apdu: c=00 i=CA p1=00 p2=C4
lc=-1 le=256 em=0
2015-12-21 22:16:57 scdaemon[10040] DBG: PCSC_data: 00 CA 00 C4 00
2015-12-21 22:16:57 scdaemon[10040] pcsc_transmit failed: reset card
(0x80100068)
2015-12-21 22:16:57 scdaemon[10040] apdu_send_simple(0) failed: general
error

Maybe it's more appropriate to map the PSCS_W_CARD_RESET event to the
SW_HOST_CARD_INACTIVE error code which later gets mapped to GPG_ERR_CARD_RESET
error code.

I've attached the patch file. It would make sense to backport this mapping as
well. Right now it's not yet tested.

Nope. Neither mapping the "reset card" event to SW_HOST_CARD_INACTIVE or
SW_HOST_NO_CARD helps. It seems that somewhere in the code the return code
SW error codes are not being handled correctly and the card doesn't get
resetted.

I've attached a small log where you can see that pcsc returns the error
reason "reset card" which then gets remapped to "Card reset required" (was
general error before). I also can see that the error is getting mapped to
GPG_ERR_CARD_RESET (because of the error message "Card reset required")
leaving the daemon around with no working card and reporting general errors
again (0x100b).

Additional Info: This bug only happens when you put your computer/laptop
into sleep mode while the smartcard/reader (yubikey) is plugged in. If I
remove the reader before putting it to sleep and attaching it after getting
out of the sleep mode, the scdaemon works fine.

Thank you for further testing.
I think that current code doesn't handle the case when card goes inactive/reset
while reader keeps working. Current code only goes to the reset sequence for a
card again when it detects reader failure. So, although the concept is
different, I think mapping PSCS_W_CARD_RESET to SW_HOST_NO_READER (for now) will
work. Given the situation we don't yet support multiple cards, this workaround
would be OK for a while.

Sorry to say, but mapping the error to "no reader" doesn't help. The first
reset event doesn't get handled. Later it trys to remove the reader but it's
not getting correctly resetted/reinserted again.

I've attached the debug log again

Thank you again.

It is likely that the token itself doesn't work well after wakeup from sleep
mode. In this case, all that we can do is re-inserting the token manually.

I'm not sure how PC/SC service handles USB reset after wakeup.

PRab added a subscriber: PRab.Mar 16 2016, 8:08 PM
PRab added a comment.Mar 16 2016, 9:01 PM

I believe I have also seen this issue (or something very similar) on my Windows
7 64bit machine. I am running gpg 2.1.11. I hope this isn't redundant, but it
seems that I need to restart scdaemon anytime I unplug/replug my yubikey or
suspend/resume my computer.

Sometimes it doesn't recover even after restarting scdaemon. In those cases, I
am able to fix it by stopping scdaemon, removing the yubikey, starting scdaemon,
and finally reinserting the yubikey.

davidw added a subscriber: davidw.Jul 29 2016, 5:10 PM
shtrom added a subscriber: shtrom.Oct 17 2016, 11:17 AM

I run in the same issue as PRab whenever I suspend or hibernate my machine. The
machine as Broadcom BCM5880 with a smart-card reader, so I cannot unplug it.
Quickest workaround is to kill/restart scdaemon.

Is there/could there be a command that could be sent to scdaemon via the agent
so a reset could be triggered? It should be easy enough to line that up as part
of the resume scripts.

werner added a subscriber: werner.

gniibe: Can you check the status?

(I removed gpg20 because we won't fix it anyway for 2.0)

werner edited projects, added gnupg (gpg22); removed gnupg.Oct 20 2017, 1:30 PM

I am closing this bug report, as I can't get feedback to fix something.

Please make new reports for:
(1) The issue on Windows with Yubikey: Unplug -> Plug it again
(2) The issues on Windows with Yubikey: Hibernate

Please attache the log of scdaemon if possible.

gniibe closed this task as Resolved.Oct 26 2017, 5:50 AM