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 dev-tech-crypto@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-crypto