Index: net/third_party/nss/patches/cbc.patch |
=================================================================== |
--- net/third_party/nss/patches/cbc.patch (revision 196870) |
+++ net/third_party/nss/patches/cbc.patch (working copy) |
@@ -1,16 +1,7 @@ |
-diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c |
-index c3706fe..4b79321 100644 |
---- a/mozilla/security/nss/lib/ssl/ssl3con.c |
-+++ b/mozilla/security/nss/lib/ssl/ssl3con.c |
-@@ -1844,7 +1844,6 @@ static const unsigned char mac_pad_2 [60] = { |
- }; |
- |
- /* Called from: ssl3_SendRecord() |
--** ssl3_HandleRecord() |
- ** Caller must already hold the SpecReadLock. (wish we could assert that!) |
- */ |
- static SECStatus |
-@@ -2026,6 +2025,136 @@ ssl3_ComputeRecordMAC( |
+diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c |
+--- a/nss/lib/ssl/ssl3con.c 2013-04-27 09:39:58.595657996 -0700 |
++++ b/nss/lib/ssl/ssl3con.c 2013-04-27 09:41:05.836609068 -0700 |
+@@ -2028,6 +2028,20 @@ ssl3_ComputeRecordMAC( |
return rv; |
} |
@@ -28,492 +19,63 @@ |
+} CK_NSS_MAC_CONSTANT_TIME_PARAMS; |
+#endif |
+ |
-+/* Called from: ssl3_HandleRecord() |
-+ * Caller must already hold the SpecReadLock. (wish we could assert that!) |
-+ * |
-+ * On entry: |
-+ * originalLen >= inputLen >= MAC size |
-+*/ |
-+static SECStatus |
-+ssl3_ComputeRecordMACConstantTime( |
-+ ssl3CipherSpec * spec, |
-+ PRBool useServerMacKey, |
-+ PRBool isDTLS, |
-+ SSL3ContentType type, |
-+ SSL3ProtocolVersion version, |
-+ SSL3SequenceNumber seq_num, |
-+ const SSL3Opaque * input, |
-+ int inputLen, |
-+ int originalLen, |
-+ unsigned char * outbuf, |
-+ unsigned int * outLen) |
-+{ |
-+ CK_MECHANISM_TYPE macType; |
-+ CK_NSS_MAC_CONSTANT_TIME_PARAMS params; |
+ /* Called from: ssl3_HandleRecord() |
+ * Caller must already hold the SpecReadLock. (wish we could assert that!) |
+ * |
+@@ -2050,7 +2064,8 @@ ssl3_ComputeRecordMACConstantTime( |
+ { |
+ CK_MECHANISM_TYPE macType; |
+ CK_NSS_MAC_CONSTANT_TIME_PARAMS params; |
+- SECItem param, inputItem, outputItem; |
+ PK11Context * mac_context; |
+ SECItem param; |
-+ SECStatus rv; |
-+ unsigned char header[13]; |
-+ PK11SymKey * key; |
-+ int recordLength; |
-+ |
-+ PORT_Assert(inputLen >= spec->mac_size); |
-+ PORT_Assert(originalLen >= inputLen); |
-+ |
-+ if (spec->bypassCiphers) { |
-+ /* This function doesn't support PKCS#11 bypass. We fallback on the |
-+ * non-constant time version. */ |
-+ goto fallback; |
-+ } |
-+ |
-+ if (spec->mac_def->mac == mac_null) { |
-+ *outLen = 0; |
-+ return SECSuccess; |
-+ } |
-+ |
-+ header[0] = (unsigned char)(seq_num.high >> 24); |
-+ header[1] = (unsigned char)(seq_num.high >> 16); |
-+ header[2] = (unsigned char)(seq_num.high >> 8); |
-+ header[3] = (unsigned char)(seq_num.high >> 0); |
-+ header[4] = (unsigned char)(seq_num.low >> 24); |
-+ header[5] = (unsigned char)(seq_num.low >> 16); |
-+ header[6] = (unsigned char)(seq_num.low >> 8); |
-+ header[7] = (unsigned char)(seq_num.low >> 0); |
-+ header[8] = type; |
-+ |
-+ macType = CKM_NSS_HMAC_CONSTANT_TIME; |
-+ recordLength = inputLen - spec->mac_size; |
-+ if (spec->version <= SSL_LIBRARY_VERSION_3_0) { |
-+ macType = CKM_NSS_SSL3_MAC_CONSTANT_TIME; |
-+ header[9] = recordLength >> 8; |
-+ header[10] = recordLength; |
-+ params.ulHeaderLen = 11; |
-+ } else { |
-+ if (isDTLS) { |
-+ SSL3ProtocolVersion dtls_version; |
-+ |
-+ dtls_version = dtls_TLSVersionToDTLSVersion(version); |
-+ header[9] = dtls_version >> 8; |
-+ header[10] = dtls_version; |
-+ } else { |
-+ header[9] = version >> 8; |
-+ header[10] = version; |
-+ } |
-+ header[11] = recordLength >> 8; |
-+ header[12] = recordLength; |
-+ params.ulHeaderLen = 13; |
-+ } |
-+ |
-+ params.macAlg = spec->mac_def->mmech; |
-+ params.ulBodyTotalLen = originalLen; |
-+ params.pHeader = header; |
-+ |
-+ param.data = (unsigned char*) ¶ms; |
-+ param.len = sizeof(params); |
-+ param.type = 0; |
-+ |
-+ key = spec->server.write_mac_key; |
-+ if (!useServerMacKey) { |
-+ key = spec->client.write_mac_key; |
-+ } |
+ SECStatus rv; |
+ unsigned char header[13]; |
+ PK11SymKey * key; |
+@@ -2111,34 +2126,27 @@ ssl3_ComputeRecordMACConstantTime( |
+ param.len = sizeof(params); |
+ param.type = 0; |
+ |
+- inputItem.data = (unsigned char *) input; |
+- inputItem.len = inputLen; |
+- inputItem.type = 0; |
+- |
+- outputItem.data = outbuf; |
+- outputItem.len = *outLen; |
+- outputItem.type = 0; |
+- |
+ key = spec->server.write_mac_key; |
+ if (!useServerMacKey) { |
+ key = spec->client.write_mac_key; |
+ } |
+ mac_context = PK11_CreateContextBySymKey(macType, CKA_SIGN, key, ¶m); |
+ if (mac_context == NULL) { |
+ /* Older versions of NSS may not support constant-time MAC. */ |
+ goto fallback; |
+ } |
-+ |
+ |
+- rv = PK11_SignWithSymKey(key, macType, ¶m, &outputItem, &inputItem); |
+- if (rv != SECSuccess) { |
+- if (PORT_GetError() == SEC_ERROR_INVALID_ALGORITHM) { |
+- goto fallback; |
+- } |
+ rv = PK11_DigestBegin(mac_context); |
+ rv |= PK11_DigestOp(mac_context, input, inputLen); |
+ rv |= PK11_DigestFinal(mac_context, outbuf, outLen, spec->mac_size); |
+ PK11_DestroyContext(mac_context, PR_TRUE); |
-+ |
+ |
+- *outLen = 0; |
+ PORT_Assert(rv != SECSuccess || *outLen == (unsigned)spec->mac_size); |
+ |
+ if (rv != SECSuccess) { |
-+ rv = SECFailure; |
-+ ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); |
-+ } |
-+ return rv; |
-+ |
-+fallback: |
-+ /* ssl3_ComputeRecordMAC expects the MAC to have been removed from the |
-+ * length already. */ |
-+ inputLen -= spec->mac_size; |
-+ return ssl3_ComputeRecordMAC(spec, useServerMacKey, isDTLS, type, |
-+ version, seq_num, input, inputLen, |
-+ outbuf, outLen); |
-+} |
-+ |
- static PRBool |
- ssl3_ClientAuthTokenPresent(sslSessionID *sid) { |
- PK11SlotInfo *slot = NULL; |
-@@ -9530,6 +9659,177 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) |
- return SECSuccess; |
- } |
- |
-+/* These macros return the given value with the MSB copied to all the other |
-+ * bits. They use the fact that arithmetic shift shifts-in the sign bit. |
-+ * However, this is not ensured by the C standard so you may need to replace |
-+ * them with something else for odd compilers. */ |
-+#define DUPLICATE_MSB_TO_ALL(x) ( (unsigned)( (int)(x) >> (sizeof(int)*8-1) ) ) |
-+#define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x))) |
-+ |
-+/* SECStatusToMask returns, in constant time, a mask value of all ones if rv == |
-+ * SECSuccess. Otherwise it returns zero. */ |
-+static unsigned SECStatusToMask(SECStatus rv) |
-+{ |
-+ unsigned int good; |
-+ /* rv ^ SECSuccess is zero iff rv == SECSuccess. Subtracting one results in |
-+ * the MSB being set to one iff it was zero before. */ |
-+ good = rv ^ SECSuccess; |
-+ good--; |
-+ return DUPLICATE_MSB_TO_ALL(good); |
-+} |
-+ |
-+/* ssl_ConstantTimeGE returns 0xff if a>=b and 0x00 otherwise. */ |
-+static unsigned char ssl_ConstantTimeGE(unsigned a, unsigned b) |
-+{ |
-+ a -= b; |
-+ return DUPLICATE_MSB_TO_ALL(~a); |
-+} |
-+ |
-+/* ssl_ConstantTimeEQ8 returns 0xff if a==b and 0x00 otherwise. */ |
-+static unsigned char ssl_ConstantTimeEQ8(unsigned char a, unsigned char b) |
-+{ |
-+ unsigned c = a ^ b; |
-+ c--; |
-+ return DUPLICATE_MSB_TO_ALL_8(c); |
-+} |
-+ |
-+static SECStatus ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext, |
-+ unsigned blockSize, |
-+ unsigned macSize) { |
-+ unsigned int paddingLength, good, t; |
-+ const unsigned int overhead = 1 /* padding length byte */ + macSize; |
-+ |
-+ /* These lengths are all public so we can test them in non-constant |
-+ * time. */ |
-+ if (overhead > plaintext->len) { |
-+ return SECFailure; |
-+ } |
-+ |
-+ paddingLength = plaintext->buf[plaintext->len-1]; |
-+ /* SSLv3 padding bytes are random and cannot be checked. */ |
-+ t = plaintext->len; |
-+ t -= paddingLength+overhead; |
-+ /* If len >= padding_length+overhead then the MSB of t is zero. */ |
-+ good = DUPLICATE_MSB_TO_ALL(~t); |
-+ /* SSLv3 requires that the padding is minimal. */ |
-+ t = blockSize - (paddingLength+1); |
-+ good &= DUPLICATE_MSB_TO_ALL(~t); |
-+ plaintext->len -= good & (paddingLength+1); |
-+ return (good & SECSuccess) | (~good & SECFailure); |
-+} |
-+ |
-+ |
-+static SECStatus ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, |
-+ unsigned macSize) { |
-+ unsigned int paddingLength, good, t, toCheck, i; |
-+ const unsigned int overhead = 1 /* padding length byte */ + macSize; |
-+ |
-+ /* These lengths are all public so we can test them in non-constant |
-+ * time. */ |
-+ if (overhead > plaintext->len) { |
-+ return SECFailure; |
-+ } |
-+ |
-+ paddingLength = plaintext->buf[plaintext->len-1]; |
-+ t = plaintext->len; |
-+ t -= paddingLength+overhead; |
-+ /* If len >= paddingLength+overhead then the MSB of t is zero. */ |
-+ good = DUPLICATE_MSB_TO_ALL(~t); |
-+ |
-+ /* The padding consists of a length byte at the end of the record and then |
-+ * that many bytes of padding, all with the same value as the length byte. |
-+ * Thus, with the length byte included, there are paddingLength+1 bytes of |
-+ * padding. |
-+ * |
-+ * We can't check just |paddingLength+1| bytes because that leaks |
-+ * decrypted information. Therefore we always have to check the maximum |
-+ * amount of padding possible. (Again, the length of the record is |
-+ * public information so we can use it.) */ |
-+ toCheck = 255; /* maximum amount of padding. */ |
-+ if (toCheck > plaintext->len-1) { |
-+ toCheck = plaintext->len-1; |
-+ } |
-+ |
-+ for (i = 0; i < toCheck; i++) { |
-+ unsigned int t = paddingLength - i; |
-+ /* If i <= paddingLength then the MSB of t is zero and mask is |
-+ * 0xff. Otherwise, mask is 0. */ |
-+ unsigned char mask = DUPLICATE_MSB_TO_ALL(~t); |
-+ unsigned char b = plaintext->buf[plaintext->len-1-i]; |
-+ /* The final |paddingLength+1| bytes should all have the value |
-+ * |paddingLength|. Therefore the XOR should be zero. */ |
-+ good &= ~(mask&(paddingLength ^ b)); |
-+ } |
-+ |
-+ /* If any of the final |paddingLength+1| bytes had the wrong value, |
-+ * one or more of the lower eight bits of |good| will be cleared. We |
-+ * AND the bottom 8 bits together and duplicate the result to all the |
-+ * bits. */ |
-+ good &= good >> 4; |
-+ good &= good >> 2; |
-+ good &= good >> 1; |
-+ good <<= sizeof(good)*8-1; |
-+ good = DUPLICATE_MSB_TO_ALL(good); |
-+ |
-+ plaintext->len -= good & (paddingLength+1); |
-+ return (good & SECSuccess) | (~good & SECFailure); |
-+} |
-+ |
-+/* On entry: |
-+ * originalLength >= macSize |
-+ * macSize <= MAX_MAC_LENGTH |
-+ * plaintext->len >= macSize |
-+ */ |
-+static void ssl_CBCExtractMAC(sslBuffer *plaintext, |
-+ unsigned int originalLength, |
-+ SSL3Opaque* out, |
-+ unsigned int macSize) { |
-+ unsigned char rotatedMac[MAX_MAC_LENGTH]; |
-+ /* macEnd is the index of |plaintext->buf| just after the end of the MAC. */ |
-+ unsigned macEnd = plaintext->len; |
-+ unsigned macStart = macEnd - macSize; |
-+ /* scanStart contains the number of bytes that we can ignore because |
-+ * the MAC's position can only vary by 255 bytes. */ |
-+ unsigned scanStart = 0; |
-+ unsigned i, j, divSpoiler; |
-+ unsigned char rotateOffset; |
-+ |
-+ if (originalLength > macSize + 255 + 1) |
-+ scanStart = originalLength - (macSize + 255 + 1); |
-+ |
-+ /* divSpoiler contains a multiple of macSize that is used to cause the |
-+ * modulo operation to be constant time. Without this, the time varies |
-+ * based on the amount of padding when running on Intel chips at least. |
-+ * |
-+ * The aim of right-shifting macSize is so that the compiler doesn't |
-+ * figure out that it can remove divSpoiler as that would require it |
-+ * to prove that macSize is always even, which I hope is beyond it. */ |
-+ divSpoiler = macSize >> 1; |
-+ divSpoiler <<= (sizeof(divSpoiler)-1)*8; |
-+ rotateOffset = (divSpoiler + macStart - scanStart) % macSize; |
-+ |
-+ memset(rotatedMac, 0, macSize); |
-+ for (i = scanStart; i < originalLength;) { |
-+ for (j = 0; j < macSize && i < originalLength; i++, j++) { |
-+ unsigned char macStarted = ssl_ConstantTimeGE(i, macStart); |
-+ unsigned char macEnded = ssl_ConstantTimeGE(i, macEnd); |
-+ unsigned char b = 0; |
-+ b = plaintext->buf[i]; |
-+ rotatedMac[j] |= b & macStarted & ~macEnded; |
-+ } |
-+ } |
-+ |
-+ /* Now rotate the MAC. If we knew that the MAC fit into a CPU cache line we |
-+ * could line-align |rotatedMac| and rotate in place. */ |
-+ memset(out, 0, macSize); |
-+ for (i = 0; i < macSize; i++) { |
-+ unsigned char offset = (divSpoiler + macSize - rotateOffset + i) % macSize; |
-+ for (j = 0; j < macSize; j++) { |
-+ out[j] |= rotatedMac[i] & ssl_ConstantTimeEQ8(j, offset); |
-+ } |
-+ } |
-+} |
-+ |
- /* if cText is non-null, then decipher, check MAC, and decompress the |
- * SSL record from cText->buf (typically gs->inbuf) |
- * into databuf (typically gs->buf), and any previous contents of databuf |
-@@ -9559,15 +9859,18 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) |
- ssl3CipherSpec * crSpec; |
- SECStatus rv; |
- unsigned int hashBytes = MAX_MAC_LENGTH + 1; |
-- unsigned int padding_length; |
- PRBool isTLS; |
-- PRBool padIsBad = PR_FALSE; |
- SSL3ContentType rType; |
- SSL3Opaque hash[MAX_MAC_LENGTH]; |
-+ SSL3Opaque givenHashBuf[MAX_MAC_LENGTH]; |
-+ SSL3Opaque *givenHash; |
- sslBuffer *plaintext; |
- sslBuffer temp_buf; |
- PRUint64 dtls_seq_num; |
- unsigned int ivLen = 0; |
-+ unsigned int originalLen = 0; |
-+ unsigned int good; |
-+ unsigned int minLength; |
- |
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
- |
-@@ -9635,6 +9938,30 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) |
- } |
+ rv = SECFailure; |
+ ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); |
+- return rv; |
} |
+- |
+- PORT_Assert(outputItem.len == (unsigned)spec->mac_size); |
+- *outLen = outputItem.len; |
+- |
+ return rv; |
-+ good = (unsigned)-1; |
-+ minLength = crSpec->mac_size; |
-+ if (cipher_def->type == type_block) { |
-+ /* CBC records have a padding length byte at the end. */ |
-+ minLength++; |
-+ if (crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { |
-+ /* With >= TLS 1.1, CBC records have an explicit IV. */ |
-+ minLength += cipher_def->iv_size; |
-+ } |
-+ } |
-+ |
-+ /* We can perform this test in variable time because the record's total |
-+ * length and the ciphersuite are both public knowledge. */ |
-+ if (cText->buf->len < minLength) { |
-+ SSL_DBG(("%d: SSL3[%d]: HandleRecord, record too small.", |
-+ SSL_GETPID(), ss->fd)); |
-+ /* must not hold spec lock when calling SSL3_SendAlert. */ |
-+ ssl_ReleaseSpecReadLock(ss); |
-+ SSL3_SendAlert(ss, alert_fatal, bad_record_mac); |
-+ /* always log mac error, in case attacker can read server logs. */ |
-+ PORT_SetError(SSL_ERROR_BAD_MAC_READ); |
-+ return SECFailure; |
-+ } |
-+ |
- 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 |
-@@ -9652,16 +9979,6 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) |
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
- return SECFailure; |
- } |
-- if (ivLen > cText->buf->len) { |
-- SSL_DBG(("%d: SSL3[%d]: HandleRecord, IV length check failed", |
-- SSL_GETPID(), ss->fd)); |
-- /* must not hold spec lock when calling SSL3_SendAlert. */ |
-- ssl_ReleaseSpecReadLock(ss); |
-- SSL3_SendAlert(ss, alert_fatal, bad_record_mac); |
-- /* always log mac error, in case attacker can read server logs. */ |
-- PORT_SetError(SSL_ERROR_BAD_MAC_READ); |
-- return SECFailure; |
-- } |
- |
- PRINT_BUF(80, (ss, "IV (ciphertext):", cText->buf->buf, ivLen)); |
- |
-@@ -9672,12 +9989,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) |
- rv = crSpec->decode(crSpec->decodeContext, iv, &decoded, |
- sizeof(iv), cText->buf->buf, ivLen); |
- |
-- if (rv != SECSuccess) { |
-- /* All decryption failures must be treated like a bad record |
-- * MAC; see RFC 5246 (TLS 1.2). |
-- */ |
-- padIsBad = PR_TRUE; |
-- } |
-+ good &= SECStatusToMask(rv); |
- } |
- |
- /* If we will be decompressing the buffer we need to decrypt somewhere |
-@@ -9719,54 +10031,70 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) |
- rv = crSpec->decode( |
- crSpec->decodeContext, plaintext->buf, (int *)&plaintext->len, |
- plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen); |
-+ good &= SECStatusToMask(rv); |
- |
- PRINT_BUF(80, (ss, "cleartext:", plaintext->buf, plaintext->len)); |
-- if (rv != SECSuccess) { |
-- /* All decryption failures must be treated like a bad record |
-- * MAC; see RFC 5246 (TLS 1.2). |
-- */ |
-- padIsBad = PR_TRUE; |
-- } |
-+ |
-+ originalLen = plaintext->len; |
- |
- /* If it's a block cipher, check and strip the padding. */ |
-- if (cipher_def->type == type_block && !padIsBad) { |
-- PRUint8 * pPaddingLen = plaintext->buf + plaintext->len - 1; |
-- padding_length = *pPaddingLen; |
-- /* TLS permits padding to exceed the block size, up to 255 bytes. */ |
-- if (padding_length + 1 + crSpec->mac_size > plaintext->len) |
-- padIsBad = PR_TRUE; |
-- else { |
-- plaintext->len -= padding_length + 1; |
-- /* In TLS all padding bytes must be equal to the padding length. */ |
-- if (isTLS) { |
-- PRUint8 *p; |
-- for (p = pPaddingLen - padding_length; p < pPaddingLen; ++p) { |
-- padIsBad |= *p ^ padding_length; |
-- } |
-- } |
-- } |
-- } |
-+ if (cipher_def->type == type_block) { |
-+ const unsigned int blockSize = cipher_def->iv_size; |
-+ const unsigned int macSize = crSpec->mac_size; |
- |
-- /* Remove the MAC. */ |
-- if (plaintext->len >= crSpec->mac_size) |
-- plaintext->len -= crSpec->mac_size; |
-- else |
-- padIsBad = PR_TRUE; /* really macIsBad */ |
-+ if (crSpec->version <= SSL_LIBRARY_VERSION_3_0) { |
-+ good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding( |
-+ plaintext, blockSize, macSize)); |
-+ } else { |
-+ good &= SECStatusToMask(ssl_RemoveTLSCBCPadding( |
-+ plaintext, macSize)); |
-+ } |
-+ } |
- |
- /* compute the MAC */ |
- rType = cText->type; |
-- rv = ssl3_ComputeRecordMAC( crSpec, (PRBool)(!ss->sec.isServer), |
-- IS_DTLS(ss), rType, cText->version, |
-- IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, |
-- plaintext->buf, plaintext->len, hash, &hashBytes); |
-- if (rv != SECSuccess) { |
-- padIsBad = PR_TRUE; /* really macIsBad */ |
-+ if (cipher_def->type == type_block) { |
-+ rv = ssl3_ComputeRecordMACConstantTime( |
-+ crSpec, (PRBool)(!ss->sec.isServer), |
-+ IS_DTLS(ss), rType, cText->version, |
-+ IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, |
-+ plaintext->buf, plaintext->len, originalLen, |
-+ hash, &hashBytes); |
-+ |
-+ ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf, |
-+ crSpec->mac_size); |
-+ givenHash = givenHashBuf; |
-+ |
-+ /* plaintext->len will always have enough space to remove the MAC |
-+ * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust |
-+ * plaintext->len if the result has enough space for the MAC and we |
-+ * tested the unadjusted size against minLength, above. */ |
-+ plaintext->len -= crSpec->mac_size; |
-+ } else { |
-+ /* This is safe because we checked the minLength above. */ |
-+ plaintext->len -= crSpec->mac_size; |
-+ |
-+ rv = ssl3_ComputeRecordMAC( |
-+ crSpec, (PRBool)(!ss->sec.isServer), |
-+ IS_DTLS(ss), rType, cText->version, |
-+ IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, |
-+ plaintext->buf, plaintext->len, |
-+ hash, &hashBytes); |
-+ |
-+ /* We can read the MAC directly from the record because its location is |
-+ * public when a stream cipher is used. */ |
-+ givenHash = plaintext->buf + plaintext->len; |
-+ } |
-+ |
-+ good &= SECStatusToMask(rv); |
-+ |
-+ 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 */ |
-+ good = 0; |
- } |
- |
-- /* Check the MAC */ |
-- if (hashBytes != (unsigned)crSpec->mac_size || padIsBad || |
-- NSS_SecureMemcmp(plaintext->buf + plaintext->len, hash, |
-- crSpec->mac_size) != 0) { |
-+ if (good == 0) { |
- /* must not hold spec lock when calling SSL3_SendAlert. */ |
- ssl_ReleaseSpecReadLock(ss); |
- |
+ fallback: |