Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Functions | Variables
ssl3con.c File Reference
#include "nssrenam.h"
#include "cert.h"
#include "ssl.h"
#include "cryptohi.h"
#include "keyhi.h"
#include "secder.h"
#include "secitem.h"
#include "sslimpl.h"
#include "sslproto.h"
#include "sslerr.h"
#include "prtime.h"
#include "prinrval.h"
#include "prerror.h"
#include "pratom.h"
#include "prthread.h"
#include "pk11func.h"
#include "secmod.h"
#include "nsslocks.h"
#include "ec.h"
#include "blapi.h"
#include <stdio.h>

Go to the source code of this file.

Classes

struct  SSLCipher2MechStr
struct  tooLongStr
struct  ssl3SymWrapKey
struct  dnameNode

Defines

#define PK11_SETATTRS(x, id, v, l)
#define MAX_SEND_BUF_LENGTH   32000 /* watch for 16-bit integer overflow */
#define MIN_SEND_BUF_LENGTH   4000
#define MAX_CIPHER_SUITES   20
#define SSL3_BUFFER_FUDGE   100
#define EXPORT_RSA_KEY_LENGTH   64 /* bytes */
#define mmech_null   (CK_MECHANISM_TYPE)0x80000000L
#define mmech_md5   CKM_SSL3_MD5_MAC
#define mmech_sha   CKM_SSL3_SHA1_MAC
#define mmech_md5_hmac   CKM_MD5_HMAC
#define mmech_sha_hmac   CKM_SHA_1_HMAC
#define cx   ((HMACContext *)write_mac_context)
#define SSL3_PENDING_HIGH_WATER   1024
#define md5cx   ((MD5Context *)md5_cx)
#define shacx   ((SHA1Context *)sha_cx)
#define UNKNOWN_WRAP_MECHANISM   0x7fffffff
#define MAX_HANDSHAKE_MSG_LEN   0x1ffff /* 128k - 1 */

Typedefs

typedef struct SSLCipher2MechStr SSLCipher2Mech
typedef struct tooLongStr tooLong
typedef struct dnameNode dnameNode

Functions

static void ssl3_CleanupPeerCerts (sslSocket *ss)
static PK11SymKey * ssl3_GenerateRSAPMS (sslSocket *ss, ssl3CipherSpec *spec, PK11SlotInfo *serverKeySlot)
static SECStatus ssl3_DeriveMasterSecret (sslSocket *ss, PK11SymKey *pms)
static SECStatus ssl3_DeriveConnectionKeysPKCS11 (sslSocket *ss)
static SECStatus ssl3_HandshakeFailure (sslSocket *ss)
static SECStatus ssl3_InitState (sslSocket *ss)
static sslSessionID * ssl3_NewSessionID (sslSocket *ss, PRBool is_server)
static SECStatus ssl3_SendCertificate (sslSocket *ss)
static SECStatus ssl3_SendEmptyCertificate (sslSocket *ss)
static SECStatus ssl3_SendCertificateRequest (sslSocket *ss)
static SECStatus ssl3_SendFinished (sslSocket *ss, PRInt32 flags)
static SECStatus ssl3_SendServerHello (sslSocket *ss)
static SECStatus ssl3_SendServerHelloDone (sslSocket *ss)
static SECStatus ssl3_SendServerKeyExchange (sslSocket *ss)
static SECStatus Null_Cipher (void *ctx, unsigned char *output, int *outputLen, int maxOutputLen, const unsigned char *input, int inputLen)
SSL3StatisticsSSL_GetStatistics (void)
static void SSL_AtomicIncrementLong (long *x)
static const ssl3CipherSuiteDefssl_LookupCipherSuiteDef (ssl3CipherSuite suite)
static ssl3CipherSuiteCfgssl_LookupCipherSuiteCfg (ssl3CipherSuite suite, ssl3CipherSuiteCfg *suites)
int ssl3_config_match_init (sslSocket *ss)
static PRBool config_match (ssl3CipherSuiteCfg *suite, int policy, PRBool enabled)
static int count_cipher_suites (sslSocket *ss, int policy, PRBool enabled)
static PRBool anyRestrictedEnabled (sslSocket *ss)
SECStatus ssl3_NegotiateVersion (sslSocket *ss, SSL3ProtocolVersion peerVersion)
static SECStatus ssl3_GetNewRandom (SSL3Random *random)
SECStatus ssl3_SignHashes (SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf, PRBool isTLS)
SECStatus ssl3_VerifySignedHashes (SSL3Hashes *hash, CERTCertificate *cert, SECItem *buf, PRBool isTLS, void *pwArg)
SECStatus ssl3_ComputeCommonKeyHash (PRUint8 *hashBuf, unsigned int bufLen, SSL3Hashes *hashes, PRBool bypassPKCS11)
static SECStatus ssl3_ComputeExportRSAKeyHash (SECItem modulus, SECItem publicExponent, SSL3Random *client_rand, SSL3Random *server_rand, SSL3Hashes *hashes, PRBool bypassPKCS11)
static SECStatus ssl3_ComputeDHKeyHash (SECItem dh_p, SECItem dh_g, SECItem dh_Ys, SSL3Random *client_rand, SSL3Random *server_rand, SSL3Hashes *hashes, PRBool bypassPKCS11)
static void ssl3_BumpSequenceNumber (SSL3SequenceNumber *num)
static void ssl3_CleanupKeyMaterial (ssl3KeyMaterial *mat)
static void ssl3_DestroyCipherSpec (ssl3CipherSpec *spec)
static SECStatus ssl3_SetupPendingCipherSpec (sslSocket *ss)
static SECStatus ssl3_InitPendingContextsBypass (sslSocket *ss)
static SECItem * ssl3_ParamFromIV (CK_MECHANISM_TYPE mtype, SECItem *iv, CK_ULONG ulEffectiveBits)
static SECStatus ssl3_InitPendingContextsPKCS11 (sslSocket *ss)
SECStatus ssl3_InitPendingCipherSpec (sslSocket *ss, PK11SymKey *pms)
static SECStatus ssl3_ComputeRecordMAC (ssl3CipherSpec *spec, PRBool useServerMacKey, SSL3ContentType type, SSL3ProtocolVersion version, SSL3SequenceNumber seq_num, const SSL3Opaque *input, int inputLength, unsigned char *outbuf, unsigned int *outLength)
static PRBool ssl3_ClientAuthTokenPresent (sslSessionID *sid)
static SECStatus ssl3_CompressMACEncryptRecord (sslSocket *ss, SSL3ContentType type, const SSL3Opaque *pIn, PRUint32 contentLen)
static PRInt32 ssl3_SendRecord (sslSocket *ss, SSL3ContentType type, const SSL3Opaque *pIn, PRInt32 nIn, PRInt32 flags)
int ssl3_SendApplicationData (sslSocket *ss, const unsigned char *in, PRInt32 len, PRInt32 flags)
static SECStatus ssl3_FlushHandshake (sslSocket *ss, PRInt32 flags)
static SECStatus ssl3_HandleNoCertificate (sslSocket *ss)
SECStatus SSL3_SendAlert (sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc)
static SECStatus ssl3_IllegalParameter (sslSocket *ss)
static SECStatus ssl3_DecodeError (sslSocket *ss)
static SECStatus ssl3_HandleAlert (sslSocket *ss, sslBuffer *buf)
static SECStatus ssl3_SendChangeCipherSpecs (sslSocket *ss)
static SECStatus ssl3_HandleChangeCipherSpecs (sslSocket *ss, sslBuffer *buf)
static SECStatus ssl3_UpdateHandshakeHashes (sslSocket *ss, unsigned char *b, unsigned int l)
SECStatus ssl3_AppendHandshake (sslSocket *ss, const void *void_src, PRInt32 bytes)
SECStatus ssl3_AppendHandshakeNumber (sslSocket *ss, PRInt32 num, PRInt32 lenSize)
SECStatus ssl3_AppendHandshakeVariable (sslSocket *ss, const SSL3Opaque *src, PRInt32 bytes, PRInt32 lenSize)
SECStatus ssl3_AppendHandshakeHeader (sslSocket *ss, SSL3HandshakeType t, PRUint32 length)
SECStatus ssl3_ConsumeHandshake (sslSocket *ss, void *v, PRInt32 bytes, SSL3Opaque **b, PRUint32 *length)
PRInt32 ssl3_ConsumeHandshakeNumber (sslSocket *ss, PRInt32 bytes, SSL3Opaque **b, PRUint32 *length)
SECStatus ssl3_ConsumeHandshakeVariable (sslSocket *ss, SECItem *i, PRInt32 bytes, SSL3Opaque **b, PRUint32 *length)
static SECStatus ssl3_ComputeHandshakeHashes (sslSocket *ss, ssl3CipherSpec *spec, SSL3Hashes *hashes, uint32 sender)
SECStatus ssl3_StartHandshakeHash (sslSocket *ss, unsigned char *buf, int length)
SECStatus ssl3_SendClientHello (sslSocket *ss)
static SECStatus ssl3_HandleHelloRequest (sslSocket *ss)
static int ssl_FindIndexByWrapMechanism (CK_MECHANISM_TYPE mech)
static PK11SymKey * ssl_UnwrapSymWrappingKey (SSLWrappedSymWrappingKey *pWswk, SECKEYPrivateKey *svrPrivKey, SSL3KEAType exchKeyType, CK_MECHANISM_TYPE masterWrapMech, void *pwArg)
SECStatus SSL3_ShutdownServerCache (void)
void ssl_InitSymWrapKeysLock (void)
static PK11SymKey * getWrappingKey (sslSocket *ss, PK11SlotInfo *masterSecretSlot, SSL3KEAType exchKeyType, CK_MECHANISM_TYPE masterWrapMech, void *pwArg)
static SECStatus sendRSAClientKeyExchange (sslSocket *ss, SECKEYPublicKey *svrPubKey)
static SECStatus sendDHClientKeyExchange (sslSocket *ss, SECKEYPublicKey *svrPubKey)
static SECStatus ssl3_SendClientKeyExchange (sslSocket *ss)
static SECStatus ssl3_SendCertificateVerify (sslSocket *ss)
static SECStatus ssl3_HandleServerHello (sslSocket *ss, SSL3Opaque *b, PRUint32 length)
static SECStatus ssl3_HandleServerKeyExchange (sslSocket *ss, SSL3Opaque *b, PRUint32 length)
static SECStatus ssl3_HandleCertificateRequest (sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SECStatus ssl3_RestartHandshakeAfterCertReq (sslSocket *ss, CERTCertificate *cert, SECKEYPrivateKey *key, CERTCertificateList *certChain)
static SECStatus ssl3_HandleServerHelloDone (sslSocket *ss)
static SECStatus ssl3_SendHelloRequest (sslSocket *ss)
static SECStatus ssl3_SendServerHelloSequence (sslSocket *ss)
static SECStatus ssl3_HandleClientHello (sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SECStatus ssl3_HandleV2ClientHello (sslSocket *ss, unsigned char *buffer, int length)
static SECStatus ssl3_HandleCertificateVerify (sslSocket *ss, SSL3Opaque *b, PRUint32 length, SSL3Hashes *hashes)
static SECStatus ssl3_HandleRSAClientKeyExchange (sslSocket *ss, SSL3Opaque *b, PRUint32 length, SECKEYPrivateKey *serverKey)
static SECStatus ssl3_HandleClientKeyExchange (sslSocket *ss, SSL3Opaque *b, PRUint32 length)
static SECStatus ssl3_HandleCertificate (sslSocket *ss, SSL3Opaque *b, PRUint32 length)
int ssl3_RestartHandshakeAfterServerCert (sslSocket *ss)
static SECStatus ssl3_ComputeTLSFinished (ssl3CipherSpec *spec, PRBool isServer, const SSL3Finished *hashes, TLSFinished *tlsFinished)
static SECStatus ssl3_CacheWrappedMasterSecret (sslSocket *ss, SSL3KEAType effectiveExchKeyType)
static SECStatus ssl3_HandleFinished (sslSocket *ss, SSL3Opaque *b, PRUint32 length, const SSL3Hashes *hashes)
static SECStatus ssl3_HandleHandshakeMessage (sslSocket *ss, SSL3Opaque *b, PRUint32 length)
static SECStatus ssl3_HandleHandshake (sslSocket *ss, sslBuffer *origBuf)
SECStatus ssl3_HandleRecord (sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
static void ssl3_InitCipherSpec (sslSocket *ss, ssl3CipherSpec *spec)
ssl3KeyPair * ssl3_NewKeyPair (SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey)
ssl3KeyPair * ssl3_GetKeyPairRef (ssl3KeyPair *keyPair)
void ssl3_FreeKeyPair (ssl3KeyPair *keyPair)
SECStatus ssl3_CreateRSAStepDownKeys (sslSocket *ss)
SECStatus ssl3_SetPolicy (ssl3CipherSuite which, int policy)
SECStatus ssl3_GetPolicy (ssl3CipherSuite which, PRInt32 *oPolicy)
SECStatus ssl3_CipherPrefSetDefault (ssl3CipherSuite which, PRBool enabled)
SECStatus ssl3_CipherPrefGetDefault (ssl3CipherSuite which, PRBool *enabled)
SECStatus ssl3_CipherPrefSet (sslSocket *ss, ssl3CipherSuite which, PRBool enabled)
SECStatus ssl3_CipherPrefGet (sslSocket *ss, ssl3CipherSuite which, PRBool *enabled)
void ssl3_InitSocketPolicy (sslSocket *ss)
SECStatus ssl3_ConstructV2CipherSpecsHack (sslSocket *ss, unsigned char *cs, int *size)
SECStatus ssl3_RedoHandshake (sslSocket *ss, PRBool flushCache)
void ssl3_DestroySSL3Info (sslSocket *ss)

Variables

static ssl3CipherSuiteCfg cipherSuites [ssl_V3_SUITES_IMPLEMENTED]
static const uint8 compressions []
static const int compressionMethodsCount
static const uint8 certificate_types []
PRBool ssl3_global_policy_some_restricted = PR_FALSE
CERTDistNames * ssl3_server_ca_list = NULL
static SSL3Statistics ssl3stats
static const ssl3BulkCipherDef bulk_cipher_defs []
static const ssl3KEADef kea_defs []
static const ssl3CipherSuiteDef cipher_suite_defs []
static const CK_MECHANISM_TYPE kea_alg_defs []
static const SSLCipher2Mech alg2Mech []
static const ssl3MACDef mac_defs []
const char *const ssl3_cipherName []
static const unsigned char mac_pad_1 [60]
static const unsigned char mac_pad_2 [60]
static const CK_MECHANISM_TYPE wrapMechanismList [SSL_NUM_WRAP_MECHS]
static PZLocksymWrapKeysLock = NULL
static ssl3SymWrapKey symWrapKeys [SSL_NUM_WRAP_MECHS]

Class Documentation

struct SSLCipher2MechStr

Definition at line 372 of file ssl3con.c.

Class Members
SSLCipherAlgorithm calg
CK_MECHANISM_TYPE cmech
struct tooLongStr

Definition at line 501 of file ssl3con.c.

Class Members
PRInt32 high
PRInt32 low
struct ssl3SymWrapKey

Definition at line 3885 of file ssl3con.c.

Class Members
PK11SymKey * symWrapKey
struct dnameNode

Definition at line 537 of file certhigh.c.

Collaboration diagram for dnameNode:
Class Members
SECItem name
struct dnameNode * next

Define Documentation

#define cx   ((HMACContext *)write_mac_context)

Definition at line 194 of file ssl3con.c.

Definition at line 97 of file ssl3con.c.

#define MAX_HANDSHAKE_MSG_LEN   0x1ffff /* 128k - 1 */
#define MAX_SEND_BUF_LENGTH   32000 /* watch for 16-bit integer overflow */

Definition at line 94 of file ssl3con.c.

#define md5cx   ((MD5Context *)md5_cx)

Definition at line 95 of file ssl3con.c.

Definition at line 389 of file ssl3con.c.

Definition at line 391 of file ssl3con.c.

#define mmech_null   (CK_MECHANISM_TYPE)0x80000000L

Definition at line 388 of file ssl3con.c.

Definition at line 390 of file ssl3con.c.

Definition at line 392 of file ssl3con.c.

#define PK11_SETATTRS (   x,
  id,
  v,
  l 
)
Value:
(x)->type = (id); \
              (x)->pValue=(v); (x)->ulValueLen = (l);

Definition at line 70 of file ssl3con.c.

#define shacx   ((SHA1Context *)sha_cx)

Definition at line 192 of file ssl3con.c.

Definition at line 2034 of file ssl3con.c.

#define UNKNOWN_WRAP_MECHANISM   0x7fffffff

Definition at line 3673 of file ssl3con.c.


Typedef Documentation

typedef struct dnameNode dnameNode
typedef struct tooLongStr tooLong

Function Documentation

static PRBool anyRestrictedEnabled ( sslSocket *  ss) [static]

Definition at line 695 of file ssl3con.c.

{
    int i;

    if (!ss->opt.enableSSL3 && !ss->opt.enableTLS) {
       return PR_FALSE;
    }
    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
       ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
       if (suite->policy == SSL_RESTRICTED &&
           suite->enabled &&
           suite->isPresent)
           return PR_TRUE;
    }
    return PR_FALSE;
}

Here is the caller graph for this function:

static PRBool config_match ( ssl3CipherSuiteCfg suite,
int  policy,
PRBool  enabled 
) [static]

Definition at line 663 of file ssl3con.c.

{
    PORT_Assert(policy != SSL_NOT_ALLOWED && enabled != PR_FALSE);
    if (policy == SSL_NOT_ALLOWED || !enabled)
       return PR_FALSE;
    return (PRBool)(suite->enabled &&
                    suite->isPresent &&
                   suite->policy != SSL_NOT_ALLOWED &&
                  suite->policy <= policy);
}

Here is the caller graph for this function:

static int count_cipher_suites ( sslSocket *  ss,
int  policy,
PRBool  enabled 
) [static]

Definition at line 677 of file ssl3con.c.

{
    int i, count = 0;

    if (!ss->opt.enableSSL3 && !ss->opt.enableTLS) {
       return 0;
    }
    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
       if (config_match(&ss->cipherSuites[i], policy, enabled))
           count++;
    }
    if (count <= 0) {
       PORT_SetError(SSL_ERROR_SSL_DISABLED);
    }
    return count;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PK11SymKey* getWrappingKey ( sslSocket *  ss,
PK11SlotInfo *  masterSecretSlot,
SSL3KEAType  exchKeyType,
CK_MECHANISM_TYPE  masterWrapMech,
void pwArg 
) [static]

Definition at line 3852 of file ssl3con.c.

{
    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];

    ssl_InitSymWrapKeysLock();

    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. */

    if (ss->serverCerts[exchKeyType].serverKeyPair) {
       svrPubKey = ss->serverCerts[exchKeyType].serverKeyPair->pubKey;
    }
    if (svrPubKey == NULL) {
       PORT_SetError(SEC_ERROR_LIBRARY_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) {
#ifdef NSS_ENABLE_ECC
    PK11SymKey *      Ks;
    SECKEYPublicKey   *pubWrapKey = NULL;
    SECKEYPrivateKey  *privWrapKey = NULL;
    ECCWrappedKeyInfo *ecWrapped;
#endif /* NSS_ENABLE_ECC */

    case kt_rsa:
       asymWrapMechanism = CKM_RSA_PKCS;
       rv = PK11_PubWrapSymKey(asymWrapMechanism, svrPubKey,
                               unwrappedWrappingKey, &wrappedKey);
       break;

#ifdef NSS_ENABLE_ECC
    case kt_ecdh:
       /*
        * We generate an ephemeral EC key pair. Perform an ECDH
        * computation involving this ephemeral EC public key and
        * the SSL server's (long-term) EC private key. The resulting
        * shared secret is treated in the same way as Fortezza's Ks, 
        * i.e., it is used to wrap the wrapping key. To facilitate
        * unwrapping in ssl_UnwrapWrappingKey, we also store all
        * relevant info about the ephemeral EC public key in
        * wswk.wrappedSymmetricWrappingkey and lay it out as 
        * described in the ECCWrappedKeyInfo structure.
        */
       PORT_Assert(svrPubKey->keyType == ecKey);
       if (svrPubKey->keyType != ecKey) {
           /* something is wrong in sslsecur.c if this isn't an ecKey */
           PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
           rv = SECFailure;
           goto ec_cleanup;
       }

       privWrapKey = SECKEY_CreateECPrivateKey(
           &svrPubKey->u.ec.DEREncodedParams, &pubWrapKey, NULL);
       if ((privWrapKey == NULL) || (pubWrapKey == NULL)) {
           rv = SECFailure;
           goto ec_cleanup;
       }
       
       /* Set the key size in bits */
       if (pubWrapKey->u.ec.size == 0) {
           pubWrapKey->u.ec.size = SECKEY_PublicKeyStrengthInBits(svrPubKey);
       }

       PORT_Assert(pubWrapKey->u.ec.DEREncodedParams.len + 
           pubWrapKey->u.ec.publicValue.len < MAX_EC_WRAPPED_KEY_BUFLEN);
       if (pubWrapKey->u.ec.DEREncodedParams.len + 
           pubWrapKey->u.ec.publicValue.len >= MAX_EC_WRAPPED_KEY_BUFLEN) {
           PORT_SetError(SEC_ERROR_INVALID_KEY);
           rv = SECFailure;
           goto ec_cleanup;
       }

       /* Derive Ks using ECDH */
       Ks = PK11_PubDeriveWithKDF(svrPrivKey, pubWrapKey, PR_FALSE, NULL,
                               NULL, CKM_ECDH1_DERIVE, masterWrapMech, 
                               CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
       if (Ks == NULL) {
           rv = SECFailure;
           goto ec_cleanup;
       }

       ecWrapped = (ECCWrappedKeyInfo *) (wswk.wrappedSymmetricWrappingkey);
       ecWrapped->size = pubWrapKey->u.ec.size;
       ecWrapped->encodedParamLen = pubWrapKey->u.ec.DEREncodedParams.len;
       PORT_Memcpy(ecWrapped->var, pubWrapKey->u.ec.DEREncodedParams.data, 
           pubWrapKey->u.ec.DEREncodedParams.len);

       ecWrapped->pubValueLen = pubWrapKey->u.ec.publicValue.len;
       PORT_Memcpy(ecWrapped->var + ecWrapped->encodedParamLen, 
                  pubWrapKey->u.ec.publicValue.data, 
                  pubWrapKey->u.ec.publicValue.len);

       wrappedKey.len = MAX_EC_WRAPPED_KEY_BUFLEN - 
           (ecWrapped->encodedParamLen + ecWrapped->pubValueLen);
       wrappedKey.data = ecWrapped->var + ecWrapped->encodedParamLen +
           ecWrapped->pubValueLen;

       /* wrap symmetricWrapping key with the local Ks */
       rv = PK11_WrapSymKey(masterWrapMech, NULL, Ks,
                          unwrappedWrappingKey, &wrappedKey);

       if (rv != SECSuccess) {
           goto ec_cleanup;
       }

       /* Write down the length of wrapped key in the buffer
        * wswk.wrappedSymmetricWrappingkey at the appropriate offset
        */
       ecWrapped->wrappedKeyLen = wrappedKey.len;

ec_cleanup:
       if (privWrapKey) SECKEY_DestroyPrivateKey(privWrapKey);
       if (pubWrapKey) SECKEY_DestroyPublicKey(pubWrapKey);
       if (Ks) PK11_FreeSymKey(Ks);
       asymWrapMechanism = masterWrapMech;
       break;
#endif /* NSS_ENABLE_ECC */

    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:
    PZ_Unlock(symWrapKeysLock);
    return unwrappedWrappingKey;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus Null_Cipher ( void ctx,
unsigned char *  output,
int outputLen,
int  maxOutputLen,
const unsigned char *  input,
int  inputLen 
) [static]

Definition at line 717 of file ssl3con.c.

{
    *outputLen = inputLen;
    if (input != output)
       PORT_Memcpy(output, input, inputLen);
    return SECSuccess;
}

Here is the caller graph for this function:

static SECStatus sendDHClientKeyExchange ( sslSocket *  ss,
SECKEYPublicKey *  svrPubKey 
) [static]

Definition at line 4180 of file ssl3con.c.

{
    PK11SymKey *     pms           = NULL;
    SECStatus           rv                = SECFailure;
    PRBool              isTLS;
    CK_MECHANISM_TYPE       target;

    SECKEYDHParams   dhParam;             /* DH parameters */
    SECKEYPublicKey  *pubKey = NULL;             /* Ephemeral DH key */
    SECKEYPrivateKey *privKey = NULL;     /* Ephemeral DH key */

    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));

    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);

    /* Copy DH parameters from server key */

    dhParam.prime.data = svrPubKey->u.dh.prime.data;
    dhParam.prime.len = svrPubKey->u.dh.prime.len;
    dhParam.base.data = svrPubKey->u.dh.base.data;
    dhParam.base.len = svrPubKey->u.dh.base.len;

    /* Generate ephemeral DH keypair */
    privKey = SECKEY_CreateDHPrivateKey(&dhParam, &pubKey, NULL);
    if (!privKey || !pubKey) {
           ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
           rv = SECFailure;
           goto loser;
    }
    PRINT_BUF(50, (ss, "DH public value:",
                                   pubKey->u.dh.publicValue.data,
                                   pubKey->u.dh.publicValue.len));

    if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
    else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;

    /* Determine the PMS */

    pms = PK11_PubDerive(privKey, svrPubKey, PR_FALSE, NULL, NULL,
                         CKM_DH_PKCS_DERIVE, target, CKA_DERIVE, 0, NULL);

    if (pms == NULL) {
       ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
       goto loser;
    }

    SECKEY_DestroyPrivateKey(privKey);
    privKey = NULL;

    rv = ssl3_InitPendingCipherSpec(ss,  pms);
    PK11_FreeSymKey(pms); pms = NULL;

    if (rv != SECSuccess) {
       ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
       goto loser;
    }

    rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, 
                                   pubKey->u.dh.publicValue.len + 2);
    if (rv != SECSuccess) {
       goto loser;   /* err set by ssl3_AppendHandshake* */
    }
    rv = ssl3_AppendHandshakeVariable(ss, 
                                   pubKey->u.dh.publicValue.data,
                                   pubKey->u.dh.publicValue.len, 2);
    SECKEY_DestroyPublicKey(pubKey);
    pubKey = NULL;

    if (rv != SECSuccess) {
       goto loser;   /* err set by ssl3_AppendHandshake* */
    }

    rv = SECSuccess;


loser:

    if(pms) PK11_FreeSymKey(pms);
    if(privKey) SECKEY_DestroyPrivateKey(privKey);
    if(pubKey) SECKEY_DestroyPublicKey(pubKey);
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus sendRSAClientKeyExchange ( sslSocket *  ss,
SECKEYPublicKey *  svrPubKey 
) [static]

Definition at line 4095 of file ssl3con.c.

{
    PK11SymKey *     pms           = NULL;
    SECStatus           rv                = SECFailure;
    SECItem          enc_pms       = {siBuffer, NULL, 0};
    PRBool              isTLS;

    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));

    /* Generate the pre-master secret ...  */
    ssl_GetSpecWriteLock(ss);
    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);

    pms = ssl3_GenerateRSAPMS(ss, ss->ssl3.pwSpec, NULL);
    ssl_ReleaseSpecWriteLock(ss);
    if (pms == NULL) {
       ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
       goto loser;
    }

#if defined(TRACE)
    if (ssl_trace >= 100) {
       SECStatus extractRV = PK11_ExtractKeyValue(pms);
       if (extractRV == SECSuccess) {
           SECItem * keyData = PK11_GetKeyData(pms);
           if (keyData && keyData->data && keyData->len) {
              ssl_PrintBuf(ss, "Pre-Master Secret", 
                          keyData->data, keyData->len);
           }
       }
    }
#endif

    /* Get the wrapped (encrypted) pre-master secret, enc_pms */
    enc_pms.len  = SECKEY_PublicKeyStrength(svrPubKey);
    enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len);
    if (enc_pms.data == NULL) {
       goto loser;   /* err set by PORT_Alloc */
    }

    /* wrap pre-master secret in server's public key. */
    rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey, pms, &enc_pms);
    if (rv != SECSuccess) {
       ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
       goto loser;
    }

    rv = ssl3_InitPendingCipherSpec(ss,  pms);
    PK11_FreeSymKey(pms); pms = NULL;

    if (rv != SECSuccess) {
       ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
       goto loser;
    }

    rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, 
                                isTLS ? enc_pms.len + 2 : enc_pms.len);
    if (rv != SECSuccess) {
       goto loser;   /* err set by ssl3_AppendHandshake* */
    }
    if (isTLS) {
       rv = ssl3_AppendHandshakeVariable(ss, enc_pms.data, enc_pms.len, 2);
    } else {
       rv = ssl3_AppendHandshake(ss, enc_pms.data, enc_pms.len);
    }
    if (rv != SECSuccess) {
       goto loser;   /* err set by ssl3_AppendHandshake* */
    }

    rv = SECSuccess;

loser:
    if (enc_pms.data != NULL) {
       PORT_Free(enc_pms.data);
    }
    if (pms != NULL) {
       PK11_FreeSymKey(pms);
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus ssl3_AppendHandshake ( sslSocket *  ss,
const void void_src,
PRInt32  bytes 
)

Definition at line 2854 of file ssl3con.c.

{
    unsigned char *  src  = (unsigned char *)void_src;
    int              room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len;
    SECStatus        rv;

    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); /* protects sendBuf. */

    if (ss->sec.ci.sendBuf.space < MAX_SEND_BUF_LENGTH && room < bytes) {
       rv = sslBuffer_Grow(&ss->sec.ci.sendBuf, PR_MAX(MIN_SEND_BUF_LENGTH,
               PR_MIN(MAX_SEND_BUF_LENGTH, ss->sec.ci.sendBuf.len + bytes)));
       if (rv != SECSuccess)
           return rv;       /* sslBuffer_Grow has set a memory error code. */
       room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len;
    }

    PRINT_BUF(60, (ss, "Append to Handshake", (unsigned char*)void_src, bytes));
    rv = ssl3_UpdateHandshakeHashes(ss, src, bytes);
    if (rv != SECSuccess)
       return rv;    /* error code set by ssl3_UpdateHandshakeHashes */

    while (bytes > room) {
       if (room > 0)
           PORT_Memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, src, 
                       room);
       ss->sec.ci.sendBuf.len += room;
       rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
       if (rv != SECSuccess) {
           return rv;       /* error code set by ssl3_FlushHandshake */
       }
       bytes -= room;
       src += room;
       room = ss->sec.ci.sendBuf.space;
       PORT_Assert(ss->sec.ci.sendBuf.len == 0);
    }
    PORT_Memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, src, bytes);
    ss->sec.ci.sendBuf.len += bytes;
    return SECSuccess;
}

Here is the call graph for this function:

SECStatus ssl3_AppendHandshakeHeader ( sslSocket *  ss,
SSL3HandshakeType  t,
PRUint32  length 
)

Definition at line 2937 of file ssl3con.c.

{
    SECStatus rv;

    SSL_TRC(30,("%d: SSL3[%d]: append handshake header: type %s",
       SSL_GETPID(), ss->fd, ssl3_DecodeHandshakeType(t)));
    PRINT_BUF(60, (ss, "MD5 handshake hash:",
                 (unsigned char*)ss->ssl3.hs.md5_cx, MD5_LENGTH));
    PRINT_BUF(95, (ss, "SHA handshake hash:",
                 (unsigned char*)ss->ssl3.hs.sha_cx, SHA1_LENGTH));

    rv = ssl3_AppendHandshakeNumber(ss, t, 1);
    if (rv != SECSuccess) {
       return rv;    /* error code set by AppendHandshake, if applicable. */
    }
    rv = ssl3_AppendHandshakeNumber(ss, length, 3);
    return rv;              /* error code set by AppendHandshake, if applicable. */
}

Here is the call graph for this function:

SECStatus ssl3_AppendHandshakeNumber ( sslSocket *  ss,
PRInt32  num,
PRInt32  lenSize 
)

Definition at line 2895 of file ssl3con.c.

{
    SECStatus rv;
    uint8     b[4];
    uint8 *   p = b;

    switch (lenSize) {
      case 4:
       *p++ = (num >> 24) & 0xff;
      case 3:
       *p++ = (num >> 16) & 0xff;
      case 2:
       *p++ = (num >> 8) & 0xff;
      case 1:
       *p = num & 0xff;
    }
    SSL_TRC(60, ("%d: number:", SSL_GETPID()));
    rv = ssl3_AppendHandshake(ss, &b[0], lenSize);
    return rv;       /* error code set by AppendHandshake, if applicable. */
}

Here is the call graph for this function:

SECStatus ssl3_AppendHandshakeVariable ( sslSocket *  ss,
const SSL3Opaque src,
PRInt32  bytes,
PRInt32  lenSize 
)

Definition at line 2917 of file ssl3con.c.

{
    SECStatus rv;

    PORT_Assert((bytes < (1<<8) && lenSize == 1) ||
             (bytes < (1L<<16) && lenSize == 2) ||
             (bytes < (1L<<24) && lenSize == 3));

    SSL_TRC(60,("%d: append variable:", SSL_GETPID()));
    rv = ssl3_AppendHandshakeNumber(ss, bytes, lenSize);
    if (rv != SECSuccess) {
       return rv;    /* error code set by AppendHandshake, if applicable. */
    }
    SSL_TRC(60, ("data:"));
    rv = ssl3_AppendHandshake(ss, src, bytes);
    return rv;       /* error code set by AppendHandshake, if applicable. */
}

Here is the call graph for this function:

static void ssl3_BumpSequenceNumber ( SSL3SequenceNumber num) [static]

Definition at line 1075 of file ssl3con.c.

{
    num->low++;
    if (num->low == 0)
       num->high++;
}

Here is the caller graph for this function:

static SECStatus ssl3_CacheWrappedMasterSecret ( sslSocket *  ss,
SSL3KEAType  effectiveExchKeyType 
) [static]

Definition at line 7329 of file ssl3con.c.

{
    sslSessionID *    sid      = ss->sec.ci.sid;
    PK11SymKey *      wrappingKey  = NULL;
    PK11SlotInfo *    symKeySlot;
    void *            pwArg        = ss->pkcs11PinArg;
    SECStatus         rv           = SECFailure;
    PRBool            isServer     = ss->sec.isServer;
    CK_MECHANISM_TYPE mechanism    = CKM_INVALID_MECHANISM;
    symKeySlot = PK11_GetSlotFromKey(ss->ssl3.crSpec->master_secret);
    if (!isServer) {
       int  wrapKeyIndex;
       int  incarnation;

       /* these next few functions are mere accessors and don't fail. */
       sid->u.ssl3.masterWrapIndex  = wrapKeyIndex =
                                   PK11_GetCurrentWrapIndex(symKeySlot);
       PORT_Assert(wrapKeyIndex == 0);    /* array has only one entry! */

       sid->u.ssl3.masterWrapSeries = incarnation =
                                   PK11_GetSlotSeries(symKeySlot);
       sid->u.ssl3.masterSlotID   = PK11_GetSlotID(symKeySlot);
       sid->u.ssl3.masterModuleID = PK11_GetModuleID(symKeySlot);
       sid->u.ssl3.masterValid    = PR_TRUE;
       /* Get the default wrapping key, for wrapping the master secret before
        * placing it in the SID cache entry. */
       wrappingKey = PK11_GetWrapKey(symKeySlot, wrapKeyIndex,
                                  CKM_INVALID_MECHANISM, incarnation,
                                  pwArg);
       if (wrappingKey) {
           mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */
       } else {
           int keyLength;
           /* if the wrappingKey doesn't exist, attempt to create it.
            * Note: we intentionally ignore errors here.  If we cannot
            * generate a wrapping key, it is not fatal to this SSL connection,
            * but we will not be able to restart this session.
            */
           mechanism = PK11_GetBestWrapMechanism(symKeySlot);
           keyLength = PK11_GetBestKeyLength(symKeySlot, mechanism);
           /* Zero length means fixed key length algorithm, or error.
            * It's ambiguous.
            */
           wrappingKey = PK11_KeyGen(symKeySlot, mechanism, NULL,
                                  keyLength, pwArg);
           if (wrappingKey) {
              PK11_SetWrapKey(symKeySlot, wrapKeyIndex, wrappingKey);
           }
       }
    } else {
       /* server socket using session cache. */
       mechanism = PK11_GetBestWrapMechanism(symKeySlot);
       if (mechanism != CKM_INVALID_MECHANISM) {
           wrappingKey =
              getWrappingKey(ss, symKeySlot, effectiveExchKeyType,
                            mechanism, pwArg);
           if (wrappingKey) {
              mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */
           }
       }
    }

    sid->u.ssl3.masterWrapMech = mechanism;
    PK11_FreeSlot(symKeySlot);

    if (wrappingKey) {
       SECItem wmsItem;

       wmsItem.data = sid->u.ssl3.keys.wrapped_master_secret;
       wmsItem.len  = sizeof sid->u.ssl3.keys.wrapped_master_secret;
       rv = PK11_WrapSymKey(mechanism, NULL, wrappingKey,
                          ss->ssl3.crSpec->master_secret, &wmsItem);
       /* rv is examined below. */
       sid->u.ssl3.keys.wrapped_master_secret_len = wmsItem.len;
       PK11_FreeSymKey(wrappingKey);
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus ssl3_CipherPrefGet ( sslSocket *  ss,
ssl3CipherSuite  which,
PRBool enabled 
)

Definition at line 8358 of file ssl3con.c.

{
    ssl3CipherSuiteCfg *suite;
    PRBool              pref;
    SECStatus           rv;

    suite = ssl_LookupCipherSuiteCfg(which, ss->cipherSuites);
    if (suite) {
       pref   = suite->enabled;
       rv     = SECSuccess;
    } else {
       pref   = SSL_NOT_ALLOWED;
       rv     = SECFailure; /* err code was set by Lookup. */
    }
    *enabled = pref;
    return rv;
}

Here is the call graph for this function:

Definition at line 8326 of file ssl3con.c.

{
    ssl3CipherSuiteCfg *suite;
    PRBool              pref;
    SECStatus           rv;

    suite = ssl_LookupCipherSuiteCfg(which, cipherSuites);
    if (suite) {
       pref   = suite->enabled;
       rv     = SECSuccess;
    } else {
       pref   = SSL_NOT_ALLOWED;
       rv     = SECFailure; /* err code was set by Lookup. */
    }
    *enabled = pref;
    return rv;
}

Here is the call graph for this function:

SECStatus ssl3_CipherPrefSet ( sslSocket *  ss,
ssl3CipherSuite  which,
PRBool  enabled 
)

Definition at line 8345 of file ssl3con.c.

{
    ssl3CipherSuiteCfg *suite;

    suite = ssl_LookupCipherSuiteCfg(which, ss->cipherSuites);
    if (suite == NULL) {
       return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */
    }
    suite->enabled = enabled;
    return SECSuccess;
}

Here is the call graph for this function:

Definition at line 8312 of file ssl3con.c.

{
    ssl3CipherSuiteCfg *suite;

    suite = ssl_LookupCipherSuiteCfg(which, cipherSuites);
    if (suite == NULL) {
       return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */
    }
    suite->enabled = enabled;
    return SECSuccess;
}

Here is the call graph for this function:

static void ssl3_CleanupKeyMaterial ( ssl3KeyMaterial mat) [static]

Definition at line 1084 of file ssl3con.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void ssl3_CleanupPeerCerts ( sslSocket *  ss) [static]

Definition at line 6841 of file ssl3con.c.

{
    PRArenaPool * arena = ss->ssl3.peerCertArena;
    ssl3CertNode *certs = (ssl3CertNode *)ss->ssl3.peerCertChain;

    for (; certs; certs = certs->next) {
       CERT_DestroyCertificate(certs->cert);
    }
    if (arena) PORT_FreeArena(arena, PR_FALSE);
    ss->ssl3.peerCertArena = NULL;
    ss->ssl3.peerCertChain = NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool ssl3_ClientAuthTokenPresent ( sslSessionID *  sid) [static]

Definition at line 1748 of file ssl3con.c.

                                               {
    PK11SlotInfo *slot = NULL;
    PRBool isPresent = PR_TRUE;

    /* we only care if we are doing client auth */
    if (!sid || !sid->u.ssl3.clAuthValid) {
       return PR_TRUE;
    }

    /* get the slot */
    slot = SECMOD_LookupSlot(sid->u.ssl3.clAuthModuleID,
                            sid->u.ssl3.clAuthSlotID);
    if (slot == NULL ||
       !PK11_IsPresent(slot) ||
       sid->u.ssl3.clAuthSeries     != PK11_GetSlotSeries(slot) ||
       sid->u.ssl3.clAuthSlotID     != PK11_GetSlotID(slot)     ||
       sid->u.ssl3.clAuthModuleID   != PK11_GetModuleID(slot)   ||
       (PK11_NeedLogin(slot) && !PK11_IsLoggedIn(slot, NULL))) {
       isPresent = PR_FALSE;
    } 
    if (slot) {
       PK11_FreeSlot(slot);
    }
    return isPresent;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_CompressMACEncryptRecord ( sslSocket *  ss,
SSL3ContentType  type,
const SSL3Opaque pIn,
PRUint32  contentLen 
) [static]

Definition at line 1775 of file ssl3con.c.

{
    ssl3CipherSpec *          cwSpec;
    const ssl3BulkCipherDef * cipher_def;
    sslBuffer      *          wrBuf         = &ss->sec.writeBuf;
    SECStatus                 rv;
    PRUint32                  macLen      = 0;
    PRUint32                  fragLen;
    PRUint32  p1Len, p2Len, oddLen = 0;
    PRInt32   cipherBytes =  0;

    /*
     * null compression is easy to do
    PORT_Memcpy(wrBuf->buf + SSL3_RECORD_HEADER_LENGTH, pIn, contentLen);
     */

    ssl_GetSpecReadLock(ss);       /********************************/

    cwSpec = ss->ssl3.cwSpec;
    cipher_def = cwSpec->cipher_def;
    /*
     * Add the MAC
     */
    rv = ssl3_ComputeRecordMAC( cwSpec, (PRBool)(ss->sec.isServer),
       type, cwSpec->version, cwSpec->write_seq_num, pIn, contentLen,
       wrBuf->buf + contentLen + SSL3_RECORD_HEADER_LENGTH, &macLen);
    if (rv != SECSuccess) {
       ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
       goto spec_locked_loser;
    }
    p1Len   = contentLen;
    p2Len   = macLen;
    fragLen = contentLen + macLen; /* needs to be encrypted */
    PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024);

    /*
     * Pad the text (if we're doing a block cipher)
     * then Encrypt it
     */
    if (cipher_def->type == type_block) {
       unsigned char * pBuf;
       int             padding_length;
       int             i;

       oddLen = contentLen % cipher_def->block_size;
       /* Assume blockSize is a power of two */
       padding_length = cipher_def->block_size - 1 -
                     ((fragLen) & (cipher_def->block_size - 1));
       fragLen += padding_length + 1;
       PORT_Assert((fragLen % cipher_def->block_size) == 0);

       /* Pad according to TLS rules (also acceptable to SSL3). */
       pBuf = &wrBuf->buf[fragLen + SSL3_RECORD_HEADER_LENGTH - 1];
       for (i = padding_length + 1; i > 0; --i) {
           *pBuf-- = padding_length;
       }
       /* now, if contentLen is not a multiple of block size, fix it */
       p2Len = fragLen - p1Len;
    }
    if (p1Len < 256) {
       oddLen = p1Len;
       p1Len = 0;
    } else {
       p1Len -= oddLen;
    }
    if (oddLen) {
       p2Len += oddLen;
       PORT_Assert( (cipher_def->block_size < 2) || \
                   (p2Len % cipher_def->block_size) == 0);
       memcpy(wrBuf->buf + SSL3_RECORD_HEADER_LENGTH + p1Len,
              pIn + p1Len, oddLen);
    }
    if (p1Len > 0) {
       rv = cwSpec->encode( cwSpec->encodeContext, 
           wrBuf->buf + SSL3_RECORD_HEADER_LENGTH, /* output */
           &cipherBytes,                           /* actual outlen */
           p1Len,                                  /* max outlen */
           pIn, p1Len);                      /* input, and inputlen */
       PORT_Assert(rv == SECSuccess && cipherBytes == p1Len);
       if (rv != SECSuccess || cipherBytes != p1Len) {
           PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
           goto spec_locked_loser;
       }
    }
    if (p2Len > 0) {
       PRInt32 cipherBytesPart2 = -1;
       rv = cwSpec->encode( cwSpec->encodeContext, 
           wrBuf->buf + SSL3_RECORD_HEADER_LENGTH + p1Len,
           &cipherBytesPart2,          /* output and actual outLen */
           p2Len,                             /* max outlen */
           wrBuf->buf + SSL3_RECORD_HEADER_LENGTH + p1Len,
           p2Len);                            /* input and inputLen*/
       PORT_Assert(rv == SECSuccess && cipherBytesPart2 == p2Len);
       if (rv != SECSuccess || cipherBytesPart2 != p2Len) {
           PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
           goto spec_locked_loser;
       }
       cipherBytes += cipherBytesPart2;
    }  
    PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024);

    ssl3_BumpSequenceNumber(&cwSpec->write_seq_num);

    wrBuf->len    = cipherBytes + SSL3_RECORD_HEADER_LENGTH;
    wrBuf->buf[0] = type;
    wrBuf->buf[1] = MSB(cwSpec->version);
    wrBuf->buf[2] = LSB(cwSpec->version);
    wrBuf->buf[3] = MSB(cipherBytes);
    wrBuf->buf[4] = LSB(cipherBytes);

    ssl_ReleaseSpecReadLock(ss); /************************************/

    return SECSuccess;

spec_locked_loser:
    ssl_ReleaseSpecReadLock(ss);
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus ssl3_ComputeCommonKeyHash ( PRUint8 hashBuf,
unsigned int  bufLen,
SSL3Hashes hashes,
PRBool  bypassPKCS11 
)

Definition at line 941 of file ssl3con.c.

{
    SECStatus     rv               = SECSuccess;

    if (bypassPKCS11) {
       MD5_HashBuf (hashes->md5, hashBuf, bufLen);
       SHA1_HashBuf(hashes->sha, hashBuf, bufLen);
    } else {
       rv = PK11_HashBuf(SEC_OID_MD5, hashes->md5, hashBuf, bufLen);
       if (rv != SECSuccess) {
           ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
           rv = SECFailure;
           goto done;
       }

       rv = PK11_HashBuf(SEC_OID_SHA1, hashes->sha, hashBuf, bufLen);
       if (rv != SECSuccess) {
           ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
           rv = SECFailure;
       }
    }
done:
    return rv;
}

Here is the call graph for this function:

static SECStatus ssl3_ComputeDHKeyHash ( SECItem  dh_p,
SECItem  dh_g,
SECItem  dh_Ys,
SSL3Random client_rand,
SSL3Random server_rand,
SSL3Hashes hashes,
PRBool  bypassPKCS11 
) [static]

Definition at line 1022 of file ssl3con.c.

{
    PRUint8     * hashBuf;
    PRUint8     * pBuf;
    SECStatus     rv               = SECSuccess;
    unsigned int  bufLen;
    PRUint8       buf[2*SSL3_RANDOM_LENGTH + 2 + 4096/8 + 2 + 4096/8];

    bufLen = 2*SSL3_RANDOM_LENGTH + 2 + dh_p.len + 2 + dh_g.len + 2 + dh_Ys.len;
    if (bufLen <= sizeof buf) {
       hashBuf = buf;
    } else {
       hashBuf = PORT_Alloc(bufLen);
       if (!hashBuf) {
           return SECFailure;
       }
    }

    memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH); 
       pBuf = hashBuf + SSL3_RANDOM_LENGTH;
    memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
       pBuf += SSL3_RANDOM_LENGTH;
    pBuf[0]  = (PRUint8)(dh_p.len >> 8);
    pBuf[1]  = (PRUint8)(dh_p.len);
       pBuf += 2;
    memcpy(pBuf, dh_p.data, dh_p.len);
       pBuf += dh_p.len;
    pBuf[0] = (PRUint8)(dh_g.len >> 8);
    pBuf[1] = (PRUint8)(dh_g.len);
       pBuf += 2;
    memcpy(pBuf, dh_g.data, dh_g.len);
       pBuf += dh_g.len;
    pBuf[0] = (PRUint8)(dh_Ys.len >> 8);
    pBuf[1] = (PRUint8)(dh_Ys.len);
       pBuf += 2;
    memcpy(pBuf, dh_Ys.data, dh_Ys.len);
       pBuf += dh_Ys.len;
    PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);

    rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11);

    PRINT_BUF(95, (NULL, "DHkey hash: ", hashBuf, bufLen));
    PRINT_BUF(95, (NULL, "DHkey hash: MD5 result", hashes->md5, MD5_LENGTH));
    PRINT_BUF(95, (NULL, "DHkey hash: SHA1 result", hashes->sha, SHA1_LENGTH));

    if (hashBuf != buf && hashBuf != NULL)
       PORT_Free(hashBuf);
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_ComputeExportRSAKeyHash ( SECItem  modulus,
SECItem  publicExponent,
SSL3Random client_rand,
SSL3Random server_rand,
SSL3Hashes hashes,
PRBool  bypassPKCS11 
) [static]

Definition at line 972 of file ssl3con.c.

{
    PRUint8     * hashBuf;
    PRUint8     * pBuf;
    SECStatus     rv               = SECSuccess;
    unsigned int  bufLen;
    PRUint8       buf[2*SSL3_RANDOM_LENGTH + 2 + 4096/8 + 2 + 4096/8];

    bufLen = 2*SSL3_RANDOM_LENGTH + 2 + modulus.len + 2 + publicExponent.len;
    if (bufLen <= sizeof buf) {
       hashBuf = buf;
    } else {
       hashBuf = PORT_Alloc(bufLen);
       if (!hashBuf) {
           return SECFailure;
       }
    }

    memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH); 
       pBuf = hashBuf + SSL3_RANDOM_LENGTH;
    memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
       pBuf += SSL3_RANDOM_LENGTH;
    pBuf[0]  = (PRUint8)(modulus.len >> 8);
    pBuf[1]  = (PRUint8)(modulus.len);
       pBuf += 2;
    memcpy(pBuf, modulus.data, modulus.len);
       pBuf += modulus.len;
    pBuf[0] = (PRUint8)(publicExponent.len >> 8);
    pBuf[1] = (PRUint8)(publicExponent.len);
       pBuf += 2;
    memcpy(pBuf, publicExponent.data, publicExponent.len);
       pBuf += publicExponent.len;
    PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);

    rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11);

    PRINT_BUF(95, (NULL, "RSAkey hash: ", hashBuf, bufLen));
    PRINT_BUF(95, (NULL, "RSAkey hash: MD5 result", hashes->md5, MD5_LENGTH));
    PRINT_BUF(95, (NULL, "RSAkey hash: SHA1 result", hashes->sha, SHA1_LENGTH));

    if (hashBuf != buf && hashBuf != NULL)
       PORT_Free(hashBuf);
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_ComputeHandshakeHashes ( sslSocket *  ss,
ssl3CipherSpec spec,
SSL3Hashes hashes,
uint32  sender 
) [static]

Definition at line 3076 of file ssl3con.c.

{
    SECStatus     rv        = SECSuccess;
    PRBool        isTLS     = (PRBool)(spec->version > SSL_LIBRARY_VERSION_3_0);
    unsigned int  outLength;
    SSL3Opaque    md5_inner[MAX_MAC_LENGTH];
    SSL3Opaque    sha_inner[MAX_MAC_LENGTH];

    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    if (ss->opt.bypassPKCS11) {
       /* compute them without PKCS11 */
       PRUint64      md5_cx[MAX_MAC_CONTEXT_LLONGS];
       PRUint64      sha_cx[MAX_MAC_CONTEXT_LLONGS];

#define md5cx ((MD5Context *)md5_cx)
#define shacx ((SHA1Context *)sha_cx)

       if (!spec->msItem.data) {
           PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
           return SECFailure;
       }

       MD5_Clone (md5cx,  (MD5Context *)ss->ssl3.hs.md5_cx);
       SHA1_Clone(shacx, (SHA1Context *)ss->ssl3.hs.sha_cx);

       if (!isTLS) {
           /* compute hashes for SSL3. */
           unsigned char s[4];

           s[0] = (unsigned char)(sender >> 24);
           s[1] = (unsigned char)(sender >> 16);
           s[2] = (unsigned char)(sender >> 8);
           s[3] = (unsigned char)sender;

           if (sender != 0) {
              MD5_Update(md5cx, s, 4);
              PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4));
           }

           PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1, 
                         mac_defs[mac_md5].pad_size));

           MD5_Update(md5cx, spec->msItem.data, spec->msItem.len);
           MD5_Update(md5cx, mac_pad_1, mac_defs[mac_md5].pad_size);
           MD5_End(md5cx, md5_inner, &outLength, MD5_LENGTH);

           PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength));

           if (sender != 0) {
              SHA1_Update(shacx, s, 4);
              PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4));
           }

           PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1, 
                         mac_defs[mac_sha].pad_size));

           SHA1_Update(shacx, spec->msItem.data, spec->msItem.len);
           SHA1_Update(shacx, mac_pad_1, mac_defs[mac_sha].pad_size);
           SHA1_End(shacx, sha_inner, &outLength, SHA1_LENGTH);

           PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength));
           PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2, 
                         mac_defs[mac_md5].pad_size));
           PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH));

           MD5_Begin(md5cx);
           MD5_Update(md5cx, spec->msItem.data, spec->msItem.len);
           MD5_Update(md5cx, mac_pad_2, mac_defs[mac_md5].pad_size);
           MD5_Update(md5cx, md5_inner, MD5_LENGTH);
       }
       MD5_End(md5cx, hashes->md5, &outLength, MD5_LENGTH);

       PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->md5, MD5_LENGTH));

       if (!isTLS) {
           PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2, 
                         mac_defs[mac_sha].pad_size));
           PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH));

           SHA1_Begin(shacx);
           SHA1_Update(shacx, spec->msItem.data, spec->msItem.len);
           SHA1_Update(shacx, mac_pad_2, mac_defs[mac_sha].pad_size);
           SHA1_Update(shacx, sha_inner, SHA1_LENGTH);
       }
       SHA1_End(shacx, hashes->sha, &outLength, SHA1_LENGTH);

       PRINT_BUF(60, (NULL, "SHA outer: result", hashes->sha, SHA1_LENGTH));

       rv = SECSuccess;
#undef md5cx
#undef shacx
    } else {
       /* compute hases with PKCS11 */
       PK11Context * md5;
       PK11Context * sha       = NULL;
       unsigned char *md5StateBuf = NULL;
       unsigned char *shaStateBuf = NULL;
       unsigned int  md5StateLen, shaStateLen;
       unsigned char md5StackBuf[256];
       unsigned char shaStackBuf[512];

       if (!spec->master_secret) {
           PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
           return SECFailure;
       }

       md5StateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.md5, md5StackBuf,
                                       sizeof md5StackBuf, &md5StateLen);
       if (md5StateBuf == NULL) {
           ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
           goto loser;
       }
       md5 = ss->ssl3.hs.md5;

       shaStateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.sha, shaStackBuf,
                                       sizeof shaStackBuf, &shaStateLen);
       if (shaStateBuf == NULL) {
           ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
           goto loser;
       }
       sha = ss->ssl3.hs.sha;

       if (!isTLS) {
           /* compute hashes for SSL3. */
           unsigned char s[4];

           s[0] = (unsigned char)(sender >> 24);
           s[1] = (unsigned char)(sender >> 16);
           s[2] = (unsigned char)(sender >> 8);
           s[3] = (unsigned char)sender;

           if (sender != 0) {
              rv |= PK11_DigestOp(md5, s, 4);
              PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4));
           }

           PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1, 
                       mac_defs[mac_md5].pad_size));

           rv |= PK11_DigestKey(md5,spec->master_secret);
           rv |= PK11_DigestOp(md5, mac_pad_1, mac_defs[mac_md5].pad_size);
           rv |= PK11_DigestFinal(md5, md5_inner, &outLength, MD5_LENGTH);
           PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH);
           if (rv != SECSuccess) {
              ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
              rv = SECFailure;
              goto loser;
           }

           PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength));

           if (sender != 0) {
              rv |= PK11_DigestOp(sha, s, 4);
              PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4));
           }

           PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1, 
                       mac_defs[mac_sha].pad_size));

           rv |= PK11_DigestKey(sha, spec->master_secret);
           rv |= PK11_DigestOp(sha, mac_pad_1, mac_defs[mac_sha].pad_size);
           rv |= PK11_DigestFinal(sha, sha_inner, &outLength, SHA1_LENGTH);
           PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH);
           if (rv != SECSuccess) {
              ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
              rv = SECFailure;
              goto loser;
           }

           PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength));

           PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2, 
                       mac_defs[mac_md5].pad_size));
           PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH));

           rv |= PK11_DigestBegin(md5);
           rv |= PK11_DigestKey(md5, spec->master_secret);
           rv |= PK11_DigestOp(md5, mac_pad_2, mac_defs[mac_md5].pad_size);
           rv |= PK11_DigestOp(md5, md5_inner, MD5_LENGTH);
       }
       rv |= PK11_DigestFinal(md5, hashes->md5, &outLength, MD5_LENGTH);
       PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH);
       if (rv != SECSuccess) {
           ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
           rv = SECFailure;
           goto loser;
       }

       PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->md5, MD5_LENGTH));

       if (!isTLS) {
           PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2, 
                       mac_defs[mac_sha].pad_size));
           PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH));

           rv |= PK11_DigestBegin(sha);
           rv |= PK11_DigestKey(sha,spec->master_secret);
           rv |= PK11_DigestOp(sha, mac_pad_2, mac_defs[mac_sha].pad_size);
           rv |= PK11_DigestOp(sha, sha_inner, SHA1_LENGTH);
       }
       rv |= PK11_DigestFinal(sha, hashes->sha, &outLength, SHA1_LENGTH);
       PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH);
       if (rv != SECSuccess) {
           ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
           rv = SECFailure;
           goto loser;
       }

       PRINT_BUF(60, (NULL, "SHA outer: result", hashes->sha, SHA1_LENGTH));

       rv = SECSuccess;

    loser:
       if (md5StateBuf) {
           if (PK11_RestoreContext(ss->ssl3.hs.md5, md5StateBuf, md5StateLen)
               != SECSuccess) 
           {
              ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
              rv = SECFailure;
           }
           if (md5StateBuf != md5StackBuf) {
              PORT_ZFree(md5StateBuf, md5StateLen);
           }
       }
       if (shaStateBuf) {
           if (PK11_RestoreContext(ss->ssl3.hs.sha, shaStateBuf, shaStateLen)
               != SECSuccess) 
           {
              ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
              rv = SECFailure;
           }
           if (shaStateBuf != shaStackBuf) {
              PORT_ZFree(shaStateBuf, shaStateLen);
           }
       }
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_ComputeRecordMAC ( ssl3CipherSpec spec,
PRBool  useServerMacKey,
SSL3ContentType  type,
SSL3ProtocolVersion  version,
SSL3SequenceNumber  seq_num,
const SSL3Opaque input,
int  inputLength,
unsigned char *  outbuf,
unsigned int outLength 
) [static]

Definition at line 1587 of file ssl3con.c.

{
    const ssl3MACDef * mac_def;
    SECStatus          rv;
    PRBool             isTLS;
    unsigned int       tempLen;
    unsigned char      temp[MAX_MAC_LENGTH];

    temp[0] = (unsigned char)(seq_num.high >> 24);
    temp[1] = (unsigned char)(seq_num.high >> 16);
    temp[2] = (unsigned char)(seq_num.high >>  8);
    temp[3] = (unsigned char)(seq_num.high >>  0);
    temp[4] = (unsigned char)(seq_num.low  >> 24);
    temp[5] = (unsigned char)(seq_num.low  >> 16);
    temp[6] = (unsigned char)(seq_num.low  >>  8);
    temp[7] = (unsigned char)(seq_num.low  >>  0);
    temp[8] = type;

    /* TLS MAC includes the record's version field, SSL's doesn't.
    ** We decide which MAC defintiion to use based on the version of 
    ** the protocol that was negotiated when the spec became current,
    ** NOT based on the version value in the record itself.
    ** But, we use the record'v version value in the computation.
    */
    if (spec->version <= SSL_LIBRARY_VERSION_3_0) {
       temp[9]  = MSB(inputLength);
       temp[10] = LSB(inputLength);
       tempLen  = 11;
       isTLS    = PR_FALSE;
    } else {
       /* New TLS hash includes version. */
       temp[9]  = MSB(version);
       temp[10] = LSB(version);
       temp[11] = MSB(inputLength);
       temp[12] = LSB(inputLength);
       tempLen  = 13;
       isTLS    = PR_TRUE;
    }

    PRINT_BUF(95, (NULL, "frag hash1: temp", temp, tempLen));
    PRINT_BUF(95, (NULL, "frag hash1: input", input, inputLength));

    mac_def = spec->mac_def;
    if (mac_def->mac == mac_null) {
       *outLength = 0;
       return SECSuccess;
    }
    if (! spec->bypassCiphers) {
       PK11Context *mac_context = 
           (useServerMacKey ? spec->server.write_mac_context
                            : spec->client.write_mac_context);
       rv  = PK11_DigestBegin(mac_context);
       rv |= PK11_DigestOp(mac_context, temp, tempLen);
       rv |= PK11_DigestOp(mac_context, input, inputLength);
       rv |= PK11_DigestFinal(mac_context, outbuf, outLength, spec->mac_size);
    } else {
       /* bypass version */
       const SECHashObject *hashObj = NULL;
       unsigned int       pad_bytes;
       PRUint64           write_mac_context[MAX_MAC_CONTEXT_LLONGS];

       switch (mac_def->mac) {
       case ssl_mac_null:
           *outLength = 0;
           return SECSuccess;
       case ssl_mac_md5:
           pad_bytes = 48;
           hashObj = HASH_GetRawHashObject(HASH_AlgMD5);
           break;
       case ssl_mac_sha:
           pad_bytes = 40;
           hashObj = HASH_GetRawHashObject(HASH_AlgSHA1);
           break;
       case ssl_hmac_md5: /* used with TLS */
           hashObj = HASH_GetRawHashObject(HASH_AlgMD5);
           break;
       case ssl_hmac_sha: /* used with TLS */
           hashObj = HASH_GetRawHashObject(HASH_AlgSHA1);
           break;
       default:
           break;
       }
       if (!hashObj) {
           PORT_Assert(0);
           PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
           return SECFailure;
       }

       if (!isTLS) {
           /* compute "inner" part of SSL3 MAC */
           hashObj->begin(write_mac_context);
           if (useServerMacKey)
              hashObj->update(write_mac_context, 
                            spec->server.write_mac_key_item.data,
                            spec->server.write_mac_key_item.len);
           else
              hashObj->update(write_mac_context, 
                            spec->client.write_mac_key_item.data,
                            spec->client.write_mac_key_item.len);
           hashObj->update(write_mac_context, mac_pad_1, pad_bytes);
           hashObj->update(write_mac_context, temp,  tempLen);
           hashObj->update(write_mac_context, input, inputLength);
           hashObj->end(write_mac_context,    temp, &tempLen, sizeof temp);

           /* compute "outer" part of SSL3 MAC */
           hashObj->begin(write_mac_context);
           if (useServerMacKey)
              hashObj->update(write_mac_context, 
                            spec->server.write_mac_key_item.data,
                            spec->server.write_mac_key_item.len);
           else
              hashObj->update(write_mac_context, 
                            spec->client.write_mac_key_item.data,
                            spec->client.write_mac_key_item.len);
           hashObj->update(write_mac_context, mac_pad_2, pad_bytes);
           hashObj->update(write_mac_context, temp, tempLen);
           hashObj->end(write_mac_context, outbuf, outLength, spec->mac_size);
           rv = SECSuccess;
       } else { /* is TLS */
#define cx ((HMACContext *)write_mac_context)
           if (useServerMacKey) {
              rv = HMAC_Init(cx, hashObj, 
                            spec->server.write_mac_key_item.data,
                            spec->server.write_mac_key_item.len, PR_FALSE);
           } else {
              rv = HMAC_Init(cx, hashObj, 
                            spec->client.write_mac_key_item.data,
                            spec->client.write_mac_key_item.len, PR_FALSE);
           }
           if (rv == SECSuccess) {
              HMAC_Begin(cx);
              HMAC_Update(cx, temp, tempLen);
              HMAC_Update(cx, input, inputLength);
              rv = HMAC_Finish(cx, outbuf, outLength, spec->mac_size);
              HMAC_Destroy(cx, PR_FALSE);
           }
#undef cx
       }
    }

    PORT_Assert(rv != SECSuccess || *outLength == (unsigned)spec->mac_size);

    PRINT_BUF(95, (NULL, "frag hash2: result", outbuf, *outLength));

    if (rv != SECSuccess) {
       rv = SECFailure;
       ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_ComputeTLSFinished ( ssl3CipherSpec spec,
PRBool  isServer,
const SSL3Finished hashes,
TLSFinished tlsFinished 
) [static]

Definition at line 7223 of file ssl3con.c.

{
    const char * label;
    unsigned int len;
    SECStatus    rv;

    label = isServer ? "server finished" : "client finished";
    len   = 15;

    if (spec->master_secret && !spec->bypassCiphers) {
       SECItem      param       = {siBuffer, NULL, 0};
       PK11Context *prf_context =
           PK11_CreateContextBySymKey(CKM_TLS_PRF_GENERAL, CKA_SIGN, 
                                   spec->master_secret, &param);
       if (!prf_context)
           return SECFailure;

       rv  = PK11_DigestBegin(prf_context);
       rv |= PK11_DigestOp(prf_context, (const unsigned char *) label, len);
       rv |= PK11_DigestOp(prf_context, hashes->md5, sizeof *hashes);
       rv |= PK11_DigestFinal(prf_context, tlsFinished->verify_data, 
                            &len, sizeof tlsFinished->verify_data);
       PORT_Assert(rv != SECSuccess || len == sizeof *tlsFinished);

       PK11_DestroyContext(prf_context, PR_TRUE);
    } else {
       /* bypass PKCS11 */
       SECItem inData  = { siBuffer, };
       SECItem outData = { siBuffer, };
       PRBool isFIPS   = PR_FALSE;

       inData.data  = (unsigned char *)hashes->md5;
       inData.len   = sizeof hashes[0];
       outData.data = tlsFinished->verify_data;
       outData.len  = sizeof tlsFinished->verify_data;
       rv = TLS_PRF(&spec->msItem, label, &inData, &outData, isFIPS);
       PORT_Assert(rv != SECSuccess || \
                  outData.len == sizeof tlsFinished->verify_data);
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ssl3_config_match_init ( sslSocket *  ss)

Definition at line 559 of file ssl3con.c.

{
    ssl3CipherSuiteCfg *      suite;
    const ssl3CipherSuiteDef *cipher_def;
    SSLCipherAlgorithm        cipher_alg;
    CK_MECHANISM_TYPE         cipher_mech;
    SSL3KEAType               exchKeyType;
    int                       i;
    int                       numPresent         = 0;
    int                       numEnabled         = 0;
    PRBool                    isServer;
    sslServerCerts           *svrAuth;

    PORT_Assert(ss);
    if (!ss) {
       PORT_SetError(SEC_ERROR_INVALID_ARGS);
       return 0;
    }
    if (!ss->opt.enableSSL3 && !ss->opt.enableTLS) {
       return 0;
    }
    isServer = (PRBool)(ss->sec.isServer != 0);

    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
       suite = &ss->cipherSuites[i];
       if (suite->enabled) {
           ++numEnabled;
           /* We need the cipher defs to see if we have a token that can handle
            * this cipher.  It isn't part of the static definition.
            */
           cipher_def = ssl_LookupCipherSuiteDef(suite->cipher_suite);
           if (!cipher_def) {
              suite->isPresent = PR_FALSE;
              continue;
           }
           cipher_alg=bulk_cipher_defs[cipher_def->bulk_cipher_alg ].calg;
           PORT_Assert(  alg2Mech[cipher_alg].calg == cipher_alg);
           cipher_mech = alg2Mech[cipher_alg].cmech;
           exchKeyType =
                  kea_defs[cipher_def->key_exchange_alg].exchKeyType;
#ifndef NSS_ENABLE_ECC
           svrAuth = ss->serverCerts + exchKeyType;
#else
           /* XXX SSLKEAType isn't really a good choice for 
            * indexing certificates. It doesn't work for
            * (EC)DHE-* ciphers. Here we use a hack to ensure
            * that the server uses an RSA cert for (EC)DHE-RSA.
            */
           switch (cipher_def->key_exchange_alg) {
           case kea_ecdhe_rsa:
#if NSS_SERVER_DHE_IMPLEMENTED
           /* XXX NSS does not yet implement the server side of _DHE_
            * cipher suites.  Correcting the computation for svrAuth,
            * as the case below does, causes NSS SSL servers to begin to
            * negotiate cipher suites they do not implement.  So, until
            * server side _DHE_ is implemented, keep this disabled.
            */
           case kea_dhe_rsa:
#endif
              svrAuth = ss->serverCerts + kt_rsa;
              break;
           case kea_ecdh_ecdsa:
           case kea_ecdh_rsa:
               /* 
               * XXX We ought to have different indices for 
               * ECDSA- and RSA-signed EC certificates so
               * we could support both key exchange mechanisms
               * simultaneously. For now, both of them use
               * whatever is in the certificate slot for kt_ecdh
               */
           default:
              svrAuth = ss->serverCerts + exchKeyType;
              break;
           }
#endif /* NSS_ENABLE_ECC */

           /* Mark the suites that are backed by real tokens, certs and keys */
           suite->isPresent = (PRBool)
              (((exchKeyType == kt_null) ||
                 ((!isServer || (svrAuth->serverKeyPair &&
                                 svrAuth->SERVERKEY &&
                               svrAuth->serverCertChain)) &&
                  PK11_TokenExists(kea_alg_defs[exchKeyType]))) &&
              ((cipher_alg == calg_null) || PK11_TokenExists(cipher_mech)));
           if (suite->isPresent)
              ++numPresent;
       }
    }
    PORT_Assert(numPresent > 0 || numEnabled == 0);
    if (numPresent <= 0) {
       PORT_SetError(SSL_ERROR_NO_CIPHERS_SUPPORTED);
    }
    return numPresent;
}

Here is the call graph for this function:

SECStatus ssl3_ConstructV2CipherSpecsHack ( sslSocket *  ss,
unsigned char *  cs,
int size 
)

Definition at line 8387 of file ssl3con.c.

{
    int i, count = 0;

    PORT_Assert(ss != 0);
    if (!ss) {
       PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
       return SECFailure;
    }
    if (!ss->opt.enableSSL3 && !ss->opt.enableTLS) {
       *size = 0;
       return SECSuccess;
    }
    if (cs == NULL) {
       *size = count_cipher_suites(ss, SSL_ALLOWED, PR_TRUE);
       return SECSuccess;
    }

    /* ssl3_config_match_init was called by the caller of this function. */
    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
       ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
       if (config_match(suite, SSL_ALLOWED, PR_TRUE)) {
           if (cs != NULL) {
              *cs++ = 0x00;
              *cs++ = (suite->cipher_suite >> 8) & 0xFF;
              *cs++ =  suite->cipher_suite       & 0xFF;
           }
           count++;
       }
    }
    *size = count;
    return SECSuccess;
}

Here is the call graph for this function:

SECStatus ssl3_ConsumeHandshake ( sslSocket *  ss,
void v,
PRInt32  bytes,
SSL3Opaque **  b,
PRUint32 length 
)

Definition at line 2972 of file ssl3con.c.

{
    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    if ((PRUint32)bytes > *length) {
       return ssl3_DecodeError(ss);
    }
    PORT_Memcpy(v, *b, bytes);
    PRINT_BUF(60, (ss, "consume bytes:", *b, bytes));
    *b      += bytes;
    *length -= bytes;
    return SECSuccess;
}

Here is the call graph for this function:

PRInt32 ssl3_ConsumeHandshakeNumber ( sslSocket *  ss,
PRInt32  bytes,
SSL3Opaque **  b,
PRUint32 length 
)

Definition at line 3000 of file ssl3con.c.

{
    uint8     *buf = *b;
    int       i;
    PRInt32   num = 0;

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
    PORT_Assert( bytes <= sizeof num);

    if ((PRUint32)bytes > *length) {
       return ssl3_DecodeError(ss);
    }
    PRINT_BUF(60, (ss, "consume bytes:", *b, bytes));

    for (i = 0; i < bytes; i++)
       num = (num << 8) + buf[i];
    *b      += bytes;
    *length -= bytes;
    return num;
}

Here is the call graph for this function:

SECStatus ssl3_ConsumeHandshakeVariable ( sslSocket *  ss,
SECItem *  i,
PRInt32  bytes,
SSL3Opaque **  b,
PRUint32 length 
)

Definition at line 3038 of file ssl3con.c.

{
    PRInt32   count;

    PORT_Assert(bytes <= 3);
    i->len  = 0;
    i->data = NULL;
    count = ssl3_ConsumeHandshakeNumber(ss, bytes, b, length);
    if (count < 0) {               /* Can't test for SECSuccess here. */
       return SECFailure;
    }
    if (count > 0) {
       if ((PRUint32)count > *length) {
           return ssl3_DecodeError(ss);
       }
       i->data = *b;
       i->len  = count;
       *b      += count;
       *length -= count;
    }
    return SECSuccess;
}

Here is the call graph for this function:

Definition at line 8245 of file ssl3con.c.

{
    SECStatus             rv        = SECSuccess;
    SECKEYPrivateKey *    privKey;        /* RSA step down key */
    SECKEYPublicKey *     pubKey;         /* RSA step down key */

    if (ss->stepDownKeyPair)
       ssl3_FreeKeyPair(ss->stepDownKeyPair);
    ss->stepDownKeyPair = NULL;
#ifndef HACKED_EXPORT_SERVER
    /* Sigh, should have a get key strength call for private keys */
    if (PK11_GetPrivateModulusLen(ss->serverCerts[kt_rsa].SERVERKEY) >
                                                     EXPORT_RSA_KEY_LENGTH) {
       /* need to ask for the key size in bits */
       privKey = SECKEY_CreateRSAPrivateKey(EXPORT_RSA_KEY_LENGTH * BPB,
                                        &pubKey, NULL);
       if (!privKey || !pubKey ||
           !(ss->stepDownKeyPair = ssl3_NewKeyPair(privKey, pubKey))) {
           ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
           rv = SECFailure;
       }
    }
#endif
    return rv;
}

Here is the call graph for this function:

static SECStatus ssl3_DecodeError ( sslSocket *  ss) [static]

Definition at line 2303 of file ssl3con.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_DeriveConnectionKeysPKCS11 ( sslSocket *  ss) [static]

Definition at line 2690 of file ssl3con.c.

{
    ssl3CipherSpec *         pwSpec     = ss->ssl3.pwSpec;
    const ssl3KEADef *       kea_def    = ss->ssl3.hs.kea_def;
    unsigned char *   cr     = (unsigned char *)&ss->ssl3.hs.client_random;
    unsigned char *   sr     = (unsigned char *)&ss->ssl3.hs.server_random;
    PRBool            isTLS  = (PRBool)(kea_def->tls_keygen ||
                                (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
    /* following variables used in PKCS11 path */
    const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def;
    PK11SlotInfo *         slot   = NULL;
    PK11SymKey *           symKey = NULL;
    void *                 pwArg  = ss->pkcs11PinArg;
    int                    keySize;
    CK_SSL3_KEY_MAT_PARAMS key_material_params;
    CK_SSL3_KEY_MAT_OUT    returnedKeys;
    CK_MECHANISM_TYPE      key_derive;
    CK_MECHANISM_TYPE      bulk_mechanism;
    SSLCipherAlgorithm     calg;
    SECItem                params;
    PRBool         skipKeysAndIVs = (PRBool)(cipher_def->calg == calg_null);

    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
    PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);

    if (!pwSpec->master_secret) {
       PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
       return SECFailure;
    }
    /*
     * generate the key material
     */
    key_material_params.ulMacSizeInBits = pwSpec->mac_size           * BPB;
    key_material_params.ulKeySizeInBits = cipher_def->secret_key_size* BPB;
    key_material_params.ulIVSizeInBits  = cipher_def->iv_size        * BPB;

    key_material_params.bIsExport = (CK_BBOOL)(kea_def->is_limited);
    /* was:   (CK_BBOOL)(cipher_def->keygen_mode != kg_strong); */

    key_material_params.RandomInfo.pClientRandom     = cr;
    key_material_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
    key_material_params.RandomInfo.pServerRandom     = sr;
    key_material_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
    key_material_params.pReturnedKeyMaterial         = &returnedKeys;

    returnedKeys.pIVClient = pwSpec->client.write_iv;
    returnedKeys.pIVServer = pwSpec->server.write_iv;
    keySize                = cipher_def->key_size;

    if (skipKeysAndIVs) {
       keySize                             = 0;
        key_material_params.ulKeySizeInBits = 0;
        key_material_params.ulIVSizeInBits  = 0;
       returnedKeys.pIVClient              = NULL;
       returnedKeys.pIVServer              = NULL;
    }

    calg = cipher_def->calg;
    PORT_Assert(     alg2Mech[calg].calg == calg);
    bulk_mechanism = alg2Mech[calg].cmech;

    params.data    = (unsigned char *)&key_material_params;
    params.len     = sizeof(key_material_params);

    if (isTLS) {
       key_derive    = CKM_TLS_KEY_AND_MAC_DERIVE;
    } else {
       key_derive    = CKM_SSL3_KEY_AND_MAC_DERIVE;
    }

    /* CKM_SSL3_KEY_AND_MAC_DERIVE is defined to set ENCRYPT, DECRYPT, and
     * DERIVE by DEFAULT */
    symKey = PK11_Derive(pwSpec->master_secret, key_derive, &params,
                         bulk_mechanism, CKA_ENCRYPT, keySize);
    if (!symKey) {
       ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
       return SECFailure;
    }
    /* we really should use the actual mac'ing mechanism here, but we
     * don't because these types are used to map keytype anyway and both
     * mac's map to the same keytype.
     */
    slot  = PK11_GetSlotFromKey(symKey);

    PK11_FreeSlot(slot); /* slot is held until the key is freed */
    pwSpec->client.write_mac_key =
       PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
           CKM_SSL3_SHA1_MAC, returnedKeys.hClientMacSecret, PR_TRUE, pwArg);
    if (pwSpec->client.write_mac_key == NULL ) {
       goto loser;   /* loser sets err */
    }
    pwSpec->server.write_mac_key =
       PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
           CKM_SSL3_SHA1_MAC, returnedKeys.hServerMacSecret, PR_TRUE, pwArg);
    if (pwSpec->server.write_mac_key == NULL ) {
       goto loser;   /* loser sets err */
    }
    if (!skipKeysAndIVs) {
       pwSpec->client.write_key =
              PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
                   bulk_mechanism, returnedKeys.hClientKey, PR_TRUE, pwArg);
       if (pwSpec->client.write_key == NULL ) {
           goto loser;      /* loser sets err */
       }
       pwSpec->server.write_key =
              PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
                   bulk_mechanism, returnedKeys.hServerKey, PR_TRUE, pwArg);
       if (pwSpec->server.write_key == NULL ) {
           goto loser;      /* loser sets err */
       }
    }
    PK11_FreeSymKey(symKey);
    return SECSuccess;


loser:
    if (symKey) PK11_FreeSymKey(symKey);
    ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_DeriveMasterSecret ( sslSocket *  ss,
PK11SymKey *  pms 
) [static]

Definition at line 2537 of file ssl3con.c.

{
    ssl3CipherSpec *  pwSpec = ss->ssl3.pwSpec;
    const ssl3KEADef *kea_def= ss->ssl3.hs.kea_def;
    unsigned char *   cr     = (unsigned char *)&ss->ssl3.hs.client_random;
    unsigned char *   sr     = (unsigned char *)&ss->ssl3.hs.server_random;
    PRBool            isTLS  = (PRBool)(kea_def->tls_keygen ||
                                (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
    /* 
     * Whenever isDH is true, we need to use CKM_TLS_MASTER_KEY_DERIVE_DH
     * which, unlike CKM_TLS_MASTER_KEY_DERIVE, converts arbitrary size
     * data into a 48-byte value. 
     */
    PRBool    isDH = (PRBool) ((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) ||
                              (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh));
    SECStatus         rv = SECFailure;
    CK_MECHANISM_TYPE master_derive;
    CK_MECHANISM_TYPE key_derive;
    SECItem           params;
    CK_FLAGS          keyFlags;
    CK_VERSION        pms_version;
    CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params;

    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
    PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
    if (isTLS) {
       if(isDH) master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH;
       else master_derive = CKM_TLS_MASTER_KEY_DERIVE;
       key_derive    = CKM_TLS_KEY_AND_MAC_DERIVE;
       keyFlags      = CKF_SIGN | CKF_VERIFY;
    } else {
       if (isDH) master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH;
       else master_derive = CKM_SSL3_MASTER_KEY_DERIVE;
       key_derive    = CKM_SSL3_KEY_AND_MAC_DERIVE;
       keyFlags      = 0;
    }

    if (pms || !pwSpec->master_secret) {
       master_params.pVersion                     = &pms_version;
       master_params.RandomInfo.pClientRandom     = cr;
       master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
       master_params.RandomInfo.pServerRandom     = sr;
       master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;

       params.data = (unsigned char *) &master_params;
       params.len  = sizeof master_params;
    }

    if (pms != NULL) {
#if defined(TRACE)
       if (ssl_trace >= 100) {
           SECStatus extractRV = PK11_ExtractKeyValue(pms);
           if (extractRV == SECSuccess) {
              SECItem * keyData = PK11_GetKeyData(pms);
              if (keyData && keyData->data && keyData->len) {
                  ssl_PrintBuf(ss, "Pre-Master Secret", 
                             keyData->data, keyData->len);
              }
           }
       }
#endif
       pwSpec->master_secret = PK11_DeriveWithFlags(pms, master_derive, 
                            &params, key_derive, CKA_DERIVE, 0, keyFlags);
       if (!isDH && pwSpec->master_secret && ss->opt.detectRollBack) {
           SSL3ProtocolVersion client_version;
           client_version = pms_version.major << 8 | pms_version.minor;
           if (client_version != ss->clientHelloVersion) {
              /* Destroy it.  Version roll-back detected. */
              PK11_FreeSymKey(pwSpec->master_secret);
              pwSpec->master_secret = NULL;
           }
       }
       if (pwSpec->master_secret == NULL) {
           /* Generate a faux master secret in the same slot as the old one. */
           PK11SlotInfo * slot = PK11_GetSlotFromKey((PK11SymKey *)pms);
           PK11SymKey *   fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot);

           PK11_FreeSlot(slot);
           if (fpms != NULL) {
              pwSpec->master_secret = PK11_DeriveWithFlags(fpms, 
                                   master_derive, &params, key_derive, 
                                   CKA_DERIVE, 0, keyFlags);
              PK11_FreeSymKey(fpms);
           }
       }
    }
    if (pwSpec->master_secret == NULL) {
       /* Generate a faux master secret from the internal slot. */
       PK11SlotInfo *  slot = PK11_GetInternalSlot();
       PK11SymKey *    fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot);

       PK11_FreeSlot(slot);
       if (fpms != NULL) {
           pwSpec->master_secret = PK11_DeriveWithFlags(fpms, 
                                   master_derive, &params, key_derive, 
                                   CKA_DERIVE, 0, keyFlags);
           if (pwSpec->master_secret == NULL) {
              pwSpec->master_secret = fpms; /* use the fpms as the master. */
              fpms = NULL;
           }
       }
       if (fpms) {
           PK11_FreeSymKey(fpms);
       }
    }
    if (pwSpec->master_secret == NULL) {
       ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
       return rv;
    }
    if (ss->opt.bypassPKCS11) {
       SECItem * keydata;
       /* In hope of doing a "double bypass", 
        * need to extract the master secret's value from the key object 
        * and store it raw in the sslSocket struct.
        */
       rv = PK11_ExtractKeyValue(pwSpec->master_secret);
       if (rv != SECSuccess) {
           return rv;
       } 
       /* This returns the address of the secItem inside the key struct,
        * not a copy or a reference.  So, there's no need to free it.
        */
       keydata = PK11_GetKeyData(pwSpec->master_secret);
       if (keydata && keydata->len <= sizeof pwSpec->raw_master_secret) {
           memcpy(pwSpec->raw_master_secret, keydata->data, keydata->len);
           pwSpec->msItem.data = pwSpec->raw_master_secret;
           pwSpec->msItem.len  = keydata->len;
       } else {
           PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
           return SECFailure;
       }
    }
    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ssl3_DestroyCipherSpec ( ssl3CipherSpec spec) [static]

Definition at line 1106 of file ssl3con.c.

{
    PRBool freeit = (PRBool)(!spec->bypassCiphers);
/*  PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); Don't have ss! */
    if (spec->destroy) {
       spec->destroy(spec->encodeContext, freeit);
       spec->destroy(spec->decodeContext, freeit);
       spec->encodeContext = NULL; /* paranoia */
       spec->decodeContext = NULL;
    }
    if (spec->master_secret != NULL) {
       PK11_FreeSymKey(spec->master_secret);
       spec->master_secret = NULL;
    }
    spec->msItem.data = NULL;
    spec->msItem.len  = 0;
    ssl3_CleanupKeyMaterial(&spec->client);
    ssl3_CleanupKeyMaterial(&spec->server);
    spec->bypassCiphers = PR_FALSE;
    spec->destroy=NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void ssl3_DestroySSL3Info ( sslSocket *  ss)

Definition at line 8462 of file ssl3con.c.

{

    if (ss->ssl3.clientCertificate != NULL)
       CERT_DestroyCertificate(ss->ssl3.clientCertificate);

    if (ss->ssl3.clientPrivateKey != NULL)
       SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);

    if (ss->ssl3.peerCertArena != NULL)
       ssl3_CleanupPeerCerts(ss);

    if (ss->ssl3.clientCertChain != NULL) {
       CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
       ss->ssl3.clientCertChain = NULL;
    }

    /* clean up handshake */
    if (ss->opt.bypassPKCS11) {
       SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE);
       MD5_DestroyContext((MD5Context *)ss->ssl3.hs.md5_cx, PR_FALSE);
    } 
    if (ss->ssl3.hs.md5) {
       PK11_DestroyContext(ss->ssl3.hs.md5,PR_TRUE);
    }
    if (ss->ssl3.hs.sha) {
       PK11_DestroyContext(ss->ssl3.hs.sha,PR_TRUE);
    }

    /* free the SSL3Buffer (msg_body) */
    PORT_Free(ss->ssl3.hs.msg_body.buf);

    /* free up the CipherSpecs */
    ssl3_DestroyCipherSpec(&ss->ssl3.specs[0]);
    ssl3_DestroyCipherSpec(&ss->ssl3.specs[1]);

    ss->ssl3.initialized = PR_FALSE;
}

Here is the call graph for this function:

static SECStatus ssl3_FlushHandshake ( sslSocket *  ss,
PRInt32  flags 
) [static]

Definition at line 2129 of file ssl3con.c.

{
    PRInt32 rv = SECSuccess;

    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
    PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );

    if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
       return rv;

    /* only this flag is allowed */
    PORT_Assert(!(flags & ~ssl_SEND_FLAG_FORCE_INTO_BUFFER));
    if ((flags & ~ssl_SEND_FLAG_FORCE_INTO_BUFFER) != 0) {
       PORT_SetError(SEC_ERROR_INVALID_ARGS);
       rv = SECFailure;
    } else {
       rv = ssl3_SendRecord(ss, content_handshake, ss->sec.ci.sendBuf.buf,
                          ss->sec.ci.sendBuf.len, flags);
    }
    if (rv < 0) { 
       int err = PORT_GetError();
       PORT_Assert(err != PR_WOULD_BLOCK_ERROR);
       if (err == PR_WOULD_BLOCK_ERROR) {
           PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
       }
    } else if (rv < ss->sec.ci.sendBuf.len) {
       /* short write should never happen */
       PORT_Assert(rv >= ss->sec.ci.sendBuf.len);
       PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
       rv = SECFailure;
    } else {
       rv = SECSuccess;
    }

    /* Whether we succeeded or failed, toss the old handshake data. */
    ss->sec.ci.sendBuf.len = 0;
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void ssl3_FreeKeyPair ( ssl3KeyPair *  keyPair)

Definition at line 8226 of file ssl3con.c.

{
    PRInt32 newCount =  PR_AtomicDecrement(&keyPair->refCount);
    if (!newCount) {
       if (keyPair->privKey)
           SECKEY_DestroyPrivateKey(keyPair->privKey);
       if (keyPair->pubKey)
           SECKEY_DestroyPublicKey( keyPair->pubKey);
       PORT_Free(keyPair);
    }
}

Here is the call graph for this function:

static PK11SymKey * ssl3_GenerateRSAPMS ( sslSocket *  ss,
ssl3CipherSpec spec,
PK11SlotInfo *  serverKeySlot 
) [static]

Definition at line 6358 of file ssl3con.c.

{
    PK11SymKey *      pms          = NULL;
    PK11SlotInfo *    slot         = serverKeySlot;
    void *          pwArg          = ss->pkcs11PinArg;
    SECItem           param;
    CK_VERSION             version;
    CK_MECHANISM_TYPE mechanism_array[3];

    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    if (slot == NULL) {
       SSLCipherAlgorithm calg;
       /* The specReadLock would suffice here, but we cannot assert on
       ** read locks.  Also, all the callers who call with a non-null
       ** slot already hold the SpecWriteLock.
       */
       PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
       PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);

        calg = spec->cipher_def->calg;
       PORT_Assert(alg2Mech[calg].calg == calg);

       /* First get an appropriate slot.  */
       mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN;
       mechanism_array[1] = CKM_RSA_PKCS;
       mechanism_array[2] = alg2Mech[calg].cmech;

       slot = PK11_GetBestSlotMultiple(mechanism_array, 3, pwArg);
       if (slot == NULL) {
          /* can't find a slot with all three, find a slot with the minimum */
           slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg);
           if (slot == NULL) {
              PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND);
              return pms;   /* which is NULL */
           }
       }
    }

    /* Generate the pre-master secret ...  */
    version.major = MSB(ss->clientHelloVersion);
    version.minor = LSB(ss->clientHelloVersion);

    param.data = (unsigned char *)&version;
    param.len  = sizeof version;

    pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, &param, 0, pwArg);
    if (!serverKeySlot)
       PK11_FreeSlot(slot);
    if (pms == NULL) {
       ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
    }
    return pms;
}

Here is the call graph for this function:

Here is the caller graph for this function:

ssl3KeyPair* ssl3_GetKeyPairRef ( ssl3KeyPair *  keyPair)

Definition at line 8219 of file ssl3con.c.

{
    PR_AtomicIncrement(&keyPair->refCount);
    return keyPair;
}

Here is the call graph for this function:

static SECStatus ssl3_GetNewRandom ( SSL3Random random) [static]

Definition at line 760 of file ssl3con.c.

{
    PRIntervalTime gmt = PR_IntervalToSeconds(PR_IntervalNow());
    SECStatus rv;

    random->rand[0] = (unsigned char)(gmt >> 24);
    random->rand[1] = (unsigned char)(gmt >> 16);
    random->rand[2] = (unsigned char)(gmt >>  8);
    random->rand[3] = (unsigned char)(gmt);

    /* first 4 bytes are reserverd for time */
    rv = PK11_GenerateRandom(&random->rand[4], SSL3_RANDOM_LENGTH - 4);
    if (rv != SECSuccess) {
       ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus ssl3_GetPolicy ( ssl3CipherSuite  which,
PRInt32 oPolicy 
)

Definition at line 8292 of file ssl3con.c.

{
    ssl3CipherSuiteCfg *suite;
    PRInt32             policy;
    SECStatus           rv;

    suite = ssl_LookupCipherSuiteCfg(which, cipherSuites);
    if (suite) {
       policy = suite->policy;
       rv     = SECSuccess;
    } else {
       policy = SSL_NOT_ALLOWED;
       rv     = SECFailure; /* err code was set by Lookup. */
    }
    *oPolicy = policy;
    return rv;
}

Here is the call graph for this function:

static SECStatus ssl3_HandleAlert ( sslSocket *  ss,
sslBuffer *  buf 
) [static]

Definition at line 2317 of file ssl3con.c.

{
    SSL3AlertLevel       level;
    SSL3AlertDescription desc;
    int                  error;

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    SSL_TRC(3, ("%d: SSL3[%d]: handle alert record", SSL_GETPID(), ss->fd));

    if (buf->len != 2) {
       (void)ssl3_DecodeError(ss);
       PORT_SetError(SSL_ERROR_RX_MALFORMED_ALERT);
       return SECFailure;
    }
    level = (SSL3AlertLevel)buf->buf[0];
    desc  = (SSL3AlertDescription)buf->buf[1];
    buf->len = 0;
    SSL_TRC(5, ("%d: SSL3[%d] received alert, level = %d, description = %d",
        SSL_GETPID(), ss->fd, level, desc));

    switch (desc) {
    case close_notify:             ss->recvdCloseNotify = 1;
                            error = SSL_ERROR_CLOSE_NOTIFY_ALERT;     break;
    case unexpected_message:       error = SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT;
                                                                 break;
    case bad_record_mac:    error = SSL_ERROR_BAD_MAC_ALERT;     break;
    case decryption_failed:        error = SSL_ERROR_DECRYPTION_FAILED_ALERT; 
                                                                 break;
    case record_overflow:   error = SSL_ERROR_RECORD_OVERFLOW_ALERT;  break;
    case decompression_failure: error = SSL_ERROR_DECOMPRESSION_FAILURE_ALERT;
                                                                 break;
    case handshake_failure:        error = SSL_ERROR_HANDSHAKE_FAILURE_ALERT;
                                                                 break;
    case no_certificate:    error = SSL_ERROR_NO_CERTIFICATE;    break;
    case bad_certificate:   error = SSL_ERROR_BAD_CERT_ALERT;    break;
    case unsupported_certificate:error = SSL_ERROR_UNSUPPORTED_CERT_ALERT;break;
    case certificate_revoked:      error = SSL_ERROR_REVOKED_CERT_ALERT;       break;
    case certificate_expired:      error = SSL_ERROR_EXPIRED_CERT_ALERT;       break;
    case certificate_unknown:      error = SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT;
                                                                 break;
    case illegal_parameter:        error = SSL_ERROR_ILLEGAL_PARAMETER_ALERT;break;

    /* All alerts below are TLS only. */
    case unknown_ca:               error = SSL_ERROR_UNKNOWN_CA_ALERT;       break;
    case access_denied:     error = SSL_ERROR_ACCESS_DENIED_ALERT;    break;
    case decode_error:             error = SSL_ERROR_DECODE_ERROR_ALERT;     break;
    case decrypt_error:     error = SSL_ERROR_DECRYPT_ERROR_ALERT;    break;
    case export_restriction:       error = SSL_ERROR_EXPORT_RESTRICTION_ALERT; 
                                                                 break;
    case protocol_version:  error = SSL_ERROR_PROTOCOL_VERSION_ALERT; break;
    case insufficient_security: error = SSL_ERROR_INSUFFICIENT_SECURITY_ALERT; 
                                                                 break;
    case internal_error:    error = SSL_ERROR_INTERNAL_ERROR_ALERT;   break;
    case user_canceled:     error = SSL_ERROR_USER_CANCELED_ALERT;    break;
    case no_renegotiation:  error = SSL_ERROR_NO_RENEGOTIATION_ALERT; break;

    /* Alerts for TLS client hello extensions */
    case unsupported_extension: 
                     error = SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT;    break;
    case certificate_unobtainable: 
                     error = SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT; break;
    case unrecognized_name: 
                     error = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;        break;
    case bad_certificate_status_response: 
                     error = SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT; break;
    case bad_certificate_hash_value: 
                     error = SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT;      break;
    default:         error = SSL_ERROR_RX_UNKNOWN_ALERT;               break;
    }
    if (level == alert_fatal) {
       ss->sec.uncache(ss->sec.ci.sid);
       if ((ss->ssl3.hs.ws == wait_server_hello) &&
           (desc == handshake_failure)) {
           /* XXX This is a hack.  We're assuming that any handshake failure
            * XXX on the client hello is a failure to match ciphers.
            */
           error = SSL_ERROR_NO_CYPHER_OVERLAP;
       }
       PORT_SetError(error);
       return SECFailure;
    }
    if ((desc == no_certificate) && (ss->ssl3.hs.ws == wait_client_cert)) {
       /* I'm a server. I've requested a client cert. He hasn't got one. */
       SECStatus rv;

       PORT_Assert(ss->sec.isServer);
       ss->ssl3.hs.ws = wait_client_key;
       rv = ssl3_HandleNoCertificate(ss);
       return rv;
    }
    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleCertificate ( sslSocket *  ss,
SSL3Opaque b,
PRUint32  length 
) [static]

Definition at line 6859 of file ssl3con.c.

{
    ssl3CertNode *   c;
    ssl3CertNode *   certs  = NULL;
    PRArenaPool *    arena  = NULL;
    CERTCertificate *cert;
    PRInt32          remaining  = 0;
    PRInt32          size;
    SECStatus        rv;
    PRBool           isServer      = (PRBool)(!!ss->sec.isServer);
    PRBool           trusted       = PR_FALSE;
    PRBool           isTLS;
    SSL3AlertDescription desc      = bad_certificate;
    int              errCode    = SSL_ERROR_RX_MALFORMED_CERTIFICATE;
    SECItem          certItem;

    SSL_TRC(3, ("%d: SSL3[%d]: handle certificate handshake",
              SSL_GETPID(), ss->fd));
    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    if ((ss->ssl3.hs.ws != wait_server_cert) &&
       (ss->ssl3.hs.ws != wait_client_cert)) {
       desc    = unexpected_message;
       errCode = SSL_ERROR_RX_UNEXPECTED_CERTIFICATE;
       goto alert_loser;
    }

    if (ss->sec.peerCert != NULL) {
       if (ss->sec.peerKey) {
           SECKEY_DestroyPublicKey(ss->sec.peerKey);
           ss->sec.peerKey = NULL;
       }
       CERT_DestroyCertificate(ss->sec.peerCert);
       ss->sec.peerCert = NULL;
    }

    ssl3_CleanupPeerCerts(ss);
    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);

    /* It is reported that some TLS client sends a Certificate message
    ** with a zero-length message body.  We'll treat that case like a
    ** normal no_certificates message to maximize interoperability.
    */
    if (length) {
       remaining = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
       if (remaining < 0)
           goto loser;      /* fatal alert already sent by ConsumeHandshake. */
       if ((PRUint32)remaining > length)
           goto decode_loser;
    }

    if (!remaining) {
       if (!(isTLS && isServer))
           goto alert_loser;
       /* This is TLS's version of a no_certificate alert. */
       /* I'm a server. I've requested a client cert. He hasn't got one. */
       rv = ssl3_HandleNoCertificate(ss);
       if (rv != SECSuccess) {
           errCode = PORT_GetError();
           goto loser;
       }
       goto cert_block;
    }

    ss->ssl3.peerCertArena = arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if ( arena == NULL ) {
       goto loser;   /* don't send alerts on memory errors */
    }

    /* First get the peer cert. */
    remaining -= 3;
    if (remaining < 0)
       goto decode_loser;

    size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
    if (size <= 0)
       goto loser;   /* fatal alert already sent by ConsumeHandshake. */

    if (remaining < size)
       goto decode_loser;

    certItem.data = b;
    certItem.len = size;
    b      += size;
    length -= size;
    remaining -= size;

    ss->sec.peerCert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL,
                                            PR_FALSE, PR_TRUE);
    if (ss->sec.peerCert == NULL) {
       /* We should report an alert if the cert was bad, but not if the
        * problem was just some local problem, like memory error.
        */
       goto ambiguous_err;
    }

    /* Now get all of the CA certs. */
    while (remaining > 0) {
       remaining -= 3;
       if (remaining < 0)
           goto decode_loser;

       size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
       if (size <= 0)
           goto loser;      /* fatal alert already sent by ConsumeHandshake. */

       if (remaining < size)
           goto decode_loser;

       certItem.data = b;
       certItem.len = size;
       b      += size;
       length -= size;
       remaining -= size;

       c = PORT_ArenaNew(arena, ssl3CertNode);
       if (c == NULL) {
           goto loser;      /* don't send alerts on memory errors */
       }

       c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL,
                                         PR_FALSE, PR_TRUE);
       if (c->cert == NULL) {
           goto ambiguous_err;
       }

       if (c->cert->trust)
           trusted = PR_TRUE;

       c->next = certs;
       certs = c;
    }

    if (remaining != 0)
        goto decode_loser;

    SECKEY_UpdateCertPQG(ss->sec.peerCert);

    /*
     * Ask caller-supplied callback function to validate cert chain.
     */
    rv = (SECStatus)(*ss->authCertificate)(ss->authCertificateArg, ss->fd,
                                      PR_TRUE, isServer);
    if (rv) {
       errCode = PORT_GetError();
       if (!ss->handleBadCert) {
           goto bad_cert;
       }
       rv = (SECStatus)(*ss->handleBadCert)(ss->badCertArg, ss->fd);
       if ( rv ) {
           if ( rv == SECWouldBlock ) {
              /* someone will handle this connection asynchronously*/
              SSL_DBG(("%d: SSL3[%d]: go to async cert handler",
                      SSL_GETPID(), ss->fd));
              ss->ssl3.peerCertChain = certs;
              certs               = NULL;
              ssl_SetAlwaysBlock(ss);
              goto cert_block;
           }
           /* cert is bad */
           goto bad_cert;
       }
       /* cert is good */
    }

    /* start SSL Step Up, if appropriate */
    cert = ss->sec.peerCert;
    if (!isServer &&
       ssl3_global_policy_some_restricted &&
        ss->ssl3.policy == SSL_ALLOWED &&
       anyRestrictedEnabled(ss) &&
       SECSuccess == CERT_VerifyCertNow(cert->dbhandle, cert,
                                        PR_FALSE, /* checkSig */
                                     certUsageSSLServerWithStepUp,
/*XXX*/                                     ss->authCertificateArg) ) {
       ss->ssl3.policy         = SSL_RESTRICTED;
       ss->ssl3.hs.rehandshake = PR_TRUE;
    }

    ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);

    if (!ss->sec.isServer) {
       /* set the server authentication and key exchange types and sizes
       ** from the value in the cert.  If the key exchange key is different,
       ** it will get fixed when we handle the server key exchange message.
       */
       SECKEYPublicKey * pubKey  = CERT_ExtractPublicKey(cert);
       ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType;
       ss->sec.keaType       = ss->ssl3.hs.kea_def->exchKeyType;
       if (pubKey) {
           ss->sec.keaKeyBits = ss->sec.authKeyBits =
              SECKEY_PublicKeyStrengthInBits(pubKey);
#ifdef NSS_ENABLE_ECC
           if (ss->sec.keaType == kt_ecdh) {
              /* Get authKeyBits from signing key.
               * XXX The code below uses a quick approximation of
               * key size based on cert->signatureWrap.signature.data
               * (which contains the DER encoded signature). The field
               * cert->signatureWrap.signature.len contains the
               * length of the encoded signature in bits.
               */
              if (ss->ssl3.hs.kea_def->kea == kea_ecdh_ecdsa) {
                  ss->sec.authKeyBits = 
                     cert->signatureWrap.signature.data[3]*8;
                  if (cert->signatureWrap.signature.data[4] == 0x00)
                         ss->sec.authKeyBits -= 8;
                  /* 
                   * XXX: if cert is not signed by ecdsa we should
                   * destroy pubKey and goto bad_cert
                   */
              } else if (ss->ssl3.hs.kea_def->kea == kea_ecdh_rsa) {
                  ss->sec.authKeyBits = cert->signatureWrap.signature.len;
                  /* 
                   * XXX: if cert is not signed by rsa we should
                   * destroy pubKey and goto bad_cert
                   */
              }
           }
#endif /* NSS_ENABLE_ECC */
           SECKEY_DestroyPublicKey(pubKey); 
           pubKey = NULL;
       }
    }

    ss->ssl3.peerCertChain = certs;  certs = NULL;  arena = NULL;

cert_block:
    if (ss->sec.isServer) {
       ss->ssl3.hs.ws = wait_client_key;
    } else {
       ss->ssl3.hs.ws = wait_cert_request; /* disallow server_key_exchange */
       if (ss->ssl3.hs.kea_def->is_limited ||
           /* XXX OR server cert is signing only. */
#ifdef NSS_ENABLE_ECC
           ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa ||
           ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa ||
#endif /* NSS_ENABLE_ECC */
           ss->ssl3.hs.kea_def->exchKeyType == kt_dh) {
           ss->ssl3.hs.ws = wait_server_key; /* allow server_key_exchange */
       }
    }

    /* rv must normally be equal to SECSuccess here.  If we called
     * handleBadCert, it can also be SECWouldBlock.
     */
    return rv;

ambiguous_err:
    errCode = PORT_GetError();
    switch (errCode) {
    case PR_OUT_OF_MEMORY_ERROR:
    case SEC_ERROR_BAD_DATABASE:
    case SEC_ERROR_NO_MEMORY:
       if (isTLS) {
           desc = internal_error;
           goto alert_loser;
       }
       goto loser;
    }
    /* fall through to bad_cert. */

bad_cert:     /* caller has set errCode. */
    switch (errCode) {
    case SEC_ERROR_LIBRARY_FAILURE:     desc = unsupported_certificate; break;
    case SEC_ERROR_EXPIRED_CERTIFICATE: desc = certificate_expired;     break;
    case SEC_ERROR_REVOKED_CERTIFICATE: desc = certificate_revoked;     break;
    case SEC_ERROR_INADEQUATE_KEY_USAGE:
    case SEC_ERROR_INADEQUATE_CERT_TYPE:
                                      desc = certificate_unknown;     break;
    case SEC_ERROR_UNTRUSTED_CERT:
                  desc = isTLS ? access_denied : certificate_unknown; break;
    case SEC_ERROR_UNKNOWN_ISSUER:      
    case SEC_ERROR_UNTRUSTED_ISSUER:    
                  desc = isTLS ? unknown_ca : certificate_unknown; break;
    case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
                  desc = isTLS ? unknown_ca : certificate_expired; break;

    case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
    case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID:
    case SEC_ERROR_CA_CERT_INVALID:
    case SEC_ERROR_BAD_SIGNATURE:
    default:                            desc = bad_certificate;     break;
    }
    SSL_DBG(("%d: SSL3[%d]: peer certificate is no good: error=%d",
            SSL_GETPID(), ss->fd, errCode));

    goto alert_loser;

decode_loser:
    desc = isTLS ? decode_error : bad_certificate;

alert_loser:
    (void)SSL3_SendAlert(ss, alert_fatal, desc);

loser:
    ss->ssl3.peerCertChain = certs;  certs = NULL;  arena = NULL;
    ssl3_CleanupPeerCerts(ss);

    if (ss->sec.peerCert != NULL) {
       CERT_DestroyCertificate(ss->sec.peerCert);
       ss->sec.peerCert = NULL;
    }
    (void)ssl_MapLowLevelError(errCode);
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleCertificateRequest ( sslSocket *  ss,
SSL3Opaque b,
PRUint32  length 
) [static]

Definition at line 4925 of file ssl3con.c.

{
    PRArenaPool *        arena       = NULL;
    dnameNode *          node;
    PRInt32              remaining;
    PRBool               isTLS       = PR_FALSE;
    int                  i;
    int                  errCode     = SSL_ERROR_RX_MALFORMED_CERT_REQUEST;
    int                  nnames      = 0;
    SECStatus            rv;
    SSL3AlertDescription desc        = illegal_parameter;
    SECItem              cert_types  = {siBuffer, NULL, 0};
    CERTDistNames        ca_list;

    SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_request handshake",
              SSL_GETPID(), ss->fd));
    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    if (ss->ssl3.hs.ws != wait_cert_request &&
       ss->ssl3.hs.ws != wait_server_key) {
       desc    = unexpected_message;
       errCode = SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST;
       goto alert_loser;
    }

    /* clean up anything left from previous handshake. */
    if (ss->ssl3.clientCertChain != NULL) {
       CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
       ss->ssl3.clientCertChain = NULL;
    }
    if (ss->ssl3.clientCertificate != NULL) {
       CERT_DestroyCertificate(ss->ssl3.clientCertificate);
       ss->ssl3.clientCertificate = NULL;
    }
    if (ss->ssl3.clientPrivateKey != NULL) {
       SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
       ss->ssl3.clientPrivateKey = NULL;
    }

    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
    rv = ssl3_ConsumeHandshakeVariable(ss, &cert_types, 1, &b, &length);
    if (rv != SECSuccess)
       goto loser;          /* malformed, alert has been sent */

    arena = ca_list.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL)
       goto no_mem;

    remaining = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
    if (remaining < 0)
       goto loser;          /* malformed, alert has been sent */

    if ((PRUint32)remaining > length)
       goto alert_loser;

    ca_list.head = node = PORT_ArenaZNew(arena, dnameNode);
    if (node == NULL)
       goto no_mem;

    while (remaining > 0) {
       PRInt32 len;

       if (remaining < 2)
           goto alert_loser;       /* malformed */

       node->name.len = len = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
       if (len <= 0)
           goto loser;             /* malformed, alert has been sent */

       remaining -= 2;
       if (remaining < len)
           goto alert_loser;       /* malformed */

       node->name.data = b;
       b         += len;
       length    -= len;
       remaining -= len;
       nnames++;
       if (remaining <= 0)
           break;           /* success */

       node->next = PORT_ArenaZNew(arena, dnameNode);
       node = node->next;
       if (node == NULL)
           goto no_mem;
    }

    ca_list.nnames = nnames;
    ca_list.names  = PORT_ArenaNewArray(arena, SECItem, nnames);
    if (nnames > 0 && ca_list.names == NULL)
        goto no_mem;

    for(i = 0, node = (dnameNode*)ca_list.head;
       i < nnames;
       i++, node = node->next) {
       ca_list.names[i] = node->name;
    }

    if (length != 0)
        goto alert_loser;          /* malformed */

    desc = no_certificate;
    ss->ssl3.hs.ws = wait_hello_done;

    if (ss->getClientAuthData == NULL) {
       rv = SECFailure; /* force it to send a no_certificate alert */
    } else {
       /* XXX Should pass cert_types in this call!! */
       rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg,
                                           ss->fd, &ca_list,
                                           &ss->ssl3.clientCertificate,
                                           &ss->ssl3.clientPrivateKey);
    }
    switch (rv) {
    case SECWouldBlock:     /* getClientAuthData has put up a dialog box. */
       ssl_SetAlwaysBlock(ss);
       break; /* not an error */

    case SECSuccess:
        /* check what the callback function returned */
        if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) {
            /* we are missing either the key or cert */
            if (ss->ssl3.clientCertificate) {
                /* got a cert, but no key - free it */
                CERT_DestroyCertificate(ss->ssl3.clientCertificate);
                ss->ssl3.clientCertificate = NULL;
            }
            if (ss->ssl3.clientPrivateKey) {
                /* got a key, but no cert - free it */
                SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
                ss->ssl3.clientPrivateKey = NULL;
            }
            goto send_no_certificate;
        }
       /* Setting ssl3.clientCertChain non-NULL will cause
        * ssl3_HandleServerHelloDone to call SendCertificate.
        */
       ss->ssl3.clientCertChain = CERT_CertChainFromCert(
                                   ss->ssl3.clientCertificate,
                                   certUsageSSLClient, PR_FALSE);
       if (ss->ssl3.clientCertChain == NULL) {
           if (ss->ssl3.clientCertificate != NULL) {
              CERT_DestroyCertificate(ss->ssl3.clientCertificate);
              ss->ssl3.clientCertificate = NULL;
           }
           if (ss->ssl3.clientPrivateKey != NULL) {
              SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
              ss->ssl3.clientPrivateKey = NULL;
           }
           goto send_no_certificate;
       }
       break; /* not an error */

    case SECFailure:
    default:
send_no_certificate:
       if (isTLS) {
           ss->ssl3.sendEmptyCert = PR_TRUE;
       } else {
           (void)SSL3_SendAlert(ss, alert_warning, no_certificate);
       }
       rv = SECSuccess;
       break;
    }
    goto done;

no_mem:
    rv = SECFailure;
    PORT_SetError(SEC_ERROR_NO_MEMORY);
    goto done;

alert_loser:
    if (isTLS && desc == illegal_parameter)
       desc = decode_error;
    (void)SSL3_SendAlert(ss, alert_fatal, desc);
loser:
    PORT_SetError(errCode);
    rv = SECFailure;
done:
    if (arena != NULL)
       PORT_FreeArena(arena, PR_FALSE);
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleCertificateVerify ( sslSocket *  ss,
SSL3Opaque b,
PRUint32  length,
SSL3Hashes hashes 
) [static]

Definition at line 6294 of file ssl3con.c.

{
    SECItem              signed_hash = {siBuffer, NULL, 0};
    SECStatus            rv;
    int                  errCode     = SSL_ERROR_RX_MALFORMED_CERT_VERIFY;
    SSL3AlertDescription desc        = handshake_failure;
    PRBool               isTLS;

    SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_verify handshake",
              SSL_GETPID(), ss->fd));
    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    if (ss->ssl3.hs.ws != wait_cert_verify || ss->sec.peerCert == NULL) {
       desc    = unexpected_message;
       errCode = SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY;
       goto alert_loser;
    }

    rv = ssl3_ConsumeHandshakeVariable(ss, &signed_hash, 2, &b, &length);
    if (rv != SECSuccess) {
       goto loser;          /* malformed. */
    }

    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);

    /* XXX verify that the key & kea match */
    rv = ssl3_VerifySignedHashes(hashes, ss->sec.peerCert, &signed_hash,
                             isTLS, ss->pkcs11PinArg);
    if (rv != SECSuccess) {
       errCode = PORT_GetError();
       desc = isTLS ? decrypt_error : handshake_failure;
       goto alert_loser;
    }

    signed_hash.data = NULL;

    if (length != 0) {
       desc    = isTLS ? decode_error : illegal_parameter;
       goto alert_loser;    /* malformed */
    }
    ss->ssl3.hs.ws = wait_change_cipher;
    return SECSuccess;

alert_loser:
    SSL3_SendAlert(ss, alert_fatal, desc);
loser:
    PORT_SetError(errCode);
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleChangeCipherSpecs ( sslSocket *  ss,
sslBuffer *  buf 
) [static]

Definition at line 2477 of file ssl3con.c.

{
    ssl3CipherSpec *           prSpec;
    SSL3WaitState              ws      = ss->ssl3.hs.ws;
    SSL3ChangeCipherSpecChoice change;

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    SSL_TRC(3, ("%d: SSL3[%d]: handle change_cipher_spec record",
              SSL_GETPID(), ss->fd));

    if (ws != wait_change_cipher) {
       (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
       PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER);
       return SECFailure;
    }

    if(buf->len != 1) {
       (void)ssl3_DecodeError(ss);
       PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
       return SECFailure;
    }
    change = (SSL3ChangeCipherSpecChoice)buf->buf[0];
    if (change != change_cipher_spec_choice) {
       /* illegal_parameter is correct here for both SSL3 and TLS. */
       (void)ssl3_IllegalParameter(ss);
       PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
       return SECFailure;
    }
    buf->len = 0;

    /* Swap the pending and current read specs. */
    ssl_GetSpecWriteLock(ss);   /*************************************/
    prSpec                    = ss->ssl3.prSpec;
    prSpec->read_seq_num.high = prSpec->read_seq_num.low = 0;

    ss->ssl3.prSpec  = ss->ssl3.crSpec;
    ss->ssl3.crSpec  = prSpec;
    ss->ssl3.hs.ws   = wait_finished;

    SSL_TRC(3, ("%d: SSL3[%d] Set Current Read Cipher Suite to Pending",
              SSL_GETPID(), ss->fd ));

    /* If we are really through with the old cipher prSpec
     * (Both the read and write sides have changed) destroy it.
     */
    if (ss->ssl3.prSpec == ss->ssl3.pwSpec) {
       ssl3_DestroyCipherSpec(ss->ssl3.prSpec);
    }
    ssl_ReleaseSpecWriteLock(ss);   /*************************************/
    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleClientHello ( sslSocket *  ss,
SSL3Opaque b,
PRUint32  length 
) [static]

Definition at line 5398 of file ssl3con.c.

{
    sslSessionID *      sid      = NULL;
    PRInt32          tmp;
    unsigned int        i;
    int                 j;
    SECStatus           rv;
    int                 errCode  = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
    SSL3AlertDescription desc    = illegal_parameter;
    SSL3ProtocolVersion version;
    SECItem             sidBytes = {siBuffer, NULL, 0};
    SECItem             suites   = {siBuffer, NULL, 0};
    SECItem             comps    = {siBuffer, NULL, 0};
    PRBool              haveSpecWriteLock = PR_FALSE;
    PRBool              haveXmitBufLock   = PR_FALSE;

    SSL_TRC(3, ("%d: SSL3[%d]: handle client_hello handshake",
       SSL_GETPID(), ss->fd));

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));

    /* Get peer name of client */
    rv = ssl_GetPeerInfo(ss);
    if (rv != SECSuccess) {
       return rv;           /* error code is set. */
    }

    rv = ssl3_InitState(ss);
    if (rv != SECSuccess) {
       return rv;           /* ssl3_InitState has set the error code. */
    }

    if ((ss->ssl3.hs.ws != wait_client_hello) &&
       (ss->ssl3.hs.ws != idle_handshake)) {
       desc    = unexpected_message;
       errCode = SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO;
       goto alert_loser;
    }

    tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
    if (tmp < 0)
       goto loser;          /* malformed, alert already sent */
    ss->clientHelloVersion = version = (SSL3ProtocolVersion)tmp;
    rv = ssl3_NegotiateVersion(ss, version);
    if (rv != SECSuccess) {
       desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version : handshake_failure;
       errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
       goto alert_loser;
    }

    /* grab the client random data. */
    rv = ssl3_ConsumeHandshake(
       ss, &ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH, &b, &length);
    if (rv != SECSuccess) {
       goto loser;          /* malformed */
    }

    /* grab the client's SID, if present. */
    rv = ssl3_ConsumeHandshakeVariable(ss, &sidBytes, 1, &b, &length);
    if (rv != SECSuccess) {
       goto loser;          /* malformed */
    }

    if (sidBytes.len > 0 && !ss->opt.noCache) {
       SSL_TRC(7, ("%d: SSL3[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x",
                    SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0],
                  ss->sec.ci.peer.pr_s6_addr32[1], 
                  ss->sec.ci.peer.pr_s6_addr32[2],
                  ss->sec.ci.peer.pr_s6_addr32[3]));
       if (ssl_sid_lookup) {
           sid = (*ssl_sid_lookup)(&ss->sec.ci.peer, sidBytes.data, 
                                   sidBytes.len, ss->dbHandle);
       } else {
           errCode = SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED;
           goto loser;
       }
    }

    /* grab the list of cipher suites. */
    rv = ssl3_ConsumeHandshakeVariable(ss, &suites, 2, &b, &length);
    if (rv != SECSuccess) {
       goto loser;          /* malformed */
    }

    /* grab the list of compression methods. */
    rv = ssl3_ConsumeHandshakeVariable(ss, &comps, 1, &b, &length);
    if (rv != SECSuccess) {
       goto loser;          /* malformed */
    }

    desc = handshake_failure;

    if (sid != NULL) {
       /* We've found a session cache entry for this client.
        * Now, if we're going to require a client-auth cert,
        * and we don't already have this client's cert in the session cache,
        * and this is the first handshake on this connection (not a redo),
        * then drop this old cache entry and start a new session.
        */
       if ((sid->peerCert == NULL) && ss->opt.requestCertificate &&
           ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) ||
            (ss->opt.requireCertificate == SSL_REQUIRE_NO_ERROR) ||
            ((ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE) 
             && !ss->firstHsDone))) {

           SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_not_ok );
           ss->sec.uncache(sid);
           ssl_FreeSID(sid);
           sid = NULL;
       }
    }

#ifdef NSS_ENABLE_ECC
    /* Disable any ECC cipher suites for which we have no cert. */
    ssl3_FilterECCipherSuitesByServerCerts(ss);
#endif

#ifdef PARANOID
    /* Look for a matching cipher suite. */
    j = ssl3_config_match_init(ss);
    if (j <= 0) {           /* no ciphers are working/supported by PK11 */
       errCode = PORT_GetError();  /* error code is already set. */
       goto alert_loser;
    }
#endif

    /* If we already have a session for this client, be sure to pick the
    ** same cipher suite we picked before.
    ** This is not a loop, despite appearances.
    */
    if (sid) do {
       ssl3CipherSuiteCfg *suite = ss->cipherSuites;
       /* Find the entry for the cipher suite used in the cached session. */
       for (j = ssl_V3_SUITES_IMPLEMENTED; j > 0; --j, ++suite) {
           if (suite->cipher_suite == sid->u.ssl3.cipherSuite)
              break;
       }
       PORT_Assert(j > 0);
       if (j <= 0)
           break;
#ifdef PARANOID
       /* Double check that the cached cipher suite is still enabled,
        * implemented, and allowed by policy.  Might have been disabled.
        * The product policy won't change during the process lifetime.  
        * Implemented ("isPresent") shouldn't change for servers.
        */
       if (!config_match(suite, ss->ssl3.policy, PR_TRUE))
           break;
#else
       if (!suite->enabled)
           break;
#endif
       /* Double check that the cached cipher suite is in the client's list */
       for (i = 0; i < suites.len; i += 2) {
           if ((suites.data[i]     == MSB(suite->cipher_suite)) &&
               (suites.data[i + 1] == LSB(suite->cipher_suite))) {

              ss->ssl3.hs.cipher_suite = suite->cipher_suite;
              ss->ssl3.hs.suite_def =
                  ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
              goto suite_found;
           }
       }
    } while (0);

    /* START A NEW SESSION */

    /* Handle TLS hello extensions, for SSL3 & TLS, 
     * only if we're not restarting a previous session.
     */
    if (length) {
       /* Get length of hello extensions */
       PRInt32 extension_length;
       extension_length = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
        if (extension_length < 0) {
           goto loser;                           /* alert already sent */
       }
       if (extension_length != length) {
           ssl3_DecodeError(ss);          /* send alert */
           goto loser;
       }
       rv = ssl3_HandleClientHelloExtensions(ss, &b, &length);
       if (rv != SECSuccess) {
           goto loser;             /* malformed */
       }
    }

#ifndef PARANOID
    /* Look for a matching cipher suite. */
    j = ssl3_config_match_init(ss);
    if (j <= 0) {           /* no ciphers are working/supported by PK11 */
       errCode = PORT_GetError();  /* error code is already set. */
       goto alert_loser;
    }
#endif

    /* Select a cipher suite.
    ** NOTE: This suite selection algorithm should be the same as the one in
    ** ssl3_HandleV2ClientHello().  
    */
    for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
       ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
       if (!config_match(suite, ss->ssl3.policy, PR_TRUE))
           continue;
       for (i = 0; i < suites.len; i += 2) {
           if ((suites.data[i]     == MSB(suite->cipher_suite)) &&
               (suites.data[i + 1] == LSB(suite->cipher_suite))) {

              ss->ssl3.hs.cipher_suite = suite->cipher_suite;
              ss->ssl3.hs.suite_def =
                  ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
              goto suite_found;
           }
       }
    }
    errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
    goto alert_loser;

suite_found:
    /* Look for a matching compression algorithm. */
    for (i = 0; i < comps.len; i++) {
       for (j = 0; j < compressionMethodsCount; j++) {
           if (comps.data[i] == compressions[j]) {
              ss->ssl3.hs.compression = 
                                   (SSL3CompressionMethod)compressions[j];
              goto compression_found;
           }
       }
    }
    errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP;
                            /* null compression must be supported */
    goto alert_loser;

compression_found:
    suites.data = NULL;
    comps.data = NULL;

    ss->sec.send = ssl3_SendApplicationData;

    /* If there are any failures while processing the old sid,
     * we don't consider them to be errors.  Instead, We just behave
     * as if the client had sent us no sid to begin with, and make a new one.
     */
    if (sid != NULL) do {
       ssl3CipherSpec *pwSpec;
       SECItem         wrappedMS;         /* wrapped key */

       if (sid->version != ss->version  ||
           sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite) {
           break;    /* not an error */
       }

       if (ss->sec.ci.sid) {
           ss->sec.uncache(ss->sec.ci.sid);
           PORT_Assert(ss->sec.ci.sid != sid);  /* should be impossible, but ... */
           if (ss->sec.ci.sid != sid) {
              ssl_FreeSID(ss->sec.ci.sid);
           }
           ss->sec.ci.sid = NULL;
       }
       /* we need to resurrect the master secret.... */

       ssl_GetSpecWriteLock(ss);  haveSpecWriteLock = PR_TRUE;
       pwSpec = ss->ssl3.pwSpec;
       if (sid->u.ssl3.keys.msIsWrapped) {
           PK11SymKey *    wrapKey;       /* wrapping key */
           CK_FLAGS        keyFlags      = 0;
           if (ss->opt.bypassPKCS11) {
              /* we cannot restart a non-bypass session in a 
              ** bypass socket.
              */
              break;  
           }

           wrapKey = getWrappingKey(ss, NULL, sid->u.ssl3.exchKeyType,
                                 sid->u.ssl3.masterWrapMech, 
                                 ss->pkcs11PinArg);
           if (!wrapKey) {
              /* we have a SID cache entry, but no wrapping key for it??? */
              break;
           }

           if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
              keyFlags = CKF_SIGN | CKF_VERIFY;
           }

           wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
           wrappedMS.len  = sid->u.ssl3.keys.wrapped_master_secret_len;

           /* unwrap the master secret. */
           pwSpec->master_secret =
              PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, 
                         NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
                         CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags);
           PK11_FreeSymKey(wrapKey);
           if (pwSpec->master_secret == NULL) {
              break; /* not an error */
           }
       } else if (ss->opt.bypassPKCS11) {
           wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
           wrappedMS.len  = sid->u.ssl3.keys.wrapped_master_secret_len;
           memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len);
           pwSpec->msItem.data = pwSpec->raw_master_secret;
           pwSpec->msItem.len  = wrappedMS.len;
       } else {
           /* We CAN restart a bypass session in a non-bypass socket. */
           /* need to import the raw master secret to session object */
           PK11SlotInfo * slot;
           wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
           wrappedMS.len  = sid->u.ssl3.keys.wrapped_master_secret_len;
           slot = PK11_GetInternalSlot();
           pwSpec->master_secret =  
              PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, 
                              PK11_OriginUnwrap, CKA_ENCRYPT, &wrappedMS, 
                              NULL);
           PK11_FreeSlot(slot);
           if (pwSpec->master_secret == NULL) {
              break; /* not an error */
           }
       }
       ss->sec.ci.sid = sid;
       if (sid->peerCert != NULL) {
           ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
       }

       /*
        * Old SID passed all tests, so resume this old session.
        *
        * XXX make sure compression still matches
        */
       SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_hits );
       ss->ssl3.hs.isResuming = PR_TRUE;

        ss->sec.authAlgorithm = sid->authAlgorithm;
       ss->sec.authKeyBits   = sid->authKeyBits;
       ss->sec.keaType       = sid->keaType;
       ss->sec.keaKeyBits    = sid->keaKeyBits;

       /* server sids don't remember the server cert we previously sent,
       ** but they do remember the kea type we originally used, so we
       ** can locate it again, provided that the current ssl socket
       ** has had its server certs configured the same as the previous one.
       */
       ss->sec.localCert     = 
              CERT_DupCertificate(ss->serverCerts[sid->keaType].serverCert);

       ssl_GetXmitBufLock(ss); haveXmitBufLock = PR_TRUE;

       rv = ssl3_SendServerHello(ss);
       if (rv != SECSuccess) {
           errCode = PORT_GetError();
           goto loser;
       }

       if (haveSpecWriteLock) {
           ssl_ReleaseSpecWriteLock(ss);
           haveSpecWriteLock = PR_FALSE;
       }

       /* NULL value for PMS signifies re-use of the old MS */
       rv = ssl3_InitPendingCipherSpec(ss,  NULL);
       if (rv != SECSuccess) {
           errCode = PORT_GetError();
           goto loser;
       }

       rv = ssl3_SendChangeCipherSpecs(ss);
       if (rv != SECSuccess) {
           errCode = PORT_GetError();
           goto loser;
       }
       rv = ssl3_SendFinished(ss, 0);
       ss->ssl3.hs.ws = wait_change_cipher;
       if (rv != SECSuccess) {
           errCode = PORT_GetError();
           goto loser;
       }

       if (haveXmitBufLock) {
           ssl_ReleaseXmitBufLock(ss);
           haveXmitBufLock = PR_FALSE;
       }

        return SECSuccess;
    } while (0);

    if (haveSpecWriteLock) {
       ssl_ReleaseSpecWriteLock(ss);
       haveSpecWriteLock = PR_FALSE;
    }

    if (sid) {       /* we had a sid, but it's no longer valid, free it */
       SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_not_ok );
       ss->sec.uncache(sid);
       ssl_FreeSID(sid);
       sid = NULL;
    }
    SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_misses );

    sid = ssl3_NewSessionID(ss, PR_TRUE);
    if (sid == NULL) {
       errCode = PORT_GetError();
       goto loser;   /* memory error is set. */
    }
    ss->sec.ci.sid = sid;

    ss->ssl3.hs.isResuming = PR_FALSE;
    ssl_GetXmitBufLock(ss);
    rv = ssl3_SendServerHelloSequence(ss);
    ssl_ReleaseXmitBufLock(ss);
    if (rv != SECSuccess) {
       errCode = PORT_GetError();
       goto loser;
    }

    if (haveXmitBufLock) {
       ssl_ReleaseXmitBufLock(ss);
       haveXmitBufLock = PR_FALSE;
    }

    return SECSuccess;

alert_loser:
    if (haveSpecWriteLock) {
       ssl_ReleaseSpecWriteLock(ss);
       haveSpecWriteLock = PR_FALSE;
    }
    (void)SSL3_SendAlert(ss, alert_fatal, desc);
    /* FALLTHRU */
loser:
    if (haveSpecWriteLock) {
       ssl_ReleaseSpecWriteLock(ss);
       haveSpecWriteLock = PR_FALSE;
    }

    if (haveXmitBufLock) {
       ssl_ReleaseXmitBufLock(ss);
       haveXmitBufLock = PR_FALSE;
    }

    PORT_SetError(errCode);
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleClientKeyExchange ( sslSocket *  ss,
SSL3Opaque b,
PRUint32  length 
) [static]

Definition at line 6542 of file ssl3con.c.

{
    SECKEYPrivateKey *serverKey         = NULL;
    SECStatus         rv;
const ssl3KEADef *    kea_def;
    ssl3KeyPair     *serverKeyPair      = NULL;
#ifdef NSS_ENABLE_ECC
    SECKEYPublicKey *serverPubKey       = NULL;
#endif /* NSS_ENABLE_ECC */

    SSL_TRC(3, ("%d: SSL3[%d]: handle client_key_exchange handshake",
              SSL_GETPID(), ss->fd));

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    if (ss->ssl3.hs.ws != wait_client_key) {
       SSL3_SendAlert(ss, alert_fatal, unexpected_message);
       PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH);
       return SECFailure;
    }

    kea_def   = ss->ssl3.hs.kea_def;

    if (ss->ssl3.hs.usedStepDownKey) {
        PORT_Assert(kea_def->is_limited /* XXX OR cert is signing only */
               && kea_def->exchKeyType == kt_rsa 
               && ss->stepDownKeyPair != NULL);
        if (!kea_def->is_limited  ||
             kea_def->exchKeyType != kt_rsa ||
             ss->stepDownKeyPair == NULL) {
              /* shouldn't happen, don't use step down if it does */
              goto skip;
        }
       serverKeyPair = ss->stepDownKeyPair;
       ss->sec.keaKeyBits = EXPORT_RSA_KEY_LENGTH * BPB;
    } else 
skip:
#ifdef NSS_ENABLE_ECC
    /* XXX Using SSLKEAType to index server certifiates
     * does not work for (EC)DHE ciphers. Until we have
     * an indexing mechanism general enough for all key
     * exchange algorithms, we'll need to deal with each
     * one seprately.
     */
    if ((kea_def->kea == kea_ecdhe_rsa) ||
               (kea_def->kea == kea_ecdhe_ecdsa)) {
       if (ss->ephemeralECDHKeyPair != NULL) {
          serverKeyPair = ss->ephemeralECDHKeyPair;
          if (serverKeyPair->pubKey) {
              ss->sec.keaKeyBits = 
                  SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey);
          }
       }
    } else 
#endif
    {
       sslServerCerts * sc = ss->serverCerts + kea_def->exchKeyType;
       serverKeyPair = sc->serverKeyPair;
       ss->sec.keaKeyBits = sc->serverKeyBits;
    }

    if (serverKeyPair) {
       serverKey = serverKeyPair->privKey;
    }

    if (serverKey == NULL) {
       SEND_ALERT
       PORT_SetError(SSL_ERROR_NO_SERVER_KEY_FOR_ALG);
       return SECFailure;
    }

    ss->sec.keaType    = kea_def->exchKeyType;

    switch (kea_def->exchKeyType) {
    case kt_rsa:
       rv = ssl3_HandleRSAClientKeyExchange(ss, b, length, serverKey);
       if (rv != SECSuccess) {
           SEND_ALERT
           return SECFailure;      /* error code set */
       }
       break;


#ifdef NSS_ENABLE_ECC
    case kt_ecdh:
       /* XXX We really ought to be able to store multiple
        * EC certs (a requirement if we wish to support both
        * ECDH-RSA and ECDH-ECDSA key exchanges concurrently).
        * When we make that change, we'll need an index other
        * than kt_ecdh to pick the right EC certificate.
        */
       if (serverKeyPair) {
           serverPubKey = serverKeyPair->pubKey;
        }
       if (serverPubKey == NULL) {
           /* XXX Is this the right error code? */
           PORT_SetError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
           return SECFailure;
       }
       rv = ssl3_HandleECDHClientKeyExchange(ss, b, length, 
                                         serverPubKey, serverKey);
       if (rv != SECSuccess) {
           return SECFailure;      /* error code set */
       }
       break;
#endif /* NSS_ENABLE_ECC */

    default:
       (void) ssl3_HandshakeFailure(ss);
       PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
       return SECFailure;
    }
    ss->ssl3.hs.ws = ss->sec.peerCert ? wait_cert_verify : wait_change_cipher;
    return SECSuccess;

}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleFinished ( sslSocket *  ss,
SSL3Opaque b,
PRUint32  length,
const SSL3Hashes hashes 
) [static]

Definition at line 7413 of file ssl3con.c.

{
    sslSessionID *    sid      = ss->sec.ci.sid;
    SECStatus         rv           = SECSuccess;
    PRBool            isServer     = ss->sec.isServer;
    PRBool            isTLS;
    PRBool            doStepUp;
    SSL3KEAType       effectiveExchKeyType;

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    SSL_TRC(3, ("%d: SSL3[%d]: handle finished handshake",
       SSL_GETPID(), ss->fd));

    if (ss->ssl3.hs.ws != wait_finished) {
       SSL3_SendAlert(ss, alert_fatal, unexpected_message);
       PORT_SetError(SSL_ERROR_RX_UNEXPECTED_FINISHED);
       return SECFailure;
    }

    isTLS = (PRBool)(ss->ssl3.crSpec->version > SSL_LIBRARY_VERSION_3_0);
    if (isTLS) {
       TLSFinished tlsFinished;

       if (length != sizeof tlsFinished) {
           (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
           PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED);
           return SECFailure;
       }
       rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer, 
                                    hashes, &tlsFinished);
       if (rv != SECSuccess ||
           0 != PORT_Memcmp(&tlsFinished, b, length)) {
           (void)SSL3_SendAlert(ss, alert_fatal, decrypt_error);
           PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
           return SECFailure;
       }
    } else {
       if (length != sizeof(SSL3Hashes)) {
           (void)ssl3_IllegalParameter(ss);
           PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED);
           return SECFailure;
       }

       if (0 != PORT_Memcmp(hashes, b, length)) {
           (void)ssl3_HandshakeFailure(ss);
           PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
           return SECFailure;
       }
    }

    doStepUp = (PRBool)(!isServer && ss->ssl3.hs.rehandshake);

    ssl_GetXmitBufLock(ss); /*************************************/

    if ((isServer && !ss->ssl3.hs.isResuming) ||
       (!isServer && ss->ssl3.hs.isResuming)) {
       PRInt32 flags = 0;

       rv = ssl3_SendChangeCipherSpecs(ss);
       if (rv != SECSuccess) {
           goto xmit_loser; /* err is set. */
       }
       /* If this thread is in SSL_SecureSend (trying to write some data) 
       ** or if it is going to step up, 
       ** then set the ssl_SEND_FLAG_FORCE_INTO_BUFFER flag, so that the 
       ** last two handshake messages (change cipher spec and finished) 
       ** will be sent in the same send/write call as the application data.
       */
       if (doStepUp || ss->writerThread == PR_GetCurrentThread()) {
           flags = ssl_SEND_FLAG_FORCE_INTO_BUFFER;
       }
       rv = ssl3_SendFinished(ss, flags);
       if (rv != SECSuccess) {
           goto xmit_loser; /* err is set. */
       }
    }

    /* Optimization: don't cache this connection if we're going to step up. */
    if (doStepUp) {
       ssl_FreeSID(sid);
       ss->sec.ci.sid     = sid = NULL;
       ss->ssl3.hs.rehandshake = PR_FALSE;
       rv = ssl3_SendClientHello(ss);
xmit_loser:
       ssl_ReleaseXmitBufLock(ss);
       return rv;    /* err code is set if appropriate. */
    }

    ssl_ReleaseXmitBufLock(ss);    /*************************************/

    /* The first handshake is now completed. */
    ss->handshake           = NULL;
    ss->firstHsDone         = PR_TRUE;
    ss->gs.writeOffset = 0;
    ss->gs.readOffset  = 0;

    if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) {
       effectiveExchKeyType = kt_rsa;
    } else {
       effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
    }

    if (sid->cached == never_cached && !ss->opt.noCache && ss->sec.cache) {
       /* fill in the sid */
       sid->u.ssl3.cipherSuite = ss->ssl3.hs.cipher_suite;
       sid->u.ssl3.compression = ss->ssl3.hs.compression;
       sid->u.ssl3.policy      = ss->ssl3.policy;
#ifdef NSS_ENABLE_ECC
       sid->u.ssl3.negotiatedECCurves = ss->ssl3.hs.negotiatedECCurves;
#endif
       sid->u.ssl3.exchKeyType = effectiveExchKeyType;
       sid->version            = ss->version;
       sid->authAlgorithm      = ss->sec.authAlgorithm;
       sid->authKeyBits        = ss->sec.authKeyBits;
       sid->keaType            = ss->sec.keaType;
       sid->keaKeyBits         = ss->sec.keaKeyBits;
       sid->lastAccessTime     = sid->creationTime = ssl_Time();
       sid->expirationTime     = sid->creationTime + ssl3_sid_timeout;
       sid->localCert          = CERT_DupCertificate(ss->sec.localCert);

       ssl_GetSpecReadLock(ss);    /*************************************/

       /* Copy the master secret (wrapped or unwrapped) into the sid */
       if (ss->ssl3.crSpec->msItem.len && ss->ssl3.crSpec->msItem.data) {
           sid->u.ssl3.keys.wrapped_master_secret_len = 
                         ss->ssl3.crSpec->msItem.len;
           memcpy(sid->u.ssl3.keys.wrapped_master_secret, 
                 ss->ssl3.crSpec->msItem.data, ss->ssl3.crSpec->msItem.len);
           sid->u.ssl3.masterValid    = PR_TRUE;
           sid->u.ssl3.keys.msIsWrapped = PR_FALSE;
           rv = SECSuccess;
       } else {
           rv = ssl3_CacheWrappedMasterSecret(ss, effectiveExchKeyType);
           sid->u.ssl3.keys.msIsWrapped = PR_TRUE;
       }
       ssl_ReleaseSpecReadLock(ss);  /*************************************/

       /* If the wrap failed, we don't cache the sid.
        * The connection continues normally however.
        */
       if (rv == SECSuccess) {
           (*ss->sec.cache)(sid);
       }
    }
    ss->ssl3.hs.ws = idle_handshake;

    /* Do the handshake callback for sslv3 here. */
    if (ss->handshakeCallback != NULL) {
       (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
    }

    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleHandshake ( sslSocket *  ss,
sslBuffer *  origBuf 
) [static]

Definition at line 7738 of file ssl3con.c.

{
    /*
     * There may be a partial handshake message already in the handshake
     * state. The incoming buffer may contain another portion, or a
     * complete message or several messages followed by another portion.
     *
     * Each message is made contiguous before being passed to the actual
     * message parser.
     */
    sslBuffer *buf = &ss->ssl3.hs.msgState; /* do not lose the original buffer pointer */
    SECStatus rv;

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    if (buf->buf == NULL) {
       *buf = *origBuf;
    }
    while (buf->len > 0) {
       if (ss->ssl3.hs.header_bytes < 4) {
           uint8 t;
           t = *(buf->buf++);
           buf->len--;
           if (ss->ssl3.hs.header_bytes++ == 0)
              ss->ssl3.hs.msg_type = (SSL3HandshakeType)t;
           else
              ss->ssl3.hs.msg_len = (ss->ssl3.hs.msg_len << 8) + t;
           if (ss->ssl3.hs.header_bytes < 4)
              continue;

#define MAX_HANDSHAKE_MSG_LEN 0x1ffff     /* 128k - 1 */
           if (ss->ssl3.hs.msg_len > MAX_HANDSHAKE_MSG_LEN) {
              (void)ssl3_DecodeError(ss);
              PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
              return SECFailure;
           }
#undef MAX_HANDSHAKE_MSG_LEN

           /* If msg_len is zero, be sure we fall through, 
           ** even if buf->len is zero. 
           */
           if (ss->ssl3.hs.msg_len > 0) 
              continue;
       }

       /*
        * Header has been gathered and there is at least one byte of new
        * data available for this message. If it can be done right out
        * of the original buffer, then use it from there.
        */
       if (ss->ssl3.hs.msg_body.len == 0 && buf->len >= ss->ssl3.hs.msg_len) {
           /* handle it from input buffer */
           rv = ssl3_HandleHandshakeMessage(ss, buf->buf, ss->ssl3.hs.msg_len);
           if (rv == SECFailure) {
              /* This test wants to fall through on either
               * SECSuccess or SECWouldBlock.
               * ssl3_HandleHandshakeMessage MUST set the error code.
               */
              return rv;
           }
           buf->buf += ss->ssl3.hs.msg_len;
           buf->len -= ss->ssl3.hs.msg_len;
           ss->ssl3.hs.msg_len = 0;
           ss->ssl3.hs.header_bytes = 0;
           if (rv != SECSuccess) { /* return if SECWouldBlock. */
              return rv;
           }
       } else {
           /* must be copied to msg_body and dealt with from there */
           unsigned int bytes;

           PORT_Assert(ss->ssl3.hs.msg_body.len <= ss->ssl3.hs.msg_len);
           bytes = PR_MIN(buf->len, ss->ssl3.hs.msg_len - ss->ssl3.hs.msg_body.len);

           /* Grow the buffer if needed */
           rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, ss->ssl3.hs.msg_len);
           if (rv != SECSuccess) {
              /* sslBuffer_Grow has set a memory error code. */
              return SECFailure;
           }

           PORT_Memcpy(ss->ssl3.hs.msg_body.buf + ss->ssl3.hs.msg_body.len,
                      buf->buf, bytes);
           ss->ssl3.hs.msg_body.len += bytes;
           buf->buf += bytes;
           buf->len -= bytes;

           PORT_Assert(ss->ssl3.hs.msg_body.len <= ss->ssl3.hs.msg_len);

           /* if we have a whole message, do it */
           if (ss->ssl3.hs.msg_body.len == ss->ssl3.hs.msg_len) {
              rv = ssl3_HandleHandshakeMessage(
                  ss, ss->ssl3.hs.msg_body.buf, ss->ssl3.hs.msg_len);
              /*
               * XXX This appears to be wrong.  This error handling
               * should clean up after a SECWouldBlock return, like the
               * error handling used 40 lines before/above this one,
               */
              if (rv != SECSuccess) {
                  /* ssl3_HandleHandshakeMessage MUST set error code. */
                  return rv;
              }
              ss->ssl3.hs.msg_body.len = 0;
              ss->ssl3.hs.msg_len      = 0;
              ss->ssl3.hs.header_bytes = 0;
           } else {
              PORT_Assert(buf->len == 0);
              break;
           }
       }
    }  /* end loop */

    origBuf->len = 0;       /* So ssl3_GatherAppDataRecord will keep looping. */
    buf->buf = NULL; /* not a leak. */
    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleHandshakeMessage ( sslSocket *  ss,
SSL3Opaque b,
PRUint32  length 
) [static]

Definition at line 7575 of file ssl3con.c.

{
    SECStatus         rv    = SECSuccess;
    SSL3HandshakeType type  = ss->ssl3.hs.msg_type;
    SSL3Hashes        hashes;      /* computed hashes are put here. */
    PRUint8           hdr[4];

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
    /*
     * We have to compute the hashes before we update them with the
     * current message.
     */
    ssl_GetSpecReadLock(ss);       /************************************/
    if((type == finished) || (type == certificate_verify)) {
       SSL3Sender      sender = (SSL3Sender)0;
       ssl3CipherSpec *rSpec  = ss->ssl3.prSpec;

       if (type == finished) {
           sender = ss->sec.isServer ? sender_client : sender_server;
           rSpec  = ss->ssl3.crSpec;
       }
       rv = ssl3_ComputeHandshakeHashes(ss, rSpec, &hashes, sender);
    }
    ssl_ReleaseSpecReadLock(ss); /************************************/
    if (rv != SECSuccess) {
       return rv;    /* error code was set by ssl3_ComputeHandshakeHashes*/
    }
    SSL_TRC(30,("%d: SSL3[%d]: handle handshake message: %s", SSL_GETPID(),
              ss->fd, ssl3_DecodeHandshakeType(ss->ssl3.hs.msg_type)));
    PRINT_BUF(60, (ss, "MD5 handshake hash:",
             (unsigned char*)ss->ssl3.hs.md5_cx, MD5_LENGTH));
    PRINT_BUF(95, (ss, "SHA handshake hash:",
             (unsigned char*)ss->ssl3.hs.sha_cx, SHA1_LENGTH));

    hdr[0] = (PRUint8)ss->ssl3.hs.msg_type;
    hdr[1] = (PRUint8)(length >> 16);
    hdr[2] = (PRUint8)(length >>  8);
    hdr[3] = (PRUint8)(length      );

    /* Start new handshake hashes when we start a new handshake */
    if (ss->ssl3.hs.msg_type == client_hello) {
       SSL_TRC(30,("%d: SSL3[%d]: reset handshake hashes",
              SSL_GETPID(), ss->fd ));
       if (ss->opt.bypassPKCS11) {
           MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx);
           SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx);
       } else {
           rv = PK11_DigestBegin(ss->ssl3.hs.md5);
           if (rv != SECSuccess) {
              ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
              return rv;
           }
           rv = PK11_DigestBegin(ss->ssl3.hs.sha);
           if (rv != SECSuccess) {
              ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
              return rv;
           }
       }
    }
    /* We should not include hello_request messages in the handshake hashes */
    if (ss->ssl3.hs.msg_type != hello_request) {
       rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char*) hdr, 4);
       if (rv != SECSuccess) return rv;   /* err code already set. */
       rv = ssl3_UpdateHandshakeHashes(ss, b, length);
       if (rv != SECSuccess) return rv;   /* err code already set. */
    }

    PORT_SetError(0);       /* each message starts with no error. */
    switch (ss->ssl3.hs.msg_type) {
    case hello_request:
       if (length != 0) {
           (void)ssl3_DecodeError(ss);
           PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST);
           return SECFailure;
       }
       if (ss->sec.isServer) {
           (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
           PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST);
           return SECFailure;
       }
       rv = ssl3_HandleHelloRequest(ss);
       break;
    case client_hello:
       if (!ss->sec.isServer) {
           (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
           PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO);
           return SECFailure;
       }
       rv = ssl3_HandleClientHello(ss, b, length);
       break;
    case server_hello:
       if (ss->sec.isServer) {
           (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
           PORT_SetError(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO);
           return SECFailure;
       }
       rv = ssl3_HandleServerHello(ss, b, length);
       break;
    case certificate:
       rv = ssl3_HandleCertificate(ss, b, length);
       break;
    case server_key_exchange:
       if (ss->sec.isServer) {
           (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
           PORT_SetError(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH);
           return SECFailure;
       }
       rv = ssl3_HandleServerKeyExchange(ss, b, length);
       break;
    case certificate_request:
       if (ss->sec.isServer) {
           (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
           PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST);
           return SECFailure;
       }
       rv = ssl3_HandleCertificateRequest(ss, b, length);
       break;
    case server_hello_done:
       if (length != 0) {
           (void)ssl3_DecodeError(ss);
           PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_DONE);
           return SECFailure;
       }
       if (ss->sec.isServer) {
           (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
           PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
           return SECFailure;
       }
       rv = ssl3_HandleServerHelloDone(ss);
       break;
    case certificate_verify:
       if (!ss->sec.isServer) {
           (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
           PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY);
           return SECFailure;
       }
       rv = ssl3_HandleCertificateVerify(ss, b, length, &hashes);
       break;
    case client_key_exchange:
       if (!ss->sec.isServer) {
           (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
           PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH);
           return SECFailure;
       }
       rv = ssl3_HandleClientKeyExchange(ss, b, length);
       break;
    case finished:
        rv = ssl3_HandleFinished(ss, b, length, &hashes);
       break;
    default:
       (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
       PORT_SetError(SSL_ERROR_RX_UNKNOWN_HANDSHAKE);
       rv = SECFailure;
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleHelloRequest ( sslSocket *  ss) [static]

Definition at line 3642 of file ssl3con.c.

{
    sslSessionID *sid = ss->sec.ci.sid;
    SECStatus     rv;

    SSL_TRC(3, ("%d: SSL3[%d]: handle hello_request handshake",
              SSL_GETPID(), ss->fd));

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    if (ss->ssl3.hs.ws == wait_server_hello)
       return SECSuccess;
    if (ss->ssl3.hs.ws != idle_handshake || ss->sec.isServer) {
       (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
       PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST);
       return SECFailure;
    }
    if (sid) {
       ss->sec.uncache(sid);
       ssl_FreeSID(sid);
       ss->sec.ci.sid = NULL;
    }

    ssl_GetXmitBufLock(ss);
    rv = ssl3_SendClientHello(ss);
    ssl_ReleaseXmitBufLock(ss);

    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleNoCertificate ( sslSocket *  ss) [static]

Definition at line 2175 of file ssl3con.c.

{
    if (ss->sec.peerCert != NULL) {
       if (ss->sec.peerKey != NULL) {
           SECKEY_DestroyPublicKey(ss->sec.peerKey);
           ss->sec.peerKey = NULL;
       }
       CERT_DestroyCertificate(ss->sec.peerCert);
       ss->sec.peerCert = NULL;
    }
    ssl3_CleanupPeerCerts(ss);

    /* If the server has required client-auth blindly but doesn't
     * actually look at the certificate it won't know that no
     * certificate was presented so we shutdown the socket to ensure
     * an error.  We only do this if we haven't already completed the
     * first handshake because if we're redoing the handshake we 
     * know the server is paying attention to the certificate.
     */
    if ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) ||
       (!ss->firstHsDone && 
        (ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE))) {
       PRFileDesc * lower;

       ss->sec.uncache(ss->sec.ci.sid);
       SSL3_SendAlert(ss, alert_fatal, bad_certificate);

       lower = ss->fd->lower;
#ifdef _WIN32
       lower->methods->shutdown(lower, PR_SHUTDOWN_SEND);
#else
       lower->methods->shutdown(lower, PR_SHUTDOWN_BOTH);
#endif
       PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
       return SECFailure;
    }
    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus ssl3_HandleRecord ( sslSocket *  ss,
SSL3Ciphertext cText,
sslBuffer *  databuf 
)

Definition at line 7880 of file ssl3con.c.

{
const ssl3BulkCipherDef *cipher_def;
    ssl3CipherSpec *     crSpec;
    SECStatus            rv;
    unsigned int         hashBytes        = MAX_MAC_LENGTH + 1;
    unsigned int         padding_length;
    PRBool               isTLS;
    PRBool               padIsBad               = PR_FALSE;
    SSL3ContentType      rType;
    SSL3Opaque           hash[MAX_MAC_LENGTH];

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );

    if (!ss->ssl3.initialized) {
       ssl_GetSSL3HandshakeLock(ss);
       rv = ssl3_InitState(ss);
       ssl_ReleaseSSL3HandshakeLock(ss);
       if (rv != SECSuccess) {
           return rv;              /* ssl3_InitState has set the error code. */
       }
    }

    /* check for Token Presence */
    if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) {
       PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
       return SECFailure;
    }

    /* cText is NULL when we're called from ssl3_RestartHandshakeAfterXXX().
     * This implies that databuf holds a previously deciphered SSL Handshake
     * message.
     */
    if (cText == NULL) {
       SSL_DBG(("%d: SSL3[%d]: HandleRecord, resuming handshake",
               SSL_GETPID(), ss->fd));
       rType = content_handshake;
       goto process_it;
    }

    databuf->len = 0; /* filled in by decode call below. */
    if (databuf->space < MAX_FRAGMENT_LENGTH) {
       rv = sslBuffer_Grow(databuf, MAX_FRAGMENT_LENGTH + 2048);
       if (rv != SECSuccess) {
           SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes",
                   SSL_GETPID(), ss->fd, MAX_FRAGMENT_LENGTH + 2048));
           /* sslBuffer_Grow has set a memory error code. */
           /* Perhaps we should send an alert. (but we have no memory!) */
           return SECFailure;
       }
    }

    PRINT_BUF(80, (ss, "ciphertext:", cText->buf->buf, cText->buf->len));

    ssl_GetSpecReadLock(ss); /******************************************/

    crSpec = ss->ssl3.crSpec;
    cipher_def = crSpec->cipher_def;
    isTLS = (PRBool)(crSpec->version > SSL_LIBRARY_VERSION_3_0);

    if (isTLS && cText->buf->len > (MAX_FRAGMENT_LENGTH + 2048)) {
       ssl_ReleaseSpecReadLock(ss);
       SSL3_SendAlert(ss, alert_fatal, record_overflow);
       PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
       return SECFailure;
    }
    /* decrypt from cText buf to databuf. */
    rv = crSpec->decode(
       crSpec->decodeContext, databuf->buf, (int *)&databuf->len,
       databuf->space, cText->buf->buf, cText->buf->len);

    PRINT_BUF(80, (ss, "cleartext:", databuf->buf, databuf->len));
    if (rv != SECSuccess) {
       int err = ssl_MapLowLevelError(SSL_ERROR_DECRYPTION_FAILURE);
       ssl_ReleaseSpecReadLock(ss);
       SSL3_SendAlert(ss, alert_fatal,
                      isTLS ? decryption_failed : bad_record_mac);
       PORT_SetError(err);
       return SECFailure;
    }

    /* If it's a block cipher, check and strip the padding. */
    if (cipher_def->type == type_block) {
       padding_length = *(databuf->buf + databuf->len - 1);
       /* TLS permits padding to exceed the block size, up to 255 bytes. */
       if (padding_length + 1 + crSpec->mac_size > databuf->len)
           padIsBad = PR_TRUE;
       /* if TLS, check value of first padding byte. */
       else if (padding_length && isTLS && 
                padding_length != 
                        *(databuf->buf + databuf->len - (padding_length + 1)))
           padIsBad = PR_TRUE;
       else
           databuf->len -= padding_length + 1;
    }

    /* Remove the MAC. */
    if (databuf->len >= crSpec->mac_size)
       databuf->len -= crSpec->mac_size;
    else
       padIsBad = PR_TRUE;  /* really macIsBad */

    /* compute the MAC */
    rType = cText->type;
    rv = ssl3_ComputeRecordMAC( crSpec, (PRBool)(!ss->sec.isServer),
       rType, cText->version, crSpec->read_seq_num, 
       databuf->buf, databuf->len, hash, &hashBytes);
    if (rv != SECSuccess) {
       int err = ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
       ssl_ReleaseSpecReadLock(ss);
       SSL3_SendAlert(ss, alert_fatal, bad_record_mac);
       PORT_SetError(err);
       return rv;
    }

    /* Check the MAC */
    if (hashBytes != (unsigned)crSpec->mac_size || padIsBad || 
       PORT_Memcmp(databuf->buf + databuf->len, hash, crSpec->mac_size) != 0) {
       /* must not hold spec lock when calling SSL3_SendAlert. */
       ssl_ReleaseSpecReadLock(ss);
       SSL3_SendAlert(ss, alert_fatal, bad_record_mac);
       /* always log mac error, in case attacker can read server logs. */
       PORT_SetError(SSL_ERROR_BAD_MAC_READ);

       SSL_DBG(("%d: SSL3[%d]: mac check failed", SSL_GETPID(), ss->fd));

       return SECFailure;
    }

    ssl3_BumpSequenceNumber(&crSpec->read_seq_num);

    ssl_ReleaseSpecReadLock(ss); /*****************************************/

    /*
     * The decrypted data is now in databuf.
     *
     * the null decompression routine is right here
     */

    /*
    ** Having completed the decompression, check the length again. 
    */
    if (isTLS && databuf->len > (MAX_FRAGMENT_LENGTH + 1024)) {
       SSL3_SendAlert(ss, alert_fatal, record_overflow);
       PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
       return SECFailure;
    }

    /* Application data records are processed by the caller of this
    ** function, not by this function.
    */
    if (rType == content_application_data) {
       return SECSuccess;
    }

    /* It's a record that must be handled by ssl itself, not the application.
    */
process_it:
    /* XXX  Get the xmit lock here.  Odds are very high that we'll be xmiting
     * data ang getting the xmit lock here prevents deadlocks.
     */
    ssl_GetSSL3HandshakeLock(ss);

    /* All the functions called in this switch MUST set error code if
    ** they return SECFailure or SECWouldBlock.
    */
    switch (rType) {
    case content_change_cipher_spec:
       rv = ssl3_HandleChangeCipherSpecs(ss, databuf);
       break;
    case content_alert:
       rv = ssl3_HandleAlert(ss, databuf);
       break;
    case content_handshake:
       rv = ssl3_HandleHandshake(ss, databuf);
       break;
    /*
    case content_application_data is handled before this switch
    */
    default:
       SSL_DBG(("%d: SSL3[%d]: bogus content type=%d",
               SSL_GETPID(), ss->fd, cText->type));
       /* XXX Send an alert ???  */
       PORT_SetError(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE);
       rv = SECFailure;
       break;
    }

    ssl_ReleaseSSL3HandshakeLock(ss);
    return rv;

}

Here is the call graph for this function:

static SECStatus ssl3_HandleRSAClientKeyExchange ( sslSocket *  ss,
SSL3Opaque b,
PRUint32  length,
SECKEYPrivateKey *  serverKey 
) [static]

Definition at line 6427 of file ssl3con.c.

{
    PK11SymKey *      pms;
    unsigned char *   cr     = (unsigned char *)&ss->ssl3.hs.client_random;
    unsigned char *   sr     = (unsigned char *)&ss->ssl3.hs.server_random;
    ssl3CipherSpec *  pwSpec = ss->ssl3.pwSpec;
    unsigned int      outLen = 0;
    PRBool            isTLS  = PR_FALSE;
    SECStatus         rv;
    SECItem           enc_pms;
    unsigned char     rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
    SECItem           pmsItem = {siBuffer, rsaPmsBuf, sizeof rsaPmsBuf};

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    enc_pms.data = b;
    enc_pms.len  = length;

    if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
       PRInt32 kLen;
       kLen = ssl3_ConsumeHandshakeNumber(ss, 2, &enc_pms.data, &enc_pms.len);
       if (kLen < 0) {
           PORT_SetError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
           return SECFailure;
       }
       if ((unsigned)kLen < enc_pms.len) {
           enc_pms.len = kLen;
       }
       isTLS = PR_TRUE;
    } else {
       isTLS = (PRBool)(ss->ssl3.hs.kea_def->tls_keygen != 0);
    }

    if (ss->opt.bypassPKCS11) {
       /* TRIPLE BYPASS, get PMS directly from RSA decryption.
        * Use PK11_PrivDecryptPKCS1 to decrypt the PMS to a buffer, 
        * then, check for version rollback attack, then 
        * do the equivalent of ssl3_DeriveMasterSecret, placing the MS in 
        * pwSpec->msItem.  Finally call ssl3_InitPendingCipherSpec with 
        * ss and NULL, so that it will use the MS we've already derived here. 
        */

       rv = PK11_PrivDecryptPKCS1(serverKey, rsaPmsBuf, &outLen, 
                               sizeof rsaPmsBuf, enc_pms.data, enc_pms.len);
       if (rv != SECSuccess) {
           /* avoid Bleichenbacker attack.  generate faux pms. */
           rv = PK11_GenerateRandom(rsaPmsBuf, sizeof rsaPmsBuf);
           /* ignore failure */
       } else if (ss->opt.detectRollBack) {
           SSL3ProtocolVersion client_version = 
                                    (rsaPmsBuf[0] << 8) | rsaPmsBuf[1];
           if (client_version != ss->clientHelloVersion) {
              /* Version roll-back detected. ensure failure.  */
              rv = PK11_GenerateRandom(rsaPmsBuf, sizeof rsaPmsBuf);
           }
       }
       /* have PMS, build MS without PKCS11 */
       rv = ssl3_MasterKeyDeriveBypass(pwSpec, cr, sr, &pmsItem, isTLS, 
                                   PR_TRUE);
       if (rv != SECSuccess) {
           pwSpec->msItem.data = pwSpec->raw_master_secret;
           pwSpec->msItem.len  = SSL3_MASTER_SECRET_LENGTH;
           PK11_GenerateRandom(pwSpec->msItem.data, pwSpec->msItem.len);
       }
       rv = ssl3_InitPendingCipherSpec(ss,  NULL);
    } else {
       /*
        * unwrap pms out of the incoming buffer
        * Note: CKM_SSL3_MASTER_KEY_DERIVE is NOT the mechanism used to do 
        *     the unwrap.  Rather, it is the mechanism with which the 
        *      unwrapped pms will be used.
        */
       pms = PK11_PubUnwrapSymKey(serverKey, &enc_pms,
                               CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, 0);
       if (pms != NULL) {
           PRINT_BUF(60, (ss, "decrypted premaster secret:",
                        PK11_GetKeyData(pms)->data,
                        PK11_GetKeyData(pms)->len));
       } else {
           /* unwrap failed. Generate a bogus PMS and carry on. */
           PK11SlotInfo *  slot   = PK11_GetSlotFromPrivateKey(serverKey);

           ssl_GetSpecWriteLock(ss);
           pms = ssl3_GenerateRSAPMS(ss, ss->ssl3.prSpec, slot);
           ssl_ReleaseSpecWriteLock(ss);
           PK11_FreeSlot(slot);
       }

       if (pms == NULL) {
           /* last gasp.  */
           ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
           return SECFailure;
       }

       rv = ssl3_InitPendingCipherSpec(ss,  pms);
       PK11_FreeSymKey(pms);
    }

    if (rv != SECSuccess) {
       SEND_ALERT
       return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
    }
    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleServerHello ( sslSocket *  ss,
SSL3Opaque b,
PRUint32  length 
) [static]

Definition at line 4413 of file ssl3con.c.

{
    sslSessionID *sid              = ss->sec.ci.sid;
    PRInt32       temp;            /* allow for consume number failure */
    PRBool        suite_found   = PR_FALSE;
    int           i;
    int           errCode   = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
    SECStatus     rv;
    SECItem       sidBytes  = {siBuffer, NULL, 0};
    PRBool        sid_match;
    PRBool        isTLS            = PR_FALSE;
    SSL3AlertDescription desc   = illegal_parameter;
    SSL3ProtocolVersion version;

    SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello handshake",
       SSL_GETPID(), ss->fd));
    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    rv = ssl3_InitState(ss);
    if (rv != SECSuccess) {
       errCode = PORT_GetError(); /* ssl3_InitState has set the error code. */
       goto alert_loser;
    }
    if (ss->ssl3.hs.ws != wait_server_hello) {
        errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO;
       desc    = unexpected_message;
       goto alert_loser;
    }

    temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
    if (temp < 0) {
       goto loser;   /* alert has been sent */
    }
    version = (SSL3ProtocolVersion)temp;

    /* this is appropriate since the negotiation is complete, and we only
    ** know SSL 3.x.
    */
    if (MSB(version) != MSB(SSL_LIBRARY_VERSION_3_0)) {
       desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version 
                                             : handshake_failure;
       goto alert_loser;
    }

    rv = ssl3_NegotiateVersion(ss, version);
    if (rv != SECSuccess) {
       desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version 
                                             : handshake_failure;
       errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
       goto alert_loser;
    }
    isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0);

    rv = ssl3_ConsumeHandshake(
       ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH, &b, &length);
    if (rv != SECSuccess) {
       goto loser;   /* alert has been sent */
    }

    rv = ssl3_ConsumeHandshakeVariable(ss, &sidBytes, 1, &b, &length);
    if (rv != SECSuccess) {
       goto loser;   /* alert has been sent */
    }
    if (sidBytes.len > SSL3_SESSIONID_BYTES) {
       if (isTLS)
           desc = decode_error;
       goto alert_loser;    /* malformed. */
    }

    /* find selected cipher suite in our list. */
    temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
    if (temp < 0) {
       goto loser;   /* alert has been sent */
    }
    ssl3_config_match_init(ss);
    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
       ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
       if ((temp == suite->cipher_suite) &&
           (config_match(suite, ss->ssl3.policy, PR_TRUE))) {
           suite_found = PR_TRUE;
           break;    /* success */
       }
    }
    if (!suite_found) {
       desc    = handshake_failure;
       errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
       goto alert_loser;
    }
    ss->ssl3.hs.cipher_suite = (ssl3CipherSuite)temp;
    ss->ssl3.hs.suite_def    = ssl_LookupCipherSuiteDef((ssl3CipherSuite)temp);
    PORT_Assert(ss->ssl3.hs.suite_def);
    if (!ss->ssl3.hs.suite_def) {
       PORT_SetError(errCode = SEC_ERROR_LIBRARY_FAILURE);
       goto loser;   /* we don't send alerts for our screw-ups. */
    }

    /* find selected compression method in our list. */
    temp = ssl3_ConsumeHandshakeNumber(ss, 1, &b, &length);
    if (temp < 0) {
       goto loser;   /* alert has been sent */
    }
    suite_found = PR_FALSE;
    for (i = 0; i < compressionMethodsCount; i++) {
       if (temp == compressions[i])  {
           suite_found = PR_TRUE;
           break;    /* success */
       }
    }
    if (!suite_found) {
       desc    = handshake_failure;
       errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP;
       goto alert_loser;
    }
    ss->ssl3.hs.compression = (SSL3CompressionMethod)temp;

#ifdef DISALLOW_SERVER_HELLO_EXTENSIONS
    if (length != 0) {      /* malformed */
       goto alert_loser;
    }
#endif

    /* Any errors after this point are not "malformed" errors. */
    desc    = handshake_failure;

    /* we need to call ssl3_SetupPendingCipherSpec here so we can check the
     * key exchange algorithm. */
    rv = ssl3_SetupPendingCipherSpec(ss);
    if (rv != SECSuccess) {
       goto alert_loser;    /* error code is set. */
    }

    /* We may or may not have sent a session id, we may get one back or
     * not and if so it may match the one we sent.
     * Attempt to restore the master secret to see if this is so...
     * Don't consider failure to find a matching SID an error.
     */
    sid_match = (PRBool)(sidBytes.len > 0 &&
       sidBytes.len == sid->u.ssl3.sessionIDLength &&
       !PORT_Memcmp(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len));

    if (sid_match &&
       sid->version == ss->version &&
       sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite) do {
       ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;

       SECItem       wrappedMS;   /* wrapped master secret. */

       ss->sec.authAlgorithm = sid->authAlgorithm;
       ss->sec.authKeyBits   = sid->authKeyBits;
       ss->sec.keaType       = sid->keaType;
       ss->sec.keaKeyBits    = sid->keaKeyBits;

       /* 3 cases here:
        * a) key is wrapped (implies using PKCS11)
        * b) key is unwrapped, but we're still using PKCS11
        * c) key is unwrapped, and we're bypassing PKCS11.
        */
       if (sid->u.ssl3.keys.msIsWrapped) {
           PK11SlotInfo *slot;
           PK11SymKey *  wrapKey;     /* wrapping key */
           CK_FLAGS      keyFlags      = 0;

           if (ss->opt.bypassPKCS11) {
              /* we cannot restart a non-bypass session in a 
              ** bypass socket.
              */
              break;  
           }
           /* unwrap master secret with PKCS11 */
           slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID,
                                 sid->u.ssl3.masterSlotID);
           if (slot == NULL) {
              break;        /* not considered an error. */
           }
           if (!PK11_IsPresent(slot)) {
              PK11_FreeSlot(slot);
              break;        /* not considered an error. */
           }
           wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex,
                                  sid->u.ssl3.masterWrapMech,
                                  sid->u.ssl3.masterWrapSeries,
                                  ss->pkcs11PinArg);
           PK11_FreeSlot(slot);
           if (wrapKey == NULL) {
              break;        /* not considered an error. */
           }

           if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
              keyFlags = CKF_SIGN | CKF_VERIFY;
           }

           wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
           wrappedMS.len  = sid->u.ssl3.keys.wrapped_master_secret_len;
           pwSpec->master_secret =
              PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, 
                         NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
                         CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags);
           errCode = PORT_GetError();
           PK11_FreeSymKey(wrapKey);
           if (pwSpec->master_secret == NULL) {
              break; /* errorCode set just after call to UnwrapSymKey. */
           }
       } else if (ss->opt.bypassPKCS11) {
           /* MS is not wrapped */
           wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
           wrappedMS.len  = sid->u.ssl3.keys.wrapped_master_secret_len;
           memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len);
           pwSpec->msItem.data = pwSpec->raw_master_secret;
           pwSpec->msItem.len  = wrappedMS.len;
       } else {
           /* We CAN restart a bypass session in a non-bypass socket. */
           /* need to import the raw master secret to session object */
           PK11SlotInfo *slot = PK11_GetInternalSlot();
           wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
           wrappedMS.len  = sid->u.ssl3.keys.wrapped_master_secret_len;
           pwSpec->master_secret =  
              PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, 
                              PK11_OriginUnwrap, CKA_ENCRYPT, 
                              &wrappedMS, NULL);
           PK11_FreeSlot(slot);
           if (pwSpec->master_secret == NULL) {
              break; 
           }
       }

       /* Got a Match */
       SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_hits );
       ss->ssl3.hs.ws         = wait_change_cipher;
       ss->ssl3.hs.isResuming = PR_TRUE;

       /* copy the peer cert from the SID */
       if (sid->peerCert != NULL) {
           ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
       }


       /* NULL value for PMS signifies re-use of the old MS */
       rv = ssl3_InitPendingCipherSpec(ss,  NULL);
       if (rv != SECSuccess) {
           goto alert_loser;       /* err code was set */
       }
       return SECSuccess;
    } while (0);

    if (sid_match)
       SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_not_ok );
    else
       SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_misses );

    /* throw the old one away */
    sid->u.ssl3.keys.resumable = PR_FALSE;
    (*ss->sec.uncache)(sid);
    ssl_FreeSID(sid);

    /* get a new sid */
    ss->sec.ci.sid = sid = ssl3_NewSessionID(ss, PR_FALSE);
    if (sid == NULL) {
       goto alert_loser;    /* memory error is set. */
    }

    sid->version = ss->version;
    sid->u.ssl3.sessionIDLength = sidBytes.len;
    PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len);

    ss->ssl3.hs.isResuming = PR_FALSE;
    ss->ssl3.hs.ws         = wait_server_cert;
    return SECSuccess;

alert_loser:
    (void)SSL3_SendAlert(ss, alert_fatal, desc);

loser:
    errCode = ssl_MapLowLevelError(errCode);
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleServerHelloDone ( sslSocket *  ss) [static]

Definition at line 5175 of file ssl3con.c.

{
    SECStatus     rv;
    SSL3WaitState ws          = ss->ssl3.hs.ws;
    PRBool        send_verify = PR_FALSE;

    SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello_done handshake",
              SSL_GETPID(), ss->fd));
    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    if (ws != wait_hello_done  &&
        ws != wait_server_cert &&
       ws != wait_server_key  &&
       ws != wait_cert_request) {
       SSL3_SendAlert(ss, alert_fatal, unexpected_message);
       PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
       return SECFailure;
    }

    ssl_GetXmitBufLock(ss);        /*******************************/

    if (ss->ssl3.sendEmptyCert) {
       ss->ssl3.sendEmptyCert = PR_FALSE;
       rv = ssl3_SendEmptyCertificate(ss);
       /* Don't send verify */
       if (rv != SECSuccess) {
           goto loser;      /* error code is set. */
       }
    } else
    if (ss->ssl3.clientCertChain  != NULL &&
       ss->ssl3.clientPrivateKey != NULL) {
       send_verify = PR_TRUE;
       rv = ssl3_SendCertificate(ss);
       if (rv != SECSuccess) {
           goto loser;      /* error code is set. */
       }
    }

    rv = ssl3_SendClientKeyExchange(ss);
    if (rv != SECSuccess) {
       goto loser;   /* err is set. */
    }

    if (send_verify) {
       rv = ssl3_SendCertificateVerify(ss);
       if (rv != SECSuccess) {
           goto loser;      /* err is set. */
        }
    }
    rv = ssl3_SendChangeCipherSpecs(ss);
    if (rv != SECSuccess) {
       goto loser;   /* err code was set. */
    }
    rv = ssl3_SendFinished(ss, 0);
    if (rv != SECSuccess) {
       goto loser;   /* err code was set. */
    }

    ssl_ReleaseXmitBufLock(ss);           /*******************************/

    ss->ssl3.hs.ws = wait_change_cipher;
    return SECSuccess;

loser:
    ssl_ReleaseXmitBufLock(ss);
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_HandleServerKeyExchange ( sslSocket *  ss,
SSL3Opaque b,
PRUint32  length 
) [static]

Definition at line 4695 of file ssl3con.c.

{
    PRArenaPool *    arena     = NULL;
    SECKEYPublicKey *peerKey   = NULL;
    PRBool           isTLS;
    SECStatus        rv;
    int              errCode   = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
    SSL3AlertDescription desc  = illegal_parameter;
    SSL3Hashes       hashes;
    SECItem          signature = {siBuffer, NULL, 0};

    SSL_TRC(3, ("%d: SSL3[%d]: handle server_key_exchange handshake",
              SSL_GETPID(), ss->fd));
    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );

    if (ss->ssl3.hs.ws != wait_server_key &&
       ss->ssl3.hs.ws != wait_server_cert) {
       errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH;
       desc    = unexpected_message;
       goto alert_loser;
    }
    if (ss->sec.peerCert == NULL) {
       errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH;
       desc    = unexpected_message;
       goto alert_loser;
    }

    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);

    switch (ss->ssl3.hs.kea_def->exchKeyType) {

    case kt_rsa: {
       SECItem          modulus   = {siBuffer, NULL, 0};
       SECItem          exponent  = {siBuffer, NULL, 0};

       rv = ssl3_ConsumeHandshakeVariable(ss, &modulus, 2, &b, &length);
       if (rv != SECSuccess) {
           goto loser;             /* malformed. */
       }
       rv = ssl3_ConsumeHandshakeVariable(ss, &exponent, 2, &b, &length);
       if (rv != SECSuccess) {
           goto loser;             /* malformed. */
       }
       rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
       if (rv != SECSuccess) {
           goto loser;             /* malformed. */
       }
       if (length != 0) {
           if (isTLS)
              desc = decode_error;
           goto alert_loser;              /* malformed. */
       }

       /* failures after this point are not malformed handshakes. */
       /* TLS: send decrypt_error if signature failed. */
       desc = isTLS ? decrypt_error : handshake_failure;

       /*
        *  check to make sure the hash is signed by right guy
        */
       rv = ssl3_ComputeExportRSAKeyHash(modulus, exponent,
                                     &ss->ssl3.hs.client_random,
                                     &ss->ssl3.hs.server_random, 
                                     &hashes, ss->opt.bypassPKCS11);
        if (rv != SECSuccess) {
           errCode =
              ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
           goto alert_loser;
       }
        rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
                                isTLS, ss->pkcs11PinArg);
       if (rv != SECSuccess)  {
           errCode =
              ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
           goto alert_loser;
       }

       /*
        * we really need to build a new key here because we can no longer
        * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate
        * pkcs11 slots and ID's.
        */
       arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
       if (arena == NULL) {
           goto no_memory;
       }

       peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
       if (peerKey == NULL) {
            PORT_FreeArena(arena, PR_FALSE);
           goto no_memory;
       }

       peerKey->arena              = arena;
       peerKey->keyType            = rsaKey;
       peerKey->pkcs11Slot         = NULL;
       peerKey->pkcs11ID           = CK_INVALID_HANDLE;
       if (SECITEM_CopyItem(arena, &peerKey->u.rsa.modulus,        &modulus) ||
           SECITEM_CopyItem(arena, &peerKey->u.rsa.publicExponent, &exponent))
       {
            PORT_FreeArena(arena, PR_FALSE);
           goto no_memory;
        }
       ss->sec.peerKey = peerKey;
       ss->ssl3.hs.ws = wait_cert_request;
       return SECSuccess;
    }

    case kt_dh: {
       SECItem          dh_p      = {siBuffer, NULL, 0};
       SECItem          dh_g      = {siBuffer, NULL, 0};
       SECItem          dh_Ys     = {siBuffer, NULL, 0};

       rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length);
       if (rv != SECSuccess) {
           goto loser;             /* malformed. */
       }
       rv = ssl3_ConsumeHandshakeVariable(ss, &dh_g, 2, &b, &length);
       if (rv != SECSuccess) {
           goto loser;             /* malformed. */
       }
       rv = ssl3_ConsumeHandshakeVariable(ss, &dh_Ys, 2, &b, &length);
       if (rv != SECSuccess) {
           goto loser;             /* malformed. */
       }
       rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
       if (rv != SECSuccess) {
           goto loser;             /* malformed. */
       }
       if (length != 0) {
           if (isTLS)
              desc = decode_error;
           goto alert_loser;              /* malformed. */
       }

       PRINT_BUF(60, (NULL, "Server DH p", dh_p.data, dh_p.len));
       PRINT_BUF(60, (NULL, "Server DH g", dh_g.data, dh_g.len));
       PRINT_BUF(60, (NULL, "Server DH Ys", dh_Ys.data, dh_Ys.len));

       /* failures after this point are not malformed handshakes. */
       /* TLS: send decrypt_error if signature failed. */
       desc = isTLS ? decrypt_error : handshake_failure;

       /*
        *  check to make sure the hash is signed by right guy
        */
       rv = ssl3_ComputeDHKeyHash(dh_p, dh_g, dh_Ys,
                                     &ss->ssl3.hs.client_random,
                                     &ss->ssl3.hs.server_random, 
                                     &hashes, ss->opt.bypassPKCS11);
        if (rv != SECSuccess) {
           errCode =
              ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
           goto alert_loser;
       }
        rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
                                isTLS, ss->pkcs11PinArg);
       if (rv != SECSuccess)  {
           errCode =
              ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
           goto alert_loser;
       }

       /*
        * we really need to build a new key here because we can no longer
        * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate
        * pkcs11 slots and ID's.
        */
       arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
       if (arena == NULL) {
           goto no_memory;
       }

       ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
       if (peerKey == NULL) {
           goto no_memory;
       }

       peerKey->arena              = arena;
       peerKey->keyType            = dhKey;
       peerKey->pkcs11Slot         = NULL;
       peerKey->pkcs11ID           = CK_INVALID_HANDLE;

       if (SECITEM_CopyItem(arena, &peerKey->u.dh.prime,        &dh_p) ||
           SECITEM_CopyItem(arena, &peerKey->u.dh.base,         &dh_g) ||
           SECITEM_CopyItem(arena, &peerKey->u.dh.publicValue,  &dh_Ys))
       {
            PORT_FreeArena(arena, PR_FALSE);
           goto no_memory;
        }
       ss->sec.peerKey = peerKey;
       ss->ssl3.hs.ws = wait_cert_request;
       return SECSuccess;
    }

#ifdef NSS_ENABLE_ECC
    case kt_ecdh:
       rv = ssl3_HandleECDHServerKeyExchange(ss, b, length);
       return rv;
#endif /* NSS_ENABLE_ECC */

    default:
       desc    = handshake_failure;
       errCode = SEC_ERROR_UNSUPPORTED_KEYALG;
       break;        /* goto alert_loser; */
    }

alert_loser:
    (void)SSL3_SendAlert(ss, alert_fatal, desc);
loser:
    PORT_SetError( errCode );
    return SECFailure;

no_memory:    /* no-memory error has already been set. */
    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus ssl3_HandleV2ClientHello ( sslSocket *  ss,
unsigned char *  buffer,
int  length 
)

Definition at line 5849 of file ssl3con.c.

{
    sslSessionID *      sid               = NULL;
    unsigned char *     suites;
    unsigned char *     random;
    SSL3ProtocolVersion version;
    SECStatus           rv;
    int                 i;
    int                 j;
    int                 sid_length;
    int                 suite_length;
    int                 rand_length;
    int                 errCode  = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
    SSL3AlertDescription desc    = handshake_failure;

    SSL_TRC(3, ("%d: SSL3[%d]: handle v2 client_hello", SSL_GETPID(), ss->fd));

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );

    ssl_GetSSL3HandshakeLock(ss);

    rv = ssl3_InitState(ss);
    if (rv != SECSuccess) {
       ssl_ReleaseSSL3HandshakeLock(ss);
       return rv;           /* ssl3_InitState has set the error code. */
    }

    if (ss->ssl3.hs.ws != wait_client_hello) {
       desc    = unexpected_message;
       errCode = SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO;
       goto loser;   /* alert_loser */
    }

    version      = (buffer[1] << 8) | buffer[2];
    suite_length = (buffer[3] << 8) | buffer[4];
    sid_length   = (buffer[5] << 8) | buffer[6];
    rand_length  = (buffer[7] << 8) | buffer[8];
    ss->clientHelloVersion = version;

    rv = ssl3_NegotiateVersion(ss, version);
    if (rv != SECSuccess) {
       /* send back which ever alert client will understand. */
       desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version : handshake_failure;
       errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
       goto alert_loser;
    }

    /* if we get a non-zero SID, just ignore it. */
    if (length !=
        SSL_HL_CLIENT_HELLO_HBYTES + suite_length + sid_length + rand_length) {
       SSL_DBG(("%d: SSL3[%d]: bad v2 client hello message, len=%d should=%d",
               SSL_GETPID(), ss->fd, length,
               SSL_HL_CLIENT_HELLO_HBYTES + suite_length + sid_length +
               rand_length));
       goto loser;   /* malformed */      /* alert_loser */
    }

    suites = buffer + SSL_HL_CLIENT_HELLO_HBYTES;
    random = suites + suite_length + sid_length;

    if (rand_length < SSL_MIN_CHALLENGE_BYTES ||
       rand_length > SSL_MAX_CHALLENGE_BYTES) {
       goto loser;   /* malformed */      /* alert_loser */
    }

    PORT_Assert(SSL_MAX_CHALLENGE_BYTES == SSL3_RANDOM_LENGTH);

    PORT_Memset(&ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH);
    PORT_Memcpy(
       &ss->ssl3.hs.client_random.rand[SSL3_RANDOM_LENGTH - rand_length],
       random, rand_length);

    PRINT_BUF(60, (ss, "client random:", &ss->ssl3.hs.client_random.rand[0],
                 SSL3_RANDOM_LENGTH));
#ifdef NSS_ENABLE_ECC
    /* Disable any ECC cipher suites for which we have no cert. */
    ssl3_FilterECCipherSuitesByServerCerts(ss);
#endif
    i = ssl3_config_match_init(ss);
    if (i <= 0) {
       errCode = PORT_GetError();  /* error code is already set. */
       goto alert_loser;
    }

    /* Select a cipher suite.
    ** NOTE: This suite selection algorithm should be the same as the one in
    ** ssl3_HandleClientHello().  
    */
    for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
       ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
       if (!config_match(suite, ss->ssl3.policy, PR_TRUE))
           continue;
       for (i = 0; i < suite_length; i += 3) {
           if ((suites[i]   == 0) &&
              (suites[i+1] == MSB(suite->cipher_suite)) &&
              (suites[i+2] == LSB(suite->cipher_suite))) {

              ss->ssl3.hs.cipher_suite = suite->cipher_suite;
              ss->ssl3.hs.suite_def =
                  ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
              goto suite_found;
           }
       }
    }
    errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
    goto alert_loser;

suite_found:

    ss->ssl3.hs.compression = compression_null;
    ss->sec.send            = ssl3_SendApplicationData;

    /* we don't even search for a cache hit here.  It's just a miss. */
    SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_misses );
    sid = ssl3_NewSessionID(ss, PR_TRUE);
    if (sid == NULL) {
       errCode = PORT_GetError();
       goto loser;   /* memory error is set. */
    }
    ss->sec.ci.sid = sid;
    /* do not worry about memory leak of sid since it now belongs to ci */

    /* We have to update the handshake hashes before we can send stuff */
    rv = ssl3_UpdateHandshakeHashes(ss, buffer, length);
    if (rv != SECSuccess) {
       errCode = PORT_GetError();
       goto loser;
    }

    ssl_GetXmitBufLock(ss);
    rv = ssl3_SendServerHelloSequence(ss);
    ssl_ReleaseXmitBufLock(ss);
    if (rv != SECSuccess) {
       errCode = PORT_GetError();
       goto loser;
    }

    /* XXX_1  The call stack to here is:
     * ssl_Do1stHandshake -> ssl2_HandleClientHelloMessage -> here.
     * ssl2_HandleClientHelloMessage returns whatever we return here.
     * ssl_Do1stHandshake will continue looping if it gets back either
     *        SECSuccess or SECWouldBlock.
     * SECSuccess is preferable here.  See XXX_1 in sslgathr.c.
     */
    ssl_ReleaseSSL3HandshakeLock(ss);
    return SECSuccess;

alert_loser:
    SSL3_SendAlert(ss, alert_fatal, desc);
loser:
    ssl_ReleaseSSL3HandshakeLock(ss);
    PORT_SetError(errCode);
    return SECFailure;
}

Here is the call graph for this function:

static SECStatus ssl3_HandshakeFailure ( sslSocket *  ss) [static]

Definition at line 2291 of file ssl3con.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_IllegalParameter ( sslSocket *  ss) [static]

Definition at line 2276 of file ssl3con.c.

{
    PRBool isTLS;

    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
    (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
    PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
                                   : SSL_ERROR_BAD_SERVER );
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ssl3_InitCipherSpec ( sslSocket *  ss,
ssl3CipherSpec spec 
) [static]

Definition at line 8080 of file ssl3con.c.

{
    spec->cipher_def               = &bulk_cipher_defs[cipher_null];
    PORT_Assert(spec->cipher_def->cipher == cipher_null);
    spec->mac_def                  = &mac_defs[mac_null];
    PORT_Assert(spec->mac_def->mac == mac_null);
    spec->encode                   = Null_Cipher;
    spec->decode                   = Null_Cipher;
    spec->destroy                  = NULL;
    spec->mac_size                 = 0;
    spec->master_secret            = NULL;
    spec->bypassCiphers            = PR_FALSE;

    spec->msItem.data              = NULL;
    spec->msItem.len               = 0;

    spec->client.write_key         = NULL;
    spec->client.write_mac_key     = NULL;
    spec->client.write_mac_context = NULL;

    spec->server.write_key         = NULL;
    spec->server.write_mac_key     = NULL;
    spec->server.write_mac_context = NULL;

    spec->write_seq_num.high       = 0;
    spec->write_seq_num.low        = 0;

    spec->read_seq_num.high        = 0;
    spec->read_seq_num.low         = 0;

    spec->version                  = ss->opt.enableTLS
                                          ? SSL_LIBRARY_VERSION_3_1_TLS
                                          : SSL_LIBRARY_VERSION_3_0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus ssl3_InitPendingCipherSpec ( sslSocket *  ss,
PK11SymKey *  pms 
)

Definition at line 1507 of file ssl3con.c.

{
    ssl3CipherSpec  *  pwSpec;
    SECStatus          rv;

    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));

    ssl_GetSpecWriteLock(ss);      /**************************************/

    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);

    pwSpec        = ss->ssl3.pwSpec;

    if (pms || (!pwSpec->msItem.len && !pwSpec->master_secret)) {
       rv = ssl3_DeriveMasterSecret(ss, pms);
       if (rv != SECSuccess) {
           goto done;  /* err code set by ssl3_DeriveMasterSecret */
       }
    }
    if (pwSpec->msItem.len && pwSpec->msItem.data) {
       /* Double Bypass */
       const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def;
       PRBool             isTLS   = (PRBool)(kea_def->tls_keygen ||
                                (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
       pwSpec->bypassCiphers = PR_TRUE;
       rv = ssl3_KeyAndMacDeriveBypass( pwSpec, 
                          (const unsigned char *)&ss->ssl3.hs.client_random,
                          (const unsigned char *)&ss->ssl3.hs.server_random,
                          isTLS, 
                          (PRBool)(kea_def->is_limited));
       if (rv == SECSuccess) {
           rv = ssl3_InitPendingContextsBypass(ss);
       }
    } else if (pwSpec->master_secret) {
       rv = ssl3_DeriveConnectionKeysPKCS11(ss);
       if (rv == SECSuccess) {
           rv = ssl3_InitPendingContextsPKCS11(ss);
       }
    } else {
       PORT_Assert(pwSpec->master_secret);
       PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
       rv = SECFailure;
    }

done:
    ssl_ReleaseSpecWriteLock(ss);  /******************************/
    if (rv != SECSuccess)
       ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
    return rv;
}

Here is the call graph for this function:

static SECStatus ssl3_InitPendingContextsBypass ( sslSocket *  ss) [static]

Definition at line 1207 of file ssl3con.c.

{
      ssl3CipherSpec  *  pwSpec;
const ssl3BulkCipherDef *cipher_def;
      void *             serverContext = NULL;
      void *             clientContext = NULL;
      BLapiInitContextFunc initFn = (BLapiInitContextFunc)NULL;
      int                mode     = 0;
      unsigned int       optArg1  = 0;
      unsigned int       optArg2  = 0;
      PRBool             server_encrypts = ss->sec.isServer;
      CK_ULONG           macLength;
      SSLCipherAlgorithm calg;
      SECStatus          rv;

    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));

    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);

    pwSpec        = ss->ssl3.pwSpec;
    cipher_def    = pwSpec->cipher_def;
    macLength     = pwSpec->mac_size;

    /* MAC setup is done when computing the mac, not here.
     * Now setup the crypto contexts.
     */

    calg = cipher_def->calg;

    serverContext = pwSpec->server.cipher_context;
    clientContext = pwSpec->client.cipher_context;

    switch (calg) {
    case ssl_calg_null:
       pwSpec->encode  = Null_Cipher;
       pwSpec->decode  = Null_Cipher;
        pwSpec->destroy = NULL;
       goto success;

    case ssl_calg_rc4:
       initFn = (BLapiInitContextFunc)RC4_InitContext;
       pwSpec->encode  = (SSLCipher) RC4_Encrypt;
       pwSpec->decode  = (SSLCipher) RC4_Decrypt;
       pwSpec->destroy = (SSLDestroy) RC4_DestroyContext;
       break;
    case ssl_calg_rc2:
       initFn = (BLapiInitContextFunc)RC2_InitContext;
       mode = NSS_RC2_CBC;
       optArg1 = cipher_def->key_size;
       pwSpec->encode  = (SSLCipher) RC2_Encrypt;
       pwSpec->decode  = (SSLCipher) RC2_Decrypt;
       pwSpec->destroy = (SSLDestroy) RC2_DestroyContext;
       break;
    case ssl_calg_des:
       initFn = (BLapiInitContextFunc)DES_InitContext;
       mode = NSS_DES_CBC;
       optArg1 = server_encrypts;
       pwSpec->encode  = (SSLCipher) DES_Encrypt;
       pwSpec->decode  = (SSLCipher) DES_Decrypt;
       pwSpec->destroy = (SSLDestroy) DES_DestroyContext;
       break;
    case ssl_calg_3des:
       initFn = (BLapiInitContextFunc)DES_InitContext;
       mode = NSS_DES_EDE3_CBC;
       optArg1 = server_encrypts;
       pwSpec->encode  = (SSLCipher) DES_Encrypt;
       pwSpec->decode  = (SSLCipher) DES_Decrypt;
       pwSpec->destroy = (SSLDestroy) DES_DestroyContext;
       break;
    case ssl_calg_aes:
       initFn = (BLapiInitContextFunc)AES_InitContext;
       mode = NSS_AES_CBC;
       optArg1 = server_encrypts;
       optArg2 = AES_BLOCK_SIZE;
       pwSpec->encode  = (SSLCipher) AES_Encrypt;
       pwSpec->decode  = (SSLCipher) AES_Decrypt;
       pwSpec->destroy = (SSLDestroy) AES_DestroyContext;
       break;

    case ssl_calg_idea:
    case ssl_calg_fortezza :
    default:
       PORT_Assert(0);
       PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
       goto bail_out;
    }
    rv = (*initFn)(serverContext,
                 pwSpec->server.write_key_item.data,
                 pwSpec->server.write_key_item.len,
                 pwSpec->server.write_iv_item.data,
                 mode, optArg1, optArg2);
    if (rv != SECSuccess) {
       PORT_Assert(0);
       PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
       goto bail_out;
    }

    if (calg == ssl_calg_des || calg == ssl_calg_3des || calg == ssl_calg_aes) {
       /* For block ciphers, if the server is encrypting, then the client
        * is decrypting, and vice versa.
        */
       optArg1 = !optArg1;
    }

    rv = (*initFn)(clientContext,
                 pwSpec->client.write_key_item.data,
                 pwSpec->client.write_key_item.len,
                 pwSpec->client.write_iv_item.data,
                 mode, optArg1, optArg2);
    if (rv != SECSuccess) {
       PORT_Assert(0);
       PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
       goto bail_out;
    }

    pwSpec->encodeContext = (ss->sec.isServer) ? serverContext : clientContext;
    pwSpec->decodeContext = (ss->sec.isServer) ? clientContext : serverContext;

success:
    return SECSuccess;

bail_out:
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ssl3_InitPendingContextsPKCS11 ( sslSocket *  ss) [static]

Definition at line 1359 of file ssl3con.c.

{
      ssl3CipherSpec  *  pwSpec;
const ssl3BulkCipherDef *cipher_def;
      PK11Context *      serverContext = NULL;
      PK11Context *      clientContext = NULL;
      SECItem *          param;
      CK_MECHANISM_TYPE  mechanism;
      CK_MECHANISM_TYPE  mac_mech;
      CK_ULONG           macLength;
      CK_ULONG           effKeyBits;
      SECItem            iv;
      SECItem            mac_param;
      SSLCipherAlgorithm calg;

    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));

    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);

    pwSpec        = ss->ssl3.pwSpec;
    cipher_def    = pwSpec->cipher_def;
    macLength     = pwSpec->mac_size;

    /* 
    ** Now setup the MAC contexts, 
    **   crypto contexts are setup below.
    */

    pwSpec->client.write_mac_context = NULL;
    pwSpec->server.write_mac_context = NULL;
    mac_mech       = pwSpec->mac_def->mmech;
    mac_param.data = (unsigned char *)&macLength;
    mac_param.len  = sizeof(macLength);
    mac_param.type = 0;

    pwSpec->client.write_mac_context = PK11_CreateContextBySymKey(
           mac_mech, CKA_SIGN, pwSpec->client.write_mac_key, &mac_param);
    if (pwSpec->client.write_mac_context == NULL)  {
       ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
       goto fail;
    }
    pwSpec->server.write_mac_context = PK11_CreateContextBySymKey(
           mac_mech, CKA_SIGN, pwSpec->server.write_mac_key, &mac_param);
    if (pwSpec->server.write_mac_context == NULL) {
       ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
       goto fail;
    }

    /* 
    ** Now setup the crypto contexts.
    */

    calg = cipher_def->calg;
    PORT_Assert(alg2Mech[calg].calg == calg);

    if (calg == calg_null) {
       pwSpec->encode  = Null_Cipher;
       pwSpec->decode  = Null_Cipher;
       pwSpec->destroy = NULL;
       return SECSuccess;
    }
    mechanism = alg2Mech[calg].cmech;
    effKeyBits = cipher_def->key_size * BPB;

    /*
     * build the server context
     */
    iv.data = pwSpec->server.write_iv;
    iv.len  = cipher_def->iv_size;
    param = ssl3_ParamFromIV(mechanism, &iv, effKeyBits);
    if (param == NULL) {
       ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE);
       goto fail;
    }
    serverContext = PK11_CreateContextBySymKey(mechanism,
                            (ss->sec.isServer ? CKA_ENCRYPT : CKA_DECRYPT),
                            pwSpec->server.write_key, param);
    iv.data = PK11_IVFromParam(mechanism, param, (int *)&iv.len);
    if (iv.data)
       PORT_Memcpy(pwSpec->server.write_iv, iv.data, iv.len);
    SECITEM_FreeItem(param, PR_TRUE);
    if (serverContext == NULL) {
       ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
       goto fail;
    }

    /*
     * build the client context
     */
    iv.data = pwSpec->client.write_iv;
    iv.len  = cipher_def->iv_size;

    param = ssl3_ParamFromIV(mechanism, &iv, effKeyBits);
    if (param == NULL) {
       ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE);
       goto fail;
    }
    clientContext = PK11_CreateContextBySymKey(mechanism,
                            (ss->sec.isServer ? CKA_DECRYPT : CKA_ENCRYPT),
                            pwSpec->client.write_key, param);
    iv.data = PK11_IVFromParam(mechanism, param, (int *)&iv.len);
    if (iv.data)
       PORT_Memcpy(pwSpec->client.write_iv, iv.data, iv.len);
    SECITEM_FreeItem(param,PR_TRUE);
    if (clientContext == NULL) {
       ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
       goto fail;
    }
    pwSpec->encode  = (SSLCipher) PK11_CipherOp;
    pwSpec->decode  = (SSLCipher) PK11_CipherOp;
    pwSpec->destroy = (SSLDestroy) PK11_DestroyContext;

    pwSpec->encodeContext = (ss->sec.isServer) ? serverContext : clientContext;
    pwSpec->decodeContext = (ss->sec.isServer) ? clientContext : serverContext;

    serverContext = NULL;
    clientContext = NULL;

    return SECSuccess;

fail:
    if (serverContext != NULL) PK11_DestroyContext(serverContext, PR_TRUE);
    if (clientContext != NULL) PK11_DestroyContext(clientContext, PR_TRUE);
    if (pwSpec->client.write_mac_context != NULL) {
       PK11_DestroyContext(pwSpec->client.write_mac_context,PR_TRUE);
       pwSpec->client.write_mac_context = NULL;
    }
    if (pwSpec->server.write_mac_context != NULL) {
       PK11_DestroyContext(pwSpec->server.write_mac_context,PR_TRUE);
       pwSpec->server.write_mac_context = NULL;
    }

    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void ssl3_InitSocketPolicy ( sslSocket *  ss)

Definition at line 8378 of file ssl3con.c.

{
    PORT_Memcpy(ss->cipherSuites, cipherSuites, sizeof cipherSuites);
}
static SECStatus ssl3_InitState ( sslSocket *  ss) [static]

Definition at line 8128 of file ssl3con.c.

{
    PK11Context *md5  = NULL;
    PK11Context *sha  = NULL;
    SECStatus    rv;
    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));

    if (ss->ssl3.initialized)
       return SECSuccess;   /* Function should be idempotent */

    ss->ssl3.policy = SSL_ALLOWED;

    ssl_GetSpecWriteLock(ss);
    ss->ssl3.crSpec = ss->ssl3.cwSpec = &ss->ssl3.specs[0];
    ss->ssl3.prSpec = ss->ssl3.pwSpec = &ss->ssl3.specs[1];
    ss->ssl3.hs.rehandshake = PR_FALSE;
    ssl3_InitCipherSpec(ss, ss->ssl3.crSpec);
    ssl3_InitCipherSpec(ss, ss->ssl3.prSpec);

    ss->ssl3.hs.ws = (ss->sec.isServer) ? wait_client_hello : wait_server_hello;
#ifdef NSS_ENABLE_ECC
    ss->ssl3.hs.negotiatedECCurves = SSL3_SUPPORTED_CURVES_MASK;
#endif
    ssl_ReleaseSpecWriteLock(ss);

    /*
     * note: We should probably lookup an SSL3 slot for these
     * handshake hashes in hopes that we wind up with the same slots
     * that the master secret will wind up in ...
     */
    SSL_TRC(30,("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd));
    if (ss->opt.bypassPKCS11) {
       MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx);
       SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx);
    } else {
       ss->ssl3.hs.md5 = md5 = PK11_CreateDigestContext(SEC_OID_MD5);
       if (md5 == NULL) {
           ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
           goto loser;
       }
       rv = PK11_DigestBegin(ss->ssl3.hs.md5);
       if (rv != SECSuccess) {
           ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
           goto loser;
       }

       sha = ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA1);
       if (sha == NULL) {
           ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
           goto loser;
       }
       rv = PK11_DigestBegin(ss->ssl3.hs.sha);
       if (rv != SECSuccess) {
           ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
           goto loser;
       }
    }

    ss->ssl3.initialized = PR_TRUE;

    return SECSuccess;

loser:
    if (md5 != NULL) PK11_DestroyContext(md5, PR_TRUE);
    if (sha != NULL) PK11_DestroyContext(sha, PR_TRUE);
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus ssl3_NegotiateVersion ( sslSocket *  ss,
SSL3ProtocolVersion  peerVersion 
)

Definition at line 731 of file ssl3con.c.

{
    SSL3ProtocolVersion version;
    SSL3ProtocolVersion maxVersion;

    if (ss->opt.enableTLS) {
       maxVersion = SSL_LIBRARY_VERSION_3_1_TLS;
    } else if (ss->opt.enableSSL3) {
       maxVersion = SSL_LIBRARY_VERSION_3_0;
    } else {
       /* what are we doing here? */
       PORT_Assert(