diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-07 22:10:06 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-07 22:10:06 +0000 |
commit | ef21c83524b111067f2d8b175d034fd08a51583a (patch) | |
tree | a821c67de1fe830576887b5c962130deedf3ac7d /net | |
parent | 793d3a3c7137f9df125322b9c7b342000cc4ad52 (diff) | |
download | chromium_src-ef21c83524b111067f2d8b175d034fd08a51583a.zip chromium_src-ef21c83524b111067f2d8b175d034fd08a51583a.tar.gz chromium_src-ef21c83524b111067f2d8b175d034fd08a51583a.tar.bz2 |
net: Precede each CBC encrypted application data record with an empty one.
Precede each CBC encrypted application data record with an empty
application data record in order to randomize the IV in a backwards
compatible manner.
(This is a reland of r90632 which was reverted in r90643 because it tickled a
bug in remoting unittests.)
http://codereview.chromium.org/7239002
BUG=87159
TEST=HTTPS sites continue to work.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@91768 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/socket/ssl_client_socket_unittest.cc | 2 | ||||
-rw-r--r-- | net/third_party/nss/README.chromium | 5 | ||||
-rwxr-xr-x | net/third_party/nss/patches/applypatches.sh | 2 | ||||
-rw-r--r-- | net/third_party/nss/patches/cbcrandomiv.patch | 73 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3con.c | 28 |
5 files changed, 107 insertions, 3 deletions
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index 49c9191..9946c90 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc @@ -396,7 +396,7 @@ TEST_F(SSLClientSocketTest, Read_FullDuplex) { // memio circular buffer (4k bytes) in SSLClientSocketNSS to wrap around. // This tests the fix for http://crbug.com/29815. std::string request_text = "GET / HTTP/1.1\r\nUser-Agent: long browser name "; - for (int i = 0; i < 3800; ++i) + for (int i = 0; i < 3768; ++i) request_text.push_back('*'); request_text.append("\r\n\r\n"); scoped_refptr<net::IOBuffer> request_buffer( diff --git a/net/third_party/nss/README.chromium b/net/third_party/nss/README.chromium index 4960c63..02793ef 100644 --- a/net/third_party/nss/README.chromium +++ b/net/third_party/nss/README.chromium @@ -51,6 +51,11 @@ Patches: previous session. patches/didhandshakeresume.patch + * Precede each set of CBC encrypted application data records, resulting from + a single call to ssl3_SendApplicationData, with an empty application data + record in order to randomize the IV in a backwards compatible manner. + patches/cbcrandomiv.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 3fd7993..9aafb92 100755 --- a/net/third_party/nss/patches/applypatches.sh +++ b/net/third_party/nss/patches/applypatches.sh @@ -22,3 +22,5 @@ patch -p6 < $patches_dir/clientauth.patch patch -p6 < $patches_dir/cachedinfo.patch patch -p6 < $patches_dir/didhandshakeresume.patch + +patch -p6 < $patches_dir/cbcrandomiv.patch diff --git a/net/third_party/nss/patches/cbcrandomiv.patch b/net/third_party/nss/patches/cbcrandomiv.patch new file mode 100644 index 0000000..9f1b57a --- /dev/null +++ b/net/third_party/nss/patches/cbcrandomiv.patch @@ -0,0 +1,73 @@ +commit 36840201a321147d9c33a944784ff56980aae5d8 +Author: Adam Langley <agl@chromium.org> +Date: Wed Jun 22 13:36:50 2011 -0400 + + cbcrandomiv.patch + +diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c +index 2cc1e05..eb7d63e 100644 +--- a/mozilla/security/nss/lib/ssl/ssl3con.c ++++ b/mozilla/security/nss/lib/ssl/ssl3con.c +@@ -2229,7 +2229,7 @@ ssl3_SendRecord( sslSocket * ss, + return SECFailure; + } + +- while (nIn > 0) { ++ do { + PRUint32 contentLen = PR_MIN(nIn, MAX_FRAGMENT_LENGTH); + + if (wrBuf->space < contentLen + SSL3_BUFFER_FUDGE) { +@@ -2306,7 +2306,7 @@ ssl3_SendRecord( sslSocket * ss, + } + } + totalSent += contentLen; +- } ++ } while (nIn > 0); + return totalSent; + } + +@@ -2321,6 +2321,7 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, + { + PRInt32 totalSent = 0; + PRInt32 discarded = 0; ++ PRBool isBlockCipher; + + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); + if (len < 0 || !in) { +@@ -2345,6 +2346,28 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, + len--; + discarded = 1; + } ++ ++ ssl_GetSpecReadLock(ss); ++ isBlockCipher = ss->ssl3.cwSpec->cipher_def->type == type_block; ++ ssl_ReleaseSpecReadLock(ss); ++ ++ if (isBlockCipher && len > 0) { ++ // We assume that block ciphers are used in CBC mode and prepend an ++ // empty record. This effectively randomizes the IV in a backwards ++ // compatible way. ++ PRInt32 sent = ssl3_SendRecord(ss, content_application_data, ++ in, 0 /* no payload */, flags); ++ if (sent < 0) { ++ return SECFailure; /* error code set by ssl3_SendRecord */ ++ } ++ if (ss->pendingBuf.len) { ++ /* must be a non-blocking socket */ ++ PORT_Assert(!ssl_SocketIsBlocking(ss)); ++ PORT_Assert(ss->lastWriteBlocked); ++ return SECFailure; ++ } ++ } ++ + while (len > totalSent) { + PRInt32 sent, toSend; + +@@ -2377,6 +2400,7 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, + break; + } + } ++ + if (ss->pendingBuf.len) { + /* Must be non-blocking. */ + PORT_Assert(!ssl_SocketIsBlocking(ss)); diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c index 2cc1e05..eb7d63e 100644 --- a/net/third_party/nss/ssl/ssl3con.c +++ b/net/third_party/nss/ssl/ssl3con.c @@ -2229,7 +2229,7 @@ ssl3_SendRecord( sslSocket * ss, return SECFailure; } - while (nIn > 0) { + do { PRUint32 contentLen = PR_MIN(nIn, MAX_FRAGMENT_LENGTH); if (wrBuf->space < contentLen + SSL3_BUFFER_FUDGE) { @@ -2306,7 +2306,7 @@ ssl3_SendRecord( sslSocket * ss, } } totalSent += contentLen; - } + } while (nIn > 0); return totalSent; } @@ -2321,6 +2321,7 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, { PRInt32 totalSent = 0; PRInt32 discarded = 0; + PRBool isBlockCipher; PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); if (len < 0 || !in) { @@ -2345,6 +2346,28 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, len--; discarded = 1; } + + ssl_GetSpecReadLock(ss); + isBlockCipher = ss->ssl3.cwSpec->cipher_def->type == type_block; + ssl_ReleaseSpecReadLock(ss); + + if (isBlockCipher && len > 0) { + // We assume that block ciphers are used in CBC mode and prepend an + // empty record. This effectively randomizes the IV in a backwards + // compatible way. + PRInt32 sent = ssl3_SendRecord(ss, content_application_data, + in, 0 /* no payload */, flags); + if (sent < 0) { + return SECFailure; /* error code set by ssl3_SendRecord */ + } + if (ss->pendingBuf.len) { + /* must be a non-blocking socket */ + PORT_Assert(!ssl_SocketIsBlocking(ss)); + PORT_Assert(ss->lastWriteBlocked); + return SECFailure; + } + } + while (len > totalSent) { PRInt32 sent, toSend; @@ -2377,6 +2400,7 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, break; } } + if (ss->pendingBuf.len) { /* Must be non-blocking. */ PORT_Assert(!ssl_SocketIsBlocking(ss)); |