From a8d0dfac3170e3cd92f964c8a51c61a15c96b20d Mon Sep 17 00:00:00 2001
From: Fredrik Thulin <fredrik@thulin.net>
Date: Mon, 21 Jan 2013 13:21:06 +0100
Subject: [PATCH] C_InitToken: label is not NULL terminated

PKCS#11 v2.2 is very clear that the 'label' argument provided to
C_InitToken is *not* necessarily NULL-terminated, but rather of
fixed size (32 bytes) and whitespace-padded.
---
 gck-rpc-dispatch.c | 34 +++++++++++++++++++++++++++++++++-
 gck-rpc-module.c   |  6 +++++-
 gck-rpc-private.h  |  4 ++--
 p11proxy-mitm      |  2 +-
 4 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/gck-rpc-dispatch.c b/gck-rpc-dispatch.c
index 9bf2fa1..be1d7d9 100644
--- a/gck-rpc-dispatch.c
+++ b/gck-rpc-dispatch.c
@@ -601,6 +601,34 @@ static CK_RV proto_read_null_string(CallState * cs, CK_UTF8CHAR_PTR * val)
 	return CKR_OK;
 }
 
+static CK_RV proto_read_space_string(CallState * cs, CK_UTF8CHAR_PTR * val, CK_ULONG length)
+{
+	GckRpcMessage *msg;
+	const unsigned char *data;
+	size_t n_data;
+
+	assert(cs);
+	assert(val);
+
+	msg = cs->req;
+
+	/* Check that we're supposed to have this at this point */
+	assert(!msg->signature || gck_rpc_message_verify_part(msg, "s"));
+
+	if (!egg_buffer_get_byte_array
+	    (&msg->buffer, msg->parsed, &msg->parsed, &data, &n_data))
+		return PARSE_ERROR;
+
+	/* Allocate a block of memory for it. */
+	*val = call_alloc(cs, n_data);
+	if (!*val)
+		return CKR_DEVICE_MEMORY;
+
+	memcpy(*val, data, n_data);
+
+	return CKR_OK;
+}
+
 static CK_RV proto_read_mechanism(CallState * cs, CK_MECHANISM_PTR mech)
 {
 	GckRpcMessage *msg;
@@ -781,6 +809,10 @@ static CK_RV proto_write_session_info(CallState * cs, CK_SESSION_INFO_PTR info)
 	_ret = proto_read_null_string (cs, &val); \
 	if (_ret != CKR_OK) goto _cleanup;
 
+#define IN_SPACE_STRING(val, len)			   \
+	_ret = proto_read_space_string (cs, &val, len);	   \
+	if (_ret != CKR_OK) goto _cleanup;
+
 #define IN_BYTE_BUFFER(buffer, buffer_len_ptr) \
 	_ret = proto_read_byte_buffer (cs, &buffer, &buffer_len_ptr); \
 	if (_ret != CKR_OK) goto _cleanup;
@@ -1033,7 +1065,7 @@ static CK_RV rpc_C_InitToken(CallState * cs)
 	BEGIN_CALL(C_InitToken);
 	IN_ULONG(slot_id);
 	IN_BYTE_ARRAY(pin, pin_len);
-	IN_STRING(label);
+	IN_SPACE_STRING(label, 32);
 	PROCESS_CALL((slot_id, pin, pin_len, label));
 	END_CALL;
 }
diff --git a/gck-rpc-module.c b/gck-rpc-module.c
index d858186..c3b62c1 100644
--- a/gck-rpc-module.c
+++ b/gck-rpc-module.c
@@ -1134,6 +1134,10 @@ proto_read_sesssion_info(GckRpcMessage * msg, CK_SESSION_INFO_PTR info)
 	if (!gck_rpc_message_write_zero_string (_cs->req, val)) \
 		{ _ret = CKR_HOST_MEMORY; goto _cleanup; }
 
+#define IN_SPACE_STRING(val, len)						\
+	if (!gck_rpc_message_write_space_string (_cs->req, val, len))	\
+		{ _ret = CKR_HOST_MEMORY; goto _cleanup; }
+
 #define IN_BYTE_BUFFER(arr, len) \
 	if (!gck_rpc_message_write_byte_buffer (_cs->req, arr, len))	\
 		{ _ret = CKR_HOST_MEMORY; goto _cleanup; }
@@ -1499,7 +1503,7 @@ rpc_C_InitToken(CK_SLOT_ID id, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len,
 	BEGIN_CALL(C_InitToken);
 	IN_ULONG(id);
 	IN_BYTE_ARRAY(pin, pin_len);
-	IN_STRING(label);
+	IN_SPACE_STRING(label, 32);
 	PROCESS_CALL;
 	END_CALL;
 }
diff --git a/gck-rpc-private.h b/gck-rpc-private.h
index cf7f6ad..a3843e5 100644
--- a/gck-rpc-private.h
+++ b/gck-rpc-private.h
@@ -144,7 +144,7 @@ static const GckRpcCall gck_rpc_calls[] = {
 	 "ssssuuuuuuuuuuuvvs"},
 	{GCK_RPC_CALL_C_GetMechanismList, "C_GetMechanismList", "ufu", "au"},
 	{GCK_RPC_CALL_C_GetMechanismInfo, "C_GetMechanismInfo", "uu", "uuu"},
-	{GCK_RPC_CALL_C_InitToken, "C_InitToken", "uayz", ""},
+	{GCK_RPC_CALL_C_InitToken, "C_InitToken", "uays", ""},
 	{GCK_RPC_CALL_C_WaitForSlotEvent, "C_WaitForSlotEvent", "u", "u"},
 	{GCK_RPC_CALL_C_OpenSession, "C_OpenSession", "uu", "u"},
 	{GCK_RPC_CALL_C_CloseSession, "C_CloseSession", "u", ""},
@@ -216,7 +216,7 @@ static const GckRpcCall gck_rpc_calls[] = {
 #endif
 
 #define GCK_RPC_HANDSHAKE \
-	"PRIVATE-GNOME-KEYRING-PKCS11-PROTOCOL-V-2"
+	"PRIVATE-GNOME-KEYRING-PKCS11-PROTOCOL-V-3"
 #define GCK_RPC_HANDSHAKE_LEN \
 	(sizeof (GCK_RPC_HANDSHAKE) - 1)
 
diff --git a/p11proxy-mitm b/p11proxy-mitm
index 013f161..a640150 100755
--- a/p11proxy-mitm
+++ b/p11proxy-mitm
@@ -95,7 +95,7 @@ request_list = [
     (6, "C_GetTokenInfo", "u", "ssssuuuuuuuuuuuvvs"),
     (7, "C_GetMechanismList", "ufu", "au"),
     (8, "C_GetMechanismInfo", "uu", "uuu"),
-    (9, "C_InitToken", "uayz", ""),
+    (9, "C_InitToken", "uays", ""),
     (10, "C_WaitForSlotEvent", "u", "u"),
     (11, "C_OpenSession", "uu", "u"),
     (12, "C_CloseSession", "u", ""),
-- 
GitLab