summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/socket/ssl_client_socket_unittest.cc2
-rw-r--r--net/third_party/nss/README.chromium5
-rwxr-xr-xnet/third_party/nss/patches/applypatches.sh2
-rw-r--r--net/third_party/nss/patches/cbcrandomiv.patch73
-rw-r--r--net/third_party/nss/ssl/ssl3con.c28
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));