diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-17 18:52:27 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-17 18:52:27 +0000 |
commit | 513276f41ca989762139ccf87852be28d4f54dcc (patch) | |
tree | d70b8a76448023905ab11cd98782766a3765c5b2 /net/third_party | |
parent | c1190589fd6d6b77bf11f1d321d0524ba18a7e89 (diff) | |
download | chromium_src-513276f41ca989762139ccf87852be28d4f54dcc.zip chromium_src-513276f41ca989762139ccf87852be28d4f54dcc.tar.gz chromium_src-513276f41ca989762139ccf87852be28d4f54dcc.tar.bz2 |
Cap the record layer version number of TLS ClientHello to TLS 1.0
if we don't know what TLS version the server supports.
Fix the -p option for the patch commands in applypatches.sh.
R=agl@chromium.org,rsleevi@chromium.org
BUG=136666
TEST=manual: visit https://cybozulive.com/, https://www.billpaysite.com/,
and https://members.mh-frontier.jp/mypage/ on Linux or Mac. The connection
should succeed.
Review URL: https://chromiumcodereview.appspot.com/10777021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@147056 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/third_party')
-rw-r--r-- | net/third_party/nss/README.chromium | 5 | ||||
-rwxr-xr-x | net/third_party/nss/patches/applypatches.sh | 14 | ||||
-rw-r--r-- | net/third_party/nss/patches/getchannelinfo.patch | 6 | ||||
-rw-r--r-- | net/third_party/nss/patches/recordlayerversion.patch | 186 | ||||
-rw-r--r-- | net/third_party/nss/ssl/dtls1con.c | 3 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3con.c | 54 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslimpl.h | 3 |
7 files changed, 252 insertions, 19 deletions
diff --git a/net/third_party/nss/README.chromium b/net/third_party/nss/README.chromium index fd4238f..95e7973 100644 --- a/net/third_party/nss/README.chromium +++ b/net/third_party/nss/README.chromium @@ -85,6 +85,11 @@ Patches: * Don't crash when the SSL keylog file cannot be opened. patches/sslkeylogerror.patch + * Sets the record layer version number of ClientHello to at most TLS 1.0 + if we don't know what protocol version the server supports. + https://bugzilla.mozilla.org/show_bug.cgi?id=774547 + patches/recordlayerversion.patch + Apply the patches to NSS by running the patches/applypatches.sh script. Read the comments at the top of patches/applypatches.sh for instructions. diff --git a/net/third_party/nss/patches/applypatches.sh b/net/third_party/nss/patches/applypatches.sh index b586613..b5736ad9 100755 --- a/net/third_party/nss/patches/applypatches.sh +++ b/net/third_party/nss/patches/applypatches.sh @@ -3,8 +3,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# Run this script in the mozilla/security/nss/lib directory in a NSS source -# tree. +# Run this script in the mozilla/security/nss/lib/ssl directory in a NSS +# source tree. # # Point patches_dir to the src/net/third_party/nss/patches directory in a # chromium source tree. @@ -36,14 +36,16 @@ patch -p5 < $patches_dir/falsestartnpn.patch patch -p5 < $patches_dir/dhvalues.patch -patch -p4 < $patches_dir/channelid.patch +patch -p5 < $patches_dir/channelid.patch patch -p4 < $patches_dir/dtlssrtp.patch -patch -p4 < $patches_dir/keylog.patch +patch -p5 < $patches_dir/keylog.patch patch -p4 < $patches_dir/getchannelinfo.patch -patch -p4 < $patches_dir/tlsunique.patch +patch -p5 < $patches_dir/tlsunique.patch -patch -p4 < $patches_dir/sslkeylogerror.patch +patch -p5 < $patches_dir/sslkeylogerror.patch + +patch -p4 < $patches_dir/recordlayerversion.patch diff --git a/net/third_party/nss/patches/getchannelinfo.patch b/net/third_party/nss/patches/getchannelinfo.patch index 530b7fe..f6bd0e0 100644 --- a/net/third_party/nss/patches/getchannelinfo.patch +++ b/net/third_party/nss/patches/getchannelinfo.patch @@ -1,7 +1,7 @@ -Index: ssl/sslinfo.c +Index: net/third_party/nss/ssl/sslinfo.c =================================================================== ---- ssl/sslinfo.c (revision 142907) -+++ ssl/sslinfo.c (working copy) +--- net/third_party/nss/ssl/sslinfo.c (revision 143014) ++++ net/third_party/nss/ssl/sslinfo.c (revision 143015) @@ -97,11 +97,11 @@ } else if (ss->ssl3.initialized) { /* SSL3 and TLS */ ssl_GetSpecReadLock(ss); diff --git a/net/third_party/nss/patches/recordlayerversion.patch b/net/third_party/nss/patches/recordlayerversion.patch new file mode 100644 index 0000000..f43241c --- /dev/null +++ b/net/third_party/nss/patches/recordlayerversion.patch @@ -0,0 +1,186 @@ +Index: net/third_party/nss/ssl/sslimpl.h +=================================================================== +--- net/third_party/nss/ssl/sslimpl.h (revision 146623) ++++ net/third_party/nss/ssl/sslimpl.h (working copy) +@@ -294,6 +294,8 @@ + #define ssl_SEND_FLAG_NO_BUFFER 0x20000000 + #define ssl_SEND_FLAG_USE_EPOCH 0x10000000 /* DTLS only */ + #define ssl_SEND_FLAG_NO_RETRANSMIT 0x08000000 /* DTLS only */ ++#define ssl_SEND_FLAG_CAP_RECORD_VERSION \ ++ 0x04000000 /* TLS only */ + #define ssl_SEND_FLAG_MASK 0x7f000000 + + /* +@@ -1414,6 +1416,7 @@ + ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, + PRBool isServer, + PRBool isDTLS, ++ PRBool capRecordVersion, + SSL3ContentType type, + const SSL3Opaque * pIn, + PRUint32 contentLen, +Index: net/third_party/nss/ssl/ssl3con.c +=================================================================== +--- net/third_party/nss/ssl/ssl3con.c (revision 146623) ++++ net/third_party/nss/ssl/ssl3con.c (working copy) +@@ -2057,6 +2057,7 @@ + ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, + PRBool isServer, + PRBool isDTLS, ++ PRBool capRecordVersion, + SSL3ContentType type, + const SSL3Opaque * pIn, + PRUint32 contentLen, +@@ -2216,8 +2217,13 @@ + wrBuf->buf[11] = MSB(cipherBytes); + wrBuf->buf[12] = LSB(cipherBytes); + } else { +- wrBuf->buf[1] = MSB(cwSpec->version); +- wrBuf->buf[2] = LSB(cwSpec->version); ++ SSL3ProtocolVersion version = cwSpec->version; ++ ++ if (capRecordVersion) { ++ version = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0, version); ++ } ++ wrBuf->buf[1] = MSB(version); ++ wrBuf->buf[2] = LSB(version); + wrBuf->buf[3] = MSB(cipherBytes); + wrBuf->buf[4] = LSB(cipherBytes); + } +@@ -2247,7 +2253,14 @@ + * all ciphertext into the pending ciphertext buffer. + * ssl_SEND_FLAG_USE_EPOCH (for DTLS) + * Forces the use of the provided epoch +- * ++ * ssl_SEND_FLAG_CAP_RECORD_VERSION ++ * Caps the record layer version number of TLS ClientHello to { 3, 1 } ++ * (TLS 1.0). Some TLS 1.0 servers (which seem to use F5 BIG-IP) ignore ++ * ClientHello.client_version and use the record layer version number ++ * (TLSPlaintext.version) instead when negotiating protocol versions. In ++ * addition, if the record layer version number of ClientHello is { 3, 2 } ++ * (TLS 1.1) or higher, these servers reset the TCP connections. Set this ++ * flag to work around such servers. + */ + PRInt32 + ssl3_SendRecord( sslSocket * ss, +@@ -2260,6 +2273,7 @@ + sslBuffer * wrBuf = &ss->sec.writeBuf; + SECStatus rv; + PRInt32 totalSent = 0; ++ PRBool capRecordVersion; + + SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d", + SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type), +@@ -2268,6 +2282,16 @@ + + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); + ++ capRecordVersion = ((flags & ssl_SEND_FLAG_CAP_RECORD_VERSION) != 0); ++ ++ if (capRecordVersion) { ++ /* ssl_SEND_FLAG_CAP_RECORD_VERSION can only be used with ++ * TLS ClientHello. */ ++ PORT_Assert(!IS_DTLS(ss)); ++ PORT_Assert(type == content_handshake); ++ PORT_Assert(ss->ssl3.hs.ws == wait_server_hello); ++ } ++ + if (ss->ssl3.initialized == PR_FALSE) { + /* This can happen on a server if the very first incoming record + ** looks like a defective ssl3 record (e.g. too long), and we're +@@ -2324,7 +2348,8 @@ + + rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, + ss->sec.isServer, IS_DTLS(ss), +- type, pIn, 1, wrBuf); ++ capRecordVersion, type, pIn, ++ 1, wrBuf); + if (rv != SECSuccess) + goto spec_locked_loser; + +@@ -2337,7 +2362,8 @@ + + rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, + ss->sec.isServer, IS_DTLS(ss), +- type, pIn + 1, contentLen - 1, ++ capRecordVersion, type, ++ pIn + 1, contentLen - 1, + &secondRecord); + if (rv == SECSuccess) { + PRINT_BUF(50, (ss, "send (encrypted) record data [2/2]:", +@@ -2349,6 +2375,7 @@ + rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, + ss->sec.isServer, + IS_DTLS(ss), ++ capRecordVersion, + type, pIn, + contentLen, wrBuf); + } else { +@@ -2560,6 +2587,8 @@ + static SECStatus + ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags) + { ++ static const PRInt32 allowedFlags = ssl_SEND_FLAG_FORCE_INTO_BUFFER | ++ ssl_SEND_FLAG_CAP_RECORD_VERSION; + PRInt32 rv = SECSuccess; + + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); +@@ -2568,9 +2597,9 @@ + 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) { ++ /* only these flags are allowed */ ++ PORT_Assert(!(flags & ~allowedFlags)); ++ if ((flags & ~allowedFlags) != 0) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; + } else { +@@ -3981,8 +4010,10 @@ + int num_suites; + int actual_count = 0; + PRBool isTLS = PR_FALSE; ++ PRBool serverVersionKnown = PR_FALSE; + PRInt32 total_exten_len = 0; + unsigned numCompressionMethods; ++ PRInt32 flags; + + SSL_TRC(3, ("%d: SSL3[%d]: send client_hello handshake", SSL_GETPID(), + ss->fd)); +@@ -4070,6 +4101,7 @@ + } + + if (sid) { ++ serverVersionKnown = PR_TRUE; + SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_hits ); + + /* Are we attempting a stateless session resume? */ +@@ -4305,7 +4337,11 @@ + ssl_renegotiation_info_xtn; + } + +- rv = ssl3_FlushHandshake(ss, 0); ++ flags = 0; ++ if (!serverVersionKnown && !IS_DTLS(ss)) { ++ flags |= ssl_SEND_FLAG_CAP_RECORD_VERSION; ++ } ++ rv = ssl3_FlushHandshake(ss, flags); + if (rv != SECSuccess) { + return rv; /* error code set by ssl3_FlushHandshake */ + } +Index: net/third_party/nss/ssl/dtls1con.c +=================================================================== +--- net/third_party/nss/ssl/dtls1con.c (revision 146623) ++++ net/third_party/nss/ssl/dtls1con.c (working copy) +@@ -834,7 +834,8 @@ + + if (cwSpec) { + rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE, +- type, pIn, contentLen, wrBuf); ++ PR_FALSE, type, pIn, contentLen, ++ wrBuf); + } else { + PR_NOT_REACHED("Couldn't find a cipher spec matching epoch"); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); diff --git a/net/third_party/nss/ssl/dtls1con.c b/net/third_party/nss/ssl/dtls1con.c index a020416..a0d4318 100644 --- a/net/third_party/nss/ssl/dtls1con.c +++ b/net/third_party/nss/ssl/dtls1con.c @@ -834,7 +834,8 @@ dtls_CompressMACEncryptRecord(sslSocket * ss, if (cwSpec) { rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE, - type, pIn, contentLen, wrBuf); + PR_FALSE, type, pIn, contentLen, + wrBuf); } else { PR_NOT_REACHED("Couldn't find a cipher spec matching epoch"); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c index 1f6def2..e7741a0 100644 --- a/net/third_party/nss/ssl/ssl3con.c +++ b/net/third_party/nss/ssl/ssl3con.c @@ -2057,6 +2057,7 @@ SECStatus ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, PRBool isServer, PRBool isDTLS, + PRBool capRecordVersion, SSL3ContentType type, const SSL3Opaque * pIn, PRUint32 contentLen, @@ -2216,8 +2217,13 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, wrBuf->buf[11] = MSB(cipherBytes); wrBuf->buf[12] = LSB(cipherBytes); } else { - wrBuf->buf[1] = MSB(cwSpec->version); - wrBuf->buf[2] = LSB(cwSpec->version); + SSL3ProtocolVersion version = cwSpec->version; + + if (capRecordVersion) { + version = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0, version); + } + wrBuf->buf[1] = MSB(version); + wrBuf->buf[2] = LSB(version); wrBuf->buf[3] = MSB(cipherBytes); wrBuf->buf[4] = LSB(cipherBytes); } @@ -2247,7 +2253,14 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, * all ciphertext into the pending ciphertext buffer. * ssl_SEND_FLAG_USE_EPOCH (for DTLS) * Forces the use of the provided epoch - * + * ssl_SEND_FLAG_CAP_RECORD_VERSION + * Caps the record layer version number of TLS ClientHello to { 3, 1 } + * (TLS 1.0). Some TLS 1.0 servers (which seem to use F5 BIG-IP) ignore + * ClientHello.client_version and use the record layer version number + * (TLSPlaintext.version) instead when negotiating protocol versions. In + * addition, if the record layer version number of ClientHello is { 3, 2 } + * (TLS 1.1) or higher, these servers reset the TCP connections. Set this + * flag to work around such servers. */ PRInt32 ssl3_SendRecord( sslSocket * ss, @@ -2260,6 +2273,7 @@ ssl3_SendRecord( sslSocket * ss, sslBuffer * wrBuf = &ss->sec.writeBuf; SECStatus rv; PRInt32 totalSent = 0; + PRBool capRecordVersion; SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d", SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type), @@ -2268,6 +2282,16 @@ ssl3_SendRecord( sslSocket * ss, PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); + capRecordVersion = ((flags & ssl_SEND_FLAG_CAP_RECORD_VERSION) != 0); + + if (capRecordVersion) { + /* ssl_SEND_FLAG_CAP_RECORD_VERSION can only be used with + * TLS ClientHello. */ + PORT_Assert(!IS_DTLS(ss)); + PORT_Assert(type == content_handshake); + PORT_Assert(ss->ssl3.hs.ws == wait_server_hello); + } + if (ss->ssl3.initialized == PR_FALSE) { /* This can happen on a server if the very first incoming record ** looks like a defective ssl3 record (e.g. too long), and we're @@ -2324,7 +2348,8 @@ ssl3_SendRecord( sslSocket * ss, rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, ss->sec.isServer, IS_DTLS(ss), - type, pIn, 1, wrBuf); + capRecordVersion, type, pIn, + 1, wrBuf); if (rv != SECSuccess) goto spec_locked_loser; @@ -2337,7 +2362,8 @@ ssl3_SendRecord( sslSocket * ss, rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, ss->sec.isServer, IS_DTLS(ss), - type, pIn + 1, contentLen - 1, + capRecordVersion, type, + pIn + 1, contentLen - 1, &secondRecord); if (rv == SECSuccess) { PRINT_BUF(50, (ss, "send (encrypted) record data [2/2]:", @@ -2349,6 +2375,7 @@ ssl3_SendRecord( sslSocket * ss, rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, ss->sec.isServer, IS_DTLS(ss), + capRecordVersion, type, pIn, contentLen, wrBuf); } else { @@ -2560,6 +2587,8 @@ ssl3_FlushHandshake(sslSocket *ss, PRInt32 flags) static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags) { + static const PRInt32 allowedFlags = ssl_SEND_FLAG_FORCE_INTO_BUFFER | + ssl_SEND_FLAG_CAP_RECORD_VERSION; PRInt32 rv = SECSuccess; PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); @@ -2568,9 +2597,9 @@ ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags) 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) { + /* only these flags are allowed */ + PORT_Assert(!(flags & ~allowedFlags)); + if ((flags & ~allowedFlags) != 0) { PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; } else { @@ -3981,8 +4010,10 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending) int num_suites; int actual_count = 0; PRBool isTLS = PR_FALSE; + PRBool serverVersionKnown = PR_FALSE; PRInt32 total_exten_len = 0; unsigned numCompressionMethods; + PRInt32 flags; SSL_TRC(3, ("%d: SSL3[%d]: send client_hello handshake", SSL_GETPID(), ss->fd)); @@ -4070,6 +4101,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending) } if (sid) { + serverVersionKnown = PR_TRUE; SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_hits ); /* Are we attempting a stateless session resume? */ @@ -4305,7 +4337,11 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending) ssl_renegotiation_info_xtn; } - rv = ssl3_FlushHandshake(ss, 0); + flags = 0; + if (!serverVersionKnown && !IS_DTLS(ss)) { + flags |= ssl_SEND_FLAG_CAP_RECORD_VERSION; + } + rv = ssl3_FlushHandshake(ss, flags); if (rv != SECSuccess) { return rv; /* error code set by ssl3_FlushHandshake */ } diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h index eda1885..e482ae5 100644 --- a/net/third_party/nss/ssl/sslimpl.h +++ b/net/third_party/nss/ssl/sslimpl.h @@ -294,6 +294,8 @@ struct sslSocketOpsStr { #define ssl_SEND_FLAG_NO_BUFFER 0x20000000 #define ssl_SEND_FLAG_USE_EPOCH 0x10000000 /* DTLS only */ #define ssl_SEND_FLAG_NO_RETRANSMIT 0x08000000 /* DTLS only */ +#define ssl_SEND_FLAG_CAP_RECORD_VERSION \ + 0x04000000 /* TLS only */ #define ssl_SEND_FLAG_MASK 0x7f000000 /* @@ -1414,6 +1416,7 @@ extern SECStatus ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, PRBool isServer, PRBool isDTLS, + PRBool capRecordVersion, SSL3ContentType type, const SSL3Opaque * pIn, PRUint32 contentLen, |