OLD | NEW |
| (Empty) |
1 From 1c425d479c495d266c23876887198a54e82e7078 Mon Sep 17 00:00:00 2001 | |
2 From: Adam Langley <agl@chromium.org> | |
3 Date: Mon, 3 Oct 2011 12:22:24 -0400 | |
4 Subject: [PATCH] cachedinfo.patch | |
5 | |
6 --- | |
7 mozilla/security/nss/lib/ssl/fnv1a64.c | 72 +++++++++ | |
8 mozilla/security/nss/lib/ssl/manifest.mn | 1 + | |
9 mozilla/security/nss/lib/ssl/ssl.h | 26 +++ | |
10 mozilla/security/nss/lib/ssl/ssl3con.c | 221 +++++++++++++++++++------ | |
11 mozilla/security/nss/lib/ssl/ssl3ext.c | 258 ++++++++++++++++++++++++++++++ | |
12 mozilla/security/nss/lib/ssl/sslauth.c | 40 +++++ | |
13 mozilla/security/nss/lib/ssl/sslimpl.h | 33 ++++- | |
14 mozilla/security/nss/lib/ssl/sslsock.c | 11 ++ | |
15 mozilla/security/nss/lib/ssl/sslt.h | 3 +- | |
16 9 files changed, 611 insertions(+), 54 deletions(-) | |
17 create mode 100644 mozilla/security/nss/lib/ssl/fnv1a64.c | |
18 | |
19 diff --git a/mozilla/security/nss/lib/ssl/fnv1a64.c b/mozilla/security/nss/lib/s
sl/fnv1a64.c | |
20 new file mode 100644 | |
21 index 0000000..c7c4b08 | |
22 --- /dev/null | |
23 +++ b/mozilla/security/nss/lib/ssl/fnv1a64.c | |
24 @@ -0,0 +1,72 @@ | |
25 +/* | |
26 + * FNV1A64 Hash | |
27 + * http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param | |
28 + * | |
29 + * ***** BEGIN LICENSE BLOCK ***** | |
30 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | |
31 + * | |
32 + * The contents of this file are subject to the Mozilla Public License Version | |
33 + * 1.1 (the "License"); you may not use this file except in compliance with | |
34 + * the License. You may obtain a copy of the License at | |
35 + * http://www.mozilla.org/MPL/ | |
36 + * | |
37 + * Software distributed under the License is distributed on an "AS IS" basis, | |
38 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
39 + * for the specific language governing rights and limitations under the | |
40 + * License. | |
41 + * | |
42 + * The Original Code is the Netscape security libraries. | |
43 + * | |
44 + * The Initial Developer of the Original Code is | |
45 + * Netscape Communications Corporation. | |
46 + * Portions created by the Initial Developer are Copyright (C) 1994-2000 | |
47 + * the Initial Developer. All Rights Reserved. | |
48 + * | |
49 + * Contributor(s): | |
50 + * Adam Langley, Google Inc. | |
51 + * | |
52 + * Alternatively, the contents of this file may be used under the terms of | |
53 + * either the GNU General Public License Version 2 or later (the "GPL"), or | |
54 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | |
55 + * in which case the provisions of the GPL or the LGPL are applicable instead | |
56 + * of those above. If you wish to allow use of your version of this file only | |
57 + * under the terms of either the GPL or the LGPL, and not to allow others to | |
58 + * use your version of this file under the terms of the MPL, indicate your | |
59 + * decision by deleting the provisions above and replace them with the notice | |
60 + * and other provisions required by the GPL or the LGPL. If you do not delete | |
61 + * the provisions above, a recipient may use your version of this file under | |
62 + * the terms of any one of the MPL, the GPL or the LGPL. | |
63 + * | |
64 + * ***** END LICENSE BLOCK ***** */ | |
65 + | |
66 +/* $Id: fnv1a64.c,v 1.0 2010/08/09 13:00:00 agl%google.com Exp $ */ | |
67 + | |
68 +#include "prtypes.h" | |
69 +#include "prnetdb.h" | |
70 + | |
71 +/* Older versions of Visual C++ don't support the 'ull' suffix. */ | |
72 +#ifdef _MSC_VER | |
73 +static const PRUint64 FNV1A64_OFFSET_BASIS = 14695981039346656037ui64; | |
74 +static const PRUint64 FNV1A64_PRIME = 1099511628211ui64; | |
75 +#else | |
76 +static const PRUint64 FNV1A64_OFFSET_BASIS = 14695981039346656037ull; | |
77 +static const PRUint64 FNV1A64_PRIME = 1099511628211ull; | |
78 +#endif | |
79 + | |
80 +void FNV1A64_Init(PRUint64* digest) { | |
81 + *digest = FNV1A64_OFFSET_BASIS; | |
82 +} | |
83 + | |
84 +void FNV1A64_Update(PRUint64* digest, const unsigned char *data, | |
85 + unsigned int length) { | |
86 + unsigned int i; | |
87 + | |
88 + for (i = 0; i < length; i++) { | |
89 + *digest ^= data[i]; | |
90 + *digest *= FNV1A64_PRIME; | |
91 + } | |
92 +} | |
93 + | |
94 +void FNV1A64_Final(PRUint64 *digest) { | |
95 + *digest = PR_htonll(*digest); | |
96 +} | |
97 diff --git a/mozilla/security/nss/lib/ssl/manifest.mn b/mozilla/security/nss/lib
/ssl/manifest.mn | |
98 index 8451229..f09d770 100644 | |
99 --- a/mozilla/security/nss/lib/ssl/manifest.mn | |
100 +++ b/mozilla/security/nss/lib/ssl/manifest.mn | |
101 @@ -51,6 +51,7 @@ MAPFILE = $(OBJDIR)/ssl.def | |
102 | |
103 CSRCS = \ | |
104 derive.c \ | |
105 + fnv1a64.c \ | |
106 prelib.c \ | |
107 ssl3con.c \ | |
108 ssl3gthr.c \ | |
109 diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/s
sl.h | |
110 index 221fe2d..3a22b45 100644 | |
111 --- a/mozilla/security/nss/lib/ssl/ssl.h | |
112 +++ b/mozilla/security/nss/lib/ssl/ssl.h | |
113 @@ -140,6 +140,8 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFil
eDesc *fd); | |
114 /* bits. The advantage of False Start is that it saves a round trip for */ | |
115 /* client-speaks-first protocols when performing a full handshake. */ | |
116 #define SSL_ENABLE_OCSP_STAPLING 23 /* Request OCSP stapling (client) */ | |
117 +#define SSL_ENABLE_CACHED_INFO 24 /* Enable TLS cached information */ | |
118 + /* extension, off by default. */ | |
119 | |
120 #ifdef SSL_DEPRECATED_FUNCTION | |
121 /* Old deprecated function names */ | |
122 @@ -256,6 +258,12 @@ SSL_IMPORT SECStatus SSL_SecurityStatus(PRFileDesc *fd, int
*on, char **cipher, | |
123 #define SSL_SECURITY_STATUS_FORTEZZA 3 /* NO LONGER SUPPORTED */ | |
124 | |
125 /* | |
126 +** Returns true if the server's Certificate message contained a hash of the | |
127 +** certificate chain due to the TLS cached info extension. | |
128 +*/ | |
129 +SSL_IMPORT PRBool SSL_CertChainDigestReceived(PRFileDesc *fd); | |
130 + | |
131 +/* | |
132 ** Return the certificate for our SSL peer. If the client calls this | |
133 ** it will always return the server's certificate. If the server calls | |
134 ** this, it may return NULL if client authentication is not enabled or | |
135 @@ -275,6 +283,13 @@ SSL_IMPORT CERTCertificate *SSL_PeerCertificate(PRFileDesc
*fd); | |
136 SSL_IMPORT SECStatus SSL_PeerCertificateChain( | |
137 PRFileDesc *fd, CERTCertificate **certs, unsigned int *certs_size); | |
138 | |
139 +/* | |
140 +** Set the predicted cert chain to be used in the cached info extension. | |
141 +*/ | |
142 +SSL_IMPORT SECStatus SSL_SetPredictedPeerCertificates(PRFileDesc *fd, | |
143 + CERTCertificate **certs, | |
144 + unsigned int len); | |
145 + | |
146 /* SSL_GetStapledOCSPResponse returns the OCSP response that was provided by | |
147 * the TLS server. The resulting data is copied to |out_data|. On entry, |*len| | |
148 * must contain the size of |out_data|. On exit, |*len| will contain the size | |
149 @@ -405,6 +420,17 @@ SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBad
CertHandler f, | |
150 void *arg); | |
151 | |
152 /* | |
153 + ** Set the predicted chain of certificates for the peer. This is used for the | |
154 + ** TLS Cached Info extension. Note that the SSL_ENABLE_CACHED_INFO option must | |
155 + ** be set for this to occur. | |
156 + ** | |
157 + ** This function takes a reference to each of the given certificates. | |
158 + */ | |
159 + SSL_IMPORT SECStatus SSL_SetPredictedPeerCertificates( | |
160 + PRFileDesc *fd, CERTCertificate **certs, | |
161 + unsigned int numCerts); | |
162 + | |
163 +/* | |
164 ** Configure SSL socket for running a secure server. Needs the | |
165 ** certificate for the server and the servers private key. The arguments | |
166 ** are copied. | |
167 diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/s
sl/ssl3con.c | |
168 index ca2793f..dd99962 100644 | |
169 --- a/mozilla/security/nss/lib/ssl/ssl3con.c | |
170 +++ b/mozilla/security/nss/lib/ssl/ssl3con.c | |
171 @@ -5145,7 +5145,6 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUin
t32 length) | |
172 ssl3_CopyPeerCertsFromSID(ss, sid); | |
173 } | |
174 | |
175 - | |
176 /* NULL value for PMS signifies re-use of the old MS */ | |
177 rv = ssl3_InitPendingCipherSpec(ss, NULL); | |
178 if (rv != SECSuccess) { | |
179 @@ -7715,6 +7714,69 @@ ssl3_SendCertificate(sslSocket *ss) | |
180 } | |
181 } | |
182 | |
183 + if (ss->ssl3.cachedInfoCertChainDigestReceived) { | |
184 + /* Compute hash. */ | |
185 + PRUint64 certChainHash; | |
186 + int i; | |
187 + FNV1A64_Init(&certChainHash); | |
188 + for (i = 0; i < certChain->len; i++) { | |
189 + unsigned int certLen = certChain->certs[i].len; | |
190 + unsigned char certLenArray[3] = { | |
191 + certLen >> 16, | |
192 + certLen >> 8, | |
193 + certLen | |
194 + }; | |
195 + FNV1A64_Update(&certChainHash, certLenArray, sizeof(certLenArray)); | |
196 + FNV1A64_Update(&certChainHash, certChain->certs[i].data, certLen); | |
197 + } | |
198 + FNV1A64_Final(&certChainHash); | |
199 + | |
200 + /* Both |&certChainHash| and |ss->ssl3.certChainDigest| should be in | |
201 + * network byte order since both are computed with the FNV1A64 hash, | |
202 + * which calls the function htonll. | |
203 + */ | |
204 + if (memcmp(&certChainHash, ss->ssl3.certChainDigest, | |
205 + sizeof(certChainHash)) == 0) { | |
206 + /* The client correctly predicted the certificate chain. */ | |
207 + | |
208 + /* Handshake type: certificate. */ | |
209 + rv = ssl3_AppendHandshakeNumber(ss, certificate, 1); | |
210 + if (rv != SECSuccess) { | |
211 + return rv; /* err set by AppendHandshake. */ | |
212 + } | |
213 + /* Handshake message length. */ | |
214 + rv = ssl3_AppendHandshakeNumber(ss, 15, 3); | |
215 + if (rv != SECSuccess) { | |
216 + return rv; /* err set by AppendHandshake. */ | |
217 + } | |
218 + /* CertChainLen(3) + ASN.1CertLen(3) + DigestLen(1) + Digest(8) */ | |
219 + rv = ssl3_AppendHandshakeNumber(ss, 12, 3); | |
220 + if (rv != SECSuccess) { | |
221 + return rv; /* err set by AppendHandshake. */ | |
222 + } | |
223 + /* ASN.1CertLen(3) + DigestLen(1) + Digest(8) */ | |
224 + rv = ssl3_AppendHandshakeNumber(ss, 9, 3); | |
225 + if (rv != SECSuccess) { | |
226 + return rv; /* err set by AppendHandshake. */ | |
227 + } | |
228 + /* Digest Length Byte */ | |
229 + rv = ssl3_AppendHandshakeNumber(ss, sizeof(certChainHash), 1); | |
230 + if (rv != SECSuccess) { | |
231 + return rv; /* err set by AppendHandshake. */ | |
232 + } | |
233 + /* Digest */ | |
234 + rv = ssl3_AppendHandshake(ss, &certChainHash, | |
235 + sizeof(certChainHash)); | |
236 + if (rv != SECSuccess) { | |
237 + return rv; /* err set by AppendHandshake. */ | |
238 + } | |
239 + | |
240 + return SECSuccess; | |
241 + } | |
242 + } | |
243 + | |
244 + /* Send the entire certificate as usual. */ | |
245 + | |
246 rv = ssl3_AppendHandshakeHeader(ss, certificate, len + 3); | |
247 if (rv != SECSuccess) { | |
248 return rv; /* err set by AppendHandshake. */ | |
249 @@ -7869,7 +7931,6 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUin
t32 length) | |
250 PRInt32 size; | |
251 SECStatus rv; | |
252 PRBool isServer = (PRBool)(!!ss->sec.isServer); | |
253 - PRBool trusted = PR_FALSE; | |
254 PRBool isTLS; | |
255 SSL3AlertDescription desc = bad_certificate; | |
256 int errCode = SSL_ERROR_RX_MALFORMED_CERTIFICATE; | |
257 @@ -7929,35 +7990,46 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRU
int32 length) | |
258 goto loser; /* don't send alerts on memory errors */ | |
259 } | |
260 | |
261 - /* First get the peer cert. */ | |
262 - remaining -= 3; | |
263 - if (remaining < 0) | |
264 - goto decode_loser; | |
265 + if (length == 12 && ssl3_ExtensionNegotiated(ss, ssl_cached_info_xtn)) { | |
266 + /* We are dealing with a certificate_chain digest */ | |
267 + int i; | |
268 | |
269 - size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); | |
270 - if (size <= 0) | |
271 - goto loser; /* fatal alert already sent by ConsumeHandshake. */ | |
272 + ss->ssl3.cachedInfoCertChainDigestReceived = PR_TRUE; | |
273 | |
274 - if (remaining < size) | |
275 - goto decode_loser; | |
276 + /* Make sure the digests match. */ | |
277 + if (memcmp(b + 4, ss->ssl3.certChainDigest, 8)) { | |
278 + desc = handshake_failure; | |
279 + goto alert_loser; | |
280 + } | |
281 | |
282 - certItem.data = b; | |
283 - certItem.len = size; | |
284 - b += size; | |
285 - length -= size; | |
286 - remaining -= size; | |
287 + /* First get the peer cert. */ | |
288 + if (ss->ssl3.predictedCertChain[0] == NULL) { | |
289 + desc = handshake_failure; | |
290 + goto alert_loser; | |
291 + } | |
292 + ss->sec.peerCert = CERT_DupCertificate(ss->ssl3.predictedCertChain[0]); | |
293 | |
294 - ss->sec.peerCert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, | |
295 - PR_FALSE, PR_TRUE); | |
296 - if (ss->sec.peerCert == NULL) { | |
297 - /* We should report an alert if the cert was bad, but not if the | |
298 - * problem was just some local problem, like memory error. | |
299 - */ | |
300 - goto ambiguous_err; | |
301 - } | |
302 + /* Now get all of the CA certs. */ | |
303 + ss->ssl3.peerCertChain = NULL; | |
304 + for (i = 1; ss->ssl3.predictedCertChain[i] != NULL; i++) { | |
305 + c = PORT_ArenaNew(arena, ssl3CertNode); | |
306 + if (c == NULL) { | |
307 + goto loser; /* don't send alerts on memory errors */ | |
308 + } | |
309 + c->cert = CERT_DupCertificate(ss->ssl3.predictedCertChain[i]); | |
310 + c->next = NULL; | |
311 + if (lastCert) { | |
312 + lastCert->next = c; | |
313 + } else { | |
314 + ss->ssl3.peerCertChain = c; | |
315 + } | |
316 + lastCert = c; | |
317 + } | |
318 + } else { | |
319 + /* We are dealing with a regular certificate message */ | |
320 + ss->ssl3.cachedInfoCertChainDigestReceived = PR_FALSE; | |
321 | |
322 - /* Now get all of the CA certs. */ | |
323 - while (remaining > 0) { | |
324 + /* First get the peer cert. */ | |
325 remaining -= 3; | |
326 if (remaining < 0) | |
327 goto decode_loser; | |
328 @@ -7971,35 +8043,63 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRU
int32 length) | |
329 | |
330 certItem.data = b; | |
331 certItem.len = size; | |
332 - b += size; | |
333 + b += size; | |
334 length -= size; | |
335 remaining -= size; | |
336 | |
337 - c = PORT_ArenaNew(arena, ssl3CertNode); | |
338 - if (c == NULL) { | |
339 - goto loser; /* don't send alerts on memory errors */ | |
340 - } | |
341 - | |
342 - c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, | |
343 - PR_FALSE, PR_TRUE); | |
344 - if (c->cert == NULL) { | |
345 + ss->sec.peerCert = CERT_NewTempCertificate(ss->dbHandle, &certItem, | |
346 + NULL, PR_FALSE, PR_TRUE); | |
347 + if (ss->sec.peerCert == NULL) { | |
348 + /* We should report an alert if the cert was bad, but not if the | |
349 + * problem was just some local problem, like memory error. | |
350 + */ | |
351 goto ambiguous_err; | |
352 } | |
353 | |
354 - if (c->cert->trust) | |
355 - trusted = PR_TRUE; | |
356 + /* Now get all of the CA certs. */ | |
357 + while (remaining > 0) { | |
358 + remaining -= 3; | |
359 + if (remaining < 0) | |
360 + goto decode_loser; | |
361 | |
362 - c->next = NULL; | |
363 - if (lastCert) { | |
364 - lastCert->next = c; | |
365 - } else { | |
366 - certs = c; | |
367 + size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); | |
368 + if (size <= 0) | |
369 + goto loser; /* fatal alert already sent by ConsumeHandshake. */ | |
370 + | |
371 + if (remaining < size) | |
372 + goto decode_loser; | |
373 + | |
374 + certItem.data = b; | |
375 + certItem.len = size; | |
376 + b += size; | |
377 + length -= size; | |
378 + remaining -= size; | |
379 + | |
380 + c = PORT_ArenaNew(arena, ssl3CertNode); | |
381 + if (c == NULL) { | |
382 + goto loser; /* don't send alerts on memory errors */ | |
383 + } | |
384 + | |
385 + c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, | |
386 + PR_FALSE, PR_TRUE); | |
387 + if (c->cert == NULL) { | |
388 + goto ambiguous_err; | |
389 + } | |
390 + | |
391 + c->next = NULL; | |
392 + if (lastCert) { | |
393 + lastCert->next = c; | |
394 + } else { | |
395 + certs = c; | |
396 + } | |
397 + lastCert = c; | |
398 } | |
399 - lastCert = c; | |
400 - } | |
401 | |
402 - if (remaining != 0) | |
403 - goto decode_loser; | |
404 + if (remaining != 0) | |
405 + goto decode_loser; | |
406 + | |
407 + ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL; | |
408 + } | |
409 | |
410 SECKEY_UpdateCertPQG(ss->sec.peerCert); | |
411 | |
412 @@ -8019,8 +8119,6 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUin
t32 length) | |
413 /* someone will handle this connection asynchronously*/ | |
414 SSL_DBG(("%d: SSL3[%d]: go to async cert handler", | |
415 SSL_GETPID(), ss->fd)); | |
416 - ss->ssl3.peerCertChain = certs; | |
417 - certs = NULL; | |
418 ssl_SetAlwaysBlock(ss); | |
419 goto cert_block; | |
420 } | |
421 @@ -8045,7 +8143,7 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUin
t32 length) | |
422 } | |
423 | |
424 ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert); | |
425 - ssl3_CopyPeerCertsToSID(certs, ss->sec.ci.sid); | |
426 + ssl3_CopyPeerCertsToSID(ss->ssl3.peerCertChain, ss->sec.ci.sid); | |
427 | |
428 if (!ss->sec.isServer) { | |
429 /* set the server authentication and key exchange types and sizes | |
430 @@ -8090,8 +8188,6 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUin
t32 length) | |
431 } | |
432 } | |
433 | |
434 - ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL; | |
435 - | |
436 cert_block: | |
437 if (ss->sec.isServer) { | |
438 ss->ssl3.hs.ws = wait_client_key; | |
439 @@ -8161,7 +8257,10 @@ alert_loser: | |
440 (void)SSL3_SendAlert(ss, alert_fatal, desc); | |
441 | |
442 loser: | |
443 - ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL; | |
444 + if (ss->ssl3.peerCertChain == NULL) { | |
445 + ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL; | |
446 + } | |
447 + PORT_Assert(certs == NULL); | |
448 ssl3_CleanupPeerCerts(ss); | |
449 | |
450 if (ss->sec.peerCert != NULL) { | |
451 @@ -9647,6 +9746,21 @@ ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache) | |
452 return rv; | |
453 } | |
454 | |
455 +static void | |
456 +ssl3_CleanupPredictedPeerCertificates(sslSocket *ss) { | |
457 + unsigned int i; | |
458 + | |
459 + if (!ss->ssl3.predictedCertChain) | |
460 + return; | |
461 + | |
462 + for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { | |
463 + CERT_DestroyCertificate(ss->ssl3.predictedCertChain[i]); | |
464 + } | |
465 + | |
466 + PORT_Free(ss->ssl3.predictedCertChain); | |
467 + ss->ssl3.predictedCertChain = NULL; | |
468 +} | |
469 + | |
470 /* Called from ssl_DestroySocketContents() in sslsock.c */ | |
471 void | |
472 ssl3_DestroySSL3Info(sslSocket *ss) | |
473 @@ -9666,6 +9780,9 @@ ssl3_DestroySSL3Info(sslSocket *ss) | |
474 ss->ssl3.clientCertChain = NULL; | |
475 } | |
476 | |
477 + if (ss->ssl3.predictedCertChain != NULL) | |
478 + ssl3_CleanupPredictedPeerCertificates(ss); | |
479 + | |
480 /* clean up handshake */ | |
481 if (ss->opt.bypassPKCS11) { | |
482 SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE); | |
483 diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/s
sl/ssl3ext.c | |
484 index 4e3d9cc..17898fb 100644 | |
485 --- a/mozilla/security/nss/lib/ssl/ssl3ext.c | |
486 +++ b/mozilla/security/nss/lib/ssl/ssl3ext.c | |
487 @@ -236,6 +236,7 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[]
= { | |
488 { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn }, | |
489 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, | |
490 { ssl_next_proto_neg_xtn, &ssl3_ServerHandleNextProtoNegoXtn }, | |
491 + { ssl_cached_info_xtn, &ssl3_ServerHandleCachedInfoXtn }, | |
492 { -1, NULL } | |
493 }; | |
494 | |
495 @@ -247,6 +248,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTL
S[] = { | |
496 { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, | |
497 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, | |
498 { ssl_next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, | |
499 + { ssl_cached_info_xtn, &ssl3_ClientHandleCachedInfoXtn }, | |
500 { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, | |
501 { -1, NULL } | |
502 }; | |
503 @@ -272,6 +274,7 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTEN
SIONS] = { | |
504 #endif | |
505 { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, | |
506 { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn }, | |
507 + { ssl_cached_info_xtn, &ssl3_ClientSendCachedInfoXtn }, | |
508 { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn } | |
509 /* any extra entries will appear as { 0, NULL } */ | |
510 }; | |
511 @@ -676,6 +679,261 @@ ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16
ex_type, | |
512 return SECSuccess; | |
513 } | |
514 | |
515 +/* ssl3_ClientSendCachedInfoXtn builds the cached_info extension on the | |
516 + * client side. */ | |
517 +PRInt32 | |
518 +ssl3_ClientSendCachedInfoXtn(sslSocket * ss, PRBool append, | |
519 + PRUint32 maxBytes) | |
520 +{ | |
521 + PRInt32 extension_length; | |
522 + PRBool send_empty; | |
523 + CERTCertificate ** predictedCertChain; | |
524 + | |
525 + if (!ss->opt.enableCachedInfo) | |
526 + return 0; | |
527 + | |
528 + predictedCertChain = ss->ssl3.predictedCertChain; | |
529 + send_empty = (predictedCertChain == NULL); | |
530 + | |
531 + /* minimum extension: | |
532 + * extension_type (2-bytes) + | |
533 + * length(extension_data) (2-bytes) + | |
534 + * length(cached_info) (2-bytes) + | |
535 + */ | |
536 + extension_length = send_empty ? 6 : 16; | |
537 + | |
538 + if (append && maxBytes >= extension_length) { | |
539 + SECStatus rv; | |
540 + | |
541 + /* ExtensionType */ | |
542 + rv = ssl3_AppendHandshakeNumber(ss, ssl_cached_info_xtn, 2); | |
543 + if (rv != SECSuccess) | |
544 + return -1; | |
545 + /* Extension Length */ | |
546 + rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); | |
547 + if (rv != SECSuccess) | |
548 + return -1; | |
549 + if (send_empty) { | |
550 + /* Cached Information Length */ | |
551 + rv = ssl3_AppendHandshakeNumber(ss, 0, 2); | |
552 + if (rv != SECSuccess) | |
553 + return -1; | |
554 + } else { | |
555 + PRUint64 certChainHash; | |
556 + int i; | |
557 + PRUint8* digestPtr = (PRUint8*) &certChainHash; | |
558 + | |
559 + /* Cached Information Length */ | |
560 + rv = ssl3_AppendHandshakeNumber(ss, 10, 2); | |
561 + if (rv != SECSuccess) | |
562 + return -1; | |
563 + /* Cached Information Type */ | |
564 + rv = ssl3_AppendHandshakeNumber(ss, 1 /* certificate_chain */, 1); | |
565 + if (rv != SECSuccess) | |
566 + return -1; | |
567 + /* hash length */ | |
568 + rv = ssl3_AppendHandshakeNumber(ss, 8, 1); | |
569 + if (rv != SECSuccess) | |
570 + return -1; | |
571 + /* hash */ | |
572 + FNV1A64_Init(&certChainHash); | |
573 + for (i = 0; predictedCertChain[i] != NULL; i++) { | |
574 + unsigned int certLen = predictedCertChain[i]->derCert.len; | |
575 + unsigned char certLenArray[3] = { | |
576 + certLen >> 16, | |
577 + certLen >> 8, | |
578 + certLen | |
579 + }; | |
580 + FNV1A64_Update(&certChainHash, certLenArray, 3); | |
581 + FNV1A64_Update(&certChainHash, | |
582 + predictedCertChain[i]->derCert.data, certLen); | |
583 + } | |
584 + FNV1A64_Final(&certChainHash); | |
585 + rv = ssl3_AppendHandshake(ss, &certChainHash, 8); | |
586 + if (rv != SECSuccess) | |
587 + return -1; | |
588 + for (i = 0; i < 8; i++) { | |
589 + ss->ssl3.certChainDigest[i] = digestPtr[i]; | |
590 + } | |
591 + } | |
592 + | |
593 + } else if (maxBytes < extension_length) { | |
594 + PORT_Assert(0); | |
595 + return 0; | |
596 + } | |
597 + ss->xtnData.advertised[ss->xtnData.numAdvertised++] = | |
598 + ssl_cached_info_xtn; | |
599 + return extension_length; | |
600 +} | |
601 + | |
602 +SECStatus | |
603 +ssl3_ServerHandleCachedInfoXtn(sslSocket *ss, PRUint16 ex_type, | |
604 + SECItem *data) | |
605 +{ | |
606 + SECStatus rv; | |
607 + unsigned char *cached_info = data->data; | |
608 + unsigned int remaining_len; | |
609 + | |
610 + /* Ignore the extension if it isn't enabled. */ | |
611 + if (!ss->opt.enableCachedInfo) | |
612 + return SECSuccess; | |
613 + | |
614 + if (data->len < 2) | |
615 + return SECFailure; | |
616 + remaining_len = (cached_info[0] << 8) | cached_info[1]; | |
617 + if (remaining_len > 2048 || remaining_len != data->len - 2) | |
618 + return SECFailure; | |
619 + cached_info += 2; | |
620 + | |
621 + /* Handle reconnaissance case. */ | |
622 + if (remaining_len == 0) { | |
623 + /* The client supports information caching, but provides no information | |
624 + * about what information types it supports */ | |
625 + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; | |
626 + rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type, | |
627 + ssl3_ServerSendCachedInfoXtn); | |
628 + return rv; | |
629 + } | |
630 + | |
631 + /* Iterate over the CachedObjects and pick the first item of type | |
632 + * certificate_chain, while ignoring everything else. */ | |
633 + while (remaining_len >= 2) { | |
634 + unsigned char cached_object_type = *cached_info++; | |
635 + unsigned int cached_object_length = *cached_info++; | |
636 + remaining_len -= 2; | |
637 + if (remaining_len < cached_object_length) | |
638 + return SECFailure; | |
639 + if (cached_object_length != 8) /* The digest must be present. */ | |
640 + return SECFailure; | |
641 + if (cached_object_type == cached_info_certificate_chain && | |
642 + !ss->ssl3.cachedInfoCertChainDigestReceived) { | |
643 + ss->ssl3.cachedInfoCertChainDigestReceived = PR_TRUE; | |
644 + memcpy(ss->ssl3.certChainDigest, cached_info, 8); | |
645 + } | |
646 + remaining_len -= cached_object_length; | |
647 + cached_info += cached_object_length; | |
648 + } | |
649 + | |
650 + if (remaining_len != 0) | |
651 + return SECFailure; | |
652 + | |
653 + if (ss->ssl3.cachedInfoCertChainDigestReceived) { | |
654 + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; | |
655 + rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type, | |
656 + ssl3_ServerSendCachedInfoXtn); | |
657 + return SECSuccess; | |
658 + } | |
659 + | |
660 + return SECSuccess; | |
661 +} | |
662 + | |
663 +/* ssl3_ServerSendCachedInfoXtn builds the cached_info extension on the | |
664 + * server side. */ | |
665 +PRInt32 | |
666 +ssl3_ServerSendCachedInfoXtn(sslSocket * ss, PRBool append, | |
667 + PRUint32 maxBytes) | |
668 +{ | |
669 + PRInt32 extension_length = 2 /* extension type */ + | |
670 + 2 /* extension length */ + | |
671 + 2 /* cached_info length */ + | |
672 + 1 /* CachedInformationType */ + | |
673 + 1 /* hash value length (0) */; | |
674 + SECStatus rv; | |
675 + | |
676 + PORT_Assert(ss->opt.enableCachedInfo); | |
677 + | |
678 + if (append && maxBytes >= extension_length) { | |
679 + /* ExtensionType */ | |
680 + rv = ssl3_AppendHandshakeNumber(ss, ssl_cached_info_xtn, 2); | |
681 + if (rv != SECSuccess) | |
682 + return -1; | |
683 + /* Extension Length */ | |
684 + rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); | |
685 + if (rv != SECSuccess) | |
686 + return -1; | |
687 + /* Cached Information Length */ | |
688 + rv = ssl3_AppendHandshakeNumber(ss, 2, 2); | |
689 + if (rv != SECSuccess) | |
690 + return -1; | |
691 + /* Cached Information Type */ | |
692 + rv = ssl3_AppendHandshakeNumber(ss, 1 /* certificate_chain */, 1); | |
693 + if (rv != SECSuccess) | |
694 + return -1; | |
695 + /* hash length */ | |
696 + rv = ssl3_AppendHandshakeNumber(ss, 0, 1); | |
697 + if (rv != SECSuccess) | |
698 + return -1; | |
699 + } else if (maxBytes < extension_length) { | |
700 + PORT_Assert(0); | |
701 + return 0; | |
702 + } | |
703 + | |
704 + return extension_length; | |
705 +} | |
706 + | |
707 +SECStatus | |
708 +ssl3_ClientHandleCachedInfoXtn(sslSocket *ss, PRUint16 ex_type, | |
709 + SECItem *data) | |
710 +{ | |
711 + unsigned char * cached_info = data->data; | |
712 + unsigned int remaining_cached_info_length; | |
713 + PRBool has_correct_cert_chain = PR_FALSE; | |
714 + | |
715 + /* If we didn't request this extension, then the server may not echo it. */ | |
716 + if (!ss->opt.enableCachedInfo) | |
717 + return SECFailure; | |
718 + | |
719 + if (data->len == 0) { | |
720 + /* The server supports information caching, but provides no information | |
721 + * about what information types it supports */ | |
722 + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; | |
723 + return SECSuccess; | |
724 + } | |
725 + | |
726 + if (data->len < 2) | |
727 + return SECFailure; | |
728 + remaining_cached_info_length = (cached_info[0] << 8) | cached_info[1]; | |
729 + if (remaining_cached_info_length != data->len - 2) | |
730 + return SECFailure; | |
731 + cached_info += 2; | |
732 + while (remaining_cached_info_length >= 2) { | |
733 + /* The server supports only those CachedInformationType types that are | |
734 + * identified by a present CachedObject */ | |
735 + unsigned char cached_object_type; | |
736 + unsigned int cached_object_length; | |
737 + unsigned char cached_object_digest[8]; | |
738 + cached_object_type = *cached_info++; | |
739 + cached_object_length = *cached_info++; | |
740 + remaining_cached_info_length -= 2; | |
741 + if (remaining_cached_info_length < cached_object_length) | |
742 + return SECFailure; | |
743 + if (cached_object_length != 0 && cached_object_length != 8) | |
744 + return SECFailure; | |
745 + remaining_cached_info_length -= cached_object_length; | |
746 + if (cached_object_type == cached_info_certificate_chain) { | |
747 + if (cached_object_length == 0) | |
748 + has_correct_cert_chain = PR_TRUE; | |
749 + else { /* Hashes must match */ | |
750 + int i; | |
751 + for (i = 0; i < 8; i++) | |
752 + cached_object_digest[i] = *cached_info++; | |
753 + if (!memcmp(cached_object_digest, ss->ssl3.certChainDigest, 8)) | |
754 + has_correct_cert_chain = PR_TRUE; | |
755 + } | |
756 + } | |
757 + } | |
758 + | |
759 + if (remaining_cached_info_length != 0) | |
760 + return SECFailure; | |
761 + | |
762 + if (has_correct_cert_chain) { | |
763 + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; | |
764 + return SECSuccess; | |
765 + } | |
766 + | |
767 + return SECFailure; | |
768 +} | |
769 + | |
770 /* ssl3_ClientSendStatusRequestXtn builds the status_request extension on the | |
771 * client side. See RFC 4366 section 3.6. */ | |
772 PRInt32 | |
773 diff --git a/mozilla/security/nss/lib/ssl/sslauth.c b/mozilla/security/nss/lib/s
sl/sslauth.c | |
774 index df40f30..fcd15ca 100644 | |
775 --- a/mozilla/security/nss/lib/ssl/sslauth.c | |
776 +++ b/mozilla/security/nss/lib/ssl/sslauth.c | |
777 @@ -95,6 +95,46 @@ SSL_PeerCertificateChain(PRFileDesc *fd, CERTCertificate **ce
rts, | |
778 return SECSuccess; | |
779 } | |
780 | |
781 +SECStatus | |
782 +SSL_SetPredictedPeerCertificates(PRFileDesc *fd, CERTCertificate **certs, | |
783 + unsigned int numCerts) | |
784 +{ | |
785 + sslSocket *ss; | |
786 + unsigned int i; | |
787 + | |
788 + ss = ssl_FindSocket(fd); | |
789 + if (!ss) { | |
790 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedPeerCertificates", | |
791 + SSL_GETPID(), fd)); | |
792 + return SECFailure; | |
793 + } | |
794 + | |
795 + ss->ssl3.predictedCertChain = | |
796 + PORT_NewArray(CERTCertificate*, numCerts + 1); | |
797 + if (!ss->ssl3.predictedCertChain) | |
798 + return SECFailure; /* error code was set */ | |
799 + for (i = 0; i < numCerts; i++) | |
800 + ss->ssl3.predictedCertChain[i] = CERT_DupCertificate(certs[i]); | |
801 + ss->ssl3.predictedCertChain[numCerts] = NULL; | |
802 + | |
803 + return SECSuccess; | |
804 +} | |
805 + | |
806 +PRBool | |
807 +SSL_CertChainDigestReceived(PRFileDesc *fd) | |
808 +{ | |
809 + sslSocket *ss; | |
810 + | |
811 + ss = ssl_FindSocket(fd); | |
812 + if (!ss) { | |
813 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_CertChainDigestReceived", | |
814 + SSL_GETPID(), fd)); | |
815 + return SECFailure; | |
816 + } | |
817 + | |
818 + return ss->ssl3.cachedInfoCertChainDigestReceived; | |
819 +} | |
820 + | |
821 /* NEED LOCKS IN HERE. */ | |
822 CERTCertificate * | |
823 SSL_LocalCertificate(PRFileDesc *fd) | |
824 diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/s
sl/sslimpl.h | |
825 index 8e2bd14..f1e9a3e 100644 | |
826 --- a/mozilla/security/nss/lib/ssl/sslimpl.h | |
827 +++ b/mozilla/security/nss/lib/ssl/sslimpl.h | |
828 @@ -340,6 +340,7 @@ typedef struct sslOptionsStr { | |
829 unsigned int requireSafeNegotiation : 1; /* 22 */ | |
830 unsigned int enableFalseStart : 1; /* 23 */ | |
831 unsigned int enableOCSPStapling : 1; /* 24 */ | |
832 + unsigned int enableCachedInfo : 1; /* 25 */ | |
833 } sslOptions; | |
834 | |
835 typedef enum { sslHandshakingUndetermined = 0, | |
836 @@ -754,6 +755,11 @@ struct TLSExtensionDataStr { | |
837 PRUint32 sniNameArrSize; | |
838 }; | |
839 | |
840 +typedef enum { | |
841 + cached_info_certificate_chain = 1, | |
842 + cached_info_trusted_cas = 2 | |
843 +} TLSCachedInfoType; | |
844 + | |
845 /* | |
846 ** This is the "hs" member of the "ssl3" struct. | |
847 ** This entire struct is protected by ssl3HandshakeLock | |
848 @@ -832,6 +838,14 @@ struct ssl3StateStr { | |
849 CERTCertificateList *clientCertChain; /* used by client */ | |
850 PRBool sendEmptyCert; /* used by client */ | |
851 | |
852 + /* TLS Cached Info Extension */ | |
853 + CERTCertificate ** predictedCertChain; | |
854 + /* An array terminated with a NULL. */ | |
855 + PRUint8 certChainDigest[8]; | |
856 + /* Used in cached info extension. Stored in network | |
857 + * byte order. */ | |
858 + PRBool cachedInfoCertChainDigestReceived; | |
859 + | |
860 int policy; | |
861 /* This says what cipher suites we can do, and should | |
862 * be either SSL_ALLOWED or SSL_RESTRICTED | |
863 @@ -839,7 +853,10 @@ struct ssl3StateStr { | |
864 PRArenaPool * peerCertArena; | |
865 /* These are used to keep track of the peer CA */ | |
866 void * peerCertChain; | |
867 - /* chain while we are trying to validate it. */ | |
868 + /* Chain while we are trying to validate it. This | |
869 + * does not include the leaf cert. It is actually a | |
870 + * linked list of ssl3CertNode structs. | |
871 + */ | |
872 CERTDistNames * ca_list; | |
873 /* used by server. trusted CAs for this socket. */ | |
874 PRBool initialized; | |
875 @@ -1524,6 +1541,10 @@ extern SECStatus ssl3_ClientHandleSessionTicketXtn(sslSoc
ket *ss, | |
876 PRUint16 ex_type, SECItem *data); | |
877 extern SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, | |
878 PRUint16 ex_type, SECItem *data); | |
879 +extern SECStatus ssl3_ServerHandleCachedInfoXtn(sslSocket *ss, | |
880 + PRUint16 ex_type, SECItem *data); | |
881 +extern SECStatus ssl3_ClientHandleCachedInfoXtn(sslSocket *ss, | |
882 + PRUint16 ex_type, SECItem *data); | |
883 extern SECStatus ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, | |
884 PRUint16 ex_type, SECItem *data); | |
885 extern SECStatus ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, | |
886 @@ -1545,6 +1566,10 @@ extern PRInt32 ssl3_ClientSendStatusRequestXtn(sslSocket
*ss, PRBool append, | |
887 */ | |
888 extern PRInt32 ssl3_SendServerNameXtn(sslSocket *ss, PRBool append, | |
889 PRUint32 maxBytes); | |
890 +extern PRInt32 ssl3_ClientSendCachedInfoXtn(sslSocket *ss, PRBool append, | |
891 + PRUint32 maxBytes); | |
892 +extern PRInt32 ssl3_ServerSendCachedInfoXtn(sslSocket *ss, PRBool append, | |
893 + PRUint32 maxBytes); | |
894 | |
895 /* Assigns new cert, cert chain and keys to ss->serverCerts | |
896 * struct. If certChain is NULL, tries to find one. Aborts if | |
897 @@ -1648,6 +1673,12 @@ SECStatus SSL_DisableDefaultExportCipherSuites(void); | |
898 SECStatus SSL_DisableExportCipherSuites(PRFileDesc * fd); | |
899 PRBool SSL_IsExportCipherSuite(PRUint16 cipherSuite); | |
900 | |
901 +/********************** FNV hash *********************/ | |
902 + | |
903 +void FNV1A64_Init(PRUint64 *digest); | |
904 +void FNV1A64_Update(PRUint64 *digest, const unsigned char *data, | |
905 + unsigned int length); | |
906 +void FNV1A64_Final(PRUint64 *digest); | |
907 | |
908 #ifdef TRACE | |
909 #define SSL_TRACE(msg) ssl_Trace msg | |
910 diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/s
sl/sslsock.c | |
911 index 4c4df3f..3d89d86 100644 | |
912 --- a/mozilla/security/nss/lib/ssl/sslsock.c | |
913 +++ b/mozilla/security/nss/lib/ssl/sslsock.c | |
914 @@ -186,6 +186,7 @@ static sslOptions ssl_defaults = { | |
915 PR_FALSE, /* requireSafeNegotiation */ | |
916 PR_FALSE, /* enableFalseStart */ | |
917 PR_FALSE, /* enableOCSPStapling */ | |
918 + PR_FALSE, /* enableCachedInfo */ | |
919 }; | |
920 | |
921 sslSessionIDLookupFunc ssl_sid_lookup; | |
922 @@ -743,6 +744,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) | |
923 ss->opt.enableOCSPStapling = on; | |
924 break; | |
925 | |
926 + case SSL_ENABLE_CACHED_INFO: | |
927 + ss->opt.enableCachedInfo = on; | |
928 + break; | |
929 + | |
930 default: | |
931 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
932 rv = SECFailure; | |
933 @@ -808,6 +813,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) | |
934 on = ss->opt.requireSafeNegotiation; break; | |
935 case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break; | |
936 case SSL_ENABLE_OCSP_STAPLING: on = ss->opt.enableOCSPStapling; break; | |
937 + case SSL_ENABLE_CACHED_INFO: on = ss->opt.enableCachedInfo; break; | |
938 | |
939 default: | |
940 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
941 @@ -862,6 +868,7 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn) | |
942 case SSL_ENABLE_OCSP_STAPLING: | |
943 on = ssl_defaults.enableOCSPStapling; | |
944 break; | |
945 + case SSL_ENABLE_CACHED_INFO: on = ssl_defaults.enableCachedInfo; break; | |
946 | |
947 default: | |
948 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
949 @@ -1013,6 +1020,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) | |
950 ssl_defaults.enableOCSPStapling = on; | |
951 break; | |
952 | |
953 + case SSL_ENABLE_CACHED_INFO: | |
954 + ssl_defaults.enableCachedInfo = on; | |
955 + break; | |
956 + | |
957 default: | |
958 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
959 return SECFailure; | |
960 diff --git a/mozilla/security/nss/lib/ssl/sslt.h b/mozilla/security/nss/lib/ssl/
sslt.h | |
961 index 917c093..bca7496 100644 | |
962 --- a/mozilla/security/nss/lib/ssl/sslt.h | |
963 +++ b/mozilla/security/nss/lib/ssl/sslt.h | |
964 @@ -205,9 +205,10 @@ typedef enum { | |
965 #endif | |
966 ssl_session_ticket_xtn = 35, | |
967 ssl_next_proto_neg_xtn = 13172, | |
968 + ssl_cached_info_xtn = 13173, | |
969 ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ | |
970 } SSLExtensionType; | |
971 | |
972 -#define SSL_MAX_EXTENSIONS 7 | |
973 +#define SSL_MAX_EXTENSIONS 8 | |
974 | |
975 #endif /* __sslt_h_ */ | |
OLD | NEW |