#include <pthread.h>
#include <stdlib.h>
#include <security/cryptoki.h>
#include "softGlobal.h"
#include "softObject.h"
#include "softSession.h"
#include "softKeystore.h"
#include "softKeystoreUtil.h"
CK_RV
C_CreateObject(CK_SESSION_HANDLE hSession,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phObject)
{
CK_RV rv;
soft_session_t *session_p;
boolean_t lock_held = B_FALSE;
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
rv = handle2session(hSession, &session_p);
if (rv != CKR_OK)
return (rv);
if ((pTemplate == NULL) || (ulCount == 0) ||
(phObject == NULL)) {
rv = CKR_ARGUMENTS_BAD;
goto clean_exit;
}
rv = soft_add_object(pTemplate, ulCount, phObject, session_p);
clean_exit:
SES_REFRELE(session_p, lock_held);
return (rv);
}
CK_RV
C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phNewObject)
{
CK_RV rv;
soft_session_t *session_p;
boolean_t lock_held = B_FALSE;
soft_object_t *old_object, *new_object = NULL;
ulong_t i;
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
rv = handle2session(hSession, &session_p);
if (rv != CKR_OK)
return (rv);
if (((ulCount > 0) && (pTemplate == NULL)) ||
(phNewObject == NULL)) {
rv = CKR_ARGUMENTS_BAD;
goto clean_exit;
}
HANDLE2OBJECT(hObject, old_object, rv);
if (rv != CKR_OK) {
goto clean_exit;
}
(void) pthread_mutex_lock(&old_object->object_mutex);
rv = soft_copy_object(old_object, &new_object, SOFT_COPY_OBJECT,
session_p);
if ((rv != CKR_OK) || (new_object == NULL)) {
(void) pthread_mutex_unlock(&old_object->object_mutex);
goto clean_exit1;
}
(void) pthread_mutex_unlock(&old_object->object_mutex);
for (i = 0; i < ulCount; i++) {
rv = soft_set_attribute(new_object, &pTemplate[i], B_TRUE);
if (rv != CKR_OK) {
goto fail;
}
}
rv = soft_pin_expired_check(new_object);
if (rv != CKR_OK) {
goto fail;
}
rv = soft_object_write_access_check(session_p, new_object);
if (rv != CKR_OK) {
goto fail;
}
if (IS_TOKEN_OBJECT(new_object)) {
new_object->version = 1;
rv = soft_put_object_to_keystore(new_object);
if (rv != CKR_OK) {
goto fail;
}
new_object->session_handle = CK_INVALID_HANDLE;
soft_add_token_object_to_slot(new_object);
OBJ_REFRELE(old_object);
SES_REFRELE(session_p, lock_held);
*phNewObject = set_objecthandle(new_object);
return (CKR_OK);
}
*phNewObject = set_objecthandle(new_object);
soft_add_object_to_session(new_object, session_p);
OBJ_REFRELE(old_object);
SES_REFRELE(session_p, lock_held);
return (rv);
fail:
soft_cleanup_object(new_object);
free(new_object);
clean_exit1:
OBJ_REFRELE(old_object);
clean_exit:
SES_REFRELE(session_p, lock_held);
return (rv);
}
CK_RV
C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
{
CK_RV rv;
soft_object_t *object_p;
soft_session_t *session_p;
boolean_t lock_held = B_FALSE;
CK_SESSION_HANDLE creating_session;
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
rv = handle2session(hSession, &session_p);
if (rv != CKR_OK)
return (rv);
HANDLE2OBJECT_DESTROY(hObject, object_p, rv);
if (rv != CKR_OK) {
SES_REFRELE(session_p, lock_held);
return (rv);
}
creating_session = object_p->session_handle;
if (creating_session == 0) {
rv = soft_pin_expired_check(object_p);
if (rv != CKR_OK) {
SES_REFRELE(session_p, lock_held);
return (rv);
}
rv = soft_object_write_access_check(session_p, object_p);
if (rv != CKR_OK) {
SES_REFRELE(session_p, lock_held);
return (rv);
}
(void) pthread_mutex_lock(&object_p->object_mutex);
if (object_p->obj_delete_sync & OBJECT_IS_DELETING) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
SES_REFRELE(session_p, lock_held);
return (CKR_OBJECT_HANDLE_INVALID);
}
object_p->obj_delete_sync |= OBJECT_IS_DELETING;
(void) pthread_mutex_unlock(&object_p->object_mutex);
SES_REFRELE(session_p, lock_held);
soft_delete_token_object(object_p, B_TRUE, B_FALSE);
return (CKR_OK);
}
if (hSession != creating_session) {
SES_REFRELE(session_p, lock_held);
rv = handle2session(creating_session, &session_p);
if (rv != CKR_OK)
return (rv);
}
(void) pthread_mutex_lock(&object_p->object_mutex);
if (object_p->obj_delete_sync & OBJECT_IS_DELETING) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
SES_REFRELE(session_p, lock_held);
return (CKR_OBJECT_HANDLE_INVALID);
}
object_p->obj_delete_sync |= OBJECT_IS_DELETING;
(void) pthread_mutex_unlock(&object_p->object_mutex);
soft_delete_object(session_p, object_p, B_FALSE, B_FALSE);
SES_REFRELE(session_p, lock_held);
return (rv);
}
CK_RV
C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
{
CK_RV rv = CKR_OK, rv1 = CKR_OK;
soft_object_t *object_p;
soft_session_t *session_p;
boolean_t lock_held = B_FALSE;
ulong_t i;
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
rv = handle2session(hSession, &session_p);
if (rv != CKR_OK)
return (rv);
if ((pTemplate == NULL) || (ulCount == 0)) {
SES_REFRELE(session_p, lock_held);
return (CKR_ARGUMENTS_BAD);
}
HANDLE2OBJECT(hObject, object_p, rv);
if (rv != CKR_OK) {
SES_REFRELE(session_p, lock_held);
return (rv);
}
if (IS_TOKEN_OBJECT(object_p)) {
rv = soft_keystore_load_latest_object(object_p);
if (rv != CKR_OK) {
OBJ_REFRELE(object_p);
SES_REFRELE(session_p, lock_held);
return (rv);
}
}
(void) pthread_mutex_lock(&object_p->object_mutex);
for (i = 0; i < ulCount; i++) {
rv = soft_get_attribute(object_p, &pTemplate[i]);
if (rv != CKR_OK)
rv1 = rv;
}
(void) pthread_mutex_unlock(&object_p->object_mutex);
OBJ_REFRELE(object_p);
SES_REFRELE(session_p, lock_held);
rv = rv1;
return (rv);
}
CK_RV
C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
{
CK_RV rv = CKR_OK;
soft_object_t *object_p;
soft_object_t *new_object = NULL;
soft_session_t *session_p;
boolean_t lock_held = B_FALSE;
ulong_t i;
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
rv = handle2session(hSession, &session_p);
if (rv != CKR_OK)
return (rv);
if ((pTemplate == NULL) || (ulCount == 0)) {
SES_REFRELE(session_p, lock_held);
return (CKR_ARGUMENTS_BAD);
}
HANDLE2OBJECT(hObject, object_p, rv);
if (rv != CKR_OK) {
SES_REFRELE(session_p, lock_held);
return (rv);
}
if (object_p->bool_attr_mask & NOT_MODIFIABLE_BOOL_ON) {
rv = CKR_ATTRIBUTE_READ_ONLY;
goto fail_1;
}
if (IS_TOKEN_OBJECT(object_p)) {
rv = soft_keystore_load_latest_object(object_p);
if (rv != CKR_OK) {
goto fail_1;
}
}
(void) pthread_mutex_lock(&object_p->object_mutex);
rv = soft_copy_object(object_p, &new_object, SOFT_SET_ATTR_VALUE, NULL);
if ((rv != CKR_OK) || (new_object == NULL)) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
goto fail_1;
}
(void) pthread_mutex_unlock(&object_p->object_mutex);
rv = soft_object_write_access_check(session_p, new_object);
if (rv != CKR_OK) {
goto fail;
}
for (i = 0; i < ulCount; i++) {
rv = soft_set_attribute(new_object, &pTemplate[i], B_FALSE);
if (rv != CKR_OK) {
goto fail;
}
}
(void) pthread_mutex_lock(&object_p->object_mutex);
soft_merge_object(object_p, new_object);
if (IS_TOKEN_OBJECT(object_p)) {
object_p->version++;
rv = soft_modify_object_to_keystore(object_p);
}
(void) pthread_mutex_unlock(&object_p->object_mutex);
free(new_object);
OBJ_REFRELE(object_p);
SES_REFRELE(session_p, lock_held);
return (rv);
fail:
soft_cleanup_object(new_object);
free(new_object);
fail_1:
OBJ_REFRELE(object_p);
SES_REFRELE(session_p, lock_held);
return (rv);
}
CK_RV
C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
CK_ULONG_PTR pulSize)
{
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
return (CKR_FUNCTION_NOT_SUPPORTED);
}
CK_RV
C_FindObjectsInit(CK_SESSION_HANDLE sh, CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount)
{
CK_RV rv;
soft_session_t *session_p;
boolean_t lock_held = B_TRUE;
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
rv = handle2session(sh, &session_p);
if (rv != CKR_OK)
return (rv);
if ((ulCount > 0) && (pTemplate == NULL)) {
lock_held = B_FALSE;
SES_REFRELE(session_p, lock_held);
return (CKR_ARGUMENTS_BAD);
}
(void) pthread_mutex_lock(&session_p->session_mutex);
if (session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE) {
SES_REFRELE(session_p, lock_held);
return (CKR_OPERATION_ACTIVE);
} else {
session_p->find_objects.flags = CRYPTO_OPERATION_ACTIVE;
}
(void) pthread_mutex_unlock(&session_p->session_mutex);
rv = soft_find_objects_init(session_p, pTemplate, ulCount);
if (rv != CKR_OK) {
(void) pthread_mutex_lock(&session_p->session_mutex);
session_p->find_objects.flags = 0;
(void) pthread_mutex_unlock(&session_p->session_mutex);
}
lock_held = B_FALSE;
SES_REFRELE(session_p, lock_held);
return (rv);
}
CK_RV
C_FindObjects(CK_SESSION_HANDLE sh,
CK_OBJECT_HANDLE_PTR phObject,
CK_ULONG ulMaxObjectCount,
CK_ULONG_PTR pulObjectCount)
{
soft_session_t *session_p;
CK_RV rv = CKR_OK;
boolean_t lock_held = B_TRUE;
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
rv = handle2session(sh, &session_p);
if (rv != CKR_OK)
return (rv);
if (((phObject == NULL) && (ulMaxObjectCount != 0)) ||
(pulObjectCount == NULL)) {
lock_held = B_FALSE;
SES_REFRELE(session_p, lock_held);
return (CKR_ARGUMENTS_BAD);
}
if (ulMaxObjectCount == 0) {
*pulObjectCount = 0;
lock_held = B_FALSE;
SES_REFRELE(session_p, lock_held);
return (CKR_OK);
}
(void) pthread_mutex_lock(&session_p->session_mutex);
if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
SES_REFRELE(session_p, lock_held);
return (CKR_OPERATION_NOT_INITIALIZED);
}
soft_find_objects(session_p, phObject, ulMaxObjectCount,
pulObjectCount);
SES_REFRELE(session_p, lock_held);
return (rv);
}
CK_RV
C_FindObjectsFinal(CK_SESSION_HANDLE sh)
{
soft_session_t *session_p;
CK_RV rv;
boolean_t lock_held = B_TRUE;
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
rv = handle2session(sh, &session_p);
if (rv != CKR_OK)
return (rv);
(void) pthread_mutex_lock(&session_p->session_mutex);
if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
SES_REFRELE(session_p, lock_held);
return (CKR_OPERATION_NOT_INITIALIZED);
}
soft_find_objects_final(session_p);
SES_REFRELE(session_p, lock_held);
return (rv);
}