acshk / acsccid

acsccid is a PC/SC driver for Linux/Mac OS X and it supports ACS CCID smart card readers. This library provides a PC/SC IFD handler implementation and communicates with the readers through the PC/SC Lite resource manager (pcscd).
GNU Lesser General Public License v2.1
104 stars 19 forks source link

Load Authentication Keys without PICC present #24

Closed hinxx closed 3 years ago

hinxx commented 3 years ago

I'm using ACR122U (ACR122U214) on Linux with master code from this repo. I'm trying to understand the behavior of the load keys command. The reason I'm trying this is because the API says that the keys are loaded into the reader, so I tried avoiding loading the keys every time a PICC is presented hence the use of the SCardControl().

Should I be able to perform 'Load Authentication Keys' command without PICC being present?

I have a code that tries to load the keys using this SCardControl():

#define IOCTL_CCID_ESCAPE               SCARD_CTL_CODE(3500)
...
rv = SCardConnect(context, readerName, SCARD_SHARE_DIRECT, 0, &readerHandle, &dwActiveProtocol);
...
rv = SCardControl(readerHandle, IOCTL_CCID_ESCAPE, _sendData, _sendLen, _recvData, *_recvLen, _recvLen);

If I try SCardControl() after the reader is detected and connected (no PICC presented) it does not work, I get 0 length response from the reader. If the SCardControl() is called after the PICC is presented and connected I get the 90 00 success response. Is this expected?

Reading the API manual it seems that I should not be using SCardControl() to load the keys, so it surprises me that it works in case PICC is present.

I've been doing this with default key values and also noticed that I can authenticate with the PICC even if the load keys command is not made at all. I tried disconnecting the reader to make it forget the keys, but the authentication still worked without loading the keys. Is this expected?

Log snippet of failed keys load (without PICC):

00000130 winscard_svc.c:362:ContextThread() Received command: CONTROL from client 14
00000014 readerfactory.c:848:RFReaderInfoById() RefReader() count was: 1
00000006 ifdhandler.c:1849:IFDHControl() ControlCode: 0x42000DAC, usb:072f/2200:libudev:0:/dev/bus/usb/003/038 (lun: 0)
00000005 Control TxBuffer: FF 82 00 00 06 FF FF FF FF FF FF 
00000023 -> 000000 6B 0B 00 00 00 00 08 00 00 00 FF 82 00 00 06 FF FF FF FF FF FF 
00687568 <- 000000 83 00 00 00 00 00 08 02 FE 00 
00000021 Control RxBuffer: 
00000049 winscard.c:1359:SCardControl() UnrefReader() count was: 2
00000025 winscard_svc.c:732:ContextThread() CONTROL rv=0x0 for client 14

Log snippet of successful keys load (with PICC):

00000111 winscard_svc.c:362:ContextThread() Received command: CONTROL from client 14
00000013 readerfactory.c:848:RFReaderInfoById() RefReader() count was: 1
00000005 ifdhandler.c:1849:IFDHControl() ControlCode: 0x42000DAC, usb:072f/2200:libudev:0:/dev/bus/usb/003/038 (lun: 0)
00000006 Control TxBuffer: FF 82 00 00 06 FF FF FF FF FF FF 
00000016 -> 000000 6B 0B 00 00 00 00 12 00 00 00 FF 82 00 00 06 FF FF FF FF FF FF 
00023962 <- 000000 83 02 00 00 00 00 12 00 81 00 90 00 
00000005 Control RxBuffer: 90 00 
00000005 winscard.c:1359:SCardControl() UnrefReader() count was: 2
00000005 winscard_svc.c:732:ContextThread() CONTROL rv=0x0 for client 14
godfreychung commented 3 years ago

Yes, the command needs PICC present. In order to forget the key, you need to unplug the reader.

hinxx commented 3 years ago

Got it! Thanks!