From c1e30395d8f4551a5f0fa253eefeefc9a9154f7e Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Mon, 8 Dec 2008 20:34:49 +0000 Subject: Support the concept of read-write and read-only sessions. --- ckcapi-session.c | 36 ++++++++++++++++++++++++++++++++---- ckcapi-session.h | 7 ++++++- ckcapi.c | 22 ++++++++++++---------- 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/ckcapi-session.c b/ckcapi-session.c index 1fdb07e..f4f00aa 100644 --- a/ckcapi-session.c +++ b/ckcapi-session.c @@ -214,7 +214,7 @@ ckcapi_session_destroy(CkCapiSession* sess) static CK_RV lock_ref_internal(CkCapiArray* sessions, CK_SESSION_HANDLE id, - int remove, CkCapiSession** sess_ret) + BOOL remove, BOOL writable, CkCapiSession** sess_ret) { CkCapiSession *sess; DWORD r; @@ -238,6 +238,10 @@ lock_ref_internal(CkCapiArray* sessions, CK_SESSION_HANDLE id, return CKR_SESSION_HANDLE_INVALID; } + /* Make sure it's the right kind of session */ + if(writable && !sess->read_write) + return CKR_SESSION_READ_ONLY; + ASSERT(sess->id == id); /* Closing takes precedence over active operations */ @@ -297,7 +301,31 @@ lock_ref_internal(CkCapiArray* sessions, CK_SESSION_HANDLE id, } CK_RV -ckcapi_session_get_lock_ref(CK_ULONG id, int remove, CkCapiSession **sess) +ckcapi_session_get_lock_ref(CK_ULONG id, BOOL writable, CkCapiSession **sess) +{ + /* This must be called without any locks held */ + + CK_RV ret = CKR_OK; + + ASSERT(sess); + + if(id <= 0) + { + DBG(("invalid session id passed: %d", id)); + return CKR_ARGUMENTS_BAD; + } + + ckcapi_lock_global(); + + ret = lock_ref_internal (all_sessions, id, FALSE, writable, sess); + + ckcapi_unlock_global(); + + return ret; +} + +CK_RV +ckcapi_session_remove_lock_ref(CK_ULONG id, CkCapiSession **sess) { /* This must be called without any locks held */ @@ -313,7 +341,7 @@ ckcapi_session_get_lock_ref(CK_ULONG id, int remove, CkCapiSession **sess) ckcapi_lock_global(); - ret = lock_ref_internal (all_sessions, id, remove, sess); + ret = lock_ref_internal (all_sessions, id, TRUE, FALSE, sess); ckcapi_unlock_global(); @@ -414,7 +442,7 @@ ckcapi_session_close_all(CK_SLOT_ID slot) continue; /* We need any calls in other threads to finish, so wait here */ - if(lock_ref_internal(sessions, i, 1, &sess) == CKR_OK) + if(lock_ref_internal(sessions, i, TRUE, FALSE, &sess) == CKR_OK) ckcapi_session_unref_unlock(sess); } diff --git a/ckcapi-session.h b/ckcapi-session.h index 4fb68fa..7b71c07 100644 --- a/ckcapi-session.h +++ b/ckcapi-session.h @@ -34,6 +34,8 @@ typedef struct _CkCapiSession HCERTSTORE store; /* Handle to an open certificate store */ + BOOL read_write; /* A read-write session? */ + int operation_type; /* Whether an operation is happening or not */ void* operation_data; /* Data for this operation */ CkCapiSessionCancel operation_cancel; /* Callback to cancel operation when necessary */ @@ -62,9 +64,12 @@ void ckcapi_session_destroy (CkCapiSession* sess); CK_RV ckcapi_session_register (CkCapiSession* sess); /* Get a session from a handle, and lock it */ -CK_RV ckcapi_session_get_lock_ref (CK_ULONG id, int remove, +CK_RV ckcapi_session_get_lock_ref (CK_ULONG id, BOOL writable, CkCapiSession **sess); +/* Get a session from a handle, remove it from list, and lock it */ +CK_RV ckcapi_session_remove_lock_ref (CK_ULONG id, CkCapiSession **sess); + /* Unlock and unreference a session */ void ckcapi_session_unref_unlock (CkCapiSession* sess); diff --git a/ckcapi.c b/ckcapi.c index 1bc6dd9..378746e 100644 --- a/ckcapi.c +++ b/ckcapi.c @@ -595,6 +595,9 @@ CC_C_OpenSession(CK_SLOT_ID id, CK_FLAGS flags, CK_VOID_PTR application, sess->notify_callback = notify; sess->user_data = application; + if(flags & CKF_RW_SESSION) + sess->read_write = TRUE; + ret = ckcapi_session_register(sess); if(ret == CKR_OK) { @@ -619,8 +622,7 @@ CC_C_CloseSession(CK_SESSION_HANDLE session) ENTER(C_CloseSession); PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - /* The 'remove' flag removes it from the main session list */ - ret = ckcapi_session_get_lock_ref(session, 1, &sess); + ret = ckcapi_session_remove_lock_ref(session, &sess); if(ret == CKR_OK) { /* This will unref and possibly destroy the session */ @@ -794,7 +796,7 @@ CC_C_GetAttributeValue(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, PREREQ(object, CKR_OBJECT_HANDLE_INVALID); PREREQ(!count || templ, CKR_ARGUMENTS_BAD); - ret = ckcapi_session_get_lock_ref(session, 0, &sess); + ret = ckcapi_session_get_lock_ref(session, FALSE, &sess); if(ret == CKR_OK) { ret = ckcapi_session_get_object_data_for(sess, object, &objdata); @@ -829,7 +831,7 @@ CC_C_FindObjectsInit(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR templ, PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); PREREQ(!count || templ, CKR_ARGUMENTS_BAD); - ret = ckcapi_session_get_lock_ref(session, 0, &sess); + ret = ckcapi_session_get_lock_ref(session, FALSE, &sess); if(ret == CKR_OK) { ret = ckcapi_session_find_init(sess, templ, count); @@ -851,7 +853,7 @@ CC_C_FindObjects(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR objects, PREREQ(object_count, CKR_ARGUMENTS_BAD); PREREQ(!max_object_count || objects, CKR_ARGUMENTS_BAD); - ret = ckcapi_session_get_lock_ref(session, 0, &sess); + ret = ckcapi_session_get_lock_ref(session, FALSE, &sess); if(ret == CKR_OK) { ret = ckcapi_session_find(sess, objects, max_object_count, object_count); @@ -870,7 +872,7 @@ CC_C_FindObjectsFinal(CK_SESSION_HANDLE session) ENTER(C_FindObjectsFinal); PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - ret = ckcapi_session_get_lock_ref(session, 0, &sess); + ret = ckcapi_session_get_lock_ref(session, FALSE, &sess); if(ret == CKR_OK) { ret = ckcapi_session_find_final(sess); @@ -938,7 +940,7 @@ CC_C_DecryptInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, PREREQ(mechanism, CKR_ARGUMENTS_BAD); PREREQ(key, CKR_ARGUMENTS_BAD); - ret = ckcapi_session_get_lock_ref(session, 0, &sess); + ret = ckcapi_session_get_lock_ref(session, FALSE, &sess); if(ret == CKR_OK) { ret = ckcapi_session_get_object_data_for(sess, key, &objdata); @@ -963,7 +965,7 @@ CC_C_Decrypt(CK_SESSION_HANDLE session, CK_BYTE_PTR encrypted_data, PREREQ(encrypted_data, CKR_ARGUMENTS_BAD); PREREQ(encrypted_data_len, CKR_ARGUMENTS_BAD); - ret = ckcapi_session_get_lock_ref(session, 0, &sess); + ret = ckcapi_session_get_lock_ref(session, FALSE, &sess); if(ret == CKR_OK) { ret = ckcapi_session_decrypt(sess, encrypted_data, encrypted_data_len, @@ -1061,7 +1063,7 @@ CC_C_SignInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, PREREQ(mechanism, CKR_ARGUMENTS_BAD); PREREQ(key, CKR_ARGUMENTS_BAD); - ret = ckcapi_session_get_lock_ref(session, 0, &sess); + ret = ckcapi_session_get_lock_ref(session, FALSE, &sess); if(ret == CKR_OK) { ret = ckcapi_session_get_object_data_for(sess, key, &objdata); @@ -1086,7 +1088,7 @@ CC_C_Sign(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, PREREQ(data, CKR_ARGUMENTS_BAD); PREREQ(data_len, CKR_ARGUMENTS_BAD); - ret = ckcapi_session_get_lock_ref(session, 0, &sess); + ret = ckcapi_session_get_lock_ref(session, FALSE, &sess); if(ret == CKR_OK) { ret = ckcapi_session_sign(sess, data, data_len, signature, signature_len); -- cgit v1.2.3