Unlock User PIN with PKCS#11:

One of the three unblock methods can be activated from the 'opensc-pkcs11' section of opensc.conf:
- C_SetPin() in the unlogged sesssion;
- C_SetPin() in the CKU_SPECIFIC_CONTEXT session;
- C_InitPin() in CKU_SO session (inspired by Pierre Ossman).
-- This last one works, for a while, only for the pkcs15 cards without SOPIN auth object.
   For the pkcs15 cards with SOPIN, this method will be useful for the cards 
   that do not have then modes '00' and '01' of ISO command 'RESET RETRY COUNTER'.

Test commands:
# pkcs11-tool --module ./opensc-pkcs11.so --slot 0 --unlock-pin --puk "123456" --new-pin "9999"
# pkcs11-tool --module ./opensc-pkcs11.so --slot 0 --unlock-pin -l --login-type context-specific --puk "123456" --new-pin "9999"
# pkcs11-tool --module ./opensc-pkcs11.so --slot 0 --init-pin -l --new-pin "9999"



git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3901 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
viktor.tarasov 2010-01-08 15:41:07 +00:00
parent 39ca6b156f
commit e2dae6b97b
6 changed files with 284 additions and 59 deletions

View File

@ -379,6 +379,21 @@ app opensc-pkcs11 {
#
# Default: false
# soft_keygen_allowed = true;
# User PIN unblock style
# none: PIN unblock is not possible with PKCS#11 API;
# set_pin_in_unlogged_session: C_SetPIN() in unlogged session:
# PUK is passed as the 'OldPin' argument of the C_SetPIN() call.
# set_pin_in_specific_context: C_SetPIN() in the CKU_SPECIFIC_CONTEXT logged session:
# PUK is passed as the 'OldPin' argument of the C_SetPIN() call.
# init_pin_in_so_session: C_InitPIN() in CKU_SO logged session:
# User PIN 'UNBLOCK' is protected by SOPIN. (PUK == SOPIN).
# # Actually this style works only for the PKCS15 contents without SOPIN.
# # For those with SOPIN, this mode will be usefull for the cards without
# # modes 00 and 01 of ISO command 'RESET RETRY COUNTER'. --vt
#
# Default: none
# user_pin_unblock_style = set_pin_in_unlogged_session;
}
}

View File

@ -53,6 +53,8 @@ struct pkcs15_fw_data {
struct pkcs15_any_object * objects[MAX_OBJECTS];
unsigned int num_objects;
unsigned int locked;
unsigned char user_puk[64];
unsigned int user_puk_len;
};
struct pkcs15_any_object {
@ -965,12 +967,43 @@ static CK_RV pkcs15_login(struct sc_pkcs11_card *p11card,
/* If there's no SO PIN on the card, silently
* accept any PIN, and lock the card if required */
if (rc == SC_ERROR_OBJECT_NOT_FOUND
&& sc_pkcs11_conf.lock_login)
rc = lock_card(fw_data);
if (rc < 0)
if (rc == SC_ERROR_OBJECT_NOT_FOUND) {
rc = 0;
if (sc_pkcs11_conf.lock_login)
rc = lock_card(fw_data);
if (sc_pkcs11_conf.pin_unblock_style == SC_PKCS11_PIN_UNBLOCK_SO_LOGGED_INITPIN) {
if (ulPinLen && ulPinLen < sizeof(fw_data->user_puk)) {
memcpy(fw_data->user_puk, pPin, ulPinLen);
fw_data->user_puk_len = ulPinLen;
}
}
sc_debug(context, "No SOPIN found; returns %d\n", rc);
return sc_to_cryptoki_error(rc, p11card->reader);
}
else if (rc < 0) {
return sc_to_cryptoki_error(rc, p11card->reader);
}
break;
case CKU_CONTEXT_SPECIFIC:
/* For a while, used only to unblock User PIN. */
rc = 0;
if (sc_pkcs11_conf.lock_login)
rc = lock_card(fw_data);
#if 0
/* TODO: Look for pkcs15 auth object with 'unblockingPin' flag activated.
* If exists, do verification of PIN (in fact PUK). */
if (sc_pkcs11_conf.pin_unblock_style == SC_PKCS11_PIN_UNBLOCK_SCONTEXT_SETPIN) {
if (ulPinLen && ulPinLen < sizeof(fw_data->user_puk)) {
memcpy(fw_data->user_puk, pPin, ulPinLen);
fw_data->user_puk_len = ulPinLen;
}
}
#endif
sc_debug(context, "context specific login returns %d\n", rc);
return sc_to_cryptoki_error(rc, p11card->reader);
default:
return CKR_USER_TYPE_INVALID;
}
@ -1008,7 +1041,7 @@ static CK_RV pkcs15_login(struct sc_pkcs11_card *p11card,
return sc_to_cryptoki_error(rc, p11card->reader);
rc = sc_pkcs15_verify_pin(card, pin, pPin, ulPinLen);
sc_debug(context, "PIN verification returned %d\n", rc);
sc_debug(context, "PKCS15 verify PIN returned %d\n", rc);
return sc_to_cryptoki_error(rc, p11card->reader);
}
@ -1016,7 +1049,10 @@ static CK_RV pkcs15_logout(struct sc_pkcs11_card *p11card, void *fw_token)
{
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
int rc = 0;
memset(fw_data->user_puk, 0, sizeof(fw_data->user_puk));
fw_data->user_puk_len = 0;
sc_pkcs15_pincache_clear(fw_data->p15_card);
sc_logout(fw_data->p15_card->card);
@ -1026,7 +1062,7 @@ static CK_RV pkcs15_logout(struct sc_pkcs11_card *p11card, void *fw_token)
}
static CK_RV pkcs15_change_pin(struct sc_pkcs11_card *p11card,
void *fw_token,
void *fw_token, int login_user,
CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen,
CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen)
{
@ -1046,14 +1082,34 @@ static CK_RV pkcs15_change_pin(struct sc_pkcs11_card *p11card,
*/
pOldPin = pNewPin = NULL;
ulOldLen = ulNewLen = 0;
} else
if (ulNewLen < pin->min_length ||
ulNewLen > pin->max_length)
}
else if (ulNewLen < pin->min_length || ulNewLen > pin->max_length) {
return CKR_PIN_LEN_RANGE;
}
rc = sc_pkcs15_change_pin(fw_data->p15_card, pin, pOldPin, ulOldLen,
pNewPin, ulNewLen);
sc_debug(context, "PIN change returned %d\n", rc);
if (login_user < 0) {
if (sc_pkcs11_conf.pin_unblock_style != SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN) {
sc_debug(context, "PIN unlock is not allowed in unlogged session");
return CKR_FUNCTION_NOT_SUPPORTED;
}
rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin, pOldPin, ulOldLen, pNewPin, ulNewLen);
}
else if (login_user == CKU_CONTEXT_SPECIFIC) {
if (sc_pkcs11_conf.pin_unblock_style != SC_PKCS11_PIN_UNBLOCK_SCONTEXT_SETPIN) {
sc_debug(context, "PIN unlock is not allowed with CKU_CONTEXT_SPECIFIC login");
return CKR_FUNCTION_NOT_SUPPORTED;
}
rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin, pOldPin, ulOldLen, pNewPin, ulNewLen);
}
else if (login_user == CKU_USER) {
rc = sc_pkcs15_change_pin(fw_data->p15_card, pin, pOldPin, ulOldLen, pNewPin, ulNewLen);
}
else {
sc_debug(context, "cannot change PIN: non supported login type: %i", login_user);
return CKR_FUNCTION_NOT_SUPPORTED;
}
sc_debug(context, "PIN change returns %d\n", rc);
return sc_to_cryptoki_error(rc, p11card->reader);
}
@ -1066,9 +1122,30 @@ static CK_RV pkcs15_init_pin(struct sc_pkcs11_card *p11card,
struct sc_pkcs15init_pinargs args;
struct sc_profile *profile;
struct sc_pkcs15_object *auth_obj;
sc_pkcs15_pin_info_t *pin_info;
struct sc_pkcs15_pin_info *pin_info;
int rc;
sc_debug(context, "pkcs15 init PIN: pin %p:%d\n", pPin, ulPinLen);
pin_info = slot_data_pin_info(slot->fw_data);
if (pin_info && sc_pkcs11_conf.pin_unblock_style == SC_PKCS11_PIN_UNBLOCK_SO_LOGGED_INITPIN) {
if (fw_data->user_puk_len) {
rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin_info,
fw_data->user_puk, fw_data->user_puk_len, pPin, ulPinLen);
}
else {
#if 0
/* TODO: Actually sc_pkcs15_unblock_pin() do not accepts zero length value as a PUK argument.
* It's usefull for the cards that do not supports modes 00 and 01
* of ISO 'RESET RETRY COUNTER' command. */
rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin_info, NULL, 0, pPin, ulPinLen);
#else
return sc_to_cryptoki_error(SC_ERROR_NOT_SUPPORTED, p11card->reader);
#endif
}
return sc_to_cryptoki_error(rc, p11card->reader);
}
rc = sc_lock(p11card->card);
if (rc < 0)
return sc_to_cryptoki_error(rc, p11card->reader);
@ -1704,6 +1781,9 @@ static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card,
/* 3.a Try on-card key pair generation */
sc_pkcs15init_set_p15card(profile, fw_data->p15_card);
sc_debug(context, "Try on-card key pair generation");
rc = sc_pkcs15init_generate_key(fw_data->p15_card, profile,
&keygen_args, keybits, &priv_key_obj);
if (rc >= 0) {

View File

@ -316,6 +316,7 @@ CK_RV attr_find_var(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t *ctx)
{
scconf_block *conf_block = NULL;
char *unblock_style = NULL;
/* Set defaults */
conf->plug_and_play = 1;
@ -324,7 +325,7 @@ void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t *ctx)
conf->hide_empty_tokens = 1;
conf->lock_login = 0;
conf->soft_keygen_allowed = 0;
conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_NOT_ALLOWED;
conf_block = sc_get_conf_block(ctx, "pkcs11", NULL, 1);
if (!conf_block)
@ -339,6 +340,17 @@ void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t *ctx)
conf->hide_empty_tokens = scconf_get_bool(conf_block, "hide_empty_tokens", conf->hide_empty_tokens);
conf->lock_login = scconf_get_bool(conf_block, "lock_login", conf->lock_login);
conf->soft_keygen_allowed = scconf_get_bool(conf_block, "soft_keygen_allowed", conf->soft_keygen_allowed);
sc_debug(ctx, "PKCS#11 options: plug_and_play=%d max_virtual_slots=%d slots_per_card=%d hide_empty_tokens=%d lock_login=%d",
conf->plug_and_play, conf->max_virtual_slots, conf->slots_per_card, conf->hide_empty_tokens, conf->lock_login);
unblock_style = (char *) scconf_get_str(conf_block, "user_pin_unblock_style", NULL);
if (unblock_style && !strcmp(unblock_style, "set_pin_in_unlogged_session"))
conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN;
else if (unblock_style && !strcmp(unblock_style, "set_pin_in_specific_context"))
conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_SCONTEXT_SETPIN;
else if (unblock_style && !strcmp(unblock_style, "init_pin_in_so_session"))
conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_SO_LOGGED_INITPIN;
sc_debug(ctx, "PKCS#11 options: plug_and_play=%d max_virtual_slots=%d slots_per_card=%d "
"hide_empty_tokens=%d lock_login=%d pin_unblock_style=%d",
conf->plug_and_play, conf->max_virtual_slots, conf->slots_per_card,
conf->hide_empty_tokens, conf->lock_login, conf->pin_unblock_style);
}

View File

@ -232,7 +232,7 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */
goto out;
}
if (userType != CKU_USER && userType != CKU_SO) {
if (userType != CKU_USER && userType != CKU_SO && userType != CKU_CONTEXT_SPECIFIC) {
rv = CKR_USER_TYPE_INVALID;
goto out;
}
@ -241,7 +241,7 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */
if (rv != CKR_OK)
goto out;
sc_debug(context, "Login for session %d\n", hSession);
sc_debug(context, "Login for session %d; userType %d\n", hSession, userType);
slot = session->slot;
@ -361,17 +361,16 @@ CK_RV C_SetPIN(CK_SESSION_HANDLE hSession,
if (rv != CKR_OK)
goto out;
sc_debug(context, "Changing PIN (session %d)\n", hSession);
slot = session->slot;
sc_debug(context, "Changing PIN (session %d; login user %d)\n", hSession, slot->login_user);
if (!(session->flags & CKF_RW_SESSION)) {
rv = CKR_SESSION_READ_ONLY;
goto out;
}
slot = session->slot;
rv = slot->card->framework->change_pin(slot->card, slot->fw_data,
pOldPin, ulOldLen,
pNewPin, ulNewLen);
slot->login_user, pOldPin, ulOldLen, pNewPin, ulNewLen);
out: sc_pkcs11_unlock();
return rv;

View File

@ -45,6 +45,11 @@ extern "C" {
#define PKCS11_DEFAULT_MODULE_NAME "opensc-pkcs11.so"
#endif
#define SC_PKCS11_PIN_UNBLOCK_NOT_ALLOWED 0
#define SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN 1
#define SC_PKCS11_PIN_UNBLOCK_SCONTEXT_SETPIN 2
#define SC_PKCS11_PIN_UNBLOCK_SO_LOGGED_INITPIN 3
extern void *C_LoadModule(const char *name, CK_FUNCTION_LIST_PTR_PTR);
extern CK_RV C_UnloadModule(void *module);
@ -93,6 +98,7 @@ struct sc_pkcs11_config {
unsigned char hide_empty_tokens;
unsigned char lock_login;
unsigned char soft_keygen_allowed;
unsigned int pin_unblock_style;
};
/*
@ -158,7 +164,7 @@ struct sc_pkcs11_framework_ops {
CK_RV (*login)(struct sc_pkcs11_card *, void *,
CK_USER_TYPE, CK_CHAR_PTR, CK_ULONG);
CK_RV (*logout)(struct sc_pkcs11_card *, void *);
CK_RV (*change_pin)(struct sc_pkcs11_card *, void *,
CK_RV (*change_pin)(struct sc_pkcs11_card *, void *, int,
CK_CHAR_PTR, CK_ULONG,
CK_CHAR_PTR, CK_ULONG);

View File

@ -54,7 +54,11 @@ enum {
OPT_INIT_PIN,
OPT_ATTR_FROM,
OPT_KEY_TYPE,
OPT_PRIVATE
OPT_PRIVATE,
OPT_UNLOCK_PIN,
OPT_PUK,
OPT_NEW_PIN,
OPT_LOGIN_TYPE
};
static const struct option options[] = {
@ -69,11 +73,15 @@ static const struct option options[] = {
{ "mechanism", 1, NULL, 'm' },
{ "login", 0, NULL, 'l' },
{ "login-type", 1, NULL, OPT_LOGIN_TYPE },
{ "pin", 1, NULL, 'p' },
{ "puk", 1, NULL, OPT_PUK },
{ "new-pin", 1, NULL, OPT_NEW_PIN },
{ "so-pin", 1, NULL, OPT_SO_PIN },
{ "init-token", 0, NULL, OPT_INIT_TOKEN },
{ "init-pin", 0, NULL, OPT_INIT_PIN },
{ "change-pin", 0, NULL, 'c' },
{ "unlock-pin", 0, NULL, OPT_UNLOCK_PIN },
{ "keypairgen", 0, NULL, 'k' },
{ "key-type", 1, NULL, OPT_KEY_TYPE },
{ "write-object", 1, NULL, 'w' },
@ -110,12 +118,16 @@ static const char *option_help[] = {
"Hash some data",
"Specify mechanism (use -M for a list of supported mechanisms)",
"Log into the token first (not needed when using --pin)",
"Log into the token first",
"Specify login type ('so', 'user', 'context-specific'; default:'user')",
"Supply User PIN on the command line (if used in scripts: careful!)",
"Supply User PUK on the command line",
"Supply new User PIN on the command line",
"Supply SO PIN on the command line (if used in scripts: careful!)",
"Initialize the token, its label and its SO PIN (use with --label and --so-pin)",
"Initialize the User PIN (use with --pin)",
"Change your User PIN",
"Initialize the User PIN (use with --pin and --login)",
"Change User PIN",
"Unlock User PIN (without '--login' unlock in ulogged session; otherwise '--login_type' has to be 'context-specific')",
"Key pair generation",
"Specify the type and length of the key to create, for example rsa:1024",
"Write an object (key, cert, data) to the card",
@ -158,10 +170,13 @@ static size_t opt_object_id_len = 0, new_object_id_len = 0;
static char * opt_object_label = NULL;
static char * opt_pin = NULL;
static char * opt_so_pin = NULL;
static char * opt_puk = NULL;
static char * opt_new_pin = NULL;
static char * opt_application_label = NULL;
static char * opt_application_id = NULL;
static char * opt_key_type = NULL;
static int opt_is_private = 0;
static int opt_login_type = -1;
static void *module = NULL;
static CK_FUNCTION_LIST_PTR p11 = NULL;
@ -213,6 +228,7 @@ static int login(CK_SESSION_HANDLE, int);
static void init_token(CK_SLOT_ID);
static void init_pin(CK_SLOT_ID, CK_SESSION_HANDLE);
static int change_pin(CK_SLOT_ID, CK_SESSION_HANDLE);
static int unlock_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess, int login_type);
static void show_object(CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
static void show_key(CK_SESSION_HANDLE, CK_OBJECT_HANDLE, int);
static void show_cert(CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
@ -279,11 +295,11 @@ int main(int argc, char * argv[])
int do_test = 0;
int do_test_kpgen_certwrite = 0;
int need_session = 0;
int need_to_be_so = 0;
int opt_login = 0;
int do_init_token = 0;
int do_init_pin = 0;
int do_change_pin = 0;
int do_unlock_pin = 0;
int action_count = 0;
CK_RV rv;
@ -393,13 +409,16 @@ int main(int argc, char * argv[])
opt_output = optarg;
break;
case 'p':
need_session |= NEED_SESSION_RW;
opt_login = 1;
opt_pin = optarg;
break;
case 'c':
do_change_pin = 1;
need_session |= CKF_SERIAL_SESSION; /* no need for a R/W session */
need_session |= NEED_SESSION_RW;
action_count++;
break;
case OPT_UNLOCK_PIN:
do_unlock_pin = 1;
need_session |= NEED_SESSION_RW;
action_count++;
break;
case 's':
@ -434,6 +453,24 @@ int main(int argc, char * argv[])
case OPT_APPLICATION_ID:
opt_application_id = optarg;
break;
case OPT_NEW_PIN:
opt_new_pin = optarg;
break;
case OPT_PUK:
opt_puk = optarg;
break;
case OPT_LOGIN_TYPE:
if (!strcmp(optarg, "so"))
opt_login_type = CKU_SO;
else if (!strcmp(optarg, "user"))
opt_login_type = CKU_USER;
else if (!strcmp(optarg, "context-specific"))
opt_login_type = CKU_CONTEXT_SPECIFIC;
else {
printf("Unsupported login type \"%s\"\n", optarg);
util_print_usage_and_die(app_name, options, option_help);
}
break;
case OPT_SO_PIN:
opt_so_pin = optarg;
break;
@ -443,7 +480,6 @@ int main(int argc, char * argv[])
break ;
case OPT_INIT_PIN:
need_session |= NEED_SESSION_RW;
need_to_be_so |= 1;
do_init_pin = 1;
action_count++;
break ;
@ -549,15 +585,30 @@ int main(int argc, char * argv[])
p11_fatal("C_OpenSession", rv);
}
if (opt_login) {
int r;
if (opt_login_type == -1)
opt_login_type = do_init_pin ? CKU_SO : CKU_USER;
r = login(session, opt_login_type);
if (r != 0)
return r;
}
if (do_change_pin)
/* To be sure we won't mix things up with the -l or -p options,
* we safely stop here. */
return change_pin(opt_slot, session);
if (opt_login || opt_pin || do_init_pin) {
int r = login(session, need_to_be_so);
if (r != 0)
return r;
if (do_unlock_pin) {
if (opt_login_type != -1
&& opt_login_type != CKU_CONTEXT_SPECIFIC) {
printf("Invalid login type for 'Unlock User PIN' operation\n");
util_print_usage_and_die(app_name, options, option_help);
}
return unlock_pin(opt_slot, session, opt_login_type);
}
if (do_init_pin) {
@ -785,7 +836,7 @@ static void list_objects(CK_SESSION_HANDLE sess)
p11->C_FindObjectsFinal(sess);
}
static int login(CK_SESSION_HANDLE session, int need_to_be_so)
static int login(CK_SESSION_HANDLE session, int login_type)
{
char *pin = NULL;
CK_TOKEN_INFO info;
@ -793,27 +844,35 @@ static int login(CK_SESSION_HANDLE session, int need_to_be_so)
get_token_info(opt_slot, &info);
if (!(info.flags & CKF_LOGIN_REQUIRED))
return 0;
/* Identify which pin to enter */
if (info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
if (need_to_be_so ? opt_so_pin : opt_pin)
pin = need_to_be_so ? opt_so_pin : opt_pin;
} else
if (info.flags & CKF_LOGIN_REQUIRED || need_to_be_so) {
if (need_to_be_so ? !opt_so_pin : !opt_pin)
pin = getpass(need_to_be_so ?
"Please enter SO PIN: " :
"Please enter User PIN: ");
else
pin = need_to_be_so ? opt_so_pin : opt_pin;
if (!pin || !*pin)
return 1;
} else {
return 0;
if (login_type == CKU_SO)
pin = opt_so_pin;
else if (login_type == CKU_USER)
pin = opt_pin;
else if (login_type == CKU_CONTEXT_SPECIFIC)
pin = opt_pin ? opt_pin : opt_puk;
if (!pin && (info.flags & CKF_LOGIN_REQUIRED)
&& !(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) {
if (login_type == CKU_SO)
pin = getpass("Please enter SO PIN: ");
else if (login_type == CKU_USER)
pin = getpass("Please enter User PIN: ");
else if (login_type == CKU_CONTEXT_SPECIFIC)
pin = getpass("Please enter Specific Context Secret Code: ");
}
rv = p11->C_Login(session, need_to_be_so ? CKU_SO : CKU_USER,
(CK_UTF8CHAR *) pin,
pin == NULL ? 0 : strlen(pin));
if (!(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
&& (!pin || !*pin)
&& login_type != CKU_CONTEXT_SPECIFIC)
return 1;
rv = p11->C_Login(session, login_type,
(CK_UTF8CHAR *) pin, pin == NULL ? 0 : strlen(pin));
if (rv != CKR_OK)
p11_fatal("C_Login", rv);
@ -866,8 +925,10 @@ static void init_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess)
get_token_info(slot, &info);
new_pin = opt_pin ? opt_pin : opt_new_pin;
if (!(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) {
if (opt_pin == NULL) {
if (new_pin == NULL) {
new_pin = getpass("Please enter the new PIN: ");
if (!new_pin || !*new_pin || strlen(new_pin) > 20)
util_fatal("Invalid User PIN\n");
@ -876,8 +937,6 @@ static void init_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess)
if (!new_pin || !*new_pin ||
strcmp(new_buf, new_pin) != 0)
util_fatal("Different new User PINs, exiting\n");
} else {
new_pin = opt_pin;
}
}
@ -924,6 +983,60 @@ static int change_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess)
return 0;
}
static int unlock_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess, int login_type)
{
char unlock_buf[21], *unlock_code = NULL;
char new_buf[21], *new_pin = NULL;
CK_TOKEN_INFO info;
CK_RV rv;
get_token_info(slot, &info);
if (login_type == CKU_CONTEXT_SPECIFIC)
unlock_code = opt_pin ? opt_pin : opt_puk;
else if (login_type == -1)
unlock_code = opt_puk;
else
return 1;
if (!(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) && !unlock_code) {
if (login_type == CKU_CONTEXT_SPECIFIC)
unlock_code = getpass("Please enter the 'Change PIN' context secret code: ");
else if (login_type == -1)
unlock_code = getpass("Please enter unblock code for User PIN: ");
if (!unlock_code || !*unlock_code || strlen(unlock_code) > 20)
return 1;
strcpy(unlock_buf, unlock_code);
unlock_code = unlock_buf;
}
new_pin = opt_new_pin;
if (!(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) && !new_pin) {
new_pin = getpass("Please enter the new PIN: ");
strcpy(new_buf, new_pin);
new_pin = getpass("Please enter the new PIN again: ");
if (!new_pin || !*new_pin || strcmp(new_buf, new_pin) != 0) {
printf(" different new PINs, exiting\n");
return -1;
}
if (!new_pin || !*new_pin || strlen(new_pin) > 20)
return 1;
}
rv = p11->C_SetPIN(sess,
(CK_UTF8CHAR *) unlock_code, unlock_code == NULL ? 0 : strlen(unlock_code),
(CK_UTF8CHAR *) new_pin, new_pin == NULL ? 0 : strlen(new_pin));
if (rv != CKR_OK)
p11_fatal("C_SetPIN", rv);
printf("PIN successfully changed\n");
return 0;
}
static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE key)
{