OLD | NEW |
(Empty) | |
| 1 diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/s
sl/ssl3con.c |
| 2 index c3706fe..4b79321 100644 |
| 3 --- a/mozilla/security/nss/lib/ssl/ssl3con.c |
| 4 +++ b/mozilla/security/nss/lib/ssl/ssl3con.c |
| 5 @@ -1844,7 +1844,6 @@ static const unsigned char mac_pad_2 [60] = { |
| 6 }; |
| 7 |
| 8 /* Called from: ssl3_SendRecord() |
| 9 -** ssl3_HandleRecord() |
| 10 ** Caller must already hold the SpecReadLock. (wish we could assert that!) |
| 11 */ |
| 12 static SECStatus |
| 13 @@ -2026,6 +2025,136 @@ ssl3_ComputeRecordMAC( |
| 14 return rv; |
| 15 } |
| 16 |
| 17 +/* This is a bodge to allow this code to be compiled against older NSS headers |
| 18 + * that don't contain the CBC constant-time changes. */ |
| 19 +#ifndef CKM_NSS_HMAC_CONSTANT_TIME |
| 20 +#define CKM_NSS_HMAC_CONSTANT_TIME (CKM_NSS + 19) |
| 21 +#define CKM_NSS_SSL3_MAC_CONSTANT_TIME (CKM_NSS + 20) |
| 22 + |
| 23 +typedef struct CK_NSS_MAC_CONSTANT_TIME_PARAMS { |
| 24 + CK_MECHANISM_TYPE hashAlg; /* in */ |
| 25 + CK_ULONG ulBodyTotalLen; /* in */ |
| 26 + CK_BYTE * pHeader; /* in */ |
| 27 + CK_ULONG ulHeaderLen; /* in */ |
| 28 +} CK_NSS_MAC_CONSTANT_TIME_PARAMS; |
| 29 +#endif |
| 30 + |
| 31 +/* Called from: ssl3_HandleRecord() |
| 32 + * Caller must already hold the SpecReadLock. (wish we could assert that!) |
| 33 + * |
| 34 + * On entry: |
| 35 + * originalLen >= inputLen >= MAC size |
| 36 +*/ |
| 37 +static SECStatus |
| 38 +ssl3_ComputeRecordMACConstantTime( |
| 39 + ssl3CipherSpec * spec, |
| 40 + PRBool useServerMacKey, |
| 41 + PRBool isDTLS, |
| 42 + SSL3ContentType type, |
| 43 + SSL3ProtocolVersion version, |
| 44 + SSL3SequenceNumber seq_num, |
| 45 + const SSL3Opaque * input, |
| 46 + int inputLen, |
| 47 + int originalLen, |
| 48 + unsigned char * outbuf, |
| 49 + unsigned int * outLen) |
| 50 +{ |
| 51 + CK_MECHANISM_TYPE macType; |
| 52 + CK_NSS_MAC_CONSTANT_TIME_PARAMS params; |
| 53 + PK11Context * mac_context; |
| 54 + SECItem param; |
| 55 + SECStatus rv; |
| 56 + unsigned char header[13]; |
| 57 + PK11SymKey * key; |
| 58 + int recordLength; |
| 59 + |
| 60 + PORT_Assert(inputLen >= spec->mac_size); |
| 61 + PORT_Assert(originalLen >= inputLen); |
| 62 + |
| 63 + if (spec->bypassCiphers) { |
| 64 + /* This function doesn't support PKCS#11 bypass. We fallback on the |
| 65 + * non-constant time version. */ |
| 66 + goto fallback; |
| 67 + } |
| 68 + |
| 69 + if (spec->mac_def->mac == mac_null) { |
| 70 + *outLen = 0; |
| 71 + return SECSuccess; |
| 72 + } |
| 73 + |
| 74 + header[0] = (unsigned char)(seq_num.high >> 24); |
| 75 + header[1] = (unsigned char)(seq_num.high >> 16); |
| 76 + header[2] = (unsigned char)(seq_num.high >> 8); |
| 77 + header[3] = (unsigned char)(seq_num.high >> 0); |
| 78 + header[4] = (unsigned char)(seq_num.low >> 24); |
| 79 + header[5] = (unsigned char)(seq_num.low >> 16); |
| 80 + header[6] = (unsigned char)(seq_num.low >> 8); |
| 81 + header[7] = (unsigned char)(seq_num.low >> 0); |
| 82 + header[8] = type; |
| 83 + |
| 84 + macType = CKM_NSS_HMAC_CONSTANT_TIME; |
| 85 + recordLength = inputLen - spec->mac_size; |
| 86 + if (spec->version <= SSL_LIBRARY_VERSION_3_0) { |
| 87 + macType = CKM_NSS_SSL3_MAC_CONSTANT_TIME; |
| 88 + header[9] = recordLength >> 8; |
| 89 + header[10] = recordLength; |
| 90 + params.ulHeaderLen = 11; |
| 91 + } else { |
| 92 + if (isDTLS) { |
| 93 + SSL3ProtocolVersion dtls_version; |
| 94 + |
| 95 + dtls_version = dtls_TLSVersionToDTLSVersion(version); |
| 96 + header[9] = dtls_version >> 8; |
| 97 + header[10] = dtls_version; |
| 98 + } else { |
| 99 + header[9] = version >> 8; |
| 100 + header[10] = version; |
| 101 + } |
| 102 + header[11] = recordLength >> 8; |
| 103 + header[12] = recordLength; |
| 104 + params.ulHeaderLen = 13; |
| 105 + } |
| 106 + |
| 107 + params.hashAlg = spec->mac_def->mmech; |
| 108 + params.ulBodyTotalLen = originalLen; |
| 109 + params.pHeader = header; |
| 110 + |
| 111 + param.data = (unsigned char*) ¶ms; |
| 112 + param.len = sizeof(params); |
| 113 + param.type = 0; |
| 114 + |
| 115 + key = spec->server.write_mac_key; |
| 116 + if (!useServerMacKey) { |
| 117 + key = spec->client.write_mac_key; |
| 118 + } |
| 119 + mac_context = PK11_CreateContextBySymKey(macType, CKA_SIGN, key, ¶m); |
| 120 + if (mac_context == NULL) { |
| 121 + /* Older versions of NSS may not support constant-time MAC. */ |
| 122 + goto fallback; |
| 123 + } |
| 124 + |
| 125 + rv = PK11_DigestBegin(mac_context); |
| 126 + rv |= PK11_DigestOp(mac_context, input, inputLen); |
| 127 + rv |= PK11_DigestFinal(mac_context, outbuf, outLen, spec->mac_size); |
| 128 + PK11_DestroyContext(mac_context, PR_TRUE); |
| 129 + |
| 130 + PORT_Assert(rv != SECSuccess || *outLen == (unsigned)spec->mac_size); |
| 131 + |
| 132 + if (rv != SECSuccess) { |
| 133 + rv = SECFailure; |
| 134 + ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); |
| 135 + } |
| 136 + return rv; |
| 137 + |
| 138 +fallback: |
| 139 + /* ssl3_ComputeRecordMAC expects the MAC to have been removed from the |
| 140 + * length already. */ |
| 141 + inputLen -= spec->mac_size; |
| 142 + return ssl3_ComputeRecordMAC(spec, useServerMacKey, isDTLS, type, |
| 143 + version, seq_num, input, inputLen, |
| 144 + outbuf, outLen); |
| 145 +} |
| 146 + |
| 147 static PRBool |
| 148 ssl3_ClientAuthTokenPresent(sslSessionID *sid) { |
| 149 PK11SlotInfo *slot = NULL; |
| 150 @@ -9530,6 +9659,177 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) |
| 151 return SECSuccess; |
| 152 } |
| 153 |
| 154 +/* These macros return the given value with the MSB copied to all the other |
| 155 + * bits. They use the fact that arithmetic shift shifts-in the sign bit. |
| 156 + * However, this is not ensured by the C standard so you may need to replace |
| 157 + * them with something else for odd compilers. */ |
| 158 +#define DUPLICATE_MSB_TO_ALL(x) ( (unsigned)( (int)(x) >> (sizeof(int)*8-1) ) ) |
| 159 +#define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x))) |
| 160 + |
| 161 +/* SECStatusToMask returns, in constant time, a mask value of all ones if rv == |
| 162 + * SECSuccess. Otherwise it returns zero. */ |
| 163 +static unsigned SECStatusToMask(SECStatus rv) |
| 164 +{ |
| 165 + unsigned int good; |
| 166 + /* rv ^ SECSuccess is zero iff rv == SECSuccess. Subtracting one results in |
| 167 + * the MSB being set to one iff it was zero before. */ |
| 168 + good = rv ^ SECSuccess; |
| 169 + good--; |
| 170 + return DUPLICATE_MSB_TO_ALL(good); |
| 171 +} |
| 172 + |
| 173 +/* ssl_ConstantTimeGE returns 0xff if a>=b and 0x00 otherwise. */ |
| 174 +static unsigned char ssl_ConstantTimeGE(unsigned a, unsigned b) |
| 175 +{ |
| 176 + a -= b; |
| 177 + return DUPLICATE_MSB_TO_ALL(~a); |
| 178 +} |
| 179 + |
| 180 +/* ssl_ConstantTimeEQ8 returns 0xff if a==b and 0x00 otherwise. */ |
| 181 +static unsigned char ssl_ConstantTimeEQ8(unsigned char a, unsigned char b) |
| 182 +{ |
| 183 + unsigned c = a ^ b; |
| 184 + c--; |
| 185 + return DUPLICATE_MSB_TO_ALL_8(c); |
| 186 +} |
| 187 + |
| 188 +static SECStatus ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext, |
| 189 + unsigned blockSize, |
| 190 + unsigned macSize) { |
| 191 + unsigned int paddingLength, good, t; |
| 192 + const unsigned int overhead = 1 /* padding length byte */ + macSize; |
| 193 + |
| 194 + /* These lengths are all public so we can test them in non-constant |
| 195 + * time. */ |
| 196 + if (overhead > plaintext->len) { |
| 197 + return SECFailure; |
| 198 + } |
| 199 + |
| 200 + paddingLength = plaintext->buf[plaintext->len-1]; |
| 201 + /* SSLv3 padding bytes are random and cannot be checked. */ |
| 202 + t = plaintext->len; |
| 203 + t -= paddingLength+overhead; |
| 204 + /* If len >= padding_length+overhead then the MSB of t is zero. */ |
| 205 + good = DUPLICATE_MSB_TO_ALL(~t); |
| 206 + /* SSLv3 requires that the padding is minimal. */ |
| 207 + t = blockSize - (paddingLength+1); |
| 208 + good &= DUPLICATE_MSB_TO_ALL(~t); |
| 209 + plaintext->len -= good & (paddingLength+1); |
| 210 + return (good & SECSuccess) | (~good & SECFailure); |
| 211 +} |
| 212 + |
| 213 + |
| 214 +static SECStatus ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, |
| 215 + unsigned macSize) { |
| 216 + unsigned int paddingLength, good, t, toCheck, i; |
| 217 + const unsigned int overhead = 1 /* padding length byte */ + macSize; |
| 218 + |
| 219 + /* These lengths are all public so we can test them in non-constant |
| 220 + * time. */ |
| 221 + if (overhead > plaintext->len) { |
| 222 + return SECFailure; |
| 223 + } |
| 224 + |
| 225 + paddingLength = plaintext->buf[plaintext->len-1]; |
| 226 + t = plaintext->len; |
| 227 + t -= paddingLength+overhead; |
| 228 + /* If len >= paddingLength+overhead then the MSB of t is zero. */ |
| 229 + good = DUPLICATE_MSB_TO_ALL(~t); |
| 230 + |
| 231 + /* The padding consists of a length byte at the end of the record and then |
| 232 + * that many bytes of padding, all with the same value as the length byte. |
| 233 + * Thus, with the length byte included, there are paddingLength+1 bytes of |
| 234 + * padding. |
| 235 + * |
| 236 + * We can't check just |paddingLength+1| bytes because that leaks |
| 237 + * decrypted information. Therefore we always have to check the maximum |
| 238 + * amount of padding possible. (Again, the length of the record is |
| 239 + * public information so we can use it.) */ |
| 240 + toCheck = 255; /* maximum amount of padding. */ |
| 241 + if (toCheck > plaintext->len-1) { |
| 242 + toCheck = plaintext->len-1; |
| 243 + } |
| 244 + |
| 245 + for (i = 0; i < toCheck; i++) { |
| 246 + unsigned int t = paddingLength - i; |
| 247 + /* If i <= paddingLength then the MSB of t is zero and mask is |
| 248 + * 0xff. Otherwise, mask is 0. */ |
| 249 + unsigned char mask = DUPLICATE_MSB_TO_ALL(~t); |
| 250 + unsigned char b = plaintext->buf[plaintext->len-1-i]; |
| 251 + /* The final |paddingLength+1| bytes should all have the value |
| 252 + * |paddingLength|. Therefore the XOR should be zero. */ |
| 253 + good &= ~(mask&(paddingLength ^ b)); |
| 254 + } |
| 255 + |
| 256 + /* If any of the final |paddingLength+1| bytes had the wrong value, |
| 257 + * one or more of the lower eight bits of |good| will be cleared. We |
| 258 + * AND the bottom 8 bits together and duplicate the result to all the |
| 259 + * bits. */ |
| 260 + good &= good >> 4; |
| 261 + good &= good >> 2; |
| 262 + good &= good >> 1; |
| 263 + good <<= sizeof(good)*8-1; |
| 264 + good = DUPLICATE_MSB_TO_ALL(good); |
| 265 + |
| 266 + plaintext->len -= good & (paddingLength+1); |
| 267 + return (good & SECSuccess) | (~good & SECFailure); |
| 268 +} |
| 269 + |
| 270 +/* On entry: |
| 271 + * originalLength >= macSize |
| 272 + * macSize <= MAX_MAC_LENGTH |
| 273 + * plaintext->len >= macSize |
| 274 + */ |
| 275 +static void ssl_CBCExtractMAC(sslBuffer *plaintext, |
| 276 + unsigned int originalLength, |
| 277 + SSL3Opaque* out, |
| 278 + unsigned int macSize) { |
| 279 + unsigned char rotatedMac[MAX_MAC_LENGTH]; |
| 280 + /* macEnd is the index of |plaintext->buf| just after the end of the MAC. *
/ |
| 281 + unsigned macEnd = plaintext->len; |
| 282 + unsigned macStart = macEnd - macSize; |
| 283 + /* scanStart contains the number of bytes that we can ignore because |
| 284 + * the MAC's position can only vary by 255 bytes. */ |
| 285 + unsigned scanStart = 0; |
| 286 + unsigned i, j, divSpoiler; |
| 287 + unsigned char rotateOffset; |
| 288 + |
| 289 + if (originalLength > macSize + 255 + 1) |
| 290 + scanStart = originalLength - (macSize + 255 + 1); |
| 291 + |
| 292 + /* divSpoiler contains a multiple of macSize that is used to cause the |
| 293 + * modulo operation to be constant time. Without this, the time varies |
| 294 + * based on the amount of padding when running on Intel chips at least. |
| 295 + * |
| 296 + * The aim of right-shifting macSize is so that the compiler doesn't |
| 297 + * figure out that it can remove divSpoiler as that would require it |
| 298 + * to prove that macSize is always even, which I hope is beyond it. */ |
| 299 + divSpoiler = macSize >> 1; |
| 300 + divSpoiler <<= (sizeof(divSpoiler)-1)*8; |
| 301 + rotateOffset = (divSpoiler + macStart - scanStart) % macSize; |
| 302 + |
| 303 + memset(rotatedMac, 0, macSize); |
| 304 + for (i = scanStart; i < originalLength;) { |
| 305 + for (j = 0; j < macSize && i < originalLength; i++, j++) { |
| 306 + unsigned char macStarted = ssl_ConstantTimeGE(i, macStart); |
| 307 + unsigned char macEnded = ssl_ConstantTimeGE(i, macEnd); |
| 308 + unsigned char b = 0; |
| 309 + b = plaintext->buf[i]; |
| 310 + rotatedMac[j] |= b & macStarted & ~macEnded; |
| 311 + } |
| 312 + } |
| 313 + |
| 314 + /* Now rotate the MAC. If we knew that the MAC fit into a CPU cache line we |
| 315 + * could line-align |rotatedMac| and rotate in place. */ |
| 316 + memset(out, 0, macSize); |
| 317 + for (i = 0; i < macSize; i++) { |
| 318 + unsigned char offset = (divSpoiler + macSize - rotateOffset + i) % macSi
ze; |
| 319 + for (j = 0; j < macSize; j++) { |
| 320 + out[j] |= rotatedMac[i] & ssl_ConstantTimeEQ8(j, offset); |
| 321 + } |
| 322 + } |
| 323 +} |
| 324 + |
| 325 /* if cText is non-null, then decipher, check MAC, and decompress the |
| 326 * SSL record from cText->buf (typically gs->inbuf) |
| 327 * into databuf (typically gs->buf), and any previous contents of databuf |
| 328 @@ -9559,15 +9859,18 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText,
sslBuffer *databuf) |
| 329 ssl3CipherSpec * crSpec; |
| 330 SECStatus rv; |
| 331 unsigned int hashBytes = MAX_MAC_LENGTH + 1; |
| 332 - unsigned int padding_length; |
| 333 PRBool isTLS; |
| 334 - PRBool padIsBad = PR_FALSE; |
| 335 SSL3ContentType rType; |
| 336 SSL3Opaque hash[MAX_MAC_LENGTH]; |
| 337 + SSL3Opaque givenHashBuf[MAX_MAC_LENGTH]; |
| 338 + SSL3Opaque *givenHash; |
| 339 sslBuffer *plaintext; |
| 340 sslBuffer temp_buf; |
| 341 PRUint64 dtls_seq_num; |
| 342 unsigned int ivLen = 0; |
| 343 + unsigned int originalLen = 0; |
| 344 + unsigned int good; |
| 345 + unsigned int minLength; |
| 346 |
| 347 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
| 348 |
| 349 @@ -9635,6 +9938,30 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, s
slBuffer *databuf) |
| 350 } |
| 351 } |
| 352 |
| 353 + good = (unsigned)-1; |
| 354 + minLength = crSpec->mac_size; |
| 355 + if (cipher_def->type == type_block) { |
| 356 + /* CBC records have a padding length byte at the end. */ |
| 357 + minLength++; |
| 358 + if (crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { |
| 359 + /* With >= TLS 1.1, CBC records have an explicit IV. */ |
| 360 + minLength += cipher_def->iv_size; |
| 361 + } |
| 362 + } |
| 363 + |
| 364 + /* We can perform this test in variable time because the record's total |
| 365 + * length and the ciphersuite are both public knowledge. */ |
| 366 + if (cText->buf->len < minLength) { |
| 367 + SSL_DBG(("%d: SSL3[%d]: HandleRecord, record too small.", |
| 368 + SSL_GETPID(), ss->fd)); |
| 369 + /* must not hold spec lock when calling SSL3_SendAlert. */ |
| 370 + ssl_ReleaseSpecReadLock(ss); |
| 371 + SSL3_SendAlert(ss, alert_fatal, bad_record_mac); |
| 372 + /* always log mac error, in case attacker can read server logs. */ |
| 373 + PORT_SetError(SSL_ERROR_BAD_MAC_READ); |
| 374 + return SECFailure; |
| 375 + } |
| 376 + |
| 377 if (cipher_def->type == type_block && |
| 378 crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { |
| 379 /* Consume the per-record explicit IV. RFC 4346 Section 6.2.3.2 states |
| 380 @@ -9652,16 +9979,6 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, s
slBuffer *databuf) |
| 381 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
| 382 return SECFailure; |
| 383 } |
| 384 - if (ivLen > cText->buf->len) { |
| 385 - SSL_DBG(("%d: SSL3[%d]: HandleRecord, IV length check failed", |
| 386 - SSL_GETPID(), ss->fd)); |
| 387 - /* must not hold spec lock when calling SSL3_SendAlert. */ |
| 388 - ssl_ReleaseSpecReadLock(ss); |
| 389 - SSL3_SendAlert(ss, alert_fatal, bad_record_mac); |
| 390 - /* always log mac error, in case attacker can read server logs. */ |
| 391 - PORT_SetError(SSL_ERROR_BAD_MAC_READ); |
| 392 - return SECFailure; |
| 393 - } |
| 394 |
| 395 PRINT_BUF(80, (ss, "IV (ciphertext):", cText->buf->buf, ivLen)); |
| 396 |
| 397 @@ -9672,12 +9989,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, s
slBuffer *databuf) |
| 398 rv = crSpec->decode(crSpec->decodeContext, iv, &decoded, |
| 399 sizeof(iv), cText->buf->buf, ivLen); |
| 400 |
| 401 - if (rv != SECSuccess) { |
| 402 - /* All decryption failures must be treated like a bad record |
| 403 - * MAC; see RFC 5246 (TLS 1.2). |
| 404 - */ |
| 405 - padIsBad = PR_TRUE; |
| 406 - } |
| 407 + good &= SECStatusToMask(rv); |
| 408 } |
| 409 |
| 410 /* If we will be decompressing the buffer we need to decrypt somewhere |
| 411 @@ -9719,54 +10031,70 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText,
sslBuffer *databuf) |
| 412 rv = crSpec->decode( |
| 413 crSpec->decodeContext, plaintext->buf, (int *)&plaintext->len, |
| 414 plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen); |
| 415 + good &= SECStatusToMask(rv); |
| 416 |
| 417 PRINT_BUF(80, (ss, "cleartext:", plaintext->buf, plaintext->len)); |
| 418 - if (rv != SECSuccess) { |
| 419 - /* All decryption failures must be treated like a bad record |
| 420 - * MAC; see RFC 5246 (TLS 1.2). |
| 421 - */ |
| 422 - padIsBad = PR_TRUE; |
| 423 - } |
| 424 + |
| 425 + originalLen = plaintext->len; |
| 426 |
| 427 /* If it's a block cipher, check and strip the padding. */ |
| 428 - if (cipher_def->type == type_block && !padIsBad) { |
| 429 - PRUint8 * pPaddingLen = plaintext->buf + plaintext->len - 1; |
| 430 - padding_length = *pPaddingLen; |
| 431 - /* TLS permits padding to exceed the block size, up to 255 bytes. */ |
| 432 - if (padding_length + 1 + crSpec->mac_size > plaintext->len) |
| 433 - padIsBad = PR_TRUE; |
| 434 - else { |
| 435 - plaintext->len -= padding_length + 1; |
| 436 - /* In TLS all padding bytes must be equal to the padding length. */ |
| 437 - if (isTLS) { |
| 438 - PRUint8 *p; |
| 439 - for (p = pPaddingLen - padding_length; p < pPaddingLen; ++p) { |
| 440 - padIsBad |= *p ^ padding_length; |
| 441 - } |
| 442 - } |
| 443 - } |
| 444 - } |
| 445 + if (cipher_def->type == type_block) { |
| 446 + const unsigned int blockSize = cipher_def->iv_size; |
| 447 + const unsigned int macSize = crSpec->mac_size; |
| 448 |
| 449 - /* Remove the MAC. */ |
| 450 - if (plaintext->len >= crSpec->mac_size) |
| 451 - plaintext->len -= crSpec->mac_size; |
| 452 - else |
| 453 - padIsBad = PR_TRUE; /* really macIsBad */ |
| 454 + if (crSpec->version <= SSL_LIBRARY_VERSION_3_0) { |
| 455 + good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding( |
| 456 + plaintext, blockSize, macSize)); |
| 457 + } else { |
| 458 + good &= SECStatusToMask(ssl_RemoveTLSCBCPadding( |
| 459 + plaintext, macSize)); |
| 460 + } |
| 461 + } |
| 462 |
| 463 /* compute the MAC */ |
| 464 rType = cText->type; |
| 465 - rv = ssl3_ComputeRecordMAC( crSpec, (PRBool)(!ss->sec.isServer), |
| 466 - IS_DTLS(ss), rType, cText->version, |
| 467 - IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, |
| 468 - plaintext->buf, plaintext->len, hash, &hashBytes); |
| 469 - if (rv != SECSuccess) { |
| 470 - padIsBad = PR_TRUE; /* really macIsBad */ |
| 471 + if (cipher_def->type == type_block) { |
| 472 + rv = ssl3_ComputeRecordMACConstantTime( |
| 473 + crSpec, (PRBool)(!ss->sec.isServer), |
| 474 + IS_DTLS(ss), rType, cText->version, |
| 475 + IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, |
| 476 + plaintext->buf, plaintext->len, originalLen, |
| 477 + hash, &hashBytes); |
| 478 + |
| 479 + ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf, |
| 480 + crSpec->mac_size); |
| 481 + givenHash = givenHashBuf; |
| 482 + |
| 483 + /* plaintext->len will always have enough space to remove the MAC |
| 484 + * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust |
| 485 + * plaintext->len if the result has enough space for the MAC and we |
| 486 + * tested the unadjusted size against minLength, above. */ |
| 487 + plaintext->len -= crSpec->mac_size; |
| 488 + } else { |
| 489 + /* This is safe because we checked the minLength above. */ |
| 490 + plaintext->len -= crSpec->mac_size; |
| 491 + |
| 492 + rv = ssl3_ComputeRecordMAC( |
| 493 + crSpec, (PRBool)(!ss->sec.isServer), |
| 494 + IS_DTLS(ss), rType, cText->version, |
| 495 + IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, |
| 496 + plaintext->buf, plaintext->len, |
| 497 + hash, &hashBytes); |
| 498 + |
| 499 + /* We can read the MAC directly from the record because its location is |
| 500 + * public when a stream cipher is used. */ |
| 501 + givenHash = plaintext->buf + plaintext->len; |
| 502 + } |
| 503 + |
| 504 + good &= SECStatusToMask(rv); |
| 505 + |
| 506 + if (hashBytes != (unsigned)crSpec->mac_size || |
| 507 + NSS_SecureMemcmp(givenHash, hash, crSpec->mac_size) != 0) { |
| 508 + /* We're allowed to leak whether or not the MAC check was correct */ |
| 509 + good = 0; |
| 510 } |
| 511 |
| 512 - /* Check the MAC */ |
| 513 - if (hashBytes != (unsigned)crSpec->mac_size || padIsBad || |
| 514 - NSS_SecureMemcmp(plaintext->buf + plaintext->len, hash, |
| 515 - crSpec->mac_size) != 0) { |
| 516 + if (good == 0) { |
| 517 /* must not hold spec lock when calling SSL3_SendAlert. */ |
| 518 ssl_ReleaseSpecReadLock(ss); |
| 519 |
OLD | NEW |