* 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

@ -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_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;
u8 feature_buf[256]; u8 feature_buf[256], rbuf[SC_MAX_APDU_BUFFER_SIZE];
size_t rcount;
DWORD i, feature_len, display_ioctl; DWORD i, feature_len, display_ioctl;
PCSC_TLV_STRUCTURE *pcsc_tlv; PCSC_TLV_STRUCTURE *pcsc_tlv;
@ -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) { } else if (pcsc_tlv[i].tag == FEATURE_IFD_PIN_PROPERTIES) {
display_ioctl = ntohl(pcsc_tlv[i].value); display_ioctl = ntohl(pcsc_tlv[i].value);
} else { } 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);
} }
} }
@ -603,10 +604,10 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
} else { } else {
sc_debug(reader->ctx, "%s %s", log_text, log_disabled); sc_debug(reader->ctx, "%s %s", log_text, log_disabled);
} }
}
if (display_ioctl) { if (display_ioctl) {
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; rcount = sizeof(rbuf);
size_t rcount = sizeof(rbuf);
r = pcsc_internal_transmit(reader, slot, NULL, 0, rbuf, &rcount, display_ioctl); r = pcsc_internal_transmit(reader, slot, NULL, 0, rbuf, &rcount, display_ioctl);
if (r == SC_SUCCESS) { if (r == SC_SUCCESS) {
if (rcount != sizeof(PIN_PROPERTIES_STRUCTURE)) { if (rcount != sizeof(PIN_PROPERTIES_STRUCTURE)) {
@ -624,7 +625,6 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
} }
} }
} }
}
return SC_SUCCESS; return SC_SUCCESS;
} }
@ -1018,10 +1018,10 @@ out:
static int static int
pcsc_pin_cmd(sc_reader_t *reader, sc_slot_info_t * slot, struct sc_pin_cmd_data *data) 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) { if (slot->capabilities & SC_SLOT_CAP_PIN_PAD) {
return part10_pin_cmd(reader, slot, data); return part10_pin_cmd(reader, slot, data);
} else { } else {
/* XXX: probably dead code */
return ctbcs_pin_cmd(reader, slot, data); return ctbcs_pin_cmd(reader, slot, data);
} }
} }
@ -1061,7 +1061,7 @@ struct sc_reader_driver * sc_get_pcsc_driver(void)
#define SC_CCID_PIN_UNITS_BYTES 0x80 #define SC_CCID_PIN_UNITS_BYTES 0x80
/* 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, sc_slot_info_t *slot, struct sc_pin_cmd_data *data)
{ {
int offset = 0, count = 0; int offset = 0, count = 0;
sc_apdu_t *apdu = data->apdu; sc_apdu_t *apdu = data->apdu;
@ -1121,7 +1121,10 @@ static int part10_build_verify_pin_block(u8 * buf, size_t * size, struct sc_pin_
pin_verify->bEntryValidationCondition = 0x02; /* Keypress only */ pin_verify->bEntryValidationCondition = 0x02; /* Keypress only */
if (slot->capabilities & SC_SLOT_CAP_DISPLAY)
pin_verify->bNumberMessage = 0xFF; /* Default message */ pin_verify->bNumberMessage = 0xFF; /* Default message */
else
pin_verify->bNumberMessage = 0x00; /* No messages */
/* Ignore language and T=1 parameters. */ /* Ignore language and T=1 parameters. */
pin_verify->wLangId = HOST_TO_CCID_16(0x0000); pin_verify->wLangId = HOST_TO_CCID_16(0x0000);
@ -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 */ /* 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; int offset = 0, count = 0;
sc_apdu_t *apdu = data->apdu; 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->bmPINLengthFormat = tmp; /* bmPINLengthFormat */
pin_modify->bInsertionOffsetOld = 0x00; /* bOffsetOld */ /* Set offsets if not Case 1 APDU */
if (data->pin1.length_offset != 4) {
/* bInsertionOffsetNew */ pin_modify->bInsertionOffsetOld = data->pin1.offset - 5;
tmp = 0x00; pin_modify->bInsertionOffsetNew = data->pin2.offset - 5;
if (data->pin1.encoding == SC_PIN_ENCODING_GLP) { } else {
tmp = 0x08; pin_modify->bInsertionOffsetOld = 0x00;
pin_modify->bInsertionOffsetNew = 0x00;
} }
pin_modify->bInsertionOffsetNew = tmp; /* 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;
@ -1223,12 +1226,16 @@ static int part10_build_modify_pin_block(u8 * buf, size_t * size, struct sc_pin_
pin_modify->bConfirmPIN = 0x03; /* bConfirmPIN, all */ pin_modify->bConfirmPIN = 0x03; /* bConfirmPIN, all */
pin_modify->bEntryValidationCondition = 0x02; /* bEntryValidationCondition, keypress only */ 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. */ /* 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->wLangId = HOST_TO_CCID_16(0x0000);
pin_modify->bMsgIndex1 = 0x00; pin_modify->bMsgIndex1 = 0x00; /* Default message indexes */
pin_modify->bMsgIndex2 = 0x00; pin_modify->bMsgIndex2 = 0x01;
pin_modify->bMsgIndex3 = 0x00; pin_modify->bMsgIndex3 = 0x02;
pin_modify->bTeoPrologue[0] = 0x00; pin_modify->bTeoPrologue[0] = 0x00;
pin_modify->bTeoPrologue[1] = 0x00; pin_modify->bTeoPrologue[1] = 0x00;
pin_modify->bTeoPrologue[2] = 0x00; pin_modify->bTeoPrologue[2] = 0x00;
@ -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!"); sc_error(reader->ctx, "Pinpad reader does not support verification!");
return SC_ERROR_NOT_SUPPORTED; 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; ioctl = pslot->verify_ioctl ? pslot->verify_ioctl : pslot->verify_ioctl_start;
break; break;
case SC_PIN_CMD_CHANGE: 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!"); sc_error(reader->ctx, "Pinpad reader does not support modification!");
return SC_ERROR_NOT_SUPPORTED; 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; ioctl = pslot->modify_ioctl ? pslot->modify_ioctl : pslot->modify_ioctl_start;
break; break;
default: default:
@ -1345,6 +1352,9 @@ part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
case 0x6402: /* PINs don't match */ case 0x6402: /* PINs don't match */
r = SC_ERROR_KEYPAD_PIN_MISMATCH; r = SC_ERROR_KEYPAD_PIN_MISMATCH;
break; 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"); SC_TEST_RET(reader->ctx, r, "PIN command failed");