On Tue, 10 Nov 2009 18:48:21 +0100
Pierre Ossman <oss...@cendio.se> wrote:

> I'm looking at implementing support for unblocking a locked PIN in my
> application, but looking at OpenSC that doesn't seem to be possible. In
> fact, there are a number of issues along the way.
> 

I've had another look at this and implemented a somewhat ugly hack to
provide this functionality. Basically C_Login will return success for
CKU_SO if it can't find an auth object and then rely on the PIN cache
in C_InitPIN.

Comment away!

-- 
Pierre Ossman            OpenSource-based Thin Client Technology
System Developer         Telephone: +46-13-21 46 00
Cendio AB                Web: http://www.cendio.com
Index: src/pkcs11/framework-pkcs15.c
===================================================================
--- src/pkcs11/framework-pkcs15.c	(revision 18564)
+++ src/pkcs11/framework-pkcs15.c	(working copy)
@@ -907,13 +907,18 @@
 		/* A card with no SO PIN is treated as if no SO login
 		 * is required */
 		rc = sc_pkcs15_find_so_pin(card, &auth_object);
-
-		/* If there's no SO PIN on the card, silently
-		 * accept any PIN, and lock the card if required */
-		if (rc == SC_ERROR_OBJECT_NOT_FOUND
-		 && sc_pkcs11_conf.lock_login)
+		if (rc == SC_ERROR_OBJECT_NOT_FOUND) {
+			/* Need to lock the card though */
 			rc = lock_card(fw_data);
-		if (rc < 0)
+			if (rc < 0) {
+				 return sc_to_cryptoki_error(rc,
+						 p11card->reader);
+			}
+			/* And cache the PIN as init_pin might need it */
+			cache_pin(fw_token, userType, NULL, pPin, ulPinLen);
+			return CKR_OK;
+		}
+		else if (rc < 0)
 			return sc_to_cryptoki_error(rc, p11card->reader);
 		break;
 	default:
@@ -1006,11 +1011,11 @@
 	return sc_to_cryptoki_error(rc, p11card->reader);
 }
 
-#ifdef USE_PKCS15_INIT
-static CK_RV pkcs15_init_pin(struct sc_pkcs11_card *p11card,
+static CK_RV pkcs15_create_pin(struct sc_pkcs11_card *p11card,
 			struct sc_pkcs11_slot *slot,
 			CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
 {
+#ifdef USE_PKCS15_INIT
 	struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
 	struct sc_pkcs15init_pinargs args;
 	struct sc_profile	*profile;
@@ -1052,8 +1057,52 @@
 	cache_pin(slot->fw_data, CKU_USER, &pin_info->path, pPin, ulPinLen);
 
 	return CKR_OK;
+#else
+	return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
 }
 
+static CK_RV pkcs15_init_pin(struct sc_pkcs11_card *p11card,
+			struct sc_pkcs11_slot *slot,
+			CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
+{
+	struct pkcs15_fw_data *fw_data;
+	struct pkcs15_slot_data *slot_data;
+	struct sc_pkcs15_pin_info *pin;
+	int			rc;
+
+	fw_data = (struct pkcs15_fw_data *)p11card->fw_data;
+	slot_data = (struct pkcs15_slot_data *)slot->fw_data;
+
+	pin = slot_data_pin_info(slot_data);
+
+	/* If we don't have a PIN then we want to create it */
+	if (!pin) {
+		sc_debug(context, "No PIN found. Attempting to create one...\n");
+		return pkcs15_create_pin(p11card, slot, pPin, ulPinLen);
+	}
+
+	/* Otherwise we want to reset the one we have */
+
+	if (ulPinLen < pin->min_length ||
+	    ulPinLen > pin->max_length)
+		return CKR_PIN_LEN_RANGE;
+
+	/* This assumes that either:
+	 * (a) We have a cached SO PIN
+	 * (b) We have previously logged in as CKU_SO and the card
+	 *     will therefore accept the unblock request. */
+	rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin,
+				   slot_data->pin[CKU_SO].value,
+				   slot_data->pin[CKU_SO].len,
+				   pPin, ulPinLen);
+	if (rc < 0)
+		return sc_to_cryptoki_error(rc, p11card->reader);
+
+	return CKR_OK;
+}
+
+#ifdef USE_PKCS15_INIT
 static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card,
 		struct sc_pkcs11_slot *slot,
 		struct sc_profile *profile,
@@ -1690,14 +1739,13 @@
 	pkcs15_logout,
 	pkcs15_change_pin,
 	NULL,			/* init_token */
+	pkcs15_init_pin,
 #ifdef USE_PKCS15_INIT
-	pkcs15_init_pin,
 	pkcs15_create_object,
 	pkcs15_gen_keypair,
 #else
 	NULL,
 	NULL,
-	NULL,
 #endif
 	NULL,			/* seed_random */
 	pkcs15_get_random

Attachment: signature.asc
Description: PGP signature

_______________________________________________
opensc-devel mailing list
opensc-devel@lists.opensc-project.org
http://www.opensc-project.org/mailman/listinfo/opensc-devel

Reply via email to