Simplified PIN policy retrieval to only read the data that is actually needed,

excluding the CRT info from the SE-SDO, which is not guaranteed to be
available in all card types.

Use an explicit PIN policy structure type instead of keeping the info in the
sc_pin_cmd_data, since this type of info is only used privately in the card
driver.
This commit is contained in:
Zoltan Kelemen 2020-07-01 08:02:53 +02:00 committed by Frank Morgner
parent 741ee73ec9
commit 19063932f0
1 changed files with 28 additions and 68 deletions

View File

@ -116,11 +116,21 @@ struct iasecc_pin_status {
struct iasecc_pin_status *checked_pins = NULL;
/* Any absent field is set to -1, except scbs, which is always present */
struct iasecc_pin_policy {
int min_length;
int max_length;
int stored_length;
int tries_maximum;
int tries_remaining;
unsigned char scbs[IASECC_MAX_SCBS];
};
static int iasecc_select_file(struct sc_card *card, const struct sc_path *path, struct sc_file **file_out);
static int iasecc_process_fci(struct sc_card *card, struct sc_file *file, const unsigned char *buf, size_t buflen);
static int iasecc_get_serialnr(struct sc_card *card, struct sc_serial_number *serial);
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);
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_get_free_reference(struct sc_card *card, struct iasecc_ctl_get_free_reference *ctl_data);
@ -2198,20 +2208,19 @@ iasecc_chv_set_pinpad(struct sc_card *card, unsigned char reference)
static int
iasecc_pin_get_policy (struct sc_card *card, struct sc_pin_cmd_data *data)
iasecc_pin_get_policy (struct sc_card *card, struct sc_pin_cmd_data *data, struct iasecc_pin_policy *pin)
{
struct sc_context *ctx = card->ctx;
struct sc_file *save_current_df = NULL, *save_current_ef = NULL;
struct iasecc_sdo sdo;
struct sc_path path;
unsigned ii;
int rv;
LOG_FUNC_CALLED(ctx);
sc_log(ctx, "iasecc_pin_get_policy(card:%p)", card);
if (data->pin_type != SC_AC_CHV) {
sc_log(ctx, "To unblock PIN it's CHV reference should be presented");
sc_log(ctx, "PIN policy only available for CHV type");
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
}
@ -2259,74 +2268,25 @@ iasecc_pin_get_policy (struct sc_card *card, struct sc_pin_cmd_data *data)
sc_log(ctx,
"iasecc_pin_get_policy() sdo.docp.size.size %"SC_FORMAT_LEN_SIZE_T"u",
sdo.docp.size.size);
for (ii=0; ii<sizeof(sdo.docp.scbs); ii++) {
struct iasecc_se_info se;
unsigned char scb = sdo.docp.scbs[ii];
struct sc_acl_entry *acl = &data->pin1.acls[ii];
int crt_num = 0;
memset(&se, 0, sizeof(se));
memset(&acl->crts, 0, sizeof(acl->crts));
memcpy(pin->scbs, sdo.docp.scbs, sizeof(pin->scbs));
sc_log(ctx, "iasecc_pin_get_policy() set info acls: SCB 0x%X", scb);
/* acl->raw_value = scb; */
acl->method = scb & IASECC_SCB_METHOD_MASK;
acl->key_ref = scb & IASECC_SCB_METHOD_MASK_REF;
if (scb==0 || scb==0xFF)
continue;
if (se.reference != (int)acl->key_ref) {
memset(&se, 0, sizeof(se));
se.reference = acl->key_ref;
rv = iasecc_se_get_info(card, &se);
LOG_TEST_GOTO_ERR(ctx, rv, "SDO get data error");
}
if (scb & IASECC_SCB_METHOD_USER_AUTH) {
rv = iasecc_se_get_crt_by_usage(card, &se,
IASECC_CRT_TAG_AT, IASECC_UQB_AT_USER_PASSWORD, &acl->crts[crt_num]);
LOG_TEST_GOTO_ERR(ctx, rv, "no authentication template for 'USER PASSWORD'");
sc_log(ctx, "iasecc_pin_get_policy() scb:0x%X; sdo_ref:[%i,%i,...]",
scb, acl->crts[crt_num].refs[0], acl->crts[crt_num].refs[1]);
crt_num++;
}
if (scb & (IASECC_SCB_METHOD_SM | IASECC_SCB_METHOD_EXT_AUTH)) {
sc_log(ctx, "'SM' and 'EXTERNAL AUTHENTICATION' protection methods are not supported: SCB:0x%X", scb);
/* Set to 'NEVER' if all conditions are needed or
* there is no user authentication method allowed */
if (!crt_num || (scb & IASECC_SCB_METHOD_NEED_ALL))
acl->method = SC_AC_NEVER;
continue;
}
sc_file_free(se.df);
pin->min_length = (sdo.data.chv.size_min.value ? *sdo.data.chv.size_min.value : -1);
pin->max_length = (sdo.data.chv.size_max.value ? *sdo.data.chv.size_max.value : -1);
pin->tries_maximum = (sdo.docp.tries_maximum.value ? *sdo.docp.tries_maximum.value : -1);
pin->tries_remaining = (sdo.docp.tries_remaining.value ? *sdo.docp.tries_remaining.value : -1);
if (sdo.docp.size.value && sdo.docp.size.size <= sizeof(int)) {
unsigned int n = 0;
unsigned int i;
for (i=0; i<sdo.docp.size.size; i++)
n = (n << 8) + *(sdo.docp.size.value + i);
pin->stored_length = n;
} else {
pin->stored_length = -1;
}
if (sdo.data.chv.size_max.value)
data->pin1.max_length = *sdo.data.chv.size_max.value;
if (sdo.data.chv.size_min.value)
data->pin1.min_length = *sdo.data.chv.size_min.value;
if (sdo.docp.tries_maximum.value)
data->pin1.max_tries = *sdo.docp.tries_maximum.value;
if (sdo.docp.tries_remaining.value)
data->pin1.tries_left = *sdo.docp.tries_remaining.value;
if (sdo.docp.size.value) {
for (ii=0; ii<sdo.docp.size.size; ii++)
data->pin1.stored_length = ((data->pin1.stored_length) << 8) + *(sdo.docp.size.value + ii);
}
data->pin1.encoding = SC_PIN_ENCODING_ASCII;
data->pin1.offset = 5;
data->pin1.logged_in = SC_PIN_STATE_UNKNOWN;
sc_log(ctx,
"PIN policy: size max/min %"SC_FORMAT_LEN_SIZE_T"u/%"SC_FORMAT_LEN_SIZE_T"u, tries max/left %i/%i",
data->pin1.max_length, data->pin1.min_length,
data->pin1.max_tries, data->pin1.tries_left);
sc_log(ctx, "PIN policy: size max/min %i/%i, tries max/left %i/%i",
pin->max_length, pin->min_length, pin->tries_maximum, pin->tries_remaining);
iasecc_sdo_free_fields(card, &sdo);
if (save_current_df) {