* Correctly set offsets for PINs for PIN modification operations with pinpads. Thanks to Robert Konklewski.
* Only set messages if the reader has display capabilities. * Detect rejected pinpad commands * Whitespace fixes git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3679 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
16baddcc74
commit
6041595895
|
@ -110,9 +110,9 @@ static int pcsc_ret_to_error(long rv)
|
|||
case SCARD_E_NO_READERS_AVAILABLE:
|
||||
return SC_ERROR_NO_READERS_FOUND;
|
||||
#endif
|
||||
case SCARD_E_NO_SERVICE:
|
||||
/* If the service is (auto)started, there could be readers later */
|
||||
return SC_ERROR_NO_READERS_FOUND;
|
||||
case SCARD_E_NO_SERVICE:
|
||||
/* If the service is (auto)started, there could be readers later */
|
||||
return SC_ERROR_NO_READERS_FOUND;
|
||||
default:
|
||||
return SC_ERROR_UNKNOWN;
|
||||
}
|
||||
|
@ -505,7 +505,8 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
|||
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
||||
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
|
||||
int r;
|
||||
u8 feature_buf[256];
|
||||
u8 feature_buf[256], rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
size_t rcount;
|
||||
DWORD i, feature_len, display_ioctl;
|
||||
PCSC_TLV_STRUCTURE *pcsc_tlv;
|
||||
|
||||
|
@ -543,7 +544,7 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
|||
}
|
||||
sc_debug(reader->ctx, "Proto after reconnect = %d", slot->active_protocol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for pinpad support */
|
||||
if (priv->gpriv->SCardControl != NULL) {
|
||||
|
@ -580,7 +581,7 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
|||
} 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);
|
||||
sc_debug(reader->ctx, "Reader feature %02x is not supported", pcsc_tlv[i].tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -602,25 +603,24 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
|||
slot->capabilities |= SC_SLOT_CAP_PIN_PAD;
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (display_ioctl) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -634,7 +634,7 @@ static int pcsc_disconnect(sc_reader_t * reader, sc_slot_info_t * slot)
|
|||
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
||||
|
||||
priv->gpriv->SCardDisconnect(pslot->pcsc_card, priv->gpriv->transaction_reset ?
|
||||
SCARD_RESET_CARD : SCARD_LEAVE_CARD);
|
||||
SCARD_RESET_CARD : SCARD_LEAVE_CARD);
|
||||
memset(pslot, 0, sizeof(*pslot));
|
||||
slot->flags = 0;
|
||||
return SC_SUCCESS;
|
||||
|
@ -807,7 +807,7 @@ static int pcsc_init(sc_context_t *ctx, void **reader_data)
|
|||
gpriv->SCardControl = (SCardControl_t)lt_dlsym(gpriv->dlhandle, "SCardControl132");
|
||||
#endif
|
||||
if (gpriv->SCardControl == NULL) {
|
||||
gpriv->SCardControl = (SCardControl_t)lt_dlsym(gpriv->dlhandle, "SCardControl");
|
||||
gpriv->SCardControl = (SCardControl_t)lt_dlsym(gpriv->dlhandle, "SCardControl");
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1018,10 +1018,10 @@ out:
|
|||
static int
|
||||
pcsc_pin_cmd(sc_reader_t *reader, sc_slot_info_t * slot, struct sc_pin_cmd_data *data)
|
||||
{
|
||||
/* XXX: temporary */
|
||||
if (slot->capabilities & SC_SLOT_CAP_PIN_PAD) {
|
||||
return part10_pin_cmd(reader, slot, data);
|
||||
} else {
|
||||
/* XXX: probably dead code */
|
||||
return ctbcs_pin_cmd(reader, slot, data);
|
||||
}
|
||||
}
|
||||
|
@ -1051,7 +1051,7 @@ struct sc_reader_driver * sc_get_pcsc_driver(void)
|
|||
*/
|
||||
|
||||
/* Local definitions */
|
||||
#define SC_CCID_PIN_TIMEOUT 30
|
||||
#define SC_CCID_PIN_TIMEOUT 30
|
||||
|
||||
/* CCID definitions */
|
||||
#define SC_CCID_PIN_ENCODING_BIN 0x00
|
||||
|
@ -1061,13 +1061,13 @@ struct sc_reader_driver * sc_get_pcsc_driver(void)
|
|||
#define SC_CCID_PIN_UNITS_BYTES 0x80
|
||||
|
||||
/* 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, sc_slot_info_t *slot, struct sc_pin_cmd_data *data)
|
||||
{
|
||||
int offset = 0, count = 0;
|
||||
sc_apdu_t *apdu = data->apdu;
|
||||
u8 tmp;
|
||||
unsigned int tmp16;
|
||||
PIN_VERIFY_STRUCTURE *pin_verify = (PIN_VERIFY_STRUCTURE *)buf;
|
||||
PIN_VERIFY_STRUCTURE *pin_verify = (PIN_VERIFY_STRUCTURE *)buf;
|
||||
|
||||
/* PIN verification control message */
|
||||
pin_verify->bTimerOut = SC_CCID_PIN_TIMEOUT;
|
||||
|
@ -1120,8 +1120,11 @@ static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_
|
|||
pin_verify->wPINMaxExtraDigit = HOST_TO_CCID_16(tmp16); /* Min Max */
|
||||
|
||||
pin_verify->bEntryValidationCondition = 0x02; /* Keypress only */
|
||||
|
||||
pin_verify->bNumberMessage = 0xFF; /* Default message */
|
||||
|
||||
if (slot->capabilities & SC_SLOT_CAP_DISPLAY)
|
||||
pin_verify->bNumberMessage = 0xFF; /* Default message */
|
||||
else
|
||||
pin_verify->bNumberMessage = 0x00; /* No messages */
|
||||
|
||||
/* Ignore language and T=1 parameters. */
|
||||
pin_verify->wLangId = HOST_TO_CCID_16(0x0000);
|
||||
|
@ -1129,7 +1132,7 @@ static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_
|
|||
pin_verify->bTeoPrologue[0] = 0x00;
|
||||
pin_verify->bTeoPrologue[1] = 0x00;
|
||||
pin_verify->bTeoPrologue[2] = 0x00;
|
||||
|
||||
|
||||
/* APDU itself */
|
||||
pin_verify->abData[offset++] = apdu->cla;
|
||||
pin_verify->abData[offset++] = apdu->ins;
|
||||
|
@ -1153,7 +1156,7 @@ static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_
|
|||
|
||||
|
||||
/* 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, sc_slot_info_t *slot, struct sc_pin_cmd_data *data)
|
||||
{
|
||||
int offset = 0, count = 0;
|
||||
sc_apdu_t *apdu = data->apdu;
|
||||
|
@ -1205,14 +1208,14 @@ static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_
|
|||
}
|
||||
pin_modify->bmPINLengthFormat = tmp; /* bmPINLengthFormat */
|
||||
|
||||
pin_modify->bInsertionOffsetOld = 0x00; /* bOffsetOld */
|
||||
|
||||
/* bInsertionOffsetNew */
|
||||
tmp = 0x00;
|
||||
if (data->pin1.encoding == SC_PIN_ENCODING_GLP) {
|
||||
tmp = 0x08;
|
||||
/* Set offsets if not Case 1 APDU */
|
||||
if (data->pin1.length_offset != 4) {
|
||||
pin_modify->bInsertionOffsetOld = data->pin1.offset - 5;
|
||||
pin_modify->bInsertionOffsetNew = data->pin2.offset - 5;
|
||||
} else {
|
||||
pin_modify->bInsertionOffsetOld = 0x00;
|
||||
pin_modify->bInsertionOffsetNew = 0x00;
|
||||
}
|
||||
pin_modify->bInsertionOffsetNew = tmp; /* bOffsetNew */
|
||||
|
||||
if (!data->pin1.min_length || !data->pin1.max_length)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
@ -1222,17 +1225,21 @@ static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_
|
|||
|
||||
pin_modify->bConfirmPIN = 0x03; /* bConfirmPIN, all */
|
||||
pin_modify->bEntryValidationCondition = 0x02; /* bEntryValidationCondition, keypress only */
|
||||
|
||||
if (slot->capabilities & SC_SLOT_CAP_DISPLAY)
|
||||
pin_modify->bNumberMessage = 0x03; /* 3 messages (because bConfirmPIN = 3), all default. Could be 0xFF too */
|
||||
else
|
||||
pin_modify->bNumberMessage = 0x00; /* No messages */
|
||||
|
||||
/* Ignore language and T=1 parameters. */
|
||||
pin_modify->bNumberMessage = 0x00; /* XXX: Latest released CCID driver rejects 0xFF */
|
||||
pin_modify->wLangId = HOST_TO_CCID_16(0x0000);
|
||||
pin_modify->bMsgIndex1 = 0x00;
|
||||
pin_modify->bMsgIndex2 = 0x00;
|
||||
pin_modify->bMsgIndex3 = 0x00;
|
||||
pin_modify->bMsgIndex1 = 0x00; /* Default message indexes */
|
||||
pin_modify->bMsgIndex2 = 0x01;
|
||||
pin_modify->bMsgIndex3 = 0x02;
|
||||
pin_modify->bTeoPrologue[0] = 0x00;
|
||||
pin_modify->bTeoPrologue[1] = 0x00;
|
||||
pin_modify->bTeoPrologue[2] = 0x00;
|
||||
|
||||
|
||||
/* APDU itself */
|
||||
pin_modify->abData[offset++] = apdu->cla;
|
||||
pin_modify->abData[offset++] = apdu->ins;
|
||||
|
@ -1286,7 +1293,7 @@ part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
|||
sc_error(reader->ctx, "Pinpad reader does not support verification!");
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
r = part10_build_verify_pin_block(sbuf, &scount, data);
|
||||
r = part10_build_verify_pin_block(sbuf, &scount, slot, data);
|
||||
ioctl = pslot->verify_ioctl ? pslot->verify_ioctl : pslot->verify_ioctl_start;
|
||||
break;
|
||||
case SC_PIN_CMD_CHANGE:
|
||||
|
@ -1295,7 +1302,7 @@ part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
|||
sc_error(reader->ctx, "Pinpad reader does not support modification!");
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
r = part10_build_modify_pin_block(sbuf, &scount, data);
|
||||
r = part10_build_modify_pin_block(sbuf, &scount, slot, data);
|
||||
ioctl = pslot->modify_ioctl ? pslot->modify_ioctl : pslot->modify_ioctl_start;
|
||||
break;
|
||||
default:
|
||||
|
@ -1337,14 +1344,17 @@ part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
|||
r = SC_SUCCESS;
|
||||
switch (((unsigned int) apdu->sw1 << 8) | apdu->sw2) {
|
||||
case 0x6400: /* Input timed out */
|
||||
r = SC_ERROR_KEYPAD_TIMEOUT;
|
||||
r = SC_ERROR_KEYPAD_TIMEOUT;
|
||||
break;
|
||||
case 0x6401: /* Input cancelled */
|
||||
r = SC_ERROR_KEYPAD_CANCELLED;
|
||||
r = SC_ERROR_KEYPAD_CANCELLED;
|
||||
break;
|
||||
case 0x6402: /* PINs don't match */
|
||||
r = SC_ERROR_KEYPAD_PIN_MISMATCH;
|
||||
break;
|
||||
case 0x6B80: /* Wrong data in the buffer, rejected by firmware */
|
||||
r = SC_ERROR_READER;
|
||||
break;
|
||||
}
|
||||
|
||||
SC_TEST_RET(reader->ctx, r, "PIN command failed");
|
||||
|
|
Loading…
Reference in New Issue