- 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:
okir 2003-06-23 12:56:36 +00:00
parent 3c50c4d4e0
commit 127f94ad37
7 changed files with 111 additions and 17 deletions

View File

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

View File

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

View File

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

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

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