Пример #1
0
/* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock. 
 * 
 * Currently, the list of functions called through ss->handshake is:
 * 
 * In sslsocks.c:
 *  SocksGatherRecord
 *  SocksHandleReply	
 *  SocksStartGather
 *
 * In sslcon.c:
 *  ssl_GatherRecord1stHandshake
 *  ssl2_HandleClientSessionKeyMessage
 *  ssl2_HandleMessage
 *  ssl2_HandleVerifyMessage
 *  ssl2_BeginClientHandshake
 *  ssl2_BeginServerHandshake
 *  ssl2_HandleClientHelloMessage
 *  ssl2_HandleServerHelloMessage
 * 
 * The ss->handshake function returns SECWouldBlock under these conditions:
 * 1.	ssl_GatherRecord1stHandshake called ssl2_GatherData which read in 
 *	the beginning of an SSL v3 hello message and returned SECWouldBlock 
 *	to switch to SSL v3 handshake processing.
 *
 * 2.	ssl2_HandleClientHelloMessage discovered version 3.0 in the incoming
 *	v2 client hello msg, and called ssl3_HandleV2ClientHello which 
 *	returned SECWouldBlock.
 *
 * 3.   SECWouldBlock was returned by one of the callback functions, via
 *	one of these paths:
 * -	ssl2_HandleMessage() -> ssl2_HandleRequestCertificate() ->
 *	ss->getClientAuthData()
 *
 * -	ssl2_HandleServerHelloMessage() -> ss->handleBadCert()
 *
 * -	ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() -> 
 *	ssl3_HandleRecord() -> ssl3_HandleHandshake() -> 
 *	ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificate() -> 
 *	ss->handleBadCert()
 *
 * -	ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() -> 
 *	ssl3_HandleRecord() -> ssl3_HandleHandshake() -> 
 *	ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificateRequest() -> 
 *	ss->getClientAuthData()
 *
 * Called from: SSL_ForceHandshake	(below), 
 *              ssl_SecureRecv 		(below) and
 *              ssl_SecureSend		(below)
 *	  from: WaitForResponse 	in sslsocks.c
 *	        ssl_SocksRecv   	in sslsocks.c
 *              ssl_SocksSend   	in sslsocks.c
 *
 * Caller must hold the (write) handshakeLock.
 */
int 
ssl_Do1stHandshake(sslSocket *ss)
{
    int rv        = SECSuccess;
    int loopCount = 0;

    do {
	PORT_Assert(ss->opt.noLocks ||  ssl_Have1stHandshakeLock(ss) );
	PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
	PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
	PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss));

	if (ss->handshake == 0) {
	    /* Previous handshake finished. Switch to next one */
	    ss->handshake = ss->nextHandshake;
	    ss->nextHandshake = 0;
	}
	if (ss->handshake == 0) {
	    /* Previous handshake finished. Switch to security handshake */
	    ss->handshake = ss->securityHandshake;
	    ss->securityHandshake = 0;
	}
	if (ss->handshake == 0) {
	    ssl_GetRecvBufLock(ss);
	    ss->gs.recordLen = 0;
	    ssl_ReleaseRecvBufLock(ss);

	    SSL_TRC(3, ("%d: SSL[%d]: handshake is completed",
			SSL_GETPID(), ss->fd));
            /* call handshake callback for ssl v2 */
	    /* for v3 this is done in ssl3_HandleFinished() */
	    if ((ss->handshakeCallback != NULL) && /* has callback */
		(!ss->firstHsDone) &&              /* only first time */
		(ss->version < SSL_LIBRARY_VERSION_3_0)) {  /* not ssl3 */
		ss->firstHsDone     = PR_TRUE;
		(ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
	    }
	    ss->firstHsDone         = PR_TRUE;
	    ss->gs.writeOffset = 0;
	    ss->gs.readOffset  = 0;
	    break;
	}
	rv = (*ss->handshake)(ss);
	++loopCount;
    /* This code must continue to loop on SECWouldBlock, 
     * or any positive value.	See XXX_1 comments.
     */
    } while (rv != SECFailure);  	/* was (rv >= 0); XXX_1 */

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

    if (rv == SECWouldBlock) {
	PORT_SetError(PR_WOULD_BLOCK_ERROR);
	rv = SECFailure;
    }
    return rv;
}
Пример #2
0
/* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock. 
 * 
 * Currently, the list of functions called through ss->handshake is:
 * 
 * In sslsocks.c:
 *  SocksGatherRecord
 *  SocksHandleReply	
 *  SocksStartGather
 *
 * In sslcon.c:
 *  ssl_GatherRecord1stHandshake
 *  ssl2_HandleClientSessionKeyMessage
 *  ssl2_HandleMessage
 *  ssl2_HandleVerifyMessage
 *  ssl2_BeginClientHandshake
 *  ssl2_BeginServerHandshake
 *  ssl2_HandleClientHelloMessage
 *  ssl2_HandleServerHelloMessage
 * 
 * The ss->handshake function returns SECWouldBlock under these conditions:
 * 1.	ssl_GatherRecord1stHandshake called ssl2_GatherData which read in 
 *	the beginning of an SSL v3 hello message and returned SECWouldBlock 
 *	to switch to SSL v3 handshake processing.
 *
 * 2.	ssl2_HandleClientHelloMessage discovered version 3.0 in the incoming
 *	v2 client hello msg, and called ssl3_HandleV2ClientHello which 
 *	returned SECWouldBlock.
 *
 * 3.   SECWouldBlock was returned by one of the callback functions, via
 *	one of these paths:
 * -	ssl2_HandleMessage() -> ssl2_HandleRequestCertificate() ->
 *	ss->getClientAuthData()
 *
 * -	ssl2_HandleServerHelloMessage() -> ss->handleBadCert()
 *
 * -	ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() -> 
 *	ssl3_HandleRecord() -> ssl3_HandleHandshake() -> 
 *	ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificate() -> 
 *	ss->handleBadCert()
 *
 * -	ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() -> 
 *	ssl3_HandleRecord() -> ssl3_HandleHandshake() -> 
 *	ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificateRequest() -> 
 *	ss->getClientAuthData()
 *
 * Called from: SSL_ForceHandshake	(below), 
 *              ssl_SecureRecv 		(below) and
 *              ssl_SecureSend		(below)
 *	  from: WaitForResponse 	in sslsocks.c
 *	        ssl_SocksRecv   	in sslsocks.c
 *              ssl_SocksSend   	in sslsocks.c
 *
 * Caller must hold the (write) handshakeLock.
 */
int 
ssl_Do1stHandshake(sslSocket *ss)
{
    int rv        = SECSuccess;
    int loopCount = 0;

    do {
	PORT_Assert(ss->opt.noLocks ||  ssl_Have1stHandshakeLock(ss) );
	PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
	PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
	PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss));

	if (ss->handshake == 0) {
	    /* Previous handshake finished. Switch to next one */
	    ss->handshake = ss->nextHandshake;
	    ss->nextHandshake = 0;
	}
	if (ss->handshake == 0) {
	    /* Previous handshake finished. Switch to security handshake */
	    ss->handshake = ss->securityHandshake;
	    ss->securityHandshake = 0;
	}
	if (ss->handshake == 0) {
	    /* for v3 this is done in ssl3_FinishHandshake */
	    if (!ss->firstHsDone && ss->version < SSL_LIBRARY_VERSION_3_0) {
		ssl_GetRecvBufLock(ss);
		ss->gs.recordLen = 0;
		ssl_FinishHandshake(ss);
		ssl_ReleaseRecvBufLock(ss);
	    }
	    break;
	}
	rv = (*ss->handshake)(ss);
	++loopCount;
    /* This code must continue to loop on SECWouldBlock, 
     * or any positive value.	See XXX_1 comments.
     */
    } while (rv != SECFailure);  	/* was (rv >= 0); XXX_1 */

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

    if (rv == SECWouldBlock) {
	PORT_SetError(PR_WOULD_BLOCK_ERROR);
	rv = SECFailure;
    }
    return rv;
}
Пример #3
0
int 
ssl_Do1stHandshake(sslSocket *ss)
{
    int rv        = SECSuccess;
    int loopCount = 0;

    do {
	PORT_Assert(ss->opt.noLocks ||  ssl_Have1stHandshakeLock(ss) );
	PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
	PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
	PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss));

	if (ss->handshake == 0) {
	    
	    ss->handshake = ss->nextHandshake;
	    ss->nextHandshake = 0;
	}
	if (ss->handshake == 0) {
	    
	    ss->handshake = ss->securityHandshake;
	    ss->securityHandshake = 0;
	}
	if (ss->handshake == 0) {
	    
	    if (!ss->firstHsDone && ss->version < SSL_LIBRARY_VERSION_3_0) {
		ssl_GetRecvBufLock(ss);
		ss->gs.recordLen = 0;
		ssl_FinishHandshake(ss);
		ssl_ReleaseRecvBufLock(ss);
	    }
	    break;
	}
	rv = (*ss->handshake)(ss);
	++loopCount;
    } while (rv != SECFailure);  	

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

    if (rv == SECWouldBlock) {
	PORT_SetError(PR_WOULD_BLOCK_ERROR);
	rv = SECFailure;
    }
    return rv;
}
Пример #4
0
/* This function encodes the key_exchange field in
 * the KeyShareEntry structure. */
SECStatus
tls13_EncodeECDHEKeyShareKEX(sslSocket *ss, const SECKEYPublicKey *pubKey)
{
    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
    PORT_Assert(pubKey->keyType == ecKey);

    return ssl3_AppendHandshake(ss, pubKey->u.ec.publicValue.data,
                                pubKey->u.ec.publicValue.len);
}
Пример #5
0
/*
** Save away write data that is trying to be written before the security
** handshake has been completed. When the handshake is completed, we will
** flush this data out.
** Caller must hold xmitBufLock
*/
SECStatus 
ssl_SaveWriteData(sslSocket *ss, const void *data, unsigned int len)
{
    SECStatus    rv;

    PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
    rv = sslBuffer_Append(&ss->pendingBuf, data, len);
    SSL_TRC(5, ("%d: SSL[%d]: saving %u bytes of data (%u total saved so far)",
		 SSL_GETPID(), ss->fd, len, ss->pendingBuf.len));
    return rv;
}
Пример #6
0
/* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock.
 *
 * Currently, the list of functions called through ss->handshake is:
 *
 * In sslsocks.c:
 *  SocksGatherRecord
 *  SocksHandleReply
 *  SocksStartGather
 *
 * In sslcon.c:
 *  ssl_GatherRecord1stHandshake
 *  ssl_BeginClientHandshake
 *  ssl_BeginServerHandshake
 *
 * The ss->handshake function returns SECWouldBlock if it was returned by
 *  one of the callback functions, via one of these paths:
 *
 * -    ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() ->
 *  ssl3_HandleRecord() -> ssl3_HandleHandshake() ->
 *  ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificate() ->
 *  ss->handleBadCert()
 *
 * -    ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() ->
 *  ssl3_HandleRecord() -> ssl3_HandleHandshake() ->
 *  ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificateRequest() ->
 *  ss->getClientAuthData()
 *
 * Called from: SSL_ForceHandshake  (below),
 *              ssl_SecureRecv      (below) and
 *              ssl_SecureSend      (below)
 *    from: WaitForResponse     in sslsocks.c
 *          ssl_SocksRecv       in sslsocks.c
 *              ssl_SocksSend       in sslsocks.c
 *
 * Caller must hold the (write) handshakeLock.
 */
int
ssl_Do1stHandshake(sslSocket *ss)
{
    int rv = SECSuccess;

    while (ss->handshake && rv == SECSuccess) {
        PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
        PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
        PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
        PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss));

        rv = (*ss->handshake)(ss);
    };

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

    if (rv == SECWouldBlock) {
        PORT_SetError(PR_WOULD_BLOCK_ERROR);
        rv = SECFailure;
    }
    return rv;
}
Пример #7
0
/*
** Send saved write data. This will flush out data sent prior to a
** complete security handshake. Hopefully there won't be too much of it.
** Returns count of the bytes sent, NOT a SECStatus.
** Caller must hold xmitBufLock
*/
int 
ssl_SendSavedWriteData(sslSocket *ss)
{
    int rv	= 0;

    PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
    if (ss->pendingBuf.len != 0) {
	SSL_TRC(5, ("%d: SSL[%d]: sending %d bytes of saved data",
		     SSL_GETPID(), ss->fd, ss->pendingBuf.len));
	rv = ssl_DefSend(ss, ss->pendingBuf.buf, ss->pendingBuf.len, 0);
	if (rv < 0) {
	    return rv;
	} 
	ss->pendingBuf.len -= rv;
	if (ss->pendingBuf.len > 0 && rv > 0) {
	    /* UGH !! This shifts the whole buffer down by copying it */
	    PORT_Memmove(ss->pendingBuf.buf, ss->pendingBuf.buf + rv, 
	                 ss->pendingBuf.len);
    	}
    }
    return rv;
}
Пример #8
0
/* Called from ssl3_SendClientKeyExchange(). */
SECStatus
ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
{
    PK11SymKey *	pms 		= NULL;
    SECStatus           rv    		= SECFailure;
    PRBool              isTLS, isTLS12;
    CK_MECHANISM_TYPE	target;
    SECKEYPublicKey	*pubKey = NULL;		/* Ephemeral ECDH key */
    SECKEYPrivateKey	*privKey = NULL;	/* Ephemeral ECDH 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);
    isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);

    /* Generate ephemeral EC keypair */
    if (svrPubKey->keyType != ecKey) {
	PORT_SetError(SEC_ERROR_BAD_KEY);
	goto loser;
    }
    /* XXX SHOULD CALL ssl3_CreateECDHEphemeralKeys here, instead! */
    privKey = SECKEY_CreateECPrivateKey(&svrPubKey->u.ec.DEREncodedParams, 
	                                &pubKey, ss->pkcs11PinArg);
    if (!privKey || !pubKey) {
	    ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
	    rv = SECFailure;
	    goto loser;
    }
    PRINT_BUF(50, (ss, "ECDH public value:",
					pubKey->u.ec.publicValue.data,
					pubKey->u.ec.publicValue.len));

    if (isTLS12) {
	target = CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256;
    } else if (isTLS) {
	target = CKM_TLS_MASTER_KEY_DERIVE_DH;
    } else {
	target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
    }

    /*  Determine the PMS */
    pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL,
			    CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
			    CKD_NULL, NULL, NULL);

    if (pms == NULL) {
	SSL3AlertDescription desc  = illegal_parameter;
	(void)SSL3_SendAlert(ss, alert_fatal, desc);
	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.ec.publicValue.len + 1);
    if (rv != SECSuccess) {
        goto loser;	/* err set by ssl3_AppendHandshake* */
    }

    rv = ssl3_AppendHandshakeVariable(ss, 
					pubKey->u.ec.publicValue.data,
					pubKey->u.ec.publicValue.len, 1);
    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;
}
Пример #9
0
/* Called from ssl3_SendClientKeyExchange(). */
SECStatus
ssl3_SendECDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey)
{
    PK11SymKey *pms = NULL;
    SECStatus rv = SECFailure;
    PRBool isTLS, isTLS12;
    CK_MECHANISM_TYPE target;
    const namedGroupDef *groupDef;
    sslEphemeralKeyPair *keyPair = NULL;
    SECKEYPublicKey *pubKey;

    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);
    isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);

    /* Generate ephemeral EC keypair */
    if (svrPubKey->keyType != ecKey) {
        PORT_SetError(SEC_ERROR_BAD_KEY);
        goto loser;
    }
    groupDef = ssl_ECPubKey2NamedGroup(svrPubKey);
    if (!groupDef) {
        PORT_SetError(SEC_ERROR_BAD_KEY);
        goto loser;
    }
    rv = ssl_CreateECDHEphemeralKeyPair(groupDef, &keyPair);
    if (rv != SECSuccess) {
        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
        goto loser;
    }

    pubKey = keyPair->keys->pubKey;
    PRINT_BUF(50, (ss, "ECDH public value:",
                   pubKey->u.ec.publicValue.data,
                   pubKey->u.ec.publicValue.len));

    if (isTLS12) {
        target = CKM_TLS12_MASTER_KEY_DERIVE_DH;
    } else if (isTLS) {
        target = CKM_TLS_MASTER_KEY_DERIVE_DH;
    } else {
        target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
    }

    /* Determine the PMS */
    pms = PK11_PubDeriveWithKDF(keyPair->keys->privKey, svrPubKey,
                                PR_FALSE, NULL, NULL, CKM_ECDH1_DERIVE, target,
                                CKA_DERIVE, 0, CKD_NULL, NULL, NULL);

    if (pms == NULL) {
        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
        goto loser;
    }

    rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
                                    pubKey->u.ec.publicValue.len + 1);
    if (rv != SECSuccess) {
        goto loser; /* err set by ssl3_AppendHandshake* */
    }

    rv = ssl3_AppendHandshakeVariable(ss, pubKey->u.ec.publicValue.data,
                                      pubKey->u.ec.publicValue.len, 1);

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

    rv = ssl3_InitPendingCipherSpec(ss, pms);
    if (rv != SECSuccess) {
        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
        goto loser;
    }

    PK11_FreeSymKey(pms);
    ssl_FreeEphemeralKeyPair(keyPair);
    return SECSuccess;

loser:
    if (pms)
        PK11_FreeSymKey(pms);
    if (keyPair)
        ssl_FreeEphemeralKeyPair(keyPair);
    return SECFailure;
}