minidriver: added support for session pin
This commit is contained in:
parent
74ec7b04ff
commit
7c3bb44cdf
|
@ -237,6 +237,7 @@ sc_pkcs15_unbind
|
|||
sc_pkcs15_unblock_pin
|
||||
sc_pkcs15_verify_pin
|
||||
sc_pkcs15_get_pin_info
|
||||
sc_pkcs15_verify_pin_with_session_pin
|
||||
sc_pkcs15emu_add_data_object
|
||||
sc_pkcs15emu_add_pin_obj
|
||||
sc_pkcs15emu_add_rsa_prkey
|
||||
|
|
|
@ -330,6 +330,22 @@ sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pi
|
|||
int
|
||||
_sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pin_obj,
|
||||
const unsigned char *pincode, size_t pinlen)
|
||||
{
|
||||
return sc_pkcs15_verify_pin_with_session_pin(p15card, pin_obj, pincode,
|
||||
pinlen, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify a PIN and generate a session 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_with_session_pin(struct sc_pkcs15_card *p15card,
|
||||
struct sc_pkcs15_object *pin_obj,
|
||||
const unsigned char *pincode, size_t pinlen,
|
||||
const unsigned char *sessionpin, size_t *sessionpinlen)
|
||||
{
|
||||
struct sc_context *ctx = p15card->card->ctx;
|
||||
struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
|
||||
|
@ -350,7 +366,6 @@ _sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *p
|
|||
|
||||
/* Initialize arguments */
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.cmd = SC_PIN_CMD_VERIFY;
|
||||
data.pin_type = auth_info->auth_method;
|
||||
|
||||
if (auth_info->auth_type == SC_PKCS15_PIN_AUTH_TYPE_PIN) {
|
||||
|
@ -404,6 +419,19 @@ _sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *p
|
|||
data.pin1.prompt = "Please enter PIN";
|
||||
}
|
||||
|
||||
if (card->caps & SC_CARD_CAP_SESSION_PIN && sessionpin && sessionpinlen) {
|
||||
/* session pin is requested and supported with standard verification*/
|
||||
data.cmd = SC_PIN_CMD_GET_SESSION_PIN;
|
||||
memcpy(&data.pin2, &data.pin1, sizeof (data.pin1));
|
||||
data.pin2.data = sessionpin;
|
||||
data.pin2.len = *sessionpinlen;
|
||||
} else {
|
||||
/* perform a standard verify */
|
||||
data.cmd = SC_PIN_CMD_VERIFY;
|
||||
if (sessionpinlen)
|
||||
*sessionpinlen = 0;
|
||||
}
|
||||
|
||||
r = sc_lock(card);
|
||||
LOG_TEST_RET(ctx, r, "sc_lock() failed");
|
||||
|
||||
|
@ -416,6 +444,16 @@ _sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *p
|
|||
|
||||
r = sc_pin_cmd(card, &data, &auth_info->tries_left);
|
||||
sc_log(ctx, "PIN cmd result %i", r);
|
||||
if (r == SC_SUCCESS) {
|
||||
sc_pkcs15_pincache_add(p15card, pin_obj, pincode, pinlen);
|
||||
if (data.cmd == SC_PIN_CMD_GET_SESSION_PIN) {
|
||||
*sessionpinlen = data.pin2.len;
|
||||
}
|
||||
} else {
|
||||
if (data.cmd == SC_PIN_CMD_GET_SESSION_PIN) {
|
||||
*sessionpinlen = 0;
|
||||
}
|
||||
}
|
||||
out:
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(ctx, r);
|
||||
|
|
|
@ -767,6 +767,10 @@ int sc_pkcs15_find_skey_by_id(struct sc_pkcs15_card *card,
|
|||
int sc_pkcs15_verify_pin(struct sc_pkcs15_card *card,
|
||||
struct sc_pkcs15_object *pin_obj,
|
||||
const u8 *pincode, size_t pinlen);
|
||||
int sc_pkcs15_verify_pin_with_session_pin(struct sc_pkcs15_card *p15card,
|
||||
struct sc_pkcs15_object *pin_obj,
|
||||
const unsigned char *pincode, size_t pinlen,
|
||||
const unsigned char *sessionpin, size_t *sessionpinlen);
|
||||
int sc_pkcs15_change_pin(struct sc_pkcs15_card *card,
|
||||
struct sc_pkcs15_object *pin_obj,
|
||||
const u8 *oldpincode, size_t oldpinlen,
|
||||
|
|
|
@ -2346,18 +2346,21 @@ md_dialog_perform_pin_operation_thread(PVOID lpParameter)
|
|||
const u8 *pin1 = (const u8 *) parameter[3];
|
||||
size_t pin1len = parameter[4];
|
||||
const u8 *pin2 = (const u8 *) parameter[5];
|
||||
size_t pin2len = parameter[6];
|
||||
size_t *pin2len = (size_t *) parameter[6];
|
||||
int rv = 0;
|
||||
switch (operation)
|
||||
{
|
||||
case SC_PIN_CMD_VERIFY:
|
||||
rv = sc_pkcs15_verify_pin(p15card, pin_obj, pin1, pin1len);
|
||||
break;
|
||||
case SC_PIN_CMD_GET_SESSION_PIN:
|
||||
rv = sc_pkcs15_verify_pin_with_session_pin(p15card, pin_obj, pin1, pin1len, pin2, pin2len);
|
||||
break;
|
||||
case SC_PIN_CMD_CHANGE:
|
||||
rv = sc_pkcs15_change_pin(p15card, pin_obj, pin1, pin1len,pin2, pin2len);
|
||||
rv = sc_pkcs15_change_pin(p15card, pin_obj, pin1, pin1len,pin2, pin2len ? *pin2len : 0);
|
||||
break;
|
||||
case SC_PIN_CMD_UNBLOCK:
|
||||
rv = sc_pkcs15_unblock_pin(p15card, pin_obj, pin1, pin1len,pin2, pin2len);
|
||||
rv = sc_pkcs15_unblock_pin(p15card, pin_obj, pin1, pin1len,pin2, pin2len ? *pin2len : 0);
|
||||
break;
|
||||
default:
|
||||
rv = (DWORD) ERROR_INVALID_PARAMETER;
|
||||
|
@ -2421,7 +2424,7 @@ static int
|
|||
md_dialog_perform_pin_operation(PCARD_DATA pCardData, int operation, struct sc_pkcs15_card *p15card,
|
||||
struct sc_pkcs15_object *pin_obj,
|
||||
const u8 *pin1, size_t pin1len,
|
||||
const u8 *pin2, size_t pin2len, BOOL displayUI)
|
||||
const u8 *pin2, size_t *pin2len, BOOL displayUI)
|
||||
{
|
||||
LONG_PTR parameter[10];
|
||||
INT_PTR result = 0;
|
||||
|
@ -4750,6 +4753,7 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData,
|
|||
VENDOR_SPECIFIC *vs;
|
||||
struct sc_pkcs15_object *pin_obj = NULL;
|
||||
struct sc_pkcs15_auth_info *auth_info = NULL;
|
||||
unsigned int auth_method;
|
||||
int r;
|
||||
BOOL DisplayPinpadUI = FALSE;
|
||||
|
||||
|
@ -4773,11 +4777,16 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData,
|
|||
if ((vs->p15card) == NULL)
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
|
||||
#if 0
|
||||
/* TODO do we need to return SCARD_E_UNSUPPORTED_FEATURE if the card
|
||||
* doesn't support it or if the minidriver doesn't support it in general?
|
||||
* */
|
||||
if (dwFlags == CARD_AUTHENTICATE_GENERATE_SESSION_PIN || dwFlags == CARD_AUTHENTICATE_SESSION_PIN) {
|
||||
if (! (vs->reader->capabilities & SC_READER_CAP_PIN_PAD
|
||||
|| vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH))
|
||||
return SCARD_E_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dwFlags & ~(CARD_AUTHENTICATE_GENERATE_SESSION_PIN | CARD_AUTHENTICATE_SESSION_PIN | CARD_PIN_SILENT_CONTEXT))
|
||||
return SCARD_E_INVALID_PARAMETER;
|
||||
|
@ -4808,6 +4817,8 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData,
|
|||
if (!pin_obj)
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
|
||||
/* save the pin type */
|
||||
auth_method = auth_info->auth_method;
|
||||
|
||||
/* Do we need to display a prompt to enter PIN on pin pad? */
|
||||
logprintf(pCardData, 7, "PIN pad=%s, pbPinData=%p, hwndParent=%p\n",
|
||||
|
@ -4815,13 +4826,53 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData,
|
|||
|| vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH
|
||||
? "yes" : "no", pbPinData, vs->hwndParent);
|
||||
|
||||
/* check if the pin is the session pin generated by a previous authentication with a pinpad */
|
||||
if (pbPinData != NULL && cbPinData == sizeof(MAGIC_SESSION_PIN) && memcmp(MAGIC_SESSION_PIN, pbPinData, sizeof(MAGIC_SESSION_PIN)) == 0) {
|
||||
pbPinData = NULL;
|
||||
cbPinData = 0;
|
||||
if (dwFlags & CARD_AUTHENTICATE_SESSION_PIN) {
|
||||
/* check if the pin is the session pin generated by a previous authentication with a pinpad */
|
||||
if (pbPinData != NULL && cbPinData == sizeof(MAGIC_SESSION_PIN) && memcmp(MAGIC_SESSION_PIN, pbPinData, sizeof(MAGIC_SESSION_PIN)) == 0) {
|
||||
logprintf(pCardData, 2, "use magic session pin");
|
||||
pbPinData = NULL;
|
||||
cbPinData = 0;
|
||||
} else {
|
||||
/* seems we have a real session pin, set the pin type accordingly */
|
||||
logprintf(pCardData, 2, "use real session pin with %d bytes", cbPinData);
|
||||
auth_info->auth_method = SC_AC_SESSION;
|
||||
}
|
||||
}
|
||||
|
||||
r = md_dialog_perform_pin_operation(pCardData, SC_PIN_CMD_VERIFY, vs->p15card, pin_obj, (const u8 *) pbPinData, cbPinData, NULL, 0, DisplayPinpadUI);
|
||||
/* set the session pin according to the minidriver specification */
|
||||
if (dwFlags & CARD_AUTHENTICATE_GENERATE_SESSION_PIN) {
|
||||
logprintf(pCardData, 2, "generating session pin");
|
||||
if (ppbSessionPin) *ppbSessionPin = pCardData->pfnCspAlloc(SC_MAX_PIN_SIZE);
|
||||
if (ppbSessionPin) *pcbSessionPin = SC_MAX_PIN_SIZE;
|
||||
r = md_dialog_perform_pin_operation(pCardData, SC_PIN_CMD_GET_SESSION_PIN, vs->p15card, pin_obj, (const u8 *) pbPinData, cbPinData,
|
||||
ppbSessionPin && *ppbSessionPin ? *ppbSessionPin : NULL, pcbSessionPin, DisplayPinpadUI);
|
||||
if (r) {
|
||||
if (ppbSessionPin) {
|
||||
pCardData->pfnCspFree(*ppbSessionPin);
|
||||
*ppbSessionPin = NULL;
|
||||
}
|
||||
if (pcbSessionPin) *pcbSessionPin = 0;
|
||||
logprintf(pCardData, 2, "generating session pin failed");
|
||||
} else {
|
||||
if (pcbSessionPin && *pcbSessionPin) {
|
||||
logprintf(pCardData, 2, "generated session pin with %d bytes", *pcbSessionPin);
|
||||
} else {
|
||||
logprintf(pCardData, 2, "session pin not supported");
|
||||
if (ppbSessionPin) {
|
||||
pCardData->pfnCspFree(*ppbSessionPin);
|
||||
*ppbSessionPin = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (pcbSessionPin) *pcbSessionPin = 0;
|
||||
if (ppbSessionPin) *ppbSessionPin = NULL;
|
||||
logprintf(pCardData, 2, "standard pin verification");
|
||||
r = md_dialog_perform_pin_operation(pCardData, SC_PIN_CMD_VERIFY, vs->p15card, pin_obj, (const u8 *) pbPinData, cbPinData, NULL, NULL, DisplayPinpadUI);
|
||||
}
|
||||
|
||||
/* restore the pin type */
|
||||
auth_info->auth_method = auth_method;
|
||||
|
||||
if (r) {
|
||||
logprintf(pCardData, 1, "PIN code verification failed: %s; tries left %i\n", sc_strerror(r), auth_info->tries_left);
|
||||
|
@ -4841,17 +4892,16 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData,
|
|||
|
||||
/* set the session pin according to the minidriver specification */
|
||||
if (dwFlags == CARD_AUTHENTICATE_GENERATE_SESSION_PIN
|
||||
&& pcbSessionPin && *pcbSessionPin == 0
|
||||
&& (vs->reader->capabilities & SC_READER_CAP_PIN_PAD
|
||||
|| vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) {
|
||||
/* we set it to a special value for pinpad authentication to force a new pinpad authentication */
|
||||
if (pcbSessionPin) *pcbSessionPin = sizeof(MAGIC_SESSION_PIN);
|
||||
/* If we could not generate a real session PIN, set it to a special
|
||||
* value for pinpad authentication to force a new pinpad authentication */
|
||||
*pcbSessionPin = sizeof(MAGIC_SESSION_PIN);
|
||||
if (ppbSessionPin) {
|
||||
*ppbSessionPin = pCardData->pfnCspAlloc(sizeof(MAGIC_SESSION_PIN));
|
||||
if (ppbSessionPin) memcpy(*ppbSessionPin, MAGIC_SESSION_PIN, sizeof(MAGIC_SESSION_PIN));
|
||||
}
|
||||
} else {
|
||||
if (pcbSessionPin) *pcbSessionPin = 0;
|
||||
if (ppbSessionPin) *ppbSessionPin = NULL;
|
||||
}
|
||||
|
||||
return SCARD_S_SUCCESS;
|
||||
|
@ -4945,7 +4995,7 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData,
|
|||
(*pcAttemptsRemaining) = (DWORD) -1;
|
||||
|
||||
rv = md_dialog_perform_pin_operation(pCardData, (dwFlags & PIN_CHANGE_FLAG_UNBLOCK ? SC_PIN_CMD_UNBLOCK:SC_PIN_CMD_CHANGE),
|
||||
vs->p15card, pin_obj, (const u8 *) pbAuthenticatingPinData, cbAuthenticatingPinData, pbTargetData, cbTargetData, DisplayPinpadUI);
|
||||
vs->p15card, pin_obj, (const u8 *) pbAuthenticatingPinData, cbAuthenticatingPinData, pbTargetData, &cbTargetData, DisplayPinpadUI);
|
||||
|
||||
if (rv) {
|
||||
logprintf(pCardData, 2, "Failed to %s %s PIN: '%s' (%i)\n",
|
||||
|
@ -5261,6 +5311,9 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData,
|
|||
if (cbData < sizeof(*p))
|
||||
return ERROR_INSUFFICIENT_BUFFER;
|
||||
*p = CARD_PIN_STRENGTH_PLAINTEXT;
|
||||
if (vs->p15card->card->caps & SC_CARD_CAP_SESSION_PIN) {
|
||||
*p |= CARD_PIN_STRENGTH_SESSION_PIN;
|
||||
}
|
||||
}
|
||||
else if (wcscmp(CP_KEY_IMPORT_SUPPORT, wszProperty) == 0) {
|
||||
DWORD *p = (DWORD *)pbData;
|
||||
|
|
Loading…
Reference in New Issue