diff --git a/lib/pk11wrap/pk11cxt.c b/lib/pk11wrap/pk11cxt.c
--- a/lib/pk11wrap/pk11cxt.c
+++ b/lib/pk11wrap/pk11cxt.c
@@ -52,16 +52,37 @@ PK11_ExitContextMonitor(PK11Context *cx)
if ((cx->ownSession) && (cx->slot->isThreadSafe)) {
/* Should this use monitors instead? */
PZ_Unlock(cx->sessionLock);
} else {
PK11_ExitSlotMonitor(cx->slot);
}
}
+static void
+pk11_releaseSlotMonitor(PK11Context *cx)
+{
+ if ((cx->ownSession) && (cx->slot->isThreadSafe)) {
+ return;
+ } else {
+ PK11_ExitSlotMonitor(cx->slot);
+ }
+}
+
+static void
+pk11_reacquireSlotMonitor(PK11Context *cx)
+{
+ if ((cx->ownSession) && (cx->slot->isThreadSafe)) {
+ return;
+ } else {
+ PK11_EnterSlotMonitor(cx->slot);
+ }
+}
+
+
/*
* Free up a Cipher Context
*/
void
PK11_DestroyContext(PK11Context *context, PRBool freeit)
{
pk11_CloseSession(context->slot, context->session, context->ownSession);
/* initialize the critical fields of the context */
@@ -166,27 +187,33 @@ pk11_contextInitMessage(PK11Context *con
context->simulate_message = PR_FALSE;
/* check that we can do the Message interface. We need to check
* for either 1) are we using a PKCS #11 v3 interface and 2) is the
* Message flag set on the mechanism. If either is false we simulate
* the message interface for the Encrypt and Decrypt cases using the
* PKCS #11 V2 interface.
* Sign and verify do not have V2 interfaces, so we go ahead and fail
* if those cases */
+ /* release the monitor before calling DoesMechanism */
+ pk11_releaseSlotMonitor(context);
if ((version.major >= 3) &&
PK11_DoesMechanismFlag(slot, (mech)->mechanism, flags)) {
+ /* restore it before calling the init function */
+ pk11_reacquireSlotMonitor(context);
crv = (*initFunc)((context)->session, (mech), (key)->objectID);
if ((crv == CKR_FUNCTION_NOT_SUPPORTED) ||
(crv == CKR_MECHANISM_INVALID)) {
/* we have a 3.0 interface, and the flag was set (or ignored)
* but the implementation was not there, use the V2 interface */
crv = (scrv);
context->simulate_message = PR_TRUE;
}
} else {
+ /* restore the monitor */
+ pk11_reacquireSlotMonitor(context);
crv = (scrv);
context->simulate_message = PR_TRUE;
}
return crv;
}
/*
* Context initialization. Used by all flavors of CreateContext