Blob Blame History Raw
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