summaryrefslogtreecommitdiff
path: root/ckcapi-session.c
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2008-12-09 20:09:51 +0000
committerStef Walter <stef@memberwebs.com>2008-12-09 20:09:51 +0000
commitd108e2008ec7205ef3907296fd3e5a810e45919b (patch)
treed4206f5c4187221523a0a47c255f5df00cf6596e /ckcapi-session.c
parent2ef411d0fb1923bf75c3c631992cdef787d0c619 (diff)
First shot at renaming the project.
Diffstat (limited to 'ckcapi-session.c')
-rw-r--r--ckcapi-session.c982
1 files changed, 0 insertions, 982 deletions
diff --git a/ckcapi-session.c b/ckcapi-session.c
deleted file mode 100644
index d1d345c..0000000
--- a/ckcapi-session.c
+++ /dev/null
@@ -1,982 +0,0 @@
-/*
- * Copyright (C) 2007 Stef Walter
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <stdlib.h>
-
-#include "ckcapi.h"
-#include "ckcapi-builtin.h"
-#include "ckcapi-cert.h"
-#include "ckcapi-key.h"
-#include "ckcapi-object.h"
-#include "ckcapi-rsa.h"
-#include "ckcapi-session.h"
-#include "ckcapi-token.h"
-#include "ckcapi-trust.h"
-
-/* For operation_type in CkCapiSession */
-enum
-{
- OPERATION_NONE,
- OPERATION_FIND,
- OPERATION_SIGN,
- OPERATION_DECRYPT
-};
-
-static CkCapiArray* all_sessions = NULL;
-
-static void
-object_data_release(CkCapiObjectData* objdata)
-{
- ASSERT(objdata->data_funcs);
- ASSERT(objdata->data_funcs->release);
- (objdata->data_funcs->release)(objdata);
-}
-
-CK_RV
-ckcapi_session_create(CK_SLOT_ID slot, CkCapiSession** ret)
-{
- CkCapiSession* sess;
- const char *store;
- DWORD err;
-
- sess = calloc(1, sizeof(CkCapiSession));
- if(!sess)
- return CKR_HOST_MEMORY;
-
- sess->object_data = ckcapi_hash_new(NULL, NULL);
- if(!sess->object_data) {
- free(sess);
- return CKR_HOST_MEMORY;
- }
-
- sess->mutex = CreateMutex(NULL, FALSE, NULL);
- if(!sess->mutex) {
- ckcapi_hash_free(sess->object_data, NULL);
- free(sess);
- return CKR_HOST_MEMORY;
- }
-
- store = ckcapi_token_get_store_name(slot);
- if(store)
- {
- sess->store = CertOpenSystemStore((HCRYPTPROV)NULL, store);
- if(sess->store == NULL)
- {
- err = GetLastError();
-
- /* Store not found, we don't care */
- if(err != ERROR_FILE_NOT_FOUND)
- {
- ckcapi_hash_free(sess->object_data, NULL);
- CloseHandle(sess->mutex);
- free(sess);
- return ckcapi_winerr_to_ckr(err);
- }
- }
- }
-
- sess->slot = slot;
-
- DBGS(sess, "created");
-
- *ret = sess;
- return CKR_OK;
-}
-
-CK_RV
-ckcapi_session_register(CkCapiSession* sess)
-{
- CkCapiSession* blank = NULL;
- CK_SESSION_HANDLE id = 0;
- CK_RV ret = CKR_OK;
- size_t i;
-
- ASSERT(sess);
- ASSERT(sess->id == 0 && sess->refs == 0);
-
- DBGS(sess, "registering new session");
-
- ckcapi_lock_global();
-
- /* Find a nice session identifier */
- while(id == 0) {
-
- /* Allocate sessions properly */
- if(!all_sessions)
- {
- all_sessions = ckcapi_array_new(0, 1, sizeof(CkCapiSession*));
- if(!all_sessions)
- {
- ret = CKR_HOST_MEMORY;
- break;
- }
-
- /* A blank entry for '0' */
- ckcapi_array_append(all_sessions, blank);
-
- DBG(("allocated new session list"));
- }
-
- /*
- * PKCS#11 GRAY AREA: We're assuming we can reuse session
- * handles. PKCS#11 spec says they're like file handles,
- * and file handles get reused :)
- */
-
- /* Note we never put anything in array position '0' */
- for(i = 1; i < all_sessions->len; ++i)
- {
- /* Any empty position will do */
- if(!ckcapi_array_index(all_sessions, CkCapiSession*, i))
- {
- id = i;
- break;
- }
- }
-
- /* Couldn't find a handle, append a handle */
- if(id == 0)
- {
- id = all_sessions->len;
- ckcapi_array_append(all_sessions, blank);
- }
- }
-
- if(ret == CKR_OK)
- {
- ASSERT(id > 0 && id < all_sessions->len);
- ASSERT(!ckcapi_array_index(all_sessions, CkCapiSession*, id));
-
-
- /* And assign it to the session handle */
- ckcapi_array_index(all_sessions, CkCapiSession*, i) = sess;
- sess->id = id;
-
- /* The session list reference */
- ASSERT(sess->refs == 0);
- sess->refs++;
-
- DBGS(sess, "registered sesson id");
- }
-
- ckcapi_unlock_global();
-
- return ret;
-}
-
-void
-ckcapi_session_destroy(CkCapiSession* sess)
-{
- ASSERT(sess);
- ASSERT(sess->refs == 0);
-
- /* Ask any pending operations to cleanup */
- if(sess->operation_type)
- {
- ASSERT(sess->operation_cancel);
- (sess->operation_cancel)(sess);
- }
-
- ASSERT(sess->operation_type == 0);
- ASSERT(sess->operation_data == NULL);
- ASSERT(sess->operation_cancel == NULL);
-
- if(sess->store)
- CertCloseStore(sess->store, 0);
-
- /* Make all the object adat go away */
- ASSERT(sess->object_data != NULL);
- ckcapi_hash_free(sess->object_data, object_data_release);
-
- /* And make the mutex go away */
- ASSERT(sess->mutex != NULL);
- CloseHandle(sess->mutex);
-
- DBGS(sess, "destroyed");
- free(sess);
-}
-
-void
-ckcapi_session_get_info(CkCapiSession* sess, CK_SESSION_INFO_PTR info)
-{
- ASSERT(sess);
- ASSERT(info);
-
- info->slotID = sess->slot;
- info->flags = CKF_SERIAL_SESSION;
- if(sess->read_write)
- info->flags |= CKF_RW_SESSION;
-
- if(ckcapi_token_is_logged_in(sess->slot))
- info->state = sess->read_write ? CKS_RW_USER_FUNCTIONS : CKS_RO_USER_FUNCTIONS;
- else
- info->state = sess->read_write ? CKS_RW_PUBLIC_SESSION : CKS_RO_PUBLIC_SESSION;
-
- /* TODO: We could implement some use of GetLastError() here */
- info->ulDeviceError = 0;
-}
-
-static CK_RV
-lock_ref_internal(CkCapiArray* sessions, CK_SESSION_HANDLE id,
- BOOL remove, BOOL writable, CkCapiSession** sess_ret)
-{
- CkCapiSession *sess;
- DWORD r;
-
- ASSERT(sessions);
- ASSERT(sess_ret);
-
- if(id >= sessions->len)
- {
- DBG(("invalid session id: %d", id));
- return CKR_SESSION_HANDLE_INVALID;
- }
-
- /* A seemingly valid id */
- ASSERT(sessions);
- sess = ckcapi_array_index(sessions, CkCapiSession*, id);
-
- if(!sess)
- {
- DBG(("session does not exist: %d", 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 */
- if(!remove)
- {
- /*
- * An initial check is done to make sure this session is not active.
- * This is done outside of the lock. The real check is done later
- * inside a lock. This is so we can return quickly without blocking
- * in most cases.
- */
-
- if(sess->in_call)
- {
- DBGS(sess, ("an operation is already active in this session"));
- return CKR_OPERATION_ACTIVE;
- }
- }
-
- /* Lock the CallCkCapiSession */
- r = WaitForSingleObject(sess->mutex, INFINITE);
- ASSERT(r == WAIT_OBJECT_0);
-
- /* Do the real check */
- if(!remove && sess->in_call)
- {
- ReleaseMutex(sess->mutex);
- DBGS(sess, ("an operation is already active in this session"));
- return CKR_OPERATION_ACTIVE;
- }
-
- /* Make sure it doesn't go away */
- ASSERT(sess->refs > 0);
- sess->refs++;
-
- DBGS(sess, "found and locked session");
-
- /* And remove it if necessary */
- if(remove)
- {
- ckcapi_array_index(sessions, CkCapiSession*, id) = NULL;
-
- /* The session list reference */
- sess->refs--;
- ASSERT(sess->refs > 0);
-
- DBGS(sess, "removed session from list");
- }
- else
- {
- ASSERT(!sess->in_call);
- sess->in_call = 1;
- }
-
- *sess_ret = sess;
- return CKR_OK;
-}
-
-CK_RV
-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 */
-
- 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, TRUE, FALSE, sess);
-
- ckcapi_unlock_global();
-
- return ret;
-}
-
-void
-ckcapi_session_unref_unlock(CkCapiSession* sess)
-{
- /* The CallCkCapiSession must be locked at this point */
-
- int refs;
- BOOL r;
-
- ASSERT(sess);
-
- ASSERT(sess->refs > 0);
- sess->refs--;
- refs = sess->refs;
-
- sess->in_call = 0;
-
- DBGS(sess, "unlocked session");
-
- r = ReleaseMutex(sess->mutex);
- ASSERT(r == TRUE);
-
- /*
- * At this point if no references are held, then we can safely
- * delete. No other thread should be involved.
- */
-
- if(refs == 0)
- ckcapi_session_destroy(sess);
-}
-
-CK_RV
-ckcapi_session_close_all(CK_SLOT_ID slot)
-{
- /* This must be called without any locks held */
-
- CkCapiArray* sessions;
- CkCapiSession *sess;
- size_t i;
- CK_RV ret = CKR_OK;
-
- /*
- * PKCS#11 GRAY AREA: What happens when this gets called
- * concurrently? We don't return an error on the second call,
- * because by the time it returns, all sessions should be closed.
- */
-
- DBG(("closing all sessions for: %d", slot));
-
- if(!all_sessions)
- return CKR_OK;
-
- ckcapi_lock_global();
-
- sessions = ckcapi_array_sized_new(0, 1, sizeof(CkCapiSession*),
- all_sessions->len);
- if(!sessions)
- ret = CKR_HOST_MEMORY;
-
- /* Steal all the session data */
- if(ret == CKR_OK)
- {
- for(i = 0; i < all_sessions->len; ++i)
- {
- sess = ckcapi_array_index(all_sessions, CkCapiSession*, i);
- if(sess && (slot == ((CK_SLOT_ID)-1) || sess->slot == slot))
- {
- /* Steal this session */
- ckcapi_array_index(all_sessions, CkCapiSession*, i) = NULL;
- }
- else
- {
- /* Not a session we're interested in */
- sess = NULL;
- }
-
- /* Both null and normal sessions are set to preserve indexes */
- ckcapi_array_append(sessions, sess);
- }
-
- ASSERT(sessions->len == all_sessions->len);
- }
-
- ckcapi_unlock_global();
-
- if(ret != CKR_OK)
- return ret;
-
- /* Close each session in turn */
- for(i = 0; i < sessions->len; ++i)
- {
- if(!ckcapi_array_index(sessions, CkCapiSession*, i))
- continue;
-
- /* We need any calls in other threads to finish, so wait here */
- if(lock_ref_internal(sessions, i, TRUE, FALSE, &sess) == CKR_OK)
- ckcapi_session_unref_unlock(sess);
- }
-
- /* We stole the memory above, free it now */
- ckcapi_array_free(sessions, 1);
- return CKR_OK;
-}
-
-void
-ckcapi_session_cleanup_all()
-{
- ckcapi_session_close_all((CK_SLOT_ID)-1);
-
- ckcapi_lock_global();
-
- ckcapi_array_free(all_sessions, 1);
- all_sessions = NULL;
-
- ckcapi_unlock_global();
-}
-
-/* ----------------------------------------------------------------------------
- * OBJECT DATA
- */
-
-CK_RV
-ckcapi_session_get_object_data(CkCapiSession* sess, CkCapiObject* obj,
- CkCapiObjectData** objdata)
-{
- CK_OBJECT_HANDLE id;
- CkCapiObjectData* newdata;
- CK_RV ret;
-
- ASSERT(sess);
- ASSERT(sess->object_data);
- ASSERT(obj);
- ASSERT(obj->obj_funcs);
- ASSERT(obj->obj_funcs->load_data);
- ASSERT(objdata);
-
- id = obj->id;
-
- *objdata = ckcapi_hash_get(sess->object_data, ckcapi_hash_key(id));
- if(*objdata)
- return CKR_OK;
-
- ret = (obj->obj_funcs->load_data)(sess, obj, &newdata);
- if(ret != CKR_OK)
- return ret;
-
- newdata->object = id;
- ASSERT(newdata->data_funcs);
-
- if(!ckcapi_hash_set(sess->object_data, ckcapi_hash_key(id), newdata)) {
- object_data_release(newdata);
- return CKR_HOST_MEMORY;
- }
-
- *objdata = newdata;
- return CKR_OK;
-}
-
-void
-ckcapi_session_clear_object_data(CkCapiSession* sess, CkCapiObject* obj)
-{
- CkCapiObjectData* objdata;
-
- ASSERT(sess);
- ASSERT(sess->object_data);
- ASSERT(obj);
-
- objdata = (CkCapiObjectData*)ckcapi_hash_rem(sess->object_data, ckcapi_hash_key(obj->id));
- if(objdata)
- object_data_release(objdata);
-}
-
-void
-ckcapi_session_enum_object_data(CkCapiSession* sess,
- CkCapiEnumObjectData enum_func, void* arg)
-{
- CK_OBJECT_HANDLE i, max;
- CkCapiObject* obj;
- CkCapiObjectData* objdata;
-
- ASSERT(sess);
- ASSERT(sess->object_data);
- ASSERT(enum_func);
-
- max = ckcapi_token_get_max_handle();
- for(i = 0; i < max; ++i)
- {
- objdata = (CkCapiObjectData*)ckcapi_hash_get(sess->object_data, ckcapi_hash_key(i));
- if(!objdata)
- continue;
-
- obj = ckcapi_token_lookup_object(sess->slot, i);
- if(!obj)
- continue;
-
- (enum_func)(sess, obj, objdata, arg);
- }
-}
-
-CK_RV
-ckcapi_session_get_object_data_for(CkCapiSession* sess, CK_OBJECT_HANDLE hand,
- CkCapiObjectData** objdata)
-{
- CkCapiObject* obj;
-
- obj = ckcapi_token_lookup_object(sess->slot, hand);
- if(!obj)
- return CKR_OBJECT_HANDLE_INVALID;
-
- return ckcapi_session_get_object_data(sess, obj, objdata);
-}
-
-void
-ckcapi_session_take_object_data(CkCapiSession* sess, CkCapiObject* obj,
- CkCapiObjectData* objdata)
-{
- CkCapiObjectData* prev;
-
- ASSERT(obj);
- ASSERT(sess);
- ASSERT(sess->object_data);
-
- ASSERT(objdata);
- objdata->object = obj->id;
-
- prev = ckcapi_hash_rem(sess->object_data, ckcapi_hash_key(obj->id));
- if(prev)
- object_data_release(prev);
-
- if(!ckcapi_hash_set(sess->object_data, ckcapi_hash_key(obj->id), objdata))
- object_data_release(objdata);
-}
-
-
-/* ----------------------------------------------------------------------------
- * FIND OPERATION
- */
-
-static BOOL
-get_ulong_attribute(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR templ,
- CK_ULONG count, CK_ULONG* val)
-{
- CK_ULONG i;
-
- ASSERT(val);
- ASSERT(!count || templ);
-
- for(i = 0; i < count; ++i)
- {
- if(templ[i].type == type)
- {
- *val = *((CK_ULONG*)templ[i].pValue);
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static CK_RV
-gather_objects(CkCapiSession* sess, CK_ATTRIBUTE_PTR match,
- CK_ULONG count, CkCapiArray* arr)
-{
- CK_OBJECT_CLASS ocls = CKO_ANY;
- CK_RV ret = CKR_OK;
-
- get_ulong_attribute(CKA_CLASS, match, count, &ocls);
-
- /* Search for builtins */
- ret = ckcapi_builtin_find(sess, ocls, match, count, arr);
- if(ret != CKR_OK)
- return ret;
-
- /*
- * Search through certificates.
- *
- * We always do this search first. In Windows a lots hangs off
- * the certificates. For example private keys are not contained
- * in the same stores that certificates are in. There are a different
- * set of key containers many of which can be used together
- * with a certificate stored in any store.
- *
- * The trust objects we expose also depend on the certificates
- * loaded.
- */
- ret = ckcapi_cert_find(sess, ocls, match, count, arr);
- if(ret != CKR_OK)
- return ret;
-
- /* Search through trust objects */
- ret = ckcapi_trust_find(sess, ocls, match, count, arr);
- if(ret != CKR_OK)
- return ret;
-
- /* Search through key objects */
- ret = ckcapi_key_find(sess, ocls, match, count, arr);
- if(ret != CKR_OK)
- return ret;
-
- return ret;
-}
-
-void
-cleanup_find_operation(CkCapiSession* sess)
-{
- ASSERT(sess->operation_type == OPERATION_FIND);
- if(sess->operation_data)
- ckcapi_array_free((CkCapiArray*)sess->operation_data, TRUE);
- sess->operation_type = OPERATION_NONE;
- sess->operation_data = NULL;
- sess->operation_cancel = NULL;
-}
-
-void
-purge_duplicate_objects(CkCapiArray* arr)
-{
- CkCapiHash* checks;
- CK_OBJECT_HANDLE v;
- size_t i;
-
- checks = ckcapi_hash_new(NULL, NULL);
- if(!checks)
- return;
-
- for(i = 0; i < arr->len; )
- {
- v = ckcapi_array_index(arr, CK_OBJECT_HANDLE, i);
- if(ckcapi_hash_get(checks, ckcapi_hash_key(v)))
- {
- ckcapi_array_remove_index(arr, i);
- /* Look at same i again */
- }
- else
- {
- if(!ckcapi_hash_set(checks, ckcapi_hash_key(v), arr))
- break;
- ++i;
- }
- }
-
- ckcapi_hash_free(checks, NULL);
-}
-
-CK_RV
-ckcapi_session_find_init(CkCapiSession* sess, CK_ATTRIBUTE_PTR match,
- CK_ULONG count)
-{
- CkCapiArray* arr;
- CK_RV ret;
-
- ASSERT(sess);
- ASSERT(!count || match);
-
- if(sess->operation_type != OPERATION_NONE)
- return CKR_OPERATION_ACTIVE;
-
- arr = ckcapi_array_new(0, 1, sizeof(CK_OBJECT_HANDLE));
- if(!arr)
- return CKR_HOST_MEMORY;
-
- ret = gather_objects(sess, match, count, arr);
- if(ret != CKR_OK)
- {
- ckcapi_array_free(arr, TRUE);
- return ret;
- }
-
- /* Cleanup all duplicates in the array */
- purge_duplicate_objects(arr);
-
- sess->operation_type = OPERATION_FIND;
- sess->operation_data = arr;
- sess->operation_cancel = cleanup_find_operation;
-
- return CKR_OK;
-}
-
-CK_RV
-ckcapi_session_find(CkCapiSession* sess, CK_OBJECT_HANDLE_PTR objects,
- CK_ULONG max_object_count, CK_ULONG_PTR object_count)
-{
- CkCapiArray* arr;
- size_t i;
-
- ASSERT(sess);
- ASSERT(object_count);
- ASSERT(!max_object_count || objects);
-
- if(sess->operation_type != OPERATION_FIND)
- return CKR_OPERATION_NOT_INITIALIZED;
-
- if(!max_object_count)
- {
- *object_count = 0;
- return CKR_OK;
- }
-
- arr = (CkCapiArray*)sess->operation_data;
- *object_count = (max_object_count > arr->len ? arr->len : max_object_count);
- for(i = 0; i < *object_count; ++i)
- objects[i] = ckcapi_array_index(arr, CK_OBJECT_HANDLE, i);
-
- ckcapi_array_remove_range(arr, 0, *object_count);
-
- return CKR_OK;
-}
-
-CK_RV
-ckcapi_session_find_final(CkCapiSession* sess)
-{
- ASSERT(sess);
-
- if(sess->operation_type != OPERATION_FIND)
- return CKR_OPERATION_NOT_INITIALIZED;
-
- cleanup_find_operation(sess);
- return CKR_OK;
-}
-
-
-/* ----------------------------------------------------------------------------
- * CRYPTO OPERATIONS
- */
-
-typedef struct _CryptoContext
-{
- CK_MECHANISM_TYPE mech_type;
- CkCapiDestroyFunc mech_cleanup;
- void* mech_data;
-}
-CryptoContext;
-
-void
-cleanup_crypto_operation(CkCapiSession* sess)
-{
- CryptoContext* ctx;
-
- if(sess->operation_data)
- {
- ctx = (CryptoContext*)sess->operation_data;
- if(ctx->mech_cleanup)
- (ctx->mech_cleanup)(ctx->mech_data);
- free(ctx);
- }
-
- sess->operation_type = OPERATION_NONE;
- sess->operation_data = NULL;
- sess->operation_cancel = NULL;
-}
-
-CK_RV
-ckcapi_session_sign_init(CkCapiSession* sess, CK_MECHANISM_PTR mech,
- CkCapiObjectData *objdata)
-{
- CryptoContext* ctx;
- CK_RV ret;
-
- ASSERT(sess);
- ASSERT(mech);
- ASSERT(objdata);
-
- if(sess->operation_type != OPERATION_NONE)
- return CKR_OPERATION_ACTIVE;
-
- ctx = calloc(1, sizeof(CryptoContext));
- if(!ctx)
- return CKR_HOST_MEMORY;
-
- ctx->mech_type = mech->mechanism;
-
- switch(mech->mechanism)
- {
- case CKM_RSA_PKCS:
- ret = ckcapi_rsa_pkcs_sign_init(objdata, &ctx->mech_data);
- ctx->mech_cleanup = ckcapi_rsa_pkcs_sign_cleanup;
- break;
- default:
- ret = CKR_MECHANISM_INVALID;
- break;
- };
-
- if(ret != CKR_OK)
- {
- free(ctx);
- ASSERT(!sess->operation_data);
- return ret;
- }
-
- sess->operation_type = OPERATION_SIGN;
- sess->operation_data = ctx;
- sess->operation_cancel = cleanup_crypto_operation;
- return CKR_OK;
-}
-
-CK_RV
-ckcapi_session_sign(CkCapiSession* sess, CK_BYTE_PTR data, CK_ULONG n_data,
- CK_BYTE_PTR signature, CK_ULONG_PTR n_signature)
-{
- CryptoContext *ctx;
- BOOL incomplete;
- CK_RV ret;
-
- ASSERT(sess);
- ASSERT(data);
- ASSERT(n_data);
-
- if(sess->operation_type != OPERATION_SIGN)
- return CKR_OPERATION_NOT_INITIALIZED;
-
- ctx = (CryptoContext*)sess->operation_data;
- switch(ctx->mech_type)
- {
- case CKM_RSA_PKCS:
- ret = ckcapi_rsa_pkcs_sign_perform(data, n_data, signature, n_signature,
- &ctx->mech_data);
- break;
-
- default:
- ASSERT(FALSE);
- ret = CKR_GENERAL_ERROR;
- break;
- }
-
- /* Buffer calculation, we don't end operation */
- incomplete = (ret == CKR_BUFFER_TOO_SMALL || (ret == CKR_OK && !signature));
-
- if(!incomplete)
- cleanup_crypto_operation(sess);
-
- return ret;
-}
-
-CK_RV
-ckcapi_session_decrypt_init(CkCapiSession* sess, CK_MECHANISM_PTR mech,
- CkCapiObjectData *objdata)
-{
- CryptoContext* ctx;
- CK_RV ret;
-
- ASSERT(sess);
- ASSERT(mech);
- ASSERT(objdata);
-
- if(sess->operation_type != OPERATION_NONE)
- return CKR_OPERATION_ACTIVE;
-
- ctx = calloc(1, sizeof(CryptoContext));
- if(!ctx)
- return CKR_HOST_MEMORY;
-
- ctx->mech_type = mech->mechanism;
-
- switch(mech->mechanism)
- {
- case CKM_RSA_PKCS:
- ret = ckcapi_rsa_pkcs_decrypt_init(objdata, &ctx->mech_data);
- ctx->mech_cleanup = ckcapi_rsa_pkcs_decrypt_cleanup;
- break;
- default:
- ret = CKR_MECHANISM_INVALID;
- break;
- };
-
- if(ret != CKR_OK)
- {
- free(ctx);
- ASSERT(!sess->operation_data);
- return ret;
- }
-
- sess->operation_type = OPERATION_DECRYPT;
- sess->operation_data = ctx;
- sess->operation_cancel = cleanup_crypto_operation;
- return CKR_OK;
-}
-
-CK_RV
-ckcapi_session_decrypt(CkCapiSession* sess, CK_BYTE_PTR encdata, CK_ULONG n_encdata,
- CK_BYTE_PTR result, CK_ULONG_PTR n_result)
-{
- CryptoContext *ctx;
- BOOL incomplete;
- CK_RV ret;
-
- ASSERT(sess);
- ASSERT(encdata);
- ASSERT(n_encdata);
-
- if(sess->operation_type != OPERATION_DECRYPT)
- return CKR_OPERATION_NOT_INITIALIZED;
-
- ctx = (CryptoContext*)sess->operation_data;
- switch(ctx->mech_type)
- {
- case CKM_RSA_PKCS:
- ret = ckcapi_rsa_pkcs_decrypt_perform(encdata, n_encdata, result, n_result,
- &ctx->mech_data);
- break;
-
- default:
- ASSERT(FALSE);
- ret = CKR_GENERAL_ERROR;
- break;
- }
-
- /* Buffer calculation, we don't end operation */
- incomplete = (ret == CKR_BUFFER_TOO_SMALL || (ret == CKR_OK && !result));
-
- if(!incomplete)
- cleanup_crypto_operation(sess);
-
- return ret;
-}