Page MenuHome GnuPG

scdaemon often needs restarting after removing OpenPGP smartcard
Closed, ResolvedPublic

Description

If SSH operations have been attempted while the OpenPGP card is unplugged
scdaemon may need to be restarted for it to recover the key.

The card reader is a PC/SC compatible Todos Argos Mini II reader. Driver source
available.

0. gpg-agent running with --enable-ssh-support

  1. card inserted

ssh-add -L
[shows SSH key]

  1. remove card

ssh-add -L
[shows no keys]

  1. insert card

ssh-add -L
[still shows no keys]

  1. Other operations such as "gpg --clearsign" still finds the card and is

successful. But it appears gpg now bypasses the agent and accesses the card
directly.

  1. Restart scdaeon

pkill -9 scdaemon; pkill -HUP gpg-agent
ssh-add -L
[now finds key again]

If the same is done, but skipping "ssh-add -L" in step 2 the nscdaemon finds the
card again, and the pin cache is cleared just like expected.

In this broken state .gnupg/reader_0.status reports "ACTIVE".

Also pcsc-wrapper is no longer running when this happens.

pcsc_scan properly identifies the card as removed / inserted OpenPGP.

Last lines of the logs says:

scdaemon[12866]: PC/SC RESET failed: no smartcard (0xffffffff8010000c)
scdaemon[12866]: no supported card application found: General error
gpg-agent[12810]: error getting serial number of card: General error
gpg-agent[12810]: ssh request handler for request_identities (11) ready

and scdaemon closes the connection to pcsc-wrapper.

Details

Version
2.0.0

Event Timeline

hno set Version to 2.0.0.
hno added a subscriber: hno.

It's a 64-bit error where the decoded error code is sign extended by the shift
operation and no longer equals to the value of the corresponding define.

unsigned char << something

is an int. Casted to a long in the assignment will sign extend resulting in
0xffffffff8010000, which != 0x8010000.

One possible patch, but other alternatives is also possible. Should be decided
if these values is signed or unsigned.

It's worth noting that the same error may bite other parts of the code as well.

The long is due to the PC/SC specs. In fact Windows 64 bit won't get into
trouble because a long is there still 32 bits. To avoid type mismatches I have
done another patch using a masking approach. Please try it.

With err being long there is still signedness mismatch on 32-bit platforms.

#define PCSC_E_NO_SMARTCARD 0x8010000C

is an unsigned int (constant, does not fit in int so it's an unsigned int).

then in the expression which was the culpit you have

if (err == PCSC_E_NO_SMARTCARD)

where err is an long, and PCSC_E_NO_SMARTCARD) is an unsigned int too large for
a 32-bit long..

and this is a somewhat dangerous borderline to work on wrt sign extension..

But both patches works fine here on 64-bit.

Looks like a small BTS bug showed it's ugly face there. The only possible choice
in "Assignet To" for me is "- no selection -" and is set by default, which
removed the existing assignment set by werner..

Thanks for noting the problem with assigned to.

Fixed in SVN. Will go into 2.0.1