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 |