Update pcsc pinpad code to latest pcsc-lite code, limit to pcsc-lite only.

Verify works fine, modify needs some debugging-testing.


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@2668 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
martin 2005-10-29 21:17:15 +00:00
parent 1f58981bcb
commit 89cfac8735
1 changed files with 92 additions and 84 deletions

View File

@ -34,6 +34,9 @@
#ifdef HAVE_READER_H #ifdef HAVE_READER_H
#include <reader.h> #include <reader.h>
#ifdef HOST_TO_CCID_32
#define PINPAD_ENABLED
#endif
#endif #endif
/* Default timeout value for SCardGetStatusChange /* Default timeout value for SCardGetStatusChange
@ -436,10 +439,11 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
struct pcsc_private_data *priv = GET_PRIV_DATA(reader); struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot); struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
int r; int r;
#ifdef CM_IOCTL_GET_FEATURE_REQUEST #ifdef PINPAD_ENABLED
int i; int i;
u8 feature_buf[256]; u8 feature_buf[256];
DWORD feature_len; DWORD feature_len;
PCSC_TLV_STRUCTURE *pcsc_tlv;
#endif #endif
r = refresh_slot_attributes(reader, slot); r = refresh_slot_attributes(reader, slot);
@ -465,28 +469,33 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
pslot->pcsc_card = card_handle; pslot->pcsc_card = card_handle;
/* check for pinpad support */ /* check for pinpad support */
#ifdef CM_IOCTL_GET_FEATURE_REQUEST #ifdef PINPAD_ENABLED
sc_debug(reader->ctx, "Requesting reader features ... "); sc_debug(reader->ctx, "Requesting reader features ... ");
rv = SCardControl(pslot->pcsc_card, CM_IOCTL_GET_FEATURE_REQUEST, NULL, rv = SCardControl(pslot->pcsc_card, CM_IOCTL_GET_FEATURE_REQUEST, NULL,
0, feature_buf, sizeof(feature_buf), &feature_len); 0, feature_buf, sizeof(feature_buf), &feature_len);
if (rv == SCARD_S_SUCCESS) { if (rv == SCARD_S_SUCCESS) {
if (!(feature_len % 6)) {
for (i = 0; i < feature_len; i += 6) { if (!(feature_len % sizeof(PCSC_TLV_STRUCTURE))) {
if (feature_buf[i] == FEATURE_VERIFY_PIN_DIRECT) { /* get the number of elements instead of the complete size */
feature_len /= sizeof(PCSC_TLV_STRUCTURE);
pcsc_tlv = (PCSC_TLV_STRUCTURE *)feature_buf;
for (i = 0; i < feature_len; i++) {
if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_DIRECT) {
sc_debug(reader->ctx, "Reader supports pinpad PIN verification"); sc_debug(reader->ctx, "Reader supports pinpad PIN verification");
pslot->verify_ioctl = dw2i_be(feature_buf, i + 2); pslot->verify_ioctl = pcsc_tlv[i].value;
if (priv->gpriv->enable_pinpad) { if (priv->gpriv->enable_pinpad) {
slot->capabilities |= SC_SLOT_CAP_PIN_PAD; slot->capabilities |= SC_SLOT_CAP_PIN_PAD;
} }
} else if (feature_buf[i] == FEATURE_MODIFY_PIN_DIRECT) { } else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_DIRECT) {
sc_debug(reader->ctx, "Reader supports pinpad PIN modification"); sc_debug(reader->ctx, "Reader supports pinpad PIN modification");
pslot->modify_ioctl = dw2i_be(feature_buf, i + 2); pslot->modify_ioctl = pcsc_tlv[i].value;
if (priv->gpriv->enable_pinpad) { if (priv->gpriv->enable_pinpad) {
slot->capabilities |= SC_SLOT_CAP_PIN_PAD; slot->capabilities |= SC_SLOT_CAP_PIN_PAD;
} }
} else { } else {
sc_debug(reader->ctx, "Reader pinpad feature: %02x not recognized", feature_buf[i]); sc_debug(reader->ctx, "Reader pinpad feature: %02x not recognized", pcsc_tlv[i].tag);
} }
} }
} else } else
@ -494,7 +503,7 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
} else { } else {
PCSC_ERROR(reader->ctx, "SCardControl failed", rv) PCSC_ERROR(reader->ctx, "SCardControl failed", rv)
} }
#endif /* CM_IOCTL_GET_FEATURE_REQUEST */ #endif /* PINPAD_ENABLED */
return SC_SUCCESS; return SC_SUCCESS;
} }
@ -729,6 +738,7 @@ struct sc_reader_driver * sc_get_pcsc_driver(void)
* Similar to CCID in spirit. * Similar to CCID in spirit.
*/ */
#ifdef PINPAD_ENABLED
/* Local definitions */ /* Local definitions */
#define SC_CCID_PIN_TIMEOUT 30 #define SC_CCID_PIN_TIMEOUT 30
@ -742,22 +752,23 @@ struct sc_reader_driver * sc_get_pcsc_driver(void)
/* Build a pin verification block + APDU */ /* Build a pin verification block + APDU */
static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_cmd_data *data) static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_cmd_data *data)
{ {
size_t buflen, count = 0; int offset = 0, count = 0;
sc_apdu_t *apdu = data->apdu; sc_apdu_t *apdu = data->apdu;
u8 tmp; u8 tmp;
buflen = sizeof(buf); uint16_t tmp16;
PIN_VERIFY_STRUCTURE *pin_verify = (PIN_VERIFY_STRUCTURE *)buf;
/* PIN verification control message */ /* PIN verification control message */
buf[count++] = SC_CCID_PIN_TIMEOUT; /* bTimeOut */ pin_verify->bTimerOut = SC_CCID_PIN_TIMEOUT;
buf[count++] = SC_CCID_PIN_TIMEOUT; /* bTimeOut2 */ pin_verify->bTimerOut2 = SC_CCID_PIN_TIMEOUT;
/* bmFormatString */ /* bmFormatString */
tmp = 0x00; tmp = 0x00;
if (data->pin1.encoding == SC_PIN_ENCODING_ASCII) { if (data->pin1.encoding == SC_PIN_ENCODING_ASCII) {
tmp |= SC_CCID_PIN_ENCODING_ASCII; tmp |= SC_CCID_PIN_ENCODING_ASCII;
/* if the effective pin length offset is specified, use it */ /* if the effective pin length offset is specified, use it */
if (data->pin1.length_offset > 3) { if (data->pin1.length_offset > 4) {
tmp |= SC_CCID_PIN_UNITS_BYTES; tmp |= SC_CCID_PIN_UNITS_BYTES;
tmp |= (data->pin1.length_offset - 5) << 3; tmp |= (data->pin1.length_offset - 5) << 3;
} }
@ -771,7 +782,7 @@ static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_
} else } else
return SC_ERROR_NOT_SUPPORTED; return SC_ERROR_NOT_SUPPORTED;
buf[count++] = tmp; /* bmFormatString */ pin_verify->bmFormatString = tmp;
/* bmPINBlockString */ /* bmPINBlockString */
tmp = 0x00; tmp = 0x00;
@ -779,7 +790,7 @@ static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_
/* GLP pin length is encoded in 4 bits and block size is always 8 bytes */ /* GLP pin length is encoded in 4 bits and block size is always 8 bytes */
tmp |= 0x40 | 0x08; tmp |= 0x40 | 0x08;
} }
buf[count++] = tmp; /* bmPINBlockString */ pin_verify->bmPINBlockString = tmp;
/* bmPINLengthFormat */ /* bmPINLengthFormat */
tmp = 0x00; tmp = 0x00;
@ -787,43 +798,39 @@ static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_
/* GLP pins expect the effective pin length from bit 4 */ /* GLP pins expect the effective pin length from bit 4 */
tmp |= 0x04; tmp |= 0x04;
} }
buf[count++] = tmp; /* bmPINLengthFormat */ pin_verify->bmPINLengthFormat = tmp; /* bmPINLengthFormat */
if (!data->pin1.min_length || !data->pin1.max_length) if (!data->pin1.min_length || !data->pin1.max_length)
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
buf[count++] = data->pin1.max_length; /* wPINMaxExtraDigit: max */
buf[count++] = data->pin1.min_length; /* wPINMaxExtraDigit: min */
buf[count++] = 0x02; /* bEntryValidationCondition, keypress only */
tmp16 = (data->pin1.min_length << 8 ) + data->pin1.max_length;
pin_verify->wPINMaxExtraDigit = HOST_TO_CCID_16(tmp16); /* Min Max */
pin_verify->bEntryValidationCondition = 0x02; /* Keypress only */
/* Ignore language and T=1 parameters. */ /* Ignore language and T=1 parameters. */
buf[count++] = 0x00; /* bNumberMessage */ pin_verify->bNumberMessage = 0x00;
buf[count++] = 0x00; /* wLangId */ pin_verify->wLangId = HOST_TO_CCID_16(0x0000);
buf[count++] = 0x00; /* " */ pin_verify->bMsgIndex = 0x00;
buf[count++] = 0x00; /* bMsgIndex */ pin_verify->bTeoPrologue[0] = 0x00;
buf[count++] = 0x00; /* bTeoPrologue */ pin_verify->bTeoPrologue[1] = 0x00;
buf[count++] = 0x00; /* " */ pin_verify->bTeoPrologue[2] = 0x00;
buf[count++] = 0x00; /* " */
/* ulDataLength */
if (data->pin1.length_offset != 4)
tmp = apdu->datalen + 4;
else
tmp = 4;
buf[count++] = tmp; /* ulDataLength */
/* APDU itself */ /* APDU itself */
buf[count++] = apdu->cla; pin_verify->abData[offset++] = apdu->cla;
buf[count++] = apdu->ins; pin_verify->abData[offset++] = apdu->ins;
buf[count++] = apdu->p1; pin_verify->abData[offset++] = apdu->p1;
buf[count++] = apdu->p2; pin_verify->abData[offset++] = apdu->p2;
/* Copy data if not Case 1 */ /* Copy data if not Case 1 */
if (data->pin1.length_offset != 4) { if (data->pin1.length_offset != 4) {
memcpy(&buf[count], apdu->data, apdu->datalen); memcpy(&pin_verify->abData[offset], apdu->data, apdu->datalen);
count += apdu->datalen; offset += apdu->datalen;
} }
pin_verify->ulDataLength = HOST_TO_CCID_32(offset); /* APDU size */
count = sizeof(PIN_VERIFY_STRUCTURE) + offset -1;
*size = count; *size = count;
return SC_SUCCESS; return SC_SUCCESS;
} }
@ -833,14 +840,15 @@ static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_
/* Build a pin modification block + APDU */ /* Build a pin modification block + APDU */
static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_cmd_data *data) static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_cmd_data *data)
{ {
size_t buflen, count = 0; int offset = 0, count = 0;
sc_apdu_t *apdu = data->apdu; sc_apdu_t *apdu = data->apdu;
u8 tmp; u8 tmp;
buflen = sizeof(buf); uint16_t tmp16;
PIN_MODIFY_STRUCTURE *pin_modify = (PIN_MODIFY_STRUCTURE *)buf;
/* PIN verification control message */ /* PIN verification control message */
buf[count++] = SC_CCID_PIN_TIMEOUT; /* bTimeOut */ pin_modify->bTimerOut = SC_CCID_PIN_TIMEOUT; /* bTimeOut */
buf[count++] = SC_CCID_PIN_TIMEOUT; /* bTimeOut2 */ pin_modify->bTimerOut2 = SC_CCID_PIN_TIMEOUT; /* bTimeOut2 */
/* bmFormatString */ /* bmFormatString */
tmp = 0x00; tmp = 0x00;
@ -848,7 +856,7 @@ static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_
tmp |= SC_CCID_PIN_ENCODING_ASCII; tmp |= SC_CCID_PIN_ENCODING_ASCII;
/* if the effective pin length offset is specified, use it */ /* if the effective pin length offset is specified, use it */
if (data->pin1.length_offset > 3) { if (data->pin1.length_offset > 4) {
tmp |= SC_CCID_PIN_UNITS_BYTES; tmp |= SC_CCID_PIN_UNITS_BYTES;
tmp |= (data->pin1.length_offset - 5) << 3; tmp |= (data->pin1.length_offset - 5) << 3;
} }
@ -862,7 +870,7 @@ static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_
} else } else
return SC_ERROR_NOT_SUPPORTED; return SC_ERROR_NOT_SUPPORTED;
buf[count++] = tmp; /* bmFormatString */ pin_modify->bmFormatString = tmp; /* bmFormatString */
/* bmPINBlockString */ /* bmPINBlockString */
tmp = 0x00; tmp = 0x00;
@ -870,7 +878,7 @@ static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_
/* GLP pin length is encoded in 4 bits and block size is always 8 bytes */ /* GLP pin length is encoded in 4 bits and block size is always 8 bytes */
tmp |= 0x40 | 0x08; tmp |= 0x40 | 0x08;
} }
buf[count++] = tmp; /* bmPINBlockString */ pin_modify->bmPINBlockString = tmp; /* bmPINBlockString */
/* bmPINLengthFormat */ /* bmPINLengthFormat */
tmp = 0x00; tmp = 0x00;
@ -878,59 +886,56 @@ static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_
/* GLP pins expect the effective pin length from bit 4 */ /* GLP pins expect the effective pin length from bit 4 */
tmp |= 0x04; tmp |= 0x04;
} }
buf[count++] = tmp; /* bmPINLengthFormat */ pin_modify->bmPINLengthFormat = tmp; /* bmPINLengthFormat */
buf[count++] = 0x00; /* bOffsetOld */ pin_modify->bInsertionOffsetOld = 0x00; /* bOffsetOld */
buf[count++] = 0x00; /* bOffsetNew */ pin_modify->bInsertionOffsetNew = 0x00; /* bOffsetNew */
if (!data->pin1.min_length || !data->pin1.max_length) if (!data->pin1.min_length || !data->pin1.max_length)
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
buf[count++] = data->pin1.max_length; /* wPINMaxExtraDigit: max */
buf[count++] = data->pin1.min_length; /* wPINMaxExtraDigit: min */ tmp16 = (data->pin1.min_length << 8 ) + data->pin1.max_length;
pin_modify->wPINMaxExtraDigit = HOST_TO_CCID_16(tmp16); /* Min Max */
buf[count++] = 0x03; /* bConfirmPIN, all */ pin_modify->bConfirmPIN = 0x03; /* bConfirmPIN, all */
buf[count++] = 0x02; /* bEntryValidationCondition, keypress only */ pin_modify->bEntryValidationCondition = 0x02; /* bEntryValidationCondition, keypress only */
/* Ignore language and T=1 parameters. */ /* Ignore language and T=1 parameters. */
buf[count++] = 0x00; /* bNumberMessage */ pin_modify->bNumberMessage = 0x00;
buf[count++] = 0x00; /* wLangId */ pin_modify->wLangId = HOST_TO_CCID_16(0x0000);
buf[count++] = 0x00; /* " */ pin_modify->bMsgIndex1 = 0x00;
/* Only as many as bNumberMessage messages, currently none */ pin_modify->bMsgIndex2 = 0x00;
/* buf[count++] = 0x00; */ /* bMsgIndex1 */ pin_modify->bMsgIndex3 = 0x00;
/* buf[count++] = 0x00; */ /* bMsgIndex2 */ pin_modify->bTeoPrologue[0] = 0x00;
/* buf[count++] = 0x00; */ /* bMsgIndex3 */ pin_modify->bTeoPrologue[1] = 0x00;
buf[count++] = 0x00; /* bTeoPrologue */ pin_modify->bTeoPrologue[2] = 0x00;
buf[count++] = 0x00; /* " */
buf[count++] = 0x00; /* " */
/* ulDataLength */
if (data->pin1.length_offset != 4)
tmp = apdu->datalen + 4;
else
tmp = 4;
buf[count++] = tmp; /* ulDataLength */
/* APDU itself */ /* APDU itself */
buf[count++] = apdu->cla; pin_modify->abData[offset++] = apdu->cla;
buf[count++] = apdu->ins; pin_modify->abData[offset++] = apdu->ins;
buf[count++] = apdu->p1; pin_modify->abData[offset++] = apdu->p1;
buf[count++] = apdu->p2; pin_modify->abData[offset++] = apdu->p2;
/* Copy full APDU if not Case 1 */ /* Copy data if not Case 1 */
if (data->pin1.length_offset != 4) { if (data->pin1.length_offset != 4) {
memcpy(&buf[count], apdu->data, apdu->datalen); memcpy(&pin_modify->abData[offset], apdu->data, apdu->datalen);
count += apdu->datalen; offset += apdu->datalen;
} }
pin_modify->ulDataLength = HOST_TO_CCID_32(offset); /* APDU size */
count = sizeof(PIN_MODIFY_STRUCTURE) + offset -1;
*size = count; *size = count;
return SC_SUCCESS; return SC_SUCCESS;
} }
#endif
/* Do the PIN command */ /* Do the PIN command */
static int static int
part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot, part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
struct sc_pin_cmd_data *data) struct sc_pin_cmd_data *data)
{ {
#ifdef PINPAD_ENABLED
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE], sbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE], sbuf[SC_MAX_APDU_BUFFER_SIZE];
char dbuf[SC_MAX_APDU_BUFFER_SIZE * 3]; char dbuf[SC_MAX_APDU_BUFFER_SIZE * 3];
size_t rcount = sizeof(rbuf), scount = 0; size_t rcount = sizeof(rbuf), scount = 0;
@ -1014,6 +1019,9 @@ part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
/* PIN command completed, all is good */ /* PIN command completed, all is good */
return SC_SUCCESS; return SC_SUCCESS;
#else
return SC_ERROR_NOT_SUPPORTED;
#endif /* PINPAD_ENABLED */
} }
#endif /* HAVE_PCSC */ #endif /* HAVE_PCSC */