if (!symWrapKeysLock) nss_InitLock(&symWrapKeysLock, nssILockOther);
ssl_InitSymWrapKeysLock();
getWrappingKey( sslSocket *       ss,		PK11SlotInfo *    masterSecretSlot,		SSL3KEAType       exchKeyType,                CK_MECHANISM_TYPE masterWrapMech,	        void *            pwArg){    CERTCertificate *        svrCert;    SECKEYPrivateKey *       svrPrivKey;    SECKEYPublicKey *        svrPubKey             = NULL;    PK11SymKey *             unwrappedWrappingKey  = NULL;    PK11SymKey **            pSymWrapKey;    CK_MECHANISM_TYPE        asymWrapMechanism = CKM_INVALID_MECHANISM;    int                      length;    int                      symWrapMechIndex;    SECStatus                rv;    SECItem                  wrappedKey;    SSLWrappedSymWrappingKey wswk;    svrPrivKey  = ss->serverCerts[exchKeyType].serverKey;    PORT_Assert(svrPrivKey != NULL);    if (!svrPrivKey) {    	return NULL;	/* why are we here?!? */    }    symWrapMechIndex = ssl_FindIndexByWrapMechanism(masterWrapMech);    PORT_Assert(symWrapMechIndex >= 0);    if (symWrapMechIndex < 0)    	return NULL;	/* invalid masterWrapMech. */    pSymWrapKey = &symWrapKeys[symWrapMechIndex].symWrapKey[exchKeyType];    /* atomically initialize the lock */    if (!symWrapKeysLock)	nss_InitLock(&symWrapKeysLock, nssILockOther);    PZ_Lock(symWrapKeysLock);    unwrappedWrappingKey = *pSymWrapKey;    if (unwrappedWrappingKey != NULL) {	if (PK11_VerifyKeyOK(unwrappedWrappingKey)) {	    unwrappedWrappingKey = PK11_ReferenceSymKey(unwrappedWrappingKey);	    goto done;	}	/* slot series has changed, so this key is no good any more. */	PK11_FreeSymKey(unwrappedWrappingKey);	*pSymWrapKey = unwrappedWrappingKey = NULL;    }    /* Try to get wrapped SymWrapping key out of the (disk) cache. */    /* Following call fills in wswk on success. */    if (ssl_GetWrappingKey(symWrapMechIndex, exchKeyType, &wswk)) {    	/* found the wrapped sym wrapping key on disk. */	unwrappedWrappingKey =	    ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, exchKeyType,                                     masterWrapMech, pwArg);	if (unwrappedWrappingKey) {	    goto install;	}    }    if (!masterSecretSlot) 	/* caller doesn't want to create a new one. */    	goto loser;    length = PK11_GetBestKeyLength(masterSecretSlot, masterWrapMech);    /* Zero length means fixed key length algorithm, or error.     * It's ambiguous.     */    unwrappedWrappingKey = PK11_KeyGen(masterSecretSlot, masterWrapMech, NULL,                                       length, pwArg);    if (!unwrappedWrappingKey) {    	goto loser;    }    /* Prepare the buffer to receive the wrappedWrappingKey,     * the symmetric wrapping key wrapped using the server's pub key.     */    PORT_Memset(&wswk, 0, sizeof wswk);	/* eliminate UMRs. */    svrCert         = ss->serverCerts[exchKeyType].serverCert;    svrPubKey       = CERT_ExtractPublicKey(svrCert);    if (svrPubKey == NULL) {	/* CERT_ExtractPublicKey doesn't set error code */	PORT_SetError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);    	goto loser;    }    wrappedKey.type = siBuffer;    wrappedKey.len  = SECKEY_PublicKeyStrength(svrPubKey);    wrappedKey.data = wswk.wrappedSymmetricWrappingkey;    PORT_Assert(wrappedKey.len <= sizeof wswk.wrappedSymmetricWrappingkey);    if (wrappedKey.len > sizeof wswk.wrappedSymmetricWrappingkey)    	goto loser;    /* wrap symmetric wrapping key in server's public key. */    switch (exchKeyType) {    PK11SymKey *      Ks;    PK11SlotInfo *    fSlot;    SECItem           param;    case kt_fortezza:	/* get the slot that the fortezza server private key is in. */	fSlot = PK11_GetSlotFromPrivateKey(svrPrivKey);	if (fSlot == NULL) {	    SET_ERROR_CODE	    goto loser;	}	/* Look up the Token Fixed Key */	Ks = PK11_FindFixedKey(fSlot, CKM_SKIPJACK_CBC64, NULL, pwArg);	PK11_FreeSlot(fSlot);	if (Ks == NULL) {	    SET_ERROR_CODE	    goto loser;	}	/* wrap symmetricWrapping key with the local Ks */	param.type = siBuffer;    	param.data = wswk.wrapIV;    	param.len  = sizeof wswk.wrapIV;	rv = PK11_WrapSymKey(CKM_SKIPJACK_CBC64, &param, Ks,	                     unwrappedWrappingKey, &wrappedKey);	wswk.wrapIVLen = param.len;	PK11_FreeSymKey(Ks);	asymWrapMechanism = CKM_SKIPJACK_CBC64;	break;    case kt_rsa:	asymWrapMechanism = CKM_RSA_PKCS;	rv = PK11_PubWrapSymKey(asymWrapMechanism, svrPubKey,	                        unwrappedWrappingKey, &wrappedKey);	break;    default:	rv = SECFailure;	break;    }    if (rv != SECSuccess) {	ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);	goto loser;    }    PORT_Assert(asymWrapMechanism != CKM_INVALID_MECHANISM);    wswk.symWrapMechanism  = masterWrapMech;    wswk.symWrapMechIndex  = symWrapMechIndex;    wswk.asymWrapMechanism = asymWrapMechanism;    wswk.exchKeyType       = exchKeyType;    wswk.wrappedSymKeyLen  = wrappedKey.len;    /* put it on disk. */    /* If the wrapping key for this KEA type has already been set,      * then abandon the value we just computed and      * use the one we got from the disk.     */    if (ssl_SetWrappingKey(&wswk)) {    	/* somebody beat us to it.  The original contents of our wswk	 * has been replaced with the content on disk.  Now, discard	 * the key we just created and unwrap this new one.	 */    	PK11_FreeSymKey(unwrappedWrappingKey);	unwrappedWrappingKey =	    ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, exchKeyType,                                     masterWrapMech, pwArg);    }install:    if (unwrappedWrappingKey) {	*pSymWrapKey = PK11_ReferenceSymKey(unwrappedWrappingKey);    }loser:done:    if (svrPubKey) {    	SECKEY_DestroyPublicKey(svrPubKey);	svrPubKey = NULL;    }    PZ_Unlock(symWrapKeysLock);    return unwrappedWrappingKey;}