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:
nelsonb%netscape.com 2000-05-24 03:35:23 +00:00
parent e4ad3d1501
commit 73f5156cca
4 changed files with 63 additions and 31 deletions

View File

@ -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, &params, 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);

View File

@ -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);

View File

@ -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;

View File

@ -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;