| OLD | NEW |
| 1 diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/s
sl/ssl3con.c | 1 diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c |
| 2 index c3706fe..4b79321 100644 | 2 --- a/nss/lib/ssl/ssl3con.c» 2013-04-27 09:39:58.595657996 -0700 |
| 3 --- a/mozilla/security/nss/lib/ssl/ssl3con.c | 3 +++ b/nss/lib/ssl/ssl3con.c» 2013-04-27 09:41:05.836609068 -0700 |
| 4 +++ b/mozilla/security/nss/lib/ssl/ssl3con.c | 4 @@ -2028,6 +2028,20 @@ ssl3_ComputeRecordMAC( |
| 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; | 5 return rv; |
| 15 } | 6 } |
| 16 | 7 |
| 17 +/* This is a bodge to allow this code to be compiled against older NSS headers | 8 +/* 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. */ | 9 + * that don't contain the CBC constant-time changes. */ |
| 19 +#ifndef CKM_NSS_HMAC_CONSTANT_TIME | 10 +#ifndef CKM_NSS_HMAC_CONSTANT_TIME |
| 20 +#define CKM_NSS_HMAC_CONSTANT_TIME (CKM_NSS + 19) | 11 +#define CKM_NSS_HMAC_CONSTANT_TIME (CKM_NSS + 19) |
| 21 +#define CKM_NSS_SSL3_MAC_CONSTANT_TIME (CKM_NSS + 20) | 12 +#define CKM_NSS_SSL3_MAC_CONSTANT_TIME (CKM_NSS + 20) |
| 22 + | 13 + |
| 23 +typedef struct CK_NSS_MAC_CONSTANT_TIME_PARAMS { | 14 +typedef struct CK_NSS_MAC_CONSTANT_TIME_PARAMS { |
| 24 + CK_MECHANISM_TYPE macAlg; /* in */ | 15 + CK_MECHANISM_TYPE macAlg; /* in */ |
| 25 + CK_ULONG ulBodyTotalLen; /* in */ | 16 + CK_ULONG ulBodyTotalLen; /* in */ |
| 26 + CK_BYTE * pHeader; /* in */ | 17 + CK_BYTE * pHeader; /* in */ |
| 27 + CK_ULONG ulHeaderLen; /* in */ | 18 + CK_ULONG ulHeaderLen; /* in */ |
| 28 +} CK_NSS_MAC_CONSTANT_TIME_PARAMS; | 19 +} CK_NSS_MAC_CONSTANT_TIME_PARAMS; |
| 29 +#endif | 20 +#endif |
| 30 + | 21 + |
| 31 +/* Called from: ssl3_HandleRecord() | 22 /* Called from: ssl3_HandleRecord() |
| 32 + * Caller must already hold the SpecReadLock. (wish we could assert that!) | 23 * Caller must already hold the SpecReadLock. (wish we could assert that!) |
| 33 + * | 24 * |
| 34 + * On entry: | 25 @@ -2050,7 +2064,8 @@ ssl3_ComputeRecordMACConstantTime( |
| 35 + * originalLen >= inputLen >= MAC size | 26 { |
| 36 +*/ | 27 CK_MECHANISM_TYPE macType; |
| 37 +static SECStatus | 28 CK_NSS_MAC_CONSTANT_TIME_PARAMS params; |
| 38 +ssl3_ComputeRecordMACConstantTime( | 29 - SECItem param, inputItem, outputItem; |
| 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; | 30 + PK11Context * mac_context; |
| 54 + SECItem param; | 31 + SECItem param; |
| 55 + SECStatus rv; | 32 SECStatus rv; |
| 56 + unsigned char header[13]; | 33 unsigned char header[13]; |
| 57 + PK11SymKey * key; | 34 PK11SymKey * key; |
| 58 + int recordLength; | 35 @@ -2111,34 +2126,27 @@ ssl3_ComputeRecordMACConstantTime( |
| 59 + | 36 param.len = sizeof(params); |
| 60 + PORT_Assert(inputLen >= spec->mac_size); | 37 param.type = 0; |
| 61 + PORT_Assert(originalLen >= inputLen); | 38 |
| 62 + | 39 - inputItem.data = (unsigned char *) input; |
| 63 + if (spec->bypassCiphers) { | 40 - inputItem.len = inputLen; |
| 64 +» /* This function doesn't support PKCS#11 bypass. We fallback on the | 41 - inputItem.type = 0; |
| 65 +» * non-constant time version. */ | 42 - |
| 66 +» goto fallback; | 43 - outputItem.data = outbuf; |
| 67 + } | 44 - outputItem.len = *outLen; |
| 68 + | 45 - outputItem.type = 0; |
| 69 + if (spec->mac_def->mac == mac_null) { | 46 - |
| 70 +» *outLen = 0; | 47 key = spec->server.write_mac_key; |
| 71 +» return SECSuccess; | 48 if (!useServerMacKey) { |
| 72 + } | 49 » key = spec->client.write_mac_key; |
| 73 + | 50 } |
| 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.macAlg = 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); | 51 + mac_context = PK11_CreateContextBySymKey(macType, CKA_SIGN, key, ¶m); |
| 120 + if (mac_context == NULL) { | 52 + if (mac_context == NULL) { |
| 121 + /* Older versions of NSS may not support constant-time MAC. */ | 53 + /* Older versions of NSS may not support constant-time MAC. */ |
| 122 + goto fallback; | 54 + goto fallback; |
| 123 + } | 55 + } |
| 124 + | 56 |
| 57 - rv = PK11_SignWithSymKey(key, macType, ¶m, &outputItem, &inputItem); |
| 58 - if (rv != SECSuccess) { |
| 59 -» if (PORT_GetError() == SEC_ERROR_INVALID_ALGORITHM) { |
| 60 -» goto fallback; |
| 61 -» } |
| 125 + rv = PK11_DigestBegin(mac_context); | 62 + rv = PK11_DigestBegin(mac_context); |
| 126 + rv |= PK11_DigestOp(mac_context, input, inputLen); | 63 + rv |= PK11_DigestOp(mac_context, input, inputLen); |
| 127 + rv |= PK11_DigestFinal(mac_context, outbuf, outLen, spec->mac_size); | 64 + rv |= PK11_DigestFinal(mac_context, outbuf, outLen, spec->mac_size); |
| 128 + PK11_DestroyContext(mac_context, PR_TRUE); | 65 + PK11_DestroyContext(mac_context, PR_TRUE); |
| 129 + | 66 |
| 67 -» *outLen = 0; |
| 130 + PORT_Assert(rv != SECSuccess || *outLen == (unsigned)spec->mac_size); | 68 + PORT_Assert(rv != SECSuccess || *outLen == (unsigned)spec->mac_size); |
| 131 + | 69 + |
| 132 + if (rv != SECSuccess) { | 70 + if (rv != SECSuccess) { |
| 133 +» rv = SECFailure; | 71 » rv = SECFailure; |
| 134 +» ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); | 72 » ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); |
| 135 + } | 73 -» return rv; |
| 136 + return rv; | 74 } |
| 137 + | 75 - |
| 138 +fallback: | 76 - PORT_Assert(outputItem.len == (unsigned)spec->mac_size); |
| 139 + /* ssl3_ComputeRecordMAC expects the MAC to have been removed from the | 77 - *outLen = outputItem.len; |
| 140 + * length already. */ | 78 - |
| 141 + inputLen -= spec->mac_size; | 79 return rv; |
| 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 | 80 |
| 154 +/* These macros return the given value with the MSB copied to all the other | 81 fallback: |
| 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 |