diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-30 19:23:14 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-30 19:23:14 +0000 |
commit | 74420021f4dccfd255b87088617c064ce83e0d55 (patch) | |
tree | db4f7e79921e3ee6efa389a772ce0c560676d75f /net/third_party | |
parent | 9021148bc55f5dc94cb3944d63015289683be2fd (diff) | |
download | chromium_src-74420021f4dccfd255b87088617c064ce83e0d55.zip chromium_src-74420021f4dccfd255b87088617c064ce83e0d55.tar.gz chromium_src-74420021f4dccfd255b87088617c064ce83e0d55.tar.bz2 |
Update cbcrandomiv.patch to the currently proposed patch (v10) for the
NSS upstream in https://bugzilla.mozilla.org/show_bug.cgi?id=665814.
R=agl@chromium.org
BUG=87159
TEST=HTTPS sites continue to work.
Review URL: http://codereview.chromium.org/8084004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@103517 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/third_party')
-rw-r--r-- | net/third_party/nss/patches/cbcrandomiv.patch | 265 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3con.c | 127 |
2 files changed, 286 insertions, 106 deletions
diff --git a/net/third_party/nss/patches/cbcrandomiv.patch b/net/third_party/nss/patches/cbcrandomiv.patch index 16f2609..445b2f9 100644 --- a/net/third_party/nss/patches/cbcrandomiv.patch +++ b/net/third_party/nss/patches/cbcrandomiv.patch @@ -1,59 +1,226 @@ Index: mozilla/security/nss/lib/ssl/ssl3con.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/ssl/ssl3con.c,v -retrieving revision 1.142.2.5 -diff -u -p -u -r1.142.2.5 ssl3con.c ---- mozilla/security/nss/lib/ssl/ssl3con.c 25 Jan 2011 01:49:22 -0000 1.142.2.5 -+++ mozilla/security/nss/lib/ssl/ssl3con.c 11 Aug 2011 02:15:58 -0000 -@@ -2315,6 +2315,8 @@ ssl3_SendApplicationData(sslSocket *ss, +retrieving revision 1.151 +diff -u -p -8 -r1.151 ssl3con.c +--- mozilla/security/nss/lib/ssl/ssl3con.c 26 Jul 2011 02:13:37 -0000 1.151 ++++ mozilla/security/nss/lib/ssl/ssl3con.c 29 Sep 2011 17:39:16 -0000 +@@ -2032,56 +2032,56 @@ ssl3_ClientAuthTokenPresent(sslSessionID + isPresent = PR_FALSE; + } + if (slot) { + PK11_FreeSlot(slot); + } + return isPresent; + } + ++/* Caller must hold the spec read lock. wrBuf is sometimes, but not always, ++ * ss->sec.writeBuf. ++ */ + static SECStatus +-ssl3_CompressMACEncryptRecord(sslSocket * ss, ++ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, ++ PRBool isServer, + SSL3ContentType type, + const SSL3Opaque * pIn, +- PRUint32 contentLen) ++ PRUint32 contentLen, ++ sslBuffer * wrBuf) { - PRInt32 totalSent = 0; - PRInt32 discarded = 0; -+ PRBool isBlockCipher; -+ int recordIndex; - - PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); - if (len < 0 || !in) { -@@ -2339,7 +2341,12 @@ ssl3_SendApplicationData(sslSocket *ss, - len--; - discarded = 1; +- ssl3CipherSpec * cwSpec; + const ssl3BulkCipherDef * cipher_def; +- sslBuffer * wrBuf = &ss->sec.writeBuf; + SECStatus rv; + PRUint32 macLen = 0; + PRUint32 fragLen; + PRUint32 p1Len, p2Len, oddLen = 0; + PRInt32 cipherBytes = 0; + +- ssl_GetSpecReadLock(ss); /********************************/ +- +- cwSpec = ss->ssl3.cwSpec; + cipher_def = cwSpec->cipher_def; + + if (cwSpec->compressor) { + int outlen; + rv = cwSpec->compressor( + cwSpec->compressContext, wrBuf->buf + SSL3_RECORD_HEADER_LENGTH, + &outlen, wrBuf->space - SSL3_RECORD_HEADER_LENGTH, pIn, contentLen); + if (rv != SECSuccess) + return rv; + pIn = wrBuf->buf + SSL3_RECORD_HEADER_LENGTH; + contentLen = outlen; } -- while (len > totalSent) { -+ -+ ssl_GetSpecReadLock(ss); -+ isBlockCipher = ss->ssl3.cwSpec->cipher_def->type == type_block; -+ ssl_ReleaseSpecReadLock(ss); -+ -+ for (recordIndex = 0; len > totalSent; recordIndex++) { - PRInt32 sent, toSend; - if (totalSent > 0) { -@@ -2354,6 +2361,28 @@ ssl3_SendApplicationData(sslSocket *ss, - ssl_GetXmitBufLock(ss); + /* + * Add the MAC + */ +- rv = ssl3_ComputeRecordMAC( cwSpec, (PRBool)(ss->sec.isServer), ++ rv = ssl3_ComputeRecordMAC( cwSpec, isServer, + type, cwSpec->version, cwSpec->write_seq_num, pIn, contentLen, + wrBuf->buf + contentLen + SSL3_RECORD_HEADER_LENGTH, &macLen); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); +- goto spec_locked_loser; ++ return SECFailure; + } + p1Len = contentLen; + p2Len = macLen; + fragLen = contentLen + macLen; /* needs to be encrypted */ + PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024); + + /* + * Pad the text (if we're doing a block cipher) +@@ -2124,52 +2124,46 @@ ssl3_CompressMACEncryptRecord(sslSocket + rv = cwSpec->encode( cwSpec->encodeContext, + wrBuf->buf + SSL3_RECORD_HEADER_LENGTH, /* output */ + &cipherBytes, /* actual outlen */ + p1Len, /* max outlen */ + pIn, p1Len); /* input, and inputlen */ + PORT_Assert(rv == SECSuccess && cipherBytes == p1Len); + if (rv != SECSuccess || cipherBytes != p1Len) { + PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); +- goto spec_locked_loser; ++ return SECFailure; } - toSend = PR_MIN(len - totalSent, MAX_FRAGMENT_LENGTH); -+ if (isBlockCipher && -+ ss->ssl3.cwSpec->version <= SSL_LIBRARY_VERSION_3_1_TLS) { -+ /* -+ * We assume that block ciphers are used in CBC mode and send -+ * only one byte in the first record. This effectively -+ * randomizes the IV in a backward compatible way. -+ * -+ * We get back to the MAX_FRAGMENT_LENGTH record boundary in -+ * the second record. So for a large amount of data, we send -+ * 1 -+ * MAX_FRAGMENT_LENGTH - 1 -+ * MAX_FRAGMENT_LENGTH -+ * MAX_FRAGMENT_LENGTH -+ * ... + } + if (p2Len > 0) { + PRInt32 cipherBytesPart2 = -1; + rv = cwSpec->encode( cwSpec->encodeContext, + wrBuf->buf + SSL3_RECORD_HEADER_LENGTH + p1Len, + &cipherBytesPart2, /* output and actual outLen */ + p2Len, /* max outlen */ + wrBuf->buf + SSL3_RECORD_HEADER_LENGTH + p1Len, + p2Len); /* input and inputLen*/ + PORT_Assert(rv == SECSuccess && cipherBytesPart2 == p2Len); + if (rv != SECSuccess || cipherBytesPart2 != p2Len) { + PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); +- goto spec_locked_loser; ++ return SECFailure; + } + cipherBytes += cipherBytesPart2; + } + PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024); + + ssl3_BumpSequenceNumber(&cwSpec->write_seq_num); + + wrBuf->len = cipherBytes + SSL3_RECORD_HEADER_LENGTH; + wrBuf->buf[0] = type; + wrBuf->buf[1] = MSB(cwSpec->version); + wrBuf->buf[2] = LSB(cwSpec->version); + wrBuf->buf[3] = MSB(cipherBytes); + wrBuf->buf[4] = LSB(cipherBytes); + +- ssl_ReleaseSpecReadLock(ss); /************************************/ +- + return SECSuccess; +- +-spec_locked_loser: +- ssl_ReleaseSpecReadLock(ss); +- return SECFailure; + } + + /* Process the plain text before sending it. + * Returns the number of bytes of plaintext that were successfully sent + * plus the number of bytes of plaintext that were copied into the + * output (write) buffer. + * Returns SECFailure on a hard IO error, memory error, or crypto error. + * Does NOT return SECWouldBlock. +@@ -2220,39 +2214,87 @@ ssl3_SendRecord( sslSocket * ss + /* check for Token Presence */ + if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) { + PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL); + return SECFailure; + } + + while (nIn > 0) { + PRUint32 contentLen = PR_MIN(nIn, MAX_FRAGMENT_LENGTH); ++ unsigned int spaceNeeded; ++ unsigned int numRecords; ++ ++ ssl_GetSpecReadLock(ss); /********************************/ ++ ++ if (nIn > 1 && ++ ss->ssl3.cwSpec->version <= SSL_LIBRARY_VERSION_3_1_TLS && ++ type == content_application_data && ++ ss->ssl3.cwSpec->cipher_def->type == type_block /* CBC mode */) { ++ /* We will split the first byte of the record into its own record, ++ * as explained in the documentation for SSL_CBC_RANDOM_IV in ssl.h + */ -+ if (recordIndex == 0) { -+ toSend = 1; -+ } else if (recordIndex == 1 && -+ len - totalSent > MAX_FRAGMENT_LENGTH) { -+ toSend--; ++ numRecords = 2; ++ } else { ++ numRecords = 1; ++ } + +- if (wrBuf->space < contentLen + SSL3_BUFFER_FUDGE) { +- PRInt32 newSpace = PR_MAX(wrBuf->space * 2, contentLen); +- newSpace = PR_MIN(newSpace, MAX_FRAGMENT_LENGTH); +- newSpace += SSL3_BUFFER_FUDGE; +- rv = sslBuffer_Grow(wrBuf, newSpace); ++ spaceNeeded = contentLen + (numRecords * SSL3_BUFFER_FUDGE); ++ if (spaceNeeded > wrBuf->space) { ++ rv = sslBuffer_Grow(wrBuf, spaceNeeded); + if (rv != SECSuccess) { + SSL_DBG(("%d: SSL3[%d]: SendRecord, tried to get %d bytes", +- SSL_GETPID(), ss->fd, newSpace)); +- return SECFailure; /* sslBuffer_Grow set a memory error code. */ ++ SSL_GETPID(), ss->fd, spaceNeeded)); ++ goto spec_locked_loser; /* sslBuffer_Grow set a memory error code. */ + } + } - sent = ssl3_SendRecord(ss, content_application_data, - in + totalSent, toSend, flags); - if (sent < 0) { ++ ++ if (numRecords == 2) { ++ sslBuffer secondRecord; ++ ++ rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, ++ ss->sec.isServer, type, pIn, 1, ++ wrBuf); ++ if (rv != SECSuccess) ++ goto spec_locked_loser; ++ ++ PRINT_BUF(50, (ss, "send (encrypted) record data [1/2]:", ++ wrBuf->buf, wrBuf->len)); ++ ++ secondRecord.buf = wrBuf->buf + wrBuf->len; ++ secondRecord.len = 0; ++ secondRecord.space = wrBuf->space - wrBuf->len; ++ ++ rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, ++ ss->sec.isServer, type, pIn + 1, ++ contentLen - 1, &secondRecord); ++ if (rv == SECSuccess) { ++ PRINT_BUF(50, (ss, "send (encrypted) record data [2/2]:", ++ secondRecord.buf, secondRecord.len)); ++ wrBuf->len += secondRecord.len; ++ } ++ } else { ++ rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, ++ ss->sec.isServer, type, pIn, ++ contentLen, wrBuf); ++ if (rv == SECSuccess) { ++ PRINT_BUF(50, (ss, "send (encrypted) record data [1/1]:", ++ wrBuf->buf, wrBuf->len)); + } + } + +- rv = ssl3_CompressMACEncryptRecord( ss, type, pIn, contentLen); ++spec_locked_loser: ++ ssl_ReleaseSpecReadLock(ss); /************************************/ ++ + if (rv != SECSuccess) + return SECFailure; + + pIn += contentLen; + nIn -= contentLen; + PORT_Assert( nIn >= 0 ); + +- PRINT_BUF(50, (ss, "send (encrypted) record data:", wrBuf->buf, wrBuf->len)); +- + /* If there's still some previously saved ciphertext, + * or the caller doesn't want us to send the data yet, + * then add all our new ciphertext to the amount previously saved. + */ + if ((ss->pendingBuf.len > 0) || + (flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) { + + rv = ssl_SaveWriteData(ss, wrBuf->buf, wrBuf->len); diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c index f305acb..ad8f4cd 100644 --- a/net/third_party/nss/ssl/ssl3con.c +++ b/net/third_party/nss/ssl/ssl3con.c @@ -2042,24 +2042,24 @@ ssl3_ClientAuthTokenPresent(sslSessionID *sid) { return isPresent; } +/* Caller must hold the spec read lock. wrBuf is sometimes, but not always, + * ss->sec.writeBuf. + */ static SECStatus -ssl3_CompressMACEncryptRecord(sslSocket * ss, +ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, + PRBool isServer, SSL3ContentType type, const SSL3Opaque * pIn, - PRUint32 contentLen) + PRUint32 contentLen, + sslBuffer * wrBuf) { - ssl3CipherSpec * cwSpec; const ssl3BulkCipherDef * cipher_def; - sslBuffer * wrBuf = &ss->sec.writeBuf; SECStatus rv; PRUint32 macLen = 0; PRUint32 fragLen; PRUint32 p1Len, p2Len, oddLen = 0; PRInt32 cipherBytes = 0; - ssl_GetSpecReadLock(ss); /********************************/ - - cwSpec = ss->ssl3.cwSpec; cipher_def = cwSpec->cipher_def; if (cwSpec->compressor) { @@ -2076,12 +2076,12 @@ ssl3_CompressMACEncryptRecord(sslSocket * ss, /* * Add the MAC */ - rv = ssl3_ComputeRecordMAC( cwSpec, (PRBool)(ss->sec.isServer), + rv = ssl3_ComputeRecordMAC( cwSpec, isServer, type, cwSpec->version, cwSpec->write_seq_num, pIn, contentLen, wrBuf->buf + contentLen + SSL3_RECORD_HEADER_LENGTH, &macLen); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); - goto spec_locked_loser; + return SECFailure; } p1Len = contentLen; p2Len = macLen; @@ -2134,7 +2134,7 @@ ssl3_CompressMACEncryptRecord(sslSocket * ss, PORT_Assert(rv == SECSuccess && cipherBytes == p1Len); if (rv != SECSuccess || cipherBytes != p1Len) { PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); - goto spec_locked_loser; + return SECFailure; } } if (p2Len > 0) { @@ -2148,7 +2148,7 @@ ssl3_CompressMACEncryptRecord(sslSocket * ss, PORT_Assert(rv == SECSuccess && cipherBytesPart2 == p2Len); if (rv != SECSuccess || cipherBytesPart2 != p2Len) { PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); - goto spec_locked_loser; + return SECFailure; } cipherBytes += cipherBytesPart2; } @@ -2163,13 +2163,7 @@ ssl3_CompressMACEncryptRecord(sslSocket * ss, wrBuf->buf[3] = MSB(cipherBytes); wrBuf->buf[4] = LSB(cipherBytes); - ssl_ReleaseSpecReadLock(ss); /************************************/ - return SECSuccess; - -spec_locked_loser: - ssl_ReleaseSpecReadLock(ss); - return SECFailure; } /* Process the plain text before sending it. @@ -2230,20 +2224,70 @@ ssl3_SendRecord( sslSocket * ss, while (nIn > 0) { PRUint32 contentLen = PR_MIN(nIn, MAX_FRAGMENT_LENGTH); + unsigned int spaceNeeded; + unsigned int numRecords; - if (wrBuf->space < contentLen + SSL3_BUFFER_FUDGE) { - PRInt32 newSpace = PR_MAX(wrBuf->space * 2, contentLen); - newSpace = PR_MIN(newSpace, MAX_FRAGMENT_LENGTH); - newSpace += SSL3_BUFFER_FUDGE; - rv = sslBuffer_Grow(wrBuf, newSpace); + ssl_GetSpecReadLock(ss); /********************************/ + + if (nIn > 1 && + ss->ssl3.cwSpec->version <= SSL_LIBRARY_VERSION_3_1_TLS && + type == content_application_data && + ss->ssl3.cwSpec->cipher_def->type == type_block /* CBC mode */) { + /* We will split the first byte of the record into its own record, + * as explained in the documentation for SSL_CBC_RANDOM_IV in ssl.h + */ + numRecords = 2; + } else { + numRecords = 1; + } + + spaceNeeded = contentLen + (numRecords * SSL3_BUFFER_FUDGE); + if (spaceNeeded > wrBuf->space) { + rv = sslBuffer_Grow(wrBuf, spaceNeeded); if (rv != SECSuccess) { SSL_DBG(("%d: SSL3[%d]: SendRecord, tried to get %d bytes", - SSL_GETPID(), ss->fd, newSpace)); - return SECFailure; /* sslBuffer_Grow set a memory error code. */ + SSL_GETPID(), ss->fd, spaceNeeded)); + goto spec_locked_loser; /* sslBuffer_Grow set a memory error code. */ } } - rv = ssl3_CompressMACEncryptRecord( ss, type, pIn, contentLen); + if (numRecords == 2) { + sslBuffer secondRecord; + + rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, + ss->sec.isServer, type, pIn, 1, + wrBuf); + if (rv != SECSuccess) + goto spec_locked_loser; + + PRINT_BUF(50, (ss, "send (encrypted) record data [1/2]:", + wrBuf->buf, wrBuf->len)); + + secondRecord.buf = wrBuf->buf + wrBuf->len; + secondRecord.len = 0; + secondRecord.space = wrBuf->space - wrBuf->len; + + rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, + ss->sec.isServer, type, pIn + 1, + contentLen - 1, &secondRecord); + if (rv == SECSuccess) { + PRINT_BUF(50, (ss, "send (encrypted) record data [2/2]:", + secondRecord.buf, secondRecord.len)); + wrBuf->len += secondRecord.len; + } + } else { + rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, + ss->sec.isServer, type, pIn, + contentLen, wrBuf); + if (rv == SECSuccess) { + PRINT_BUF(50, (ss, "send (encrypted) record data [1/1]:", + wrBuf->buf, wrBuf->len)); + } + } + +spec_locked_loser: + ssl_ReleaseSpecReadLock(ss); /************************************/ + if (rv != SECSuccess) return SECFailure; @@ -2251,8 +2295,6 @@ ssl3_SendRecord( sslSocket * ss, nIn -= contentLen; PORT_Assert( nIn >= 0 ); - PRINT_BUF(50, (ss, "send (encrypted) record data:", wrBuf->buf, wrBuf->len)); - /* If there's still some previously saved ciphertext, * or the caller doesn't want us to send the data yet, * then add all our new ciphertext to the amount previously saved. @@ -2320,8 +2362,6 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, { PRInt32 totalSent = 0; PRInt32 discarded = 0; - PRBool isBlockCipher; - int recordIndex; PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); if (len < 0 || !in) { @@ -2346,12 +2386,7 @@ 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); - - for (recordIndex = 0; len > totalSent; recordIndex++) { + while (len > totalSent) { PRInt32 sent, toSend; if (totalSent > 0) { @@ -2366,28 +2401,6 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, ssl_GetXmitBufLock(ss); } toSend = PR_MIN(len - totalSent, MAX_FRAGMENT_LENGTH); - if (isBlockCipher && - ss->ssl3.cwSpec->version <= SSL_LIBRARY_VERSION_3_1_TLS) { - /* - * We assume that block ciphers are used in CBC mode and send - * only one byte in the first record. This effectively - * randomizes the IV in a backward compatible way. - * - * We get back to the MAX_FRAGMENT_LENGTH record boundary in - * the second record. So for a large amount of data, we send - * 1 - * MAX_FRAGMENT_LENGTH - 1 - * MAX_FRAGMENT_LENGTH - * MAX_FRAGMENT_LENGTH - * ... - */ - if (recordIndex == 0) { - toSend = 1; - } else if (recordIndex == 1 && - len - totalSent > MAX_FRAGMENT_LENGTH) { - toSend--; - } - } sent = ssl3_SendRecord(ss, content_application_data, in + totalSent, toSend, flags); if (sent < 0) { |