Closed polhenarejos closed 2 years ago
First, I'd try comparing (diffing) the two use cases:
virt_cacard <--> libcacard <--> vpcd <--> pcsc <--> opensc <--> CCID emulator <--> USB <--> opensc-tool -an -vvvvvvvvvvvvvvv 2>&1 > broken.txt
vs
virt_cacard <--> libcacard <--> vpcd <--> opensc-tool -an -vvvvvvvvvvvvvvv 2>&1 > working.txt
Now remove timestamps, PID/TID and check the difference between working.txt and broken.txt...
Done.
I uploaded the diff log to https://gist.github.com/polhenarejos/8585a41018ff09a92872923b09ba5b25
I also uploaded the working and broken in case are needed in a separate gist
https://gist.github.com/polhenarejos/f1d94d399760d06aaf2bed139a9e067f
If you want me to look at this, you need to give me the two raw logs...
Do you refer to broken and working? I've uploaded both at https://gist.github.com/polhenarejos/f1d94d399760d06aaf2bed139a9e067f
by removing the timestamp, you've also deleted some of the APDUs. Just upload the complete logs of both cases...
Right, my fault.
I uploaded the corrected clean logs to https://gist.github.com/polhenarejos/f1d94d399760d06aaf2bed139a9e067f
The versions of OpenSC that you've used for both tests differ...
here's one difference:
Outgoing APDU (12 bytes):
00 A4 04 0C 07 A0 00 00 01 16 DB 00 ............
[opensc-tool] reader-pcsc.c:244:pcsc_internal_transmit: called
[opensc-tool] reader-pcsc.c:335:pcsc_transmit:
Incoming APDU (2 bytes):
90 00 ..
vs
Outgoing APDU (12 bytes):
00 A4 04 0C 07 A0 00 00 01 16 DB 00 ............
[opensc-tool] reader-pcsc.c:244:pcsc_internal_transmit: called
[opensc-tool] reader-pcsc.c:335:pcsc_transmit:
Incoming APDU (2 bytes):
61 0D a.
ccid-emulator uses opensc to communicate to the card. I think this passthrough conflicts with the result that's expected by the actual application. try using the default driver, to avoid this:
diff --git a/ccid/src/ccid.c b/ccid/src/ccid.c
index 6a03767..7742b3f 100644
--- a/ccid/src/ccid.c
+++ b/ccid/src/ccid.c
@@ -455,6 +455,7 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, size_t inlen, __u8 **out, size_t *o
sc_result = SC_SUCCESS;
} else {
sc_sm_stop(card);
+ sc_set_card_driver(ctx, "default");
sc_result = sc_connect_card(reader, &card);
card->caps |= SC_CARD_CAP_APDU_EXT;
}
OpenSC-0.22.0-rc1-74-gc902e199, rev: c902e199, commit-time: 2021-08-10 11:09:03 +0200
via git checkout tags/0.22.0
ccid.c
to load "default" driver, as the suggested patch.I still get the same issues and the APDU are still the same (90 00
vs. 61 0D
). Is there another place where I could load the driver?
I've updated both logs at https://gist.github.com/polhenarejos/f1d94d399760d06aaf2bed139a9e067f
in case of using the ccid-emulator, could you also create and compare a log on the RPI with the log on opensc-tool -n
running on the PC?
Sure! I updated the logs at https://gist.github.com/polhenarejos/f1d94d399760d06aaf2bed139a9e067f
What I see is that everything starts to diverge at line 773, with different APDU. What I do not know is why both opensc-tool send different APDU if both are in the same version 0.22.0.
What these APDU mean?
the difference in the ATR doesn't cause the card to respond differently, but a different card state does.
your https://gist.github.com/polhenarejos/f1d94d399760d06aaf2bed139a9e067f still only contains working-clean.txt and broken-clean.txt. both are ok, but in the broken case, you could try to debug the ccid-emulator as well. To hardcode this, you could try the following:
diff --git a/ccid/src/ccid.c b/ccid/src/ccid.c
index 6a03767..f073cf6 100644
--- a/ccid/src/ccid.c
+++ b/ccid/src/ccid.c
@@ -200,6 +200,9 @@ int ccid_initialize(int reader_id, int verbose)
i = initialize(reader_id, verbose, &ctx, &reader);
if (i < 0)
return i;
+ if (verbose > 0) {
+ sc_ctx_log_to_file(ctx, "stderr");
+ }
return SC_SUCCESS;
}
@@ -455,6 +458,7 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, size_t inlen, __u8 **out, size_t *o
sc_result = SC_SUCCESS;
} else {
sc_sm_stop(card);
+ sc_set_card_driver(ctx, "default");
sc_result = sc_connect_card(reader, &card);
card->caps |= SC_CARD_CAP_APDU_EXT;
}
Sure! I've uploaded ccid logs at https://gist.github.com/polhenarejos/74cc428cc594b16408bfe5ae98af5ab9
I ran and stopped ccid-emulator
for each opensc-tool -n
command in both sides to obtain separate logs.
The command I used:
ccid-emulator --serial 123456 --interface 1123344 -vvvvvvvvvvvvvvv > ccid-stdout-working.txt 2> ccid-stderr-working.txt
changing the file for each case.
Edit: I realized that ccid-working logs are useless, since opensc-tool -n
in the RPI does not make use of CCID Emulator. Sorry for adding noise.
Comparing broken and ccid-broken logs, what I do not understand is that when, for instance, when the end client in the PC sends the APDU 00 A4 04 0C 07 A0 00 00 01 16 DB 00
, the CCID Emulator receives back the APDU 61 0D
(exactly as with working case). But the end client in the PC, receives 90 00
. It seems that in between there is a translation from 61 0D
to 90 00
, which I cannot find.
I ran pcscd -a -f -d
in the PC to log what is received by the usb. I put the log at https://gist.github.com/polhenarejos/74cc428cc594b16408bfe5ae98af5ab9
Lines 388-390 are the above APDU and, in this case, is 90 00
. Narrowing the actions, it seems that this happens in between usb and ccid.
I also uploaded cleaned logs of pcscd for broken and working cases.
https://gist.github.com/polhenarejos/4c55d119f71b2663d86ed4679a4dc9ad
Please have a look at the following lines of debug output from ccid-emulator: https://gist.github.com/polhenarejos/74cc428cc594b16408bfe5ae98af5ab9#file-ccid-stderr-broken-clean-txt-L910-L939
The card responds with 61 0D
, but apdu->sw1
/apdu->sw2
are somehow set to 90
/00
. The problem is somewhere between the following lines:
https://github.com/frankmorgner/vsmartcard/blob/92847665325ad7b46e17f7161f943f7984eb4d54/ccid/src/ccid.c#L240-L265
You need to find out where/why 61 0D
is misinterpreted as 90 00
...
Digging into libopensc, I found the place when it changes:
https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/apdu.c#L420-L435
called from https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/apdu.c#L534-L538
Now, I do not know why apdu->le == 0
is true
.
I commented out the APDU bytes change as:
diff --git a/src/libopensc/apdu.c b/src/libopensc/apdu.c
index b52183ea..5cafed80 100644
--- a/src/libopensc/apdu.c
+++ b/src/libopensc/apdu.c
@@ -428,8 +428,8 @@ sc_get_response(struct sc_card *card, struct sc_apdu *apdu, size_t olen)
LOG_FUNC_CALLED(ctx);
if (apdu->le == 0) {
/* no data is requested => change return value to 0x9000 and ignore the remaining data */
- apdu->sw1 = 0x90;
- apdu->sw2 = 0x00;
+ //apdu->sw1 = 0x90;
+ //apdu->sw2 = 0x00;
return SC_SUCCESS;
}
And now all pkcs11-tool, opensc-tool... commands work properly. I can list object, mechanisms, as a local reader. However, I do not know whether I am breaking something deeper and what are the long-term implications of changing/not changing the return value to 0x9000. Honestly, I do not know what I am doing commenting this out.
Since OpenSC is statically linked to ccid-emulator, the modification is straightforward without breaking anything in the system.
I've pushed a change, that hopefully fixes your issue.
Thanks @frankmorgner for the efforts and quick response. Glad to see it works.
Finally, I could make it work based on your change:
diff --git a/ccid/src/ccid.c b/ccid/src/ccid.c
index bab81cf..7411b75 100644
--- a/ccid/src/ccid.c
+++ b/ccid/src/ccid.c
@@ -641,14 +641,15 @@ perform_PC_to_RDR_XfrBlock(const u8 *in, size_t inlen, __u8** out, size_t *outle
}
sc_result = sc_bytes2apdu(ctx, abDataIn, apdulen, &apdu);
- if (sc_result >= 0)
+ if (sc_result >= 0) {
+ /* don't magically get additional data in OpenSC */
+ apdu.flags |= SC_APDU_FLAGS_NO_GET_RESP;
sc_result = get_rapdu(&apdu, &abDataOut,
&abDataOutLen);
+ }
else
bin_log(ctx, SC_LOG_DEBUG_VERBOSE, "Invalid APDU", abDataIn,
__le32_to_cpu(request->dwLength));
- /* don't magically get additional data in OpenSC */
- apdu->flags |= SC_APDU_FLAGS_NO_GET_RESP;
sc_result = get_RDR_to_PC_DataBlock(request->bSeq, sc_result,
out, outlen, abDataOut, abDataOutLen);
my fault, thanks for checking
I have a RPi0 configured as a GadgetFS to provide SC functionalities. I am using virt_cacard to emualte the smart card. The scheme is the following:
virt_cacard <--> libcacard <--> vpcd <--> pcsc <--> opensc <--> CCID emulator <--> USB
The USB is connected to a PC, where OpenSC is also installed.
After some modifications to work in the RPI0, the ccid emulator starts up and the USB is detected by the PC. However, something is broken in the middle because OpenSC tools always show "Unsupported card":
The strange part is that OpenSC tools are able to work when I run them directly in the RPI0, without the CCID Emulator middle layer:
Thus, I guess is something related with CCID Emulator, the small portion I modified or USB stuff.
Commands I use:
I also tried with
vicc
but I cannot manage to work even in the RPI0. It always shows "Unsupported card" in the PC and in the RPI0, with or without CCID Emulator.Expected behaviour
What should happen?
opensc-tool -an
should display the card when using CCID Emulator, as it shows when it is executed by the host.Actual behaviour
What happens instead?
opensc-tool -an
(and others) shows "Unsupported card" when CCID Emulator is in the middle.Steps to reproduce
libcacard
.autoconfig()
function inusb.c
to be recognized by the RPI0:else if (stat (DEVNAME = "20980000.usb", &statb) == 0) { HIGHSPEED = 1; device_desc.bcdDevice = __constant_cpu_to_le16 (0x0100);
pi@rpi0:~ $ pkcs11-tool --list-slots Available slots: Slot 0 (0x0): Virtual PCD 00 00 token label : CAC II token manufacturer : Common Access Card token model : PKCS#15 emulated token flags : login required, rng, token initialized, PIN initialized hardware version : 0.0 firmware version : 0.0 serial num : 000058bd002c19b5 pin min/max : 4/8 Slot 1 (0x4): Virtual PCD 00 01 (empty)
pi@rpi0:~ $ pkcs11-tool --list-interfaces Interface 'PKCS 11' version: 3.0 funcs=0xb63ec394 flags=0x0 Interface 'PKCS 11' version: 2.20 funcs=0xb63ec508 flags=0x0 Using slot 0 with a present token (0x0)
pi@rpi0:~ $ opensc-tool -l
Detected readers (pcsc)
Nr. Card Features Name 0 Yes Virtual PCD 00 00
pol@myPC:~$ pkcs11-tool --list-slots Available slots: Slot 0 (0x0): KOBIL EMV CAP - SecOVID Reader III [1123344] (123456) 00 00 (token not recognized)
pol@myPC:~$ pkcs11-tool --list-interfaces Interface 'PKCS 11' version: 3.0 funcs=0x76401394 flags=0x0 Interface 'PKCS 11' version: 2.20 funcs=0x76401508 flags=0x0 Using slot 0 with a present token (0x0)
pol@myPC:~$ opensc-tool -l
Detected readers (pcsc)
Nr. Card Features Name 0 Yes PIN pad KOBIL EMV CAP - SecOVID Reader III [1123344] (123456) 00 00
pol@myPC:~ $ lsusb -vvv Bus 001 Device 009: ID 0d46:3010 Kobil Systems GmbH Couldn't open device, some information will be missing Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 255 Vendor Specific Class bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x0d46 Kobil Systems GmbH idProduct 0x3010 bcdDevice 1.00 iManufacturer 1 iProduct 2 iSerial 3 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 0x0056 bNumInterfaces 1 bConfigurationValue 3 iConfiguration 4 bmAttributes 0xc0 Self Powered MaxPower 2mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 11 Chip/SmartCard bInterfaceSubClass 0 bInterfaceProtocol 0 iInterface 5 ChipCard Interface Descriptor: bLength 54 bDescriptorType 33 bcdCCID 1.10 (Warning: Only accurate for version 1.0) nMaxSlotIndex 0 bVoltageSupport 1 5.0V dwProtocols 3 T=0 T=1 dwDefaultClock 3580 dwMaxiumumClock 3580 bNumClockSupported 1 dwDataRate 9600 bps dwMaxDataRate 9600 bps bNumDataRatesSupp. 1 dwMaxIFSD 255 dwSyncProtocols 00000000 dwMechanical 00000000 dwFeatures 000404FA Auto configuration based on ATR Auto voltage selection Auto clock change Auto baud rate change Auto parameter negotiation made by CCID Auto IFSD exchange Short and extended APDU level exchange dwMaxCCIDMsgLen 65545 bClassGetResponse echo bClassEnvelope echo wlcdLayout 255 cols 255 lines bPINSupport 51 verification modification bMaxCCIDBusySlots 1 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x02 EP 2 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 1