From ca911e342c077108783f2b14c541cd197035d2c3 Mon Sep 17 00:00:00 2001 From: Zoltan Kelemen Date: Wed, 1 Jul 2020 08:16:27 +0200 Subject: [PATCH] Improved PIN info retrieval, now returning verification status, and attempts left even when previously not available (due to card not providing it in the SDO). --- src/libopensc/card-iasecc.c | 42 ++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index a67e6780..58c420b6 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -133,6 +133,7 @@ static int iasecc_sdo_get_data(struct sc_card *card, struct iasecc_sdo *sdo); static int iasecc_pin_get_policy (struct sc_card *card, struct sc_pin_cmd_data *data, struct iasecc_pin_policy *pin); static int iasecc_pin_is_verified(struct sc_card *card, struct sc_pin_cmd_data *pin_cmd, int *tries_left); static int iasecc_pin_get_status(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left); +static int iasecc_pin_get_info(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left); static int iasecc_get_free_reference(struct sc_card *card, struct iasecc_ctl_get_free_reference *ctl_data); static int iasecc_sdo_put_data(struct sc_card *card, struct iasecc_sdo_update *update); @@ -2309,6 +2310,45 @@ err: } +static int +iasecc_pin_get_info(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left) +{ + struct sc_context *ctx = card->ctx; + struct iasecc_pin_policy policy; + int rv; + + LOG_FUNC_CALLED(ctx); + sc_log(ctx, "iasecc_pin_get_info(card:%p)", card); + + /* + * Get PIN status first and thereafter update with info from PIN policy, when available. + * The first one is typically used for the PIN verification status and number of remaining + * tries, and the second one for the maximum tries. If a field is present in both, the + * policy takes precedence. + */ + rv = iasecc_pin_get_status(card, data, tries_left); + LOG_TEST_RET(ctx, rv, "Failed to get PIN status"); + + rv = iasecc_pin_get_policy(card, data, &policy); + LOG_TEST_RET(ctx, rv, "Failed to get PIN policy"); + + /* + * We only care about the tries_xxx fields in the PIN policy, since the other ones are not + * commonly expected or used in a SC_PIN_CMD_GET_INFO response. Note that max_tries is + * always taken from the policy, since it is never expected to be available in status (it + * is set to -1 when not available in policy). + */ + data->pin1.max_tries = policy.tries_maximum; + if (policy.tries_remaining >= 0) + data->pin1.tries_left = policy.tries_remaining; + + if (tries_left) + *tries_left = data->pin1.tries_left; + + LOG_FUNC_RETURN(ctx, rv); +} + + static int iasecc_keyset_change(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left) { @@ -2550,7 +2590,7 @@ iasecc_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_le rv = iasecc_pin_reset(card, data, tries_left); break; case SC_PIN_CMD_GET_INFO: - rv = iasecc_pin_get_policy(card, data); + rv = iasecc_pin_get_info(card, data, tries_left); break; default: sc_log(ctx, "Other pin commands not supported yet: 0x%X", data->cmd);