[gnome-keyring] Basic rough implementation of prompting for C_Login



commit 83fff3a4138586368d300da66132dc05c27ff378
Author: Stef Walter <stef memberwebs com>
Date:   Tue Jun 8 03:40:48 2010 +0000

    Basic rough implementation of prompting for C_Login

 pkcs11/wrap-layer/gkm-wrap-layer.c  |  263 +++++++++++++++-------
 pkcs11/wrap-layer/gkm-wrap-prompt.c |  440 +++++++++++++++++++++++++++++------
 pkcs11/wrap-layer/gkm-wrap-prompt.h |   47 ++++-
 3 files changed, 592 insertions(+), 158 deletions(-)
---
diff --git a/pkcs11/wrap-layer/gkm-wrap-layer.c b/pkcs11/wrap-layer/gkm-wrap-layer.c
index 15d4350..5e71bf3 100644
--- a/pkcs11/wrap-layer/gkm-wrap-layer.c
+++ b/pkcs11/wrap-layer/gkm-wrap-layer.c
@@ -43,6 +43,7 @@ typedef struct _Session {
 	CK_SESSION_HANDLE real_session;
 	CK_G_APPLICATION_ID app_id;
 	CK_SLOT_ID wrap_slot;
+	CK_OBJECT_HANDLE specific;
 } Session;
 
 G_LOCK_DEFINE_STATIC (wrap_layer);
@@ -100,7 +101,7 @@ map_slot_to_real (CK_SLOT_ID_PTR slot, Mapping *mapping)
 }
 
 static CK_RV
-map_session_to_real (CK_SESSION_HANDLE_PTR handle, Mapping *mapping)
+map_session_to_real (CK_SESSION_HANDLE_PTR handle, Mapping *mapping, Session *session)
 {
 	CK_RV rv = CKR_OK;
 	Session *sess;
@@ -117,6 +118,8 @@ map_session_to_real (CK_SESSION_HANDLE_PTR handle, Mapping *mapping)
 			if (sess != NULL) {
 				*handle = sess->real_session;
 				rv = map_slot_unlocked (sess->wrap_slot, mapping);
+				if (session != NULL)
+					memcpy (session, sess, sizeof (Session));
 			} else {
 				rv = CKR_SESSION_HANDLE_INVALID;
 			}
@@ -127,21 +130,23 @@ map_session_to_real (CK_SESSION_HANDLE_PTR handle, Mapping *mapping)
 	return rv;
 }
 
-#define MAP_SLOT_UP(slot, map) G_STMT_START { \
-
+static void
+stash_session_specific_key (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE key)
+{
+	Session *sess;
 
+	G_LOCK (wrap_layer);
 
-#define MAP_SLOT_DOWN(slot, map) G_STMT_START { \
-	if (!map_slot_down (&slot, &map)) \
-		return CKR_SLOT_ID_INVALID; \
-	} G_STMT_END
+		if (wrap_sessions) {
+			sess = g_hash_table_lookup (wrap_sessions, GINT_TO_POINTER ((gint)handle));
+			if (sess == NULL)
+				g_warning ("sessions out of sync with lower layer");
+			else
+				sess->specific = key;
+		}
 
-#define MAP_SESSION_DOWN(session, map) G_STMT_START { \
-	CK_SLOT_ID slot = (session >> HANDLE_SLOT_BITS); \
-	if (!map_slot_down (&slot, &map)) \
-		return CKR_SESSION_HANDLE_INVALID; \
-	session &= HANDLE_REAL_MASK; \
-	} G_STMT_END
+	G_UNLOCK (wrap_layer);
+}
 
 static CK_RV
 wrap_C_Initialize (CK_VOID_PTR init_args)
@@ -225,12 +230,15 @@ wrap_C_Initialize (CK_VOID_PTR init_args)
 static CK_RV
 wrap_C_Finalize (CK_VOID_PTR reserved)
 {
-	guint i;
+	CK_FUNCTION_LIST_PTR funcs;
+	GList *l;
 
 	G_LOCK (wrap_layer);
 
-		for (i = 0; i < n_wrap_mappings; ++i)
-			(wrap_mappings[i].funcs->C_Finalize) (NULL);
+		for (l = wrap_modules; l != NULL; l = g_list_next (l)) {
+			funcs = l->data;
+			(funcs->C_Finalize) (NULL);
+		}
 		g_free (wrap_mappings);
 		wrap_mappings = NULL;
 
@@ -336,7 +344,10 @@ wrap_C_GetTokenInfo (CK_SLOT_ID id, CK_TOKEN_INFO_PTR info)
 	rv = map_slot_to_real (&id, &map);
 	if (rv != CKR_OK)
 		return rv;
-	return (map.funcs->C_GetTokenInfo) (id, info);
+	rv = (map.funcs->C_GetTokenInfo) (id, info);
+	if (rv == CKR_OK)
+		info->flags |= CKF_PROTECTED_AUTHENTICATION_PATH;
+	return rv;
 }
 
 static CK_RV
@@ -424,7 +435,7 @@ wrap_C_CloseSession (CK_SESSION_HANDLE handle)
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	rv = (map.funcs->C_CloseSession) (handle);
@@ -478,7 +489,7 @@ wrap_C_GetFunctionStatus (CK_SESSION_HANDLE handle)
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_GetFunctionStatus) (handle);
@@ -490,7 +501,7 @@ wrap_C_CancelFunction (CK_SESSION_HANDLE handle)
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_CancelFunction) (handle);
@@ -505,7 +516,7 @@ wrap_C_GetSessionInfo (CK_SESSION_HANDLE handle, CK_SESSION_INFO_PTR info)
 	if (info == NULL)
 		return CKR_ARGUMENTS_BAD;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 
@@ -519,25 +530,70 @@ wrap_C_GetSessionInfo (CK_SESSION_HANDLE handle, CK_SESSION_INFO_PTR info)
 static CK_RV
 wrap_C_InitPIN (CK_SESSION_HANDLE handle, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
 {
+#if 0
+	GkmWrapPrompt *prompt;
+#endif
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
-	return (map.funcs->C_InitPIN) (handle, pin, pin_len);
+#if 0
+	prompt = gkm_wrap_prompt_for_init_pin (map.funcs, handle, pin, pin_len);
+
+	for (;;) {
+		if (prompt && !gkm_wrap_prompt_do_init_pin (prompt, rv, &pin, &pin_len))
+			break;
+#endif
+		rv = (map.funcs->C_InitPIN) (handle, pin, pin_len);
+#if 0
+		if (!prompt || rv != CKR_PIN_INVALID || rv != CKR_PIN_LEN_RANGE)
+			break;
+	}
+
+	if (prompt) {
+		gkm_wrap_prompt_done_init_pin (prompt, rv);
+		g_object_unref (prompt);
+	}
+#endif
+	return rv;
 }
 
 static CK_RV
 wrap_C_SetPIN (CK_SESSION_HANDLE handle, CK_UTF8CHAR_PTR old_pin, CK_ULONG old_pin_len, CK_UTF8CHAR_PTR new_pin, CK_ULONG new_pin_len)
 {
+#if 0
+	GkmWrapPrompt *prompt;
+#endif
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
-	return (map.funcs->C_SetPIN) (handle, old_pin, old_pin_len, new_pin, new_pin_len);
+#if 0
+	prompt = gkm_wrap_prompt_for_set_pin (map.funcs, handle,
+	                                      old_pin, old_pin_len,
+	                                      new_pin, new_pin_len);
+
+	for (;;) {
+		if (prompt && !gkm_wrap_prompt_do_set_pin (prompt, rv, &old_pin, &old_pin_len,
+		                                           &new_pin, &new_pin_len))
+			break;
+#endif
+		rv = (map.funcs->C_SetPIN) (handle, old_pin, old_pin_len, new_pin, new_pin_len);
+#if 0
+		if (!prompt || rv != CKR_PIN_INVALID || rv != CKR_PIN_LEN_RANGE)
+			break;
+	}
+
+	if (prompt) {
+		gkm_wrap_prompt_done_set_pin (prompt, rv);
+		g_object_unref (prompt);
+	}
+#endif
+	return rv;
 }
 
 static CK_RV
@@ -546,7 +602,7 @@ wrap_C_GetOperationState (CK_SESSION_HANDLE handle, CK_BYTE_PTR operation_state,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_GetOperationState) (handle, operation_state, operation_state_len);
@@ -560,7 +616,7 @@ wrap_C_SetOperationState (CK_SESSION_HANDLE handle, CK_BYTE_PTR operation_state,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_SetOperationState) (handle, operation_state, operation_state_len, encryption_key, authentication_key);
@@ -570,13 +626,33 @@ static CK_RV
 wrap_C_Login (CK_SESSION_HANDLE handle, CK_USER_TYPE user_type,
               CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
 {
+	GkmWrapPrompt *prompt;
+	Session session;
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, &session);
 	if (rv != CKR_OK)
 		return rv;
-	return (map.funcs->C_Login) (handle, user_type, pin, pin_len);
+
+	prompt = gkm_wrap_prompt_for_login (map.funcs, user_type, handle, session.specific, pin, pin_len);
+
+	for (;;) {
+		rv = (map.funcs->C_Login) (handle, user_type, pin, pin_len);
+
+		if (!prompt || rv != CKR_PIN_INCORRECT)
+			break;
+
+		if (!gkm_wrap_prompt_do_login (prompt, user_type, rv, &pin, &pin_len))
+			break;
+	}
+
+	if (prompt) {
+		gkm_wrap_prompt_done_login (prompt, user_type, rv);
+		g_object_unref (prompt);
+	}
+
+	return rv;
 }
 
 static CK_RV
@@ -585,7 +661,7 @@ wrap_C_Logout (CK_SESSION_HANDLE handle)
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_Logout) (handle);
@@ -599,7 +675,7 @@ wrap_C_CreateObject (CK_SESSION_HANDLE handle, CK_ATTRIBUTE_PTR template,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 
@@ -636,7 +712,7 @@ wrap_C_CopyObject (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_CopyObject) (handle, object, template, count, new_object);
@@ -648,7 +724,7 @@ wrap_C_DestroyObject (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object)
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_DestroyObject) (handle, object);
@@ -661,7 +737,7 @@ wrap_C_GetObjectSize (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_GetObjectSize) (handle, object, size);
@@ -674,7 +750,7 @@ wrap_C_GetAttributeValue (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_GetAttributeValue) (handle, object, template, count);
@@ -687,7 +763,7 @@ wrap_C_SetAttributeValue (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_SetAttributeValue) (handle, object, template, count);
@@ -700,7 +776,7 @@ wrap_C_FindObjectsInit (CK_SESSION_HANDLE handle, CK_ATTRIBUTE_PTR template,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_FindObjectsInit) (handle, template, count);
@@ -713,7 +789,7 @@ wrap_C_FindObjects (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE_PTR objects,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_FindObjects) (handle, objects, max_count, count);
@@ -725,7 +801,7 @@ wrap_C_FindObjectsFinal (CK_SESSION_HANDLE handle)
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_FindObjectsFinal) (handle);
@@ -735,13 +811,17 @@ static CK_RV
 wrap_C_EncryptInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
                     CK_OBJECT_HANDLE key)
 {
+	Session session;
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, &session);
 	if (rv != CKR_OK)
 		return rv;
-	return (map.funcs->C_EncryptInit) (handle, mechanism, key);
+	rv = (map.funcs->C_EncryptInit) (handle, mechanism, key);
+	if (rv == CKR_OK)
+		stash_session_specific_key (session.wrap_session, key);
+	return rv;
 }
 
 static CK_RV
@@ -751,7 +831,7 @@ wrap_C_Encrypt (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_Encrypt) (handle, data, data_len, encrypted_data, encrypted_data_len);
@@ -765,7 +845,7 @@ wrap_C_EncryptUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_EncryptUpdate) (handle, part, part_len, encrypted_part, encrypted_part_len);
@@ -778,7 +858,7 @@ wrap_C_EncryptFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR last_part,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_EncryptFinal) (handle, last_part, last_part_len);
@@ -788,13 +868,17 @@ static CK_RV
 wrap_C_DecryptInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
                     CK_OBJECT_HANDLE key)
 {
+	Session session;
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, &session);
 	if (rv != CKR_OK)
 		return rv;
-	return (map.funcs->C_DecryptInit) (handle, mechanism, key);
+	rv = (map.funcs->C_DecryptInit) (handle, mechanism, key);
+	if (rv == CKR_OK)
+		stash_session_specific_key (session.wrap_session, key);
+	return rv;
 }
 
 static CK_RV
@@ -804,7 +888,7 @@ wrap_C_Decrypt (CK_SESSION_HANDLE handle, CK_BYTE_PTR enc_data,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_Decrypt) (handle, enc_data, enc_data_len, data, data_len);
@@ -817,7 +901,7 @@ wrap_C_DecryptUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR enc_part,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_DecryptUpdate) (handle, enc_part, enc_part_len, part, part_len);
@@ -830,7 +914,7 @@ wrap_C_DecryptFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR last_part,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_DecryptFinal) (handle, last_part, last_part_len);
@@ -842,7 +926,7 @@ wrap_C_DigestInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism)
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_DigestInit) (handle, mechanism);
@@ -855,7 +939,7 @@ wrap_C_Digest (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_Digest) (handle, data, data_len, digest, digest_len);
@@ -867,7 +951,7 @@ wrap_C_DigestUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part, CK_ULONG part_l
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_DigestUpdate) (handle, part, part_len);
@@ -879,7 +963,7 @@ wrap_C_DigestKey (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE key)
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_DigestKey) (handle, key);
@@ -892,7 +976,7 @@ wrap_C_DigestFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR digest,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_DigestFinal) (handle, digest, digest_len);
@@ -902,13 +986,17 @@ static CK_RV
 wrap_C_SignInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
                  CK_OBJECT_HANDLE key)
 {
+	Session session;
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, &session);
 	if (rv != CKR_OK)
 		return rv;
-	return (map.funcs->C_SignInit) (handle, mechanism, key);
+	rv = (map.funcs->C_SignInit) (handle, mechanism, key);
+	if (rv == CKR_OK)
+		stash_session_specific_key (session.wrap_session, key);
+	return rv;
 }
 
 static CK_RV
@@ -918,7 +1006,7 @@ wrap_C_Sign (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_Sign) (handle, data, data_len, signature, signature_len);
@@ -930,7 +1018,7 @@ wrap_C_SignUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part, CK_ULONG part_len
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_SignUpdate) (handle, part, part_len);
@@ -943,7 +1031,7 @@ wrap_C_SignFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR signature,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_SignFinal) (handle, signature, signature_len);
@@ -953,13 +1041,18 @@ static CK_RV
 wrap_C_SignRecoverInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
                         CK_OBJECT_HANDLE key)
 {
+	Session session;
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, &session);
 	if (rv != CKR_OK)
 		return rv;
-	return (map.funcs->C_SignRecoverInit) (handle, mechanism, key);
+	rv = (map.funcs->C_SignRecoverInit) (handle, mechanism, key);
+	if (rv == CKR_OK)
+		stash_session_specific_key (session.wrap_session, key);
+	return rv;
+
 }
 
 static CK_RV
@@ -969,7 +1062,7 @@ wrap_C_SignRecover (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_le
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_SignRecover) (handle, data, data_len, signature, signature_len);
@@ -979,13 +1072,17 @@ static CK_RV
 wrap_C_VerifyInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
                    CK_OBJECT_HANDLE key)
 {
+	Session session;
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, &session);
 	if (rv != CKR_OK)
 		return rv;
-	return (map.funcs->C_VerifyInit) (handle, mechanism, key);
+	rv = (map.funcs->C_VerifyInit) (handle, mechanism, key);
+	if (rv == CKR_OK)
+		stash_session_specific_key (session.wrap_session, key);
+	return rv;
 }
 
 static CK_RV
@@ -995,7 +1092,7 @@ wrap_C_Verify (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_Verify) (handle, data, data_len, signature, signature_len);
@@ -1007,7 +1104,7 @@ wrap_C_VerifyUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part, CK_ULONG part_l
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_VerifyUpdate) (handle, part, part_len);
@@ -1020,7 +1117,7 @@ wrap_C_VerifyFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR signature,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_VerifyFinal) (handle, signature, signature_len);
@@ -1030,13 +1127,17 @@ static CK_RV
 wrap_C_VerifyRecoverInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
                           CK_OBJECT_HANDLE key)
 {
+	Session session;
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, &session);
 	if (rv != CKR_OK)
 		return rv;
-	return (map.funcs->C_VerifyRecoverInit) (handle, mechanism, key);
+	rv = (map.funcs->C_VerifyRecoverInit) (handle, mechanism, key);
+	if (rv == CKR_OK)
+		stash_session_specific_key (session.wrap_session, key);
+	return rv;
 }
 
 static CK_RV
@@ -1046,7 +1147,7 @@ wrap_C_VerifyRecover (CK_SESSION_HANDLE handle, CK_BYTE_PTR signature,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_VerifyRecover) (handle, signature, signature_len, data, data_len);
@@ -1060,7 +1161,7 @@ wrap_C_DigestEncryptUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_DigestEncryptUpdate) (handle, part, part_len, enc_part, enc_part_len);
@@ -1074,7 +1175,7 @@ wrap_C_DecryptDigestUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR enc_part,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_DecryptDigestUpdate) (handle, enc_part, enc_part_len, part, part_len);
@@ -1088,7 +1189,7 @@ wrap_C_SignEncryptUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_SignEncryptUpdate) (handle, part, part_len, enc_part, enc_part_len);
@@ -1102,7 +1203,7 @@ wrap_C_DecryptVerifyUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR enc_part,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_DecryptVerifyUpdate) (handle, enc_part, enc_part_len, part, part_len);
@@ -1116,7 +1217,7 @@ wrap_C_GenerateKey (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_GenerateKey) (handle, mechanism, template, count, key);
@@ -1131,7 +1232,7 @@ wrap_C_GenerateKeyPair (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_GenerateKeyPair) (handle, mechanism, pub_template, pub_count, priv_template, priv_count, pub_key, priv_key);
@@ -1145,7 +1246,7 @@ wrap_C_WrapKey (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_WrapKey) (handle, mechanism, wrapping_key, key, wrapped_key, wrapped_key_len);
@@ -1160,7 +1261,7 @@ wrap_C_UnwrapKey (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_UnwrapKey) (handle, mechanism, unwrapping_key, wrapped_key, wrapped_key_len, template, count, key);
@@ -1174,7 +1275,7 @@ wrap_C_DeriveKey (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_DeriveKey) (handle, mechanism, base_key, template, count, key);
@@ -1186,7 +1287,7 @@ wrap_C_SeedRandom (CK_SESSION_HANDLE handle, CK_BYTE_PTR seed, CK_ULONG seed_len
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_SeedRandom) (handle, seed, seed_len);
@@ -1199,7 +1300,7 @@ wrap_C_GenerateRandom (CK_SESSION_HANDLE handle, CK_BYTE_PTR random_data,
 	Mapping map;
 	CK_RV rv;
 
-	rv = map_session_to_real (&handle, &map);
+	rv = map_session_to_real (&handle, &map, NULL);
 	if (rv != CKR_OK)
 		return rv;
 	return (map.funcs->C_GenerateRandom) (handle, random_data, random_len);
diff --git a/pkcs11/wrap-layer/gkm-wrap-prompt.c b/pkcs11/wrap-layer/gkm-wrap-prompt.c
index cfaa68b..1ba8986 100644
--- a/pkcs11/wrap-layer/gkm-wrap-prompt.c
+++ b/pkcs11/wrap-layer/gkm-wrap-prompt.c
@@ -44,14 +44,19 @@ struct _GkmWrapPrompt {
 	CK_SESSION_HANDLE session;
 	CK_OBJECT_HANDLE object;
 
-	GArray *template;
-	CK_ULONG n_template;
+	gpointer prompt_data;
+	GDestroyNotify destroy_data;
 
-	guint iteration;
-	gchar *password;
 	GQueue pool;
 };
 
+typedef struct _CredentialPrompt {
+	GArray *template;
+	CK_ULONG n_template;
+	gchar *password;
+	guint iteration;
+} CredentialPrompt;
+
 G_DEFINE_TYPE (GkmWrapPrompt, gkm_wrap_prompt, GKU_TYPE_PROMPT);
 
 /* -----------------------------------------------------------------------------
@@ -351,7 +356,7 @@ get_attributes_from_object (GkmWrapPrompt *self, CK_ULONG *n_attrs)
 }
 
 static void
-prepare_unlock_login_keyring (GkmWrapPrompt *self)
+prepare_unlock_keyring_login (GkmWrapPrompt *self)
 {
 	GkuPrompt *prompt;
 	const gchar *text;
@@ -382,7 +387,7 @@ prepare_unlock_login_keyring (GkmWrapPrompt *self)
 
 
 static void
-prepare_unlock_other_keyring (GkmWrapPrompt *self, const gchar *label)
+prepare_unlock_keyring_other (GkmWrapPrompt *self, const gchar *label)
 {
 	GkuPrompt *prompt;
 	gchar *text;
@@ -416,8 +421,58 @@ prepare_unlock_other_keyring (GkmWrapPrompt *self, const gchar *label)
 		gku_prompt_hide_widget (prompt, "auto_unlock_check");
 }
 
+
+static const gchar*
+prepare_unlock_object_title (CK_OBJECT_CLASS klass)
+{
+	switch (klass) {
+	case CKO_PRIVATE_KEY:
+		return _("Unlock private key");
+	case CKO_CERTIFICATE:
+		return _("Unlock certificate");
+	case CKO_PUBLIC_KEY:
+		return _("Unlock public key");
+	default:
+		return _("Unlock");
+	}
+}
+
+static const gchar*
+prepare_unlock_object_primary (CK_OBJECT_CLASS klass)
+{
+	switch (klass) {
+	case CKO_PRIVATE_KEY:
+		return _("Enter password to unlock the private key");
+	case CKO_CERTIFICATE:
+		return _("Enter password to unlock the certificate");
+	case CKO_PUBLIC_KEY:
+		return _("Enter password to unlock the public key");
+	default:
+		return _("Enter password to unlock");
+	}
+}
+
+static gchar*
+prepare_unlock_object_secondary (CK_OBJECT_CLASS klass, const gchar *label)
+{
+	switch (klass) {
+	case CKO_PRIVATE_KEY:
+		/* TRANSLATORS: The private key is locked */
+		return g_strdup_printf (_("An application wants access to the private key '%s', but it is locked"), label);
+	case CKO_CERTIFICATE:
+		/* TRANSLATORS: The certificate is locked */
+		return g_strdup_printf (_("An application wants access to the certificate '%s', but it is locked"), label);
+	case CKO_PUBLIC_KEY:
+		/* TRANSLATORS: The public key is locked */
+		return g_strdup_printf (_("An application wants access to the public key '%s', but it is locked"), label);
+	default:
+		/* TRANSLATORS: The object '%s' is locked */
+		return g_strdup_printf (_("An application wants access to '%s', but it is locked"), label);
+	}
+}
+
 static void
-prepare_unlock_other_object (GkmWrapPrompt *self, const gchar *label)
+prepare_unlock_object (GkmWrapPrompt *self, const gchar *label, CK_OBJECT_CLASS klass)
 {
 	GkuPrompt *prompt;
 	gchar *text;
@@ -426,13 +481,10 @@ prepare_unlock_other_object (GkmWrapPrompt *self, const gchar *label)
 
 	prompt = GKU_PROMPT (self);
 
-	gku_prompt_set_title (prompt, _("Unlock"));
+	gku_prompt_set_title (prompt, prepare_unlock_object_title (klass));
+	gku_prompt_set_primary_text (prompt, prepare_unlock_object_primary (klass));
 
-	text = g_markup_printf_escaped (_("Enter password for '%s' to unlock"), label);
-	gku_prompt_set_primary_text (prompt, text);
-	g_free (text);
-
-	text = g_markup_printf_escaped (_("An application wants access to '%s', but it is locked"), label);
+	text = prepare_unlock_object_secondary (klass, label);
 	gku_prompt_set_secondary_text (prompt, text);
 	g_free (text);
 
@@ -486,18 +538,55 @@ prepare_unlock_prompt (GkmWrapPrompt *self, gboolean first)
 	if (klass == CKO_G_COLLECTION) {
 		if (attr && attr->pValue && attr->ulValueLen == 5 &&
 		    memcmp (attr->pValue, "login", 5)) {
-			prepare_unlock_login_keyring (self);
+			prepare_unlock_keyring_login (self);
 		} else {
-			prepare_unlock_other_keyring (self, label);
+			prepare_unlock_keyring_other (self, label);
 		}
 	} else {
-		prepare_unlock_other_object (self, label);
+		prepare_unlock_object (self, label, klass);
 	}
 
 	if (!first)
 		gku_prompt_set_warning (GKU_PROMPT (self), _("The unlock password was incorrect"));
 }
 
+static void
+prepare_unlock_token (GkmWrapPrompt *self, CK_TOKEN_INFO_PTR tinfo)
+{
+	GkuPrompt *prompt;
+	gchar *label;
+	gchar *text;
+
+	g_assert (GKM_WRAP_IS_PROMPT (self));
+
+	prompt = GKU_PROMPT (self);
+
+	label = g_strndup ((gchar*)tinfo->label, sizeof (tinfo->label));
+	g_strchomp (label);
+
+	/* Build up the prompt */
+	gku_prompt_show_widget (prompt, "password_area");
+	gku_prompt_hide_widget (prompt, "confirm_area");
+	gku_prompt_hide_widget (prompt, "original_area");
+	gku_prompt_set_title (prompt, _("Unlock certificate/key storage"));
+	gku_prompt_set_primary_text (prompt, _("Enter password to unlock the certificate/key storage"));
+
+	/* TRANSLATORS: The storage is locked, and needs unlocking before the application can use it. */
+	text = g_strdup_printf (_("An application wants access to the certificate/key storage '%s', but it is locked"), label);
+	gku_prompt_set_secondary_text (prompt, text);
+	g_free (text);
+
+#if 0
+	if (gkd_login_is_usable ()) {
+		gku_prompt_show_widget (prompt, "details_area");
+		gku_prompt_show_widget (prompt, "lock_area");
+		gku_prompt_hide_widget (prompt, "options_area");
+	}
+#endif
+
+	g_free (label);
+}
+
 /* -----------------------------------------------------------------------------
  * OBJECT
  */
@@ -508,74 +597,49 @@ gkm_wrap_prompt_init (GkmWrapPrompt *self)
 	g_queue_init (&self->pool);
 }
 
-#if 0
-static void
-gkm_wrap_prompt_dispose (GObject *obj)
-{
-	GkmWrapPrompt *self = GKM_WRAP_PROMPT (obj);
-
-	G_OBJECT_CLASS (gkm_wrap_prompt_parent_class)->dispose (obj);
-}
-#endif
-
 static void
 gkm_wrap_prompt_finalize (GObject *obj)
 {
 	GkmWrapPrompt *self = GKM_WRAP_PROMPT (obj);
 
-	egg_secure_strfree (self->password);
+	if (self->destroy_data && self->prompt_data)
+		(self->destroy_data) (self->prompt_data);
+	self->destroy_data = NULL;
+	self->prompt_data = NULL;
 
 	while (!g_queue_is_empty(&self->pool))
 		g_free (g_queue_pop_head (&self->pool));
 
-	g_array_free (self->template, TRUE);
 
 	G_OBJECT_CLASS (gkm_wrap_prompt_parent_class)->finalize (obj);
 }
 
-static void
-gkm_wrap_prompt_set_property (GObject *obj, guint prop_id, const GValue *value,
-                                GParamSpec *pspec)
-{
-	switch (prop_id) {
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-gkm_wrap_prompt_get_property (GObject *obj, guint prop_id, GValue *value,
-                                GParamSpec *pspec)
-{
-	switch (prop_id) {
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
-		break;
-	}
-}
 
 static void
 gkm_wrap_prompt_class_init (GkmWrapPromptClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-#if 0
-	gobject_class->dispose = gkm_wrap_prompt_dispose;
-#endif
 	gobject_class->finalize = gkm_wrap_prompt_finalize;
-	gobject_class->set_property = gkm_wrap_prompt_set_property;
-	gobject_class->get_property = gkm_wrap_prompt_get_property;
 }
 
 /* -----------------------------------------------------------------------------
- * PUBLIC
+ * CREDENTIAL
  */
 
+static void
+credential_prompt_free (gpointer user_data)
+{
+	CredentialPrompt *data = user_data;
+	egg_secure_strfree (data->password);
+	g_array_free (data->template, TRUE);
+	g_slice_free (CredentialPrompt, data);
+}
+
 GkmWrapPrompt*
 gkm_wrap_prompt_for_credential (CK_FUNCTION_LIST_PTR module, CK_SESSION_HANDLE session,
                                 CK_ATTRIBUTE_PTR template, CK_ULONG n_template)
 {
+	CredentialPrompt *data;
 	CK_ATTRIBUTE_PTR attr;
 	CK_ATTRIBUTE_PTR options;
 	CK_ULONG n_options, i;
@@ -600,19 +664,21 @@ gkm_wrap_prompt_for_credential (CK_FUNCTION_LIST_PTR module, CK_SESSION_HANDLE s
 
 	/* Build up the prompt */
 	self = g_object_new (GKM_WRAP_TYPE_PROMPT, NULL);
-	self->object = object;
+	self->prompt_data = data = g_slice_new0 (CredentialPrompt);
+	self->destroy_data = credential_prompt_free;
 	self->module = module;
 	self->session = session;
+	self->object = object;
 
 	/* Build up a copy of the template with CKA_VALUE first */
-	self->template = g_array_new (FALSE, FALSE, sizeof (CK_ATTRIBUTE));
-	g_array_append_val (self->template, *attr);
+	data->template = g_array_new (FALSE, FALSE, sizeof (CK_ATTRIBUTE));
+	g_array_append_val (data->template, *attr);
 	for (i = 0; i < n_template; ++i) {
 		if (template[i].type != CKA_VALUE)
-			g_array_append_val (self->template, template[i]);
+			g_array_append_val (data->template, template[i]);
 	}
 
-	self->n_template = n_template;
+	data->n_template = n_template;
 
 	/* Now load up the unlock options into the prompt*/
 	options = get_unlock_options_from_object (self, &n_options);
@@ -629,13 +695,17 @@ gkm_wrap_prompt_do_credential (GkmWrapPrompt *self, CK_ATTRIBUTE_PTR *template,
 	CK_ATTRIBUTE_PTR options;
 	CK_ATTRIBUTE_PTR attr;
 	CK_ULONG n_options, i;
+	CredentialPrompt *data;
 
 	g_return_val_if_fail (GKM_WRAP_IS_PROMPT (self), FALSE);
 	g_return_val_if_fail (template, FALSE);
 	g_return_val_if_fail (n_template, FALSE);
 
-	prepare_unlock_prompt (self, self->iteration == 0);
-	++(self->iteration);
+	g_assert (self->destroy_data == credential_prompt_free);
+	data = self->prompt_data;
+
+	prepare_unlock_prompt (self, data->iteration == 0);
+	++(data->iteration);
 
 	gku_prompt_request_attention_sync (NULL, on_prompt_attention,
 	                                   g_object_ref (self), g_object_unref);
@@ -643,28 +713,28 @@ gkm_wrap_prompt_do_credential (GkmWrapPrompt *self, CK_ATTRIBUTE_PTR *template,
 	if (gku_prompt_get_response (GKU_PROMPT (self)) != GKU_RESPONSE_OK)
 		return FALSE;
 
-	egg_secure_strfree (self->password);
-	self->password = gku_prompt_get_password (GKU_PROMPT (self), "password");
-	g_return_val_if_fail (self->password, FALSE);
+	egg_secure_strfree (data->password);
+	data->password = gku_prompt_get_password (GKU_PROMPT (self), "password");
+	g_return_val_if_fail (data->password, FALSE);
 
 	/* Truncate any extra options off the end of template */
-	g_assert (self->n_template > 0);
-	g_assert (self->template->len >= self->n_template);
-	g_array_set_size (self->template, self->n_template);
+	g_assert (data->n_template > 0);
+	g_assert (data->template->len >= data->n_template);
+	g_array_set_size (data->template, data->n_template);
 
 	/* Put the password into the template, always first */
-	attr = &g_array_index (self->template, CK_ATTRIBUTE, 0);
+	attr = &g_array_index (data->template, CK_ATTRIBUTE, 0);
 	g_assert (attr->type == CKA_VALUE);
-	attr->pValue = self->password;
-	attr->ulValueLen = strlen (self->password);
+	attr->pValue = data->password;
+	attr->ulValueLen = strlen (data->password);
 
 	/* Tag any options onto the end of template */
 	options = get_unlock_options_from_prompt (self, &n_options);
 	for (i = 0; options && i < n_options; ++i)
-		g_array_append_val (self->template, options[i]);
+		g_array_append_val (data->template, options[i]);
 
-	*template = (CK_ATTRIBUTE_PTR)self->template->data;
-	*n_template = self->template->len;
+	*template = (CK_ATTRIBUTE_PTR)data->template->data;
+	*n_template = data->template->len;
 	return TRUE;
 }
 
@@ -692,3 +762,223 @@ gkm_wrap_prompt_done_credential (GkmWrapPrompt *self, CK_RV call_result)
 		/* TODO: Implement removal from login keyring */
 	}
 }
+
+#if 0
+GkmWrapPrompt*
+gkm_wrap_prompt_for_init_pin (CK_FUNCTION_LIST_PTR module, CK_SESSION_HANDLE session,
+                              CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
+{
+
+}
+
+gboolean
+gkm_wrap_prompt_do_init_pin (GkmWrapPrompt *prompt, CK_RV last_result,
+                             CK_UTF8CHAR_PTR *pin, CK_ULONG *n_pin)
+{
+
+}
+
+void
+gkm_wrap_prompt_done_init_pin (GkmWrapPrompt *prompt, CK_RV call_result)
+{
+
+}
+
+GkmWrapPrompt*
+gkm_wrap_prompt_for_set_pin (CK_FUNCTION_LIST_PTR module, CK_SESSION_HANDLE session,
+                             CK_UTF8CHAR_PTR old_pin, CK_ULONG n_old_pin,
+                             CK_UTF8CHAR_PTR new_pin, CK_ULONG n_new_pin)
+{
+
+}
+
+gboolean
+gkm_wrap_prompt_do_set_pin (GkmWrapPrompt *prompt, CK_RV last_result,
+                            CK_UTF8CHAR_PTR *old_pin, CK_ULONG *n_old_pin,
+                            CK_UTF8CHAR_PTR *new_pin, CK_ULONG *n_new_pin)
+{
+
+}
+
+void
+gkm_wrap_prompt_done_set_pin (GkmWrapPrompt *prompt, CK_RV call_result)
+{
+
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ * LOGIN
+ */
+
+static GkmWrapPrompt*
+login_prompt_for_specific (CK_FUNCTION_LIST_PTR module, CK_SESSION_HANDLE session,
+                           CK_OBJECT_HANDLE object)
+{
+	GkmWrapPrompt *self;
+	CK_ATTRIBUTE attr;
+	CK_BBOOL always;
+	CK_RV rv;
+
+	g_assert (module);
+
+	if (object == 0)
+		return NULL;
+
+	/* Find out if the object is CKA_ALWAYS_AUTHENTICATE */
+	always = CK_FALSE;
+	attr.type = CKA_ALWAYS_AUTHENTICATE;
+	attr.pValue = &always;
+	attr.ulValueLen = sizeof (always);
+
+	rv = (module->C_GetAttributeValue) (session, object, &attr, 1);
+	if (rv != CKR_OK || always != CK_TRUE)
+		return NULL;
+
+	/* Build up the prompt */
+	self = g_object_new (GKM_WRAP_TYPE_PROMPT, NULL);
+	self->module = module;
+	self->session = session;
+	self->object = object;
+	self->destroy_data = (GDestroyNotify)egg_secure_strfree;
+
+	return self;
+}
+
+static gboolean
+login_prompt_do_specific (GkmWrapPrompt *self, CK_RV last_result,
+                          CK_UTF8CHAR_PTR *pin, CK_ULONG *n_pin)
+{
+	g_assert (GKM_WRAP_IS_PROMPT (self));
+	g_assert (pin);
+	g_assert (n_pin);
+
+	prepare_unlock_prompt (self, *pin == NULL);
+
+	gku_prompt_request_attention_sync (NULL, on_prompt_attention,
+	                                   g_object_ref (self), g_object_unref);
+
+	if (gku_prompt_get_response (GKU_PROMPT (self)) != GKU_RESPONSE_OK)
+		return FALSE;
+
+	g_assert (self->destroy_data == (GDestroyNotify)egg_secure_strfree);
+	egg_secure_strfree (self->prompt_data);
+
+	self->prompt_data = gku_prompt_get_password (GKU_PROMPT (self), "password");
+	g_return_val_if_fail (self->prompt_data, FALSE);
+
+	*pin = self->prompt_data;
+	*n_pin = strlen (self->prompt_data);
+	return TRUE;
+}
+
+static GkmWrapPrompt*
+login_prompt_for_user (CK_FUNCTION_LIST_PTR module, CK_SESSION_HANDLE session)
+{
+	GkmWrapPrompt *self;
+
+	g_assert (module);
+
+	/* Build up the prompt */
+	self = g_object_new (GKM_WRAP_TYPE_PROMPT, NULL);
+	self->module = module;
+	self->session = session;
+	self->destroy_data = (GDestroyNotify)egg_secure_strfree;
+
+	return self;
+}
+
+static gboolean
+login_prompt_do_user (GkmWrapPrompt *self, CK_RV last_result,
+                       CK_UTF8CHAR_PTR *pin, CK_ULONG *n_pin)
+{
+	CK_SESSION_INFO sinfo;
+	CK_TOKEN_INFO tinfo;
+	CK_RV rv;
+
+	g_assert (GKM_WRAP_IS_PROMPT (self));
+	g_assert (self->module);
+	g_assert (pin);
+	g_assert (n_pin);
+
+	rv = (self->module->C_GetSessionInfo) (self->session, &sinfo);
+	if (rv != CKR_OK)
+		return FALSE;
+
+	rv = (self->module->C_GetTokenInfo) (sinfo.slotID, &tinfo);
+	if (rv != CKR_OK)
+		return FALSE;
+
+	prepare_unlock_token (self, &tinfo);
+
+	gku_prompt_request_attention_sync (NULL, on_prompt_attention,
+	                                   g_object_ref (self), g_object_unref);
+
+	if (gku_prompt_get_response (GKU_PROMPT (self)) != GKU_RESPONSE_OK)
+		return FALSE;
+
+	g_assert (self->destroy_data == (GDestroyNotify)egg_secure_strfree);
+	egg_secure_strfree (self->prompt_data);
+
+	self->prompt_data = gku_prompt_get_password (GKU_PROMPT (self), "password");
+	g_return_val_if_fail (self->prompt_data, FALSE);
+
+	*pin = self->prompt_data;
+	*n_pin = strlen (self->prompt_data);
+	return TRUE;
+}
+
+GkmWrapPrompt*
+gkm_wrap_prompt_for_login (CK_FUNCTION_LIST_PTR module, CK_USER_TYPE user_type,
+                           CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object,
+                           CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
+{
+	g_return_val_if_fail (module, NULL);
+
+	if (pin != NULL || n_pin != 0)
+		return NULL;
+
+	switch (user_type) {
+	case CKU_CONTEXT_SPECIFIC:
+		return login_prompt_for_specific (module, session, object);
+	case CKU_USER:
+		return login_prompt_for_user (module, session);
+	default:
+		return NULL;
+	}
+}
+
+gboolean
+gkm_wrap_prompt_do_login (GkmWrapPrompt *self, CK_USER_TYPE user_type, CK_RV last_result,
+                          CK_UTF8CHAR_PTR *pin, CK_ULONG *n_pin)
+{
+	g_return_val_if_fail (GKM_WRAP_IS_PROMPT (self), FALSE);
+	g_return_val_if_fail (pin, FALSE);
+	g_return_val_if_fail (n_pin, FALSE);
+
+	switch (user_type) {
+	case CKU_CONTEXT_SPECIFIC:
+		return login_prompt_do_specific (self, last_result, pin, n_pin);
+	case CKU_USER:
+		return login_prompt_do_user (self, last_result, pin, n_pin);
+	default:
+		return FALSE;
+	}
+}
+
+void
+gkm_wrap_prompt_done_login (GkmWrapPrompt *self, CK_USER_TYPE user_type, CK_RV call_result)
+{
+	g_return_if_fail (GKM_WRAP_IS_PROMPT (self));
+
+#if 0
+	switch (user_type) {
+	case CKU_CONTEXT_SPECIFIC:
+		login_prompt_done_specific (self, call_result);
+		break;
+	case CKU_USER:
+		login_prompt_done_user (self, call_result);
+		break;
+	}
+#endif
+}
diff --git a/pkcs11/wrap-layer/gkm-wrap-prompt.h b/pkcs11/wrap-layer/gkm-wrap-prompt.h
index 855ce89..8e8c0e7 100644
--- a/pkcs11/wrap-layer/gkm-wrap-prompt.h
+++ b/pkcs11/wrap-layer/gkm-wrap-prompt.h
@@ -55,9 +55,52 @@ void                gkm_wrap_prompt_done_credential         (GkmWrapPrompt *self
                                                              CK_RV call_result);
 
 #if 0
-void                gkm_wrap_prompt_complete                (GkmWrapPrompt *self);
+GkmWrapPrompt*      gkm_wrap_prompt_for_init_pin            (CK_FUNCTION_LIST_PTR module,
+                                                             CK_SESSION_HANDLE session,
+                                                             CK_UTF8CHAR_PTR pin,
+                                                             CK_ULONG pin_len);
+
+gboolean            gkm_wrap_prompt_do_init_pin             (GkmWrapPrompt *prompt,
+                                                             CK_RV last_result,
+                                                             CK_UTF8CHAR_PTR *pin,
+                                                             CK_ULONG *n_pin);
+
+void                gkm_wrap_prompt_done_init_pin           (GkmWrapPrompt *prompt,
+                                                             CK_RV call_result);
+
+GkmWrapPrompt*      gkm_wrap_prompt_for_set_pin             (CK_FUNCTION_LIST_PTR module,
+                                                             CK_SESSION_HANDLE session,
+                                                             CK_UTF8CHAR_PTR old_pin,
+                                                             CK_ULONG n_old_pin,
+                                                             CK_UTF8CHAR_PTR new_pin,
+                                                             CK_ULONG n_new_pin);
+
+gboolean            gkm_wrap_prompt_do_set_pin              (GkmWrapPrompt *prompt,
+                                                             CK_RV last_result,
+                                                             CK_UTF8CHAR_PTR *old_pin,
+                                                             CK_ULONG *n_old_pin,
+                                                             CK_UTF8CHAR_PTR *new_pin,
+                                                             CK_ULONG *n_new_pin);
 
-void                gkm_wrap_prompt_dismiss                 (GkmWrapPrompt *self);
+void                gkm_wrap_prompt_done_set_pin            (GkmWrapPrompt *prompt,
+                                                             CK_RV call_result);
 #endif
 
+GkmWrapPrompt*      gkm_wrap_prompt_for_login               (CK_FUNCTION_LIST_PTR module,
+                                                             CK_USER_TYPE user_type,
+                                                             CK_SESSION_HANDLE session,
+                                                             CK_OBJECT_HANDLE object,
+                                                             CK_UTF8CHAR_PTR pin,
+                                                             CK_ULONG n_pin);
+
+gboolean            gkm_wrap_prompt_do_login                (GkmWrapPrompt *prompt,
+                                                             CK_USER_TYPE user_type,
+                                                             CK_RV last_result,
+                                                             CK_UTF8CHAR_PTR *pin,
+                                                             CK_ULONG *n_pin);
+
+void                gkm_wrap_prompt_done_login              (GkmWrapPrompt *prompt,
+                                                             CK_USER_TYPE user_type,
+                                                             CK_RV call_result);
+
 #endif /* __GKM_WRAP_PROMPT_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]