diff --git a/src/libopensc/internal-winscard.h b/src/libopensc/internal-winscard.h index 6c75a95a..e671817e 100644 --- a/src/libopensc/internal-winscard.h +++ b/src/libopensc/internal-winscard.h @@ -137,21 +137,27 @@ typedef LONG (PCSC_API *SCardListReaders_t)(SCARDCONTEXT hContext, LPCSTR mszGro #endif /** - * TeleTrust Class 2 reader tags + * PC/SC v2.02.05 part 10 reader tags */ #define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400) -#define FEATURE_VERIFY_PIN_START 0x01 /**< OMNIKEY Proposal */ -#define FEATURE_VERIFY_PIN_FINISH 0x02 /**< OMNIKEY Proposal */ -#define FEATURE_MODIFY_PIN_START 0x03 /**< OMNIKEY Proposal */ -#define FEATURE_MODIFY_PIN_FINISH 0x04 /**< OMNIKEY Proposal */ -#define FEATURE_GET_KEY_PRESSED 0x05 /**< OMNIKEY Proposal */ -#define FEATURE_VERIFY_PIN_DIRECT 0x06 /**< USB CCID PIN Verify */ -#define FEATURE_MODIFY_PIN_DIRECT 0x07 /**< USB CCID PIN Modify */ -#define FEATURE_MCT_READERDIRECT 0x08 /**< KOBIL Proposal */ -#define FEATURE_MCT_UNIVERSAL 0x09 /**< KOBIL Proposal */ -#define FEATURE_IFD_PIN_PROP 0x0A /**< Gemplus Proposal */ -#define FEATURE_ABORT 0x0B /**< SCM Proposal */ +#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 +#define FEATURE_MODIFY_PIN_DIRECT 0x07 +#define FEATURE_MCT_READERDIRECT 0x08 +#define FEATURE_MCT_UNIVERSAL 0x09 +#define FEATURE_IFD_PIN_PROPERTIES 0x0A +#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 /* structures used (but not defined) in PCSC Part 10 revision 2.01.02: * "IFDs with Secure Pin Entry Capabilities" */ @@ -235,6 +241,14 @@ typedef struct uint8_t abData[1]; /**< Data to send to the ICC */ } PIN_MODIFY_STRUCTURE; +typedef struct { + uint16_t wLcdLayout; /**< display characteristics */ + uint16_t wLcdMaxCharacters; + uint16_t wLcdMaxLines; + uint8_t bEntryValidationCondition; + uint8_t bTimeOut2; +} PIN_PROPERTIES_STRUCTURE; + /* restore default structure elements alignment */ #ifdef __APPLE__ #pragma pack() diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 9d9529d4..3bf5b523 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -207,7 +207,7 @@ static int pcsc_internal_transmit(sc_reader_t *reader, sc_slot_info_t *slot, return SC_ERROR_UNKNOWN_DATA_RECEIVED; *recvsize = dwRecvLength; - return 0; + return SC_SUCCESS; } static int pcsc_transmit(sc_reader_t *reader, sc_slot_info_t *slot, @@ -422,7 +422,7 @@ static int pcsc_wait_for_event(sc_reader_t **readers, *event |= SC_EVENT_CARD_REMOVED; if (*event) { *reader = i; - return 0; + return SC_SUCCESS; } /* No match - copy the state so pcscd knows @@ -509,7 +509,7 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot) struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot); int r; u8 feature_buf[256]; - DWORD i, feature_len; + DWORD i, feature_len, display_ioctl; PCSC_TLV_STRUCTURE *pcsc_tlv; r = refresh_slot_attributes(reader, slot); @@ -575,6 +575,8 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot) pslot->modify_ioctl_start = ntohl(pcsc_tlv[i].value); } else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_FINISH) { pslot->modify_ioctl_finish = ntohl(pcsc_tlv[i].value); + } else if (pcsc_tlv[i].tag == FEATURE_IFD_PIN_PROPERTIES) { + display_ioctl = ntohl(pcsc_tlv[i].value); } else { sc_debug(reader->ctx, "Reader pinpad feature: %02x not supported", pcsc_tlv[i].tag); } @@ -599,7 +601,25 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot) } else { sc_debug(reader->ctx, "%s %s", log_text, log_disabled); } - } + } + + if (display_ioctl) { + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; + size_t rcount = sizeof(rbuf); + r = pcsc_internal_transmit(reader, slot, NULL, 0, rbuf, &rcount, display_ioctl); + if (r == SC_SUCCESS) { + if (rcount != sizeof(PIN_PROPERTIES_STRUCTURE)) { + PIN_PROPERTIES_STRUCTURE *caps = (PIN_PROPERTIES_STRUCTURE *)rbuf; + if (caps->wLcdLayout > 0) { + sc_debug(reader->ctx, "Reader has a display: %04X", caps->wLcdLayout); + slot->capabilities |= SC_SLOT_CAP_DISPLAY; + } else + sc_debug(reader->ctx, "Reader does not have a display."); + } else { + sc_debug(reader->ctx, "Returned PIN properties structure has bad length (%d)", rcount); + } + } + } } else sc_debug(reader->ctx, "Inconsistent TLV from reader!"); } else { @@ -838,7 +858,7 @@ static int pcsc_finish(sc_context_t *ctx, void *prv_data) free(gpriv); } - return 0; + return SC_SUCCESS; } static int pcsc_detect_readers(sc_context_t *ctx, void *prv_data)