From 5ca8739c930b5ee4cbc778f2de7c9c693cd674f4 Mon Sep 17 00:00:00 2001
From: Joy Latten <jmlatten@linux.vnet.ibm.com>
Date: Tue, 11 Nov 2014 17:45:18 -0600
Subject: [PATCH] ICSF Token: C_SignUpdate was sometimes segfaulting and
 testcases were reporting that resulting signature did not match expected
 signature. Verification tests were also failing. ICSF token Was not copying
 chain data and setting initiated flag appropriately. Segfault occurred
 because needed to check clear text to see if not null before ber encoding.
 Also was not setting verify flag.

Signed-off-by: Joy Latten <jmlatten@linux.vnet.ibm.com>
---
 usr/lib/pkcs11/icsf_stdll/icsf.c          |  6 +++---
 usr/lib/pkcs11/icsf_stdll/icsf_specific.c | 29 +++++++++++++++--------------
 2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/usr/lib/pkcs11/icsf_stdll/icsf.c b/usr/lib/pkcs11/icsf_stdll/icsf.c
index 8e6dd4e..24f1580 100644
--- a/usr/lib/pkcs11/icsf_stdll/icsf.c
+++ b/usr/lib/pkcs11/icsf_stdll/icsf.c
@@ -2988,8 +2988,8 @@ int icsf_hash_signverify(LDAP *ld, int *reason, struct icsf_object_record *key,
 		return -1;
 	}
 
-	if (ber_printf(msg, "ooo", clear_text, clear_text_len,
-		      (chain_data) ? chain_data : "",
+	if (ber_printf(msg, "ooo", (clear_text) ? clear_text : "",
+		       clear_text_len, (chain_data) ? chain_data : "",
 		      (chain_data_len) ? *chain_data_len : 0UL,
 		      (sig) ? sig : "", (sig_len) ? *sig_len : 0) < 0) {
 		rc = -1;
@@ -3018,7 +3018,7 @@ int icsf_hash_signverify(LDAP *ld, int *reason, struct icsf_object_record *key,
 	}
 
 	/* Only need to return the length for signing */
-	if (!verify)
+	if (sig_len && !verify)
 		*sig_len = length;
 
 	/* leave if just returning the length. */
diff --git a/usr/lib/pkcs11/icsf_stdll/icsf_specific.c b/usr/lib/pkcs11/icsf_stdll/icsf_specific.c
index 397df28..f6b8765 100644
--- a/usr/lib/pkcs11/icsf_stdll/icsf_specific.c
+++ b/usr/lib/pkcs11/icsf_stdll/icsf_specific.c
@@ -3645,7 +3645,12 @@ token_specific_sign_update(SESSION *session, CK_BYTE *in_data,
 		if (rc != 0) {
 			OCK_LOG_ERR(CKR_FUNCTION_FAILED);
 			rc = icsf_to_ock_err(rc, reason);
+		} else {
+			multi_part_ctx->initiated = TRUE;
+			memcpy(multi_part_ctx->chain_data, chain_data,
+			       chain_data_len);
 		}
+
 		if (buffer)
 			free(buffer);
 
@@ -3659,11 +3664,6 @@ token_specific_sign_update(SESSION *session, CK_BYTE *in_data,
 done:
 	if (rc != 0)
 		free_sv_ctx(ctx);
-	else {
-		if (multi_part_ctx->initiated == FALSE)
-			multi_part_ctx->initiated = TRUE;
-		memcpy(multi_part_ctx->chain_data, chain_data, chain_data_len);
-	}
 
 	return rc;
 }
@@ -3758,7 +3758,8 @@ token_specific_sign_final(SESSION *session, CK_BBOOL length_only,
 		}
 
 		rc = icsf_hash_signverify(session_state->ld, &reason,
-				&mapping->icsf_object, &ctx->mech, "LAST",
+				&mapping->icsf_object, &ctx->mech,
+				multi_part_ctx->initiated ? "LAST":"ONLY",
 				(buffer) ? buffer : NULL,
 				multi_part_ctx->used_data_len, signature,
 				sig_len, chain_data, &chain_data_len, 0);
@@ -4170,11 +4171,15 @@ token_specific_verify_update(SESSION *session, CK_BYTE *in_data,
 				&mapping->icsf_object, &ctx->mech,
 				(multi_part_ctx->initiated) ? "MIDDLE":"FIRST",
 				buffer, out_len, NULL, NULL,
-				chain_data, &chain_data_len, 0);
+				chain_data, &chain_data_len, 1);
 
 		if (rc != 0) {
 			OCK_LOG_ERR(CKR_FUNCTION_FAILED);
 			rc = icsf_to_ock_err(rc, reason);
+		} else {
+			multi_part_ctx->initiated = TRUE;
+			memcpy(multi_part_ctx->chain_data, chain_data,
+			       chain_data_len);
 		}
 		if (buffer)
 			free(buffer);
@@ -4189,11 +4194,6 @@ token_specific_verify_update(SESSION *session, CK_BYTE *in_data,
 done:
 	if (rc != 0)
 		free_sv_ctx(ctx);
-	else {
-		if (multi_part_ctx->initiated == FALSE)
-			multi_part_ctx->initiated = TRUE;
-		memcpy(multi_part_ctx->chain_data, chain_data, chain_data_len);
-	}
 
 	return rc;
 }
@@ -4279,10 +4279,11 @@ token_specific_verify_final(SESSION *session, CK_BYTE *signature,
 		}
 
 		rc = icsf_hash_signverify(session_state->ld, &reason,
-				&mapping->icsf_object, &ctx->mech, "LAST",
+				&mapping->icsf_object, &ctx->mech,
+				multi_part_ctx->initiated ? "LAST":"ONLY",
 				(buffer) ? buffer : NULL,
 				multi_part_ctx->used_data_len, signature,
-				&sig_len, chain_data, &chain_data_len, 0);
+				&sig_len, chain_data, &chain_data_len, 1);
 
 		if (rc != 0)
 			rc = icsf_to_ock_err(rc, reason);
-- 
1.8.5.2

