Lock API against concurrent use from other threads

Backported version of the original opencryptoki commit

    commit 3756138fc3427e1d53010780d0af1c44bd05b9e2
    Author: Ingo Franzki <ifranzki@linux.ibm.com>
    Date:   Tue Oct 8 10:26:21 2019 +0200

    API: Lock API against concurrent use from other threads
    
    Use a recursive mutex in the API-slot to lock the API calls
    against concurrent use by other threads of the same process.
    
    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
 usr/include/pkcs11/apictl.h        |    1 
 usr/lib/pkcs11/api/api_interface.c |  247 +++++++++++++++++++++++++++++++++++++
 usr/lib/pkcs11/api/apiproto.h      |    7 -
 usr/lib/pkcs11/api/apiutil.c       |   76 +++++++++--
 4 files changed, 316 insertions(+), 15 deletions(-)

--- a/usr/include/pkcs11/apictl.h
+++ b/usr/include/pkcs11/apictl.h
@@ -300,6 +300,7 @@
 #include <local_types.h>
 #include <stdll.h>
 #include <slotmgr.h>
+#include <pthread.h>
 
 #ifndef _APILOCAL_H
 #define _APILOCAL_H
--- a/usr/lib/pkcs11/api/api_interface.c
+++ b/usr/lib/pkcs11/api/api_interface.c
@@ -434,6 +434,8 @@ CK_RV C_CloseSession(CK_SESSION_HANDLE h
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_CloseSession) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_CloseSession(&rSession);
 		TRACE_DEVEL("Called STDLL rv = 0x%lx\n", rv);
@@ -450,6 +452,8 @@ CK_RV C_CloseSession(CK_SESSION_HANDLE h
 			decr_sess_counts(rSession.slotID);
 		} else
 			TRACE_DEVEL("fcn->ST_CloseSession failed:0x%lx\n", rv);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
 		rv = CKR_FUNCTION_NOT_SUPPORTED;
@@ -513,9 +517,13 @@ C_CopyObject(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_CopyObject) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_CopyObject(&rSession, hObject, pTemplate, ulCount,
 					phNewObject);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
 		rv = CKR_FUNCTION_NOT_SUPPORTED;
@@ -583,9 +591,13 @@ C_CreateObject(CK_SESSION_HANDLE hSessio
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_CreateObject) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_CreateObject(&rSession, pTemplate, ulCount,
 					  phObject);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_CreateObject returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -641,9 +653,13 @@ C_Decrypt(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_Decrypt) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_Decrypt(&rSession, pEncryptedData,
 				     ulEncryptedDataLen, pData, pulDataLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_Decrypt returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -697,10 +713,14 @@ C_DecryptDigestUpdate(CK_SESSION_HANDLE
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_DecryptDigestUpdate) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_DecryptDigestUpdate(&rSession, pEncryptedPart,
 						 ulEncryptedPartLen, pPart,
 						 pulPartLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_DecryptDigestUpdate returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -758,8 +778,12 @@ C_DecryptFinal(CK_SESSION_HANDLE hSessio
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_DecryptFinal) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_DecryptFinal(&rSession, pLastPart, pulLastPartLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_DecryptFinal returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -812,8 +836,12 @@ C_DecryptInit(CK_SESSION_HANDLE hSession
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_DecryptInit) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_DecryptInit(&rSession, pMechanism, hKey);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_DecryptInit returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -868,10 +896,14 @@ C_DecryptUpdate(CK_SESSION_HANDLE hSessi
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_DecryptUpdate) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_DecryptUpdate(&rSession, pEncryptedPart,
 					   ulEncryptedPartLen, pPart,
 					   pulPartLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_DecryptUpdate:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -922,10 +954,14 @@ C_DecryptVerifyUpdate(CK_SESSION_HANDLE
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_DecryptVerifyUpdate) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_DecryptVerifyUpdate(&rSession, pEncryptedPart,
 						 ulEncryptedPartLen, pPart,
 						 pulPartLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_DecryptVerifyUpdate returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -988,9 +1024,13 @@ C_DeriveKey(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_DeriveKey) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_DeriveKey(&rSession, pMechanism, hBaseKey,
 				       pTemplate, ulAttributeCount, phKey);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_DeriveKey returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1038,8 +1078,12 @@ CK_RV C_DestroyObject(CK_SESSION_HANDLE
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_DestroyObject) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_DestroyObject(&rSession, hObject);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_DestroyObject returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1088,9 +1132,13 @@ C_Digest(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_Digest) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_Digest(&rSession, pData, ulDataLen, pDigest,
 				    pulDigestLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_Digest:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1144,10 +1192,14 @@ C_DigestEncryptUpdate(CK_SESSION_HANDLE
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_DigestEncryptUpdate) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_DigestEncryptUpdate(&rSession, pPart, ulPartLen,
 						 pEncryptedPart,
 						 pulEncryptedPartLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_DigestEncryptUpdate returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1195,8 +1247,12 @@ C_DigestFinal(CK_SESSION_HANDLE hSession
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_DigestFinal) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_DigestFinal(&rSession, pDigest, pulDigestLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_DigestFinal returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1244,8 +1300,12 @@ CK_RV C_DigestInit(CK_SESSION_HANDLE hSe
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_DigestInit) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_DigestInit(&rSession, pMechanism);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_DigestInit returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1287,8 +1347,12 @@ CK_RV C_DigestKey(CK_SESSION_HANDLE hSes
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_DigestKey) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_DigestKey(&rSession, hKey);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEBUG("fcn->ST_DigestKey returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1332,8 +1396,12 @@ C_DigestUpdate(CK_SESSION_HANDLE hSessio
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_DigestUpdate) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_DigestUpdate(&rSession, pPart, ulPartLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_DigestUpdate returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1384,9 +1452,13 @@ C_Encrypt(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_Encrypt) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_Encrypt(&rSession, pData, ulDataLen,
 				     pEncryptedData, pulEncryptedDataLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_Encrypt returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1436,8 +1508,12 @@ C_EncryptFinal(CK_SESSION_HANDLE hSessio
 	}
 	if (fcn->ST_EncryptFinal) {
 		// Map the Session to the slot session
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		rv = fcn->ST_EncryptFinal(&rSession, pLastEncryptedPart,
 					  pulLastEncryptedPartLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_EncryptFinal: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1486,8 +1562,12 @@ C_EncryptInit(CK_SESSION_HANDLE hSession
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_EncryptInit) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_EncryptInit(&rSession, pMechanism, hKey);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_INFO("fcn->ST_EncryptInit returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1539,9 +1619,13 @@ C_EncryptUpdate(CK_SESSION_HANDLE hSessi
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_EncryptUpdate) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_EncryptUpdate(&rSession, pPart, ulPartLen,
 					   pEncryptedPart, pulEncryptedPartLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_EncryptUpdate returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1619,6 +1703,8 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
 	//close the lock file descriptor here to avoid memory leak
 	XProcClose();
 
+	DestroyAPILock();
+
 	return CKR_OK;
 }				// end of C_Finalize
 
@@ -1666,9 +1752,13 @@ C_FindObjects(CK_SESSION_HANDLE hSession
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_FindObjects) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_FindObjects(&rSession, phObject, ulMaxObjectCount,
 					 pulObjectCount);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_FindObjects returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1716,8 +1806,12 @@ CK_RV C_FindObjectsFinal(CK_SESSION_HAND
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_FindObjectsFinal) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_FindObjectsFinal(&rSession);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_FindObjectsFinal returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1769,8 +1863,12 @@ C_FindObjectsInit(CK_SESSION_HANDLE hSes
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_FindObjectsInit) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_FindObjectsInit(&rSession, pTemplate, ulCount);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_FindObjectsInit returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1825,9 +1923,13 @@ C_GenerateKey(CK_SESSION_HANDLE hSession
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_GenerateKey) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_GenerateKey(&rSession, pMechanism, pTemplate,
 					 ulCount, phKey);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_GenerateKey returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1890,6 +1992,8 @@ C_GenerateKeyPair(CK_SESSION_HANDLE hSes
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_GenerateKeyPair) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_GenerateKeyPair(&rSession, pMechanism,
 					     pPublicKeyTemplate,
@@ -1897,6 +2001,8 @@ C_GenerateKeyPair(CK_SESSION_HANDLE hSes
 					     pPrivateKeyTemplate,
 					     ulPrivateKeyAttributeCount,
 					     phPublicKey, phPrivateKey);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_GenerateKeyPair returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -1944,8 +2050,12 @@ C_GenerateRandom(CK_SESSION_HANDLE hSess
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_GenerateRandom) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_GenerateRandom(&rSession, RandomData, ulRandomLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_GenerateRandom returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -2004,9 +2114,13 @@ C_GetAttributeValue(CK_SESSION_HANDLE hS
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_GetAttributeValue) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_GetAttributeValue(&rSession, hObject, pTemplate,
 					       ulCount);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_GetAttributeValue returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -2190,7 +2304,11 @@ C_GetMechanismInfo(CK_SLOT_ID slotID,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_GetMechanismInfo) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		rv = fcn->ST_GetMechanismInfo(slotID, type, pInfo);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_GetMechanismInfo returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -2248,7 +2366,11 @@ C_GetMechanismList(CK_SLOT_ID slotID,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_GetMechanismList) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		rv = fcn->ST_GetMechanismList(slotID, pMechanismList, pulCount);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_GetMechanismList returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -2312,8 +2434,12 @@ C_GetObjectSize(CK_SESSION_HANDLE hSessi
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_GetObjectSize) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_GetObjectSize(&rSession, hObject, pulSize);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_GetObjectSize retuned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -2364,9 +2490,13 @@ C_GetOperationState(CK_SESSION_HANDLE hS
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_GetOperationState) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_GetOperationState(&rSession, pOperationState,
 					       pulOperationStateLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_GetOperationState returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -2418,8 +2548,12 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_GetSessionInfo) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_GetSessionInfo(&rSession, pInfo);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 
 		TRACE_DEVEL("fcn->ST_GetSessionInfo returned: 0x%lx\n", rv);
 		TRACE_DEVEL("Slot %lu  State %lx  Flags %lx DevErr %lx\n",
@@ -2739,10 +2873,14 @@ CK_RV C_GetTokenInfo(CK_SLOT_ID slotID,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_GetTokenInfo) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		rv = fcn->ST_GetTokenInfo(slotID, pInfo);
 		if (rv == CKR_OK) {
 			get_sess_count(slotID, &(pInfo->ulSessionCount));
 		}
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("rv %lu CK_TOKEN_INFO Flags %lx\n", rv, pInfo->flags);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -2892,6 +3030,14 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
 		;
 	}
 
+	/* Create the API lock. */
+	if (CreateAPILock()  != CKR_OK) {
+		free((void *)Anchor);
+		Anchor = NULL;
+		TRACE_ERROR("Create API Lock failed.\n");
+		return CKR_FUNCTION_FAILED;
+	}
+
 	// Create the shared memory lock.
 	if (CreateXProcLock() != CKR_OK) {
 		free((void *)Anchor);
@@ -3019,8 +3165,12 @@ CK_RV C_InitPIN(CK_SESSION_HANDLE hSessi
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_InitPIN) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_InitPIN(&rSession, pPin, ulPinLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_InitPIN returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3088,7 +3238,11 @@ C_InitToken(CK_SLOT_ID slotID,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_InitToken) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		rv = fcn->ST_InitToken(slotID, pPin, ulPinLen, pLabel);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_InitToken returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3145,8 +3299,12 @@ C_Login(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_Login) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_Login(&rSession, userType, pPin, ulPinLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_Login returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3194,8 +3352,12 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSessio
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_Logout) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_Logout(&rSession);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_Logout returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3266,6 +3428,10 @@ C_OpenSession(CK_SLOT_ID slotID,
 	}
 
 	if (fcn->ST_OpenSession) {
+		if (APILock() != CKR_OK) {
+			free(apiSessp);
+			return CKR_CANT_LOCK;
+		}
 		rv = fcn->ST_OpenSession(slotID, flags, &(apiSessp->sessionh));
 		TRACE_DEVEL("fcn->ST_OpenSession returned: 0x%lx\n", rv);
 
@@ -3282,6 +3448,7 @@ C_OpenSession(CK_SLOT_ID slotID,
 				 * and return failure */
 				fcn->ST_CloseSession(apiSessp);
 				free(apiSessp);
+				APIUnLock();
 				rv = CKR_HOST_MEMORY;
 				goto done;
 			}
@@ -3300,6 +3467,10 @@ C_OpenSession(CK_SLOT_ID slotID,
 		} else {
 			free(apiSessp);
 		}
+		if (APIUnLock() != CKR_OK) {
+			free(apiSessp);
+			return CKR_CANT_LOCK;
+		}
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
 		free(apiSessp);
@@ -3347,8 +3518,12 @@ C_SeedRandom(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_SeedRandom) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_SeedRandom(&rSession, pSeed, ulSeedLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_SeedRandom returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3409,9 +3584,13 @@ C_SetAttributeValue(CK_SESSION_HANDLE hS
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_SetAttributeValue) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_SetAttributeValue(&rSession, hObject, pTemplate,
 					       ulCount);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_SetAttributeValue returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3463,11 +3642,15 @@ C_SetOperationState(CK_SESSION_HANDLE hS
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_SetOperationState) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_SetOperationState(&rSession, pOperationState,
 					       ulOperationStateLen,
 					       hEncryptionKey,
 					       hAuthenticationKey);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_SetOperationState returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3523,9 +3706,13 @@ C_SetPIN(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_SetPIN) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_SetPIN(&rSession, pOldPin, ulOldLen, pNewPin,
 				    ulNewLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_SetPIN returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3579,9 +3766,13 @@ C_Sign(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_Sign) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_Sign(&rSession, pData, ulDataLen, pSignature,
 				  pulSignatureLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_Sign returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3632,10 +3823,14 @@ C_SignEncryptUpdate(CK_SESSION_HANDLE hS
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_SignEncryptUpdate) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_SignEncryptUpdate(&rSession, pPart, ulPartLen,
 					       pEncryptedPart,
 					       pulEncryptedPartLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_SignEncryptUpdate return: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3690,8 +3885,12 @@ C_SignFinal(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_SignFinal) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_SignFinal(&rSession, pSignature, pulSignatureLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_SignFinal returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3746,8 +3945,12 @@ C_SignInit(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_SignInit) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_SignInit(&rSession, pMechanism, hKey);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_SignInit returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3797,9 +4000,13 @@ C_SignRecover(CK_SESSION_HANDLE hSession
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_SignRecover) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_SignRecover(&rSession, pData, ulDataLen,
 					 pSignature, pulSignatureLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_SignRecover returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3850,8 +4057,12 @@ C_SignRecoverInit(CK_SESSION_HANDLE hSes
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_SignRecoverInit) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_SignRecoverInit(&rSession, pMechanism, hKey);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_SignRecoverInit returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3900,8 +4111,12 @@ C_SignUpdate(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_SignUpdate) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_SignUpdate(&rSession, pPart, ulPartLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_SignUpdate returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -3964,10 +4179,14 @@ C_UnwrapKey(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_UnwrapKey) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_UnwrapKey(&rSession, pMechanism, hUnwrappingKey,
 				       pWrappedKey, ulWrappedKeyLen, pTemplate,
 				       ulAttributeCount, phKey);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_UnwrapKey returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -4020,9 +4239,13 @@ C_Verify(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_Verify) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_Verify(&rSession, pData, ulDataLen, pSignature,
 				    ulSignatureLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_Verify returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -4070,8 +4293,12 @@ C_VerifyFinal(CK_SESSION_HANDLE hSession
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_VerifyFinal) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_VerifyFinal(&rSession, pSignature, ulSignatureLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_VerifyFinal returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -4121,8 +4348,12 @@ C_VerifyInit(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_VerifyInit) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_VerifyInit(&rSession, pMechanism, hKey);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_VerifyInit returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -4173,9 +4404,13 @@ C_VerifyRecover(CK_SESSION_HANDLE hSessi
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_VerifyRecover) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_VerifyRecover(&rSession, pSignature,
 					   ulSignatureLen, pData, pulDataLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_VerifyRecover returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -4223,8 +4458,12 @@ C_VerifyRecoverInit(CK_SESSION_HANDLE hS
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_VerifyRecoverInit) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_VerifyRecoverInit(&rSession, pMechanism, hKey);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_VerifyRecoverInit returned:0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -4268,8 +4507,12 @@ C_VerifyUpdate(CK_SESSION_HANDLE hSessio
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_VerifyUpdate) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_VerifyUpdate(&rSession, pPart, ulPartLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_VerifyUpdate returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
@@ -4459,9 +4702,13 @@ C_WrapKey(CK_SESSION_HANDLE hSession,
 		return CKR_TOKEN_NOT_PRESENT;
 	}
 	if (fcn->ST_WrapKey) {
+		if (APILock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		// Map the Session to the slot session
 		rv = fcn->ST_WrapKey(&rSession, pMechanism, hWrappingKey, hKey,
 				     pWrappedKey, pulWrappedKeyLen);
+		if (APIUnLock() != CKR_OK)
+			return CKR_CANT_LOCK;
 		TRACE_DEVEL("fcn->ST_WrapKey returned: 0x%lx\n", rv);
 	} else {
 		TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
--- a/usr/lib/pkcs11/api/apiproto.h
+++ b/usr/lib/pkcs11/api/apiproto.h
@@ -322,6 +322,11 @@ CK_RV XProcLock(void);
 CK_RV XProcUnLock(void);
 CK_RV XProcClose(void);
 
+CK_RV CreateAPILock();
+CK_RV DestroyAPILock();
+CK_RV APILock();
+CK_RV APIUnLock();
+
 void _init(void);
 void get_sess_count(CK_SLOT_ID, CK_ULONG *);
 void incr_sess_counts(CK_SLOT_ID);
@@ -336,7 +341,7 @@ void CK_Info_From_Internal (CK_INFO_PTR
 
 int sessions_exist(CK_SLOT_ID);
 
-void CloseAllSessions(CK_SLOT_ID slot_id);
+CK_RV CloseAllSessions(CK_SLOT_ID slot_id);
 int init_socket_data();
 
 #define OCK_SYSLOG(priority, fmt, ...) \
--- a/usr/lib/pkcs11/api/apiutil.c
+++ b/usr/lib/pkcs11/api/apiutil.c
@@ -318,6 +318,8 @@
 
 static int xplfd = -1;
 
+static pthread_mutex_t api_mutex; /* lock API calls against other threads */
+
 #include <libgen.h>
 
 #define LIBLOCATION  LIB_PATH
@@ -379,26 +381,66 @@ CK_RV XProcClose(void)
 	return CKR_OK;
 }
 
+CK_RV CreateAPILock()
+{
+	pthread_mutexattr_t attr;
+
+	if (pthread_mutexattr_init(&attr)) {
+		TRACE_ERROR("Mutex attribute init failed.\n");
+		return CKR_FUNCTION_FAILED;
+	}
+	if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) {
+		TRACE_ERROR("Mutex attribute set failed.\n");
+		return CKR_FUNCTION_FAILED;
+	}
+	if (pthread_mutex_init(&api_mutex, &attr)) {
+		TRACE_ERROR("Mutex init failed.\n");
+		return CKR_FUNCTION_FAILED;
+	}
+
+	return CKR_OK;
+}
+
+CK_RV DestroyAPILock()
+{
+	if (pthread_mutex_destroy(&api_mutex))
+		return CKR_FUNCTION_FAILED;
+
+	return CKR_OK;
+}
+
+CK_RV APILock()
+{
+	if (pthread_mutex_lock(&api_mutex)) {
+		TRACE_ERROR("APILock failed.\n");
+		return CKR_CANT_LOCK;
+	}
+
+	return CKR_OK;
+}
+
+CK_RV APIUnLock()
+{
+	if (pthread_mutex_unlock(&api_mutex)) {
+		TRACE_ERROR("APIUnLock failed.\n");
+		return CKR_CANT_LOCK;
+	}
+
+	return CKR_OK;
+}
+
 unsigned long AddToSessionList(ST_SESSION_T * pSess)
 {
 	unsigned long handle;
 
-	pthread_mutex_lock(&(Anchor->SessListMutex));
-
 	handle = bt_node_add(&(Anchor->sess_btree), pSess);
 
-	pthread_mutex_unlock(&(Anchor->SessListMutex));
-
 	return handle;
 }
 
 void RemoveFromSessionList(CK_SESSION_HANDLE handle)
 {
-	pthread_mutex_lock(&(Anchor->SessListMutex));
-
 	bt_node_free(&(Anchor->sess_btree), handle, free);
-
-	pthread_mutex_unlock(&(Anchor->SessListMutex));
 }
 
 /* CloseMe
@@ -433,9 +475,10 @@ void CloseMe(void *node_value, unsigned
  * @slot_id and if it matches, will close the session. Once all the nodes are closed, we check
  * to see if the tree is empty and if so, destroy it
  */
-void CloseAllSessions(CK_SLOT_ID slot_id)
+CK_RV CloseAllSessions(CK_SLOT_ID slot_id)
 {
-	pthread_mutex_lock(&(Anchor->SessListMutex));
+	if (APILock() != CKR_OK)
+		return CKR_CANT_LOCK;
 
 	/* for every node in the API-level session tree, call CloseMe on it */
 	bt_for_each_node(&(Anchor->sess_btree), CloseMe, (void *)&slot_id);
@@ -443,14 +486,18 @@ void CloseAllSessions(CK_SLOT_ID slot_id
 	if (bt_is_empty(&(Anchor->sess_btree)))
 		bt_destroy(&(Anchor->sess_btree), NULL);
 
-	pthread_mutex_unlock(&(Anchor->SessListMutex));
+	if (APIUnLock() != CKR_OK)
+		return CKR_CANT_LOCK;
+
+	return CKR_OK;
 }
 
 int Valid_Session(CK_SESSION_HANDLE handle, ST_SESSION_T * rSession)
 {
 	ST_SESSION_T *tmp;
 
-	pthread_mutex_lock(&(Anchor->SessListMutex));
+	if (APILock() != CKR_OK)
+		return CKR_CANT_LOCK;
 
 	tmp = bt_get_node_value(&(Anchor->sess_btree), handle);
 	if (tmp) {
@@ -458,7 +505,8 @@ int Valid_Session(CK_SESSION_HANDLE hand
 		rSession->sessionh = tmp->sessionh;
 	}
 
-	pthread_mutex_unlock(&(Anchor->SessListMutex));
+	if (APIUnLock() != CKR_OK)
+		return CKR_CANT_LOCK;
 
 	return (tmp ? TRUE : FALSE);
 }
@@ -850,7 +898,6 @@ API_Slot_t *sltp;
 	sltp->dlop_p = NULL;
 	sltp->pSTfini = NULL;
 	sltp->pSTcloseall = NULL;
-
 }
 
 int DL_Load_and_Init(API_Slot_t *sltp, CK_SLOT_ID slotID)
@@ -907,6 +954,7 @@ int DL_Load_and_Init(API_Slot_t *sltp, C
 		DL_Unload(sltp);
 		return FALSE;
 	}
+
 	// Returns true or false
 	rv = pSTinit(&(sltp->FcnList), slotID, sinfp->confname, trace);
 	TRACE_DEBUG("return from STDDLL Init = %lx\n", rv);
