aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2015-07-23 06:49:13 +0200
committerRob Austein <sra@hactrn.net>2015-07-23 06:49:13 +0200
commitfc8c37cb8c4112eaba0805d7a26cd2275e902738 (patch)
tree27a55973a80f31071741a81c0dedd25cb3279df7
parent60a46afc01b73e763251370642cf61b15ba067d0 (diff)
First pass at adding incremental digest support. C_Digest*() only so
far. Compiles, not yet tested.
-rw-r--r--pkcs11.c122
1 files changed, 98 insertions, 24 deletions
diff --git a/pkcs11.c b/pkcs11.c
index 318055e..9d61927 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -137,13 +137,6 @@
* like CKA_KEY_TYPE, so it's just something we look up given the key
* object handle.
*
- * At the moment we don't need to keep any signature or digest state
- * in the session structure, which is good since the current hash
- * cores don't allow us to extract state anyway. This makes it
- * impossible to implement the incremental operations
- * (C_DigestUpdate(), C_SignUpdate()) but also simplifies our current
- * task.
- *
* General idea is that we have separate descriptors/handles/state for
* each operation that we're allowed to do in parallel, so sign,
* verify, digest, encrypt, decrypt, wrapkey, and unwrapkey all need
@@ -165,6 +158,10 @@ typedef struct p11_session {
CK_OBJECT_HANDLE
sign_key_handle, /* Key for C_Sign*() */
verify_key_handle; /* Key for C_Verify() */
+ hal_hash_state_t
+ digest_state, /* Hash state for C_Digest*() */
+ sign_digest_state, /* Hash state for C_Sign*() */
+ verify_digest_state; /* Hash state for C_Verify*() */
} p11_session_t;
/*
@@ -1309,7 +1306,9 @@ static void p11_session_free(p11_session_t *session)
return;
sql_finalize_and_clear(&session->find_query);
-
+ hal_hash_cleanup(&session->digest_state);
+ hal_hash_cleanup(&session->sign_digest_state);
+ hal_hash_cleanup(&session->verify_digest_state);
free(session);
}
@@ -3040,6 +3039,9 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession,
if (session->digest_descriptor == NULL)
lose(CKR_OPERATION_NOT_INITIALIZED);
+ if (session->digest_state.state != NULL)
+ lose(CKR_OPERATION_ACTIVE);
+
rv = *pulDigestLen < session->digest_descriptor->digest_length ? CKR_BUFFER_TOO_SMALL : CKR_OK;
*pulDigestLen = session->digest_descriptor->digest_length;
@@ -3069,6 +3071,94 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession,
mutex_unlock_return_with_rv(rv, p11_global_mutex);
}
+CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen)
+{
+ ENTER_PUBLIC_FUNCTION(C_DigestUpdate);
+
+ p11_session_t *session;
+ CK_RV rv = CKR_OK;
+
+ mutex_lock_or_return_failure(p11_global_mutex);
+
+ if ((session = p11_session_find(hSession)) == NULL)
+ lose(CKR_SESSION_HANDLE_INVALID);
+
+ if (pPart == NULL)
+ lose(CKR_ARGUMENTS_BAD);
+
+ if (session->digest_descriptor == NULL)
+ lose(CKR_OPERATION_NOT_INITIALIZED);
+
+ if (!session->digest_descriptor->can_restore_state)
+ lose(CKR_FUNCTION_FAILED);
+
+ if (session->digest_state.state == NULL) {
+ hal_error_t err = hal_hash_initialize(session->digest_descriptor,
+ &session->digest_state, NULL, 0);
+ if (err == HAL_ERROR_ALLOCATION_FAILURE)
+ lose(CKR_HOST_MEMORY);
+ else if (err != HAL_OK)
+ lose(CKR_FUNCTION_FAILED);
+ }
+
+ if (!hal_check(hal_hash_update(session->digest_state, pPart, ulPartLen)))
+ lose(CKR_FUNCTION_FAILED);
+
+ return mutex_unlock(p11_global_mutex);
+
+ fail:
+ if (session != NULL) {
+ hal_hash_cleanup(&session->digest_state);
+ session->digest_descriptor = NULL;
+ }
+ mutex_unlock_return_with_rv(rv, p11_global_mutex);
+}
+
+CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pDigest,
+ CK_ULONG_PTR pulDigestLen)
+{
+ ENTER_PUBLIC_FUNCTION(C_DigestFinal);
+
+ p11_session_t *session;
+ CK_RV rv = CKR_OK;
+
+ mutex_lock_or_return_failure(p11_global_mutex);
+
+ if ((session = p11_session_find(hSession)) == NULL)
+ lose(CKR_SESSION_HANDLE_INVALID);
+
+ if (pulDigestLen == NULL)
+ lose(CKR_ARGUMENTS_BAD);
+
+ if (session->digest_descriptor == NULL || session->digest_state.state == NULL)
+ lose(CKR_OPERATION_NOT_INITIALIZED);
+
+ rv = *pulDigestLen < session->digest_descriptor->digest_length ? CKR_BUFFER_TOO_SMALL : CKR_OK;
+
+ *pulDigestLen = session->digest_descriptor->digest_length;
+
+ if (pDigest == NULL)
+ return mutex_unlock(p11_global_mutex);
+
+ if (rv == CKR_BUFFER_TOO_SMALL)
+ lose(CKR_BUFFER_TOO_SMALL);
+
+ if (!hal_check(hal_hash_finalize(session->digest_state, pDigest, *pulDigestLen)))
+ lose(CKR_FUNCTION_FAILED);
+
+ rv = CKR_OK; /* Fall through */
+
+ fail:
+ if (session != NULL) {
+ hal_hash_cleanup(&session->digest_state);
+ session->digest_descriptor = NULL;
+ }
+ mutex_unlock_return_with_rv(rv, p11_global_mutex);
+}
+
CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
@@ -3734,14 +3824,6 @@ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession,
return CKR_FUNCTION_NOT_SUPPORTED;
}
-CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession,
- CK_BYTE_PTR pPart,
- CK_ULONG ulPartLen)
-{
- ENTER_PUBLIC_FUNCTION(C_DigestUpdate);
- return CKR_FUNCTION_NOT_SUPPORTED;
-}
-
CK_RV C_DigestKey(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hKey)
{
@@ -3749,14 +3831,6 @@ CK_RV C_DigestKey(CK_SESSION_HANDLE hSession,
return CKR_FUNCTION_NOT_SUPPORTED;
}
-CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession,
- CK_BYTE_PTR pDigest,
- CK_ULONG_PTR pulDigestLen)
-{
- ENTER_PUBLIC_FUNCTION(C_DigestFinal);
- return CKR_FUNCTION_NOT_SUPPORTED;
-}
-
CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen)