Since revision 5991 my CCID driver does support
These two services have been introduced in PC/SC v2 part 10 version 2.02.07 March 2010 and 2.02.08 April 2010.
FEATURE_CCID_ESC_COMMANDThis feature can be used to retrieve the control code to send a CCID escape command (
PC_to_RDR_Escape) to the reader using
The value is returned by the
CM_IOCTL_GET_FEATURE_REQUESTcommand. This will return a TLV data stream. The
dwControlCodeto use is the value corresponding to the tag
Before this mechanism it was possible to use the value
IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGEbut this value is not specified/documented in any official document (AFAIK).
FEATURE_CCID_ESC_COMMANDis now portable (everywhere the PC/SC drivers implement it).
SCardControl()function is quiet limited with the Microsoft CCID driver on Windows. So some smart card reader manufacturers use
SCardTransmit()to send commands to the reader (instead of the card).
This mechanism is fragile since the reader must interpret the command and determine if the command if for itself or for the card.
The PC/SC workgroup documented a way to know how the driver is expecting to receive commands for itself.
bPPDUSupportis a tag in the TLV data stream returned by
FEATURE_GET_TLV_PROPERTIES. The value is coded as:
- Bit 0: If set to 1, PPDU is supported over
- Bit 1: If set to 1, PPDU is supported over
Implementation in my CCID driverBy default, for security reasons, sending an arbitrary
PC_to_RDR_Escapecommand is forbidden. This can be configured using the
ifdDriverOptionssetting in the driver
[...] <key>ifdDriverOptions</key> <string>0x0000</string> <!-- Possible values for ifdDriverOptions 1: DRIVER_OPTION_CCID_EXCHANGE_AUTHORIZED the CCID Exchange command is allowed. You can use it through SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, ...) [...]If the bit 0 of
ifdDriverOptionsis set then the driver will allow the use of
IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGEand now also the value associated to
The driver will always report
bPPDUSupport. By default the value is 0x00. But if If the bit 0 of
ifdDriverOptionsis set then the value of
bPPDUSupportwill be 0x01 indicating the support of
Sample codeThe use of these features may be hard to understand. So a small example can help.
#! /usr/bin/env python """ # FEATURE_CCID_ESC_COMMAND.py: Unitary test for FEATURE_CCID_ESC_COMMAND # Copyright (C) 2011 Ludovic Rousseau """ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, see <http://www.gnu.org/licenses/>. from smartcard.System import readers from smartcard.pcsc.PCSCPart10 import (SCARD_SHARE_DIRECT, SCARD_LEAVE_CARD, FEATURE_CCID_ESC_COMMAND, getFeatureRequest, hasFeature) def main(): """ main """ card_connection = readers().createConnection() card_connection.connect(mode=SCARD_SHARE_DIRECT, disposition=SCARD_LEAVE_CARD) feature_list = getFeatureRequest(card_connection) ccid_esc_command = hasFeature(feature_list, FEATURE_CCID_ESC_COMMAND) if ccid_esc_command is None: raise Exception("The reader does not support FEATURE_CCID_ESC_COMMAND") # proprietary commands for Xiring readers version = [ord(c) for c in "VERSION"] res = card_connection.control(ccid_esc_command, version) print res print ''.join([chr(x) for x in res]) serial = [ord(c) for c in "GET_SN"] res = card_connection.control(ccid_esc_command, serial) print res print ''.join([chr(x) for x in res]) if __name__ == "__main__": main()
In CThe C language is much more verbose than Python. I added support of
scardcontrol.cexample code provided with the CCID driver.
The idea is the same as in Python:
- get the control code to use using
SCardControl()to send a command
CommentsPC/SC now documents a way to send arbitrary proprietary commands to a reader. We now have two questions:
What command should you send?You should know what you are doing and use the smart card reader user manual. So the command you want to use is documented, but maybe the documentation is not public. In general proprietary commands are not publicly documented.
How to know what reader exactly you are using?I do not have an answer to this question. Using the PC/SC reader name is fragile. See a previous blog article What is in a PC/SC reader name? The reader name can change over time like with "Gemplus" becoming "Gemalto".
Maybe PC/SC must provide a new mechanism to report the USB VendorID and ProductID so that an application can be sure a specific reader is used.
ConclusionHaving to use proprietary commands is a sign of failure from the PC/SC workgroup. A service is needed but missing from the PC/SC standard. It has then been implemented using a proprietary mechanism (not documented, not portable, not interoperable).
It is a failure because the application is now linked to a particular smart card reader model.