aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pkcs11.c122
1 files changed, 98 insertions, 24 deletions
diff --git a/pkcs11.c b/pkcs11.c
index ff5304a..36ecefc 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;
/*
@@ -1491,7 +1488,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);
}
@@ -3293,6 +3292,9 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession,
if (session->digest_descriptor == NULL)
lose(CKR_OPERATION_NOT_INITIALIZED);
+ if (session->digest_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;
@@ -3322,6 +3324,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 == 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 == 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)
@@ -4108,14 +4198,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)
{
@@ -4123,14 +4205,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)