Thanks Robert for your reply. I will try your solution.
For the reference, I'm attaching the back ported fix for the 3.12.5, with no
warranties.
Regards,
Sergey
--- nss-3.12.5-orig/mozilla/security/nss/lib/ssl/ssl.h Tue Jan 15 16:40:47 2013
+++ nss-3.12.5/mozilla/security/nss/lib/ssl/ssl.h Wed Jan 16 17:22:43 2013
@@ -122,6 +122,33 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFi
/* default: off */
/* NOT YET IMPLEMENTED in 3.12.5 */
+/* For SSL 3.0 and TLS 1.0, by default we prevent chosen plaintext attacks
+ * on SSL CBC mode cipher suites (see RFC 4346 Section F.3) by splitting
+ * non-empty application_data records into two records; the first record has
+ * only the first byte of plaintext, and the second has the rest.
+ *
+ * This only prevents the attack in the sending direction; the connection may
+ * still be vulnerable to such attacks if the peer does not implement a similar
+ * countermeasure.
+ *
+ * This protection mechanism is on by default; the default can be overridden
+ * by the application setting the option SSL_CBC_RANDOM_IV to PR_FALSE.
+ *
+ * The per-record IV in TLS 1.1 and later adds one block of overhead per
+ * record, whereas this hack will add at least two blocks of overhead per
+ * record, so TLS 1.1+ will always be more efficient.
+ *
+ * Other implementations (e.g. some versions of OpenSSL, in some
+ * configurations) prevent the same attack by prepending an empty
+ * application_data record to every application_data record they send; we do
+ * not do that because some implementations cannot handle empty
+ * application_data records. Also, we only split application_data records and
+ * not other types of records, because some implementations will not accept
+ * fragmented records of some other types (e.g. some versions of NSS do not
+ * accept fragmented alerts).
+ */
+#define SSL_CBC_RANDOM_IV 23
+
#ifdef SSL_DEPRECATED_FUNCTION
/* Old deprecated function names */
SSL_IMPORT SECStatus SSL_Enable(PRFileDesc *fd, int option, PRBool on);
--- nss-3.12.5-orig/mozilla/security/nss/lib/ssl/ssl3con.c Tue Jan 15
16:40:47 2013
+++ nss-3.12.5/mozilla/security/nss/lib/ssl/ssl3con.c Wed Jan 16 15:12:16 2013
@@ -2018,23 +2018,20 @@ ssl3_ClientAuthTokenPresent(sslSessionID
}
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->compress) {
@@ -2051,12 +2048,12 @@ ssl3_CompressMACEncryptRecord(sslSocket
/*
* 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;
@@ -2109,7 +2106,7 @@ ssl3_CompressMACEncryptRecord(sslSocket
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) {
@@ -2123,7 +2120,7 @@ ssl3_CompressMACEncryptRecord(sslSocket
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;
}
@@ -2138,13 +2135,7 @@ ssl3_CompressMACEncryptRecord(sslSocket
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.
@@ -2205,28 +2196,76 @@ ssl3_SendRecord( sslSocket * ss
while (nIn > 0) {
PRUint32 contentLen = PR_MIN(nIn, MAX_FRAGMENT_LENGTH);
+ unsigned int spaceNeeded;
+ unsigned int numRecords;
+
+ ssl_GetSpecReadLock(ss); /********************************/
- 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);
+ if (nIn > 1 && ss->opt.cbcRandomIV &&
+ 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 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:",
+ wrBuf->buf, wrBuf->len));
+ }
+ }
+
+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,
--- nss-3.12.5-orig/mozilla/security/nss/lib/ssl/sslimpl.h Tue Jan 15
16:40:47 2013
+++ nss-3.12.5/mozilla/security/nss/lib/ssl/sslimpl.h Wed Jan 16 15:12:23 2013
@@ -337,6 +337,8 @@ typedef struct sslOptionsStr {
unsigned int enableDeflate : 1; /* 19 */
unsigned int enableRenegotiation : 2; /* 20-21 */
unsigned int requireSafeNegotiation : 1; /* 22 */
+ unsigned int _enableFalseStart_notInUse : 1; /* 23 */
+ unsigned int cbcRandomIV : 1; /* 24 */
} sslOptions;
typedef enum { sslHandshakingUndetermined = 0,
--- nss-3.12.5-orig/mozilla/security/nss/lib/ssl/sslsock.c Tue Jan 15
16:40:47 2013
+++ nss-3.12.5/mozilla/security/nss/lib/ssl/sslsock.c Wed Jan 16 15:14:16 2013
@@ -183,6 +183,8 @@ static sslOptions ssl_defaults = {
PR_FALSE, /* enableDeflate */
0, /* enableRenegotiation (default: never) */
PR_FALSE, /* requireSafeNegotiation */
+ PR_FALSE, /* enableFalseStart - not in use */
+ PR_TRUE /* cbcRandomIV */
};
sslSessionIDLookupFunc ssl_sid_lookup;
@@ -720,6 +722,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 wh
ss->opt.requireSafeNegotiation = on;
break;
+ case SSL_CBC_RANDOM_IV:
+ ss->opt.cbcRandomIV = on;
+ break;
+
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
@@ -783,6 +789,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 wh
on = ss->opt.enableRenegotiation; break;
case SSL_REQUIRE_SAFE_NEGOTIATION:
on = ss->opt.requireSafeNegotiation; break;
+ case SSL_CBC_RANDOM_IV: on = ss->opt.cbcRandomIV; break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -833,6 +840,7 @@ SSL_OptionGetDefault(PRInt32 which, PRBo
case SSL_REQUIRE_SAFE_NEGOTIATION:
on = ssl_defaults.requireSafeNegotiation;
break;
+ case SSL_CBC_RANDOM_IV: on = ssl_defaults.cbcRandomIV; break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -975,6 +983,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBo
case SSL_REQUIRE_SAFE_NEGOTIATION:
ssl_defaults.requireSafeNegotiation = on;
break;
+
+ case SSL_CBC_RANDOM_IV:
+ ssl_defaults.cbcRandomIV = on;
+ break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
On Tuesday, January 15, 2013 11:37:47 PM UTC+2, Robert Relyea wrote:
> On 01/13/2013 02:51 AM, Sergey Emantayev wrote:
>
> > Hi all,
>
> >
>
> > We are using NSS 3.12.5 in our security project. I'm interested in applying
> > the fix of CVE-2011-3389 in this version. Due to the project requirement we
> > are obligated to use a FIPS certified NSS module so we cannot move to NSS
> > 3.13 there this issue is originally fixed.
>
> >
>
> > Looking to the bug notes
> > https://bugzilla.mozilla.org/show_bug.cgi?id=665814 I found two code
> > patches:
>
> > 1. patch to add empty application data records by Adam Langley
> > https://bug665814.bugzilla.mozilla.org/attachment.cgi?id=541137
>
> > 2. patch v11: Prevent chosen plaintext attacks on CBC mode, on by default
> > by Brian Smith (:bsmith)
> > https://bug665814.bugzilla.mozilla.org/attachment.cgi?id=563777
>
> You can pick up NSS 3.13 while still using NSS 3.12.5 softoken. This is
>
> what Red Hat ships in RHEL (well actually we ship NSS-SOFTOKEN 3.12.9,
>
> which just got its FIPS cert last year, and in 6.4 we are shipping it
>
> with NSS 3.14).
>
>
>
> That would be most reliable.
>
> >
>
> > Are both patches enough to back port the fix to 3.12.5 or if not even
> > possible to any other 3.12.x version?
>
> >
>
> > Thanks& regards,
>
> > Sergey Emantayev
--
dev-tech-crypto mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-crypto