/* * Unblock a PIN. */ int sc_pkcs15_unblock_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pin_obj, const u8 *puk, size_t puklen, const u8 *newpin, size_t newpinlen) { int r; sc_card_t *card; struct sc_pin_cmd_data data; struct sc_pkcs15_object *puk_obj; struct sc_pkcs15_pin_info *puk_info = NULL; struct sc_pkcs15_pin_info *pin_info = (struct sc_pkcs15_pin_info *)pin_obj->data; /* make sure the pins are in valid range */ if ((r = _validate_pin(p15card, pin_info, newpinlen)) != SC_SUCCESS) return r; card = p15card->card; /* get pin_info object of the puk (this is a little bit complicated * as we don't have the id of the puk (at least now)) * note: for compatibility reasons we give no error if no puk object * is found */ /* first step: try to get the pkcs15 object of the puk */ r = sc_pkcs15_find_pin_by_auth_id(p15card, &pin_obj->auth_id, &puk_obj); if (r >= 0 && puk_obj) { /* second step: get the pkcs15 info object of the puk */ puk_info = (struct sc_pkcs15_pin_info *)puk_obj->data; } if (!puk_info) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unable to get puk object, using pin object instead!"); puk_info = pin_info; } /* make sure the puk is in valid range */ if ((r = _validate_pin(p15card, puk_info, puklen)) != SC_SUCCESS) return r; r = sc_lock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed"); /* the path in the pin object is optional */ if (pin_info->path.len > 0) { r = sc_select_file(card, &pin_info->path, NULL); if (r) goto out; } /* set pin_cmd data */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_UNBLOCK; data.pin_type = SC_AC_CHV; data.pin_reference = pin_info->reference; data.pin1.data = puk; data.pin1.len = puklen; data.pin1.pad_char = pin_info->pad_char; data.pin1.min_length = pin_info->min_length; data.pin1.max_length = pin_info->max_length; data.pin1.pad_length = pin_info->stored_length; data.pin2.data = newpin; data.pin2.len = newpinlen; data.pin2.pad_char = puk_info->pad_char; data.pin2.min_length = puk_info->min_length; data.pin2.max_length = puk_info->max_length; data.pin2.pad_length = puk_info->stored_length; if (pin_info->flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) data.flags |= SC_PIN_CMD_NEED_PADDING; switch (pin_info->type) { case SC_PKCS15_PIN_TYPE_BCD: data.pin1.encoding = SC_PIN_ENCODING_BCD; break; case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: data.pin1.encoding = SC_PIN_ENCODING_ASCII; break; } switch (puk_info->type) { case SC_PKCS15_PIN_TYPE_BCD: data.pin2.encoding = SC_PIN_ENCODING_BCD; break; case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: data.pin2.encoding = SC_PIN_ENCODING_ASCII; break; } if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { data.flags |= SC_PIN_CMD_USE_PINPAD; if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) { data.pin1.prompt = "Please enter PUK"; data.pin2.prompt = "Please enter new SO PIN"; } else { data.pin1.prompt = "Please enter PUK"; data.pin2.prompt = "Please enter new PIN"; } } r = sc_pin_cmd(card, &data, &pin_info->tries_left); if (r == SC_SUCCESS) sc_pkcs15_pincache_add(p15card, pin_obj, newpin, newpinlen); out: sc_unlock(card); return r; }
/* * Verify a PIN. * * If the code given to us has zero length, this means we * should ask the card reader to obtain the PIN from the * reader's PIN pad */ int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pin_obj, const unsigned char *pincode, size_t pinlen) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_pin_info *pin_info = (struct sc_pkcs15_pin_info *)pin_obj->data; int r; sc_card_t *card; struct sc_pin_cmd_data data; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PIN(%p;len:%i)", pincode, pinlen); r = _validate_pin(p15card, pin_info, pinlen); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "PIN value do not conforms the PIN policy"); card = p15card->card; r = sc_lock(card); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed"); /* the path in the pin object is optional */ if (pin_info->path.len > 0) { r = sc_select_file(card, &pin_info->path, NULL); if (r) goto out; } /* Initialize arguments */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_VERIFY; data.pin_type = pin_info->auth_method; data.pin_reference = pin_info->reference; data.pin1.min_length = pin_info->min_length; data.pin1.max_length = pin_info->max_length; data.pin1.pad_length = pin_info->stored_length; data.pin1.pad_char = pin_info->pad_char; data.pin1.data = pincode; data.pin1.len = pinlen; if (pin_info->flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) data.flags |= SC_PIN_CMD_NEED_PADDING; switch (pin_info->type) { case SC_PKCS15_PIN_TYPE_BCD: data.pin1.encoding = SC_PIN_ENCODING_BCD; break; case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: data.pin1.encoding = SC_PIN_ENCODING_ASCII; break; default: /* assume/hope the card driver knows how to encode the pin */ data.pin1.encoding = 0; } if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { if (!pincode && !pinlen) data.flags |= SC_PIN_CMD_USE_PINPAD; if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) data.pin1.prompt = "Please enter SO PIN"; else data.pin1.prompt = "Please enter PIN"; } r = sc_pin_cmd(card, &data, &pin_info->tries_left); if (r == SC_SUCCESS) sc_pkcs15_pincache_add(p15card, pin_obj, pincode, pinlen); out: sc_unlock(card); return r; }
/* * Change a PIN. */ int sc_pkcs15_change_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pin_obj, const u8 *oldpin, size_t oldpinlen, const u8 *newpin, size_t newpinlen) { int r; sc_card_t *card; struct sc_pin_cmd_data data; struct sc_pkcs15_pin_info *pin_info = (struct sc_pkcs15_pin_info *)pin_obj->data; /* make sure the pins are in valid range */ if ((r = _validate_pin(p15card, pin_info, oldpinlen)) != SC_SUCCESS) return r; if ((r = _validate_pin(p15card, pin_info, newpinlen)) != SC_SUCCESS) return r; card = p15card->card; r = sc_lock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed"); /* the path in the pin object is optional */ if (pin_info->path.len > 0) { r = sc_select_file(card, &pin_info->path, NULL); if (r) goto out; } /* set pin_cmd data */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_CHANGE; data.pin_type = SC_AC_CHV; data.pin_reference = pin_info->reference; data.pin1.data = oldpin; data.pin1.len = oldpinlen; data.pin1.pad_char = pin_info->pad_char; data.pin1.min_length = pin_info->min_length; data.pin1.max_length = pin_info->max_length; data.pin1.pad_length = pin_info->stored_length; data.pin2.data = newpin; data.pin2.len = newpinlen; data.pin2.pad_char = pin_info->pad_char; data.pin2.min_length = pin_info->min_length; data.pin2.max_length = pin_info->max_length; data.pin2.pad_length = pin_info->stored_length; if (pin_info->flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) data.flags |= SC_PIN_CMD_NEED_PADDING; switch (pin_info->type) { case SC_PKCS15_PIN_TYPE_BCD: data.pin1.encoding = SC_PIN_ENCODING_BCD; data.pin2.encoding = SC_PIN_ENCODING_BCD; break; case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: data.pin1.encoding = SC_PIN_ENCODING_ASCII; data.pin2.encoding = SC_PIN_ENCODING_ASCII; break; } if((!oldpin || !newpin) && p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { data.flags |= SC_PIN_CMD_USE_PINPAD; if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) { data.pin1.prompt = "Please enter SO PIN"; data.pin2.prompt = "Please enter new SO PIN"; } else { data.pin1.prompt = "Please enter PIN"; data.pin2.prompt = "Please enter new PIN"; } } r = sc_pin_cmd(card, &data, &pin_info->tries_left); if (r == SC_SUCCESS) sc_pkcs15_pincache_add(p15card, pin_obj, newpin, newpinlen); out: sc_unlock(card); return r; }
/* * Change a PIN. */ int sc_pkcs15_change_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pin_obj, const u8 *oldpin, size_t oldpinlen, const u8 *newpin, size_t newpinlen) { struct sc_context *ctx = p15card->card->ctx; struct sc_pin_cmd_data data; struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data; struct sc_card *card = p15card->card; int r; LOG_FUNC_CALLED(ctx); if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); /* make sure the pins are in valid range */ r = _validate_pin(p15card, auth_info, oldpinlen); LOG_TEST_RET(ctx, r, "Old PIN value do not conform PIN policy"); r = _validate_pin(p15card, auth_info, newpinlen); LOG_TEST_RET(ctx, r, "New PIN value do not conform PIN policy"); card = p15card->card; r = sc_lock(card); LOG_TEST_RET(ctx, r, "sc_lock() failed"); /* the path in the pin object is optional */ if ((auth_info->path.len > 0) || ((auth_info->path.aid.len > 0))) { r = sc_select_file(card, &auth_info->path, NULL); if (r) goto out; } /* set pin_cmd data */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_CHANGE; data.pin_type = SC_AC_CHV; data.pin_reference = auth_info->attrs.pin.reference; data.pin1.data = oldpin; data.pin1.len = oldpinlen; data.pin1.pad_char = auth_info->attrs.pin.pad_char; data.pin1.min_length = auth_info->attrs.pin.min_length; data.pin1.max_length = auth_info->attrs.pin.max_length; data.pin1.pad_length = auth_info->attrs.pin.stored_length; data.pin2.data = newpin; data.pin2.len = newpinlen; data.pin2.pad_char = auth_info->attrs.pin.pad_char; data.pin2.min_length = auth_info->attrs.pin.min_length; data.pin2.max_length = auth_info->attrs.pin.max_length; data.pin2.pad_length = auth_info->attrs.pin.stored_length; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) data.flags |= SC_PIN_CMD_NEED_PADDING; switch (auth_info->attrs.pin.type) { case SC_PKCS15_PIN_TYPE_BCD: data.pin1.encoding = SC_PIN_ENCODING_BCD; data.pin2.encoding = SC_PIN_ENCODING_BCD; break; case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: data.pin1.encoding = SC_PIN_ENCODING_ASCII; data.pin2.encoding = SC_PIN_ENCODING_ASCII; break; } if((!oldpin || !newpin) && p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { data.flags |= SC_PIN_CMD_USE_PINPAD; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) { data.pin1.prompt = "Please enter SO PIN"; data.pin2.prompt = "Please enter new SO PIN"; } else { data.pin1.prompt = "Please enter PIN"; data.pin2.prompt = "Please enter new PIN"; } } r = sc_pin_cmd(card, &data, &auth_info->tries_left); if (r == SC_SUCCESS) sc_pkcs15_pincache_add(p15card, pin_obj, newpin, newpinlen); out: sc_unlock(card); return r; }