- added pinpad support for OpenCT
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1215 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
3c50c4d4e0
commit
127f94ad37
|
@ -932,6 +932,15 @@ static int flex_build_verify_apdu(struct sc_card *card, struct sc_apdu *apdu,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void flex_init_pin_info(struct sc_pin_cmd_pin *pin, unsigned int num)
|
||||
{
|
||||
pin->encoding = SC_PIN_ENCODING_ASCII;
|
||||
pin->max_length = 8;
|
||||
pin->pad_length = 8;
|
||||
pin->pad_char = 0;
|
||||
pin->offset = 5 + num * 8;
|
||||
}
|
||||
|
||||
static int flex_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data,
|
||||
int *tries_left)
|
||||
{
|
||||
|
@ -940,10 +949,9 @@ static int flex_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data,
|
|||
int old_cla = -1;
|
||||
|
||||
/* Fix pin data */
|
||||
data->pin1.encoding = SC_PIN_ENCODING_ASCII;
|
||||
data->pin1.max_length = 8;
|
||||
data->pin2.encoding = SC_PIN_ENCODING_ASCII;
|
||||
data->pin2.max_length = 8;
|
||||
data->flags |= SC_PIN_CMD_NEED_PADDING;
|
||||
flex_init_pin_info(&data->pin1, 0);
|
||||
flex_init_pin_info(&data->pin2, 1);
|
||||
|
||||
if (data->cmd == SC_PIN_CMD_VERIFY) {
|
||||
r = flex_build_verify_apdu(card, &apdu, data);
|
||||
|
|
|
@ -1704,9 +1704,18 @@ gpk_build_pin_apdu(sc_card_t *card, sc_apdu_t *apdu, struct sc_pin_cmd_data *dat
|
|||
memset(apdu, 0, sizeof(*apdu));
|
||||
apdu->cse = SC_APDU_CASE_3_SHORT;
|
||||
|
||||
data->flags |= SC_PIN_CMD_NEED_PADDING;
|
||||
data->pin1.encoding = SC_PIN_ENCODING_BCD;
|
||||
data->pin1.pad_length = 8;
|
||||
data->pin1.pad_char = 0x00;
|
||||
data->pin2.encoding = SC_PIN_ENCODING_BCD;
|
||||
data->pin2.pad_length = 8;
|
||||
data->pin2.pad_char = 0x00;
|
||||
|
||||
switch (data->cmd) {
|
||||
case SC_PIN_CMD_VERIFY:
|
||||
/* Copy PIN to buffer and pad */
|
||||
data->pin1.offset = 5;
|
||||
r = sc_build_pin(sbuf, 8, &data->pin1, 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1718,11 +1727,7 @@ gpk_build_pin_apdu(sc_card_t *card, sc_apdu_t *apdu, struct sc_pin_cmd_data *dat
|
|||
case SC_PIN_CMD_CHANGE:
|
||||
case SC_PIN_CMD_UNBLOCK:
|
||||
/* Copy PINs to buffer, BCD-encoded, and pad */
|
||||
data->pin1.encoding = SC_PIN_ENCODING_BCD;
|
||||
data->pin1.max_length = 8;
|
||||
data->pin2.encoding = SC_PIN_ENCODING_BCD;
|
||||
data->pin2.max_length = 8;
|
||||
data->pin2.offset = 4;
|
||||
data->pin2.offset = 5 + 4;
|
||||
if ((r = sc_build_pin(sbuf, 4, &data->pin1, 1)) < 0
|
||||
|| (r = sc_build_pin(sbuf + 4, 4, &data->pin2, 1)) < 0)
|
||||
return r;
|
||||
|
|
|
@ -848,14 +848,18 @@ static int iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data,
|
|||
} else {
|
||||
/* Call the reader driver to collect
|
||||
* the PIN and pass on the APDU to the card */
|
||||
if (data->pin1.offset == 0) {
|
||||
error(card->ctx,
|
||||
"Card driver didn't set PIN offset");
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
if (card->reader
|
||||
&& card->reader->ops
|
||||
&& card->reader->ops->enter_pin) {
|
||||
r = card->reader->ops->enter_pin(card->reader,
|
||||
&& card->reader->ops->perform_verify) {
|
||||
r = card->reader->ops->perform_verify(card->reader,
|
||||
card->slot,
|
||||
data);
|
||||
apdu->sw1 = 0x90;
|
||||
apdu->sw2 = 0x00;
|
||||
/* sw1/sw2 filled in by reader driver */
|
||||
} else {
|
||||
error(card->ctx,
|
||||
"Card reader driver does not support "
|
||||
|
|
|
@ -380,7 +380,7 @@ struct sc_reader_operations {
|
|||
/* Pin pad functions */
|
||||
int (*display_message)(struct sc_reader *, struct sc_slot_info *,
|
||||
const char *);
|
||||
int (*enter_pin)(struct sc_reader *, struct sc_slot_info *,
|
||||
int (*perform_verify)(struct sc_reader *, struct sc_slot_info *,
|
||||
struct sc_pin_cmd_data *);
|
||||
|
||||
/* Wait for an event */
|
||||
|
|
|
@ -374,7 +374,7 @@ const struct sc_reader_driver * sc_get_ctapi_driver()
|
|||
ctapi_ops.release = ctapi_release;
|
||||
ctapi_ops.connect = ctapi_connect;
|
||||
ctapi_ops.disconnect = ctapi_disconnect;
|
||||
ctapi_ops.enter_pin = ctbcs_pin_cmd;
|
||||
ctapi_ops.perform_verify = ctbcs_pin_cmd;
|
||||
|
||||
return &ctapi_drv;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,9 @@ static int openct_reader_transmit(struct sc_reader *reader,
|
|||
struct sc_slot_info *slot,
|
||||
const u8 *sendbuf, size_t sendsize,
|
||||
u8 *recvbuf, size_t *recvsize, int control);
|
||||
static int openct_reader_perform_verify(struct sc_reader *reader,
|
||||
struct sc_slot_info *slot,
|
||||
struct sc_pin_cmd_data *info);
|
||||
static int openct_reader_lock(struct sc_reader *reader,
|
||||
struct sc_slot_info *slot);
|
||||
static int openct_reader_unlock(struct sc_reader *reader,
|
||||
|
@ -62,6 +65,7 @@ static struct sc_reader_operations openct_reader_operations = {
|
|||
.connect = openct_reader_connect,
|
||||
.disconnect = openct_reader_disconnect,
|
||||
.transmit = openct_reader_transmit,
|
||||
.perform_verify = openct_reader_perform_verify,
|
||||
.lock = openct_reader_lock,
|
||||
.unlock = openct_reader_unlock,
|
||||
};
|
||||
|
@ -153,6 +157,10 @@ openct_add_reader(struct sc_context *ctx, unsigned int num, ct_info_t *info)
|
|||
for (i = 0; i < SC_MAX_SLOTS; i++) {
|
||||
reader->slot[i].drv_data = calloc(1, sizeof(struct slot_data));
|
||||
reader->slot[i].id = i;
|
||||
if (data->info.ct_display)
|
||||
reader->slot[i].capabilities |= SC_SLOT_CAP_DISPLAY;
|
||||
if (data->info.ct_keypad)
|
||||
reader->slot[i].capabilities |= SC_SLOT_CAP_PIN_PAD;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -310,13 +318,76 @@ openct_reader_transmit(struct sc_reader *reader,
|
|||
return openct_error(reader, rc);
|
||||
}
|
||||
|
||||
int
|
||||
openct_reader_perform_verify(struct sc_reader *reader,
|
||||
struct sc_slot_info *slot,
|
||||
struct sc_pin_cmd_data *info)
|
||||
{
|
||||
struct driver_data *data = (struct driver_data *) reader->drv_data;
|
||||
unsigned int pin_length = 0, pin_encoding;
|
||||
size_t j = 0;
|
||||
u8 buf[254];
|
||||
int rc;
|
||||
|
||||
/* Hotplug check */
|
||||
if ((rc = openct_reader_reconnect(reader, slot)) < 0)
|
||||
return rc;
|
||||
|
||||
if (info->apdu == NULL) {
|
||||
// complain
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
buf[j++] = info->apdu->cla;
|
||||
buf[j++] = info->apdu->ins;
|
||||
buf[j++] = info->apdu->p1;
|
||||
buf[j++] = info->apdu->p2;
|
||||
|
||||
if (info->apdu->lc) {
|
||||
size_t len = info->apdu->lc;
|
||||
|
||||
if (j + 1 + len > sizeof(buf))
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
buf[j++] = len;
|
||||
memcpy(buf+j, info->apdu->data, len);
|
||||
j += len;
|
||||
}
|
||||
|
||||
if (info->pin1.min_length == info->pin1.max_length)
|
||||
pin_length = info->pin1.min_length;
|
||||
|
||||
if (info->pin1.encoding == SC_PIN_ENCODING_ASCII)
|
||||
pin_encoding = IFD_PIN_ENCODING_ASCII;
|
||||
else if (info->pin1.encoding == SC_PIN_ENCODING_BCD)
|
||||
pin_encoding = IFD_PIN_ENCODING_BCD;
|
||||
else
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
rc = ct_card_verify(data->h, slot->id,
|
||||
0, /* no timeout?! */
|
||||
info->pin1.prompt,
|
||||
pin_encoding,
|
||||
pin_length,
|
||||
info->pin1.offset,
|
||||
buf, j,
|
||||
buf, sizeof(buf));
|
||||
if (rc < 0)
|
||||
return openct_error(reader, rc);
|
||||
if (rc != 2)
|
||||
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
||||
info->apdu->sw1 = buf[0];
|
||||
info->apdu->sw2 = buf[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
openct_reader_lock(struct sc_reader *reader,
|
||||
struct sc_slot_info *slot)
|
||||
{
|
||||
struct driver_data *data = (struct driver_data *) reader->drv_data;
|
||||
struct slot_data *slot_data = (struct slot_data *) slot->drv_data;
|
||||
int rc, retry = 1;
|
||||
int rc;
|
||||
|
||||
SC_FUNC_CALLED(reader->ctx, 1);
|
||||
|
||||
|
@ -366,5 +437,11 @@ openct_error(struct sc_reader *reader, int code)
|
|||
return code;
|
||||
|
||||
/* Fixme: translate error code */
|
||||
switch (code) {
|
||||
case IFD_ERROR_USER_TIMEOUT:
|
||||
return SC_ERROR_KEYPAD_TIMEOUT;
|
||||
case IFD_ERROR_USER_ABORT:
|
||||
return SC_ERROR_KEYPAD_CANCELLED;
|
||||
}
|
||||
return SC_ERROR_READER;
|
||||
}
|
||||
|
|
|
@ -601,7 +601,7 @@ const struct sc_reader_driver * sc_get_pcsc_driver()
|
|||
pcsc_ops.release = pcsc_release;
|
||||
pcsc_ops.connect = pcsc_connect;
|
||||
pcsc_ops.disconnect = pcsc_disconnect;
|
||||
pcsc_ops.enter_pin = ctbcs_pin_cmd;
|
||||
pcsc_ops.perform_verify = ctbcs_pin_cmd;
|
||||
pcsc_ops.wait_for_event = pcsc_wait_for_event;
|
||||
|
||||
return &pcsc_drv;
|
||||
|
|
Loading…
Reference in New Issue