Fix the logic in client and server to detect version roll-back attack,
rolling back from TLS (SSL 3.1) to SSL 3.0. Provide a new SSL socket option to disable roll-back detection in servers, since certain TLS clients are doing it incorrectly. git-svn-id: svn://10.0.0.236/trunk@70708 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
e4ad3d1501
commit
73f5156cca
@ -32,7 +32,7 @@
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: ssl3con.c,v 1.5 2000-05-18 15:32:18 mcgreer%netscape.com Exp $
|
||||
* $Id: ssl3con.c,v 1.6 2000-05-24 03:35:23 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "cert.h"
|
||||
@ -1813,6 +1813,7 @@ ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms)
|
||||
SECItem params;
|
||||
int keySize;
|
||||
CK_FLAGS keyFlags;
|
||||
CK_VERSION pms_version;
|
||||
CK_SSL3_KEY_MAT_PARAMS key_material_params;
|
||||
CK_SSL3_KEY_MAT_OUT returnedKeys;
|
||||
CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params;
|
||||
@ -1832,7 +1833,7 @@ ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms)
|
||||
}
|
||||
|
||||
if (pms || !pwSpec->master_secret) {
|
||||
master_params.pVersion = NULL;
|
||||
master_params.pVersion = &pms_version;
|
||||
master_params.RandomInfo.pClientRandom = cr;
|
||||
master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
|
||||
master_params.RandomInfo.pServerRandom = sr;
|
||||
@ -1846,6 +1847,15 @@ ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms)
|
||||
pwSpec->master_secret = PK11_DeriveWithFlags((PK11SymKey *)pms,
|
||||
master_derive, ¶ms, key_derive,
|
||||
CKA_DERIVE, 0, keyFlags);
|
||||
if (pwSpec->master_secret != NULL && ss->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);
|
||||
@ -2556,7 +2566,8 @@ ssl3_SendClientHello(sslSocket *ss)
|
||||
return rv; /* err set by ssl3_AppendHandshake* */
|
||||
}
|
||||
|
||||
rv = ssl3_AppendHandshakeNumber(ss, ss->version, 2);
|
||||
ss->clientHelloVersion = ss->version;
|
||||
rv = ssl3_AppendHandshakeNumber(ss, ss->clientHelloVersion, 2);
|
||||
if (rv != SECSuccess) {
|
||||
return rv; /* err set by ssl3_AppendHandshake* */
|
||||
}
|
||||
@ -4545,7 +4556,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
|
||||
tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
|
||||
if (tmp < 0)
|
||||
goto loser; /* malformed, alert already sent */
|
||||
version = (SSL3ProtocolVersion)tmp;
|
||||
ss->clientHelloVersion = version = (SSL3ProtocolVersion)tmp;
|
||||
rv = ssl3_NegotiateVersion(ss, version);
|
||||
if (rv != SECSuccess) {
|
||||
/* We can't do the usual isTLS test here, because the negotiated
|
||||
@ -4968,6 +4979,7 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length)
|
||||
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) {
|
||||
@ -5722,8 +5734,8 @@ ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
|
||||
}
|
||||
|
||||
/* Generate the pre-master secret ... */
|
||||
version.major = MSB(ss->version);
|
||||
version.minor = LSB(ss->version);
|
||||
version.major = MSB(ss->clientHelloVersion);
|
||||
version.minor = LSB(ss->clientHelloVersion);
|
||||
|
||||
param.data = (unsigned char *)&version;
|
||||
param.len = sizeof version;
|
||||
@ -5777,7 +5789,10 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss,
|
||||
}
|
||||
}
|
||||
/*
|
||||
* decrypt out of the incoming buffer
|
||||
* decrypt pms out of the incoming buffer
|
||||
* Note: CKM_SSL3_PRE_MASTER_KEY_GEN 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_PRE_MASTER_KEY_GEN, CKA_DERIVE, 0);
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: sslcon.c,v 1.1 2000-03-31 19:33:44 relyea%netscape.com Exp $
|
||||
* $Id: sslcon.c,v 1.2 2000-05-24 03:35:23 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "cert.h"
|
||||
@ -3075,16 +3075,15 @@ invalid:
|
||||
cp = msg = ci->sendBuf.buf;
|
||||
msg[0] = SSL_MT_CLIENT_HELLO;
|
||||
if ( ss->enableTLS ) {
|
||||
msg[1] = MSB(SSL_LIBRARY_VERSION_3_1_TLS);
|
||||
msg[2] = LSB(SSL_LIBRARY_VERSION_3_1_TLS);
|
||||
ss->clientHelloVersion = SSL_LIBRARY_VERSION_3_1_TLS;
|
||||
} else if ( ss->enableSSL3 ) {
|
||||
msg[1] = MSB(SSL_LIBRARY_VERSION_3_0);
|
||||
msg[2] = LSB(SSL_LIBRARY_VERSION_3_0);
|
||||
ss->clientHelloVersion = SSL_LIBRARY_VERSION_3_0;
|
||||
} else {
|
||||
msg[1] = MSB(SSL_LIBRARY_VERSION_2);
|
||||
msg[2] = LSB(SSL_LIBRARY_VERSION_2);
|
||||
ss->clientHelloVersion = SSL_LIBRARY_VERSION_2;
|
||||
}
|
||||
|
||||
msg[1] = MSB(ss->clientHelloVersion);
|
||||
msg[2] = LSB(ss->clientHelloVersion);
|
||||
msg[3] = MSB(localCipherSize);
|
||||
msg[4] = LSB(localCipherSize);
|
||||
msg[5] = MSB(sidLen);
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: sslimpl.h,v 1.2 2000-05-12 18:43:28 dougt%netscape.com Exp $
|
||||
* $Id: sslimpl.h,v 1.3 2000-05-24 03:35:23 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#ifndef __sslimpl_h_
|
||||
@ -222,6 +222,22 @@ typedef struct {
|
||||
|
||||
#define ssl_V3_SUITES_IMPLEMENTED 13
|
||||
|
||||
typedef struct sslOptionsStr {
|
||||
unsigned int useSecurity : 1; /* 1 */
|
||||
unsigned int useSocks : 1; /* 2 */
|
||||
unsigned int requestCertificate : 1; /* 3 */
|
||||
unsigned int requireCertificate : 2; /* 4-5 */
|
||||
unsigned int handshakeAsClient : 1; /* 6 */
|
||||
unsigned int handshakeAsServer : 1; /* 7 */
|
||||
unsigned int enableSSL2 : 1; /* 8 */
|
||||
unsigned int enableSSL3 : 1; /* 9 */
|
||||
unsigned int enableTLS : 1; /* 10 */
|
||||
unsigned int noCache : 1; /* 11 */
|
||||
unsigned int fdx : 1; /* 12 */
|
||||
unsigned int v2CompatibleHello : 1; /* 13 */
|
||||
unsigned int detectRollBack : 1; /* 14 */
|
||||
} sslOptions;
|
||||
|
||||
/*
|
||||
** SSL Socket struct
|
||||
**
|
||||
@ -249,11 +265,13 @@ struct sslSocketStr {
|
||||
unsigned int noCache : 1;
|
||||
unsigned int fdx : 1; /* simultaneous read/write threads */
|
||||
unsigned int v2CompatibleHello : 1; /* Send v3+ client hello in v2 format */
|
||||
unsigned int detectRollBack : 1; /* Detect rollback to SSL v3 */
|
||||
unsigned int connected : 1; /* initial handshake is complete. */
|
||||
unsigned int recvdCloseNotify : 1; /* received SSL EOF. */
|
||||
|
||||
/* version of the protocol to use */
|
||||
SSL3ProtocolVersion version;
|
||||
SSL3ProtocolVersion clientHelloVersion; /* version sent in client hello. */
|
||||
|
||||
/* Non-zero if socks is enabled */
|
||||
sslSocksInfo * socks;
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: sslsock.c,v 1.1 2000-03-31 19:37:07 relyea%netscape.com Exp $
|
||||
* $Id: sslsock.c,v 1.2 2000-05-24 03:35:23 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
#include "seccomon.h"
|
||||
#include "cert.h"
|
||||
@ -145,20 +145,7 @@ sslSocketOps ssl_secure_socks_ops = { /* Both SSL and Socks. */
|
||||
/*
|
||||
** default settings for socket enables
|
||||
*/
|
||||
static struct {
|
||||
unsigned int useSecurity : 1;
|
||||
unsigned int useSocks : 1;
|
||||
unsigned int requestCertificate : 1;
|
||||
unsigned int requireCertificate : 2;
|
||||
unsigned int handshakeAsClient : 1;
|
||||
unsigned int handshakeAsServer : 1;
|
||||
unsigned int enableSSL2 : 1;
|
||||
unsigned int enableSSL3 : 1;
|
||||
unsigned int enableTLS : 1;
|
||||
unsigned int noCache : 1;
|
||||
unsigned int fdx : 1;
|
||||
unsigned int v2CompatibleHello : 1;
|
||||
} ssl_defaults = {
|
||||
static sslOptions ssl_defaults = {
|
||||
PR_TRUE, /* useSecurity */
|
||||
PR_FALSE, /* useSocks */
|
||||
PR_FALSE, /* requestCertificate */
|
||||
@ -167,10 +154,11 @@ static struct {
|
||||
PR_FALSE, /* handshakeAsServer */
|
||||
PR_TRUE, /* enableSSL2 */
|
||||
PR_TRUE, /* enableSSL3 */
|
||||
PR_FALSE, /* enableTLS */
|
||||
PR_TRUE, /* enableTLS */ /* now defaults to on in NSS 3.0 */
|
||||
PR_FALSE, /* noCache */
|
||||
PR_FALSE, /* fdx */
|
||||
PR_TRUE, /* v2CompatibleHello */
|
||||
PR_TRUE, /* detectRollBack */
|
||||
};
|
||||
|
||||
sslSessionIDLookupFunc ssl_sid_lookup;
|
||||
@ -260,6 +248,7 @@ ssl_DupSocket(sslSocket *os)
|
||||
ss->noCache = os->noCache;
|
||||
ss->fdx = os->fdx;
|
||||
ss->v2CompatibleHello = os->v2CompatibleHello;
|
||||
ss->detectRollBack = os->detectRollBack;
|
||||
ss->peerID = !os->peerID ? NULL : PORT_Strdup(os->peerID);
|
||||
ss->url = !os->url ? NULL : PORT_Strdup(os->url);
|
||||
|
||||
@ -596,6 +585,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
|
||||
}
|
||||
break;
|
||||
|
||||
case SSL_ROLLBACK_DETECTION:
|
||||
ss->detectRollBack = on;
|
||||
break;
|
||||
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
rv = SECFailure;
|
||||
@ -641,6 +634,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
|
||||
case SSL_NO_CACHE: on = ss->noCache; break;
|
||||
case SSL_ENABLE_FDX: on = ss->fdx; break;
|
||||
case SSL_V2_COMPATIBLE_HELLO: on = ss->v2CompatibleHello; break;
|
||||
case SSL_ROLLBACK_DETECTION: on = ss->detectRollBack; break;
|
||||
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
@ -678,6 +672,7 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
|
||||
case SSL_NO_CACHE: on = ssl_defaults.noCache; break;
|
||||
case SSL_ENABLE_FDX: on = ssl_defaults.fdx; break;
|
||||
case SSL_V2_COMPATIBLE_HELLO: on = ssl_defaults.v2CompatibleHello; break;
|
||||
case SSL_ROLLBACK_DETECTION: on = ssl_defaults.detectRollBack; break;
|
||||
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
@ -760,6 +755,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
|
||||
}
|
||||
break;
|
||||
|
||||
case SSL_ROLLBACK_DETECTION:
|
||||
ssl_defaults.detectRollBack = on;
|
||||
break;
|
||||
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
@ -1769,6 +1768,7 @@ ssl_NewSocket(void)
|
||||
ss->enableTLS = ssl_defaults.enableTLS ;
|
||||
ss->fdx = ssl_defaults.fdx;
|
||||
ss->v2CompatibleHello = ssl_defaults.v2CompatibleHello;
|
||||
ss->detectRollBack = ssl_defaults.detectRollBack;
|
||||
ss->peer = 0;
|
||||
ss->port = 0;
|
||||
ss->noCache = ssl_defaults.noCache;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user