From 58345488c9351d9be9a4be27c8b407c2706a33a9 Mon Sep 17 00:00:00 2001
From: Joy Latten <jmlatten@users.sourceforge.net>
Date: Fri, 20 Jan 2012 14:14:02 -0600
Subject: [PATCH] Renamed spinlocks are created in /var/lock.
 Also includes testcases.

Signed-off-by: Joy Latten <jmlatten@users.sourceforge.net>
---
 configure.in                           |    1 
 testcases/Makefile.am                  |    2 
 testcases/misc_tests/Makefile.am       |    8 
 testcases/misc_tests/README            |   61 +
 testcases/misc_tests/obj_mgmt.c        | 1463 +++++++++++++++++++++++++++++++++
 testcases/misc_tests/obj_mgmt_lock.c   | 1282 ++++++++++++++++++++++++++++
 testcases/misc_tests/spinlock_child.sh |   26 
 testcases/misc_tests/spinlock_tests.sh |   36 
 usr/include/pkcs11/slotmgr.h           |   62 -
 usr/lib/pkcs11/api/api_interface.c     |   16 
 usr/lib/pkcs11/api/apiutil.c           |   31 
 usr/lib/pkcs11/cca_stdll/h_extern.h    |    1 
 usr/lib/pkcs11/cca_stdll/loadsave.c    |    2 
 usr/lib/pkcs11/cca_stdll/new_host.c    |    4 
 usr/lib/pkcs11/cca_stdll/utility.c     |   61 -
 usr/lib/pkcs11/common/h_extern.h       |    1 
 usr/lib/pkcs11/common/new_host.c       |    8 
 usr/lib/pkcs11/common/obj_mgr.c        |   19 
 usr/lib/pkcs11/common/utility.c        |   62 -
 usr/lib/pkcs11/soft_stdll/Makefile.am  |    2 
 usr/lib/pkcs11/tpm_stdll/Makefile.am   |    2 
 usr/lib/pkcs11/tpm_stdll/h_extern.h    |    1 
 usr/lib/pkcs11/tpm_stdll/new_host.c    |    4 
 usr/lib/pkcs11/tpm_stdll/utility.c     |   63 -
 usr/sbin/pkcscca_migrate/Makefile.am   |    4 
 usr/sbin/pkcsconf/Makefile.am          |    4 
 usr/sbin/pkcsslotd/mutex.c             |   11 
 usr/sbin/pkcsslotd/pkcsslotd.h         |    1 
 usr/sbin/pkcsslotd/signal.c            |    6 
 usr/sbin/pkcsslotd/slotmgr.c           |    7 
 30 files changed, 2972 insertions(+), 279 deletions(-)
 create mode 100644 testcases/misc_tests/Makefile.am
 create mode 100644 testcases/misc_tests/README
 create mode 100644 testcases/misc_tests/obj_mgmt.c
 create mode 100644 testcases/misc_tests/obj_mgmt_lock.c
 create mode 100755 testcases/misc_tests/spinlock_child.sh
 create mode 100755 testcases/misc_tests/spinlock_tests.sh

--- a/configure.in
+++ b/configure.in
@@ -668,6 +668,7 @@ AC_CONFIG_FILES([Makefile usr/Makefile \
 	  testcases/tok_obj/Makefile \
 	  testcases/v2.11/Makefile \
 	  testcases/login/Makefile \
+	  testcases/misc_tests/Makefile \
 	  man/Makefile \
 	  man/man1/Makefile \
 	  man/man1/pkcsconf.1 \
--- a/testcases/Makefile.am
+++ b/testcases/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS=common driver init_tok mkobj oc-digest rsa_keygen rsa_test speed test_crypto threadmkobj tok_obj v2.11 login
+SUBDIRS=common driver init_tok mkobj oc-digest rsa_keygen rsa_test speed test_crypto threadmkobj tok_obj v2.11 login misc_tests
 
 noinst_SCRIPTS = ock_tests.sh init_token.sh
 
--- /dev/null
+++ b/testcases/misc_tests/Makefile.am
@@ -0,0 +1,8 @@
+noinst_PROGRAMS=obj_mgmt_tests obj_mgmt_lock_tests
+
+AM_CFLAGS=-I. -I../../usr/include/pkcs11 -I../include -I../common -I../../usr/lib/pkcs11/common -Wall
+
+AM_LDFLAGS=-L../common -lc  -ldl -lpthread -lcommon
+
+obj_mgmt_tests_SOURCES = obj_mgmt.c
+obj_mgmt_lock_tests_SOURCES = obj_mgmt_lock.c
--- /dev/null
+++ b/testcases/misc_tests/README
@@ -0,0 +1,61 @@
+Miscellaneous tests
+
+Object Management testing
+
+obj_mgmt_tests
+obj_mgmt.c - This testsuite performs various object management tasks.
+The do_CreateTokenObjects() and do_HWFeatureSearch() functions
+create token objects and by default or skipped.
+To include these two functions, use the "-noskip" option when issuing the tests.
+
+-----------------------------------------------------------------------------
+Spinlock testing
+
+Quick Start Info:
+
+Execute testcase by, 
+	spinlock_tests.sh -p <num> -l <num> -s <slotid>
+	p: the amount of child processes to create
+	l: the number of times each child process executes obj_mgmt_lock_tests
+	s: the slot to test
+
+For example, 
+	spinlock_tests.sh -p 15 -l 5 -s 1
+
+
+Additional Info:
+
+obj_mgmt_lock_tests
+spinlock_tests.sh
+spinlock_child.sh
+These test two spinlocks:
+	- /var/lock/LCK..opencryptoki which is used when accessing shared
+	  memory for pkcsslotd and pkcs#11 api calls.
+	- /var/lock/LOCK..opencryptoki_stdll which is used when accessing
+	  global shared memory in the STDLLs.
+
+The file, spinlock_tests.sh is a bash script that creates a
+number of child processes. Each child process runs spinlock_child.sh script.
+
+Usage: spinlock_tests.sh -p <num> -l <count> -s <slotid>
+	p: the amount of child processes to create
+	l: the number of times each child process executes obj_mgmt_lock_tests
+	s: the slot to test
+
+The file, spinlock_child.sh is a bash script that executes
+obj_mgmt_lock_tests a number of times. It, along with any arguments is called
+from spinlock_tests.sh script. However, it can also be run independently.
+
+Usage: spinlock_child.sh -l <count> -s <slotid>
+	l: the number of times each child process executes obj_mgmt_lock_tests
+	s: the slot to test
+
+So each child process created in spinlock_tests.sh will run
+obj_mgmt_lock_tests a number of times to test the spinlocks.
+
+obj_mgmt_lock_tests was derived from obj_mgmt.c.
+It contains several api calls that will want to acquire the various
+spinlocks.
+
+Usage: obj_mgmt_lock_tests -slot <slotid>
+
--- /dev/null
+++ b/testcases/misc_tests/obj_mgmt.c
@@ -0,0 +1,1463 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+
+#include "pkcs11types.h"
+#include "regress.h"
+#include "common.c"
+
+
+#define AES_KEY_SIZE_128	16
+
+/* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock.
+ * C_OpenSession
+ * C_CloseSession
+ *
+ * API Routines exercised that cause stdll to take /var/lock/opencryptoki_stdll
+ * spinlock.
+ * C_CreateObject
+ * C_Login
+ *
+ * 1) create a data object
+ * 2) create a certificate
+ * 3) create a key object
+ */
+CK_RV do_CreateSessionObject(void)
+{
+	CK_SLOT_ID        slot_id;
+	CK_FLAGS          flags;
+	CK_SESSION_HANDLE h_session;
+	CK_RV             rc = 0;
+	CK_BYTE           user_pin[PKCS11_MAX_PIN_LEN];
+	CK_ULONG          user_pin_len;
+
+	CK_BYTE           true  = TRUE;
+	CK_BYTE           false = FALSE;
+
+	CK_OBJECT_HANDLE  h_data;
+	CK_OBJECT_CLASS   data_class         = CKO_DATA;
+	CK_BYTE           data_application[] = "Test Application";
+	CK_BYTE           data_value[]       = "1234567890abcedfghijklmnopqrstuvwxyz";
+	CK_ATTRIBUTE      data_attribs[] =
+	{
+		{CKA_CLASS,       &data_class,       sizeof(data_class)       },
+		{CKA_TOKEN,       &false,            sizeof(false)            },
+		{CKA_APPLICATION, &data_application, sizeof(data_application) },
+		{CKA_VALUE,       &data_value,       sizeof(data_value)       }
+	};
+
+	CK_OBJECT_HANDLE    h_cert;
+	CK_OBJECT_CLASS     cert_class         = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert_type          = CKC_X_509;
+	CK_BYTE             cert_subject[]     = "Certificate subject";
+	CK_BYTE             cert_id[]          = "Certificate ID";
+	CK_BYTE             cert_value[]       = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+	CK_ATTRIBUTE        cert_attribs[] =
+	{
+		{CKA_CLASS,            &cert_class,       sizeof(cert_class)   },
+		{CKA_TOKEN,            &false,            sizeof(false)        },
+		{CKA_CERTIFICATE_TYPE, &cert_type,        sizeof(cert_type)    },
+		{CKA_SUBJECT,          &cert_subject,     sizeof(cert_subject) },
+		{CKA_ID,               &cert_id,          sizeof(cert_id)      },
+		{CKA_VALUE,            &cert_value,       sizeof(cert_value)   }
+	};
+
+	CK_OBJECT_HANDLE  h_key;
+	CK_OBJECT_CLASS   key_class          = CKO_PUBLIC_KEY;
+	CK_KEY_TYPE       key_type           = CKK_RSA;
+	CK_BYTE           key_modulus[]      = "1234567890987654321";
+	CK_BYTE           key_exponent[]     = "123";
+	CK_ATTRIBUTE      key_attribs[] =
+	{
+		{CKA_CLASS,           &key_class,    sizeof(key_class)    },
+		{CKA_KEY_TYPE,        &key_type,     sizeof(key_type)     },
+		{CKA_WRAP,            &true,         sizeof(true)         },
+		{CKA_MODULUS,         &key_modulus,  sizeof(key_modulus)  },
+		{CKA_PUBLIC_EXPONENT, &key_exponent, sizeof(key_exponent) }
+	};
+
+	testcase_begin("starting...");
+
+	if (get_user_pin(user_pin))
+		return CKR_FUNCTION_FAILED;
+	user_pin_len = (CK_ULONG)strlen((char *)user_pin);
+
+	slot_id = SLOT_ID;
+
+
+	// create a USER R/W session
+	//
+	flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
+	rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session);
+	if (rc != CKR_OK) {
+		testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if (rc != CKR_OK) {
+		testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	//
+	// now, create the objects
+	//
+
+	rc = funcs->C_CreateObject(h_session, data_attribs, 4, &h_data);
+	if (rc != CKR_OK) {
+		testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_CreateObject(h_session, cert_attribs, 6, &h_cert);
+	if (rc != CKR_OK) {
+		testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_CreateObject(h_session, key_attribs, 5, &h_key);
+	if (rc != CKR_OK) {
+		testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	// done...close the session and verify the object is deleted
+	//
+	rc = funcs->C_CloseAllSessions(slot_id);
+	if (rc != CKR_OK) {
+		testcase_fail("C_CloseAllSessions() rc=%s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	testcase_pass("looks okay...");
+	return rc;
+}
+
+/* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock.
+ * C_OpenSession
+ * C_CloseSession
+ *
+ * API routines exercised that result in stdll taking
+ * /var/lock/opencryptoki_stdll spinlock.
+ *    C_CreateObject
+ *    C_CopyObject
+ *    C_DestroyObject
+ *    C_GetAttributeValue
+ *    C_GetObjectSize
+ *
+ * 1) create a data object with no CKA_APPLICATION attribute
+ * 2) create a copy of the object specifying the CKA_APPLICATION attribute
+ * 3) extract the CK_VALUE attribute from the copy. Ensure matches the original
+ * 4) extract the CKA_APPLICATION attribute from the original. ensure empty.
+ * 5) extract the CKA_APPLICATION attribute from the copy. ensure is correct.
+ * 6) attempt to extract CK_PRIME from the original. ensure fails correctly.
+ * 7) attempt to extract CK_PRIME from a non-existant object. ensure fails
+ *    correctly.
+ * 8) get the size of the original object and copied objects
+ * 9) destroy the original object.  ensure this succeeds.
+ * A) destroy a non-existant object.  ensure this fails correctly.
+ * B) get the size of the original object.  ensure this fails correctly.
+ */
+CK_RV do_CopyObject(void)
+{
+	CK_SLOT_ID        slot_id;
+	CK_FLAGS          flags;
+	CK_SESSION_HANDLE h_session;
+	CK_RV             rc = 0;
+	CK_BYTE           user_pin[PKCS11_MAX_PIN_LEN];
+	CK_ULONG          user_pin_len;
+	CK_ULONG          obj_size;
+
+	CK_BYTE           false = FALSE;
+
+	CK_OBJECT_HANDLE  h_data;
+	CK_OBJECT_CLASS   data_class         = CKO_DATA;
+	CK_BYTE           data_application[] = "Test Application";
+	CK_BYTE           data_value[]       = "1234567890abcedfghijklmnopqrstuvwxyz";
+	CK_ATTRIBUTE      data_attribs[] =
+	{
+		{CKA_CLASS,       &data_class,       sizeof(data_class)       },
+		{CKA_TOKEN,       &false,            sizeof(false)            },
+		{CKA_VALUE,       &data_value,       sizeof(data_value)       }
+	};
+
+	CK_OBJECT_HANDLE  h_copy;
+	CK_ATTRIBUTE      copy_attribs[] =
+	{
+		{CKA_APPLICATION, &data_application, sizeof(data_application) }
+	};
+
+	CK_BYTE           buf1[100];
+	CK_ATTRIBUTE      verify_attribs[] =
+	{
+		{CKA_APPLICATION, &buf1, sizeof(buf1) }
+	};
+
+	CK_BYTE           buf2[100];
+	CK_ATTRIBUTE      prime_attribs[] =
+	{
+		{CKA_PRIME, &buf2, sizeof(buf2) }
+	};
+
+	testcase_begin("starting...");
+
+	if (get_user_pin(user_pin))
+		return CKR_FUNCTION_FAILED;
+	user_pin_len = (CK_ULONG)strlen((char *)user_pin);
+
+	slot_id = SLOT_ID;
+
+
+	/* create a USER R/W session */
+	flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
+	rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session);
+	if (rc != CKR_OK) {
+		testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if (rc != CKR_OK) {
+		testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+
+	/* create the object */
+	rc = funcs->C_CreateObject(h_session, data_attribs, 3, &h_data);
+	if (rc != CKR_OK) {
+		testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* create the copy */
+	rc = funcs->C_CopyObject(h_session, h_data, copy_attribs, 1, &h_copy);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CopyObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, try to extract the CKA_APPLICATION attribute from the original
+	 * this will pull in the token's default value for CKA_APPLICATION which
+	 */
+	verify_attribs[0].ulValueLen = sizeof(buf1);
+	rc = funcs->C_GetAttributeValue(h_session, h_data, verify_attribs, 1);
+	if (rc != CKR_OK) {
+		testcase_fail("C_GetAttributeValue() rc=%s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, try to extract the CKA_APPLICATION attribute from the copy */
+	verify_attribs[0].ulValueLen = sizeof(buf1);
+	rc = funcs->C_GetAttributeValue(h_session, h_copy, verify_attribs, 1);
+	if (rc != CKR_OK) {
+		testcase_fail("C_GetAttributeValue() rc=%s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	if (memcmp(&data_application, verify_attribs[0].pValue, sizeof(data_application)) != 0) {
+		testcase_fail("extracted attribute doesn't match");
+		return -1;
+	}
+
+	/* now, try to extract CKA_PRIME from the original.
+	 * this should not exist
+	 */
+	prime_attribs[0].ulValueLen = sizeof(buf2);
+	rc = funcs->C_GetAttributeValue(h_session, h_data, prime_attribs, 1);
+	if (rc != CKR_ATTRIBUTE_TYPE_INVALID) {
+                testcase_fail("C_GetAttributeValue() rc = %s (expected CKR_ATTRIBUTE_TYPE_INVALID)", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, try to extract CKA_PRIME from a bogus object handle.
+	 * this should not exist
+	 */
+	rc = funcs->C_GetAttributeValue(h_session, 98765, prime_attribs, 1);
+	if (rc != CKR_OBJECT_HANDLE_INVALID) {
+                testcase_fail("C_GetAttributeValue() rc = %s (expected CKR_OBJECT_HANDLE_INVALID)", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, get the size of the original object */
+	rc = funcs->C_GetObjectSize(h_session, h_data, &obj_size);
+	if (rc != CKR_OK) {
+                testcase_fail("C_GetObjectSize() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, destroy the original object */
+	rc = funcs->C_DestroyObject(h_session, h_data);
+	if (rc != CKR_OK) {
+                testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, destroy a non-existant object */
+	rc = funcs->C_DestroyObject(h_session, h_data);
+	if (rc != CKR_OBJECT_HANDLE_INVALID) {
+                testcase_fail("C_GetAttributeValue() rc = %s (expected CKR_OBJECT_HANDLE_INVALID)", p11_get_ckr(rc));
+		return rc;
+	}
+
+
+	/* now, get the size of a non-existent object */
+	rc = funcs->C_GetObjectSize(h_session, h_data, &obj_size);
+	if (rc != CKR_OBJECT_HANDLE_INVALID) {
+                testcase_fail("C_GetAttributeValue() rc = %s (expected CKR_OBJECT_HANDLE_INVALID)", p11_get_ckr(rc));
+		return rc;
+	}
+
+
+	/* done...close the session and verify the object is deleted */
+	rc = funcs->C_CloseAllSessions(slot_id);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CloseAllSessions() rc=%s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	testcase_pass("Looks okay...");
+	return CKR_OK;
+}
+
+
+/* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock.
+ * C_OpenSession
+ * C_CloseSession
+ *
+ * API routines exercised that result in stdll taking
+ * /var/lock/opencryptoki_stdll spinlock.
+ *    C_CreateObject
+ *    C_GetAttributeValue
+ *    C_SetAttributeValue
+ *
+ * 1) create a certificate object with no CKA_SERIAL_NUMBER or CKA_ISSUER
+ * 2) add CKA_SERIAL_NUMBER and CKA_ISSUER and modify CKA_ID.
+ *    verify this works.
+ * 3) try to modify CKA_VALUE and CKA_ID in a single call to
+ *    C_SetAttributeValue.  verify that this fails correctly and that
+ *    the object is not modified.
+ */
+CK_RV do_SetAttributeValues(void)
+{
+	CK_SLOT_ID        slot_id;
+	CK_FLAGS          flags;
+	CK_SESSION_HANDLE h_session;
+	CK_RV             rc = 0;
+	CK_BYTE           user_pin[PKCS11_MAX_PIN_LEN];
+	CK_ULONG          user_pin_len;
+
+	CK_BYTE           false = FALSE;
+
+	CK_OBJECT_HANDLE    h_cert;
+	CK_OBJECT_CLASS     cert_class         = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert_type          = CKC_X_509;
+	CK_BYTE             cert_subject[]     = "Certificate subject";
+	CK_BYTE             cert_id[]          = "Certificate ID";
+	CK_BYTE             cert_value[]       = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert_attribs[] =
+	{
+		{CKA_CLASS,            &cert_class,       sizeof(cert_class)   },
+		{CKA_TOKEN,            &false,            sizeof(false)        },
+		{CKA_CERTIFICATE_TYPE, &cert_type,        sizeof(cert_type)    },
+		{CKA_SUBJECT,          &cert_subject,     sizeof(cert_subject) },
+		{CKA_ID,               &cert_id,          sizeof(cert_id)      },
+		{CKA_VALUE,            &cert_value,       sizeof(cert_value)   }
+	};
+
+	CK_BYTE       cert_id2[]    = "New ID";
+	CK_BYTE       cert_issuer[] = "Certificate Issuer";
+	CK_BYTE       cert_ser_no[] = "Serial Number: 12345";
+	CK_ATTRIBUTE  update_attr[] =
+	{
+		{CKA_SERIAL_NUMBER, &cert_ser_no,  sizeof(cert_ser_no) },
+		{CKA_ISSUER,        &cert_issuer,  sizeof(cert_issuer) },
+		{CKA_ID,            &cert_id2,     sizeof(cert_id2)    }
+	};
+
+	CK_BYTE       cert_value2[] = "Invalid Value";
+	CK_BYTE       cert_id3[]    = "ID #3";
+	CK_ATTRIBUTE  invalid_attr[] =
+	{
+		{CKA_VALUE, &cert_value2,  sizeof(cert_value2) },
+		{CKA_ID,    &cert_id3,     sizeof(cert_id3)    }
+	};
+
+	testcase_begin("starting...");
+
+	if (get_user_pin(user_pin))
+		return CKR_FUNCTION_FAILED;
+	user_pin_len = (CK_ULONG)strlen((char *)user_pin);
+
+	slot_id = SLOT_ID;
+
+
+	/*  create a USER R/W session */
+	flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
+	rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if (rc != CKR_OK) {
+                testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+
+	/* create the object */
+	rc = funcs->C_CreateObject(h_session, cert_attribs, 6, &h_cert);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* Add CKA_SERIAL_NUMBER and CKA_ISSUER and change the
+	 *  existing CKA_ID
+	 */
+	rc = funcs->C_SetAttributeValue(h_session, h_cert, update_attr, 3);
+	if (rc != CKR_OK) {
+                testcase_fail("C_SetAttributeValue() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+	else {
+		CK_BYTE       buf1[100];
+		CK_BYTE       buf2[100];
+		CK_BYTE       buf3[100];
+		CK_ATTRIBUTE  check1[] =
+		{
+			{CKA_ISSUER,        &buf1, sizeof(buf1)},
+			{CKA_SERIAL_NUMBER, &buf2, sizeof(buf2)},
+			{CKA_ID,            &buf3, sizeof(buf3)}
+		};
+
+		rc = funcs->C_GetAttributeValue(h_session, h_cert, (CK_ATTRIBUTE *)&check1, 3);
+		if (rc != CKR_OK) {
+                        testcase_fail("C_GetAttributeValue() rc = %s", p11_get_ckr(rc));
+			return rc;
+		}
+
+		if (memcmp(check1[0].pValue, cert_issuer, check1[0].ulValueLen) != 0) {
+                        testcase_fail("CKA_ISSUER mismatch");
+			return -1;
+		}
+
+		if (memcmp(check1[1].pValue, cert_ser_no, check1[1].ulValueLen) != 0) {
+                        testcase_fail("CKA_SERIAL_NUMBER mismatch");
+			return -1;
+		}
+
+		if (memcmp(check1[2].pValue, cert_id2, check1[2].ulValueLen) != 0) {
+                        testcase_fail("CKA_ID mismatch");
+			return -1;
+		}
+	}
+
+	/* the next template tries to update a CK_ID (valid) and
+	 * CKA_VALUE (read-only). the entire operation should fail -- no
+	 * attributes should get modified
+	 */
+	rc = funcs->C_SetAttributeValue(h_session, h_cert, invalid_attr, 2);
+	if (rc != CKR_ATTRIBUTE_READ_ONLY) {
+                testcase_fail("C_SetAttributeValue() rc = %s (expected CKR_ATTRIBUTE_READ_ONLY)", p11_get_ckr(rc));
+		return rc;
+	}
+	else {
+		CK_BYTE       buf1[100];
+		CK_ATTRIBUTE  check1[] =
+		{
+			{CKA_ID, &buf1, sizeof(buf1)}
+		};
+
+		rc = funcs->C_GetAttributeValue(h_session, h_cert, check1, 1);
+		if (rc != CKR_OK) {
+                        testcase_fail("C_GetAttributeValue() rc = %s", p11_get_ckr(rc));
+			return rc;
+		}
+
+		if (memcmp(check1[0].pValue, cert_id2, check1[0].ulValueLen) != 0) {
+                        testcase_fail("CKA_ID mismatch");
+			return -1;
+		}
+	}
+
+	/* done...close the session and verify the object is deleted */
+	rc = funcs->C_CloseAllSessions(slot_id);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CloseAllSessions() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	testcase_pass("Looks okay...");
+	return rc;
+}
+
+
+
+
+/* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock.
+ * C_OpenSession
+ * C_CloseSession
+ *
+ * API routines exercised that result in stdll taking
+ * /var/lock/opencryptoki_stdll spinlock.
+ * C_FindObjectsInit
+ * C_FindObjects
+ * C_CreateObject
+ *
+ * 1) Create 3 certificates with different CKA_ID attributes
+ * 2) Search for a particular CKA_ID.  Verify this works.
+ * 3) Search for a non-existant CKA_ID.  Verify this returns nothing.
+ * 4) Specify an empty template.  Verify that all 3 objects are returned.
+ */
+CK_RV do_FindObjects(void)
+{
+	CK_SLOT_ID        slot_id;
+	CK_FLAGS          flags;
+	CK_SESSION_HANDLE h_session;
+	CK_RV             rc = 0;
+	CK_BYTE           user_pin[PKCS11_MAX_PIN_LEN];
+	CK_ULONG          user_pin_len;
+
+	CK_BYTE           false = FALSE;
+
+	CK_OBJECT_HANDLE    h_cert1;
+	CK_OBJECT_CLASS     cert1_class         = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert1_type          = CKC_X_509;
+	CK_BYTE             cert1_subject[]     = "Certificate subject #1";
+	CK_BYTE             cert1_id[]          = "Certificate ID #1";
+	CK_BYTE             cert1_value[]       = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert1_attribs[] =
+	{
+		{CKA_CLASS,            &cert1_class,       sizeof(cert1_class)   },
+		{CKA_TOKEN,            &false,             sizeof(false)         },
+		{CKA_CERTIFICATE_TYPE, &cert1_type,        sizeof(cert1_type)    },
+		{CKA_SUBJECT,          &cert1_subject,     sizeof(cert1_subject) },
+		{CKA_ID,               &cert1_id,          sizeof(cert1_id)      },
+		{CKA_VALUE,            &cert1_value,       sizeof(cert1_value)   }
+	};
+
+	CK_OBJECT_HANDLE    h_cert2;
+	CK_OBJECT_CLASS     cert2_class        = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert2_type         = CKC_X_509;
+	CK_BYTE             cert2_subject[]    = "Certificate subject #2";
+	CK_BYTE             cert2_id[]         = "Certificate ID #2";
+	CK_BYTE             cert2_value[]      = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert2_attribs[] =
+	{
+		{CKA_CLASS,            &cert2_class,       sizeof(cert2_class)   },
+		{CKA_TOKEN,            &false,             sizeof(false)         },
+		{CKA_CERTIFICATE_TYPE, &cert2_type,        sizeof(cert2_type)    },
+		{CKA_SUBJECT,          &cert2_subject,     sizeof(cert2_subject) },
+		{CKA_ID,               &cert2_id,          sizeof(cert2_id)      },
+		{CKA_VALUE,            &cert2_value,       sizeof(cert2_value)   }
+	};
+
+	CK_OBJECT_HANDLE    h_cert3;
+	CK_OBJECT_CLASS     cert3_class        = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert3_type         = CKC_X_509;
+	CK_BYTE             cert3_subject[]    = "Certificate subject #3";
+	CK_BYTE             cert3_id[]         = "Certificate ID #3";
+	CK_BYTE             cert3_value[]      = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert3_attribs[] =
+	{
+		{CKA_CLASS,            &cert3_class,       sizeof(cert3_class)   },
+		{CKA_TOKEN,            &false,             sizeof(false)         },
+		{CKA_CERTIFICATE_TYPE, &cert3_type,        sizeof(cert3_type)    },
+		{CKA_SUBJECT,          &cert3_subject,     sizeof(cert3_subject) },
+		{CKA_ID,               &cert3_id,          sizeof(cert3_id)      },
+		{CKA_VALUE,            &cert3_value,       sizeof(cert3_value)   }
+	};
+
+	CK_BYTE  find1_id[] = "Certificate ID #2";
+	CK_ATTRIBUTE   find1_attribs[] =
+	{
+		{CKA_ID, &find1_id,  sizeof(find1_id)}
+	};
+
+	CK_BYTE  find2_id[] = "Certificate ID #12345";
+	CK_ATTRIBUTE   find2_attribs[] =
+	{
+		{CKA_ID, &find2_id,  sizeof(find2_id)}
+	};
+
+	CK_OBJECT_HANDLE  obj_list[10];
+	CK_ULONG          find_count;
+	CK_ULONG          num_existing_objects;
+
+
+	testcase_begin("starting...");
+
+	if (get_user_pin(user_pin))
+		return CKR_FUNCTION_FAILED;
+	user_pin_len = (CK_ULONG)strlen((char *)user_pin);
+
+	slot_id = SLOT_ID;
+
+
+	/* create a USER R/W session */
+	flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
+	rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if (rc != CKR_OK) {
+                testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* Get a count on all currently existing session objects
+	 * If any objects existed before, then after we create three
+	 * new objects. we expect there to be a total of
+	 * current_num_objects+3 tokens.
+	 */
+	rc = funcs->C_FindObjectsInit(h_session, NULL, 0);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &num_existing_objects);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* Since we'll only be checking for max 10 objects...  */
+	if (num_existing_objects > 7)
+		num_existing_objects = 7;
+
+	/* create the objects */
+	rc = funcs->C_CreateObject(h_session, cert1_attribs, 6, &h_cert1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_CreateObject(h_session, cert2_attribs, 6, &h_cert2);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_CreateObject(h_session, cert3_attribs, 6, &h_cert3);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, search for the 2nd objects */
+	rc = funcs->C_FindObjectsInit(h_session, find1_attribs, 1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	if (find_count != 1) {
+                testcase_fail("found %ld instead of just 1 object", find_count);
+		return -1;
+	}
+
+	if (obj_list[0] != h_cert2) {
+                testcase_fail("got the wrong object handle");
+		return -1;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, search for a non-existant object */
+	rc = funcs->C_FindObjectsInit(h_session, find2_attribs, 1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	if (find_count != 0) {
+                testcase_fail("found %ld objects when none where expected", find_count);
+		return -1;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, try to retrieve a list of all the objects */
+	rc = funcs->C_FindObjectsInit(h_session, NULL, 0);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	if (find_count != num_existing_objects + 3) {
+		testcase_fail("found %ld instead of %ld objects", find_count,
+                                num_existing_objects + 3);
+		return -1;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* done...close the session and verify the object is deleted */
+	rc = funcs->C_CloseAllSessions(slot_id);
+	if (rc != CKR_OK) {
+		testcase_fail("C_CloseAllSessions() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	testcase_pass("Looks okay...");
+	return rc;
+}
+
+
+/* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock.
+ * C_OpenSession
+ * C_CloseSession
+ *
+ * API routines exercised that result in stdll taking
+ * /var/lock/opencryptoki_stdll spinlock.
+ * C_FindObjectsInit
+ * C_FindObjects
+ * C_CreateObject
+ *
+ *  1) Create 3 certificates as PUBLIC token objects
+ *  2) Search for a particular CKA_ID.  Verify that this works.
+ *  3) Do FindObjects with a NULL template.  Verify that all 3 token objects
+ *     are found.
+ *  4) Search for a particular CKA_ID.  Verify it works.
+ *  5) Search for a non-existant CKA_ID.  Verify it returns nothing.
+ *  6) Close all sessions.  Then create a new session.
+ *  7) Do FindObjects with a NULL template.  Verify that all 3 token objects
+ *     are found.
+ *  8) Search for a particular CKA_ID.  Verify it works.
+ *  9) Search for a non-existant CKA_ID.  Verify it returns nothing.
+ * 10) Destroy all 3 token objects
+ * 11) Do FindObjects with a NULL template.  Verify that nothing is returned.
+ */
+CK_RV do_CreateTokenObjects(void)
+{
+	CK_SLOT_ID        slot_id;
+	CK_FLAGS          flags;
+	CK_SESSION_HANDLE h_session;
+	CK_RV             rc = 0;
+	CK_BYTE           user_pin[PKCS11_MAX_PIN_LEN];
+	CK_ULONG          user_pin_len;
+
+	CK_BYTE           true = TRUE;
+	CK_BYTE           false = FALSE;
+
+	CK_OBJECT_HANDLE    h_cert1;
+	CK_OBJECT_CLASS     cert1_class         = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert1_type          = CKC_X_509;
+	CK_BYTE             cert1_subject[]     = "Certificate subject #1";
+	CK_BYTE             cert1_id[]          = "Certificate ID #1";
+	CK_BYTE             cert1_value[]       = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert1_attribs[] =
+	{
+		{CKA_CLASS,            &cert1_class,       sizeof(cert1_class)   },
+		{CKA_TOKEN,            &true,              sizeof(true)          },
+		{CKA_CERTIFICATE_TYPE, &cert1_type,        sizeof(cert1_type)    },
+		{CKA_SUBJECT,          &cert1_subject,     sizeof(cert1_subject) },
+		{CKA_ID,               &cert1_id,          sizeof(cert1_id)      },
+		{CKA_VALUE,            &cert1_value,       sizeof(cert1_value)   },
+		{CKA_PRIVATE,          &false,             sizeof(false)         }
+	};
+
+	CK_OBJECT_HANDLE    h_cert2;
+	CK_OBJECT_CLASS     cert2_class        = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert2_type         = CKC_X_509;
+	CK_BYTE             cert2_subject[]    = "Certificate subject #2";
+	CK_BYTE             cert2_id[]         = "Certificate ID #2";
+	CK_BYTE             cert2_value[]      = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert2_attribs[] =
+	{
+		{CKA_CLASS,            &cert2_class,       sizeof(cert2_class)   },
+		{CKA_TOKEN,            &true,              sizeof(true)          },
+		{CKA_CERTIFICATE_TYPE, &cert2_type,        sizeof(cert2_type)    },
+		{CKA_SUBJECT,          &cert2_subject,     sizeof(cert2_subject) },
+		{CKA_ID,               &cert2_id,          sizeof(cert2_id)      },
+		{CKA_VALUE,            &cert2_value,       sizeof(cert2_value)   },
+		{CKA_PRIVATE,          &false,             sizeof(false)         }
+	};
+
+	CK_OBJECT_HANDLE    h_cert3;
+	CK_OBJECT_CLASS     cert3_class        = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert3_type         = CKC_X_509;
+	CK_BYTE             cert3_subject[]    = "Certificate subject #3";
+	CK_BYTE             cert3_id[]         = "Certificate ID #3";
+	CK_BYTE             cert3_value[]      = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert3_attribs[] =
+	{
+		{CKA_CLASS,            &cert3_class,       sizeof(cert3_class)   },
+		{CKA_TOKEN,            &true,              sizeof(true)          },
+		{CKA_CERTIFICATE_TYPE, &cert3_type,        sizeof(cert3_type)    },
+		{CKA_SUBJECT,          &cert3_subject,     sizeof(cert3_subject) },
+		{CKA_ID,               &cert3_id,          sizeof(cert3_id)      },
+		{CKA_VALUE,            &cert3_value,       sizeof(cert3_value)   },
+		{CKA_PRIVATE,          &false,             sizeof(false)         }
+	};
+
+	CK_BYTE  find1_id[] = "Certificate ID #2";
+	CK_ATTRIBUTE   find1_attribs[] =
+	{
+		{CKA_ID, &find1_id,  sizeof(find1_id)}
+	};
+
+	CK_BYTE  find2_id[] = "Certificate ID #123456";
+	CK_ATTRIBUTE   find2_attribs[] =
+	{
+		{CKA_ID, &find2_id,  sizeof(find2_id)}
+	};
+
+	CK_OBJECT_HANDLE  obj_list[10];
+	CK_ULONG          find_count;
+
+
+
+        testcase_begin("starting...");
+
+        if (skip_token_obj == TRUE) {
+                testcase_notice("Skipping tests that creates token objects");
+                return CKR_OK;
+        }
+
+	if (get_user_pin(user_pin))
+		return CKR_FUNCTION_FAILED;
+	user_pin_len = (CK_ULONG)strlen((char *)user_pin);
+
+	slot_id = SLOT_ID;
+
+	/* create a USER R/W session */
+	flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
+	rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if (rc != CKR_OK) {
+                testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* create the token objects */
+	rc = funcs->C_CreateObject(h_session, cert1_attribs, 7, &h_cert1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_CreateObject(h_session, cert2_attribs, 7, &h_cert2);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_CreateObject(h_session, cert3_attribs, 7, &h_cert3);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, retrieve a list of all object handles */
+	rc = funcs->C_FindObjectsInit(h_session, NULL, 0);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	if (find_count != 3) {
+                testcase_fail("found %ld objects instead of expected 3", find_count);
+		return -1;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, search for the 2nd object */
+	rc = funcs->C_FindObjectsInit(h_session, find1_attribs, 1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	if (find_count != 1) {
+                testcase_fail("found %ld objects instead of expected 1", find_count);
+		return -1;
+	}
+
+	if (obj_list[0] != h_cert2) {
+                testcase_fail("found the wrong object handle");
+		return -1;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, search for a non-existant attribute */
+	rc = funcs->C_FindObjectsInit(h_session, find2_attribs, 1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	if (find_count != 0) {
+                testcase_fail("found %ld objects when none where expected", find_count);
+		return -1;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* done...close all sessions and open a new one */
+	rc = funcs->C_CloseAllSessions( slot_id );
+	if (rc != CKR_OK) {
+                testcase_fail("C_CloseAllSessions() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* create a USER R/W session */
+	flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
+	rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if (rc != CKR_OK) {
+                testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, retrieve a list of all object handles */
+	rc = funcs->C_FindObjectsInit(h_session, NULL, 0);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	if (find_count != 3) {
+                testcase_fail("found %ld objects instead of expected 3", find_count);
+		return -1;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, search for the 2nd object */
+	rc = funcs->C_FindObjectsInit(h_session, find1_attribs, 1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	if (find_count != 1) {
+                testcase_fail("found %ld objects instead of expected 1", find_count);
+		return -1;
+	}
+
+	if (obj_list[0] != h_cert2) {
+                testcase_fail("found the wrong object handle");
+		return -1;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, search for a non-existant attribute */
+	rc = funcs->C_FindObjectsInit(h_session, find2_attribs, 1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	if (find_count != 0) {
+                testcase_fail("found %ld objects when none where expected", find_count);
+		return -1;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, destroy the objects */
+	rc = funcs->C_DestroyObject(h_session, h_cert1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_DestroyObject(h_session, h_cert2);
+	if (rc != CKR_OK) {
+                testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_DestroyObject(h_session, h_cert3);
+	if (rc != CKR_OK) {
+                testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* now, retrieve a list of all object handles */
+	rc = funcs->C_FindObjectsInit(h_session, NULL, 0);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	if (find_count != 0) {
+                testcase_fail("found %ld objects when none where expected", find_count);
+		return -1;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* done...close the session */
+	rc = funcs->C_CloseAllSessions(slot_id);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CloseAllSessions() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	testcase_pass("Looks okay...");
+	return rc;
+}
+
+/*
+ * do_HW_Feature_Search Test:
+ *
+ * 1. Create 5 objects, 3 of which are HW_FEATURE objects.
+ * 2. Search for objects using a template that does not have its
+ *    HW_FEATURE attribute set.
+ * 3. Result should be that the other 2 objects are returned, and
+ *    not the HW_FEATURE objects.
+ * 4. Search for objects using a template that does have its
+ *    HW_FEATURE attribute set.
+ * 5. Result should be that the 3 hardware feature objects are returned.
+ *
+ */
+
+CK_RV do_HWFeatureSearch(void)
+{
+	unsigned int            i;
+	CK_RV 			rc, loc_rc;
+	CK_ULONG		find_count;
+	CK_SLOT_ID		slot_id;
+	CK_BBOOL		false = FALSE;
+	CK_BBOOL                true = TRUE;
+
+	CK_SESSION_HANDLE 	h_session;
+	CK_BYTE           	user_pin[PKCS11_MAX_PIN_LEN];
+	CK_ULONG          	user_pin_len;
+
+	/* A counter object */
+	CK_OBJECT_CLASS         counter1_class = CKO_HW_FEATURE;
+	CK_HW_FEATURE_TYPE      feature1_type = CKH_MONOTONIC_COUNTER;
+	CK_UTF8CHAR             counter1_label[] = "Monotonic counter";
+	CK_CHAR			counter1_value[16];
+	CK_ATTRIBUTE            counter1_template[] = {
+		{CKA_CLASS,		&counter1_class, sizeof(counter1_class)},
+		{CKA_HW_FEATURE_TYPE,	&feature1_type,  sizeof(feature1_type)},
+		{CKA_LABEL,		counter1_label,  sizeof(counter1_label)-1},
+		{CKA_VALUE,		counter1_value,	sizeof(counter1_value)},
+		{CKA_RESET_ON_INIT,	&true,		sizeof(true)},
+		{CKA_HAS_RESET,		&false,		sizeof(false)}
+	};
+	/* A clock object */
+	CK_OBJECT_CLASS         clock_class = CKO_HW_FEATURE;
+	CK_HW_FEATURE_TYPE      clock_type = CKH_CLOCK;
+	CK_UTF8CHAR             clock_label[] = "Clock";
+	CK_CHAR			clock_value[16];
+	CK_ATTRIBUTE            clock_template[] = {
+		{CKA_CLASS,		&clock_class, sizeof(clock_class)},
+		{CKA_HW_FEATURE_TYPE,	&clock_type,  sizeof(clock_type)},
+		{CKA_LABEL,		clock_label,  sizeof(clock_label)-1},
+		{CKA_VALUE,		clock_value,	sizeof(clock_value)}
+	};
+	/* A data object */
+	CK_OBJECT_CLASS		obj1_class = CKO_DATA;
+	CK_UTF8CHAR             obj1_label[] = "Object 1";
+	CK_BYTE			obj1_data[] = "Object 1's data";
+	CK_ATTRIBUTE            obj1_template[] = {
+		{CKA_CLASS,		&obj1_class,    sizeof(obj1_class)},
+		{CKA_TOKEN,		&true,          sizeof(true)},
+		{CKA_LABEL,		obj1_label,     sizeof(obj1_label)-1},
+		{CKA_VALUE,		obj1_data,	sizeof(obj1_data)}
+	};
+	/* A secret key object */
+	CK_OBJECT_CLASS		obj2_class = CKO_SECRET_KEY;
+	CK_KEY_TYPE		obj2_type = CKK_AES;
+	CK_UTF8CHAR             obj2_label[] = "Object 2";
+	CK_BYTE			obj2_data[AES_KEY_SIZE_128];
+	CK_ATTRIBUTE            obj2_template[] = {
+		{CKA_CLASS,		&obj2_class,    sizeof(obj2_class)},
+		{CKA_TOKEN,		&true,          sizeof(true)},
+		{CKA_KEY_TYPE,		&obj2_type,	sizeof(obj2_type)},
+		{CKA_LABEL,		obj2_label,     sizeof(obj2_label)-1},
+		{CKA_VALUE,		obj2_data,	sizeof(obj2_data)}
+	};
+
+	CK_OBJECT_HANDLE        h_counter1,
+				h_clock,
+				h_obj1,
+				h_obj2,
+				obj_list[10];
+	CK_ATTRIBUTE		find_tmpl[] = {
+		{CKA_CLASS,	&counter1_class, sizeof(counter1_class)}
+	};
+
+        if (skip_token_obj == TRUE) {
+                testcase_notice("Skipping tests that creates token objects");
+                return CKR_OK;
+        }
+
+	slot_id = SLOT_ID;
+
+        testcase_begin("starting...");
+
+	if (get_user_pin(user_pin))
+		return CKR_FUNCTION_FAILED;
+	user_pin_len = (CK_ULONG)strlen((char *)user_pin);
+
+	/* Open a session with the token */
+	if( (rc = funcs->C_OpenSession(slot_id,
+					(CKF_SERIAL_SESSION|CKF_RW_SESSION),
+					NULL_PTR,
+					NULL_PTR,
+					&h_session)) != CKR_OK ) {
+                testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		goto done;
+	}
+
+	// Login correctly
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if( rc != CKR_OK ) {
+                testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		goto session_close;
+	}
+
+	/* Create the 3 test objects */
+	if( (rc = funcs->C_CreateObject(h_session, obj1_template, 4, &h_obj1)) != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	if( (rc = funcs->C_CreateObject(h_session, obj2_template, 5, &h_obj2)) != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		goto destroy_1;
+	}
+
+	/* try and create a monotonic object. This should fail
+	 * since it is a read only feature.
+	 */
+	if( (rc = funcs->C_CreateObject(h_session, counter1_template, 6, &h_counter1)) != CKR_ATTRIBUTE_READ_ONLY) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		goto destroy_2;
+	}
+
+	if( (rc = funcs->C_CreateObject(h_session, clock_template, 4, &h_clock)) != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		goto destroy_2;
+	}
+
+
+	/* Search for the 2 objects w/o HW_FEATURE set */
+
+	/* A NULL template here should return all objects in v2.01, but
+	 * in v2.11, it should return all objects *except* HW_FEATURE
+	 * objects. - KEY
+	 */
+	rc = funcs->C_FindObjectsInit(h_session, NULL, 0 );
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count );
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	/* So, we created 3 objects before here, and then searched with a NULL
+	 * template, so that should return all objects except our hardware
+	 * feature object. -KEY */
+	if (find_count != 2) {
+                testcase_fail("found %ld objects when expected 2", find_count);
+		rc = -1;
+		goto destroy;
+	}
+
+	if (obj_list[0] != h_obj1 && obj_list[0] != h_obj2) {
+                testcase_fail("found the wrong object handle");
+		rc = -1;
+		goto destroy;
+	}
+
+	if (obj_list[1] != h_obj1 && obj_list[1] != h_obj2) {
+                testcase_fail("found the wrong object handle");
+		rc = -1;
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+
+	// Now find the hardware feature objects
+	rc = funcs->C_FindObjectsInit(h_session, find_tmpl, 1 );
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count );
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	if (find_count != 1) {
+                testcase_fail("found %ld objects when expected 1", find_count);
+		funcs->C_FindObjectsFinal(h_session);   // TODO: check if we really need this here
+		rc = -1;
+		goto destroy;
+	}
+
+	/* Make sure we got the right ones */
+	for( i=0; i < find_count; i++) {
+		if(obj_list[i] != h_counter1 &&
+		   obj_list[i] != h_clock)
+		{
+
+                        testcase_fail("found the wrong object handles");
+			rc = -1;
+		}
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session );
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+	}
+
+        testcase_pass("Looks okay...");
+
+destroy:
+	/* Destroy the created objects, don't clobber the rc */
+	loc_rc = funcs->C_DestroyObject(h_session, h_clock);
+	if( loc_rc != CKR_OK )
+                testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc));
+destroy_2:
+	loc_rc = funcs->C_DestroyObject(h_session, h_obj2);
+	if( loc_rc != CKR_OK )
+                testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc));
+destroy_1:
+	loc_rc = funcs->C_DestroyObject(h_session, h_obj1);
+	if( loc_rc != CKR_OK )
+                testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc));
+
+	loc_rc = funcs->C_Logout(h_session);
+	if( loc_rc != CKR_OK )
+                testcase_fail("C_Logout() rc = %s", p11_get_ckr(loc_rc));
+
+session_close:
+	/* Close the session */
+	if( (loc_rc = funcs->C_CloseSession(h_session)) != CKR_OK )
+                testcase_fail("C_CloseSession() rc = %s", p11_get_ckr(loc_rc));
+done:
+	return rc;
+}
+
+CK_RV obj_mgmt_functions()
+{
+	int         rc;
+
+	rc = do_CreateSessionObject();
+	if (rc && !no_stop)
+		return rc;
+
+
+	rc = do_CopyObject();
+	if (rc && !no_stop)
+		return rc;
+
+
+	rc = do_SetAttributeValues();
+	if (rc && !no_stop)
+		return rc;
+
+	rc = do_FindObjects();
+	if (rc && !no_stop)
+		return rc;
+
+	rc = do_HWFeatureSearch();
+	if (rc && !no_stop)
+		return rc;
+
+	rc = do_CreateTokenObjects();
+	if (rc && !no_stop)
+		return rc;
+
+	return rc;
+}
+
+int main(int argc, char **argv)
+{
+	CK_C_INITIALIZE_ARGS cinit_args;
+	int rc;
+	CK_RV rv;
+
+
+	rc = do_ParseArgs(argc, argv);
+	if ( rc != 1)
+		return rc;
+
+	printf("Using slot #%lu...\n\n", SLOT_ID );
+	printf("With option: no_init: %d, no_stop: %d, skip_token_obj: %d\n", no_init, no_stop, skip_token_obj);
+
+	rc = do_GetFunctionList();
+	if (!rc) {
+                testcase_error_f("(setup)", "do_GetFunctionList() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	memset( &cinit_args, 0x0, sizeof(cinit_args) );
+	cinit_args.flags = CKF_OS_LOCKING_OK;
+
+	// SAB Add calls to ALL functions before the C_Initialize gets hit
+
+	funcs->C_Initialize( &cinit_args );
+
+	{
+		CK_SESSION_HANDLE  hsess = 0;
+
+		rc = funcs->C_GetFunctionStatus(hsess);
+		if (rc  != CKR_FUNCTION_NOT_PARALLEL)
+			return rc;
+
+		rc = funcs->C_CancelFunction(hsess);
+		if (rc  != CKR_FUNCTION_NOT_PARALLEL)
+			return rc;
+
+	}
+
+	rv = obj_mgmt_functions();
+
+	/* make sure we return non-zero if rv is non-zero */
+	return ((rv==0) || (rv % 256) ? rv : -1);
+}
--- /dev/null
+++ b/testcases/misc_tests/obj_mgmt_lock.c
@@ -0,0 +1,1282 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+
+#include "pkcs11types.h"
+#include "regress.h"
+#include "common.c"
+
+
+#define AES_KEY_SIZE_128	16
+
+/* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock.
+ * C_OpenSession
+ * C_CloseSession
+ *
+ * API Routines exercised that cause stdll to take /var/lock/opencryptoki_stdll
+ * spinlock.
+ * C_CreateObject
+ * C_Login
+ *
+ * 1) create a data object
+ * 2) create a certificate
+ * 3) create a key object
+ */
+CK_RV do_CreateSessionObject(void)
+{
+	CK_SLOT_ID        slot_id;
+	CK_FLAGS          flags;
+	CK_SESSION_HANDLE h_session;
+	CK_RV             rc = 0;
+	CK_BYTE           user_pin[PKCS11_MAX_PIN_LEN];
+	CK_ULONG          user_pin_len;
+
+	CK_BYTE           true  = TRUE;
+	CK_BYTE           false = FALSE;
+
+	CK_OBJECT_HANDLE  h_data;
+	CK_OBJECT_CLASS   data_class         = CKO_DATA;
+	CK_BYTE           data_application[] = "Test Application";
+	CK_BYTE           data_value[]       = "1234567890abcedfghijklmnopqrstuvwxyz";
+	CK_ATTRIBUTE      data_attribs[] =
+	{
+		{CKA_CLASS,       &data_class,       sizeof(data_class)       },
+		{CKA_TOKEN,       &false,            sizeof(false)            },
+		{CKA_APPLICATION, &data_application, sizeof(data_application) },
+		{CKA_VALUE,       &data_value,       sizeof(data_value)       }
+	};
+
+	CK_OBJECT_HANDLE    h_cert;
+	CK_OBJECT_CLASS     cert_class         = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert_type          = CKC_X_509;
+	CK_BYTE             cert_subject[]     = "Certificate subject";
+	CK_BYTE             cert_id[]          = "Certificate ID";
+	CK_BYTE             cert_value[]       = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+	CK_ATTRIBUTE        cert_attribs[] =
+	{
+		{CKA_CLASS,            &cert_class,       sizeof(cert_class)   },
+		{CKA_TOKEN,            &false,            sizeof(false)        },
+		{CKA_CERTIFICATE_TYPE, &cert_type,        sizeof(cert_type)    },
+		{CKA_SUBJECT,          &cert_subject,     sizeof(cert_subject) },
+		{CKA_ID,               &cert_id,          sizeof(cert_id)      },
+		{CKA_VALUE,            &cert_value,       sizeof(cert_value)   }
+	};
+
+	CK_OBJECT_HANDLE  h_key;
+	CK_OBJECT_CLASS   key_class          = CKO_PUBLIC_KEY;
+	CK_KEY_TYPE       key_type           = CKK_RSA;
+	CK_BYTE           key_modulus[]      = "1234567890987654321";
+	CK_BYTE           key_exponent[]     = "123";
+	CK_ATTRIBUTE      key_attribs[] =
+	{
+		{CKA_CLASS,           &key_class,    sizeof(key_class)    },
+		{CKA_KEY_TYPE,        &key_type,     sizeof(key_type)     },
+		{CKA_WRAP,            &true,         sizeof(true)         },
+		{CKA_MODULUS,         &key_modulus,  sizeof(key_modulus)  },
+		{CKA_PUBLIC_EXPONENT, &key_exponent, sizeof(key_exponent) }
+	};
+
+	testcase_begin("starting...");
+
+	if (get_user_pin(user_pin))
+		return CKR_FUNCTION_FAILED;
+	user_pin_len = (CK_ULONG)strlen((char *)user_pin);
+
+	slot_id = SLOT_ID;
+
+
+	// create a USER R/W session
+	//
+	flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
+	rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session);
+	if (rc != CKR_OK) {
+		testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if (rc != CKR_OK) {
+		testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	//
+	// now, create the objects
+	//
+
+	rc = funcs->C_CreateObject(h_session, data_attribs, 4, &h_data);
+	if (rc != CKR_OK) {
+		testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_CreateObject(h_session, cert_attribs, 6, &h_cert);
+	if (rc != CKR_OK) {
+		testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_CreateObject(h_session, key_attribs, 5, &h_key);
+	if (rc != CKR_OK) {
+		testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	// done...close the session and verify the object is deleted
+	//
+	rc = funcs->C_CloseAllSessions(slot_id);
+	if (rc != CKR_OK) {
+		testcase_fail("C_CloseAllSessions() rc=%s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	testcase_pass("looks okay...");
+	return rc;
+}
+
+/* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock.
+ * C_OpenSession
+ * C_CloseSession
+ *
+ * API routines exercised that result in stdll taking
+ * /var/lock/opencryptoki_stdll spinlock.
+ *    C_CreateObject
+ *    C_CopyObject
+ *    C_DestroyObject
+ *    C_GetAttributeValue
+ *    C_GetObjectSize
+ *
+ * 1) create a data object with no CKA_APPLICATION attribute
+ * 2) create a copy of the object specifying the CKA_APPLICATION attribute
+ * 3) extract the CK_VALUE attribute from the copy. Ensure matches the original
+ * 4) extract the CKA_APPLICATION attribute from the original. ensure empty.
+ * 5) extract the CKA_APPLICATION attribute from the copy. ensure is correct.
+ * 6) attempt to extract CK_PRIME from the original. ensure fails correctly.
+ * 7) attempt to extract CK_PRIME from a non-existant object. ensure fails
+ *    correctly.
+ * 8) get the size of the original object and copied objects
+ * 9) destroy the original object.  ensure this succeeds.
+ * A) destroy a non-existant object.  ensure this fails correctly.
+ * B) get the size of the original object.  ensure this fails correctly.
+ */
+CK_RV do_CopyObject(void)
+{
+	CK_SLOT_ID        slot_id;
+	CK_FLAGS          flags;
+	CK_SESSION_HANDLE h_session;
+	CK_RV             rc = 0, loc_rc = 0;
+	CK_BYTE           user_pin[PKCS11_MAX_PIN_LEN];
+	CK_ULONG          user_pin_len;
+	CK_ULONG          obj_size;
+
+	CK_BYTE           true = TRUE;
+
+	CK_OBJECT_HANDLE  h_data;
+	CK_OBJECT_CLASS   data_class         = CKO_DATA;
+	CK_BYTE           data_application[] = "Test Application";
+	CK_BYTE           data_value[]       = "1234567890abcedfghijklmnopqrstuvwxyz";
+	CK_ATTRIBUTE      data_attribs[] =
+	{
+		{CKA_CLASS,       &data_class,       sizeof(data_class)       },
+		{CKA_TOKEN,       &true,             sizeof(true)             },
+		{CKA_VALUE,       &data_value,       sizeof(data_value)       }
+	};
+
+	CK_OBJECT_HANDLE  h_copy;
+	CK_ATTRIBUTE      copy_attribs[] =
+	{
+		{CKA_APPLICATION, &data_application, sizeof(data_application) }
+	};
+
+	CK_BYTE           buf1[100];
+	CK_ATTRIBUTE      verify_attribs[] =
+	{
+		{CKA_APPLICATION, &buf1, sizeof(buf1) }
+	};
+
+	CK_BYTE           buf2[100];
+	CK_ATTRIBUTE      prime_attribs[] =
+	{
+		{CKA_PRIME, &buf2, sizeof(buf2) }
+	};
+
+	testcase_begin("starting...");
+
+	if (get_user_pin(user_pin))
+		return CKR_FUNCTION_FAILED;
+	user_pin_len = (CK_ULONG)strlen((char *)user_pin);
+
+	slot_id = SLOT_ID;
+
+
+	/* create a USER R/W session */
+	flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
+	rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session);
+	if (rc != CKR_OK) {
+		testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if (rc != CKR_OK) {
+		testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+
+	/* create the object */
+	rc = funcs->C_CreateObject(h_session, data_attribs, 3, &h_data);
+	if (rc != CKR_OK) {
+		testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* create the copy */
+	rc = funcs->C_CopyObject(h_session, h_data, copy_attribs, 1, &h_copy);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CopyObject() rc = %s", p11_get_ckr(rc));
+		goto destroy_1;
+	}
+
+	/* now, try to extract the CKA_APPLICATION attribute from the original
+	 * this will pull in the token's default value for CKA_APPLICATION which
+	 */
+	verify_attribs[0].ulValueLen = sizeof(buf1);
+	rc = funcs->C_GetAttributeValue(h_session, h_data, verify_attribs, 1);
+	if (rc != CKR_OK) {
+		testcase_fail("C_GetAttributeValue() rc=%s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	/* now, try to extract the CKA_APPLICATION attribute from the copy */
+	verify_attribs[0].ulValueLen = sizeof(buf1);
+	rc = funcs->C_GetAttributeValue(h_session, h_copy, verify_attribs, 1);
+	if (rc != CKR_OK) {
+		testcase_fail("C_GetAttributeValue() rc=%s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	if (memcmp(&data_application, verify_attribs[0].pValue, sizeof(data_application)) != 0) {
+		testcase_fail("extracted attribute doesn't match");
+		rc = -1;
+		goto destroy;
+	}
+
+	/* now, try to extract CKA_PRIME from the original.
+	 * this should not exist
+	 */
+	prime_attribs[0].ulValueLen = sizeof(buf2);
+	rc = funcs->C_GetAttributeValue(h_session, h_data, prime_attribs, 1);
+	if (rc != CKR_ATTRIBUTE_TYPE_INVALID) {
+                testcase_fail("C_GetAttributeValue() rc = %s (expected CKR_ATTRIBUTE_TYPE_INVALID)", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	/* now, try to extract CKA_PRIME from a bogus object handle.
+	 * this should not exist
+	 */
+	rc = funcs->C_GetAttributeValue(h_session, 98765, prime_attribs, 1);
+	if (rc != CKR_OBJECT_HANDLE_INVALID) {
+                testcase_fail("C_GetAttributeValue() rc = %s (expected CKR_OBJECT_HANDLE_INVALID)", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	/* now, get the size of the original object */
+	rc = funcs->C_GetObjectSize(h_session, h_data, &obj_size);
+	if (rc != CKR_OK) {
+                testcase_fail("C_GetObjectSize() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	testcase_pass("Looks okay...");
+
+destroy:
+	/* now, destroy the original object and the copy */
+	loc_rc = funcs->C_DestroyObject(h_session, h_copy);
+	if (loc_rc != CKR_OK)
+                testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc));
+
+destroy_1:
+	loc_rc = funcs->C_DestroyObject(h_session, h_data);
+	if (loc_rc != CKR_OK)
+                testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc));
+
+	loc_rc = funcs->C_CloseAllSessions(slot_id);
+	if (loc_rc != CKR_OK)
+                testcase_error("C_CloseAllSessions() loc_rc=%s", p11_get_ckr(loc_rc));
+
+	return rc;
+}
+
+
+/* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock.
+ * C_OpenSession
+ * C_CloseSession
+ *
+ * API routines exercised that result in stdll taking
+ * /var/lock/opencryptoki_stdll spinlock.
+ *    C_CreateObject
+ *    C_GetAttributeValue
+ *    C_SetAttributeValue
+ *
+ * 1) create a certificate object with no CKA_SERIAL_NUMBER or CKA_ISSUER
+ * 2) add CKA_SERIAL_NUMBER and CKA_ISSUER and modify CKA_ID.
+ *    verify this works.
+ * 3) try to modify CKA_VALUE and CKA_ID in a single call to
+ *    C_SetAttributeValue.  verify that this fails correctly and that
+ *    the object is not modified.
+ */
+CK_RV do_SetAttributeValues(void)
+{
+	CK_SLOT_ID        slot_id;
+	CK_FLAGS          flags;
+	CK_SESSION_HANDLE h_session;
+	CK_RV             rc = 0, loc_rc = 0;
+	CK_BYTE           user_pin[PKCS11_MAX_PIN_LEN];
+	CK_ULONG          user_pin_len;
+
+	CK_BYTE           true = TRUE;
+
+	CK_OBJECT_HANDLE    h_cert;
+	CK_OBJECT_CLASS     cert_class         = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert_type          = CKC_X_509;
+	CK_BYTE             cert_subject[]     = "Certificate subject";
+	CK_BYTE             cert_id[]          = "Certificate ID";
+	CK_BYTE             cert_value[]       = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert_attribs[] =
+	{
+		{CKA_CLASS,            &cert_class,       sizeof(cert_class)   },
+		{CKA_TOKEN,            &true,             sizeof(true)         },
+		{CKA_CERTIFICATE_TYPE, &cert_type,        sizeof(cert_type)    },
+		{CKA_SUBJECT,          &cert_subject,     sizeof(cert_subject) },
+		{CKA_ID,               &cert_id,          sizeof(cert_id)      },
+		{CKA_VALUE,            &cert_value,       sizeof(cert_value)   }
+	};
+
+	CK_BYTE       cert_id2[]    = "New ID";
+	CK_BYTE       cert_issuer[] = "Certificate Issuer";
+	CK_BYTE       cert_ser_no[] = "Serial Number: 12345";
+	CK_ATTRIBUTE  update_attr[] =
+	{
+		{CKA_SERIAL_NUMBER, &cert_ser_no,  sizeof(cert_ser_no) },
+		{CKA_ISSUER,        &cert_issuer,  sizeof(cert_issuer) },
+		{CKA_ID,            &cert_id2,     sizeof(cert_id2)    }
+	};
+
+	CK_BYTE       cert_value2[] = "Invalid Value";
+	CK_BYTE       cert_id3[]    = "ID #3";
+	CK_ATTRIBUTE  invalid_attr[] =
+	{
+		{CKA_VALUE, &cert_value2,  sizeof(cert_value2) },
+		{CKA_ID,    &cert_id3,     sizeof(cert_id3)    }
+	};
+
+	testcase_begin("starting...");
+
+	if (get_user_pin(user_pin))
+		return CKR_FUNCTION_FAILED;
+	user_pin_len = (CK_ULONG)strlen((char *)user_pin);
+
+	slot_id = SLOT_ID;
+
+
+	/*  create a USER R/W session */
+	flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
+	rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if (rc != CKR_OK) {
+                testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+
+	/* create the object */
+	rc = funcs->C_CreateObject(h_session, cert_attribs, 6, &h_cert);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* Add CKA_SERIAL_NUMBER and CKA_ISSUER and change the
+	 *  existing CKA_ID
+	 */
+	rc = funcs->C_SetAttributeValue(h_session, h_cert, update_attr, 3);
+	if (rc != CKR_OK) {
+                testcase_fail("C_SetAttributeValue() rc = %s", p11_get_ckr(rc));
+		goto done;
+	}
+	else {
+		CK_BYTE       buf1[100];
+		CK_BYTE       buf2[100];
+		CK_BYTE       buf3[100];
+		CK_ATTRIBUTE  check1[] =
+		{
+			{CKA_ISSUER,        &buf1, sizeof(buf1)},
+			{CKA_SERIAL_NUMBER, &buf2, sizeof(buf2)},
+			{CKA_ID,            &buf3, sizeof(buf3)}
+		};
+
+		rc = funcs->C_GetAttributeValue(h_session, h_cert, (CK_ATTRIBUTE *)&check1, 3);
+		if (rc != CKR_OK) {
+                        testcase_fail("C_GetAttributeValue() rc = %s", p11_get_ckr(rc));
+			goto done;
+		}
+
+		if (memcmp(check1[0].pValue, cert_issuer, check1[0].ulValueLen) != 0) {
+                        testcase_fail("CKA_ISSUER mismatch");
+			rc = -1;
+			goto done;
+		}
+
+		if (memcmp(check1[1].pValue, cert_ser_no, check1[1].ulValueLen) != 0) {
+                        testcase_fail("CKA_SERIAL_NUMBER mismatch");
+			return -1;
+		}
+
+		if (memcmp(check1[2].pValue, cert_id2, check1[2].ulValueLen) != 0) {
+                        testcase_fail("CKA_ID mismatch");
+			rc = -1;
+			goto done;
+		}
+	}
+
+	/* the next template tries to update a CK_ID (valid) and
+	 * CKA_VALUE (read-only). the entire operation should fail -- no
+	 * attributes should get modified
+	 */
+	rc = funcs->C_SetAttributeValue(h_session, h_cert, invalid_attr, 2);
+	if (rc != CKR_ATTRIBUTE_READ_ONLY) {
+                testcase_fail("C_SetAttributeValue() rc = %s (expected CKR_ATTRIBUTE_READ_ONLY)", p11_get_ckr(rc));
+		goto done;
+	}
+	else {
+		CK_BYTE       buf1[100];
+		CK_ATTRIBUTE  check1[] =
+		{
+			{CKA_ID, &buf1, sizeof(buf1)}
+		};
+
+		rc = funcs->C_GetAttributeValue(h_session, h_cert, check1, 1);
+		if (rc != CKR_OK) {
+                        testcase_fail("C_GetAttributeValue() rc = %s", p11_get_ckr(rc));
+			goto done;
+		}
+
+		if (memcmp(check1[0].pValue, cert_id2, check1[0].ulValueLen) != 0) {
+                        testcase_fail("CKA_ID mismatch");
+			rc = -1;
+			goto done;
+		}
+	}
+
+	testcase_pass("Looks okay...");
+
+done:
+	/* now destroy the objects but don't clobber rc */
+	loc_rc = funcs->C_DestroyObject(h_session, h_cert);
+	if (loc_rc != CKR_OK)
+                testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc));
+
+
+	/* done...close the session */
+	loc_rc = funcs->C_CloseAllSessions(slot_id);
+	if (loc_rc != CKR_OK)
+                testcase_error("C_CloseAllSessions() loc_rc = %s", p11_get_ckr(loc_rc));
+
+	return rc;
+}
+
+
+
+
+/* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock.
+ * C_OpenSession
+ * C_CloseSession
+ *
+ * API routines exercised that result in stdll taking
+ * /var/lock/opencryptoki_stdll spinlock.
+ * C_FindObjectsInit
+ * C_FindObjects
+ * C_CreateObject
+ *
+ * 1) Create 3 certificates with different CKA_ID attributes
+ * 2) Search for a particular CKA_ID.  Verify this works.
+ * 3) Search for a non-existant CKA_ID.  Verify this returns nothing.
+ * 4) Specify an empty template.  Verify that all 3 objects are returned.
+ */
+CK_RV do_FindObjects(void)
+{
+	CK_SLOT_ID        slot_id;
+	CK_FLAGS          flags;
+	CK_SESSION_HANDLE h_session;
+	CK_RV             rc = 0, loc_rc = 0;
+	CK_BYTE           user_pin[PKCS11_MAX_PIN_LEN];
+	CK_ULONG          user_pin_len;
+
+	CK_BYTE           true = TRUE;
+
+	CK_OBJECT_HANDLE    h_cert1;
+	CK_OBJECT_CLASS     cert1_class         = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert1_type          = CKC_X_509;
+	CK_BYTE             cert1_subject[]     = "Certificate subject #1";
+	CK_BYTE             cert1_id[]          = "Certificate ID #1";
+	CK_BYTE             cert1_value[]       = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert1_attribs[] =
+	{
+		{CKA_CLASS,            &cert1_class,       sizeof(cert1_class)   },
+		{CKA_TOKEN,            &true,              sizeof(true)          },
+		{CKA_CERTIFICATE_TYPE, &cert1_type,        sizeof(cert1_type)    },
+		{CKA_SUBJECT,          &cert1_subject,     sizeof(cert1_subject) },
+		{CKA_ID,               &cert1_id,          sizeof(cert1_id)      },
+		{CKA_VALUE,            &cert1_value,       sizeof(cert1_value)   }
+	};
+
+	CK_OBJECT_HANDLE    h_cert2;
+	CK_OBJECT_CLASS     cert2_class        = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert2_type         = CKC_X_509;
+	CK_BYTE             cert2_subject[]    = "Certificate subject #2";
+	CK_BYTE             cert2_id[]         = "Certificate ID #2";
+	CK_BYTE             cert2_value[]      = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert2_attribs[] =
+	{
+		{CKA_CLASS,            &cert2_class,       sizeof(cert2_class)   },
+		{CKA_TOKEN,            &true,              sizeof(true)          },
+		{CKA_CERTIFICATE_TYPE, &cert2_type,        sizeof(cert2_type)    },
+		{CKA_SUBJECT,          &cert2_subject,     sizeof(cert2_subject) },
+		{CKA_ID,               &cert2_id,          sizeof(cert2_id)      },
+		{CKA_VALUE,            &cert2_value,       sizeof(cert2_value)   }
+	};
+
+	CK_OBJECT_HANDLE    h_cert3;
+	CK_OBJECT_CLASS     cert3_class        = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert3_type         = CKC_X_509;
+	CK_BYTE             cert3_subject[]    = "Certificate subject #3";
+	CK_BYTE             cert3_id[]         = "Certificate ID #3";
+	CK_BYTE             cert3_value[]      = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert3_attribs[] =
+	{
+		{CKA_CLASS,            &cert3_class,       sizeof(cert3_class)   },
+		{CKA_TOKEN,            &true,             sizeof(true)          },
+		{CKA_CERTIFICATE_TYPE, &cert3_type,        sizeof(cert3_type)    },
+		{CKA_SUBJECT,          &cert3_subject,     sizeof(cert3_subject) },
+		{CKA_ID,               &cert3_id,          sizeof(cert3_id)      },
+		{CKA_VALUE,            &cert3_value,       sizeof(cert3_value)   }
+	};
+
+	CK_BYTE  find1_id[] = "Certificate ID #2";
+	CK_ATTRIBUTE   find1_attribs[] =
+	{
+		{CKA_ID, &find1_id,  sizeof(find1_id)}
+	};
+
+	CK_BYTE  find2_id[] = "Certificate ID #12345";
+	CK_ATTRIBUTE   find2_attribs[] =
+	{
+		{CKA_ID, &find2_id,  sizeof(find2_id)}
+	};
+
+	CK_OBJECT_HANDLE  obj_list[10];
+	CK_ULONG          find_count;
+	int		  i, got_it = 0;
+
+
+	testcase_begin("starting...");
+
+	if (get_user_pin(user_pin))
+		return CKR_FUNCTION_FAILED;
+	user_pin_len = (CK_ULONG)strlen((char *)user_pin);
+
+	slot_id = SLOT_ID;
+
+
+	/* create a USER R/W session */
+	flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
+	rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if (rc != CKR_OK) {
+                testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* create the objects */
+	rc = funcs->C_CreateObject(h_session, cert1_attribs, 6, &h_cert1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_CreateObject(h_session, cert2_attribs, 6, &h_cert2);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		goto destroy_1;
+	}
+
+	rc = funcs->C_CreateObject(h_session, cert3_attribs, 6, &h_cert3);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		goto destroy_2;
+	}
+
+	/* now, search for the 2nd objects */
+	rc = funcs->C_FindObjectsInit(h_session, find1_attribs, 1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	/* step through list and find our object handle */
+	for (i=0; i<find_count; i++) {
+		if (obj_list[i] == h_cert2)
+			got_it++;
+	}
+	if (got_it == 0) {
+		testcase_fail("could not find object handle");
+		rc = -1;
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	/* now, search for a non-existant object */
+	rc = funcs->C_FindObjectsInit(h_session, find2_attribs, 1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	if (find_count != 0) {
+                testcase_fail("found %ld objects when none where expected", find_count);
+		rc = -1;
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	testcase_pass("Looks okay...");
+
+destroy:
+	/* now destroy the objects that were created */
+	loc_rc = funcs->C_DestroyObject(h_session, h_cert3);
+	if (loc_rc != CKR_OK)
+                testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc));
+
+destroy_2:
+	loc_rc = funcs->C_DestroyObject(h_session, h_cert2);
+	if (loc_rc != CKR_OK)
+                testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc));
+
+destroy_1:
+	loc_rc = funcs->C_DestroyObject(h_session, h_cert1);
+	if (loc_rc != CKR_OK)
+                testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc));
+
+	/* done...close the session */
+	loc_rc = funcs->C_CloseAllSessions(slot_id);
+	if (loc_rc != CKR_OK)
+		testcase_error("C_CloseAllSessions() loc_rc = %s", p11_get_ckr(loc_rc));
+
+	return rc;
+}
+
+/* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock.
+ * C_OpenSession
+ * C_CloseSession
+ *
+ * API routines exercised that result in stdll taking
+ * /var/lock/opencryptoki_stdll spinlock.
+ * C_FindObjectsInit
+ * C_FindObjects
+ * C_CreateObject
+ *
+ *  1) Create 3 certificates as PUBLIC token objects
+ *  2) Search for a particular CKA_ID.  Verify that this works.
+ *  3) Do FindObjects with a NULL template.  Verify that all 3 token objects
+ *     are found.
+ *  4) Search for a particular CKA_ID.  Verify it works.
+ *  5) Search for a non-existant CKA_ID.  Verify it returns nothing.
+ *  6) Close all sessions.  Then create a new session.
+ *  7) Search for a particular CKA_ID.  Verify it works.
+ *  8) Search for a non-existant CKA_ID.  Verify it returns nothing.
+ *  9) Destroy all 3 token objects
+ */
+CK_RV do_CreateTokenObjects(void)
+{
+	int 		  i, got_it = 0;
+	CK_SLOT_ID        slot_id;
+	CK_FLAGS          flags;
+	CK_SESSION_HANDLE h_session;
+	CK_RV             rc = 0, loc_rc = 0;
+	CK_BYTE           user_pin[PKCS11_MAX_PIN_LEN];
+	CK_ULONG          user_pin_len;
+
+	CK_BYTE           true = TRUE;
+	CK_BYTE           false = FALSE;
+
+	CK_OBJECT_HANDLE    h_cert1;
+	CK_OBJECT_CLASS     cert1_class         = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert1_type          = CKC_X_509;
+	CK_BYTE             cert1_subject[]     = "Certificate subject #1";
+	CK_BYTE             cert1_id[]          = "Certificate ID #1";
+	CK_BYTE             cert1_value[]       = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert1_attribs[] =
+	{
+		{CKA_CLASS,            &cert1_class,       sizeof(cert1_class)   },
+		{CKA_TOKEN,            &true,              sizeof(true)          },
+		{CKA_CERTIFICATE_TYPE, &cert1_type,        sizeof(cert1_type)    },
+		{CKA_SUBJECT,          &cert1_subject,     sizeof(cert1_subject) },
+		{CKA_ID,               &cert1_id,          sizeof(cert1_id)      },
+		{CKA_VALUE,            &cert1_value,       sizeof(cert1_value)   },
+		{CKA_PRIVATE,          &false,             sizeof(false)         }
+	};
+
+	CK_OBJECT_HANDLE    h_cert2;
+	CK_OBJECT_CLASS     cert2_class        = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert2_type         = CKC_X_509;
+	CK_BYTE             cert2_subject[]    = "Certificate subject #2";
+	CK_BYTE             cert2_id[]         = "Certificate ID #2";
+	CK_BYTE             cert2_value[]      = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert2_attribs[] =
+	{
+		{CKA_CLASS,            &cert2_class,       sizeof(cert2_class)   },
+		{CKA_TOKEN,            &true,              sizeof(true)          },
+		{CKA_CERTIFICATE_TYPE, &cert2_type,        sizeof(cert2_type)    },
+		{CKA_SUBJECT,          &cert2_subject,     sizeof(cert2_subject) },
+		{CKA_ID,               &cert2_id,          sizeof(cert2_id)      },
+		{CKA_VALUE,            &cert2_value,       sizeof(cert2_value)   },
+		{CKA_PRIVATE,          &false,             sizeof(false)         }
+	};
+
+	CK_OBJECT_HANDLE    h_cert3;
+	CK_OBJECT_CLASS     cert3_class        = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE cert3_type         = CKC_X_509;
+	CK_BYTE             cert3_subject[]    = "Certificate subject #3";
+	CK_BYTE             cert3_id[]         = "Certificate ID #3";
+	CK_BYTE             cert3_value[]      = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+	CK_ATTRIBUTE        cert3_attribs[] =
+	{
+		{CKA_CLASS,            &cert3_class,       sizeof(cert3_class)   },
+		{CKA_TOKEN,            &true,              sizeof(true)          },
+		{CKA_CERTIFICATE_TYPE, &cert3_type,        sizeof(cert3_type)    },
+		{CKA_SUBJECT,          &cert3_subject,     sizeof(cert3_subject) },
+		{CKA_ID,               &cert3_id,          sizeof(cert3_id)      },
+		{CKA_VALUE,            &cert3_value,       sizeof(cert3_value)   },
+		{CKA_PRIVATE,          &false,             sizeof(false)         }
+	};
+
+	CK_BYTE  find1_id[] = "Certificate ID #2";
+	CK_ATTRIBUTE   find1_attribs[] =
+	{
+		{CKA_ID, &find1_id,  sizeof(find1_id)}
+	};
+
+	CK_BYTE  find2_id[] = "Certificate ID #123456";
+	CK_ATTRIBUTE   find2_attribs[] =
+	{
+		{CKA_ID, &find2_id,  sizeof(find2_id)}
+	};
+
+	CK_OBJECT_HANDLE  obj_list[10];
+	CK_ULONG          find_count;
+
+
+
+        testcase_begin("starting...");
+
+	if (get_user_pin(user_pin))
+		return CKR_FUNCTION_FAILED;
+	user_pin_len = (CK_ULONG)strlen((char *)user_pin);
+
+	slot_id = SLOT_ID;
+
+	/* create a USER R/W session */
+	flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
+	rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if (rc != CKR_OK) {
+                testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	/* create the token objects */
+	rc = funcs->C_CreateObject(h_session, cert1_attribs, 7, &h_cert1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	rc = funcs->C_CreateObject(h_session, cert2_attribs, 7, &h_cert2);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		goto destroy_1;
+	}
+
+	rc = funcs->C_CreateObject(h_session, cert3_attribs, 7, &h_cert3);
+	if (rc != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		goto destroy_2;
+	}
+
+	/* now, search for the 2nd object */
+	rc = funcs->C_FindObjectsInit(h_session, find1_attribs, 1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+        /* step through list and find 2nd object's handle */
+        for (i=0; i<find_count; i++) {
+                if (obj_list[i] == h_cert2)
+                        got_it++;
+        }
+	if (got_it == 0) {
+                testcase_fail("could not find 2nd object's handle");
+		rc = -1;
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	/* now, search for a non-existant attribute */
+	rc = funcs->C_FindObjectsInit(h_session, find2_attribs, 1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	if (find_count != 0) {
+                testcase_fail("found %ld objects when none where expected", find_count);
+		rc = -1;
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	/* done...close all sessions and open a new one */
+	rc = funcs->C_CloseAllSessions( slot_id );
+	if (rc != CKR_OK) {
+                testcase_fail("C_CloseAllSessions() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	/* create a USER R/W session */
+	flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
+	rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if (rc != CKR_OK) {
+                testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	/* now, search for the 2nd object */
+	rc = funcs->C_FindObjectsInit(h_session, find1_attribs, 1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+        /* step through list and find 2nd object's handle */
+        for (i=0; i<find_count; i++) {
+                if (obj_list[i] == h_cert2)
+                        got_it++;
+        }
+	if (got_it == 0) {
+                testcase_fail("could not find 2nd object's handle in new session");
+		rc = -1;
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	/* now, search for a non-existant attribute */
+	rc = funcs->C_FindObjectsInit(h_session, find2_attribs, 1);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	if (find_count != 0) {
+                testcase_fail("found %ld objects when none where expected", find_count);
+		rc = -1;
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session);
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	testcase_pass("Looks okay...");
+
+	/* Destroy the created objects, don't clobber the rc */
+destroy:
+	loc_rc = funcs->C_DestroyObject(h_session, h_cert3);
+	if (loc_rc != CKR_OK)
+                testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc));
+
+destroy_2:
+	loc_rc = funcs->C_DestroyObject(h_session, h_cert2);
+	if (loc_rc != CKR_OK)
+                testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc));
+
+destroy_1:
+	loc_rc = funcs->C_DestroyObject(h_session, h_cert1);
+	if (loc_rc != CKR_OK)
+                testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc));
+
+	/* done...close the session */
+	loc_rc = funcs->C_CloseAllSessions(slot_id);
+	if (loc_rc != CKR_OK)
+                testcase_error("C_CloseAllSessions() loc_rc = %s", p11_get_ckr(loc_rc));
+
+	return rc;
+}
+
+/*
+ * do_HW_Feature_Search Test:
+ *
+ * 1. Create 5 objects, 3 of which are HW_FEATURE objects.
+ * 2. Search for objects using a template that does have its
+ *    HW_FEATURE attribute set.
+ * 3. Result should be that the hardware feature object is returned.
+ *
+ */
+
+CK_RV do_HWFeatureSearch(void)
+{
+	unsigned int            i, got_it = 0;
+	CK_RV 			rc, loc_rc;
+	CK_ULONG		find_count;
+	CK_SLOT_ID		slot_id;
+	CK_BBOOL		false = FALSE;
+	CK_BBOOL                true = TRUE;
+
+	CK_SESSION_HANDLE 	h_session;
+	CK_BYTE           	user_pin[PKCS11_MAX_PIN_LEN];
+	CK_ULONG          	user_pin_len;
+
+	/* A counter object */
+	CK_OBJECT_CLASS         counter1_class = CKO_HW_FEATURE;
+	CK_HW_FEATURE_TYPE      feature1_type = CKH_MONOTONIC_COUNTER;
+	CK_UTF8CHAR             counter1_label[] = "Monotonic counter";
+	CK_CHAR			counter1_value[16];
+	CK_ATTRIBUTE            counter1_template[] = {
+		{CKA_CLASS,		&counter1_class, sizeof(counter1_class)},
+		{CKA_HW_FEATURE_TYPE,	&feature1_type,  sizeof(feature1_type)},
+		{CKA_LABEL,		counter1_label,  sizeof(counter1_label)-1},
+		{CKA_VALUE,		counter1_value,	sizeof(counter1_value)},
+		{CKA_RESET_ON_INIT,	&true,		sizeof(true)},
+		{CKA_HAS_RESET,		&false,		sizeof(false)}
+	};
+	/* A clock object */
+	CK_OBJECT_CLASS         clock_class = CKO_HW_FEATURE;
+	CK_HW_FEATURE_TYPE      clock_type = CKH_CLOCK;
+	CK_UTF8CHAR             clock_label[] = "Clock";
+	CK_CHAR			clock_value[16];
+	CK_ATTRIBUTE            clock_template[] = {
+		{CKA_CLASS,		&clock_class, sizeof(clock_class)},
+		{CKA_HW_FEATURE_TYPE,	&clock_type,  sizeof(clock_type)},
+		{CKA_LABEL,		clock_label,  sizeof(clock_label)-1},
+		{CKA_VALUE,		clock_value,	sizeof(clock_value)}
+	};
+	/* A data object */
+	CK_OBJECT_CLASS		obj1_class = CKO_DATA;
+	CK_UTF8CHAR             obj1_label[] = "Object 1";
+	CK_BYTE			obj1_data[] = "Object 1's data";
+	CK_ATTRIBUTE            obj1_template[] = {
+		{CKA_CLASS,		&obj1_class,    sizeof(obj1_class)},
+		{CKA_TOKEN,		&true,          sizeof(true)},
+		{CKA_LABEL,		obj1_label,     sizeof(obj1_label)-1},
+		{CKA_VALUE,		obj1_data,	sizeof(obj1_data)}
+	};
+	/* A secret key object */
+	CK_OBJECT_CLASS		obj2_class = CKO_SECRET_KEY;
+	CK_KEY_TYPE		obj2_type = CKK_AES;
+	CK_UTF8CHAR             obj2_label[] = "Object 2";
+	CK_BYTE			obj2_data[AES_KEY_SIZE_128];
+	CK_ATTRIBUTE            obj2_template[] = {
+		{CKA_CLASS,		&obj2_class,    sizeof(obj2_class)},
+		{CKA_TOKEN,		&true,          sizeof(true)},
+		{CKA_KEY_TYPE,		&obj2_type,	sizeof(obj2_type)},
+		{CKA_LABEL,		obj2_label,     sizeof(obj2_label)-1},
+		{CKA_VALUE,		obj2_data,	sizeof(obj2_data)}
+	};
+
+	CK_OBJECT_HANDLE        h_counter1,
+				h_clock,
+				h_obj1,
+				h_obj2,
+				obj_list[10];
+	CK_ATTRIBUTE		find_tmpl[] = {
+		{CKA_CLASS,	&counter1_class, sizeof(counter1_class)}
+	};
+
+	slot_id = SLOT_ID;
+
+        testcase_begin("starting...");
+
+	if (get_user_pin(user_pin))
+		return CKR_FUNCTION_FAILED;
+	user_pin_len = (CK_ULONG)strlen((char *)user_pin);
+
+	/* Open a session with the token */
+	if( (rc = funcs->C_OpenSession(slot_id,
+					(CKF_SERIAL_SESSION|CKF_RW_SESSION),
+					NULL_PTR,
+					NULL_PTR,
+					&h_session)) != CKR_OK ) {
+                testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	// Login correctly
+	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+	if( rc != CKR_OK ) {
+                testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+		goto session_close;
+	}
+
+	/* Create the 3 test objects */
+	if( (rc = funcs->C_CreateObject(h_session, obj1_template, 4, &h_obj1)) != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		goto session_close;
+	}
+
+	if( (rc = funcs->C_CreateObject(h_session, obj2_template, 5, &h_obj2)) != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		goto destroy_1;
+	}
+
+	/* try and create a monotonic object. This should fail
+	 * since it is a read only feature.
+	 */
+	if( (rc = funcs->C_CreateObject(h_session, counter1_template, 6, &h_counter1)) != CKR_ATTRIBUTE_READ_ONLY) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		goto destroy_2;
+	}
+
+	if( (rc = funcs->C_CreateObject(h_session, clock_template, 4, &h_clock)) != CKR_OK) {
+                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		goto destroy_2;
+	}
+
+	/* Now find the hardware feature objects */
+	rc = funcs->C_FindObjectsInit(h_session, find_tmpl, 1 );
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count );
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+		goto destroy;
+	}
+
+	got_it = 0;
+	/* Make sure we got the right ones */
+	for(i=0; i < find_count; i++) {
+		if(obj_list[i] == h_clock) {
+			got_it++;
+		}
+	}
+
+	if (got_it != 1) {
+		testcase_fail("could not find the corect object handle");
+		rc = -1;
+		goto destroy;
+	}
+
+	rc = funcs->C_FindObjectsFinal(h_session );
+	if (rc != CKR_OK) {
+                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+	}
+
+        testcase_pass("Looks okay...");
+
+destroy:
+	/* Destroy the created objects, don't clobber the rc */
+	loc_rc = funcs->C_DestroyObject(h_session, h_clock);
+	if( loc_rc != CKR_OK )
+                testcase_error("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc));
+destroy_2:
+	loc_rc = funcs->C_DestroyObject(h_session, h_obj2);
+	if( loc_rc != CKR_OK )
+                testcase_error("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc));
+destroy_1:
+	loc_rc = funcs->C_DestroyObject(h_session, h_obj1);
+	if( loc_rc != CKR_OK )
+                testcase_error("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc));
+
+	loc_rc = funcs->C_Logout(h_session);
+	if( loc_rc != CKR_OK )
+                testcase_error("C_Logout() rc = %s", p11_get_ckr(loc_rc));
+
+session_close:
+	/* Close the session */
+	if( (loc_rc = funcs->C_CloseSession(h_session)) != CKR_OK )
+                testcase_error("C_CloseSession() rc = %s", p11_get_ckr(loc_rc));
+
+	return rc;
+}
+
+CK_RV obj_mgmt_functions()
+{
+	int         rc, errors = 0;
+
+	rc = do_CreateSessionObject();
+	if (rc)
+		errors++;
+
+	rc = do_CopyObject();
+	if (rc)
+		errors++;
+
+	rc = do_SetAttributeValues();
+	if (rc)
+		errors++;
+
+	rc = do_FindObjects();
+	if (rc)
+		errors++;
+
+	rc = do_HWFeatureSearch();
+	if (rc)
+		errors++;
+
+	rc = do_CreateTokenObjects();
+	if (rc)
+		errors++;
+
+	return errors++;
+}
+
+int main(int argc, char **argv)
+{
+	CK_C_INITIALIZE_ARGS cinit_args;
+	int rc;
+	CK_RV rv;
+
+
+	rc = do_ParseArgs(argc, argv);
+	if ( rc != 1)
+		return rc;
+
+	printf("Using slot #%lu...\n\n", SLOT_ID );
+	printf("With option: no_init: %d, no_stop: %d, skip_token_obj: %d\n", no_init, no_stop, skip_token_obj);
+
+	rc = do_GetFunctionList();
+	if (!rc) {
+                testcase_error_f("(setup)", "do_GetFunctionList() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+	memset( &cinit_args, 0x0, sizeof(cinit_args) );
+	cinit_args.flags = CKF_OS_LOCKING_OK;
+
+	// SAB Add calls to ALL functions before the C_Initialize gets hit
+
+	funcs->C_Initialize( &cinit_args );
+
+	{
+		CK_SESSION_HANDLE  hsess = 0;
+
+		rc = funcs->C_GetFunctionStatus(hsess);
+		if (rc  != CKR_FUNCTION_NOT_PARALLEL)
+			return rc;
+
+		rc = funcs->C_CancelFunction(hsess);
+		if (rc  != CKR_FUNCTION_NOT_PARALLEL)
+			return rc;
+
+	}
+
+	rv = obj_mgmt_functions();
+
+	/* make sure we return non-zero if rv is non-zero */
+	return ((rv==0) || (rv % 256) ? rv : -1);
+}
--- /dev/null
+++ b/testcases/misc_tests/spinlock_child.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+
+
+while getopts ":s:l:" option
+do
+  case $option in
+"s")
+	slotid="$OPTARG"
+	;;
+"l")
+	loopcount="$OPTARG"
+	;;
+[?])
+	echo "Usage: -s <slotid> -l loopcount"
+	;;
+esac
+done
+
+i="0"
+echo $$
+while [ $i -lt $loopcount ]
+do
+	./obj_mgmt_lock_tests -slot $slotid
+	i=$[$i+1]
+done
--- /dev/null
+++ b/testcases/misc_tests/spinlock_tests.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+
+while getopts "s:p:l:" option
+do
+ case $option in
+"s")
+	slotid="$OPTARG"
+	;;
+"p")
+	procnum="$OPTARG"
+	;;
+"l")
+	loopcount="$OPTARG"
+	;;
+[?])
+	echo "Usage: -s <slotid> -p <num_of_processes> -l <loopcount>"
+	exit
+	;;
+esac
+done
+
+if [ -z $slotid ] || [ -z $procnum ] || [ -z $loopcount ]; then
+	echo "Usage: -s <slotid> -p <num_of_processes> -l <loopcount>"
+	exit
+fi
+
+while [ $procnum -gt 0 ]
+do
+	echo "Starting child process #$procnum"
+	(./spinlock_child.sh -s $slotid -l $loopcount;) &
+	let procnum=procnum-1
+done
+
+wait
+echo "Exiting parent loop"
--- a/usr/include/pkcs11/slotmgr.h
+++ b/usr/include/pkcs11/slotmgr.h
@@ -312,15 +312,8 @@
 #ifndef _SLOTMGR_H
 #define _SLOTMGR_H
 
-
-
-#ifdef DEV
-    #define TOK_PATH  SBIN_PATH "/pkcsslotd"
-#else
-    #define TOK_PATH  SBIN_PATH "/pkcsslotd"
-#endif /* DEV */
-
-#define  XPL_FILE  "/tmp/.pkapi_xpk"
+#define TOK_PATH  SBIN_PATH "/pkcsslotd"
+#define  OCK_API_LOCK_FILE  "/var/lock/LCK..opencryptoki"
 
 #define PID_FILE_PATH "/var/run/pkcsslotd.pid"
 
@@ -427,17 +420,6 @@ typedef struct CK_SLOT_INFO_64 {
 
 
 typedef struct Slot_Mgr_Proc_t_64 {
-#if SYSVSEM
-      int                slt_mutex;
-#elif PTHREADXPL
-     pthread_mutex_t       slt_mutex;
-#elif POSIXSEM
-#error "Need to implement this"
-#elif NOXPROCLOCK
-     int       slt_mutex; // unused.
-#elif SPINXPL
-     unsigned int   slt_mutex;
-#endif
   // pthread_cond_t   proc_slot_cond;   
 
    CK_BOOL    inuse;  // flag indicating if the entry is in use
@@ -483,26 +465,6 @@ typedef struct{
 
 typedef struct {
    
-  /*************************************************************
-   *    Mutexes for access and control of the structures.
-   *    When a process wants to register with the slot mgr
-   *    it will have to get the mutex on the shared memory region
-   *    and then finds an empty slot in the process table to use.
-   *    This simplifies the management capabilities.   
-   *************************************************************/
-#if SYSVSEM
-      int                slt_mutex;
-#elif PTHREADXPL
-     pthread_mutex_t       slt_mutex;
-#elif POSIXSEM
-#error "Need to implement this"
-#elif NOXPROCLOCK
-     int       slt_mutex; // unused.
-#elif SPINXPL
-     unsigned int   slt_mutex;
-#endif
-
-   
   /* Information that the API calls will use. */
   uint8                 num_slots;
   CK_INFO_64            ck_info;
@@ -516,26 +478,6 @@ typedef struct {
 
 typedef struct {
    
-  /*************************************************************
-   *    Mutexes for access and control of the structures.
-   *    When a process wants to register with the slot mgr
-   *    it will have to get the mutex on the shared memory region
-   *    and then finds an empty slot in the process table to use.
-   *    This simplifies the management capabilities.   
-   *************************************************************/
-
-#if SYSVSEM
-   int                slt_mutex;
-#elif PTHREADXPL
-  pthread_mutex_t       slt_mutex;
-#elif POSIXSEM
-#error "Need to implement this"
-#elif NOXPROCLOCK
-  int       slt_mutex; // unused.
-#elif SPINXPL
-  unsigned int   slt_mutex;
-#endif
- 
   /* Information that the API calls will use. */
   uint8                 num_slots;
   CK_INFO               ck_info;
--- a/usr/lib/pkcs11/api/api_interface.c
+++ b/usr/lib/pkcs11/api/api_interface.c
@@ -4694,7 +4694,7 @@ C_WaitForSlotEvent ( CK_FLAGS       flag
    //  REally should be the procp->proc_mutex
    // but this is such an infrequent thing that we will simply get
    // the global shared memory lock
-   lock_shm();
+   XProcLock();
    if ( procp->slotmap) {
       // find the first bit set
       // This will have to change if more than 32 slots ever get supported
@@ -4705,11 +4705,11 @@ C_WaitForSlotEvent ( CK_FLAGS       flag
          }
       }
       *pSlot = i;  // set the flag
-      unlock_shm();
+      XProcUnLock();
       return CKR_OK;
    } else {
       if ( flags & CKF_DONT_BLOCK ) {
-         unlock_shm();
+         XProcUnLock();
          return CKR_NO_EVENT;
       } else {
          // WE need to 
@@ -4724,13 +4724,13 @@ C_WaitForSlotEvent ( CK_FLAGS       flag
          // We will choose to fail the call.
          if (procp->blocking) {
             OCK_LOG_DEBUG("WaitForSlot event called by process twice.\n");
-            unlock_shm();  // Unlock aftersetting
+            XProcUnLock();  // Unlock aftersetting
             OCK_LOG_ERR(ERR_FUNCTION_FAILED);
             return CKR_FUNCTION_FAILED;
          }
          procp->error = 0;
          procp->blocking = 0x01;
-         unlock_shm();  // Unlock aftersetting
+         XProcUnLock();  // Unlock aftersetting
 
          // NOTE:  We need to have an asynchronous mechanism for
          // the slot manager to wake up anyone blocking on this.
@@ -4740,10 +4740,10 @@ C_WaitForSlotEvent ( CK_FLAGS       flag
          while (!procp->slotmap  && !procp->error){
             sleep(1);  // Note This is really bad form.  But what the heck
          }
-         lock_shm();
+         XProcLock();
          procp->blocking = 0;
          if ( procp->error ) {
-            unlock_shm();
+            XProcUnLock();
             OCK_LOG_ERR(ERR_GENERAL_ERROR);
             return CKR_GENERAL_ERROR; // We bailed on this because we were terminating
             // General error should cause the calling thread to not try anything
@@ -4756,7 +4756,7 @@ C_WaitForSlotEvent ( CK_FLAGS       flag
                }
             }
             *pSlot = i;  // set the flag
-            unlock_shm();
+            XProcUnLock();
             return CKR_OK;
          }
       }
--- a/usr/lib/pkcs11/api/apiutil.c
+++ b/usr/lib/pkcs11/api/apiutil.c
@@ -335,22 +335,18 @@ extern  API_Proc_Struct_t  *Anchor;
 #include <stdarg.h>
 
 
-void
-set_perm(int file)
-{
-
-   // Set absolute permissions or rw-rw-r--
-   fchmod(file,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
-
-}
-
 int
 XProcLock(void)
 {
    if (xplfd == -1 ) {
-        xplfd = open(XPL_FILE,O_CREAT|O_RDWR,S_IRWXU|S_IRWXG|S_IRWXO);
+        xplfd = open(OCK_API_LOCK_FILE,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
+	if (xplfd == -1)
+	    OCK_LOG_DEBUG("Failed to open lock file,%s: %s\n",
+                          OCK_API_LOCK_FILE, strerror(errno));
    }
-   flock(xplfd,LOCK_EX);
+   if (xplfd != -1)
+	flock(xplfd,LOCK_EX);
+
    return CKR_OK;
 }
 
@@ -610,19 +606,6 @@ sessions_exist(slotID)
    return TRUE;
 }
 
-void
-unlock_shm()
-{
-   XProcUnLock();
-}
-
-void
-lock_shm()
-{
-   XProcLock();
-}
-
-
 // Terminates all sessions associated with a given process
 // this cleans up any lingering sessions with the process
 // and does not 
--- a/usr/lib/pkcs11/cca_stdll/h_extern.h
+++ b/usr/lib/pkcs11/cca_stdll/h_extern.h
@@ -2173,4 +2173,5 @@ void dump_shm(const char *);
 CK_RV sw_des3_cbc(CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *,
 		  CK_BYTE  *, CK_BYTE *, CK_BYTE);
 
+#define OCK_STDLL_LOCK_FILE	"/var/lock/LCK..opencryptoki_stdll"
 #endif
--- a/usr/lib/pkcs11/cca_stdll/loadsave.c
+++ b/usr/lib/pkcs11/cca_stdll/loadsave.c
@@ -82,7 +82,7 @@ load_token_data()
       /* Better error checking added */
       if (errno == ENOENT) {
          /* init_token_data may call save_token_data, which graps the 
-          * xproclock, so we must release it around this call */
+          * lock, so we must release it around this call */
          XProcUnLock();
          init_token_data();
          rc = XProcLock();
--- a/usr/lib/pkcs11/cca_stdll/new_host.c
+++ b/usr/lib/pkcs11/cca_stdll/new_host.c
@@ -104,14 +104,12 @@ st_Initialized()
 }
 
 extern int spinxplfd;
-extern int spin_created;
 
 void
 Fork_Initializer(void)
 {
 
 	spinxplfd = -1;
-	spin_created = 0;
 
 	// Force logout.  This cleans out the private session and list
 	// and cleans out the private object map
@@ -425,7 +423,7 @@ CK_RV SC_Finalize( CK_SLOT_ID sid )
 	object_mgr_purge_token_objects();
 	detach_shm();
 	// close spin lock file
-	if (spin_created)
+	if (spinxplfd != -1)
 	  close(spinxplfd);
 	if ( token_specific.t_final != NULL) {
 		token_specific.t_final();
--- a/usr/lib/pkcs11/cca_stdll/utility.c
+++ b/usr/lib/pkcs11/cca_stdll/utility.c
@@ -313,61 +313,33 @@ _UnlockMutex( MUTEX *mutex )
 }
 
 int spinxplfd=-1;
-int spin_created=0;
-
-extern void set_perm(int);
 
 CK_RV
-CreateXProcLock(void)
+XProcLock(void)
 {
-    // open the file that we will do the locking on...
-  spinxplfd = open("/tmp/.pkcs11spinloc",O_CREAT|O_APPEND|O_RDWR,
-        S_IRWXU|S_IRWXG|S_IRWXO);
-   if (spinxplfd) {
-	   	
-	set_perm(spinxplfd);
-	fchmod(spinxplfd,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH | S_IWOTH);
-	spin_created=1;
-   } else {
-	   perror("XPROC CREATE file :");
+
+   /* see if it exists */
+   if (spinxplfd == -1) {
+       spinxplfd = open(OCK_STDLL_LOCK_FILE, O_CREAT|O_RDWR,
+                        S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
+       if (spinxplfd == -1)
+          OCK_LOG_DEBUG("Failed to open lock file,%s: %s\n",
+                        OCK_STDLL_LOCK_FILE, strerror(errno));
    }
-    return CKR_OK;
-}
 
-CK_RV
-DestroyXProcLock(void)
-{
-	return CKR_OK;
-}
+   if (spinxplfd != -1)
+      flock(spinxplfd,LOCK_EX);
 
-CK_RV
-XProcLock(void)
-{
-	if (!spin_created) {
-	  spinxplfd = open("/tmp/.pkcs11spinloc",O_CREAT|O_APPEND|O_RDWR,
-		S_IRWXU|S_IRWXG|S_IRWXO);
-	  fchmod(spinxplfd,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH | S_IWOTH);
-	  spin_created=1;
-	}
-	if (spinxplfd){
-		flock(spinxplfd,LOCK_EX);
-	}
-	return CKR_OK;
+   return CKR_OK;
 }
 
 CK_RV
 XProcUnLock(void)
 {
-	if (!spin_created) {
-	  spinxplfd = open("/tmp/.pkcs11spinloc",O_CREAT|O_APPEND|O_RDWR,
-		S_IRWXU|S_IRWXG|S_IRWXO);
-	  fchmod(spinxplfd,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH | S_IWOTH);
-	  spin_created=1;
-	}
-	if (spinxplfd) {
-		flock(spinxplfd,LOCK_UN);
-	}
-	return CKR_OK;
+   if (spinxplfd != -1)
+      flock(spinxplfd,LOCK_UN);
+
+   return CKR_OK;
 }
 
 
@@ -740,7 +712,6 @@ attach_shm()
       return CKR_FUNCTION_FAILED;
    }
    if (created == TRUE) {
-      CreateXProcLock();
       XProcLock();
       global_shm->num_publ_tok_obj = 0;
       global_shm->num_priv_tok_obj = 0;
--- a/usr/lib/pkcs11/common/h_extern.h
+++ b/usr/lib/pkcs11/common/h_extern.h
@@ -2475,5 +2475,6 @@ void dump_shm(const char *);
 #define CKA_HIDDEN              CKA_VENDOR_DEFINED + 0x01000000
 
 
+#define OCK_STDLL_LOCK_FILE	"/var/lock/LCK..opencryptoki_stdll"
 
 #endif
--- a/usr/lib/pkcs11/common/new_host.c
+++ b/usr/lib/pkcs11/common/new_host.c
@@ -384,19 +384,13 @@ st_Initialized()
 	return TRUE;
 }
 
-#ifdef SPINXPL
 extern int spinxplfd;
-extern int spin_created;
-#endif
 
 void
 Fork_Initializer(void)
 {
 
-#ifdef SPINXPL
 	spinxplfd = -1;
-	spin_created = 0;
-#endif
 
 	// Force logout.  This cleans out the private session and list
 	// and cleans out the private object map
@@ -711,7 +705,7 @@ CK_RV SC_Finalize( CK_SLOT_ID sid )
 	object_mgr_purge_token_objects();
 	detach_shm();
 	// close spin lock file
-	if (spin_created)
+	if (spinxplfd != -1)
 	  close(spinxplfd);
 	if ( token_specific.t_final != NULL) {
 		token_specific.t_final();
--- a/usr/lib/pkcs11/common/obj_mgr.c
+++ b/usr/lib/pkcs11/common/obj_mgr.c
@@ -1163,8 +1163,10 @@ delete_token_obj_cb(void *node, unsigned
 
 		delete_token_object(o);
 
-		/* Use the same calling convention as the old code, if XProcLock fails, don't
-		 * delete from shm and don't free the object in its other btree */
+		/* Use the same calling convention as the old code, if
+		 * XProcLock fails, don't delete from shm and don't free
+		 * the object in its other btree
+		 */
 		if (XProcLock()) {
 			OCK_LOG_ERR(ERR_PROCESS_LOCK);
 			goto done;
@@ -1217,7 +1219,10 @@ object_mgr_destroy_token_objects( void )
       OCK_LOG_ERR(ERR_PROCESS_LOCK);
 done:
    if (locked1 == TRUE) MY_UnlockMutex( &obj_list_mutex );
-   if (locked2 == TRUE) XProcUnLock();
+/*   if (locked2 == TRUE) XProcUnLock(); */
+   if (locked2 == TRUE) {
+	XProcUnLock();
+   }
 
    return rc;
 }
@@ -1329,7 +1334,10 @@ object_mgr_find_in_map1( CK_OBJECT_HANDL
 // SAB XXX Fix me.. need to make it more efficient than just looking for the object to be changed
 // set a global flag that contains the ref count to all objects.. if the shm ref count changes, then we update the object
 // if not
+
+   XProcLock();
    object_mgr_check_shm( obj );
+   XProcUnLock();
 
    *ptr = obj;
 done:
@@ -1401,7 +1409,10 @@ object_mgr_find_in_map2( OBJECT
    }
 
    *handle = fa.map_handle;
+
+   XProcLock();
    object_mgr_check_shm( obj );
+   XProcUnLock();
 
    return CKR_OK;
 }
@@ -1517,7 +1528,9 @@ object_mgr_find_init( SESSION      * ses
 
 //  --- need to grab the object lock here 
    MY_LockMutex(&obj_list_mutex);
+   XProcLock();
    object_mgr_update_from_shm();
+   XProcUnLock();
 
    fa.hw_feature = FALSE;
    fa.hidden_object = FALSE;
--- a/usr/lib/pkcs11/common/utility.c
+++ b/usr/lib/pkcs11/common/utility.c
@@ -310,9 +310,7 @@
 #include "tok_spec_struct.h"
 #include "pkcs32.h"
 
-#if (SPINXPL)
 #include <sys/file.h>
-#endif
 
 
 
@@ -595,62 +593,31 @@ _UnlockMutex( MUTEX *mutex )
 
 
 int spinxplfd=-1;
-int spin_created=0;
-
-extern void set_perm(int);
 
 CK_RV
-CreateXProcLock(void)
+XProcLock(void)
 {
-
-    // open the file that we will do the locking on...
-  spinxplfd = open("/tmp/.pkcs11spinloc",O_CREAT|O_APPEND|O_RDWR,
-        S_IRWXU|S_IRWXG|S_IRWXO);
-   if (spinxplfd) {
-	   	
-	set_perm(spinxplfd);
-	fchmod(spinxplfd,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH | S_IWOTH);
-	spin_created=1;
-   } else {
-	   perror("XPROC CREATE file :");
+   if (spinxplfd == -1) {
+       spinxplfd = open(OCK_STDLL_LOCK_FILE, O_CREAT|O_RDWR,
+                        S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
+      if (spinxplfd == -1)
+          OCK_LOG_DEBUG("Failed to open lock file,%s: %s\n",
+                        OCK_STDLL_LOCK_FILE, strerror(errno));
    }
-    return CKR_OK;
-}
 
-CK_RV
-DestroyXProcLock(void)
-{
-	return CKR_OK;
-}
+   if (spinxplfd != -1)
+       flock(spinxplfd,LOCK_EX);
 
-CK_RV
-XProcLock(void)
-{
-	if (!spin_created) {
-	  spinxplfd = open("/tmp/.pkcs11spinloc",O_CREAT|O_APPEND|O_RDWR,
-		S_IRWXU|S_IRWXG|S_IRWXO);
-	  fchmod(spinxplfd,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH | S_IWOTH);
-	  spin_created=1;
-	}
-	if (spinxplfd){
-		flock(spinxplfd,LOCK_EX);
-	}
-	return CKR_OK;
+   return CKR_OK;
 }
 
 CK_RV
 XProcUnLock(void)
 {
-	if (!spin_created) {
-	  spinxplfd = open("/tmp/.pkcs11spinloc",O_CREAT|O_APPEND|O_RDWR,
-		S_IRWXU|S_IRWXG|S_IRWXO);
-	  fchmod(spinxplfd,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH | S_IWOTH);
-	  spin_created=1;
-	}
-	if (spinxplfd) {
-		flock(spinxplfd,LOCK_UN);
-	}
-	return CKR_OK;
+   if (spinxplfd != -1)
+        flock(spinxplfd,LOCK_UN);
+
+   return CKR_OK;
 }
 
 
@@ -1022,7 +989,6 @@ attach_shm()
       return CKR_FUNCTION_FAILED;
    }
    if (created == TRUE) {
-      CreateXProcLock();
       XProcLock();
       global_shm->num_publ_tok_obj = 0;
       global_shm->num_priv_tok_obj = 0;
--- a/usr/lib/pkcs11/soft_stdll/Makefile.am
+++ b/usr/lib/pkcs11/soft_stdll/Makefile.am
@@ -4,7 +4,7 @@ opencryptoki_stdll_libpkcs11_sw_la_LDFLA
 					     -lc -lpthread -lcrypto
 
 # Not all versions of automake observe libname_CFLAGS
-opencryptoki_stdll_libpkcs11_sw_la_CFLAGS = -DSPINXPL -DDEV -D_THREAD_SAFE  \
+opencryptoki_stdll_libpkcs11_sw_la_CFLAGS = -DDEV -D_THREAD_SAFE            \
 					    -DSHALLOW=0 -DSWTOK=1 -DLITE=0  \
 					    -DNOCDMF -DNOMD2 -DNODSA -DNORIPE	    \
 					    -fPIC		    \
--- a/usr/lib/pkcs11/tpm_stdll/Makefile.am
+++ b/usr/lib/pkcs11/tpm_stdll/Makefile.am
@@ -6,7 +6,7 @@ AUTOMAKE_OPTIONS = gnu
 
 #VPATH = ../common
 
-# TODO: -DLINUX and -DSPINXPL should be controlled via configure.in
+# TODO: -DLINUX should be controlled via configure.in
 
 # Not all versions of automake observe libname_CFLAGS
 opencryptoki_stdll_libpkcs11_tpm_la_CFLAGS = -DLINUX -DNOCDMF		\
--- a/usr/lib/pkcs11/tpm_stdll/h_extern.h
+++ b/usr/lib/pkcs11/tpm_stdll/h_extern.h
@@ -2059,4 +2059,5 @@ void dump_shm(const char *);
  * leaf key or the private leaf key */
 #define CKA_ENC_AUTHDATA	CKA_VENDOR_DEFINED + 0x01000001
 
+#define OCK_STDLL_LOCK_FILE	"/var/lock/LCK..opencryptoki_stdll"
 #endif
--- a/usr/lib/pkcs11/tpm_stdll/new_host.c
+++ b/usr/lib/pkcs11/tpm_stdll/new_host.c
@@ -131,7 +131,6 @@ st_Initialized()
 
 
 extern int spinxplfd;
-extern int spin_created;
 
 // ----------- SAB XXX XXX
 //
@@ -141,7 +140,6 @@ Fork_Initializer(void)
   //    initialized == FALSE; // Get the initialization to be not true
 
 	spinxplfd = -1;
-	spin_created = 0;
 
 
           // Force logout.  This cleans out the private session and list
@@ -500,7 +498,7 @@ CK_RV SC_Finalize( CK_SLOT_ID sid )
 
    detach_shm();
    // close spin lock file
-   if (spin_created)
+   if (spinxplfd != -1)
      close(spinxplfd);
    if ( token_specific.t_final != NULL) {
       token_specific.t_final();
--- a/usr/lib/pkcs11/tpm_stdll/utility.c
+++ b/usr/lib/pkcs11/tpm_stdll/utility.c
@@ -330,62 +330,32 @@ _UnlockMutex( MUTEX *mutex )
 }
 
 int spinxplfd=-1;
-int spin_created=0;
-
-extern void set_perm(int);
 
 CK_RV
-CreateXProcLock(void)
+XProcLock(void)
 {
+   /* see if it exists */
+   if (spinxplfd == -1) {
+       spinxplfd = open(OCK_STDLL_LOCK_FILE, O_CREAT|O_RDWR,
+                       S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
+      if (spinxplfd == -1)
+         OCK_LOG_DEBUG("Failed to open lock file,%s: %s\n",
+                        OCK_STDLL_LOCK_FILE, strerror(errno));
+   }
 
-	// open the file that we will do the locking on...
-	spinxplfd = open("/tmp/.pkcs11spinloc",O_CREAT|O_APPEND|O_RDWR,
-			S_IRWXU|S_IRWXG|S_IRWXO);
-	if (spinxplfd) {
-
-		set_perm(spinxplfd);
-		fchmod(spinxplfd,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH | S_IWOTH);
-		spin_created=1;
-	} else {
-		perror("XPROC CREATE file :");
-	}
-	return CKR_OK;
-}
-
-CK_RV
-DestroyXProcLock(void)
-{
-	return CKR_OK;
-}
+   if (spinxplfd != -1)
+      flock(spinxplfd,LOCK_EX);
 
-CK_RV
-XProcLock(void)
-{
-	if (!spin_created) {
-		spinxplfd = open("/tmp/.pkcs11spinloc",O_CREAT|O_APPEND|O_RDWR,
-				S_IRWXU|S_IRWXG|S_IRWXO);
-		fchmod(spinxplfd,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH | S_IWOTH);
-		spin_created=1;
-	}
-	if (spinxplfd){
-		flock(spinxplfd,LOCK_EX);
-	}
-	return CKR_OK;
+   return CKR_OK;
 }
 
 CK_RV
 XProcUnLock(void)
 {
-	if (!spin_created) {
-		spinxplfd = open("/tmp/.pkcs11spinloc",O_CREAT|O_APPEND|O_RDWR,
-				S_IRWXU|S_IRWXG|S_IRWXO);
-		fchmod(spinxplfd,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH | S_IWOTH);
-		spin_created=1;
-	}
-	if (spinxplfd) {
-		flock(spinxplfd,LOCK_UN);
-	}
-	return CKR_OK;
+   if (spinxplfd != -1)
+      flock(spinxplfd,LOCK_UN);
+
+   return CKR_OK;
 }
 
 
@@ -766,7 +736,6 @@ attach_shm()
 		// shared memory segment so we have to do
 		// this here after the segment is created
 		// to prevent a core dump
-		CreateXProcLock();
 		XProcLock();
 		global_shm->num_publ_tok_obj = 0;
 		global_shm->num_priv_tok_obj = 0;
--- a/usr/sbin/pkcscca_migrate/Makefile.am
+++ b/usr/sbin/pkcscca_migrate/Makefile.am
@@ -3,10 +3,10 @@ sbin_PROGRAMS=pkcscca_migrate
 sbin_SCRIPTS=pkcscca_migrate.sh
 
 pkcscca_migrate_SOURCES = cca_migrate.c loadsave_cca.c
-pkcscca_migrate_CFLAGS  = -DSPINXPL -DLINUX -DPROGRAM_NAME=\"$(@)\" -DNOODM -DNODAE
+pkcscca_migrate_CFLAGS  = -DLINUX -DPROGRAM_NAME=\"$(@)\" -DNOODM -DNODAE
 pkcscca_migrate_LDFLAGS = -lcrypto -ldl
 
 # Not all versions of automake observe sbinname_CFLAGS
-AM_CFLAGS = -DSPINXPL -DLINUX -DPROGRAM_NAME=\"$(@)\" -DNOODM -DNODAE
+AM_CFLAGS = -DLINUX -DPROGRAM_NAME=\"$(@)\" -DNOODM -DNODAE
 
 INCLUDES = -I. -I../../include/pkcs11
--- a/usr/sbin/pkcsconf/Makefile.am
+++ b/usr/sbin/pkcsconf/Makefile.am
@@ -3,10 +3,10 @@ sbin_PROGRAMS=pkcsconf
 pkcsconf_LDFLAGS = -lpthread -ldl
 
 # Not all versions of automake observe sbinname_CFLAGS
-pkcsconf_CFLAGS = -DSPINXPL -D_THREAD_SAFE -DDEBUG -DDEV -DAPI
+pkcsconf_CFLAGS = -D_THREAD_SAFE -DDEBUG -DDEV -DAPI
 
 # Not all versions of automake observe sbinname_CFLAGS
-AM_CFLAGS = -DSPINXPL -D_THREAD_SAFE -DDEBUG -DDEV -DAPI
+AM_CFLAGS = -D_THREAD_SAFE -DDEBUG -DDEV -DAPI
 
 pkcsconf_SOURCES = ../../lib/pkcs11/common/p11util.c pkcsconf.c
 
--- a/usr/sbin/pkcsslotd/mutex.c
+++ b/usr/sbin/pkcsslotd/mutex.c
@@ -303,17 +303,11 @@ int
 CreateXProcLock(void)
 {
   
-   xplfd = open (XPL_FILE,O_CREAT|O_RDWR,S_IRWXU|S_IRWXG|S_IRWXO);
+   xplfd = open (OCK_API_LOCK_FILE,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
    return TRUE;
 }
 
 int
-DestroyXProcLock(void)
-{
-return TRUE;
-}
-
-int
 XProcLock(void)
 {
    flock(xplfd,LOCK_EX);
@@ -326,6 +320,7 @@ XProcUnLock(void)
    flock(xplfd,LOCK_UN);
    return TRUE;
 }
+
 /*********************************************************************************
  *
  * InitializeMutexes -
@@ -467,8 +462,6 @@ int DestroyMutexes ( void ) {
 
 
   XProcUnLock();
-  DestroyXProcLock();
-
 
   return TRUE;
 
--- a/usr/sbin/pkcsslotd/pkcsslotd.h
+++ b/usr/sbin/pkcsslotd/pkcsslotd.h
@@ -537,7 +537,6 @@ int  XProcLock(void);
 int  XProcUnLock(void);
 
 int  CreateXProcLock(void);
-int  DestroyXProcLock(void);
 
 
 #endif /* _SLOTMGR_H */
--- a/usr/sbin/pkcsslotd/signal.c
+++ b/usr/sbin/pkcsslotd/signal.c
@@ -406,12 +406,6 @@ void slotdGenericSignalHandler( int Sign
 
     LogLog ( "TestSig got %s (%d; %#x)", SignalConst(Signal), Signal, Signal);
 
-    #if TEST_MUTEXES
-      /* Release the global shared memory mutex */
-      pthread_mutex_unlock(&(shmp->slt_mutex));
-      LogLog("TestSig unlocked the mutex");
-    #endif /* TEST_MUTEXES */
-
     #if TEST_COND_VARS
 
       LogLog("Locking the CV Mutex");
--- a/usr/sbin/pkcsslotd/slotmgr.c
+++ b/usr/sbin/pkcsslotd/slotmgr.c
@@ -525,13 +525,6 @@ printf("Start garbage \n");
 #endif
 
 
-
-   #if TEST_MUTEXES
-     /* Get the global shared memory mutex */
-     LogLog ("Grabbing the shared memory mutex");
-     pthread_mutex_lock(&(shmp->slt_mutex));
-   #endif /* TEST_MUTEXES */
-
    #if TEST_COND_VARS
 
      DumpSharedMemory();
