diff options
author | nelsonb%netscape.com <devnull@localhost> | 2000-05-24 03:35:23 +0000 |
---|---|---|
committer | nelsonb%netscape.com <devnull@localhost> | 2000-05-24 03:35:23 +0000 |
commit | 065d4a55f094775d6542b63d76830a2a0770c64f (patch) | |
tree | 2c4068a9be4f9972280a07f09dfbc7947d3c1474 /security | |
parent | 3dbb48e7be67b2872965c52d8c4cdde166003593 (diff) | |
download | nss-hg-065d4a55f094775d6542b63d76830a2a0770c64f.tar.gz |
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.
Diffstat (limited to 'security')
-rw-r--r-- | security/nss/lib/ssl/ssl3con.c | 27 | ||||
-rw-r--r-- | security/nss/lib/ssl/sslcon.c | 11 | ||||
-rw-r--r-- | security/nss/lib/ssl/sslimpl.h | 18 | ||||
-rw-r--r-- | security/nss/lib/ssl/sslsock.c | 30 |
4 files changed, 59 insertions, 27 deletions
diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index d2826ca09..93d5b2773 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -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); diff --git a/security/nss/lib/ssl/sslcon.c b/security/nss/lib/ssl/sslcon.c index 1f3069c5f..16b1c8570 100644 --- a/security/nss/lib/ssl/sslcon.c +++ b/security/nss/lib/ssl/sslcon.c @@ -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); diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index db5d7a83b..fe4a68f27 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/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; diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index bafae8554..2921e3b6c 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -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; |