Fix PIN length handling in ykpiv_verify*()
This commit is contained in:
+22
-21
@@ -926,50 +926,47 @@ static ykpiv_rc _cache_pin(ykpiv_state *state, const char *pin, size_t len) {
|
|||||||
if (state->pin == NULL) {
|
if (state->pin == NULL) {
|
||||||
return YKPIV_MEMORY_ERROR;
|
return YKPIV_MEMORY_ERROR;
|
||||||
}
|
}
|
||||||
memcpy(state->pin, pin, len + 1);
|
memcpy(state->pin, pin, len);
|
||||||
|
state->pin[len] = 0;
|
||||||
}
|
}
|
||||||
return YKPIV_OK;
|
return YKPIV_OK;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries) {
|
static ykpiv_rc _verify(ykpiv_state *state, const char *pin, const size_t pin_len, int *tries) {
|
||||||
// TREV TODO: pin len?
|
|
||||||
APDU apdu;
|
APDU apdu;
|
||||||
unsigned char data[261];
|
unsigned char data[261];
|
||||||
uint32_t recv_len = sizeof(data);
|
uint32_t recv_len = sizeof(data);
|
||||||
int sw;
|
int sw;
|
||||||
size_t len = 0;
|
|
||||||
ykpiv_rc res;
|
ykpiv_rc res;
|
||||||
if(pin) {
|
|
||||||
len = strlen(pin);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(len > 8) {
|
if (pin_len > 8) {
|
||||||
return YKPIV_SIZE_ERROR;
|
return YKPIV_SIZE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(apdu.raw, 0, sizeof(apdu.raw));
|
memset(apdu.raw, 0, sizeof(apdu.raw));
|
||||||
apdu.st.ins = YKPIV_INS_VERIFY;
|
apdu.st.ins = YKPIV_INS_VERIFY;
|
||||||
apdu.st.p1 = 0x00;
|
apdu.st.p1 = 0x00;
|
||||||
apdu.st.p2 = 0x80;
|
apdu.st.p2 = 0x80;
|
||||||
apdu.st.lc = pin ? 0x08 : 0;
|
apdu.st.lc = pin ? 0x08 : 0;
|
||||||
if(pin) {
|
if (pin) {
|
||||||
memcpy(apdu.st.data, pin, len);
|
memcpy(apdu.st.data, pin, pin_len);
|
||||||
if(len < 8) {
|
if (pin_len < 8) {
|
||||||
memset(apdu.st.data + len, 0xff, 8 - len);
|
memset(apdu.st.data + pin_len, 0xff, 8 - pin_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) {
|
if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) {
|
||||||
return res;
|
return res;
|
||||||
} else if(sw == SW_SUCCESS) {
|
} else if (sw == SW_SUCCESS) {
|
||||||
// Intentionally ignore errors. If the PIN fails to save, it will only
|
// Intentionally ignore errors. If the PIN fails to save, it will only
|
||||||
// be a problem if a reconnect is attempted. Failure deferred until then.
|
// be a problem if a reconnect is attempted. Failure deferred until then.
|
||||||
_cache_pin(state, pin, len + 1);
|
_cache_pin(state, pin, pin_len);
|
||||||
if (tries) *tries = (sw & 0xf);
|
if (tries) *tries = (sw & 0xf);
|
||||||
return YKPIV_OK;
|
return YKPIV_OK;
|
||||||
} else if((sw >> 8) == 0x63) {
|
} else if ((sw >> 8) == 0x63) {
|
||||||
if (tries) *tries = (sw & 0xf);
|
if (tries) *tries = (sw & 0xf);
|
||||||
return YKPIV_WRONG_PIN;
|
return YKPIV_WRONG_PIN;
|
||||||
} else if(sw == SW_ERR_AUTH_BLOCKED) {
|
} else if (sw == SW_ERR_AUTH_BLOCKED) {
|
||||||
if (tries) *tries = 0;
|
if (tries) *tries = 0;
|
||||||
return YKPIV_WRONG_PIN;
|
return YKPIV_WRONG_PIN;
|
||||||
} else {
|
} else {
|
||||||
@@ -977,13 +974,17 @@ ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries) {
|
||||||
|
return ykpiv_verify_select(state, pin, pin ? strlen(pin) : 0, tries, false);
|
||||||
|
}
|
||||||
|
|
||||||
ykpiv_rc ykpiv_verify_select(ykpiv_state *state, const char *pin, const size_t pin_len, int *tries, bool force_select) {
|
ykpiv_rc ykpiv_verify_select(ykpiv_state *state, const char *pin, const size_t pin_len, int *tries, bool force_select) {
|
||||||
ykpiv_rc res = YKPIV_OK;
|
ykpiv_rc res = YKPIV_OK;
|
||||||
if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) goto Cleanup;
|
if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) goto Cleanup;
|
||||||
if (force_select) {
|
if (force_select) {
|
||||||
if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
|
if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
|
||||||
}
|
}
|
||||||
res = ykpiv_verify(state, pin, tries);
|
res = _verify(state, pin, pin_len, tries);
|
||||||
Cleanup:
|
Cleanup:
|
||||||
|
|
||||||
_ykpiv_end_transaction(state);
|
_ykpiv_end_transaction(state);
|
||||||
@@ -1096,7 +1097,7 @@ ykpiv_rc ykpiv_change_pin(ykpiv_state *state, const char * current_pin, size_t c
|
|||||||
if (res == YKPIV_OK && new_pin != NULL) {
|
if (res == YKPIV_OK && new_pin != NULL) {
|
||||||
// Intentionally ignore errors. If the PIN fails to save, it will only
|
// Intentionally ignore errors. If the PIN fails to save, it will only
|
||||||
// be a problem if a reconnect is attempted. Failure deferred until then.
|
// be a problem if a reconnect is attempted. Failure deferred until then.
|
||||||
_cache_pin(state, new_pin, new_pin_len + 1);
|
_cache_pin(state, new_pin, new_pin_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
@@ -1358,7 +1359,7 @@ ykpiv_rc ykpiv_auth_getchallenge(ykpiv_state *state, uint8_t *challenge, const s
|
|||||||
ykpiv_rc res = YKPIV_OK;
|
ykpiv_rc res = YKPIV_OK;
|
||||||
APDU apdu = { 0 };
|
APDU apdu = { 0 };
|
||||||
unsigned char data[261] = { 0 };
|
unsigned char data[261] = { 0 };
|
||||||
unsigned long recv_len = sizeof(data);
|
uint32_t recv_len = sizeof(data);
|
||||||
int sw = 0;
|
int sw = 0;
|
||||||
|
|
||||||
if (NULL == state) return YKPIV_GENERIC_ERROR;
|
if (NULL == state) return YKPIV_GENERIC_ERROR;
|
||||||
@@ -1396,7 +1397,7 @@ ykpiv_rc ykpiv_auth_verifyresponse(ykpiv_state *state, uint8_t *response, const
|
|||||||
ykpiv_rc res = YKPIV_OK;
|
ykpiv_rc res = YKPIV_OK;
|
||||||
APDU apdu = { 0 };
|
APDU apdu = { 0 };
|
||||||
unsigned char data[261] = { 0 };
|
unsigned char data[261] = { 0 };
|
||||||
unsigned long recv_len = sizeof(data);
|
uint32_t recv_len = sizeof(data);
|
||||||
int sw = 0;
|
int sw = 0;
|
||||||
unsigned char *dataptr = apdu.st.data;
|
unsigned char *dataptr = apdu.st.data;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user