Functions used to control PIN padding and PIN pad use:

- Use PIN padding information when provided by upper layers
- Enable PIN padding at card level when min/max len set to same, nonzero value
- Allow PIN-pad use to be dynamically selected for each PIN
This commit is contained in:
Zoltan Kelemen 2020-07-01 08:38:54 +02:00 committed by Frank Morgner
parent ca911e342c
commit 8c2d629f94
1 changed files with 82 additions and 0 deletions

View File

@ -134,6 +134,11 @@ static int iasecc_pin_get_policy (struct sc_card *card, struct sc_pin_cmd_data *
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_check_update_pin(struct sc_pin_cmd_data *data, struct sc_pin_cmd_pin *pin);
static void iasecc_set_pin_padding(struct sc_pin_cmd_data *data, struct sc_pin_cmd_pin *pin,
size_t pad_len);
static int iasecc_pin_merge_policy(struct sc_card *card, struct sc_pin_cmd_data *data,
struct sc_pin_cmd_pin *pin, struct iasecc_pin_policy *policy);
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);
@ -2349,6 +2354,83 @@ iasecc_pin_get_info(struct sc_card *card, struct sc_pin_cmd_data *data, int *tri
}
/*
* Check PIN and update flags. We reject empty PINs (where data is non-NULL but length is 0) due
* to their non-obvious meaning in verification/change/unblock. We also need to update the
* SC_PIN_CMD_USE_PINPAD flag depending on the PIN being available or not (where data is NULL means
* that PIN is not available). Unfortunately we can not rely on the flag provided by the caller due
* to its ambiguous use. The approach here is to assume pin-pad input when the PIN data is NULL,
* otherwise not.
*/
static int iasecc_check_update_pin(struct sc_pin_cmd_data *data, struct sc_pin_cmd_pin *pin)
{
if ((!pin->data && pin->len) || (pin->data && !pin->len))
return SC_ERROR_INVALID_ARGUMENTS;
if (pin->data)
data->flags &= ~SC_PIN_CMD_USE_PINPAD;
else
data->flags |= SC_PIN_CMD_USE_PINPAD;
return SC_SUCCESS;
}
/* Enable PIN padding with 0xff as the padding character, unless already enabled */
static void iasecc_set_pin_padding(struct sc_pin_cmd_data *data, struct sc_pin_cmd_pin *pin,
size_t pad_len)
{
if (data->flags & SC_PIN_CMD_NEED_PADDING)
return;
pin->pad_length = pad_len;
pin->pad_char = 0xff;
data->flags |= SC_PIN_CMD_NEED_PADDING;
}
/*
* Retrieve the PIN policy and combine it with the existing fields in an intelligent way. This is
* needed since we may be called with existing settings, typically from the PKCS #15 layer. We use
* the IAS-ECC card-level PIN settings as complementary.
*/
static int
iasecc_pin_merge_policy(struct sc_card *card, struct sc_pin_cmd_data *data,
struct sc_pin_cmd_pin *pin, struct iasecc_pin_policy *policy)
{
struct sc_context *ctx = card->ctx;
size_t pad_len = 0;
int rv;
LOG_FUNC_CALLED(ctx);
sc_log(ctx, "iasecc_pin_merge_policy(card:%p)", card);
rv = iasecc_check_update_pin(data, pin);
LOG_TEST_RET(ctx, rv, "Invalid PIN");
rv = iasecc_pin_get_policy(card, data, policy);
LOG_TEST_RET(ctx, rv, "Failed to get PIN policy");
/* Some cards obviously use the min/max length fields to signal PIN padding */
if (policy->min_length > 0 && policy->min_length == policy->max_length) {
pad_len = policy->min_length;
policy->min_length = 0;
}
/* Take the most limited values of min/max lengths */
if (policy->min_length > 0 && (size_t) policy->min_length > pin->min_length)
pin->min_length = policy->min_length;
if (policy->max_length > 0 && (!pin->max_length || (size_t) policy->max_length < pin->max_length))
pin->max_length = policy->max_length;
/* Set PIN padding if needed and not already set by the caller */
if (pad_len)
iasecc_set_pin_padding(data, pin, pad_len);
LOG_FUNC_RETURN(ctx, rv);
}
static int
iasecc_keyset_change(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left)
{