From 095eff3e552c3d314f3af6a430b9b1c3acb99bd6 Mon Sep 17 00:00:00 2001
From: Fredrik Thulin <fredrik@thulin.net>
Date: Mon, 7 Jan 2013 12:11:26 +0100
Subject: [PATCH] proto_read_byte_buffer: Support undefined buffer size.

A number of PKCS#11 functions take a pointer to a buffer size as
argument. To be a transparent proxy of PKCS#11 calls, it is necessary to
support invoking these functions with a NULL pointer. pkcs11-proxy used
to send the buffer size as an integer and create a pointer to the integer
on the server side, but this is different to the backend PKCS#11 module
in some cases.

E.g. the C_Encrypt call is specified to have side effectes (finalizing)
when called with a NULL encrypted data length. The softhsm test suite
exposed that these side effects never occured because the NULL data length
pointer was conveyed as a valid pointer to the integer zero.

Since an additional uint8_t was added to "byte buffers", this is an
backwards incompatible change. As such, the version number in the protocol
greeting was increased (GCK_RPC_HANDSHAKE).
---
 gck-rpc-dispatch.c | 121 ++++++++++++++++++++++++---------------------
 gck-rpc-message.c  |  16 +++++-
 gck-rpc-module.c   |  15 ++++--
 gck-rpc-private.h  |   7 ++-
 4 files changed, 96 insertions(+), 63 deletions(-)

diff --git a/gck-rpc-dispatch.c b/gck-rpc-dispatch.c
index 67ea0aa..a0152f3 100644
--- a/gck-rpc-dispatch.c
+++ b/gck-rpc-dispatch.c
@@ -201,9 +201,10 @@ static void call_uninit(CallState * cs)
 
 static CK_RV
 proto_read_byte_buffer(CallState * cs, CK_BYTE_PTR * buffer,
-		       CK_ULONG * n_buffer)
+		       CK_ULONG_PTR * n_buffer)
 {
 	GckRpcMessage *msg;
+	uint8_t flags;
 	uint32_t length;
 
 	assert(cs);
@@ -215,23 +216,27 @@ proto_read_byte_buffer(CallState * cs, CK_BYTE_PTR * buffer,
 	/* Check that we're supposed to be reading this at this point */
 	assert(!msg->signature || gck_rpc_message_verify_part(msg, "fy"));
 
+	if (!egg_buffer_get_byte
+	    (&msg->buffer, msg->parsed, &msg->parsed, &flags))
+		return PARSE_ERROR;
+
 	/* The number of ulongs there's room for on the other end */
 	if (!egg_buffer_get_uint32
 	    (&msg->buffer, msg->parsed, &msg->parsed, &length))
 		return PARSE_ERROR;
 
-	*n_buffer = length;
-	*buffer = NULL;
 
-	/* We go ahead and allocate a buffer even if length is zero. The code used
-	 * to just return CKR_OK without allocating a buffer, but that breaks a
-	 * test case in pkcs11-tool for C_GenerateRandom of 0 bytes. Best to be as
-	 * transparent as possible and let the p11 module decide how to handle it.
-	 */
+	**n_buffer = length;
+	*buffer = NULL_PTR;
 
-	*buffer = call_alloc(cs, length * sizeof(CK_BYTE));
-	if (!*buffer)
-		return CKR_DEVICE_MEMORY;
+	if ((flags & GCK_RPC_BYTE_BUFFER_NULL_COUNT))
+		*n_buffer = NULL_PTR;
+
+	if (! (flags & GCK_RPC_BYTE_BUFFER_NULL_DATA)) {
+		*buffer = call_alloc(cs, length * sizeof(CK_BYTE));
+		if (!*buffer)
+			return CKR_DEVICE_MEMORY;
+	}
 
 	return CKR_OK;
 }
@@ -278,7 +283,7 @@ proto_read_byte_array(CallState * cs, CK_BYTE_PTR * array, CK_ULONG * n_array)
 }
 
 static CK_RV
-proto_write_byte_array(CallState * cs, CK_BYTE_PTR array, CK_ULONG len,
+proto_write_byte_array(CallState * cs, CK_BYTE_PTR array, CK_ULONG_PTR len,
 		       CK_RV ret)
 {
 	assert(cs);
@@ -300,7 +305,7 @@ proto_write_byte_array(CallState * cs, CK_BYTE_PTR array, CK_ULONG len,
 		return ret;
 	};
 
-	if (!gck_rpc_message_write_byte_array(cs->resp, array, len))
+	if (!gck_rpc_message_write_byte_array(cs->resp, array, len ? *len : 0))
 		return PREP_ERROR;
 
 	return CKR_OK;
@@ -716,6 +721,12 @@ static CK_RV proto_write_session_info(CallState * cs, CK_SESSION_INFO_PTR info)
  * CALL MACROS
  */
 
+#define DECLARE_CK_ULONG_PTR(ck_ulong_ptr_name) \
+	CK_ULONG ck_ulong_ptr_name ## _v ; \
+	CK_ULONG_PTR ck_ulong_ptr_name ; \
+	ck_ulong_ptr_name ## _v = 0; \
+	ck_ulong_ptr_name = &ck_ulong_ptr_name ## _v ;
+
 #define BEGIN_CALL(call_id) \
 	debug ((#call_id ": enter")); \
 	assert (cs); \
@@ -747,8 +758,8 @@ 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_BYTE_BUFFER(buffer, buffer_len) \
-	_ret = proto_read_byte_buffer (cs, &buffer, &buffer_len); \
+#define IN_BYTE_BUFFER(buffer, buffer_len_ptr) \
+	_ret = proto_read_byte_buffer (cs, &buffer, &buffer_len_ptr); \
 	if (_ret != CKR_OK) goto _cleanup;
 
 #define IN_BYTE_ARRAY(buffer, buffer_len) \
@@ -775,9 +786,9 @@ static CK_RV proto_write_session_info(CallState * cs, CK_SESSION_INFO_PTR info)
 	if (_ret == CKR_OK && !gck_rpc_message_write_ulong (cs->resp, val)) \
 		_ret = PREP_ERROR;
 
-#define OUT_BYTE_ARRAY(array, len) \
+#define OUT_BYTE_ARRAY(array, len_ptr) \
 	/* Note how we filter return codes */ \
-	_ret = proto_write_byte_array (cs, array, len, _ret);
+	_ret = proto_write_byte_array (cs, array, len_ptr, _ret);
 
 #define OUT_ULONG_ARRAY(array, len) \
 	/* Note how we filter return codes */ \
@@ -1136,12 +1147,12 @@ static CK_RV rpc_C_GetOperationState(CallState * cs)
 {
 	CK_SESSION_HANDLE session;
 	CK_BYTE_PTR operation_state;
-	CK_ULONG operation_state_len;
+	DECLARE_CK_ULONG_PTR(operation_state_len);
 
 	BEGIN_CALL(C_GetOperationState);
 	IN_ULONG(session);
 	IN_BYTE_BUFFER(operation_state, operation_state_len);
-	PROCESS_CALL((session, operation_state, &operation_state_len));
+	PROCESS_CALL((session, operation_state, operation_state_len));
 	OUT_BYTE_ARRAY(operation_state, operation_state_len);
 	END_CALL;
 }
@@ -1341,14 +1352,14 @@ static CK_RV rpc_C_Encrypt(CallState * cs)
 	CK_BYTE_PTR data;
 	CK_ULONG data_len;
 	CK_BYTE_PTR encrypted_data;
-	CK_ULONG encrypted_data_len;
+	DECLARE_CK_ULONG_PTR(encrypted_data_len);
 
 	BEGIN_CALL(C_Encrypt);
 	IN_ULONG(session);
 	IN_BYTE_ARRAY(data, data_len);
 	IN_BYTE_BUFFER(encrypted_data, encrypted_data_len);
 	PROCESS_CALL((session, data, data_len, encrypted_data,
-		      &encrypted_data_len));
+		      encrypted_data_len));
 	OUT_BYTE_ARRAY(encrypted_data, encrypted_data_len);
 	END_CALL;
 }
@@ -1359,14 +1370,14 @@ static CK_RV rpc_C_EncryptUpdate(CallState * cs)
 	CK_BYTE_PTR part;
 	CK_ULONG part_len;
 	CK_BYTE_PTR encrypted_part;
-	CK_ULONG encrypted_part_len;
+	DECLARE_CK_ULONG_PTR(encrypted_part_len);
 
 	BEGIN_CALL(C_EncryptUpdate);
 	IN_ULONG(session);
 	IN_BYTE_ARRAY(part, part_len);
 	IN_BYTE_BUFFER(encrypted_part, encrypted_part_len);
 	PROCESS_CALL((session, part, part_len, encrypted_part,
-		      &encrypted_part_len));
+		      encrypted_part_len));
 	OUT_BYTE_ARRAY(encrypted_part, encrypted_part_len);
 	END_CALL;
 }
@@ -1375,12 +1386,12 @@ static CK_RV rpc_C_EncryptFinal(CallState * cs)
 {
 	CK_SESSION_HANDLE session;
 	CK_BYTE_PTR last_encrypted_part;
-	CK_ULONG last_encrypted_part_len;
+	DECLARE_CK_ULONG_PTR(last_encrypted_part_len);
 
 	BEGIN_CALL(C_EncryptFinal);
 	IN_ULONG(session);
 	IN_BYTE_BUFFER(last_encrypted_part, last_encrypted_part_len);
-	PROCESS_CALL((session, last_encrypted_part, &last_encrypted_part_len));
+	PROCESS_CALL((session, last_encrypted_part, last_encrypted_part_len));
 	OUT_BYTE_ARRAY(last_encrypted_part, last_encrypted_part_len);
 	END_CALL;
 }
@@ -1405,14 +1416,14 @@ static CK_RV rpc_C_Decrypt(CallState * cs)
 	CK_BYTE_PTR encrypted_data;
 	CK_ULONG encrypted_data_len;
 	CK_BYTE_PTR data;
-	CK_ULONG data_len;
+	DECLARE_CK_ULONG_PTR(data_len);
 
 	BEGIN_CALL(C_Decrypt);
 	IN_ULONG(session);
 	IN_BYTE_ARRAY(encrypted_data, encrypted_data_len);
 	IN_BYTE_BUFFER(data, data_len);
 	PROCESS_CALL((session, encrypted_data, encrypted_data_len, data,
-		      &data_len));
+		      data_len));
 	OUT_BYTE_ARRAY(data, data_len);
 	END_CALL;
 }
@@ -1423,14 +1434,14 @@ static CK_RV rpc_C_DecryptUpdate(CallState * cs)
 	CK_BYTE_PTR encrypted_part;
 	CK_ULONG encrypted_part_len;
 	CK_BYTE_PTR part;
-	CK_ULONG part_len;
+	DECLARE_CK_ULONG_PTR(part_len);
 
 	BEGIN_CALL(C_DecryptUpdate);
 	IN_ULONG(session);
 	IN_BYTE_ARRAY(encrypted_part, encrypted_part_len);
 	IN_BYTE_BUFFER(part, part_len);
 	PROCESS_CALL((session, encrypted_part, encrypted_part_len, part,
-		      &part_len));
+		      part_len));
 	OUT_BYTE_ARRAY(part, part_len);
 	END_CALL;
 }
@@ -1439,12 +1450,12 @@ static CK_RV rpc_C_DecryptFinal(CallState * cs)
 {
 	CK_SESSION_HANDLE session;
 	CK_BYTE_PTR last_part;
-	CK_ULONG last_part_len;
+	DECLARE_CK_ULONG_PTR(last_part_len);
 
 	BEGIN_CALL(C_DecryptFinal);
 	IN_ULONG(session);
 	IN_BYTE_BUFFER(last_part, last_part_len);
-	PROCESS_CALL((session, last_part, &last_part_len));
+	PROCESS_CALL((session, last_part, last_part_len));
 	OUT_BYTE_ARRAY(last_part, last_part_len);
 	END_CALL;
 }
@@ -1467,13 +1478,13 @@ static CK_RV rpc_C_Digest(CallState * cs)
 	CK_BYTE_PTR data;
 	CK_ULONG data_len;
 	CK_BYTE_PTR digest;
-	CK_ULONG digest_len;
+	DECLARE_CK_ULONG_PTR(digest_len);
 
 	BEGIN_CALL(C_Digest);
 	IN_ULONG(session);
 	IN_BYTE_ARRAY(data, data_len);
 	IN_BYTE_BUFFER(digest, digest_len);
-	PROCESS_CALL((session, data, data_len, digest, &digest_len));
+	PROCESS_CALL((session, data, data_len, digest, digest_len));
 	OUT_BYTE_ARRAY(digest, digest_len);
 	END_CALL;
 }
@@ -1507,12 +1518,12 @@ static CK_RV rpc_C_DigestFinal(CallState * cs)
 {
 	CK_SESSION_HANDLE session;
 	CK_BYTE_PTR digest;
-	CK_ULONG digest_len;
+	DECLARE_CK_ULONG_PTR(digest_len);
 
 	BEGIN_CALL(C_DigestFinal);
 	IN_ULONG(session);
 	IN_BYTE_BUFFER(digest, digest_len);
-	PROCESS_CALL((session, digest, &digest_len));
+	PROCESS_CALL((session, digest, digest_len));
 	OUT_BYTE_ARRAY(digest, digest_len);
 	END_CALL;
 }
@@ -1537,13 +1548,13 @@ static CK_RV rpc_C_Sign(CallState * cs)
 	CK_BYTE_PTR part;
 	CK_ULONG part_len;
 	CK_BYTE_PTR signature;
-	CK_ULONG signature_len;
+	DECLARE_CK_ULONG_PTR(signature_len);
 
 	BEGIN_CALL(C_Sign);
 	IN_ULONG(session);
 	IN_BYTE_ARRAY(part, part_len);
 	IN_BYTE_BUFFER(signature, signature_len);
-	PROCESS_CALL((session, part, part_len, signature, &signature_len));
+	PROCESS_CALL((session, part, part_len, signature, signature_len));
 	OUT_BYTE_ARRAY(signature, signature_len);
 	END_CALL;
 
@@ -1566,12 +1577,12 @@ static CK_RV rpc_C_SignFinal(CallState * cs)
 {
 	CK_SESSION_HANDLE session;
 	CK_BYTE_PTR signature;
-	CK_ULONG signature_len;
+	DECLARE_CK_ULONG_PTR(signature_len);
 
 	BEGIN_CALL(C_SignFinal);
 	IN_ULONG(session);
 	IN_BYTE_BUFFER(signature, signature_len);
-	PROCESS_CALL((session, signature, &signature_len));
+	PROCESS_CALL((session, signature, signature_len));
 	OUT_BYTE_ARRAY(signature, signature_len);
 	END_CALL;
 }
@@ -1596,13 +1607,13 @@ static CK_RV rpc_C_SignRecover(CallState * cs)
 	CK_BYTE_PTR data;
 	CK_ULONG data_len;
 	CK_BYTE_PTR signature;
-	CK_ULONG signature_len;
+	DECLARE_CK_ULONG_PTR(signature_len);
 
 	BEGIN_CALL(C_SignRecover);
 	IN_ULONG(session);
 	IN_BYTE_ARRAY(data, data_len);
 	IN_BYTE_BUFFER(signature, signature_len);
-	PROCESS_CALL((session, data, data_len, signature, &signature_len));
+	PROCESS_CALL((session, data, data_len, signature, signature_len));
 	OUT_BYTE_ARRAY(signature, signature_len);
 	END_CALL;
 }
@@ -1683,13 +1694,13 @@ static CK_RV rpc_C_VerifyRecover(CallState * cs)
 	CK_BYTE_PTR signature;
 	CK_ULONG signature_len;
 	CK_BYTE_PTR data;
-	CK_ULONG data_len;
+	DECLARE_CK_ULONG_PTR(data_len);
 
 	BEGIN_CALL(C_VerifyRecover);
 	IN_ULONG(session);
 	IN_BYTE_ARRAY(signature, signature_len);
 	IN_BYTE_BUFFER(data, data_len);
-	PROCESS_CALL((session, signature, signature_len, data, &data_len));
+	PROCESS_CALL((session, signature, signature_len, data, data_len));
 	OUT_BYTE_ARRAY(data, data_len);
 	END_CALL;
 }
@@ -1700,14 +1711,14 @@ static CK_RV rpc_C_DigestEncryptUpdate(CallState * cs)
 	CK_BYTE_PTR part;
 	CK_ULONG part_len;
 	CK_BYTE_PTR encrypted_part;
-	CK_ULONG encrypted_part_len;
+	DECLARE_CK_ULONG_PTR(encrypted_part_len);
 
 	BEGIN_CALL(C_DigestEncryptUpdate);
 	IN_ULONG(session);
 	IN_BYTE_ARRAY(part, part_len);
 	IN_BYTE_BUFFER(encrypted_part, encrypted_part_len);
 	PROCESS_CALL((session, part, part_len, encrypted_part,
-		      &encrypted_part_len));
+		      encrypted_part_len));
 	OUT_BYTE_ARRAY(encrypted_part, encrypted_part_len);
 	END_CALL;
 }
@@ -1718,14 +1729,14 @@ static CK_RV rpc_C_DecryptDigestUpdate(CallState * cs)
 	CK_BYTE_PTR encrypted_part;
 	CK_ULONG encrypted_part_len;
 	CK_BYTE_PTR part;
-	CK_ULONG part_len;
+	DECLARE_CK_ULONG_PTR(part_len);
 
 	BEGIN_CALL(C_DecryptDigestUpdate);
 	IN_ULONG(session);
 	IN_BYTE_ARRAY(encrypted_part, encrypted_part_len);
 	IN_BYTE_BUFFER(part, part_len);
 	PROCESS_CALL((session, encrypted_part, encrypted_part_len, part,
-		      &part_len));
+		      part_len));
 	OUT_BYTE_ARRAY(part, part_len);
 	END_CALL;
 }
@@ -1736,14 +1747,14 @@ static CK_RV rpc_C_SignEncryptUpdate(CallState * cs)
 	CK_BYTE_PTR part;
 	CK_ULONG part_len;
 	CK_BYTE_PTR encrypted_part;
-	CK_ULONG encrypted_part_len;
+	DECLARE_CK_ULONG_PTR(encrypted_part_len);
 
 	BEGIN_CALL(C_SignEncryptUpdate);
 	IN_ULONG(session);
 	IN_BYTE_ARRAY(part, part_len);
 	IN_BYTE_BUFFER(encrypted_part, encrypted_part_len);
 	PROCESS_CALL((session, part, part_len, encrypted_part,
-		      &encrypted_part_len));
+		      encrypted_part_len));
 	OUT_BYTE_ARRAY(encrypted_part, encrypted_part_len);
 	END_CALL;
 }
@@ -1754,14 +1765,14 @@ static CK_RV rpc_C_DecryptVerifyUpdate(CallState * cs)
 	CK_BYTE_PTR encrypted_part;
 	CK_ULONG encrypted_part_len;
 	CK_BYTE_PTR part;
-	CK_ULONG part_len;
+	DECLARE_CK_ULONG_PTR(part_len);
 
 	BEGIN_CALL(C_DecryptVerifyUpdate);
 	IN_ULONG(session);
 	IN_BYTE_ARRAY(encrypted_part, encrypted_part_len);
 	IN_BYTE_BUFFER(part, part_len);
 	PROCESS_CALL((session, encrypted_part, encrypted_part_len, part,
-		      &part_len));
+		      part_len));
 	OUT_BYTE_ARRAY(part, part_len);
 	END_CALL;
 }
@@ -1819,7 +1830,7 @@ static CK_RV rpc_C_WrapKey(CallState * cs)
 	CK_OBJECT_HANDLE wrapping_key;
 	CK_OBJECT_HANDLE key;
 	CK_BYTE_PTR wrapped_key;
-	CK_ULONG wrapped_key_len;
+	DECLARE_CK_ULONG_PTR(wrapped_key_len);
 
 	BEGIN_CALL(C_WrapKey);
 	IN_ULONG(session);
@@ -1828,7 +1839,7 @@ static CK_RV rpc_C_WrapKey(CallState * cs)
 	IN_ULONG(key);
 	IN_BYTE_BUFFER(wrapped_key, wrapped_key_len);
 	PROCESS_CALL((session, &mechanism, wrapping_key, key, wrapped_key,
-		      &wrapped_key_len));
+		      wrapped_key_len));
 	OUT_BYTE_ARRAY(wrapped_key, wrapped_key_len);
 	END_CALL;
 }
@@ -1893,12 +1904,12 @@ static CK_RV rpc_C_GenerateRandom(CallState * cs)
 {
 	CK_SESSION_HANDLE session;
 	CK_BYTE_PTR random_data;
-	CK_ULONG random_len;
+	DECLARE_CK_ULONG_PTR(random_len);
 
 	BEGIN_CALL(C_GenerateRandom);
 	IN_ULONG(session);
 	IN_BYTE_BUFFER(random_data, random_len);
-	PROCESS_CALL((session, random_data, random_len));
+	PROCESS_CALL((session, random_data, *random_len));
 	OUT_BYTE_ARRAY(random_data, random_len);
 	END_CALL;
 }
diff --git a/gck-rpc-message.c b/gck-rpc-message.c
index 079b21f..440d88d 100644
--- a/gck-rpc-message.c
+++ b/gck-rpc-message.c
@@ -334,13 +334,25 @@ int gck_rpc_message_write_ulong(GckRpcMessage * msg, CK_ULONG val)
 	return egg_buffer_add_uint64(&msg->buffer, val);
 }
 
-int gck_rpc_message_write_byte_buffer(GckRpcMessage * msg, CK_ULONG count)
+int gck_rpc_message_write_byte_buffer(GckRpcMessage * msg, CK_BYTE_PTR arr, CK_ULONG *count_ptr)
 {
+	uint8_t flags;
 	assert(msg);
 
 	/* Make sure this is in the right order */
 	assert(!msg->signature || gck_rpc_message_verify_part(msg, "fy"));
-	return egg_buffer_add_uint32(&msg->buffer, count);
+
+	flags = 0;
+	if (! arr)
+		flags |= GCK_RPC_BYTE_BUFFER_NULL_DATA;
+	if (! count_ptr)
+		flags |= GCK_RPC_BYTE_BUFFER_NULL_COUNT;
+
+	egg_buffer_add_byte(&msg->buffer, flags);
+
+	egg_buffer_add_uint32(&msg->buffer, count_ptr ? *count_ptr : 0x0);
+
+	return !egg_buffer_has_error(&msg->buffer);
 }
 
 int
diff --git a/gck-rpc-module.c b/gck-rpc-module.c
index 27b4145..88313a1 100644
--- a/gck-rpc-module.c
+++ b/gck-rpc-module.c
@@ -1073,9 +1073,7 @@ proto_read_sesssion_info(GckRpcMessage * msg, CK_SESSION_INFO_PTR info)
 		{ _ret = CKR_HOST_MEMORY; goto _cleanup; }
 
 #define IN_BYTE_BUFFER(arr, len) \
-	if (len == NULL) \
-		{ _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \
-	if (!gck_rpc_message_write_byte_buffer (_cs->req, arr ? *len : 0)) \
+	if (!gck_rpc_message_write_byte_buffer (_cs->req, arr, len))	\
 		{ _ret = CKR_HOST_MEMORY; goto _cleanup; }
 
 #define IN_BYTE_ARRAY(arr, len) \
@@ -1720,7 +1718,16 @@ static CK_RV
 rpc_C_Encrypt(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len,
 	      CK_BYTE_PTR encrypted_data, CK_ULONG_PTR encrypted_data_len)
 {
-	return_val_if_fail(encrypted_data_len, CKR_ARGUMENTS_BAD);
+	return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+	/* From PKCS#11 v2.01 :
+	 *  A call to C_Encrypt always terminates the active encryption operation
+	 *  unless it returns CKR_BUFFER_TOO_SMALL or is a successful call (i.e.,
+	 *  one which returns CKR_OK) to determine the length of the buffer
+	 *  needed to hold the ciphertext.
+	 *
+	 * Thus, we can't reject for example NULL encrypted_data_len, since then
+	 * the encryption operation won't be terminated in the real PKCS#11 module.
+	 */
 
 	BEGIN_CALL(C_Encrypt);
 	IN_ULONG(session);
diff --git a/gck-rpc-private.h b/gck-rpc-private.h
index 22f897a..02c1e9d 100644
--- a/gck-rpc-private.h
+++ b/gck-rpc-private.h
@@ -216,7 +216,7 @@ static const GckRpcCall gck_rpc_calls[] = {
 #endif
 
 #define GCK_RPC_HANDSHAKE \
-	"PRIVATE-GNOME-KEYRING-PKCS11-PROTOCOL-V-1"
+	"PRIVATE-GNOME-KEYRING-PKCS11-PROTOCOL-V-2"
 #define GCK_RPC_HANDSHAKE_LEN \
 	(sizeof (GCK_RPC_HANDSHAKE) - 1)
 
@@ -237,6 +237,9 @@ typedef struct _GckRpcMessage {
 	const char *sigverify;
 } GckRpcMessage;
 
+#define GCK_RPC_BYTE_BUFFER_NULL_DATA	1
+#define GCK_RPC_BYTE_BUFFER_NULL_COUNT	2
+
 GckRpcMessage *gck_rpc_message_new(EggBufferAllocator allocator);
 
 void gck_rpc_message_free(GckRpcMessage * msg);
@@ -266,7 +269,7 @@ int gck_rpc_message_write_zero_string(GckRpcMessage * msg,
 int gck_rpc_message_write_space_string(GckRpcMessage * msg,
 				       CK_UTF8CHAR * buffer, CK_ULONG length);
 
-int gck_rpc_message_write_byte_buffer(GckRpcMessage * msg, CK_ULONG count);
+int gck_rpc_message_write_byte_buffer(GckRpcMessage * msg, CK_BYTE_PTR arr, CK_ULONG *count_ptr);
 
 int gck_rpc_message_write_byte_array(GckRpcMessage * msg,
 				     CK_BYTE_PTR arr, CK_ULONG num);
-- 
GitLab