| Index: net/third_party/nss/ssl/ssl3con.c
|
| ===================================================================
|
| --- net/third_party/nss/ssl/ssl3con.c (revision 252347)
|
| +++ net/third_party/nss/ssl/ssl3con.c (working copy)
|
| @@ -1384,6 +1384,7 @@
|
| ssl3_CleanupKeyMaterial(&spec->client);
|
| ssl3_CleanupKeyMaterial(&spec->server);
|
| spec->bypassCiphers = PR_FALSE;
|
| + spec->encryptThenMAC = PR_FALSE;
|
| spec->destroy=NULL;
|
| spec->destroyCompressContext = NULL;
|
| spec->destroyDecompressContext = NULL;
|
| @@ -1469,6 +1470,9 @@
|
| pwSpec->compressContext = NULL;
|
| pwSpec->decompressContext = NULL;
|
|
|
| + pwSpec->encryptThenMAC =
|
| + ssl3_ExtensionNegotiated(ss, ssl_encrypt_then_mac_xtn);
|
| +
|
| ssl_ReleaseSpecWriteLock(ss); /*******************************/
|
| return SECSuccess;
|
| }
|
| @@ -2732,20 +2736,26 @@
|
| return SECFailure;
|
| }
|
| } else {
|
| - /*
|
| - * Add the MAC
|
| - */
|
| - rv = ssl3_ComputeRecordMAC(cwSpec, isServer,
|
| - pseudoHeader, pseudoHeaderLen, pIn, contentLen,
|
| - wrBuf->buf + headerLen + ivLen + contentLen, &macLen);
|
| - if (rv != SECSuccess) {
|
| - ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
|
| - return SECFailure;
|
| + if (!cwSpec->encryptThenMAC) {
|
| + /*
|
| + * Add the MAC
|
| + */
|
| + rv = ssl3_ComputeRecordMAC(cwSpec, isServer,
|
| + pseudoHeader, pseudoHeaderLen, pIn, contentLen,
|
| + wrBuf->buf + headerLen + ivLen + contentLen, &macLen);
|
| + if (rv != SECSuccess) {
|
| + ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
|
| + return SECFailure;
|
| + }
|
| + p1Len = contentLen;
|
| + p2Len = macLen;
|
| + fragLen = contentLen + macLen; /* needs to be encrypted */
|
| + PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024);
|
| + } else {
|
| + p1Len = contentLen;
|
| + p2Len = 0;
|
| + fragLen = contentLen; /* needs to be encrypted */
|
| }
|
| - 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)
|
| @@ -2813,6 +2823,29 @@
|
| }
|
| cipherBytes += cipherBytesPart2;
|
| }
|
| +
|
| + if (cwSpec->encryptThenMAC) {
|
| + /*
|
| + * Add the MAC
|
| + */
|
| + pseudoHeaderLen = ssl3_BuildRecordPseudoHeader(
|
| + pseudoHeader, cwSpec->write_seq_num, type,
|
| + cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->version,
|
| + isDTLS, cipherBytes /* + crSpec->mac_size */);
|
| + PORT_Assert(pseudoHeaderLen <= sizeof(pseudoHeader));
|
| +
|
| + rv = ssl3_ComputeRecordMAC(cwSpec, isServer,
|
| + pseudoHeader, pseudoHeaderLen,
|
| + wrBuf->buf + headerLen, cipherBytes,
|
| + wrBuf->buf + headerLen + cipherBytes, &macLen);
|
| + if (rv != SECSuccess) {
|
| + ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
|
| + return SECFailure;
|
| + }
|
| + PORT_Assert(macLen == cwSpec->mac_size);
|
| + cipherBytes += macLen;
|
| + PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024);
|
| + }
|
| }
|
|
|
| PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024);
|
| @@ -9079,7 +9112,7 @@
|
| extensions_len -= 2;
|
| rv = ssl3_AppendHandshakeNumber(ss, extensions_len, 2);
|
| if (rv != SECSuccess)
|
| - return rv; /* err set by ssl3_SetupPendingCipherSpec */
|
| + return rv; /* err set by AppendHandshake. */
|
| sent_len = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, extensions_len,
|
| &ss->xtnData.serverSenders[0]);
|
| PORT_Assert(sent_len == extensions_len);
|
| @@ -11921,6 +11954,7 @@
|
| rType = content_handshake;
|
| goto process_it;
|
| }
|
| + rType = cText->type;
|
|
|
| ssl_GetSpecReadLock(ss); /******************************************/
|
|
|
| @@ -11979,6 +12013,31 @@
|
| goto decrypt_loser;
|
| }
|
|
|
| + if (crSpec->encryptThenMAC) {
|
| + /* compute the MAC */
|
| + headerLen = ssl3_BuildRecordPseudoHeader(
|
| + header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
|
| + rType, isTLS, cText->version, IS_DTLS(ss),
|
| + cText->buf->len - crSpec->mac_size);
|
| + PORT_Assert(headerLen <= sizeof(header));
|
| + /* This is safe because we checked the minLength above. */
|
| + cText->buf->len -= crSpec->mac_size;
|
| +
|
| + rv = ssl3_ComputeRecordMAC(
|
| + crSpec, (PRBool)(!ss->sec.isServer), header, headerLen,
|
| + cText->buf->buf, cText->buf->len, hash, &hashBytes);
|
| +
|
| + /* We can read the MAC directly from the record because its location
|
| + * is public when a stream cipher is used. */
|
| + givenHash = cText->buf->buf + cText->buf->len;
|
| +
|
| + if (hashBytes != (unsigned)crSpec->mac_size ||
|
| + NSS_SecureMemcmp(givenHash, hash, crSpec->mac_size) != 0) {
|
| + /* We're allowed to leak whether or not the MAC check was correct */
|
| + goto decrypt_loser;
|
| + }
|
| + }
|
| +
|
| if (cipher_def->type == type_block &&
|
| crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
|
| /* Consume the per-record explicit IV. RFC 4346 Section 6.2.3.2 states
|
| @@ -12044,7 +12103,6 @@
|
| return SECFailure;
|
| }
|
|
|
| - rType = cText->type;
|
| if (cipher_def->type == type_aead) {
|
| /* XXX For many AEAD ciphers, the plaintext is shorter than the
|
| * ciphertext by a fixed byte count, but it is not true in general.
|
| @@ -12090,7 +12148,8 @@
|
| /* If it's a block cipher, check and strip the padding. */
|
| if (cipher_def->type == type_block) {
|
| const unsigned int blockSize = cipher_def->block_size;
|
| - const unsigned int macSize = crSpec->mac_size;
|
| + const unsigned int macSize =
|
| + crSpec->encryptThenMAC ? 0 : crSpec->mac_size;
|
|
|
| if (!isTLS) {
|
| good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding(
|
| @@ -12101,6 +12160,7 @@
|
| }
|
| }
|
|
|
| + if (!crSpec->encryptThenMAC) {
|
| /* compute the MAC */
|
| headerLen = ssl3_BuildRecordPseudoHeader(
|
| header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
|
| @@ -12142,6 +12202,7 @@
|
| /* We're allowed to leak whether or not the MAC check was correct */
|
| good = 0;
|
| }
|
| + }
|
| }
|
|
|
| if (good == 0) {
|
| @@ -12317,6 +12378,7 @@
|
| spec->mac_size = 0;
|
| spec->master_secret = NULL;
|
| spec->bypassCiphers = PR_FALSE;
|
| + spec->encryptThenMAC = PR_FALSE;
|
|
|
| spec->msItem.data = NULL;
|
| spec->msItem.len = 0;
|
|
|