From fc8c37cb8c4112eaba0805d7a26cd2275e902738 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Thu, 23 Jul 2015 06:49:13 +0200 Subject: First pass at adding incremental digest support. C_Digest*() only so far. Compiles, not yet tested. --- pkcs11.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 98 insertions(+), 24 deletions(-) (limited to 'pkcs11.c') 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) -- cgit v1.2.3