diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-24 17:30:37 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-24 17:30:37 +0000 |
commit | 1141e92b442fa8fbdad6858597d38e41a17beee9 (patch) | |
tree | dd1807659d37379e25236424e684bb211106b05e /net | |
parent | 81cc5aa7ab33668800d01059ed74eb41e1712f8b (diff) | |
download | chromium_src-1141e92b442fa8fbdad6858597d38e41a17beee9.zip chromium_src-1141e92b442fa8fbdad6858597d38e41a17beee9.tar.gz chromium_src-1141e92b442fa8fbdad6858597d38e41a17beee9.tar.bz2 |
net: include patch for cached info and fix whitespace.
No code changes.
TBR=wtc
BUG=none
TEST=no code changes.
http://codereview.chromium.org/7236036/
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90377 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/third_party/nss/README.chromium | 3 | ||||
-rwxr-xr-x | net/third_party/nss/patches/applypatches.sh | 2 | ||||
-rw-r--r-- | net/third_party/nss/patches/cachedinfo.patch | 668 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl.h | 18 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3con.c | 117 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3ext.c | 52 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslauth.c | 14 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslimpl.h | 4 |
8 files changed, 775 insertions, 103 deletions
diff --git a/net/third_party/nss/README.chromium b/net/third_party/nss/README.chromium index 193fef0..1cca89a 100644 --- a/net/third_party/nss/README.chromium +++ b/net/third_party/nss/README.chromium @@ -43,6 +43,9 @@ Patches: patches/clientauth.patch https://bugzilla.mozilla.org/show_bug.cgi?id=616757 + * Add support for TLS cached info extension. + patches/cachedinfo.patch + Apply the patches to NSS by running the patches/applypatches.sh script. Read the comments at the top of patches/applypatches.sh for instructions. diff --git a/net/third_party/nss/patches/applypatches.sh b/net/third_party/nss/patches/applypatches.sh index b7948ed..c6609ca 100755 --- a/net/third_party/nss/patches/applypatches.sh +++ b/net/third_party/nss/patches/applypatches.sh @@ -18,3 +18,5 @@ patch -p6 < $patches_dir/peercertchain.patch patch -p6 < $patches_dir/ocspstapling.patch patch -p6 < $patches_dir/clientauth.patch + +patch -p6 < $patches_dir/cachedinfo.patch diff --git a/net/third_party/nss/patches/cachedinfo.patch b/net/third_party/nss/patches/cachedinfo.patch new file mode 100644 index 0000000..f57ad6d --- /dev/null +++ b/net/third_party/nss/patches/cachedinfo.patch @@ -0,0 +1,668 @@ +commit d4212da54db71bcf4e1232a9692cbdafa3cecb0f +Author: Adam Langley <agl@chromium.org> +Date: Fri Jun 24 13:10:38 2011 -0400 + + cachedinfo.patch + +diff --git a/mozilla/security/nss/lib/ssl/fnv1a64.c b/mozilla/security/nss/lib/ssl/fnv1a64.c +new file mode 100644 +index 0000000..c7c4b08 +--- /dev/null ++++ b/mozilla/security/nss/lib/ssl/fnv1a64.c +@@ -0,0 +1,72 @@ ++/* ++ * FNV1A64 Hash ++ * http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param ++ * ++ * ***** BEGIN LICENSE BLOCK ***** ++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * The Original Code is the Netscape security libraries. ++ * ++ * The Initial Developer of the Original Code is ++ * Netscape Communications Corporation. ++ * Portions created by the Initial Developer are Copyright (C) 1994-2000 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * Adam Langley, Google Inc. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPL"), or ++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++ * in which case the provisions of the GPL or the LGPL are applicable instead ++ * of those above. If you wish to allow use of your version of this file only ++ * under the terms of either the GPL or the LGPL, and not to allow others to ++ * use your version of this file under the terms of the MPL, indicate your ++ * decision by deleting the provisions above and replace them with the notice ++ * and other provisions required by the GPL or the LGPL. If you do not delete ++ * the provisions above, a recipient may use your version of this file under ++ * the terms of any one of the MPL, the GPL or the LGPL. ++ * ++ * ***** END LICENSE BLOCK ***** */ ++ ++/* $Id: fnv1a64.c,v 1.0 2010/08/09 13:00:00 agl%google.com Exp $ */ ++ ++#include "prtypes.h" ++#include "prnetdb.h" ++ ++/* Older versions of Visual C++ don't support the 'ull' suffix. */ ++#ifdef _MSC_VER ++static const PRUint64 FNV1A64_OFFSET_BASIS = 14695981039346656037ui64; ++static const PRUint64 FNV1A64_PRIME = 1099511628211ui64; ++#else ++static const PRUint64 FNV1A64_OFFSET_BASIS = 14695981039346656037ull; ++static const PRUint64 FNV1A64_PRIME = 1099511628211ull; ++#endif ++ ++void FNV1A64_Init(PRUint64* digest) { ++ *digest = FNV1A64_OFFSET_BASIS; ++} ++ ++void FNV1A64_Update(PRUint64* digest, const unsigned char *data, ++ unsigned int length) { ++ unsigned int i; ++ ++ for (i = 0; i < length; i++) { ++ *digest ^= data[i]; ++ *digest *= FNV1A64_PRIME; ++ } ++} ++ ++void FNV1A64_Final(PRUint64 *digest) { ++ *digest = PR_htonll(*digest); ++} +diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/ssl.h +index 563cfd5..7357d9f 100644 +--- a/mozilla/security/nss/lib/ssl/ssl.h ++++ b/mozilla/security/nss/lib/ssl/ssl.h +@@ -140,6 +140,8 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd); + /* bits. The advantage of False Start is that it saves a round trip for */ + /* client-speaks-first protocols when performing a full handshake. */ + #define SSL_ENABLE_OCSP_STAPLING 23 /* Request OCSP stapling (client) */ ++#define SSL_ENABLE_CACHED_INFO 24 /* Enable TLS cached information */ ++ /* extension, off by default. */ + + #ifdef SSL_DEPRECATED_FUNCTION + /* Old deprecated function names */ +@@ -438,6 +440,17 @@ SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f, + void *arg); + + /* ++ ** Set the predicted chain of certificates for the peer. This is used for the ++ ** TLS Cached Info extension. Note that the SSL_ENABLE_CACHED_INFO option must ++ ** be set for this to occur. ++ ** ++ ** This function takes a reference to each of the given certificates. ++ */ ++ SSL_IMPORT SECStatus SSL_SetPredictedPeerCertificates( ++ PRFileDesc *fd, CERTCertificate **certs, ++ unsigned int numCerts); ++ ++/* + ** Configure SSL socket for running a secure server. Needs the + ** certificate for the server and the servers private key. The arguments + ** are copied. +diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c +index 0997e18..2cc1e05 100644 +--- a/mozilla/security/nss/lib/ssl/ssl3con.c ++++ b/mozilla/security/nss/lib/ssl/ssl3con.c +@@ -5170,7 +5170,6 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) + ssl3_CopyPeerCertsFromSID(ss, sid); + } + +- + /* NULL value for PMS signifies re-use of the old MS */ + rv = ssl3_InitPendingCipherSpec(ss, NULL); + if (rv != SECSuccess) { +@@ -7958,7 +7957,6 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) + PRInt32 size; + SECStatus rv; + PRBool isServer = (PRBool)(!!ss->sec.isServer); +- PRBool trusted = PR_FALSE; + PRBool isTLS; + SSL3AlertDescription desc = bad_certificate; + int errCode = SSL_ERROR_RX_MALFORMED_CERTIFICATE; +@@ -8018,35 +8016,46 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) + goto loser; /* don't send alerts on memory errors */ + } + +- /* First get the peer cert. */ +- remaining -= 3; +- if (remaining < 0) +- goto decode_loser; ++ if (length == 12 && ssl3_ExtensionNegotiated(ss, ssl_cached_info_xtn)) { ++ /* We are dealing with a certificate_chain digest */ ++ int i; + +- size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); +- if (size <= 0) +- goto loser; /* fatal alert already sent by ConsumeHandshake. */ ++ ss->ssl3.digestReceived = PR_TRUE; + +- if (remaining < size) +- goto decode_loser; ++ /* Make sure the digests match. */ ++ if (memcmp(b + 4, ss->ssl3.certChainDigest, 8)) { ++ desc = handshake_failure; ++ goto alert_loser; ++ } + +- certItem.data = b; +- certItem.len = size; +- b += size; +- length -= size; +- remaining -= size; ++ /* First get the peer cert. */ ++ if (ss->ssl3.predictedCertChain[0] == NULL) { ++ desc = handshake_failure; ++ goto alert_loser; ++ } ++ ss->sec.peerCert = CERT_DupCertificate(ss->ssl3.predictedCertChain[0]); + +- ss->sec.peerCert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, +- PR_FALSE, PR_TRUE); +- if (ss->sec.peerCert == NULL) { +- /* We should report an alert if the cert was bad, but not if the +- * problem was just some local problem, like memory error. +- */ +- goto ambiguous_err; +- } ++ /* Now get all of the CA certs. */ ++ ss->ssl3.peerCertChain = NULL; ++ for (i = 1; ss->ssl3.predictedCertChain[i] != NULL; i++) { ++ c = PORT_ArenaNew(arena, ssl3CertNode); ++ if (c == NULL) { ++ goto loser; /* don't send alerts on memory errors */ ++ } ++ c->cert = CERT_DupCertificate(ss->ssl3.predictedCertChain[i]); ++ c->next = NULL; ++ if (lastCert) { ++ lastCert->next = c; ++ } else { ++ ss->ssl3.peerCertChain = c; ++ } ++ lastCert = c; ++ } ++ } else { ++ /* We are dealing with a regular certificate message */ ++ ss->ssl3.digestReceived = PR_FALSE; + +- /* Now get all of the CA certs. */ +- while (remaining > 0) { ++ /* First get the peer cert. */ + remaining -= 3; + if (remaining < 0) + goto decode_loser; +@@ -8060,35 +8069,61 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) + + certItem.data = b; + certItem.len = size; +- b += size; ++ b += size; + length -= size; + remaining -= size; + +- c = PORT_ArenaNew(arena, ssl3CertNode); +- if (c == NULL) { +- goto loser; /* don't send alerts on memory errors */ +- } +- +- c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, +- PR_FALSE, PR_TRUE); +- if (c->cert == NULL) { ++ ss->sec.peerCert = CERT_NewTempCertificate(ss->dbHandle, &certItem, ++ NULL, PR_FALSE, PR_TRUE); ++ if (ss->sec.peerCert == NULL) { ++ /* We should report an alert if the cert was bad, but not if the ++ * problem was just some local problem, like memory error. ++ */ + goto ambiguous_err; + } + +- if (c->cert->trust) +- trusted = PR_TRUE; ++ /* Now get all of the CA certs. */ ++ while (remaining > 0) { ++ remaining -= 3; ++ if (remaining < 0) ++ goto decode_loser; + +- c->next = NULL; +- if (lastCert) { +- lastCert->next = c; +- } else { +- certs = c; ++ size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); ++ if (size <= 0) ++ goto loser; /* fatal alert already sent by ConsumeHandshake. */ ++ ++ if (remaining < size) ++ goto decode_loser; ++ ++ certItem.data = b; ++ certItem.len = size; ++ b += size; ++ length -= size; ++ remaining -= size; ++ ++ c = PORT_ArenaNew(arena, ssl3CertNode); ++ if (c == NULL) { ++ goto loser; /* don't send alerts on memory errors */ ++ } ++ ++ c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, ++ PR_FALSE, PR_TRUE); ++ if (c->cert == NULL) { ++ goto ambiguous_err; ++ } ++ ++ c->next = NULL; ++ if (lastCert) { ++ lastCert->next = c; ++ } else { ++ certs = c; ++ } ++ lastCert = c; + } +- lastCert = c; +- } + +- if (remaining != 0) +- goto decode_loser; ++ if (remaining != 0) ++ goto decode_loser; ++ } + + SECKEY_UpdateCertPQG(ss->sec.peerCert); + +@@ -8250,7 +8285,10 @@ alert_loser: + (void)SSL3_SendAlert(ss, alert_fatal, desc); + + loser: +- ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL; ++ if (ss->ssl3.peerCertChain == NULL) { ++ ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL; ++ } ++ PORT_Assert(certs == NULL); + ssl3_CleanupPeerCerts(ss); + + if (ss->sec.peerCert != NULL) { +@@ -9736,6 +9774,21 @@ ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache) + return rv; + } + ++static void ++ssl3_CleanupPredictedPeerCertificates(sslSocket *ss) { ++ unsigned int i; ++ ++ if (!ss->ssl3.predictedCertChain) ++ return; ++ ++ for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { ++ CERT_DestroyCertificate(ss->ssl3.predictedCertChain[i]); ++ } ++ ++ PORT_Free(ss->ssl3.predictedCertChain); ++ ss->ssl3.predictedCertChain = NULL; ++} ++ + /* Called from ssl_DestroySocketContents() in sslsock.c */ + void + ssl3_DestroySSL3Info(sslSocket *ss) +@@ -9759,6 +9812,9 @@ ssl3_DestroySSL3Info(sslSocket *ss) + ss->ssl3.clientCertChain = NULL; + } + ++ if (ss->ssl3.predictedCertChain != NULL) ++ ssl3_CleanupPredictedPeerCertificates(ss); ++ + /* clean up handshake */ + if (ss->opt.bypassPKCS11) { + SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE); +diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/ssl/ssl3ext.c +index 94dab58..b68d2fd 100644 +--- a/mozilla/security/nss/lib/ssl/ssl3ext.c ++++ b/mozilla/security/nss/lib/ssl/ssl3ext.c +@@ -247,6 +247,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = { + { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, + { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, + { ssl_next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, ++ { ssl_cached_info_xtn, &ssl3_ClientHandleCachedInfoXtn }, + { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, + { -1, NULL } + }; +@@ -272,6 +273,7 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { + #endif + { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, + { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn }, ++ { ssl_cached_info_xtn, &ssl3_ClientSendCachedInfoXtn }, + { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn } + /* any extra entries will appear as { 0, NULL } */ + }; +@@ -676,6 +678,156 @@ ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type, + return SECSuccess; + } + ++/* ssl3_ClientSendCachedInfoXtn builds the cached_info extension on the ++ * client side. */ ++PRInt32 ++ssl3_ClientSendCachedInfoXtn(sslSocket * ss, PRBool append, ++ PRUint32 maxBytes) ++{ ++ PRInt32 extension_length; ++ PRBool send_empty; ++ CERTCertificate ** predictedCertChain; ++ ++ if (!ss->opt.enableCachedInfo) ++ return 0; ++ ++ predictedCertChain = ss->ssl3.predictedCertChain; ++ send_empty = (predictedCertChain == NULL); ++ ++ /* minimum extension: ++ * extension_type (2-bytes) + ++ * length(extension_data) (2-bytes) + ++ * length(cached_info) (2-bytes) + ++ */ ++ extension_length = send_empty ? 6 : 16; ++ ++ if (append && maxBytes >= extension_length) { ++ SECStatus rv; ++ ++ /* ExtensionType */ ++ rv = ssl3_AppendHandshakeNumber(ss, ssl_cached_info_xtn, 2); ++ if (rv != SECSuccess) ++ return -1; ++ /* Extension Length */ ++ rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); ++ if (rv != SECSuccess) ++ return -1; ++ if (send_empty) { ++ /* Cached Information Length */ ++ rv = ssl3_AppendHandshakeNumber(ss, 0, 2); ++ if (rv != SECSuccess) ++ return -1; ++ } else { ++ PRUint64 certChainHash; ++ int i; ++ PRUint8* digestPtr = (PRUint8*) &certChainHash; ++ ++ /* Cached Information Length */ ++ rv = ssl3_AppendHandshakeNumber(ss, 10, 2); ++ if (rv != SECSuccess) ++ return -1; ++ /* Cached Information Type */ ++ rv = ssl3_AppendHandshakeNumber(ss, 1 /* certificate_chain */, 1); ++ if (rv != SECSuccess) ++ return -1; ++ /* hash length */ ++ rv = ssl3_AppendHandshakeNumber(ss, 8, 1); ++ if (rv != SECSuccess) ++ return -1; ++ /* hash */ ++ FNV1A64_Init(&certChainHash); ++ for (i = 0; predictedCertChain[i] != NULL; i++) { ++ unsigned int certLen = predictedCertChain[i]->derCert.len; ++ unsigned char certLenArray[3] = { ++ (certLen & 0xff0000) >> 16, ++ (certLen & 0xff00) >> 8, ++ certLen & 0xff ++ }; ++ FNV1A64_Update(&certChainHash, certLenArray, 3); ++ FNV1A64_Update(&certChainHash, ++ predictedCertChain[i]->derCert.data, certLen); ++ } ++ FNV1A64_Final(&certChainHash); ++ rv = ssl3_AppendHandshake(ss, &certChainHash, 8); ++ if (rv != SECSuccess) ++ return -1; ++ for (i = 0; i < 8; i++) { ++ ss->ssl3.certChainDigest[i] = digestPtr[i]; ++ } ++ } ++ ++ } else if (maxBytes < extension_length) { ++ PORT_Assert(0); ++ return 0; ++ } ++ ss->xtnData.advertised[ss->xtnData.numAdvertised++] = ++ ssl_cached_info_xtn; ++ return extension_length; ++} ++ ++SECStatus ++ssl3_ClientHandleCachedInfoXtn(sslSocket *ss, PRUint16 ex_type, ++ SECItem *data) ++{ ++ unsigned char * cached_info = data->data; ++ unsigned int remaining_cached_info_length; ++ PRBool has_correct_cert_chain = PR_FALSE; ++ ++ /* If we didn't request this extension, then the server may not echo it. */ ++ if (!ss->opt.enableCachedInfo) ++ return SECFailure; ++ ++ if (data->len == 0) { ++ /* The server supports information caching, but provides no information ++ * about what information types it supports */ ++ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; ++ return SECSuccess; ++ } ++ ++ if (data->len < 2) ++ return SECFailure; ++ remaining_cached_info_length = (cached_info[0] << 8) | cached_info[1]; ++ if (remaining_cached_info_length != data->len - 2) ++ return SECFailure; ++ cached_info += 2; ++ while (remaining_cached_info_length >= 2) { ++ /* The server supports only those CachedInformationType types that are ++ * identified by a present CachedObject */ ++ unsigned char cached_object_type; ++ unsigned int cached_object_length; ++ unsigned char cached_object_digest[8]; ++ cached_object_type = *cached_info++; ++ cached_object_length = *cached_info++; ++ remaining_cached_info_length -= 2; ++ if (remaining_cached_info_length < cached_object_length) ++ return SECFailure; ++ if (cached_object_length != 0 && cached_object_length != 8) ++ return SECFailure; ++ remaining_cached_info_length -= cached_object_length; ++ if (cached_object_type == cached_info_certificate_chain) { ++ if (cached_object_length == 0) ++ has_correct_cert_chain = PR_TRUE; ++ else { /* Hashes must match */ ++ int i; ++ for (i = 0; i < 8; i++) ++ cached_object_digest[i] = *cached_info++; ++ if (!memcmp(cached_object_digest, ss->ssl3.certChainDigest, 8)) ++ has_correct_cert_chain = PR_TRUE; ++ } ++ } ++ } ++ ++ if (remaining_cached_info_length != 0) ++ return SECFailure; ++ ++ if (has_correct_cert_chain) { ++ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; ++ return SECSuccess; ++ } ++ ++ return SECFailure; ++} ++ + /* ssl3_ClientSendStatusRequestXtn builds the status_request extension on the + * client side. See RFC 4366 section 3.6. */ + PRInt32 +diff --git a/mozilla/security/nss/lib/ssl/sslauth.c b/mozilla/security/nss/lib/ssl/sslauth.c +index 447aaf8..6313603 100644 +--- a/mozilla/security/nss/lib/ssl/sslauth.c ++++ b/mozilla/security/nss/lib/ssl/sslauth.c +@@ -95,6 +95,31 @@ SSL_PeerCertificateChain(PRFileDesc *fd, CERTCertificate **certs, + return SECSuccess; + } + ++SECStatus ++SSL_SetPredictedPeerCertificates(PRFileDesc *fd, CERTCertificate **certs, ++ unsigned int numCerts) ++{ ++ sslSocket *ss; ++ unsigned int i; ++ ++ ss = ssl_FindSocket(fd); ++ if (!ss) { ++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedPeerCertificates", ++ SSL_GETPID(), fd)); ++ return SECFailure; ++ } ++ ++ ss->ssl3.predictedCertChain = ++ PORT_NewArray(CERTCertificate*, numCerts + 1); ++ if (!ss->ssl3.predictedCertChain) ++ return SECFailure; /* error code was set */ ++ for (i = 0; i < numCerts; i++) ++ ss->ssl3.predictedCertChain[i] = CERT_DupCertificate(certs[i]); ++ ss->ssl3.predictedCertChain[numCerts] = NULL; ++ ++ return SECSuccess; ++} ++ + /* NEED LOCKS IN HERE. */ + CERTCertificate * + SSL_LocalCertificate(PRFileDesc *fd) +diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/ssl/sslimpl.h +index 2e1364e..bf47dc2 100644 +--- a/mozilla/security/nss/lib/ssl/sslimpl.h ++++ b/mozilla/security/nss/lib/ssl/sslimpl.h +@@ -349,6 +349,7 @@ typedef struct sslOptionsStr { + unsigned int requireSafeNegotiation : 1; /* 22 */ + unsigned int enableFalseStart : 1; /* 23 */ + unsigned int enableOCSPStapling : 1; /* 24 */ ++ unsigned int enableCachedInfo : 1; /* 25 */ + } sslOptions; + + typedef enum { sslHandshakingUndetermined = 0, +@@ -773,6 +774,11 @@ struct TLSExtensionDataStr { + PRUint32 sniNameArrSize; + }; + ++typedef enum { ++ cached_info_certificate_chain = 1, ++ cached_info_trusted_cas = 2 ++} TLSCachedInfoType; ++ + /* + ** This is the "hs" member of the "ssl3" struct. + ** This entire struct is protected by ssl3HandshakeLock +@@ -854,6 +860,14 @@ struct ssl3StateStr { + CERTCertificateList *clientCertChain; /* used by client */ + PRBool sendEmptyCert; /* used by client */ + ++ /* TLS Cached Info Extension */ ++ CERTCertificate ** predictedCertChain; ++ /* An array terminated with a NULL. */ ++ PRUint8 certChainDigest[8]; ++ /* Used in cached info extension. Stored in network ++ * byte order. */ ++ PRBool digestReceived; ++ + int policy; + /* This says what cipher suites we can do, and should + * be either SSL_ALLOWED or SSL_RESTRICTED +@@ -1550,6 +1564,8 @@ extern SECStatus ssl3_ClientHandleSessionTicketXtn(sslSocket *ss, + PRUint16 ex_type, SECItem *data); + extern SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, + PRUint16 ex_type, SECItem *data); ++extern SECStatus ssl3_ClientHandleCachedInfoXtn(sslSocket *ss, ++ PRUint16 ex_type, SECItem *data); + extern SECStatus ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, + PRUint16 ex_type, SECItem *data); + extern SECStatus ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, +@@ -1571,6 +1587,8 @@ extern PRInt32 ssl3_ClientSendStatusRequestXtn(sslSocket *ss, PRBool append, + */ + extern PRInt32 ssl3_SendServerNameXtn(sslSocket *ss, PRBool append, + PRUint32 maxBytes); ++extern PRInt32 ssl3_ClientSendCachedInfoXtn(sslSocket *ss, PRBool append, ++ PRUint32 maxBytes); + + /* Assigns new cert, cert chain and keys to ss->serverCerts + * struct. If certChain is NULL, tries to find one. Aborts if +diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/ssl/sslsock.c +index 1bb211e..f00f8f4 100644 +--- a/mozilla/security/nss/lib/ssl/sslsock.c ++++ b/mozilla/security/nss/lib/ssl/sslsock.c +@@ -186,6 +186,7 @@ static sslOptions ssl_defaults = { + PR_FALSE, /* requireSafeNegotiation */ + PR_FALSE, /* enableFalseStart */ + PR_FALSE, /* enableOCSPStapling */ ++ PR_FALSE, /* enableCachedInfo */ + }; + + sslSessionIDLookupFunc ssl_sid_lookup; +@@ -747,6 +748,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) + ss->opt.enableOCSPStapling = on; + break; + ++ case SSL_ENABLE_CACHED_INFO: ++ ss->opt.enableCachedInfo = on; ++ break; ++ + default: + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; +@@ -812,6 +817,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) + on = ss->opt.requireSafeNegotiation; break; + case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break; + case SSL_ENABLE_OCSP_STAPLING: on = ss->opt.enableOCSPStapling; break; ++ case SSL_ENABLE_CACHED_INFO: on = ss->opt.enableCachedInfo; break; + + default: + PORT_SetError(SEC_ERROR_INVALID_ARGS); +@@ -866,6 +872,7 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn) + case SSL_ENABLE_OCSP_STAPLING: + on = ssl_defaults.enableOCSPStapling; + break; ++ case SSL_ENABLE_CACHED_INFO: on = ssl_defaults.enableCachedInfo; break; + + default: + PORT_SetError(SEC_ERROR_INVALID_ARGS); +@@ -1017,6 +1024,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) + ssl_defaults.enableOCSPStapling = on; + break; + ++ case SSL_ENABLE_CACHED_INFO: ++ ssl_defaults.enableCachedInfo = on; ++ break; ++ + default: + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; +diff --git a/mozilla/security/nss/lib/ssl/sslt.h b/mozilla/security/nss/lib/ssl/sslt.h +index 917c093..bca7496 100644 +--- a/mozilla/security/nss/lib/ssl/sslt.h ++++ b/mozilla/security/nss/lib/ssl/sslt.h +@@ -205,9 +205,10 @@ typedef enum { + #endif + ssl_session_ticket_xtn = 35, + ssl_next_proto_neg_xtn = 13172, ++ ssl_cached_info_xtn = 13173, + ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ + } SSLExtensionType; + +-#define SSL_MAX_EXTENSIONS 7 ++#define SSL_MAX_EXTENSIONS 8 + + #endif /* __sslt_h_ */ diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h index c65287b..7357d9f 100644 --- a/net/third_party/nss/ssl/ssl.h +++ b/net/third_party/nss/ssl/ssl.h @@ -439,15 +439,15 @@ typedef SECStatus (PR_CALLBACK *SSLBadCertHandler)(void *arg, PRFileDesc *fd); SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f, void *arg); -/* - ** Set the predicted chain of certificates for the peer. This is used for the - ** TLS Cached Info extension. Note that the SSL_ENABLE_CACHED_INFO option must - ** be set for this to occur. - ** - ** This function takes a reference to each of the given certificates. - */ - SSL_IMPORT SECStatus SSL_SetPredictedPeerCertificates( - PRFileDesc *fd, CERTCertificate **certs, +/* + ** Set the predicted chain of certificates for the peer. This is used for the + ** TLS Cached Info extension. Note that the SSL_ENABLE_CACHED_INFO option must + ** be set for this to occur. + ** + ** This function takes a reference to each of the given certificates. + */ + SSL_IMPORT SECStatus SSL_SetPredictedPeerCertificates( + PRFileDesc *fd, CERTCertificate **certs, unsigned int numCerts); /* diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c index 2a564ac..2cc1e05 100644 --- a/net/third_party/nss/ssl/ssl3con.c +++ b/net/third_party/nss/ssl/ssl3con.c @@ -5170,7 +5170,6 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ssl3_CopyPeerCertsFromSID(ss, sid); } - /* NULL value for PMS signifies re-use of the old MS */ rv = ssl3_InitPendingCipherSpec(ss, NULL); if (rv != SECSuccess) { @@ -8018,112 +8017,112 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } if (length == 12 && ssl3_ExtensionNegotiated(ss, ssl_cached_info_xtn)) { - /* We are dealing with a certificate_chain digest */ + /* We are dealing with a certificate_chain digest */ int i; - ss->ssl3.digestReceived = PR_TRUE; + ss->ssl3.digestReceived = PR_TRUE; /* Make sure the digests match. */ if (memcmp(b + 4, ss->ssl3.certChainDigest, 8)) { - desc = handshake_failure; - goto alert_loser; + desc = handshake_failure; + goto alert_loser; } - /* First get the peer cert. */ - if (ss->ssl3.predictedCertChain[0] == NULL) { - desc = handshake_failure; - goto alert_loser; + /* First get the peer cert. */ + if (ss->ssl3.predictedCertChain[0] == NULL) { + desc = handshake_failure; + goto alert_loser; } - ss->sec.peerCert = CERT_DupCertificate(ss->ssl3.predictedCertChain[0]); - - /* Now get all of the CA certs. */ + ss->sec.peerCert = CERT_DupCertificate(ss->ssl3.predictedCertChain[0]); + + /* Now get all of the CA certs. */ ss->ssl3.peerCertChain = NULL; for (i = 1; ss->ssl3.predictedCertChain[i] != NULL; i++) { c = PORT_ArenaNew(arena, ssl3CertNode); if (c == NULL) { - goto loser; /* don't send alerts on memory errors */ + goto loser; /* don't send alerts on memory errors */ } c->cert = CERT_DupCertificate(ss->ssl3.predictedCertChain[i]); c->next = NULL; if (lastCert) { - lastCert->next = c; + lastCert->next = c; } else { - ss->ssl3.peerCertChain = c; + ss->ssl3.peerCertChain = c; } lastCert = c; } } else { - /* We are dealing with a regular certificate message */ - ss->ssl3.digestReceived = PR_FALSE; - - /* First get the peer cert. */ - remaining -= 3; - if (remaining < 0) + /* We are dealing with a regular certificate message */ + ss->ssl3.digestReceived = PR_FALSE; + + /* First get the peer cert. */ + remaining -= 3; + if (remaining < 0) goto decode_loser; - - size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); - if (size <= 0) + + size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); + if (size <= 0) goto loser; /* fatal alert already sent by ConsumeHandshake. */ - - if (remaining < size) + + if (remaining < size) goto decode_loser; - - certItem.data = b; - certItem.len = size; - b += size; - length -= size; - remaining -= size; - - ss->sec.peerCert = CERT_NewTempCertificate(ss->dbHandle, &certItem, + + certItem.data = b; + certItem.len = size; + b += size; + length -= size; + remaining -= size; + + ss->sec.peerCert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, PR_FALSE, PR_TRUE); - if (ss->sec.peerCert == NULL) { + if (ss->sec.peerCert == NULL) { /* We should report an alert if the cert was bad, but not if the * problem was just some local problem, like memory error. */ goto ambiguous_err; - } - - /* Now get all of the CA certs. */ - while (remaining > 0) { + } + + /* Now get all of the CA certs. */ + while (remaining > 0) { remaining -= 3; if (remaining < 0) - goto decode_loser; - + goto decode_loser; + size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); if (size <= 0) - goto loser; /* fatal alert already sent by ConsumeHandshake. */ - + goto loser; /* fatal alert already sent by ConsumeHandshake. */ + if (remaining < size) - goto decode_loser; - + goto decode_loser; + certItem.data = b; certItem.len = size; b += size; length -= size; remaining -= size; - + c = PORT_ArenaNew(arena, ssl3CertNode); if (c == NULL) { - goto loser; /* don't send alerts on memory errors */ + goto loser; /* don't send alerts on memory errors */ } - + c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, PR_FALSE, PR_TRUE); if (c->cert == NULL) { - goto ambiguous_err; + goto ambiguous_err; } - + c->next = NULL; if (lastCert) { - lastCert->next = c; + lastCert->next = c; } else { - certs = c; + certs = c; } lastCert = c; - } - - if (remaining != 0) - goto decode_loser; + } + + if (remaining != 0) + goto decode_loser; } SECKEY_UpdateCertPQG(ss->sec.peerCert); @@ -8287,7 +8286,7 @@ alert_loser: loser: if (ss->ssl3.peerCertChain == NULL) { - ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL; + ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL; } PORT_Assert(certs == NULL); ssl3_CleanupPeerCerts(ss); @@ -9780,10 +9779,10 @@ ssl3_CleanupPredictedPeerCertificates(sslSocket *ss) { unsigned int i; if (!ss->ssl3.predictedCertChain) - return; + return; for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { - CERT_DestroyCertificate(ss->ssl3.predictedCertChain[i]); + CERT_DestroyCertificate(ss->ssl3.predictedCertChain[i]); } PORT_Free(ss->ssl3.predictedCertChain); diff --git a/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c index c2b364e..b68d2fd 100644 --- a/net/third_party/nss/ssl/ssl3ext.c +++ b/net/third_party/nss/ssl/ssl3ext.c @@ -693,7 +693,7 @@ ssl3_ClientSendCachedInfoXtn(sslSocket * ss, PRBool append, predictedCertChain = ss->ssl3.predictedCertChain; send_empty = (predictedCertChain == NULL); - + /* minimum extension: * extension_type (2-bytes) + * length(extension_data) (2-bytes) + @@ -720,40 +720,40 @@ ssl3_ClientSendCachedInfoXtn(sslSocket * ss, PRBool append, } else { PRUint64 certChainHash; int i; - PRUint8* digestPtr = (PRUint8*) &certChainHash; + PRUint8* digestPtr = (PRUint8*) &certChainHash; /* Cached Information Length */ rv = ssl3_AppendHandshakeNumber(ss, 10, 2); if (rv != SECSuccess) - return -1; + return -1; /* Cached Information Type */ rv = ssl3_AppendHandshakeNumber(ss, 1 /* certificate_chain */, 1); if (rv != SECSuccess) - return -1; + return -1; /* hash length */ rv = ssl3_AppendHandshakeNumber(ss, 8, 1); if (rv != SECSuccess) - return -1; + return -1; /* hash */ FNV1A64_Init(&certChainHash); for (i = 0; predictedCertChain[i] != NULL; i++) { - unsigned int certLen = predictedCertChain[i]->derCert.len; + unsigned int certLen = predictedCertChain[i]->derCert.len; unsigned char certLenArray[3] = { (certLen & 0xff0000) >> 16, (certLen & 0xff00) >> 8, certLen & 0xff }; - FNV1A64_Update(&certChainHash, certLenArray, 3); - FNV1A64_Update(&certChainHash, + FNV1A64_Update(&certChainHash, certLenArray, 3); + FNV1A64_Update(&certChainHash, predictedCertChain[i]->derCert.data, certLen); } FNV1A64_Final(&certChainHash); rv = ssl3_AppendHandshake(ss, &certChainHash, 8); if (rv != SECSuccess) - return -1; - for (i = 0; i < 8; i++) { - ss->ssl3.certChainDigest[i] = digestPtr[i]; - } + return -1; + for (i = 0; i < 8; i++) { + ss->ssl3.certChainDigest[i] = digestPtr[i]; + } } } else if (maxBytes < extension_length) { @@ -761,7 +761,7 @@ ssl3_ClientSendCachedInfoXtn(sslSocket * ss, PRBool append, return 0; } ss->xtnData.advertised[ss->xtnData.numAdvertised++] = - ssl_cached_info_xtn; + ssl_cached_info_xtn; return extension_length; } @@ -778,37 +778,37 @@ ssl3_ClientHandleCachedInfoXtn(sslSocket *ss, PRUint16 ex_type, return SECFailure; if (data->len == 0) { - /* The server supports information caching, but provides no information + /* The server supports information caching, but provides no information * about what information types it supports */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; return SECSuccess; } if (data->len < 2) - return SECFailure; + return SECFailure; remaining_cached_info_length = (cached_info[0] << 8) | cached_info[1]; if (remaining_cached_info_length != data->len - 2) - return SECFailure; + return SECFailure; cached_info += 2; while (remaining_cached_info_length >= 2) { - /* The server supports only those CachedInformationType types that are + /* The server supports only those CachedInformationType types that are * identified by a present CachedObject */ - unsigned char cached_object_type; + unsigned char cached_object_type; unsigned int cached_object_length; unsigned char cached_object_digest[8]; - cached_object_type = *cached_info++; + cached_object_type = *cached_info++; cached_object_length = *cached_info++; remaining_cached_info_length -= 2; if (remaining_cached_info_length < cached_object_length) - return SECFailure; + return SECFailure; if (cached_object_length != 0 && cached_object_length != 8) - return SECFailure; + return SECFailure; remaining_cached_info_length -= cached_object_length; if (cached_object_type == cached_info_certificate_chain) { if (cached_object_length == 0) - has_correct_cert_chain = PR_TRUE; + has_correct_cert_chain = PR_TRUE; else { /* Hashes must match */ - int i; + int i; for (i = 0; i < 8; i++) cached_object_digest[i] = *cached_info++; if (!memcmp(cached_object_digest, ss->ssl3.certChainDigest, 8)) @@ -818,10 +818,10 @@ ssl3_ClientHandleCachedInfoXtn(sslSocket *ss, PRUint16 ex_type, } if (remaining_cached_info_length != 0) - return SECFailure; + return SECFailure; if (has_correct_cert_chain) { - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; return SECSuccess; } diff --git a/net/third_party/nss/ssl/sslauth.c b/net/third_party/nss/ssl/sslauth.c index 76126ff..6313603 100644 --- a/net/third_party/nss/ssl/sslauth.c +++ b/net/third_party/nss/ssl/sslauth.c @@ -97,24 +97,24 @@ SSL_PeerCertificateChain(PRFileDesc *fd, CERTCertificate **certs, SECStatus SSL_SetPredictedPeerCertificates(PRFileDesc *fd, CERTCertificate **certs, - unsigned int numCerts) + unsigned int numCerts) { sslSocket *ss; unsigned int i; ss = ssl_FindSocket(fd); if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedPeerCertificates", - SSL_GETPID(), fd)); - return SECFailure; + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedPeerCertificates", + SSL_GETPID(), fd)); + return SECFailure; } ss->ssl3.predictedCertChain = - PORT_NewArray(CERTCertificate*, numCerts + 1); + PORT_NewArray(CERTCertificate*, numCerts + 1); if (!ss->ssl3.predictedCertChain) - return SECFailure; /* error code was set */ + return SECFailure; /* error code was set */ for (i = 0; i < numCerts; i++) - ss->ssl3.predictedCertChain[i] = CERT_DupCertificate(certs[i]); + ss->ssl3.predictedCertChain[i] = CERT_DupCertificate(certs[i]); ss->ssl3.predictedCertChain[numCerts] = NULL; return SECSuccess; diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h index 6d6cecc..bf47dc2 100644 --- a/net/third_party/nss/ssl/sslimpl.h +++ b/net/third_party/nss/ssl/sslimpl.h @@ -864,8 +864,8 @@ struct ssl3StateStr { CERTCertificate ** predictedCertChain; /* An array terminated with a NULL. */ PRUint8 certChainDigest[8]; - /* Used in cached info extension. Stored in network - * byte order. */ + /* Used in cached info extension. Stored in network + * byte order. */ PRBool digestReceived; int policy; |