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