PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
ssl2_CreateSessionCypher(sslSocket *ss, sslSessionID *sid, PRBool isClient){    SECItem         * rk = NULL;    SECItem         * wk = NULL;    SECItem *         param;    SECStatus         rv;    int               cipherType  = sid->u.ssl2.cipherType;    PK11SlotInfo *    slot        = NULL;    CK_MECHANISM_TYPE mechanism;    SECItem           readKey;    SECItem           writeKey;    void *readcx = 0;    void *writecx = 0;    readKey.data = 0;    writeKey.data = 0;    PORT_Assert( ssl_Have1stHandshakeLock(ss) );    if((ss->sec.ci.sid == 0))    	goto sec_loser;	/* don't crash if asserts are off */    /* Trying to cut down on all these switch statements that should be tables.     * So, test cipherType once, here, and then use tables below.      */    switch (cipherType) {    case SSL_CK_RC4_128_EXPORT40_WITH_MD5:    case SSL_CK_RC4_128_WITH_MD5:    case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:    case SSL_CK_RC2_128_CBC_WITH_MD5:    case SSL_CK_DES_64_CBC_WITH_MD5:    case SSL_CK_DES_192_EDE3_CBC_WITH_MD5:	break;    default:	SSL_DBG(("%d: SSL[%d]: ssl2_CreateSessionCypher: unknown cipher=%d",		 SSL_GETPID(), ss->fd, cipherType));	PORT_SetError(isClient ? SSL_ERROR_BAD_SERVER : SSL_ERROR_BAD_CLIENT);	goto sec_loser;    }     rk = isClient ? &readKey  : &writeKey;    wk = isClient ? &writeKey : &readKey;    /* Produce the keys for this session */    rv = ssl2_ProduceKeys(ss, &readKey, &writeKey, &sid->u.ssl2.masterKey,		     ss->sec.ci.clientChallenge, ss->sec.ci.connectionID,		     cipherType);    if (rv != SECSuccess) 	goto loser;    PRINT_BUF(7, (ss, "Session read-key: ", rk->data, rk->len));    PRINT_BUF(7, (ss, "Session write-key: ", wk->data, wk->len));    PORT_Memcpy(ss->sec.ci.readKey, readKey.data, readKey.len);    PORT_Memcpy(ss->sec.ci.writeKey, writeKey.data, writeKey.len);    ss->sec.ci.keySize = readKey.len;    /* Setup the MAC */    rv = ssl2_CreateMAC(&ss->sec, rk, wk, cipherType);    if (rv != SECSuccess)     	goto loser;    /* First create the session key object */    SSL_TRC(3, ("%d: SSL[%d]: using %s", SSL_GETPID(), ss->fd,	    ssl_cipherName[cipherType]));    mechanism  = ssl_Specs[cipherType].mechanism;    /* set destructer before we call loser... */    ss->sec.destroy = (void (*)(void*, PRBool)) PK11_DestroyContext;    slot = PK11_GetBestSlot(mechanism, ss->pkcs11PinArg);    if (slot == NULL)	goto loser;    param = PK11_ParamFromIV(mechanism, &sid->u.ssl2.cipherArg);    if (param == NULL)	goto loser;    readcx = PK11_CreateContextByRawKey(slot, mechanism, PK11_OriginUnwrap,					CKA_DECRYPT, rk, param,					ss->pkcs11PinArg);    SECITEM_FreeItem(param, PR_TRUE);    if (readcx == NULL)	goto loser;    /* build the client context */    param = PK11_ParamFromIV(mechanism, &sid->u.ssl2.cipherArg);    if (param == NULL)	goto loser;    writecx = PK11_CreateContextByRawKey(slot, mechanism, PK11_OriginUnwrap,					 CKA_ENCRYPT, wk, param,					 ss->pkcs11PinArg);    SECITEM_FreeItem(param,PR_TRUE);    if (writecx == NULL)	goto loser;    PK11_FreeSlot(slot);    rv = SECSuccess;    ss->sec.enc           = (SSLCipher) PK11_CipherOp;    ss->sec.dec           = (SSLCipher) PK11_CipherOp;    ss->sec.readcx        = (void *) readcx;    ss->sec.writecx       = (void *) writecx;    ss->sec.blockSize     = ssl_Specs[cipherType].blockSize;    ss->sec.blockShift    = ssl_Specs[cipherType].blockShift;    ss->sec.cipherType    = sid->u.ssl2.cipherType;    ss->sec.keyBits       = sid->u.ssl2.keyBits;    ss->sec.secretKeyBits = sid->u.ssl2.secretKeyBits;    goto done;  loser:    if (ss->sec.destroy) {	if (readcx)  (*ss->sec.destroy)(readcx, PR_TRUE);	if (writecx) (*ss->sec.destroy)(writecx, PR_TRUE);    }    ss->sec.destroy = NULL;    if (slot) PK11_FreeSlot(slot);  sec_loser:    rv = SECFailure;  done:    if (rk) {	SECITEM_ZfreeItem(rk, PR_FALSE);    }    if (wk) {	SECITEM_ZfreeItem(wk, PR_FALSE);    }    return rv;}