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:
Nuno Goncalves 2016-06-21 12:49:06 +01:00 committed by Viktor Tarasov
parent 68cbc288de
commit b2f6abded3
1 changed files with 2 additions and 141 deletions

View File

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