minidriver: added support for session pin

This commit is contained in:
Frank Morgner 2017-03-01 17:53:44 +01:00
parent 74ec7b04ff
commit 7c3bb44cdf
4 changed files with 112 additions and 16 deletions

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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;