diff options
-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 09da4d9..f0c757c 100644 --- a/net/third_party/nss/README.chromium +++ b/net/third_party/nss/README.chromium @@ -47,6 +47,11 @@ Patches: patches/cachedinfo.patch https://bugzilla.mozilla.org/show_bug.cgi?id=665739 + * 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 c6609ca..b58fe5e 100755 --- a/net/third_party/nss/patches/applypatches.sh +++ b/net/third_party/nss/patches/applypatches.sh @@ -20,3 +20,5 @@ patch -p6 < $patches_dir/ocspstapling.patch patch -p6 < $patches_dir/clientauth.patch patch -p6 < $patches_dir/cachedinfo.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)); |