card-gemsafeV1: use iso7816 pin_cmd implementation
GemsafeV1 is compatible with iso7816 pin commands, including SC_PIN_CMD_GET_INFO so it doesn't need to customize it. Acked-by: João Poupino <joao.poupino@gmail.com> Tested-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Nuno Goncalves <nunojpg@gmail.com>
This commit is contained in:
parent
68cbc288de
commit
b2f6abded3
|
@ -229,6 +229,7 @@ static int gemsafe_init(struct sc_card *card)
|
|||
}
|
||||
}
|
||||
|
||||
card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO;
|
||||
card->drv_data = exdata;
|
||||
|
||||
return 0;
|
||||
|
@ -563,146 +564,6 @@ static int gemsafe_get_challenge(sc_card_t *card, u8 *rnd, size_t len)
|
|||
return r;
|
||||
}
|
||||
|
||||
static int gemsafe_build_pin_apdu(struct sc_card *card,
|
||||
struct sc_apdu *apdu,
|
||||
struct sc_pin_cmd_data *data)
|
||||
{
|
||||
static u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
int r, len = 0, pad = 0, use_pin_pad = 0, ins, p1 = 0;
|
||||
|
||||
switch (data->pin_type) {
|
||||
case SC_AC_CHV:
|
||||
break;
|
||||
default:
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
if (data->flags & SC_PIN_CMD_NEED_PADDING)
|
||||
pad = 1;
|
||||
if (data->flags & SC_PIN_CMD_USE_PINPAD)
|
||||
use_pin_pad = 1;
|
||||
|
||||
data->pin1.offset = 5;
|
||||
|
||||
switch (data->cmd) {
|
||||
case SC_PIN_CMD_VERIFY:
|
||||
ins = 0x20;
|
||||
if ((r = sc_build_pin(sbuf, sizeof(sbuf), &data->pin1, pad)) < 0)
|
||||
return r;
|
||||
len = r;
|
||||
break;
|
||||
case SC_PIN_CMD_CHANGE:
|
||||
ins = 0x24;
|
||||
if (data->pin1.len != 0 || use_pin_pad) {
|
||||
if ((r = sc_build_pin(sbuf, sizeof(sbuf), &data->pin1, pad)) < 0)
|
||||
return r;
|
||||
len += r;
|
||||
} else {
|
||||
/* implicit test */
|
||||
p1 = 1;
|
||||
}
|
||||
|
||||
data->pin2.offset = data->pin1.offset + len;
|
||||
if ((r = sc_build_pin(sbuf+len, sizeof(sbuf)-len, &data->pin2, pad)) < 0)
|
||||
return r;
|
||||
len += r;
|
||||
break;
|
||||
case SC_PIN_CMD_UNBLOCK:
|
||||
ins = 0x2C;
|
||||
if (data->pin1.len != 0 || use_pin_pad) {
|
||||
if ((r = sc_build_pin(sbuf, sizeof(sbuf), &data->pin1, pad)) < 0)
|
||||
return r;
|
||||
len += r;
|
||||
} else {
|
||||
p1 |= 0x02;
|
||||
}
|
||||
|
||||
if (data->pin2.len != 0 || use_pin_pad) {
|
||||
data->pin2.offset = data->pin1.offset + len;
|
||||
if ((r = sc_build_pin(sbuf+len, sizeof(sbuf)-len, &data->pin2, pad)) < 0)
|
||||
return r;
|
||||
len += r;
|
||||
} else {
|
||||
p1 |= 0x01;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT,
|
||||
ins, p1, data->pin_reference);
|
||||
|
||||
apdu->lc = len;
|
||||
apdu->datalen = len;
|
||||
apdu->data = sbuf;
|
||||
apdu->resplen = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gemsafe_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data,
|
||||
int *tries_left)
|
||||
{
|
||||
struct sc_apdu local_apdu, *apdu;
|
||||
int r;
|
||||
|
||||
if (tries_left)
|
||||
*tries_left = -1;
|
||||
|
||||
/* See if we've been called from another card driver, which is
|
||||
* passing an APDU to us (this allows to write card drivers
|
||||
* whose PIN functions behave "mostly like ISO" except in some
|
||||
* special circumstances.
|
||||
*/
|
||||
if (data->apdu == NULL) {
|
||||
r = gemsafe_build_pin_apdu(card, &local_apdu, data);
|
||||
if (r < 0)
|
||||
return r;
|
||||
data->apdu = &local_apdu;
|
||||
}
|
||||
apdu = data->apdu;
|
||||
|
||||
if (!(data->flags & SC_PIN_CMD_USE_PINPAD)) {
|
||||
/* Transmit the APDU to the card */
|
||||
r = sc_transmit_apdu(card, apdu);
|
||||
|
||||
/* Clear the buffer - it may contain pins */
|
||||
memset((void *) apdu->data, 0, apdu->datalen);
|
||||
} else {
|
||||
/* Call the reader driver to collect
|
||||
* the PIN and pass on the APDU to the card */
|
||||
if (data->pin1.offset == 0) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Card driver didn't set PIN offset");
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
if (card->reader
|
||||
&& card->reader->ops
|
||||
&& card->reader->ops->perform_verify) {
|
||||
r = card->reader->ops->perform_verify(card->reader, data);
|
||||
/* sw1/sw2 filled in by reader driver */
|
||||
} else {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Card reader driver does not support "
|
||||
"PIN entry through reader key pad");
|
||||
r = SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't pass references to local variables up to the caller. */
|
||||
if (data->apdu == &local_apdu)
|
||||
data->apdu = NULL;
|
||||
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
|
||||
if (apdu->sw1 == 0x63) {
|
||||
if ((apdu->sw2 & 0xF0) == 0xC0 && tries_left != NULL)
|
||||
*tries_left = apdu->sw2 & 0x0F;
|
||||
return SC_ERROR_PIN_CODE_INCORRECT;
|
||||
}
|
||||
return sc_check_sw(card, apdu->sw1, apdu->sw2);
|
||||
}
|
||||
|
||||
static struct sc_card_driver *sc_get_driver(void)
|
||||
{
|
||||
struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
|
||||
|
@ -721,7 +582,7 @@ static struct sc_card_driver *sc_get_driver(void)
|
|||
gemsafe_ops.compute_signature = gemsafe_compute_signature;
|
||||
gemsafe_ops.get_challenge = gemsafe_get_challenge;
|
||||
gemsafe_ops.process_fci = gemsafe_process_fci;
|
||||
gemsafe_ops.pin_cmd = gemsafe_pin_cmd;
|
||||
gemsafe_ops.pin_cmd = iso_ops->pin_cmd;
|
||||
|
||||
return &gemsafe_drv;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue