* 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:
martin 2009-04-08 10:31:18 +00:00
parent 16baddcc74
commit 6041595895
1 changed files with 60 additions and 50 deletions

View File

@ -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");