Implemented C_SetPIN
This commit is contained in:
+62
@@ -716,6 +716,68 @@ ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHREF_ACT_CHANGE_PIN 0
|
||||||
|
#define CHREF_ACT_UNBLOCK_PIN 1
|
||||||
|
#define CHREF_ACT_CHANGE_PUK 2
|
||||||
|
|
||||||
|
static ykpiv_rc _change_pin_internal(ykpiv_state *state, int action, const char * current_pin, size_t current_pin_len, const char * new_pin, size_t new_pin_len, int *tries) {
|
||||||
|
int sw;
|
||||||
|
unsigned char templ[] = {0, YKPIV_INS_CHANGE_REFERENCE, 0, 0x80};
|
||||||
|
unsigned char indata[0x10];
|
||||||
|
unsigned char data[0xff];
|
||||||
|
unsigned long recv_len = sizeof(data);
|
||||||
|
ykpiv_rc res;
|
||||||
|
if (current_pin_len > 8) {
|
||||||
|
return YKPIV_SIZE_ERROR;
|
||||||
|
}
|
||||||
|
if (new_pin_len > 8) {
|
||||||
|
return YKPIV_SIZE_ERROR;
|
||||||
|
}
|
||||||
|
if(action == CHREF_ACT_UNBLOCK_PIN) {
|
||||||
|
templ[1] = YKPIV_INS_RESET_RETRY;
|
||||||
|
}
|
||||||
|
else if(action == CHREF_ACT_CHANGE_PUK) {
|
||||||
|
templ[3] = 0x81;
|
||||||
|
}
|
||||||
|
memcpy(indata, current_pin, current_pin_len);
|
||||||
|
if(current_pin_len < 8) {
|
||||||
|
memset(indata + current_pin_len, 0xff, 8 - current_pin_len);
|
||||||
|
}
|
||||||
|
memcpy(indata + 8, new_pin, new_pin_len);
|
||||||
|
if(new_pin_len < 8) {
|
||||||
|
memset(indata + 8 + new_pin_len, 0xff, 8 - new_pin_len);
|
||||||
|
}
|
||||||
|
res = ykpiv_transfer_data(state, templ, indata, sizeof(indata), data, &recv_len, &sw);
|
||||||
|
if(res != YKPIV_OK) {
|
||||||
|
return res;
|
||||||
|
} else if(sw != 0x9000) {
|
||||||
|
if((sw >> 8) == 0x63) {
|
||||||
|
*tries = sw & 0xf;
|
||||||
|
return YKPIV_WRONG_PIN;
|
||||||
|
} else if(sw == 0x6983) {
|
||||||
|
return YKPIV_PIN_LOCKED;
|
||||||
|
} else {
|
||||||
|
if(state->verbose) {
|
||||||
|
fprintf(stderr, "Failed changing pin, token response code: %x.\n", sw);
|
||||||
|
}
|
||||||
|
return YKPIV_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return YKPIV_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ykpiv_rc ykpiv_change_pin(ykpiv_state *state, const char * current_pin, size_t current_pin_len, const char * new_pin, size_t new_pin_len, int *tries) {
|
||||||
|
return _change_pin_internal(state, CHREF_ACT_CHANGE_PIN, current_pin, current_pin_len, new_pin, new_pin_len, tries);
|
||||||
|
}
|
||||||
|
|
||||||
|
ykpiv_rc ykpiv_change_puk(ykpiv_state *state, const char * current_puk, size_t current_puk_len, const char * new_puk, size_t new_puk_len, int *tries) {
|
||||||
|
return _change_pin_internal(state, CHREF_ACT_CHANGE_PUK, current_puk, current_puk_len, new_puk, new_puk_len, tries);
|
||||||
|
}
|
||||||
|
|
||||||
|
ykpiv_rc ykpiv_unblock_pin(ykpiv_state *state, const char * puk, size_t puk_len, const char * new_pin, size_t new_pin_len, int *tries) {
|
||||||
|
return _change_pin_internal(state, CHREF_ACT_CHANGE_PUK, puk, puk_len, new_pin, new_pin_len, tries);
|
||||||
|
}
|
||||||
|
|
||||||
ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
|
ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
|
||||||
unsigned char *data, unsigned long *len) {
|
unsigned char *data, unsigned long *len) {
|
||||||
int sw;
|
int sw;
|
||||||
|
|||||||
+10
@@ -57,6 +57,7 @@ extern "C"
|
|||||||
YKPIV_WRONG_PIN = -10,
|
YKPIV_WRONG_PIN = -10,
|
||||||
YKPIV_INVALID_OBJECT = -11,
|
YKPIV_INVALID_OBJECT = -11,
|
||||||
YKPIV_ALGORITHM_ERROR = -12,
|
YKPIV_ALGORITHM_ERROR = -12,
|
||||||
|
YKPIV_PIN_LOCKED = -13,
|
||||||
} ykpiv_rc;
|
} ykpiv_rc;
|
||||||
|
|
||||||
const char *ykpiv_strerror(ykpiv_rc err);
|
const char *ykpiv_strerror(ykpiv_rc err);
|
||||||
@@ -85,6 +86,15 @@ extern "C"
|
|||||||
unsigned char algorithm, unsigned char key);
|
unsigned char algorithm, unsigned char key);
|
||||||
ykpiv_rc ykpiv_get_version(ykpiv_state *state, char *version, size_t len);
|
ykpiv_rc ykpiv_get_version(ykpiv_state *state, char *version, size_t len);
|
||||||
ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries);
|
ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries);
|
||||||
|
ykpiv_rc ykpiv_change_pin(ykpiv_state *state, const char * current_pin, size_t current_pin_len,
|
||||||
|
const char * new_pin, size_t new_pin_len,
|
||||||
|
int *tries);
|
||||||
|
ykpiv_rc ykpiv_change_puk(ykpiv_state *state, const char * current_puk, size_t current_puk_len,
|
||||||
|
const char * new_puk, size_t new_puk_len,
|
||||||
|
int *tries);
|
||||||
|
ykpiv_rc ykpiv_unblock_pin(ykpiv_state *state, const char * puk, size_t puk_len,
|
||||||
|
const char * new_pin, size_t new_pin_len,
|
||||||
|
int *tries);
|
||||||
ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
|
ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
|
||||||
unsigned char *data, unsigned long *len);
|
unsigned char *data, unsigned long *len);
|
||||||
ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key,
|
ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key,
|
||||||
|
|||||||
@@ -62,3 +62,11 @@ global:
|
|||||||
ykpiv_list_readers;
|
ykpiv_list_readers;
|
||||||
ykpiv_import_private_key;
|
ykpiv_import_private_key;
|
||||||
} YKPIV_0.1.0;
|
} YKPIV_0.1.0;
|
||||||
|
|
||||||
|
YKPIV_1.2.1
|
||||||
|
{
|
||||||
|
global:
|
||||||
|
ykpiv_change_pin;
|
||||||
|
ykpiv_change_puk;
|
||||||
|
ykpiv_unblock_pin;
|
||||||
|
} YKPIV_1.1.0;
|
||||||
|
|||||||
+19
-25
@@ -969,17 +969,16 @@ static bool verify_pin(ykpiv_state *state, const char *pin) {
|
|||||||
* since they're very similar in what data they use. */
|
* since they're very similar in what data they use. */
|
||||||
static bool change_pin(ykpiv_state *state, enum enum_action action, const char *pin,
|
static bool change_pin(ykpiv_state *state, enum enum_action action, const char *pin,
|
||||||
const char *new_pin) {
|
const char *new_pin) {
|
||||||
unsigned char templ[] = {0, YKPIV_INS_CHANGE_REFERENCE, 0, 0x80};
|
|
||||||
unsigned char indata[0x10];
|
|
||||||
unsigned char data[0xff];
|
|
||||||
unsigned long recv_len = sizeof(data);
|
|
||||||
char pinbuf[9] = {0};
|
char pinbuf[9] = {0};
|
||||||
char new_pinbuf[9] = {0};
|
char new_pinbuf[9] = {0};
|
||||||
const char *name = action == action_arg_changeMINUS_pin ? "pin" : "puk";
|
const char *name = action == action_arg_changeMINUS_pin ? "pin" : "puk";
|
||||||
const char *new_name = action == action_arg_changeMINUS_puk ? "new puk" : "new pin";
|
const char *new_name = action == action_arg_changeMINUS_puk ? "new puk" : "new pin";
|
||||||
int sw;
|
int (*op)(ykpiv_state *state, const char * puk, size_t puk_len,
|
||||||
|
const char * new_pin, size_t new_pin_len, int *tries) = ykpiv_change_pin;
|
||||||
size_t pin_len;
|
size_t pin_len;
|
||||||
size_t new_len;
|
size_t new_len;
|
||||||
|
int tries;
|
||||||
|
ykpiv_rc res;
|
||||||
|
|
||||||
if(!pin) {
|
if(!pin) {
|
||||||
if (!read_pw(name, pinbuf, sizeof(pinbuf), false)) {
|
if (!read_pw(name, pinbuf, sizeof(pinbuf), false)) {
|
||||||
@@ -1002,38 +1001,33 @@ static bool change_pin(ykpiv_state *state, enum enum_action action, const char *
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(action == action_arg_unblockMINUS_pin) {
|
if(action == action_arg_unblockMINUS_pin) {
|
||||||
templ[1] = YKPIV_INS_RESET_RETRY;
|
op = ykpiv_unblock_pin;
|
||||||
}
|
}
|
||||||
else if(action == action_arg_changeMINUS_puk) {
|
else if(action == action_arg_changeMINUS_puk) {
|
||||||
templ[3] = 0x81;
|
op = ykpiv_change_puk;
|
||||||
}
|
}
|
||||||
memcpy(indata, pin, pin_len);
|
res = op(state, pin, pin_len, new_pin, new_len, &tries);
|
||||||
if(pin_len < 8) {
|
switch (res) {
|
||||||
memset(indata + pin_len, 0xff, 8 - pin_len);
|
case YKPIV_OK:
|
||||||
}
|
return true;
|
||||||
memcpy(indata + 8, new_pin, new_len);
|
|
||||||
if(new_len < 8) {
|
case YKPIV_WRONG_PIN:
|
||||||
memset(indata + 8 + new_len, 0xff, 8 - new_len);
|
|
||||||
}
|
|
||||||
if(ykpiv_transfer_data(state, templ, indata, sizeof(indata), data, &recv_len, &sw) != YKPIV_OK) {
|
|
||||||
return false;
|
|
||||||
} else if(sw != 0x9000) {
|
|
||||||
if((sw >> 8) == 0x63) {
|
|
||||||
int tries = sw & 0xf;
|
|
||||||
fprintf(stderr, "Failed verifying %s code, now %d tries left before blocked.\n",
|
fprintf(stderr, "Failed verifying %s code, now %d tries left before blocked.\n",
|
||||||
name, tries);
|
name, tries);
|
||||||
} else if(sw == 0x6983) {
|
return false;
|
||||||
|
|
||||||
|
case YKPIV_PIN_LOCKED:
|
||||||
if(action == action_arg_changeMINUS_pin) {
|
if(action == action_arg_changeMINUS_pin) {
|
||||||
fprintf(stderr, "The pin code is blocked, use the unblock-pin action to unblock it.\n");
|
fprintf(stderr, "The pin code is blocked, use the unblock-pin action to unblock it.\n");
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "The puk code is blocked, you will have to reinitialize the application.\n");
|
fprintf(stderr, "The puk code is blocked, you will have to reinitialize the application.\n");
|
||||||
}
|
}
|
||||||
} else {
|
return false;
|
||||||
fprintf(stderr, "Failed changing/unblocking code, error: %x\n", sw);
|
|
||||||
}
|
default:
|
||||||
|
fprintf(stderr, "Failed changing/unblocking code, error: %x\n", res);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool delete_certificate(ykpiv_state *state, enum enum_slot slot) {
|
static bool delete_certificate(ykpiv_state *state, enum enum_slot slot) {
|
||||||
|
|||||||
@@ -290,6 +290,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) {
|
|||||||
v.token_import_cert = COMMON_token_import_cert;
|
v.token_import_cert = COMMON_token_import_cert;
|
||||||
v.token_import_private_key = COMMON_token_import_private_key;
|
v.token_import_private_key = COMMON_token_import_private_key;
|
||||||
v.token_delete_cert = COMMON_token_delete_cert;
|
v.token_delete_cert = COMMON_token_delete_cert;
|
||||||
|
v.token_change_pin = YUBICO_token_change_pin;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNKNOWN:
|
case UNKNOWN:
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ typedef CK_RV (*get_t_mechanism_info_f)(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR
|
|||||||
typedef CK_RV (*get_t_objects_num_f)(ykpiv_state *, CK_ULONG_PTR, CK_ULONG_PTR);
|
typedef CK_RV (*get_t_objects_num_f)(ykpiv_state *, CK_ULONG_PTR, CK_ULONG_PTR);
|
||||||
typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG);
|
typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG);
|
||||||
typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PTR, CK_ULONG_PTR);
|
typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PTR, CK_ULONG_PTR);
|
||||||
|
typedef CK_RV (*t_change_pin_f)(ykpiv_state *, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULONG, CK_UTF8CHAR_PTR, CK_ULONG);
|
||||||
|
|
||||||
// Common token functions below
|
// Common token functions below
|
||||||
typedef CK_RV (*t_login_f)(ykpiv_state *, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULONG);
|
typedef CK_RV (*t_login_f)(ykpiv_state *, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULONG);
|
||||||
@@ -53,6 +54,7 @@ typedef struct {
|
|||||||
t_import_cert_f token_import_cert;
|
t_import_cert_f token_import_cert;
|
||||||
t_import_private_key_f token_import_private_key;
|
t_import_private_key_f token_import_private_key;
|
||||||
t_delete_cert_f token_delete_cert;
|
t_delete_cert_f token_delete_cert;
|
||||||
|
t_change_pin_f token_change_pin;
|
||||||
} token_vendor_t;
|
} token_vendor_t;
|
||||||
|
|
||||||
token_vendor_t get_token_vendor(vendor_id_t vid);
|
token_vendor_t get_token_vendor(vendor_id_t vid);
|
||||||
|
|||||||
+31
-1
@@ -421,7 +421,36 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
DIN;
|
DIN;
|
||||||
DBG("TODO!!!");
|
CK_RV rv;
|
||||||
|
token_vendor_t token;
|
||||||
|
|
||||||
|
if (piv_state == NULL) {
|
||||||
|
DBG("libykpiv is not initialized or already finalized");
|
||||||
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session.handle == CK_INVALID_HANDLE) {
|
||||||
|
DBG("User called SetPIN on closed session");
|
||||||
|
return CKR_SESSION_CLOSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hSession != YKCS11_SESSION_ID) {
|
||||||
|
DBG("Unknown session %lu", hSession);
|
||||||
|
return CKR_SESSION_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_USER_TYPE user_type = CKU_USER;
|
||||||
|
if (session.info.state == CKS_RW_SO_FUNCTIONS) {
|
||||||
|
user_type = CKU_SO;
|
||||||
|
}
|
||||||
|
|
||||||
|
token = get_token_vendor(session.slot->token->vid);
|
||||||
|
rv = token.token_change_pin(piv_state, user_type, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
||||||
|
if (rv != CKR_OK) {
|
||||||
|
DBG("Pin change failed %lx", rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
DOUT;
|
DOUT;
|
||||||
return CKR_OK;
|
return CKR_OK;
|
||||||
}
|
}
|
||||||
@@ -979,6 +1008,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
|
|||||||
DBG("Unable to store certificate data");
|
DBG("Unable to store certificate data");
|
||||||
return CKR_FUNCTION_FAILED;
|
return CKR_FUNCTION_FAILED;
|
||||||
}
|
}
|
||||||
|
*phObject = cert_id;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -334,3 +334,25 @@ CK_RV YUBICO_get_token_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_
|
|||||||
|
|
||||||
return CKR_OK;
|
return CKR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CK_RV YUBICO_token_change_pin(ykpiv_state *state, CK_USER_TYPE user_type, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen) {
|
||||||
|
int tries;
|
||||||
|
ykpiv_rc res;
|
||||||
|
if (user_type != CKU_USER) {
|
||||||
|
DBG("TODO implement other users pin change");
|
||||||
|
return CKR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
res = ykpiv_change_pin(state, pOldPin, ulOldLen, pNewPin, ulNewLen, &tries);
|
||||||
|
switch (res) {
|
||||||
|
case YKPIV_OK:
|
||||||
|
return CKR_OK;
|
||||||
|
case YKPIV_SIZE_ERROR:
|
||||||
|
return CKR_PIN_LEN_RANGE;
|
||||||
|
case YKPIV_WRONG_PIN:
|
||||||
|
return CKR_PIN_INCORRECT;
|
||||||
|
case YKPIV_PIN_LOCKED:
|
||||||
|
return CKR_PIN_LOCKED;
|
||||||
|
default:
|
||||||
|
return CKR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,5 +17,7 @@ CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_P
|
|||||||
CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num, CK_ULONG_PTR num_certs);
|
CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num, CK_ULONG_PTR num_certs);
|
||||||
CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG num);
|
CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG num);
|
||||||
CK_RV YUBICO_get_token_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_BYTE_PTR data, CK_ULONG_PTR len);
|
CK_RV YUBICO_get_token_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_BYTE_PTR data, CK_ULONG_PTR len);
|
||||||
|
CK_RV YUBICO_token_change_pin(ykpiv_state *state, CK_USER_TYPE user_type, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen,
|
||||||
|
CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user