From 258ebe2e40ccf039c4dbe84ca61df8c980b476dd Mon Sep 17 00:00:00 2001 From: Claus Steuer Date: Mon, 16 Jan 2023 11:17:50 +0100 Subject: [PATCH] allow feature query for maximum APDU size If the reader's maximum APDU size (dwMaxAPDUDataSize) cannot be queried the client application must assume that only short APDUs are supported. Since there is no data size limit for virtual smart card communication dwMaxAPDUDataSize can be set to the maximum APDU size of 65536 (extended APDUs). This updates pcsclite-vpcd's reader.h/ifdhandler.h to pcsc-1.9.9 https://salsa.debian.org/rousseau/PCSC/-/blob/1.9.9/src/PCSC --- virtualsmartcard/src/ifd-vpcd/ifd-vpcd.c | 49 +++- .../src/pcsclite-vpcd/PCSC/ifdhandler.h | 76 +++-- .../src/pcsclite-vpcd/PCSC/reader.h | 271 ++++++++++++++++++ 3 files changed, 370 insertions(+), 26 deletions(-) create mode 100644 virtualsmartcard/src/pcsclite-vpcd/PCSC/reader.h diff --git a/virtualsmartcard/src/ifd-vpcd/ifd-vpcd.c b/virtualsmartcard/src/ifd-vpcd/ifd-vpcd.c index f09278e..ca60f8c 100644 --- a/virtualsmartcard/src/ifd-vpcd/ifd-vpcd.c +++ b/virtualsmartcard/src/ifd-vpcd/ifd-vpcd.c @@ -27,10 +27,15 @@ #include #include +#include #include #include #include +#ifdef HAVE_ARPA_INET_H +#include +#endif + /* pcscd allows at most 16 readers. Apple's SmartCardServices on OS X 10.10 * freaks out if more than 8 slots are registered. We want only two slots... */ #define VICC_MAX_SLOTS (VPCDSLOTS <= PCSCLITE_MAX_READERS_CONTEXTS ? VPCDSLOTS : PCSCLITE_MAX_READERS_CONTEXTS) @@ -101,6 +106,11 @@ void log_msg(const int priority, const char *fmt, ...) #endif #endif +/* Copied from libccid ccid_ifdhandler.h */ +#define CLASS2_IOCTL_MAGIC 0x330000 +#define IOCTL_FEATURE_GET_TLV_PROPERTIES \ + SCARD_CTL_CODE(FEATURE_GET_TLV_PROPERTIES + CLASS2_IOCTL_MAGIC) + static struct vicc_ctx *ctx[VICC_MAX_SLOTS]; const char *hostname = NULL; static const char openport[] = "/dev/null"; @@ -181,13 +191,46 @@ RESPONSECODE IFDHControl (DWORD Lun, DWORD dwControlCode, PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength, LPDWORD pdwBytesReturned) { - Log9(PCSC_LOG_DEBUG, "IFDHControl not supported (Lun=%u ControlCode=%u TxBuffer=%p TxLength=%u RxBuffer=%p RxLength=%u pBytesReturned=%p)%s", + Log9(PCSC_LOG_DEBUG, "IFDHControl (Lun=%u ControlCode=%u TxBuffer=%p TxLength=%u RxBuffer=%p RxLength=%u pBytesReturned=%p)%s", (unsigned int) Lun, (unsigned int) dwControlCode, (unsigned char *) TxBuffer, (unsigned int) TxLength, (unsigned char *) RxBuffer, (unsigned int) RxLength, (unsigned int *) pdwBytesReturned, ""); - if (pdwBytesReturned) - *pdwBytesReturned = 0; + + if (pdwBytesReturned == NULL) + return IFD_COMMUNICATION_ERROR; + + if (dwControlCode == CM_IOCTL_GET_FEATURE_REQUEST) { + if (RxLength < sizeof(PCSC_TLV_STRUCTURE)) + return IFD_ERROR_INSUFFICIENT_BUFFER; + + PCSC_TLV_STRUCTURE *pcsc_tlv = (PCSC_TLV_STRUCTURE *)RxBuffer; + pcsc_tlv->tag = FEATURE_GET_TLV_PROPERTIES; + pcsc_tlv->length = sizeof(uint32_t); + uint32_t value = htonl(IOCTL_FEATURE_GET_TLV_PROPERTIES); + memcpy(&pcsc_tlv->value, &value, sizeof(uint32_t)); + *pdwBytesReturned = sizeof(PCSC_TLV_STRUCTURE); + return IFD_SUCCESS; + } + + if (dwControlCode == IOCTL_FEATURE_GET_TLV_PROPERTIES) { + if (RxLength < 6) + return IFD_ERROR_INSUFFICIENT_BUFFER; + + // Support extended APDUs with 65536 bytes + unsigned int MaxAPDUDataSize = 0x10000; + unsigned int p = 0; + RxBuffer[p++] = PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize; + RxBuffer[p++] = 4; /* length */ + RxBuffer[p++] = MaxAPDUDataSize & 0xFF; + RxBuffer[p++] = (MaxAPDUDataSize >> 8) & 0xFF; + RxBuffer[p++] = (MaxAPDUDataSize >> 16) & 0xFF; + RxBuffer[p++] = (MaxAPDUDataSize >> 24) & 0xFF; + *pdwBytesReturned = p; + return IFD_SUCCESS; + } + + *pdwBytesReturned = 0; return IFD_ERROR_NOT_SUPPORTED; } diff --git a/virtualsmartcard/src/pcsclite-vpcd/PCSC/ifdhandler.h b/virtualsmartcard/src/pcsclite-vpcd/PCSC/ifdhandler.h index 280d0b6..a60ca8f 100644 --- a/virtualsmartcard/src/pcsclite-vpcd/PCSC/ifdhandler.h +++ b/virtualsmartcard/src/pcsclite-vpcd/PCSC/ifdhandler.h @@ -1,14 +1,35 @@ /* - * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ ) * * Copyright (C) 1999-2004 - * David Corcoran + * David Corcoran * Copyright (C) 2003-2004 * Damien Sauveron * Copyright (C) 2002-2011 * Ludovic Rousseau * - * $Id: ifdhandler.h 6413 2012-08-08 09:35:18Z rousseau $ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -19,13 +40,13 @@ The routines specified hereafter will allow you to write an IFD handler for the PC/SC Lite resource manager. Please use the complement developer's kit complete with headers and Makefile at: -http://www.musclecard.com/drivers.html +https://muscle.apdu.fr/musclecard.com/sourcedrivers.html This gives a common API for communication to most readers in a homogeneous fashion. This document assumes that the driver developer is experienced with standards such as ISO-7816-(1, 2, 3, 4), EMV and MCT specifications. For listings of these specifications please access the -above web site. +above web site. @section UsbReaders USB readers @@ -61,7 +82,7 @@ Example: 0x04E6 @endverbatim -You may have an OEM of this reader in which an additional @c +You may have an OEM of this reader in which an additional @c \ can be used like in the below example: @verbatim @@ -77,9 +98,8 @@ also. You may chose not to support this feature but it is useful when reader vendors OEM products so you only distribute one driver. -The CCID driver from Ludovic Rousseau -http://pcsclite.alioth.debian.org/ccid.html uses this feature since the -same driver supports many different readers. +The CCID driver from Ludovic Rousseau https://ccid.apdu.fr/ uses this +feature since the same driver supports many different readers. @subsection ifdProductID @@ -99,6 +119,8 @@ same driver supports many different readers. SCM Microsystems USB Reader @endverbatim +The reader name must use the ASCII character set. + @subsection CFBundleExecutable The executable name which exists in the particular platform's directory. @@ -166,7 +188,7 @@ Complete sample file: @endverbatim As indicated in the XML file the DTD is available at -http://www.apple.com/DTDs/PropertyList-1.0.dtd. +http://www.apple.com/DTDs/PropertyList-1.0.dtd. @section SerialReaders Serial readers @@ -180,7 +202,7 @@ It has the following syntax: # Configuration file for pcsc-lite # David Corcoran -FRIENDLYNAME Generic Reader +FRIENDLYNAME "Generic Reader" DEVICENAME /dev/ttyS0 LIBPATH /usr/lib/pcsc/drivers/libgen_ifd.so CHANNELID 1 @@ -306,6 +328,7 @@ whichever location your reader resides. #define TAG_IFD_POLLING_THREAD_KILLABLE 0x0FB1 /**< the polling thread can be killed */ #define TAG_IFD_STOP_POLLING_THREAD 0x0FB2 /**< method used to stop the polling thread (instead of just pthread_kill()) */ #define TAG_IFD_POLLING_THREAD_WITH_TIMEOUT 0x0FB3 /**< driver uses a polling thread with a timeout parameter */ +#define TAG_IFD_DEVICE_REMOVED 0x0FB4 /**< signals the reader has been removed*/ /* * IFD Handler version number enummerations @@ -485,7 +508,7 @@ you want extended functionality. pdwBytesReturned. @note - @p *pdwBytesReturned should be set to zero on error. + @p *pdwBytesReturned should be set to zero on error. @return Error codes @retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) @@ -526,7 +549,7 @@ Once the channel is opened the reader must be in a state in which it is possible to query IFDHICCPresence() for card status. USB readers can ignore the @p Channel parameter and query the USB bus -for the particular reader by manufacturer and product id. +for the particular reader by manufacturer and product id. @ingroup IFDHandler @param[in] Lun Logical Unit Number\n @@ -594,16 +617,17 @@ don't mind loading a new driver for each reader then ignore Lun. - \ref TAG_IFD_THREAD_SAFE If the driver supports more than one reader (see \ref TAG_IFD_SIMULTANEOUS_ACCESS above) this tag indicates if the - driver supports access to multiple readers at the same time.\n - Value[0] = 1 indicates the driver supports simultaneous accesses. + driver supports access to multiple readers at the same time. + - Value[0] = 0: the driver DOES NOT support simultaneous accesses. + - Value[0] = 1: the driver supports simultaneous accesses. - \ref TAG_IFD_SLOTS_NUMBER Return the number of slots in this reader in Value[0]. - \ref TAG_IFD_SLOT_THREAD_SAFE If the reader has more than one slot (see \ref TAG_IFD_SLOTS_NUMBER above) this tag indicates if the driver supports access to multiple - slots of the same reader at the same time.\n - Value[0] = 1 indicates the driver supports simultaneous slot - accesses. + slots of the same reader at the same time. + - value[0] = 0: the driver supports only 1 slot access at a time. + - value[0] = 1: the driver supports simultaneous slot accesses. - \ref TAG_IFD_POLLING_THREAD Unused/deprecated - \ref TAG_IFD_POLLING_THREAD_WITH_TIMEOUT @@ -614,6 +638,10 @@ don't mind loading a new driver for each reader then ignore Lun. @endverbatim - \ref TAG_IFD_POLLING_THREAD_KILLABLE Tell if the polling thread can be killed (pthread_kill()) by pcscd + - value[0] = 0: the driver can NOT be stopped using + pthread_cancel(). The driver must then implement + \ref TAG_IFD_STOP_POLLING_THREAD + - value[0] = 1: the driver can be stopped using pthread_cancel() - \ref TAG_IFD_STOP_POLLING_THREAD Returns a pointer in @p Value to the function used to stop the polling thread returned by \ref TAG_IFD_POLLING_THREAD_WITH_TIMEOUT. The @@ -626,6 +654,8 @@ don't mind loading a new driver for each reader then ignore Lun. @return Error codes @retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_ERROR_INSUFFICIENT_BUFFER Buffer is too small (\ref IFD_ERROR_INSUFFICIENT_BUFFER) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) @retval IFD_ERROR_TAG Invalid tag given (\ref IFD_ERROR_TAG) @retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) */ @@ -635,7 +665,7 @@ RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag, PDWORD Length, /** This function should set the slot/card capabilities for a particular slot/card specified by @p Lun. Again, if you have only 1 card slot and -don't mind loading a new driver for each reader then ignore @p Lun. +don't mind loading a new driver for each reader then ignore @p Lun. @ingroup IFDHandler @param[in] Lun Logical Unit Number @@ -644,7 +674,7 @@ don't mind loading a new driver for each reader then ignore @p Lun. @param[out] Value Value of the desired data This function is also called when the application uses the PC/SC -SCardGetAttrib() function. The list of supported tags is not limited. +SCardSetAttrib() function. The list of supported tags is not limited. @return Error codes @retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) @@ -657,7 +687,7 @@ RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag, DWORD Length, PUCHAR Valu /** This function should set the Protocol Type Selection (PTS) of a -particular card/slot using the three PTS parameters sent +particular card/slot using the three PTS parameters sent @ingroup IFDHandler @param[in] Lun Logical Unit Number @@ -667,7 +697,7 @@ particular card/slot using the three PTS parameters sent - \ref SCARD_PROTOCOL_T1 T=1 protocol @param[in] Flags Logical OR of possible values to determine which PTS values -to negotiate +to negotiate - \ref IFD_NEGOTIATE_PTS1 - \ref IFD_NEGOTIATE_PTS2 - \ref IFD_NEGOTIATE_PTS3 @@ -781,7 +811,7 @@ This function returns the status of the card inserted in the reader/slot specified by @p Lun. In cases where the device supports asynchronous card insertion/removal detection, it is advised that the driver manages this through a thread so the driver does not have to send and receive a -command each time this function is called. +command each time this function is called. @ingroup IFDHandler @param[in] Lun Logical Unit Number diff --git a/virtualsmartcard/src/pcsclite-vpcd/PCSC/reader.h b/virtualsmartcard/src/pcsclite-vpcd/PCSC/reader.h new file mode 100644 index 0000000..f00eed7 --- /dev/null +++ b/virtualsmartcard/src/pcsclite-vpcd/PCSC/reader.h @@ -0,0 +1,271 @@ +/* + * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ ) + * + * Copyright (C) 1999-2005 + * David Corcoran + * Copyright (C) 2005-2009 + * Ludovic Rousseau + * +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief This keeps a list of defines shared between the driver and the application + */ + +#ifndef __reader_h__ +#define __reader_h__ + +/* + * Tags for requesting card and reader attributes + */ + +#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) + +#define SCARD_CLASS_VENDOR_INFO 1 /**< Vendor information definitions */ +#define SCARD_CLASS_COMMUNICATIONS 2 /**< Communication definitions */ +#define SCARD_CLASS_PROTOCOL 3 /**< Protocol definitions */ +#define SCARD_CLASS_POWER_MGMT 4 /**< Power Management definitions */ +#define SCARD_CLASS_SECURITY 5 /**< Security Assurance definitions */ +#define SCARD_CLASS_MECHANICAL 6 /**< Mechanical characteristic definitions */ +#define SCARD_CLASS_VENDOR_DEFINED 7 /**< Vendor specific definitions */ +#define SCARD_CLASS_IFD_PROTOCOL 8 /**< Interface Device Protocol options */ +#define SCARD_CLASS_ICC_STATE 9 /**< ICC State specific definitions */ +#define SCARD_CLASS_SYSTEM 0x7fff /**< System-specific definitions */ + +#define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100) /**< Vendor name. */ +#define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101) /**< Vendor-supplied interface device type (model designation of reader). */ +#define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102) /**< Vendor-supplied interface device version (DWORD in the form 0xMMmmbbbb where MM = major version, mm = minor version, and bbbb = build number). */ +#define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103) /**< Vendor-supplied interface device serial number. */ +#define SCARD_ATTR_CHANNEL_ID SCARD_ATTR_VALUE(SCARD_CLASS_COMMUNICATIONS, 0x0110) /**< DWORD encoded as 0xDDDDCCCC, where DDDD = data channel type and CCCC = channel number */ +#define SCARD_ATTR_ASYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0120) /**< FIXME */ +#define SCARD_ATTR_DEFAULT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0121) /**< Default clock rate, in kHz. */ +#define SCARD_ATTR_MAX_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0122) /**< Maximum clock rate, in kHz. */ +#define SCARD_ATTR_DEFAULT_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0123) /**< Default data rate, in bps. */ +#define SCARD_ATTR_MAX_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0124) /**< Maximum data rate, in bps. */ +#define SCARD_ATTR_MAX_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0125) /**< Maximum bytes for information file size device. */ +#define SCARD_ATTR_SYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0126) /**< FIXME */ +#define SCARD_ATTR_POWER_MGMT_SUPPORT SCARD_ATTR_VALUE(SCARD_CLASS_POWER_MGMT, 0x0131) /**< Zero if device does not support power down while smart card is inserted. Nonzero otherwise. */ +#define SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0140) /**< FIXME */ +#define SCARD_ATTR_USER_AUTH_INPUT_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0142) /**< FIXME */ +#define SCARD_ATTR_CHARACTERISTICS SCARD_ATTR_VALUE(SCARD_CLASS_MECHANICAL, 0x0150) /**< DWORD indicating which mechanical characteristics are supported. If zero, no special characteristics are supported. Note that multiple bits can be set */ + +#define SCARD_ATTR_CURRENT_PROTOCOL_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0201) /**< FIXME */ +#define SCARD_ATTR_CURRENT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0202) /**< Current clock rate, in kHz. */ +#define SCARD_ATTR_CURRENT_F SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0203) /**< Clock conversion factor. */ +#define SCARD_ATTR_CURRENT_D SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0204) /**< Bit rate conversion factor. */ +#define SCARD_ATTR_CURRENT_N SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0205) /**< Current guard time. */ +#define SCARD_ATTR_CURRENT_W SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0206) /**< Current work waiting time. */ +#define SCARD_ATTR_CURRENT_IFSC SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0207) /**< Current byte size for information field size card. */ +#define SCARD_ATTR_CURRENT_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0208) /**< Current byte size for information field size device. */ +#define SCARD_ATTR_CURRENT_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0209) /**< Current block waiting time. */ +#define SCARD_ATTR_CURRENT_CWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020a) /**< Current character waiting time. */ +#define SCARD_ATTR_CURRENT_EBC_ENCODING SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020b) /**< Current error block control encoding. */ +#define SCARD_ATTR_EXTENDED_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020c) /**< FIXME */ + +#define SCARD_ATTR_ICC_PRESENCE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0300) /**< Single byte indicating smart card presence */ +#define SCARD_ATTR_ICC_INTERFACE_STATUS SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0301) /**< Single byte. Zero if smart card electrical contact is not active; nonzero if contact is active. */ +#define SCARD_ATTR_CURRENT_IO_STATE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0302) /**< FIXME */ +#define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303) /**< Answer to reset (ATR) string. */ +#define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304) /**< Single byte indicating smart card type */ + +#define SCARD_ATTR_ESC_RESET SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA000) /**< FIXME */ +#define SCARD_ATTR_ESC_CANCEL SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA003) /**< FIXME */ +#define SCARD_ATTR_ESC_AUTHREQUEST SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA005) /**< FIXME */ +#define SCARD_ATTR_MAXINPUT SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA007) /**< FIXME */ + +#define SCARD_ATTR_DEVICE_UNIT SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0001) /**< Instance of this vendor's reader attached to the computer. The first instance will be device unit 0, the next will be unit 1 (if it is the same brand of reader) and so on. Two different brands of readers will both have zero for this value. */ +#define SCARD_ATTR_DEVICE_IN_USE SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0002) /**< Reserved for future use. */ +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0003) +#define SCARD_ATTR_DEVICE_SYSTEM_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0004) +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0005) +#define SCARD_ATTR_DEVICE_SYSTEM_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0006) +#define SCARD_ATTR_SUPRESS_T1_IFS_REQUEST SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0007) /**< FIXME */ + +#ifdef UNICODE +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_W /**< Reader's display name. */ +#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_W /**< Reader's system name. */ +#else +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_A /**< Reader's display name. */ +#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_A /**< Reader's system name. */ +#endif + +/** + * Provide source compatibility on different platforms + */ +#define SCARD_CTL_CODE(code) (0x42000000 + (code)) + +/** + * PC/SC part 10 v2.02.07 March 2010 reader tags + */ +#define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400) + +#define FEATURE_VERIFY_PIN_START 0x01 +#define FEATURE_VERIFY_PIN_FINISH 0x02 +#define FEATURE_MODIFY_PIN_START 0x03 +#define FEATURE_MODIFY_PIN_FINISH 0x04 +#define FEATURE_GET_KEY_PRESSED 0x05 +#define FEATURE_VERIFY_PIN_DIRECT 0x06 /**< Verify PIN */ +#define FEATURE_MODIFY_PIN_DIRECT 0x07 /**< Modify PIN */ +#define FEATURE_MCT_READER_DIRECT 0x08 +#define FEATURE_MCT_UNIVERSAL 0x09 +#define FEATURE_IFD_PIN_PROPERTIES 0x0A /**< retrieve properties of the IFD regarding PIN handling */ +#define FEATURE_ABORT 0x0B +#define FEATURE_SET_SPE_MESSAGE 0x0C +#define FEATURE_VERIFY_PIN_DIRECT_APP_ID 0x0D +#define FEATURE_MODIFY_PIN_DIRECT_APP_ID 0x0E +#define FEATURE_WRITE_DISPLAY 0x0F +#define FEATURE_GET_KEY 0x10 +#define FEATURE_IFD_DISPLAY_PROPERTIES 0x11 +#define FEATURE_GET_TLV_PROPERTIES 0x12 +#define FEATURE_CCID_ESC_COMMAND 0x13 +#define FEATURE_EXECUTE_PACE 0x20 + +/* structures used (but not defined) in PC/SC Part 10: + * "IFDs with Secure Pin Entry Capabilities" */ + +#include + +/* Set structure elements aligment on bytes + * http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html */ +#if defined(__APPLE__) || defined(sun) || defined(__NetBSD__) +#pragma pack(1) +#else +#pragma pack(push, 1) +#endif + +/** the structure must be 6-bytes long */ +typedef struct +{ + uint8_t tag; + uint8_t length; + uint32_t value; /**< This value is always in BIG ENDIAN format as documented in PCSC v2 part 10 ch 2.2 page 2. You can use ntohl() for example */ +} PCSC_TLV_STRUCTURE; + +/** Since CCID 1.4.1 (revision 5252) the byte order is no more important + * These macros are now deprecated and should be removed in the future */ +#define HOST_TO_CCID_16(x) (x) +#define HOST_TO_CCID_32(x) (x) + +/** structure used with \ref FEATURE_VERIFY_PIN_DIRECT */ +typedef struct +{ + uint8_t bTimerOut; /**< timeout is seconds (00 means use default timeout) */ + uint8_t bTimerOut2; /**< timeout in seconds after first key stroke */ + uint8_t bmFormatString; /**< formatting options */ + uint8_t bmPINBlockString; /**< bits 7-4 bit size of PIN length in APDU, + * bits 3-0 PIN block size in bytes after + * justification and formatting */ + uint8_t bmPINLengthFormat; /**< bits 7-5 RFU, + * bit 4 set if system units are bytes, clear if + * system units are bits, + * bits 3-0 PIN length position in system units */ + uint16_t wPINMaxExtraDigit; /**< 0xXXYY where XX is minimum PIN size in digits, + and YY is maximum PIN size in digits */ + uint8_t bEntryValidationCondition; /**< Conditions under which PIN entry should + * be considered complete */ + uint8_t bNumberMessage; /**< Number of messages to display for PIN verification */ + uint16_t wLangId; /**< Language for messages. https://docs.microsoft.com/en-us/windows/win32/intl/language-identifier-constants-and-strings */ + uint8_t bMsgIndex; /**< Message index (should be 00) */ + uint8_t bTeoPrologue[3]; /**< T=1 block prologue field to use (fill with 00) */ + uint32_t ulDataLength; /**< length of Data to be sent to the ICC */ + uint8_t abData +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + [] /* valid C99 code */ +#else + [0] /* non-standard, but usually working code */ +#endif + ; /**< Data to send to the ICC */ +} PIN_VERIFY_STRUCTURE; + +/** structure used with \ref FEATURE_MODIFY_PIN_DIRECT */ +typedef struct +{ + uint8_t bTimerOut; /**< timeout is seconds (00 means use default timeout) */ + uint8_t bTimerOut2; /**< timeout in seconds after first key stroke */ + uint8_t bmFormatString; /**< formatting options */ + uint8_t bmPINBlockString; /**< bits 7-4 bit size of PIN length in APDU, + * bits 3-0 PIN block size in bytes after + * justification and formatting */ + uint8_t bmPINLengthFormat; /**< bits 7-5 RFU, + * bit 4 set if system units are bytes, clear if + * system units are bits, + * bits 3-0 PIN length position in system units */ + uint8_t bInsertionOffsetOld; /**< Insertion position offset in bytes for + the current PIN */ + uint8_t bInsertionOffsetNew; /**< Insertion position offset in bytes for + the new PIN */ + uint16_t wPINMaxExtraDigit; + /**< 0xXXYY where XX is minimum PIN size in digits, + and YY is maximum PIN size in digits */ + uint8_t bConfirmPIN; /**< Flags governing need for confirmation of new PIN */ + uint8_t bEntryValidationCondition; /**< Conditions under which PIN entry should + * be considered complete */ + uint8_t bNumberMessage; /**< Number of messages to display for PIN verification*/ + uint16_t wLangId; /**< Language for messages. https://docs.microsoft.com/en-us/windows/win32/intl/language-identifier-constants-and-strings */ + uint8_t bMsgIndex1; /**< index of 1st prompting message */ + uint8_t bMsgIndex2; /**< index of 2d prompting message */ + uint8_t bMsgIndex3; /**< index of 3d prompting message */ + uint8_t bTeoPrologue[3]; /**< T=1 block prologue field to use (fill with 00) */ + uint32_t ulDataLength; /**< length of Data to be sent to the ICC */ + uint8_t abData +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + [] /* valid C99 code */ +#else + [0] /* non-standard, but usually working code */ +#endif + ; /**< Data to send to the ICC */ +} PIN_MODIFY_STRUCTURE; + +/** structure used with \ref FEATURE_IFD_PIN_PROPERTIES */ +typedef struct { + uint16_t wLcdLayout; /**< display characteristics */ + uint8_t bEntryValidationCondition; + uint8_t bTimeOut2; +} PIN_PROPERTIES_STRUCTURE; + +/* restore default structure elements alignment */ +#if defined(__APPLE__) || defined(sun) || defined(__NetBSD__) +#pragma pack() +#else +#pragma pack(pop) +#endif + +/* properties returned by FEATURE_GET_TLV_PROPERTIES */ +#define PCSCv2_PART10_PROPERTY_wLcdLayout 1 +#define PCSCv2_PART10_PROPERTY_bEntryValidationCondition 2 +#define PCSCv2_PART10_PROPERTY_bTimeOut2 3 +#define PCSCv2_PART10_PROPERTY_wLcdMaxCharacters 4 +#define PCSCv2_PART10_PROPERTY_wLcdMaxLines 5 +#define PCSCv2_PART10_PROPERTY_bMinPINSize 6 +#define PCSCv2_PART10_PROPERTY_bMaxPINSize 7 +#define PCSCv2_PART10_PROPERTY_sFirmwareID 8 +#define PCSCv2_PART10_PROPERTY_bPPDUSupport 9 +#define PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize 10 +#define PCSCv2_PART10_PROPERTY_wIdVendor 11 +#define PCSCv2_PART10_PROPERTY_wIdProduct 12 + +#endif +