[pkg-opensc-commit] [opensc] 257/295: minidriver: added support for session pin

Eric Dorland eric at moszumanska.debian.org
Sat Jun 24 21:11:38 UTC 2017


This is an automated email from the git hooks/post-receive script.

eric pushed a commit to branch master
in repository opensc.

commit 7c3bb44cdf3b4b287182a443a348e5ec92d5da39
Author: Frank Morgner <frankmorgner at gmail.com>
Date:   Wed Mar 1 17:53:44 2017 +0100

    minidriver: added support for session pin
---
 src/libopensc/libopensc.exports |  1 +
 src/libopensc/pkcs15-pin.c      | 40 +++++++++++++++++++-
 src/libopensc/pkcs15.h          |  4 ++
 src/minidriver/minidriver.c     | 83 +++++++++++++++++++++++++++++++++--------
 4 files changed, 112 insertions(+), 16 deletions(-)

diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports
index 18f8037..70e1505 100644
--- a/src/libopensc/libopensc.exports
+++ b/src/libopensc/libopensc.exports
@@ -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
diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c
index 28a39b7..1c7df89 100644
--- a/src/libopensc/pkcs15-pin.c
+++ b/src/libopensc/pkcs15-pin.c
@@ -331,6 +331,22 @@ 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;
 	int r;
@@ -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);
diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h
index 1746cd3..5352f9f 100644
--- a/src/libopensc/pkcs15.h
+++ b/src/libopensc/pkcs15.h
@@ -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,
diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c
index 34b1288..0e6ab78 100644
--- a/src/minidriver/minidriver.c
+++ b/src/minidriver/minidriver.c
@@ -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;
+		}
+	}
+
+	/* 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);
 	}
 
-	r = md_dialog_perform_pin_operation(pCardData, SC_PIN_CMD_VERIFY, vs->p15card, pin_obj, (const u8 *) pbPinData, cbPinData, NULL, 0, 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;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-opensc/opensc.git



More information about the pkg-opensc-commit mailing list