summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/nss
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/third_party/nss')
-rw-r--r--chromium/net/third_party/nss/README.chromium40
-rwxr-xr-xchromium/net/third_party/nss/patches/applypatches.sh20
-rw-r--r--chromium/net/third_party/nss/patches/canfalsestart.patch960
-rw-r--r--chromium/net/third_party/nss/patches/chacha20poly1305.patch22
-rw-r--r--chromium/net/third_party/nss/patches/channelid.patch2
-rw-r--r--chromium/net/third_party/nss/patches/channelid2.patch155
-rw-r--r--chromium/net/third_party/nss/patches/cipherorder.patch106
-rw-r--r--chromium/net/third_party/nss/patches/disableticketrenewal.patch17
-rw-r--r--chromium/net/third_party/nss/patches/fallbackscsv.patch207
-rw-r--r--chromium/net/third_party/nss/patches/paddingextension.patch142
-rw-r--r--chromium/net/third_party/nss/patches/paddingextensionall.patch26
-rw-r--r--chromium/net/third_party/nss/patches/sessioncache.patch100
-rw-r--r--chromium/net/third_party/nss/patches/signedcertificatetimestamps.patch421
-rw-r--r--chromium/net/third_party/nss/patches/sslnoncestatics.patch15
-rw-r--r--chromium/net/third_party/nss/patches/tls12backuphash2.patch127
-rw-r--r--chromium/net/third_party/nss/ssl/SSLerrs.h5
-rw-r--r--chromium/net/third_party/nss/ssl/exports_win.def6
-rw-r--r--chromium/net/third_party/nss/ssl/ssl.h101
-rw-r--r--chromium/net/third_party/nss/ssl/ssl3con.c406
-rw-r--r--chromium/net/third_party/nss/ssl/ssl3ext.c136
-rw-r--r--chromium/net/third_party/nss/ssl/ssl3gthr.c61
-rw-r--r--chromium/net/third_party/nss/ssl/ssl3prot.h1
-rw-r--r--chromium/net/third_party/nss/ssl/sslerr.h1
-rw-r--r--chromium/net/third_party/nss/ssl/sslimpl.h95
-rw-r--r--chromium/net/third_party/nss/ssl/sslnonce.c32
-rw-r--r--chromium/net/third_party/nss/ssl/sslproto.h5
-rw-r--r--chromium/net/third_party/nss/ssl/sslsecur.c116
-rw-r--r--chromium/net/third_party/nss/ssl/sslsock.c69
-rw-r--r--chromium/net/third_party/nss/ssl/sslt.h6
29 files changed, 2786 insertions, 614 deletions
diff --git a/chromium/net/third_party/nss/README.chromium b/chromium/net/third_party/nss/README.chromium
index 4a0f2d3ec19..8c4e008c70c 100644
--- a/chromium/net/third_party/nss/README.chromium
+++ b/chromium/net/third_party/nss/README.chromium
@@ -57,6 +57,7 @@ Patches:
* Add support for TLS Channel IDs
patches/channelid.patch
+ patches/channelid2.patch
* Add support for extracting the tls-unique channel binding value
patches/tlsunique.patch
@@ -108,10 +109,13 @@ Patches:
libraries at run time.
patches/aesgcmchromium.patch
- * Prefer to generate SHA-1 signatures for TLS 1.2 client authentication if
- the client private key is in a CAPI service provider on Windows or if the
- client private key is a 1024-bit RSA or DSA key.
+ * Support generating SHA-1 signatures for TLS 1.2 client authentication. Use
+ SHA-1 instead of SHA-256 if the server's preferences do not allow for
+ SHA-256 or if the client private key may only support SHA-1 signatures. The
+ latter happens when the key is in a CAPI service provider on Windows or if
+ it is a 1024-bit RSA or DSA key.
patches/tls12backuphash.patch
+ patches/tls12backuphash2.patch
* Support ChaCha20+Poly1305 ciphersuites
http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-01
@@ -139,6 +143,36 @@ Patches:
https://bugzilla.mozilla.org/show_bug.cgi?id=934016
patches/nullcipher_934016.patch
+ * In the case that a ClientHello record is between 256 and 511 bytes long,
+ add an extension to make it 512 bytes. This works around a bug in F5
+ terminators.
+ patches/paddingextension.patch
+ patches/paddingextensionall.patch
+
+ * Support the Certificate Transparency (RFC 6962) TLS extension
+ signed_certificate_timestamp (client only).
+ patches/signedcertificatetimestamps.patch
+
+ * Add a function to allow the cipher suites preference order to be set.
+ patches/cipherorder.patch
+
+ * Add TLS_FALLBACK_SCSV cipher suite to version fallback connections.
+ patches/fallbackscsv.patch
+
+ * Disable session ticket renewal.
+ https://bugzilla.mozilla.org/show_bug.cgi?id=930857
+ patches/disableticketrenewal.patch
+
+ * Add explicit functions for managing the SSL/TLS session cache.
+ This is a temporary workaround until Chromium migrates to NSS's
+ asynchronous certificate verification.
+ patches/sessioncache.patch
+
+ * Remove static storage qualifier from variables in sslnonce.c. Due to
+ a clang codegen bug on Mac, this caused an infinite loop.
+ https://code.google.com/p/chromium/issues/detail?id=326011
+ patches/sslnoncestatics.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/chromium/net/third_party/nss/patches/applypatches.sh b/chromium/net/third_party/nss/patches/applypatches.sh
index 947cf5e1b57..89d97bc922f 100755
--- a/chromium/net/third_party/nss/patches/applypatches.sh
+++ b/chromium/net/third_party/nss/patches/applypatches.sh
@@ -65,3 +65,23 @@ patch -p4 < $patches_dir/peercertchain2.patch
patch -p4 < $patches_dir/canfalsestart.patch
patch -p4 < $patches_dir/nullcipher_934016.patch
+
+patch -p4 < $patches_dir/paddingextension.patch
+
+patch -p4 < $patches_dir/paddingextensionall.patch
+
+patch -p4 < $patches_dir/channelid2.patch
+
+patch -p5 < $patches_dir/signedcertificatetimestamps.patch
+
+patch -p4 < $patches_dir/cipherorder.patch
+
+patch -p5 < $patches_dir/tls12backuphash2.patch
+
+patch -p4 < $patches_dir/fallbackscsv.patch
+
+patch -p4 < $patches_dir/disableticketrenewal.patch
+
+patch -p4 < $patches_dir/sessioncache.patch
+
+patch -p4 < $patches_dir/sslnoncestatics.patch
diff --git a/chromium/net/third_party/nss/patches/canfalsestart.patch b/chromium/net/third_party/nss/patches/canfalsestart.patch
index d2a9752c070..a3fb1813d21 100644
--- a/chromium/net/third_party/nss/patches/canfalsestart.patch
+++ b/chromium/net/third_party/nss/patches/canfalsestart.patch
@@ -1,8 +1,8 @@
Index: net/third_party/nss/ssl/ssl.h
===================================================================
---- net/third_party/nss/ssl/ssl.h (revision 227363)
+--- net/third_party/nss/ssl/ssl.h (revision 227672)
+++ net/third_party/nss/ssl/ssl.h (working copy)
-@@ -121,14 +121,22 @@
+@@ -121,14 +121,17 @@
#define SSL_ENABLE_FALSE_START 22 /* Enable SSL false start (off by */
/* default, applies only to */
/* clients). False start is a */
@@ -22,62 +22,42 @@ Index: net/third_party/nss/ssl/ssl.h
+ * it saves a round trip for client-speaks-first protocols when performing a
+ * full handshake.
+ *
-+ * See SSL_DefaultCanFalseStart for the default criteria that NSS uses to
-+ * determine whether to false start or not. See SSL_SetCanFalseStartCallback
-+ * for how to change that criteria. In addition to those criteria, false start
-+ * will only be done when the server selects a cipher suite with an effective
-+ * key length of 80 bits or more (including RC4-128). Also, see
-+ * SSL_HandshakeCallback for a description on how false start affects when the
-+ * handshake callback gets called.
++ * In addition to enabling this option, the application must register a
++ * callback using the SSL_SetCanFalseStartCallback function.
+ */
/* For SSL 3.0 and TLS 1.0, by default we prevent chosen plaintext attacks
* on SSL CBC mode cipher suites (see RFC 4346 Section F.3) by splitting
-@@ -741,14 +749,59 @@
+@@ -741,14 +744,45 @@
SSL_IMPORT SECStatus SSL_InheritMPServerSIDCache(const char * envString);
/*
-** Set the callback on a particular socket that gets called when we finish
-** performing a handshake.
-+** Set the callback that normally gets called when the TLS handshake
-+** is complete. If false start is not enabled, then the handshake callback is
-+** called after verifying the peer's Finished message and before sending
-+** outgoing application data and before processing incoming application data.
++** Set the callback that gets called when a TLS handshake is complete. The
++** handshake callback is called after verifying the peer's Finished message and
++** before processing incoming application data.
+**
-+** If false start is enabled and there is a custom CanFalseStartCallback
-+** callback set, then the handshake callback gets called after the peer's
-+** Finished message has been verified, which may be after application data is
-+** sent.
-+**
-+** If false start is enabled and there is not a custom CanFalseStartCallback
-+** callback established with SSL_SetCanFalseStartCallback then the handshake
-+** callback gets called before any application data is sent, which may be
-+** before the peer's Finished message has been verified.
++** For the initial handshake: If the handshake false started (see
++** SSL_ENABLE_FALSE_START), then application data may already have been sent
++** before the handshake callback is called. If we did not false start then the
++** callback will get called before any application data is sent.
*/
typedef void (PR_CALLBACK *SSLHandshakeCallback)(PRFileDesc *fd,
void *client_data);
SSL_IMPORT SECStatus SSL_HandshakeCallback(PRFileDesc *fd,
SSLHandshakeCallback cb, void *client_data);
-+/* Applications that wish to customize TLS false start should set this callback
++/* Applications that wish to enable TLS false start must set this callback
+** function. NSS will invoke the functon to determine if a particular
+** connection should use false start or not. SECSuccess indicates that the
+** callback completed successfully, and if so *canFalseStart indicates if false
+** start can be used. If the callback does not return SECSuccess then the
-+** handshake will be canceled.
-+**
-+** Applications that do not set the callback will use an internal set of
-+** criteria to determine if the connection should false start. If
-+** the callback is set false start will never be used without invoking the
-+** callback function, but some connections (e.g. resumed connections) will
-+** never use false start and therefore will not invoke the callback.
-+**
-+** NSS's internal criteria for this connection can be evaluated by calling
-+** SSL_DefaultCanFalseStart() from the custom callback.
++** handshake will be canceled. NSS's recommended criteria can be evaluated by
++** calling SSL_RecommendedCanFalseStart.
+**
-+** See the description of SSL_HandshakeCallback for important information on
-+** how registering a custom false start callback affects when the handshake
-+** callback gets called.
++** If no false start callback is registered then false start will never be
++** done, even if the SSL_ENABLE_FALSE_START option is enabled.
+**/
+typedef SECStatus (PR_CALLBACK *SSLCanFalseStartCallback)(
+ PRFileDesc *fd, void *arg, PRBool *canFalseStart);
@@ -85,62 +65,420 @@ Index: net/third_party/nss/ssl/ssl.h
+SSL_IMPORT SECStatus SSL_SetCanFalseStartCallback(
+ PRFileDesc *fd, SSLCanFalseStartCallback callback, void *arg);
+
-+/* A utility function that can be called from a custom CanFalseStartCallback
-+** function to determine what NSS would have done for this connection if the
-+** custom callback was not implemented.
-+**/
-+SSL_IMPORT SECStatus SSL_DefaultCanFalseStart(PRFileDesc *fd,
-+ PRBool *canFalseStart);
++/* This function sets *canFalseStart according to the recommended criteria for
++** false start. These criteria may change from release to release and may depend
++** on which handshake features have been negotiated and/or properties of the
++** certifciates/keys used on the connection.
++*/
++SSL_IMPORT SECStatus SSL_RecommendedCanFalseStart(PRFileDesc *fd,
++ PRBool *canFalseStart);
+
/*
** For the server, request a new handshake. For the client, begin a new
** handshake. If flushCache is non-zero, the SSL3 cache entry will be
+Index: net/third_party/nss/ssl/ssl3con.c
+===================================================================
+--- net/third_party/nss/ssl/ssl3con.c (revision 227672)
++++ net/third_party/nss/ssl/ssl3con.c (working copy)
+@@ -2890,7 +2890,7 @@
+ SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d",
+ SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type),
+ nIn));
+- PRINT_BUF(3, (ss, "Send record (plain text)", pIn, nIn));
++ PRINT_BUF(50, (ss, "Send record (plain text)", pIn, nIn));
+
+ PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
+
+@@ -7344,36 +7344,72 @@
+ return rv;
+ }
+
++static SECStatus
++ssl3_CheckFalseStart(sslSocket *ss)
++{
++ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
++ PORT_Assert( !ss->ssl3.hs.authCertificatePending );
++ PORT_Assert( !ss->ssl3.hs.canFalseStart );
++
++ if (!ss->canFalseStartCallback) {
++ SSL_TRC(3, ("%d: SSL[%d]: no false start callback so no false start",
++ SSL_GETPID(), ss->fd));
++ } else {
++ PRBool maybeFalseStart;
++ SECStatus rv;
++
++ /* An attacker can control the selected ciphersuite so we only wish to
++ * do False Start in the case that the selected ciphersuite is
++ * sufficiently strong that the attack can gain no advantage.
++ * Therefore we always require an 80-bit cipher. */
++ ssl_GetSpecReadLock(ss);
++ maybeFalseStart = ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10;
++ ssl_ReleaseSpecReadLock(ss);
++
++ if (!maybeFalseStart) {
++ SSL_TRC(3, ("%d: SSL[%d]: no false start due to weak cipher",
++ SSL_GETPID(), ss->fd));
++ } else {
++ rv = (ss->canFalseStartCallback)(ss->fd,
++ ss->canFalseStartCallbackData,
++ &ss->ssl3.hs.canFalseStart);
++ if (rv == SECSuccess) {
++ SSL_TRC(3, ("%d: SSL[%d]: false start callback returned %s",
++ SSL_GETPID(), ss->fd,
++ ss->ssl3.hs.canFalseStart ? "TRUE" : "FALSE"));
++ } else {
++ SSL_TRC(3, ("%d: SSL[%d]: false start callback failed (%s)",
++ SSL_GETPID(), ss->fd,
++ PR_ErrorToName(PR_GetError())));
++ }
++ return rv;
++ }
++ }
++
++ ss->ssl3.hs.canFalseStart = PR_FALSE;
++ return SECSuccess;
++}
++
+ PRBool
+-ssl3_CanFalseStart(sslSocket *ss) {
+- PRBool rv;
++ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss)
++{
++ PRBool result;
+
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+
+- /* XXX: does not take into account whether we are waiting for
+- * SSL_AuthCertificateComplete or SSL_RestartHandshakeAfterCertReq. If/when
+- * that is done, this function could return different results each time it
+- * would be called.
+- */
++ switch (ss->ssl3.hs.ws) {
++ case wait_new_session_ticket:
++ result = PR_TRUE;
++ break;
++ case wait_change_cipher:
++ result = !ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn);
++ break;
++ default:
++ result = PR_FALSE;
++ break;
++ }
+
+- ssl_GetSpecReadLock(ss);
+- rv = ss->opt.enableFalseStart &&
+- !ss->sec.isServer &&
+- !ss->ssl3.hs.isResuming &&
+- ss->ssl3.cwSpec &&
+-
+- /* An attacker can control the selected ciphersuite so we only wish to
+- * do False Start in the case that the selected ciphersuite is
+- * sufficiently strong that the attack can gain no advantage.
+- * Therefore we require an 80-bit cipher and a forward-secret key
+- * exchange. */
+- ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10 &&
+- (ss->ssl3.hs.kea_def->kea == kea_dhe_dss ||
+- ss->ssl3.hs.kea_def->kea == kea_dhe_rsa ||
+- ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa ||
+- ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa);
+- ssl_ReleaseSpecReadLock(ss);
+- return rv;
++ return result;
+ }
+
+ static SECStatus ssl3_SendClientSecondRound(sslSocket *ss);
+@@ -7463,6 +7499,9 @@
+ }
+ if (ss->ssl3.hs.authCertificatePending &&
+ (sendClientCert || ss->ssl3.sendEmptyCert || ss->firstHsDone)) {
++ SSL_TRC(3, ("%d: SSL3[%p]: deferring ssl3_SendClientSecondRound because"
++ " certificate authentication is still pending.",
++ SSL_GETPID(), ss->fd));
+ ss->ssl3.hs.restartTarget = ssl3_SendClientSecondRound;
+ return SECWouldBlock;
+ }
+@@ -7500,20 +7539,59 @@
+ goto loser; /* err code was set. */
+ }
+
+- /* XXX: If the server's certificate hasn't been authenticated by this
+- * point, then we may be leaking this NPN message to an attacker.
++ /* This must be done after we've set ss->ssl3.cwSpec in
++ * ssl3_SendChangeCipherSpecs because SSL_GetChannelInfo uses information
++ * from cwSpec. This must be done before we call ssl3_CheckFalseStart
++ * because the false start callback (if any) may need the information from
++ * the functions that depend on this being set.
+ */
++ ss->enoughFirstHsDone = PR_TRUE;
++
+ if (!ss->firstHsDone) {
++ /* XXX: If the server's certificate hasn't been authenticated by this
++ * point, then we may be leaking this NPN message to an attacker.
++ */
+ rv = ssl3_SendNextProto(ss);
+ if (rv != SECSuccess) {
+ goto loser; /* err code was set. */
+ }
+ }
++
+ rv = ssl3_SendEncryptedExtensions(ss);
+ if (rv != SECSuccess) {
+ goto loser; /* err code was set. */
+ }
+
++ if (!ss->firstHsDone) {
++ if (ss->opt.enableFalseStart) {
++ if (!ss->ssl3.hs.authCertificatePending) {
++ /* When we fix bug 589047, we will need to know whether we are
++ * false starting before we try to flush the client second
++ * round to the network. With that in mind, we purposefully
++ * call ssl3_CheckFalseStart before calling ssl3_SendFinished,
++ * which includes a call to ssl3_FlushHandshake, so that
++ * no application develops a reliance on such flushing being
++ * done before its false start callback is called.
++ */
++ ssl_ReleaseXmitBufLock(ss);
++ rv = ssl3_CheckFalseStart(ss);
++ ssl_GetXmitBufLock(ss);
++ if (rv != SECSuccess) {
++ goto loser;
++ }
++ } else {
++ /* The certificate authentication and the server's Finished
++ * message are racing each other. If the certificate
++ * authentication wins, then we will try to false start in
++ * ssl3_AuthCertificateComplete.
++ */
++ SSL_TRC(3, ("%d: SSL3[%p]: deferring false start check because"
++ " certificate authentication is still pending.",
++ SSL_GETPID(), ss->fd));
++ }
++ }
++ }
++
+ rv = ssl3_SendFinished(ss, 0);
+ if (rv != SECSuccess) {
+ goto loser; /* err code was set. */
+@@ -7526,10 +7604,7 @@
+ else
+ ss->ssl3.hs.ws = wait_change_cipher;
+
+- /* Do the handshake callback for sslv3 here, if we can false start. */
+- if (ss->handshakeCallback != NULL && ssl3_CanFalseStart(ss)) {
+- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
+- }
++ PORT_Assert(ssl3_WaitingForStartOfServerSecondRound(ss));
+
+ return SECSuccess;
+
+@@ -10147,13 +10222,6 @@
+
+ ss->ssl3.hs.authCertificatePending = PR_TRUE;
+ rv = SECSuccess;
+-
+- /* XXX: Async cert validation and False Start don't work together
+- * safely yet; if we leave False Start enabled, we may end up false
+- * starting (sending application data) before we
+- * SSL_AuthCertificateComplete has been called.
+- */
+- ss->opt.enableFalseStart = PR_FALSE;
+ }
+
+ if (rv != SECSuccess) {
+@@ -10278,6 +10346,12 @@
+ } else if (ss->ssl3.hs.restartTarget != NULL) {
+ sslRestartTarget target = ss->ssl3.hs.restartTarget;
+ ss->ssl3.hs.restartTarget = NULL;
++
++ if (target == ssl3_FinishHandshake) {
++ SSL_TRC(3,("%d: SSL3[%p]: certificate authentication lost the race"
++ " with peer's finished message", SSL_GETPID(), ss->fd));
++ }
++
+ rv = target(ss);
+ /* Even if we blocked here, we have accomplished enough to claim
+ * success. Any remaining work will be taken care of by subsequent
+@@ -10287,7 +10361,27 @@
+ rv = SECSuccess;
+ }
+ } else {
+- rv = SECSuccess;
++ SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race with"
++ " peer's finished message", SSL_GETPID(), ss->fd));
++
++ PORT_Assert(!ss->firstHsDone);
++ PORT_Assert(!ss->sec.isServer);
++ PORT_Assert(!ss->ssl3.hs.isResuming);
++ PORT_Assert(ss->ssl3.hs.ws != idle_handshake);
++
++ if (ss->opt.enableFalseStart &&
++ !ss->firstHsDone &&
++ !ss->sec.isServer &&
++ !ss->ssl3.hs.isResuming &&
++ ssl3_WaitingForStartOfServerSecondRound(ss)) {
++ /* ssl3_SendClientSecondRound deferred the false start check because
++ * certificate authentication was pending, so we do it now if we still
++ * haven't received any of the server's second round yet.
++ */
++ rv = ssl3_CheckFalseStart(ss);
++ } else {
++ rv = SECSuccess;
++ }
+ }
+
+ done:
+@@ -10913,9 +11007,6 @@
+ return rv;
+ }
+
+- ss->gs.writeOffset = 0;
+- ss->gs.readOffset = 0;
+-
+ if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) {
+ effectiveExchKeyType = kt_rsa;
+ } else {
+@@ -10980,6 +11071,9 @@
+ return rv;
+ }
+
++/* The return type is SECStatus instead of void because this function needs
++ * to have type sslRestartTarget.
++ */
+ SECStatus
+ ssl3_FinishHandshake(sslSocket * ss)
+ {
+@@ -10989,19 +11083,16 @@
+
+ /* The first handshake is now completed. */
+ ss->handshake = NULL;
+- ss->firstHsDone = PR_TRUE;
+
+ if (ss->ssl3.hs.cacheSID) {
+ (*ss->sec.cache)(ss->sec.ci.sid);
+ ss->ssl3.hs.cacheSID = PR_FALSE;
+ }
+
++ ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */
+ ss->ssl3.hs.ws = idle_handshake;
+
+- /* Do the handshake callback for sslv3 here, if we cannot false start. */
+- if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) {
+- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
+- }
++ ssl_FinishHandshake(ss);
+
+ return SECSuccess;
+ }
+@@ -11966,7 +12057,6 @@
+
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ return rv;
+-
+ }
+
+ /*
Index: net/third_party/nss/ssl/ssl3gthr.c
===================================================================
---- net/third_party/nss/ssl/ssl3gthr.c (revision 227363)
+--- net/third_party/nss/ssl/ssl3gthr.c (revision 227672)
+++ net/third_party/nss/ssl/ssl3gthr.c (working copy)
-@@ -374,9 +374,7 @@
- */
- if (ss->opt.enableFalseStart) {
- ssl_GetSSL3HandshakeLock(ss);
+@@ -275,11 +275,17 @@
+ {
+ SSL3Ciphertext cText;
+ int rv;
+- PRBool canFalseStart = PR_FALSE;
++ PRBool keepGoing = PR_TRUE;
+
+ SSL_TRC(30, ("ssl3_GatherCompleteHandshake"));
+
++ /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake,
++ * which requires the 1stHandshakeLock, which must be acquired before the
++ * RecvBufLock.
++ */
++ PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
++
+ do {
+ PRBool handleRecordNow = PR_FALSE;
+
+@@ -364,24 +370,52 @@
+
+ cText.buf = &ss->gs.inbuf;
+ rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
++
++ if (rv == (int) SECSuccess && ss->gs.buf.len > 0) {
++ /* We have application data to return to the application. This
++ * prioritizes returning application data to the application over
++ * completing any renegotiation handshake we may be doing.
++ */
++ PORT_Assert(ss->firstHsDone);
++ PORT_Assert(cText.type == content_application_data);
++ break;
++ }
+ }
+ if (rv < 0) {
+ return ss->recvdCloseNotify ? 0 : rv;
+ }
+
+- /* If we kicked off a false start in ssl3_HandleServerHelloDone, break
+- * out of this loop early without finishing the handshake.
+- */
+- if (ss->opt.enableFalseStart) {
+- ssl_GetSSL3HandshakeLock(ss);
- canFalseStart = (ss->ssl3.hs.ws == wait_change_cipher ||
- ss->ssl3.hs.ws == wait_new_session_ticket) &&
- ssl3_CanFalseStart(ss);
-+ canFalseStart = ss->ssl3.hs.canFalseStart;
- ssl_ReleaseSSL3HandshakeLock(ss);
+- ssl_ReleaseSSL3HandshakeLock(ss);
++ PORT_Assert(keepGoing);
++ ssl_GetSSL3HandshakeLock(ss);
++ if (ss->ssl3.hs.ws == idle_handshake) {
++ /* We are done with the current handshake so stop trying to
++ * handshake. Note that it would be safe to test ss->firstHsDone
++ * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead,
++ * we prioritize completing a renegotiation handshake over sending
++ * application data.
++ */
++ PORT_Assert(ss->firstHsDone);
++ PORT_Assert(!ss->ssl3.hs.canFalseStart);
++ keepGoing = PR_FALSE;
++ } else if (ss->ssl3.hs.canFalseStart) {
++ /* Prioritize sending application data over trying to complete
++ * the handshake if we're false starting.
++ *
++ * If we were to do this check at the beginning of the loop instead
++ * of here, then this function would become be a no-op after
++ * receiving the ServerHelloDone in the false start case, and we
++ * would never complete the handshake.
++ */
++ PORT_Assert(!ss->firstHsDone);
++
++ if (ssl3_WaitingForStartOfServerSecondRound(ss)) {
++ keepGoing = PR_FALSE;
++ } else {
++ ss->ssl3.hs.canFalseStart = PR_FALSE;
++ }
}
- } while (ss->ssl3.hs.ws != idle_handshake &&
-Index: net/third_party/nss/ssl/sslinfo.c
-===================================================================
---- net/third_party/nss/ssl/sslinfo.c (revision 227363)
-+++ net/third_party/nss/ssl/sslinfo.c (working copy)
-@@ -26,7 +26,6 @@
- sslSocket * ss;
- SSLChannelInfo inf;
- sslSessionID * sid;
-- PRBool enoughFirstHsDone = PR_FALSE;
-
- if (!info || len < sizeof inf.length) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
-@@ -43,14 +42,7 @@
- memset(&inf, 0, sizeof inf);
- inf.length = PR_MIN(sizeof inf, len);
+- } while (ss->ssl3.hs.ws != idle_handshake &&
+- !canFalseStart &&
+- ss->gs.buf.len == 0);
++ ssl_ReleaseSSL3HandshakeLock(ss);
++ } while (keepGoing);
+
+ ss->gs.readOffset = 0;
+ ss->gs.writeOffset = ss->gs.buf.len;
+@@ -404,7 +438,10 @@
+ {
+ int rv;
-- if (ss->firstHsDone) {
-- enoughFirstHsDone = PR_TRUE;
-- } else if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
-- ssl3_CanFalseStart(ss)) {
-- enoughFirstHsDone = PR_TRUE;
-- }
--
-- if (ss->opt.useSecurity && enoughFirstHsDone) {
-+ if (ss->opt.useSecurity && ss->enoughFirstHsDone) {
- sid = ss->sec.ci.sid;
- inf.protocolVersion = ss->version;
- inf.authKeyBits = ss->sec.authKeyBits;
++ /* ssl3_GatherCompleteHandshake requires both of these locks. */
++ PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
++
+ do {
+ rv = ssl3_GatherCompleteHandshake(ss, flags);
+ } while (rv > 0 && ss->gs.buf.len == 0);
Index: net/third_party/nss/ssl/sslauth.c
===================================================================
---- net/third_party/nss/ssl/sslauth.c (revision 227363)
+--- net/third_party/nss/ssl/sslauth.c (revision 227672)
+++ net/third_party/nss/ssl/sslauth.c (working copy)
@@ -100,7 +100,6 @@
sslSocket *ss;
@@ -168,7 +506,7 @@ Index: net/third_party/nss/ssl/sslauth.c
} else {
Index: net/third_party/nss/ssl/sslimpl.h
===================================================================
---- net/third_party/nss/ssl/sslimpl.h (revision 227363)
+--- net/third_party/nss/ssl/sslimpl.h (revision 227672)
+++ net/third_party/nss/ssl/sslimpl.h (working copy)
@@ -881,6 +881,8 @@
/* Shared state between ssl3_HandleFinished and ssl3_FinishHandshake */
@@ -199,28 +537,69 @@ Index: net/third_party/nss/ssl/sslimpl.h
void *pkcs11PinArg;
SSLNextProtoCallback nextProtoCallback;
void *nextProtoArg;
-@@ -1423,7 +1431,6 @@
+@@ -1423,7 +1431,19 @@
extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled);
-extern PRBool ssl3_CanFalseStart(sslSocket *ss);
++extern void ssl_FinishHandshake(sslSocket *ss);
++
++/* Returns PR_TRUE if we are still waiting for the server to respond to our
++ * client second round. Once we've received any part of the server's second
++ * round then we don't bother trying to false start since it is almost always
++ * the case that the NewSessionTicket, ChangeCipherSoec, and Finished messages
++ * were sent in the same packet and we want to process them all at the same
++ * time. If we were to try to false start in the middle of the server's second
++ * round, then we would increase the number of I/O operations
++ * (SSL_ForceHandshake/PR_Recv/PR_Send/etc.) needed to finish the handshake.
++ */
++extern PRBool ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss);
++
extern SECStatus
ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
PRBool isServer,
+Index: net/third_party/nss/ssl/sslinfo.c
+===================================================================
+--- net/third_party/nss/ssl/sslinfo.c (revision 227672)
++++ net/third_party/nss/ssl/sslinfo.c (working copy)
+@@ -26,7 +26,6 @@
+ sslSocket * ss;
+ SSLChannelInfo inf;
+ sslSessionID * sid;
+- PRBool enoughFirstHsDone = PR_FALSE;
+
+ if (!info || len < sizeof inf.length) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -43,14 +42,7 @@
+ memset(&inf, 0, sizeof inf);
+ inf.length = PR_MIN(sizeof inf, len);
+
+- if (ss->firstHsDone) {
+- enoughFirstHsDone = PR_TRUE;
+- } else if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
+- ssl3_CanFalseStart(ss)) {
+- enoughFirstHsDone = PR_TRUE;
+- }
+-
+- if (ss->opt.useSecurity && enoughFirstHsDone) {
++ if (ss->opt.useSecurity && ss->enoughFirstHsDone) {
+ sid = ss->sec.ci.sid;
+ inf.protocolVersion = ss->version;
+ inf.authKeyBits = ss->sec.authKeyBits;
Index: net/third_party/nss/ssl/sslsecur.c
===================================================================
---- net/third_party/nss/ssl/sslsecur.c (revision 227363)
+--- net/third_party/nss/ssl/sslsecur.c (revision 227672)
+++ net/third_party/nss/ssl/sslsecur.c (working copy)
-@@ -99,21 +99,12 @@
+@@ -97,23 +97,13 @@
+ ss->securityHandshake = 0;
+ }
if (ss->handshake == 0) {
- ssl_GetRecvBufLock(ss);
- ss->gs.recordLen = 0;
-+ ss->gs.writeOffset = 0;
-+ ss->gs.readOffset = 0;
- ssl_ReleaseRecvBufLock(ss);
-
- SSL_TRC(3, ("%d: SSL[%d]: handshake is completed",
- SSL_GETPID(), ss->fd));
+- ssl_GetRecvBufLock(ss);
+- ss->gs.recordLen = 0;
+- ssl_ReleaseRecvBufLock(ss);
+-
+- SSL_TRC(3, ("%d: SSL[%d]: handshake is completed",
+- SSL_GETPID(), ss->fd));
- /* call handshake callback for ssl v2 */
- /* for v3 this is done in ssl3_HandleFinished() */
- if ((ss->handshakeCallback != NULL) && /* has callback */
@@ -228,14 +607,45 @@ Index: net/third_party/nss/ssl/sslsecur.c
- (ss->version < SSL_LIBRARY_VERSION_3_0)) { /* not ssl3 */
- ss->firstHsDone = PR_TRUE;
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
-- }
++ /* for v3 this is done in ssl3_FinishHandshake */
++ if (!ss->firstHsDone && ss->version < SSL_LIBRARY_VERSION_3_0) {
++ ssl_GetRecvBufLock(ss);
++ ss->gs.recordLen = 0;
++ ssl_FinishHandshake(ss);
++ ssl_ReleaseRecvBufLock(ss);
+ }
- ss->firstHsDone = PR_TRUE;
- ss->gs.writeOffset = 0;
- ss->gs.readOffset = 0;
break;
}
rv = (*ss->handshake)(ss);
-@@ -206,6 +197,7 @@
+@@ -134,6 +124,24 @@
+ return rv;
+ }
+
++void
++ssl_FinishHandshake(sslSocket *ss)
++{
++ PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
++ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
++
++ SSL_TRC(3, ("%d: SSL[%d]: handshake is completed", SSL_GETPID(), ss->fd));
++
++ ss->firstHsDone = PR_TRUE;
++ ss->enoughFirstHsDone = PR_TRUE;
++ ss->gs.writeOffset = 0;
++ ss->gs.readOffset = 0;
++
++ if (ss->handshakeCallback) {
++ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
++ }
++}
++
+ /*
+ * Handshake function that blocks. Used to force a
+ * retry on a connection on the next read/write.
+@@ -206,6 +214,7 @@
ssl_Get1stHandshakeLock(ss);
ss->firstHsDone = PR_FALSE;
@@ -243,7 +653,7 @@ Index: net/third_party/nss/ssl/sslsecur.c
if ( asServer ) {
ss->handshake = ssl2_BeginServerHandshake;
ss->handshaking = sslHandshakingAsServer;
-@@ -221,6 +213,8 @@
+@@ -221,6 +230,8 @@
ssl_ReleaseRecvBufLock(ss);
ssl_GetSSL3HandshakeLock(ss);
@@ -252,16 +662,7 @@ Index: net/third_party/nss/ssl/sslsecur.c
/*
** Blow away old security state and get a fresh setup.
-@@ -266,7 +260,7 @@
-
- /* SSL v2 protocol does not support subsequent handshakes. */
- if (ss->version < SSL_LIBRARY_VERSION_3_0) {
-- PORT_SetError(SEC_ERROR_INVALID_ARGS);
-+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
- rv = SECFailure;
- } else {
- ssl_GetSSL3HandshakeLock(ss);
-@@ -331,6 +325,75 @@
+@@ -331,6 +342,71 @@
return SECSuccess;
}
@@ -270,7 +671,7 @@ Index: net/third_party/nss/ssl/sslsecur.c
+*/
+SECStatus
+SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb,
-+ void *client_data)
++ void *arg)
+{
+ sslSocket *ss;
+
@@ -290,7 +691,7 @@ Index: net/third_party/nss/ssl/sslsecur.c
+ ssl_GetSSL3HandshakeLock(ss);
+
+ ss->canFalseStartCallback = cb;
-+ ss->canFalseStartCallbackData = client_data;
++ ss->canFalseStartCallbackData = arg;
+
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
@@ -298,19 +699,15 @@ Index: net/third_party/nss/ssl/sslsecur.c
+ return SECSuccess;
+}
+
-+/* A utility function that can be called from a custom SSLCanFalseStartCallback
-+** function to determine what NSS would have done for this connection if the
-+** custom callback was not implemented.
-+*/
+SECStatus
-+SSL_DefaultCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
++SSL_RecommendedCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
+{
+ sslSocket *ss;
+
+ *canFalseStart = PR_FALSE;
+ ss = ssl_FindSocket(fd);
+ if (!ss) {
-+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_DefaultCanFalseStart",
++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RecommendedCanFalseStart",
+ SSL_GETPID(), fd));
+ return SECFailure;
+ }
@@ -337,9 +734,43 @@ Index: net/third_party/nss/ssl/sslsecur.c
/* Try to make progress on an SSL handshake by attempting to read the
** next handshake from the peer, and sending any responses.
** For non-blocking sockets, returns PR_ERROR_WOULD_BLOCK if it cannot
-@@ -1195,12 +1258,7 @@
+@@ -524,6 +600,9 @@
+ int amount;
+ int available;
+
++ /* ssl3_GatherAppDataRecord may call ssl_FinishHandshake, which needs the
++ * 1stHandshakeLock. */
++ ssl_Get1stHandshakeLock(ss);
+ ssl_GetRecvBufLock(ss);
+
+ available = ss->gs.writeOffset - ss->gs.readOffset;
+@@ -590,6 +669,7 @@
+
+ done:
+ ssl_ReleaseRecvBufLock(ss);
++ ssl_Release1stHandshakeLock(ss);
+ return rv;
+ }
+
+@@ -1156,7 +1236,8 @@
+ int
+ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
+ {
+- int rv = 0;
++ int rv = 0;
++ PRBool falseStart = PR_FALSE;
+
+ SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
+ SSL_GETPID(), ss->fd, len));
+@@ -1191,19 +1272,14 @@
+ ss->writerThread = PR_GetCurrentThread();
+ /* If any of these is non-zero, the initial handshake is not done. */
+ if (!ss->firstHsDone) {
+- PRBool canFalseStart = PR_FALSE;
ssl_Get1stHandshakeLock(ss);
- if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
+- if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
++ if (ss->opt.enableFalseStart &&
++ ss->version >= SSL_LIBRARY_VERSION_3_0) {
ssl_GetSSL3HandshakeLock(ss);
- if ((ss->ssl3.hs.ws == wait_change_cipher ||
- ss->ssl3.hs.ws == wait_finished ||
@@ -347,15 +778,46 @@ Index: net/third_party/nss/ssl/sslsecur.c
- ssl3_CanFalseStart(ss)) {
- canFalseStart = PR_TRUE;
- }
-+ canFalseStart = ss->ssl3.hs.canFalseStart;
++ falseStart = ss->ssl3.hs.canFalseStart;
ssl_ReleaseSSL3HandshakeLock(ss);
}
- if (!canFalseStart &&
+- if (!canFalseStart &&
++ if (!falseStart &&
+ (ss->handshake || ss->nextHandshake || ss->securityHandshake)) {
+ rv = ssl_Do1stHandshake(ss);
+ }
+@@ -1228,6 +1304,17 @@
+ goto done;
+ }
+
++ if (!ss->firstHsDone) {
++ PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_3_0);
++#ifdef DEBUG
++ ssl_GetSSL3HandshakeLock(ss);
++ PORT_Assert(ss->ssl3.hs.canFalseStart);
++ ssl_ReleaseSSL3HandshakeLock(ss);
++#endif
++ SSL_TRC(3, ("%d: SSL[%d]: SecureSend: sending data due to false start",
++ SSL_GETPID(), ss->fd));
++ }
++
+ /* Send out the data using one of these functions:
+ * ssl2_SendClear, ssl2_SendStream, ssl2_SendBlock,
+ * ssl3_SendApplicationData
Index: net/third_party/nss/ssl/sslsock.c
===================================================================
---- net/third_party/nss/ssl/sslsock.c (revision 227363)
+--- net/third_party/nss/ssl/sslsock.c (revision 227672)
+++ net/third_party/nss/ssl/sslsock.c (working copy)
-@@ -2457,10 +2457,14 @@
+@@ -366,6 +366,8 @@
+ ss->badCertArg = os->badCertArg;
+ ss->handshakeCallback = os->handshakeCallback;
+ ss->handshakeCallbackData = os->handshakeCallbackData;
++ ss->canFalseStartCallback = os->canFalseStartCallback;
++ ss->canFalseStartCallbackData = os->canFalseStartCallbackData;
+ ss->pkcs11PinArg = os->pkcs11PinArg;
+ ss->getChannelID = os->getChannelID;
+ ss->getChannelIDArg = os->getChannelIDArg;
+@@ -2457,10 +2459,14 @@
} else if (new_flags & PR_POLL_WRITE) {
/* The caller is trying to write, but the handshake is
** blocked waiting for data to read, and the first
@@ -373,265 +835,3 @@ Index: net/third_party/nss/ssl/sslsock.c
}
}
} else if ((new_flags & PR_POLL_READ) && (SSL_DataPending(fd) > 0)) {
-Index: net/third_party/nss/ssl/ssl3con.c
-===================================================================
---- net/third_party/nss/ssl/ssl3con.c (revision 227363)
-+++ net/third_party/nss/ssl/ssl3con.c (working copy)
-@@ -2890,7 +2890,7 @@
- SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d",
- SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type),
- nIn));
-- PRINT_BUF(3, (ss, "Send record (plain text)", pIn, nIn));
-+ PRINT_BUF(50, (ss, "Send record (plain text)", pIn, nIn));
-
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
-
-@@ -7344,35 +7344,42 @@
- return rv;
- }
-
--PRBool
--ssl3_CanFalseStart(sslSocket *ss) {
-- PRBool rv;
-+static SECStatus
-+ssl3_CheckFalseStart(sslSocket *ss)
-+{
-+ SECStatus rv;
-+ PRBool maybeFalseStart = PR_TRUE;
-
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
-+ PORT_Assert( !ss->ssl3.hs.authCertificatePending );
-
-- /* XXX: does not take into account whether we are waiting for
-- * SSL_AuthCertificateComplete or SSL_RestartHandshakeAfterCertReq. If/when
-- * that is done, this function could return different results each time it
-- * would be called.
-- */
-+ /* An attacker can control the selected ciphersuite so we only wish to
-+ * do False Start in the case that the selected ciphersuite is
-+ * sufficiently strong that the attack can gain no advantage.
-+ * Therefore we always require an 80-bit cipher. */
-
- ssl_GetSpecReadLock(ss);
-- rv = ss->opt.enableFalseStart &&
-- !ss->sec.isServer &&
-- !ss->ssl3.hs.isResuming &&
-- ss->ssl3.cwSpec &&
-+ if (ss->ssl3.cwSpec->cipher_def->secret_key_size < 10) {
-+ ss->ssl3.hs.canFalseStart = PR_FALSE;
-+ maybeFalseStart = PR_FALSE;
-+ }
-+ ssl_ReleaseSpecReadLock(ss);
-+ if (!maybeFalseStart) {
-+ return SECSuccess;
-+ }
-
-- /* An attacker can control the selected ciphersuite so we only wish to
-- * do False Start in the case that the selected ciphersuite is
-- * sufficiently strong that the attack can gain no advantage.
-- * Therefore we require an 80-bit cipher and a forward-secret key
-- * exchange. */
-- ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10 &&
-- (ss->ssl3.hs.kea_def->kea == kea_dhe_dss ||
-- ss->ssl3.hs.kea_def->kea == kea_dhe_rsa ||
-- ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa ||
-- ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa);
-- ssl_ReleaseSpecReadLock(ss);
-+ if (!ss->canFalseStartCallback) {
-+ rv = SSL_DefaultCanFalseStart(ss->fd, &ss->ssl3.hs.canFalseStart);
-+ } else {
-+ rv = (ss->canFalseStartCallback)(ss->fd,
-+ ss->canFalseStartCallbackData,
-+ &ss->ssl3.hs.canFalseStart);
-+ }
-+
-+ if (rv != SECSuccess) {
-+ ss->ssl3.hs.canFalseStart = PR_FALSE;
-+ }
-+
- return rv;
- }
-
-@@ -7500,20 +7507,59 @@
- goto loser; /* err code was set. */
- }
-
-- /* XXX: If the server's certificate hasn't been authenticated by this
-- * point, then we may be leaking this NPN message to an attacker.
-+ /* This must be done after we've set ss->ssl3.cwSpec in
-+ * ssl3_SendChangeCipherSpecs because SSL_GetChannelInfo uses information
-+ * from cwSpec. This must be done before we call ssl3_CheckFalseStart
-+ * because the false start callback (if any) may need the information from
-+ * the functions that depend on this being set.
- */
-+ ss->enoughFirstHsDone = PR_TRUE;
-+
- if (!ss->firstHsDone) {
-+ /* XXX: If the server's certificate hasn't been authenticated by this
-+ * point, then we may be leaking this NPN message to an attacker.
-+ */
- rv = ssl3_SendNextProto(ss);
- if (rv != SECSuccess) {
- goto loser; /* err code was set. */
- }
- }
-+
- rv = ssl3_SendEncryptedExtensions(ss);
- if (rv != SECSuccess) {
- goto loser; /* err code was set. */
- }
-
-+ if (!ss->firstHsDone) {
-+ if (ss->opt.enableFalseStart) {
-+ if (!ss->ssl3.hs.authCertificatePending) {
-+ /* When we fix bug 589047, we will need to know whether we are
-+ * false starting before we try to flush the client second
-+ * round to the network. With that in mind, we purposefully
-+ * call ssl3_CheckFalseStart before calling ssl3_SendFinished,
-+ * which includes a call to ssl3_FlushHandshake, so that
-+ * no application develops a reliance on such flushing being
-+ * done before its false start callback is called.
-+ */
-+ ssl_ReleaseXmitBufLock(ss);
-+ rv = ssl3_CheckFalseStart(ss);
-+ ssl_GetXmitBufLock(ss);
-+ if (rv != SECSuccess) {
-+ goto loser;
-+ }
-+ } else {
-+ /* The certificate authentication and the server's Finished
-+ * message are racing each other. If the certificate
-+ * authentication wins, then we will try to false start in
-+ * ssl3_AuthCertificateComplete.
-+ */
-+ SSL_TRC(3, ("%d: SSL3[%p]: deferring false start check because"
-+ " certificate authentication is still pending.",
-+ SSL_GETPID(), ss->fd));
-+ }
-+ }
-+ }
-+
- rv = ssl3_SendFinished(ss, 0);
- if (rv != SECSuccess) {
- goto loser; /* err code was set. */
-@@ -7526,8 +7572,16 @@
- else
- ss->ssl3.hs.ws = wait_change_cipher;
-
-- /* Do the handshake callback for sslv3 here, if we can false start. */
-- if (ss->handshakeCallback != NULL && ssl3_CanFalseStart(ss)) {
-+ if (ss->handshakeCallback &&
-+ (ss->ssl3.hs.canFalseStart && !ss->canFalseStartCallback)) {
-+ /* Call the handshake callback here for backwards compatibility with
-+ * applications that were using false start before
-+ * canFalseStartCallback was added. Note that we do this after calling
-+ * ssl3_SendFinished, which includes a call to ssl3_FlushHandshake,
-+ * just in case the application is relying on having the handshake
-+ * messages flushed to the network before its handshake callback is
-+ * called.
-+ */
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
- }
-
-@@ -10147,13 +10201,6 @@
-
- ss->ssl3.hs.authCertificatePending = PR_TRUE;
- rv = SECSuccess;
--
-- /* XXX: Async cert validation and False Start don't work together
-- * safely yet; if we leave False Start enabled, we may end up false
-- * starting (sending application data) before we
-- * SSL_AuthCertificateComplete has been called.
-- */
-- ss->opt.enableFalseStart = PR_FALSE;
- }
-
- if (rv != SECSuccess) {
-@@ -10278,6 +10325,12 @@
- } else if (ss->ssl3.hs.restartTarget != NULL) {
- sslRestartTarget target = ss->ssl3.hs.restartTarget;
- ss->ssl3.hs.restartTarget = NULL;
-+
-+ if (target == ssl3_FinishHandshake) {
-+ SSL_TRC(3,("%d: SSL3[%p]: certificate authentication lost the race"
-+ " with peer's finished message", SSL_GETPID(), ss->fd));
-+ }
-+
- rv = target(ss);
- /* Even if we blocked here, we have accomplished enough to claim
- * success. Any remaining work will be taken care of by subsequent
-@@ -10287,7 +10340,39 @@
- rv = SECSuccess;
- }
- } else {
-- rv = SECSuccess;
-+ SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race"
-+ " with peer's finished message", SSL_GETPID(), ss->fd));
-+
-+ PORT_Assert(!ss->firstHsDone);
-+ PORT_Assert(!ss->sec.isServer);
-+ PORT_Assert(!ss->ssl3.hs.isResuming);
-+ PORT_Assert(ss->ssl3.hs.ws == wait_change_cipher ||
-+ ss->ssl3.hs.ws == wait_finished ||
-+ ss->ssl3.hs.ws == wait_new_session_ticket);
-+
-+ /* ssl3_SendClientSecondRound deferred the false start check because
-+ * certificate authentication was pending, so we have to do it now.
-+ */
-+ if (ss->opt.enableFalseStart &&
-+ !ss->firstHsDone &&
-+ !ss->sec.isServer &&
-+ !ss->ssl3.hs.isResuming &&
-+ (ss->ssl3.hs.ws == wait_change_cipher ||
-+ ss->ssl3.hs.ws == wait_finished ||
-+ ss->ssl3.hs.ws == wait_new_session_ticket)) {
-+ rv = ssl3_CheckFalseStart(ss);
-+ if (rv == SECSuccess &&
-+ ss->handshakeCallback &&
-+ (ss->ssl3.hs.canFalseStart && !ss->canFalseStartCallback)) {
-+ /* Call the handshake callback here for backwards compatibility
-+ * with applications that were using false start before
-+ * canFalseStartCallback was added.
-+ */
-+ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
-+ }
-+ } else {
-+ rv = SECSuccess;
-+ }
- }
-
- done:
-@@ -10983,6 +11068,8 @@
- SECStatus
- ssl3_FinishHandshake(sslSocket * ss)
- {
-+ PRBool falseStarted;
-+
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( ss->ssl3.hs.restartTarget == NULL );
-@@ -10990,6 +11077,7 @@
- /* The first handshake is now completed. */
- ss->handshake = NULL;
- ss->firstHsDone = PR_TRUE;
-+ ss->enoughFirstHsDone = PR_TRUE;
-
- if (ss->ssl3.hs.cacheSID) {
- (*ss->sec.cache)(ss->sec.ci.sid);
-@@ -10997,9 +11085,14 @@
- }
-
- ss->ssl3.hs.ws = idle_handshake;
-+ falseStarted = ss->ssl3.hs.canFalseStart;
-+ ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */
-
-- /* Do the handshake callback for sslv3 here, if we cannot false start. */
-- if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) {
-+ /* Call the handshake callback for sslv3 here, unless we called it already
-+ * for the case where false start was done without a canFalseStartCallback.
-+ */
-+ if (ss->handshakeCallback &&
-+ !(falseStarted && !ss->canFalseStartCallback)) {
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
- }
-
diff --git a/chromium/net/third_party/nss/patches/chacha20poly1305.patch b/chromium/net/third_party/nss/patches/chacha20poly1305.patch
index c858413f3c3..89a71bbf6d7 100644
--- a/chromium/net/third_party/nss/patches/chacha20poly1305.patch
+++ b/chromium/net/third_party/nss/patches/chacha20poly1305.patch
@@ -9,15 +9,15 @@ index 8be517c..53c29f0 100644
+/* This is a bodge to allow this code to be compiled against older NSS
+ * headers. */
+#ifndef CKM_NSS_CHACHA20_POLY1305
-+#define CKM_NSS_CHACHA20_POLY1305 (CKM_NSS + 25)
++#define CKM_NSS_CHACHA20_POLY1305 (CKM_NSS + 26)
+
-+typedef struct CK_AEAD_PARAMS {
-+ CK_BYTE_PTR pIv; /* This is the nonce. */
-+ CK_ULONG ulIvLen;
-+ CK_BYTE_PTR pAAD;
-+ CK_ULONG ulAADLen;
-+ CK_ULONG ulTagBits;
-+} CK_AEAD_PARAMS;
++typedef struct CK_NSS_AEAD_PARAMS {
++ CK_BYTE_PTR pIv; /* This is the nonce. */
++ CK_ULONG ulIvLen;
++ CK_BYTE_PTR pAAD;
++ CK_ULONG ulAADLen;
++ CK_ULONG ulTagLen;
++} CK_NSS_AEAD_PARAMS;
+
+#endif
+
@@ -77,18 +77,18 @@ index 8be517c..53c29f0 100644
+ SECItem param;
+ SECStatus rv = SECFailure;
+ unsigned int uOutLen;
-+ CK_AEAD_PARAMS aeadParams;
++ CK_NSS_AEAD_PARAMS aeadParams;
+ static const int tagSize = 16;
+
+ param.type = siBuffer;
+ param.len = sizeof(aeadParams);
+ param.data = (unsigned char *) &aeadParams;
-+ memset(&aeadParams, 0, sizeof(CK_AEAD_PARAMS));
++ memset(&aeadParams, 0, sizeof(aeadParams));
+ aeadParams.pIv = (unsigned char *) additionalData;
+ aeadParams.ulIvLen = 8;
+ aeadParams.pAAD = (unsigned char *) additionalData;
+ aeadParams.ulAADLen = additionalDataLen;
-+ aeadParams.ulTagBits = tagSize * 8;
++ aeadParams.ulTagLen = tagSize;
+
+ if (doDecrypt) {
+ rv = pk11_decrypt(keys->write_key, CKM_NSS_CHACHA20_POLY1305, &param,
diff --git a/chromium/net/third_party/nss/patches/channelid.patch b/chromium/net/third_party/nss/patches/channelid.patch
index 46554f9014f..b2ab19d2831 100644
--- a/chromium/net/third_party/nss/patches/channelid.patch
+++ b/chromium/net/third_party/nss/patches/channelid.patch
@@ -151,7 +151,7 @@ diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
+ spki = SECKEY_EncodeDERSubjectPublicKeyInfo(ss->ssl3.channelIDPub);
+
+ if (spki->len != sizeof(P256_SPKI_PREFIX) + CHANNEL_ID_PUBLIC_KEY_LENGTH ||
-+ memcmp(spki->data, P256_SPKI_PREFIX, sizeof(P256_SPKI_PREFIX) != 0)) {
++ memcmp(spki->data, P256_SPKI_PREFIX, sizeof(P256_SPKI_PREFIX)) != 0) {
+ PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
+ rv = SECFailure;
+ goto loser;
diff --git a/chromium/net/third_party/nss/patches/channelid2.patch b/chromium/net/third_party/nss/patches/channelid2.patch
new file mode 100644
index 00000000000..1425c2a80b0
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/channelid2.patch
@@ -0,0 +1,155 @@
+diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
+index 882e356..396c408 100644
+--- a/nss/lib/ssl/ssl3con.c
++++ b/nss/lib/ssl/ssl3con.c
+@@ -7594,6 +7594,33 @@ ssl3_SendClientSecondRound(sslSocket *ss)
+
+ ssl_ReleaseXmitBufLock(ss); /*******************************/
+
++ if (!ss->ssl3.hs.isResuming &&
++ ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) {
++ /* If we are negotiating ChannelID on a full handshake then we record
++ * the handshake hashes in |sid| at this point. They will be needed in
++ * the event that we resume this session and use ChannelID on the
++ * resumption handshake. */
++ SSL3Hashes hashes;
++ SECItem *originalHandshakeHash =
++ &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
++ PORT_Assert(ss->sec.ci.sid->cached == never_cached);
++
++ ssl_GetSpecReadLock(ss);
++ PORT_Assert(ss->version > SSL_LIBRARY_VERSION_3_0);
++ rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0);
++ ssl_ReleaseSpecReadLock(ss);
++ if (rv != SECSuccess) {
++ return rv;
++ }
++
++ PORT_Assert(originalHandshakeHash->len == 0);
++ originalHandshakeHash->data = PORT_Alloc(hashes.len);
++ if (!originalHandshakeHash->data)
++ return SECFailure;
++ originalHandshakeHash->len = hashes.len;
++ memcpy(originalHandshakeHash->data, hashes.u.raw, hashes.len);
++ }
++
+ if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
+ ss->ssl3.hs.ws = wait_new_session_ticket;
+ else
+@@ -10590,6 +10617,7 @@ static SECStatus
+ ssl3_SendEncryptedExtensions(sslSocket *ss)
+ {
+ static const char CHANNEL_ID_MAGIC[] = "TLS Channel ID signature";
++ static const char CHANNEL_ID_RESUMPTION_MAGIC[] = "Resumption";
+ /* This is the ASN.1 prefix for a P-256 public key. Specifically it's:
+ * SEQUENCE
+ * SEQUENCE
+@@ -10615,7 +10643,10 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
+ SECItem *spki = NULL;
+ SSL3Hashes hashes;
+ const unsigned char *pub_bytes;
+- unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) + sizeof(SSL3Hashes)];
++ unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) +
++ sizeof(CHANNEL_ID_RESUMPTION_MAGIC) +
++ sizeof(SSL3Hashes)*2];
++ size_t signed_data_len;
+ unsigned char digest[SHA256_LENGTH];
+ SECItem digest_item;
+ unsigned char signature[64];
+@@ -10665,11 +10696,26 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
+
+ pub_bytes = spki->data + sizeof(P256_SPKI_PREFIX);
+
+- memcpy(signed_data, CHANNEL_ID_MAGIC, sizeof(CHANNEL_ID_MAGIC));
+- memcpy(signed_data + sizeof(CHANNEL_ID_MAGIC), hashes.u.raw, hashes.len);
++ signed_data_len = 0;
++ memcpy(signed_data + signed_data_len, CHANNEL_ID_MAGIC,
++ sizeof(CHANNEL_ID_MAGIC));
++ signed_data_len += sizeof(CHANNEL_ID_MAGIC);
++ if (ss->ssl3.hs.isResuming) {
++ SECItem *originalHandshakeHash =
++ &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
++ PORT_Assert(originalHandshakeHash->len > 0);
+
+- rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data,
+- sizeof(CHANNEL_ID_MAGIC) + hashes.len);
++ memcpy(signed_data + signed_data_len, CHANNEL_ID_RESUMPTION_MAGIC,
++ sizeof(CHANNEL_ID_RESUMPTION_MAGIC));
++ signed_data_len += sizeof(CHANNEL_ID_RESUMPTION_MAGIC);
++ memcpy(signed_data + signed_data_len, originalHandshakeHash->data,
++ originalHandshakeHash->len);
++ signed_data_len += originalHandshakeHash->len;
++ }
++ memcpy(signed_data + signed_data_len, hashes.u.raw, hashes.len);
++ signed_data_len += hashes.len;
++
++ rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, signed_data_len);
+ if (rv != SECSuccess)
+ goto loser;
+
+diff --git a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
+index 03cf05c..166022c 100644
+--- a/nss/lib/ssl/ssl3ext.c
++++ b/nss/lib/ssl/ssl3ext.c
+@@ -812,6 +812,15 @@ ssl3_ClientSendChannelIDXtn(sslSocket * ss, PRBool append,
+ return 0;
+ }
+
++ if (ss->sec.ci.sid->cached != never_cached &&
++ ss->sec.ci.sid->u.ssl3.originalHandshakeHash.len == 0) {
++ /* We can't do ChannelID on a connection if we're resuming and didn't
++ * do ChannelID on the original connection: without ChannelID on the
++ * original connection we didn't record the handshake hashes needed for
++ * the signature. */
++ return 0;
++ }
++
+ if (append) {
+ SECStatus rv;
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
+diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
+index 9c789bf..ca68727 100644
+--- a/nss/lib/ssl/sslimpl.h
++++ b/nss/lib/ssl/sslimpl.h
+@@ -705,6 +705,14 @@ struct sslSessionIDStr {
+ */
+ NewSessionTicket sessionTicket;
+ SECItem srvName;
++
++ /* originalHandshakeHash contains the hash of the original, full
++ * handshake prior to the server's final flow. This is either a
++ * SHA-1/MD5 combination (for TLS < 1.2) or the TLS PRF hash (for
++ * TLS 1.2). This is recorded and used only when ChannelID is
++ * negotiated as it's used to bind the ChannelID signature on the
++ * resumption handshake to the original handshake. */
++ SECItem originalHandshakeHash;
+ } ssl3;
+ } u;
+ };
+diff --git a/nss/lib/ssl/sslnonce.c b/nss/lib/ssl/sslnonce.c
+index a6f7349..eb5004c 100644
+--- a/nss/lib/ssl/sslnonce.c
++++ b/nss/lib/ssl/sslnonce.c
+@@ -148,6 +148,9 @@ ssl_DestroySID(sslSessionID *sid)
+ if (sid->u.ssl3.srvName.data) {
+ SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE);
+ }
++ if (sid->u.ssl3.originalHandshakeHash.data) {
++ SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE);
++ }
+
+ PORT_ZFree(sid, sizeof(sslSessionID));
+ }
+diff --git a/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h
+index e4d188f..b813c04 100644
+--- a/nss/lib/ssl/sslt.h
++++ b/nss/lib/ssl/sslt.h
+@@ -204,7 +204,7 @@ typedef enum {
+ ssl_app_layer_protocol_xtn = 16,
+ ssl_session_ticket_xtn = 35,
+ ssl_next_proto_nego_xtn = 13172,
+- ssl_channel_id_xtn = 30031,
++ ssl_channel_id_xtn = 30032,
+ ssl_padding_xtn = 35655,
+ ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
+ } SSLExtensionType;
diff --git a/chromium/net/third_party/nss/patches/cipherorder.patch b/chromium/net/third_party/nss/patches/cipherorder.patch
new file mode 100644
index 00000000000..16d4745dcd8
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/cipherorder.patch
@@ -0,0 +1,106 @@
+diff --git a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
+index 4cf02aa..24627ed 100644
+--- a/nss/lib/ssl/ssl.h
++++ b/nss/lib/ssl/ssl.h
+@@ -265,6 +265,13 @@ SSL_IMPORT SECStatus SSL_CipherPrefGetDefault(PRInt32 cipher, PRBool *enabled);
+ SSL_IMPORT SECStatus SSL_CipherPolicySet(PRInt32 cipher, PRInt32 policy);
+ SSL_IMPORT SECStatus SSL_CipherPolicyGet(PRInt32 cipher, PRInt32 *policy);
+
++/* SSL_CipherOrderSet sets the cipher suite preference order from |ciphers|,
++ * which must be an array of cipher suite ids of length |len|. All the given
++ * cipher suite ids must appear in the array that is returned by
++ * |SSL_GetImplementedCiphers| and may only appear once, at most. */
++SSL_IMPORT SECStatus SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers,
++ unsigned int len);
++
+ /* SSLChannelBindingType enumerates the types of supported channel binding
+ * values. See RFC 5929. */
+ typedef enum SSLChannelBindingType {
+diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
+index c2d9eeb..350d09c 100644
+--- a/nss/lib/ssl/ssl3con.c
++++ b/nss/lib/ssl/ssl3con.c
+@@ -12423,6 +12423,46 @@ ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *enabled)
+ return rv;
+ }
+
++SECStatus
++ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *ciphers, unsigned int len)
++{
++ /* |i| iterates over |ciphers| while |done| and |j| iterate over
++ * |ss->cipherSuites|. */
++ unsigned int i, done;
++
++ for (i = done = 0; i < len; i++) {
++ PRUint16 id = ciphers[i];
++ unsigned int existingIndex, j;
++ PRBool found = PR_FALSE;
++
++ for (j = done; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
++ if (ss->cipherSuites[j].cipher_suite == id) {
++ existingIndex = j;
++ found = PR_TRUE;
++ break;
++ }
++ }
++
++ if (!found) {
++ continue;
++ }
++
++ if (existingIndex != done) {
++ const ssl3CipherSuiteCfg temp = ss->cipherSuites[done];
++ ss->cipherSuites[done] = ss->cipherSuites[existingIndex];
++ ss->cipherSuites[existingIndex] = temp;
++ }
++ done++;
++ }
++
++ /* Disable all cipher suites that weren't included. */
++ for (; done < ssl_V3_SUITES_IMPLEMENTED; done++) {
++ ss->cipherSuites[done].enabled = 0;
++ }
++
++ return SECSuccess;
++}
++
+ /* copy global default policy into socket. */
+ void
+ ssl3_InitSocketPolicy(sslSocket *ss)
+diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
+index 1e4655f..7521dba 100644
+--- a/nss/lib/ssl/sslimpl.h
++++ b/nss/lib/ssl/sslimpl.h
+@@ -1711,6 +1711,8 @@ extern SECStatus ssl3_CipherPrefSet(sslSocket *ss, ssl3CipherSuite which, PRBool
+ extern SECStatus ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *on);
+ extern SECStatus ssl2_CipherPrefSet(sslSocket *ss, PRInt32 which, PRBool enabled);
+ extern SECStatus ssl2_CipherPrefGet(sslSocket *ss, PRInt32 which, PRBool *enabled);
++extern SECStatus ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *cipher,
++ unsigned int len);
+
+ extern SECStatus ssl3_SetPolicy(ssl3CipherSuite which, PRInt32 policy);
+ extern SECStatus ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *policy);
+diff --git a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c
+index 965215d..9f8286c 100644
+--- a/nss/lib/ssl/sslsock.c
++++ b/nss/lib/ssl/sslsock.c
+@@ -1344,6 +1344,19 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled)
+ return rv;
+ }
+
++SECStatus
++SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers, unsigned int len)
++{
++ sslSocket *ss = ssl_FindSocket(fd);
++
++ if (!ss) {
++ SSL_DBG(("%d: SSL[%d]: bad socket in CipherOrderSet", SSL_GETPID(),
++ fd));
++ return SECFailure;
++ }
++ return ssl3_CipherOrderSet(ss, ciphers, len);
++}
++
+ SECStatus
+ SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled)
+ {
diff --git a/chromium/net/third_party/nss/patches/disableticketrenewal.patch b/chromium/net/third_party/nss/patches/disableticketrenewal.patch
new file mode 100644
index 00000000000..ec40174bc3f
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/disableticketrenewal.patch
@@ -0,0 +1,17 @@
+Index: net/third_party/nss/ssl/sslnonce.c
+===================================================================
+--- net/third_party/nss/ssl/sslnonce.c (revision 240143)
++++ net/third_party/nss/ssl/sslnonce.c (working copy)
+@@ -438,6 +438,12 @@
+ /* We need to lock the cache, as this sid might already be in the cache. */
+ LOCK_CACHE;
+
++ /* Don't modify sid if it has ever been cached. */
++ if (sid->cached != never_cached) {
++ UNLOCK_CACHE;
++ return SECSuccess;
++ }
++
+ /* A server might have sent us an empty ticket, which has the
+ * effect of clearing the previously known ticket.
+ */
diff --git a/chromium/net/third_party/nss/patches/fallbackscsv.patch b/chromium/net/third_party/nss/patches/fallbackscsv.patch
new file mode 100644
index 00000000000..f8acb2575d8
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/fallbackscsv.patch
@@ -0,0 +1,207 @@
+diff --git a/nss/lib/ssl/SSLerrs.h b/nss/lib/ssl/SSLerrs.h
+index c0d26cc..4ff0b7d 100644
+--- a/nss/lib/ssl/SSLerrs.h
++++ b/nss/lib/ssl/SSLerrs.h
+@@ -421,3 +421,8 @@ ER3(SSL_ERROR_INVALID_CHANNEL_ID_KEY, (SSL_ERROR_BASE + 130),
+
+ ER3(SSL_ERROR_GET_CHANNEL_ID_FAILED, (SSL_ERROR_BASE + 131),
+ "The application could not get a TLS Channel ID.")
++
++ER3(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT, (SSL_ERROR_BASE + 132),
++"The connection was using a lesser TLS version as a result of a previous"
++" handshake failure, but the server indicated that it should not have been"
++" needed.")
+diff --git a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
+index 24627ed..067938c 100644
+--- a/nss/lib/ssl/ssl.h
++++ b/nss/lib/ssl/ssl.h
+@@ -163,6 +163,8 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
+ #define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */
+ /* Request Signed Certificate Timestamps via TLS extension (client) */
+ #define SSL_ENABLE_SIGNED_CERT_TIMESTAMPS 25
++#define SSL_ENABLE_FALLBACK_SCSV 26 /* Send fallback SCSV in
++ * handshakes. */
+
+ #ifdef SSL_DEPRECATED_FUNCTION
+ /* Old deprecated function names */
+diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
+index cf7ef32..946f780 100644
+--- a/nss/lib/ssl/ssl3con.c
++++ b/nss/lib/ssl/ssl3con.c
+@@ -3469,6 +3469,9 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf)
+ case certificate_unknown: error = SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT;
+ break;
+ case illegal_parameter: error = SSL_ERROR_ILLEGAL_PARAMETER_ALERT;break;
++ case inappropriate_fallback:
++ error = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT;
++ break;
+
+ /* All alerts below are TLS only. */
+ case unknown_ca: error = SSL_ERROR_UNKNOWN_CA_ALERT; break;
+@@ -4973,7 +4976,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
+ int num_suites;
+ int actual_count = 0;
+ PRBool isTLS = PR_FALSE;
+- PRBool requestingResume = PR_FALSE;
++ PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE;
+ PRInt32 total_exten_len = 0;
+ unsigned paddingExtensionLen;
+ unsigned numCompressionMethods;
+@@ -5223,8 +5226,15 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
+ num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE);
+ if (!num_suites)
+ return SECFailure; /* count_cipher_suites has set error code. */
++
++ fallbackSCSV = ss->opt.enableFallbackSCSV && (!requestingResume ||
++ ss->version < sid->version);
++ /* make room for SCSV */
+ if (ss->ssl3.hs.sendingSCSV) {
+- ++num_suites; /* make room for SCSV */
++ ++num_suites;
++ }
++ if (fallbackSCSV) {
++ ++num_suites;
+ }
+
+ /* count compression methods */
+@@ -5322,6 +5332,14 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
+ }
+ actual_count++;
+ }
++ if (fallbackSCSV) {
++ rv = ssl3_AppendHandshakeNumber(ss, TLS_FALLBACK_SCSV,
++ sizeof(ssl3CipherSuite));
++ if (rv != SECSuccess) {
++ return rv; /* err set by ssl3_AppendHandshake* */
++ }
++ actual_count++;
++ }
+ for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
+ ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
+ if (config_match(suite, ss->ssl3.policy, PR_TRUE, &ss->vrange)) {
+@@ -8037,6 +8055,19 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+ goto loser; /* malformed */
+ }
+
++ /* If the ClientHello version is less than our maximum version, check for a
++ * TLS_FALLBACK_SCSV and reject the connection if found. */
++ if (ss->vrange.max > ss->clientHelloVersion) {
++ for (i = 0; i + 1 < suites.len; i += 2) {
++ PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
++ if (suite_i != TLS_FALLBACK_SCSV)
++ continue;
++ desc = inappropriate_fallback;
++ errCode = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT;
++ goto alert_loser;
++ }
++ }
++
+ /* grab the list of compression methods. */
+ rv = ssl3_ConsumeHandshakeVariable(ss, &comps, 1, &b, &length);
+ if (rv != SECSuccess) {
+diff --git a/nss/lib/ssl/ssl3prot.h b/nss/lib/ssl/ssl3prot.h
+index 0eab970..4c19ade 100644
+--- a/nss/lib/ssl/ssl3prot.h
++++ b/nss/lib/ssl/ssl3prot.h
+@@ -98,6 +98,7 @@ typedef enum {
+ protocol_version = 70,
+ insufficient_security = 71,
+ internal_error = 80,
++ inappropriate_fallback = 86, /* could also be sent for SSLv3 */
+ user_canceled = 90,
+ no_renegotiation = 100,
+
+diff --git a/nss/lib/ssl/sslerr.h b/nss/lib/ssl/sslerr.h
+index 5a949c9..82ae7df 100644
+--- a/nss/lib/ssl/sslerr.h
++++ b/nss/lib/ssl/sslerr.h
+@@ -196,6 +196,7 @@ SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 128),
+ SSL_ERROR_BAD_CHANNEL_ID_DATA = (SSL_ERROR_BASE + 129),
+ SSL_ERROR_INVALID_CHANNEL_ID_KEY = (SSL_ERROR_BASE + 130),
+ SSL_ERROR_GET_CHANNEL_ID_FAILED = (SSL_ERROR_BASE + 131),
++SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT = (SSL_ERROR_BASE + 132),
+
+ SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
+ } SSLErrorCodes;
+diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
+index 7521dba..6d0bc15 100644
+--- a/nss/lib/ssl/sslimpl.h
++++ b/nss/lib/ssl/sslimpl.h
+@@ -336,6 +336,7 @@ typedef struct sslOptionsStr {
+ unsigned int cbcRandomIV : 1; /* 24 */
+ unsigned int enableOCSPStapling : 1; /* 25 */
+ unsigned int enableSignedCertTimestamps : 1; /* 26 */
++ unsigned int enableFallbackSCSV : 1; /* 27 */
+ } sslOptions;
+
+ typedef enum { sslHandshakingUndetermined = 0,
+diff --git a/nss/lib/ssl/sslproto.h b/nss/lib/ssl/sslproto.h
+index 6b60a28..621ef37 100644
+--- a/nss/lib/ssl/sslproto.h
++++ b/nss/lib/ssl/sslproto.h
+@@ -172,6 +172,11 @@
+ */
+ #define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF
+
++/* TLS_FALLBACK_SCSV is a signaling cipher suite value that indicates that a
++ * handshake is the result of TLS version fallback. This value is not IANA
++ * assigned. */
++#define TLS_FALLBACK_SCSV 0x5600
++
+ /* Cipher Suite Values starting with 0xC000 are defined in informational
+ * RFCs.
+ */
+diff --git a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c
+index 9f8286c..f7d44d4 100644
+--- a/nss/lib/ssl/sslsock.c
++++ b/nss/lib/ssl/sslsock.c
+@@ -174,7 +174,8 @@ static sslOptions ssl_defaults = {
+ PR_FALSE, /* enableFalseStart */
+ PR_TRUE, /* cbcRandomIV */
+ PR_FALSE, /* enableOCSPStapling */
+- PR_FALSE /* enableSignedCertTimestamps */
++ PR_FALSE, /* enableSignedCertTimestamps */
++ PR_FALSE /* enableFallbackSCSV */
+ };
+
+ /*
+@@ -870,6 +871,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
+ ss->opt.enableSignedCertTimestamps = on;
+ break;
+
++ case SSL_ENABLE_FALLBACK_SCSV:
++ ss->opt.enableFallbackSCSV = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+@@ -943,6 +948,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ on = ss->opt.enableSignedCertTimestamps;
+ break;
++ case SSL_ENABLE_FALLBACK_SCSV: on = ss->opt.enableFallbackSCSV; break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -1007,6 +1013,9 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ on = ssl_defaults.enableSignedCertTimestamps;
+ break;
++ case SSL_ENABLE_FALLBACK_SCSV:
++ on = ssl_defaults.enableFallbackSCSV;
++ break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -1178,6 +1187,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
+ ssl_defaults.enableSignedCertTimestamps = on;
+ break;
+
++ case SSL_ENABLE_FALLBACK_SCSV:
++ ssl_defaults.enableFallbackSCSV = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
diff --git a/chromium/net/third_party/nss/patches/paddingextension.patch b/chromium/net/third_party/nss/patches/paddingextension.patch
new file mode 100644
index 00000000000..966c4903b21
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/paddingextension.patch
@@ -0,0 +1,142 @@
+diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
+index 8b8b758..882e356 100644
+--- a/nss/lib/ssl/ssl3con.c
++++ b/nss/lib/ssl/ssl3con.c
+@@ -4975,6 +4975,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
+ PRBool isTLS = PR_FALSE;
+ PRBool requestingResume = PR_FALSE;
+ PRInt32 total_exten_len = 0;
++ unsigned paddingExtensionLen;
+ unsigned numCompressionMethods;
+ PRInt32 flags;
+
+@@ -5241,6 +5242,20 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
+ length += 1 + ss->ssl3.hs.cookieLen;
+ }
+
++ /* A padding extension may be included to ensure that the record containing
++ * the ClientHello doesn't have a length between 256 and 511 bytes
++ * (inclusive). Initial, ClientHello records with such lengths trigger bugs
++ * in F5 devices.
++ *
++ * This is not done for DTLS nor for renegotiation. */
++ if (!IS_DTLS(ss) && isTLS && !ss->firstHsDone) {
++ paddingExtensionLen = ssl3_CalculatePaddingExtensionLength(length);
++ total_exten_len += paddingExtensionLen;
++ length += paddingExtensionLen;
++ } else {
++ paddingExtensionLen = 0;
++ }
++
+ rv = ssl3_AppendHandshakeHeader(ss, client_hello, length);
+ if (rv != SECSuccess) {
+ return rv; /* err set by ssl3_AppendHandshake* */
+@@ -5360,6 +5375,13 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
+ return SECFailure;
+ }
+ maxBytes -= extLen;
++
++ extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes);
++ if (extLen < 0) {
++ return SECFailure;
++ }
++ maxBytes -= extLen;
++
+ PORT_Assert(!maxBytes);
+ }
+ if (ss->ssl3.hs.sendingSCSV) {
+diff --git a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
+index 0415770..cdebcc9 100644
+--- a/nss/lib/ssl/ssl3ext.c
++++ b/nss/lib/ssl/ssl3ext.c
+@@ -2297,3 +2297,56 @@ ssl3_ClientSendSigAlgsXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
+ loser:
+ return -1;
+ }
++
++unsigned int
++ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength)
++{
++ unsigned int recordLength = 1 /* handshake message type */ +
++ 3 /* handshake message length */ +
++ clientHelloLength;
++ unsigned int extensionLength;
++
++ if (recordLength < 256 || recordLength >= 512) {
++ return 0;
++ }
++
++ extensionLength = 512 - recordLength;
++ /* Extensions take at least four bytes to encode. */
++ if (extensionLength < 4) {
++ extensionLength = 4;
++ }
++
++ return extensionLength;
++}
++
++/* ssl3_AppendPaddingExtension possibly adds an extension which ensures that a
++ * ClientHello record is either < 256 bytes or is >= 512 bytes. This ensures
++ * that we don't trigger bugs in F5 products. */
++PRInt32
++ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
++ PRUint32 maxBytes)
++{
++ unsigned int paddingLen = extensionLen - 4;
++ unsigned char padding[256];
++
++ if (extensionLen == 0) {
++ return 0;
++ }
++
++ if (extensionLen < 4 ||
++ extensionLen > maxBytes ||
++ paddingLen > sizeof(padding)) {
++ PORT_Assert(0);
++ return -1;
++ }
++
++ if (SECSuccess != ssl3_AppendHandshakeNumber(ss, ssl_padding_xtn, 2))
++ return -1;
++ if (SECSuccess != ssl3_AppendHandshakeNumber(ss, paddingLen, 2))
++ return -1;
++ memset(padding, 0, paddingLen);
++ if (SECSuccess != ssl3_AppendHandshake(ss, padding, paddingLen))
++ return -1;
++
++ return extensionLen;
++}
+diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
+index 614eed1..9c789bf 100644
+--- a/nss/lib/ssl/sslimpl.h
++++ b/nss/lib/ssl/sslimpl.h
+@@ -237,6 +237,13 @@ extern PRInt32
+ ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
+ const ssl3HelloExtensionSender *sender);
+
++extern unsigned int
++ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength);
++
++extern PRInt32
++ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
++ PRUint32 maxBytes);
++
+ /* Socket ops */
+ struct sslSocketOpsStr {
+ int (*connect) (sslSocket *, const PRNetAddr *);
+diff --git a/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h
+index a8007d8..e4d188f 100644
+--- a/nss/lib/ssl/sslt.h
++++ b/nss/lib/ssl/sslt.h
+@@ -205,9 +205,10 @@ typedef enum {
+ ssl_session_ticket_xtn = 35,
+ ssl_next_proto_nego_xtn = 13172,
+ ssl_channel_id_xtn = 30031,
++ ssl_padding_xtn = 35655,
+ ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
+ } SSLExtensionType;
+
+-#define SSL_MAX_EXTENSIONS 11
++#define SSL_MAX_EXTENSIONS 11 /* doesn't include ssl_padding_xtn. */
+
+ #endif /* __sslt_h_ */
diff --git a/chromium/net/third_party/nss/patches/paddingextensionall.patch b/chromium/net/third_party/nss/patches/paddingextensionall.patch
new file mode 100644
index 00000000000..f226aacaf68
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/paddingextensionall.patch
@@ -0,0 +1,26 @@
+diff --git a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
+index cdebcc9..03cf05c 100644
+--- a/nss/lib/ssl/ssl3ext.c
++++ b/nss/lib/ssl/ssl3ext.c
+@@ -2306,7 +2306,11 @@ ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength)
+ clientHelloLength;
+ unsigned int extensionLength;
+
+- if (recordLength < 256 || recordLength >= 512) {
++ /* This condition should be:
++ * if (recordLength < 256 || recordLength >= 512) {
++ * It has been changed, temporarily, to test whether 512 byte ClientHellos
++ * are a compatibility problem. */
++ if (recordLength >= 512) {
+ return 0;
+ }
+
+@@ -2327,7 +2331,7 @@ ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
+ PRUint32 maxBytes)
+ {
+ unsigned int paddingLen = extensionLen - 4;
+- unsigned char padding[256];
++ unsigned char padding[512];
+
+ if (extensionLen == 0) {
+ return 0;
diff --git a/chromium/net/third_party/nss/patches/sessioncache.patch b/chromium/net/third_party/nss/patches/sessioncache.patch
new file mode 100644
index 00000000000..11fd9fc8e2c
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/sessioncache.patch
@@ -0,0 +1,100 @@
+diff --git a/net/third_party/nss/ssl/exports_win.def b/net/third_party/nss/ssl/exports_win.def
+index e0624f1..a1045bb 100644
+--- a/net/third_party/nss/ssl/exports_win.def
++++ b/net/third_party/nss/ssl/exports_win.def
+@@ -62,3 +62,5 @@ SSL_RestartHandshakeAfterChannelIDReq
+ SSL_GetChannelBinding
+ SSL_PeerSignedCertTimestamps
+ SSL_CipherOrderSet
++SSL_CacheSession
++SSL_CacheSessionUnlocked
+diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h
+index bef33fc..6f7c988 100644
+--- a/net/third_party/nss/ssl/ssl.h
++++ b/net/third_party/nss/ssl/ssl.h
+@@ -872,6 +872,18 @@ SSL_IMPORT int SSL_DataPending(PRFileDesc *fd);
+ SSL_IMPORT SECStatus SSL_InvalidateSession(PRFileDesc *fd);
+
+ /*
++** Cache the SSL session associated with fd, if it has not already been cached.
++*/
++SSL_IMPORT SECStatus SSL_CacheSession(PRFileDesc *fd);
++
++/*
++** Cache the SSL session associated with fd, if it has not already been cached.
++** This function may only be called when processing within a callback assigned
++** via SSL_HandshakeCallback
++*/
++SSL_IMPORT SECStatus SSL_CacheSessionUnlocked(PRFileDesc *fd);
++
++/*
+ ** Return a SECItem containing the SSL session ID associated with the fd.
+ */
+ SSL_IMPORT SECItem *SSL_GetSessionID(PRFileDesc *fd);
+diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
+index 307a0fe..e2be5e6 100644
+--- a/net/third_party/nss/ssl/ssl3con.c
++++ b/net/third_party/nss/ssl/ssl3con.c
+@@ -11240,7 +11240,7 @@ ssl3_FinishHandshake(sslSocket * ss)
+ /* The first handshake is now completed. */
+ ss->handshake = NULL;
+
+- if (ss->ssl3.hs.cacheSID) {
++ if (ss->ssl3.hs.cacheSID && ss->sec.isServer) {
+ (*ss->sec.cache)(ss->sec.ci.sid);
+ ss->ssl3.hs.cacheSID = PR_FALSE;
+ }
+diff --git a/net/third_party/nss/ssl/sslsecur.c b/net/third_party/nss/ssl/sslsecur.c
+index 31c343f..99538e5 100644
+--- a/net/third_party/nss/ssl/sslsecur.c
++++ b/net/third_party/nss/ssl/sslsecur.c
+@@ -1474,6 +1474,49 @@ SSL_InvalidateSession(PRFileDesc *fd)
+ return rv;
+ }
+
++static void
++ssl3_CacheSessionUnlocked(sslSocket *ss)
++{
++ PORT_Assert(!ss->sec.isServer);
++
++ if (ss->ssl3.hs.cacheSID) {
++ ss->sec.cache(ss->sec.ci.sid);
++ ss->ssl3.hs.cacheSID = PR_FALSE;
++ }
++}
++
++SECStatus
++SSL_CacheSession(PRFileDesc *fd)
++{
++ sslSocket * ss = ssl_FindSocket(fd);
++ SECStatus rv = SECFailure;
++
++ if (ss) {
++ ssl_Get1stHandshakeLock(ss);
++ ssl_GetSSL3HandshakeLock(ss);
++
++ ssl3_CacheSessionUnlocked(ss);
++ rv = SECSuccess;
++
++ ssl_ReleaseSSL3HandshakeLock(ss);
++ ssl_Release1stHandshakeLock(ss);
++ }
++ return rv;
++}
++
++SECStatus
++SSL_CacheSessionUnlocked(PRFileDesc *fd)
++{
++ sslSocket * ss = ssl_FindSocket(fd);
++ SECStatus rv = SECFailure;
++
++ if (ss) {
++ ssl3_CacheSessionUnlocked(ss);
++ rv = SECSuccess;
++ }
++ return rv;
++}
++
+ SECItem *
+ SSL_GetSessionID(PRFileDesc *fd)
+ {
diff --git a/chromium/net/third_party/nss/patches/signedcertificatetimestamps.patch b/chromium/net/third_party/nss/patches/signedcertificatetimestamps.patch
new file mode 100644
index 00000000000..8ac3079f19f
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/signedcertificatetimestamps.patch
@@ -0,0 +1,421 @@
+diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h
+index 67cc3a7..4cf02aa 100644
+--- a/net/third_party/nss/ssl/ssl.h
++++ b/net/third_party/nss/ssl/ssl.h
+@@ -161,6 +161,8 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
+ */
+ #define SSL_CBC_RANDOM_IV 23
+ #define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */
++/* Request Signed Certificate Timestamps via TLS extension (client) */
++#define SSL_ENABLE_SIGNED_CERT_TIMESTAMPS 25
+
+ #ifdef SSL_DEPRECATED_FUNCTION
+ /* Old deprecated function names */
+@@ -464,6 +466,23 @@ SSL_IMPORT CERTCertList *SSL_PeerCertificateChain(PRFileDesc *fd);
+ */
+ SSL_IMPORT const SECItemArray * SSL_PeerStapledOCSPResponses(PRFileDesc *fd);
+
++/* SSL_PeerSignedCertTimestamps returns the signed_certificate_timestamp
++ * extension data provided by the TLS server. The return value is a pointer
++ * to an internal SECItem that contains the returned response (as a serialized
++ * SignedCertificateTimestampList, see RFC 6962). The returned pointer is only
++ * valid until the callback function that calls SSL_PeerSignedCertTimestamps
++ * (e.g. the authenticate certificate hook, or the handshake callback) returns.
++ *
++ * If no Signed Certificate Timestamps were given by the server then the result
++ * will be empty. If there was an error, then the result will be NULL.
++ *
++ * You must set the SSL_ENABLE_SIGNED_CERT_TIMESTAMPS option to indicate support
++ * for Signed Certificate Timestamps to a server.
++ *
++ * libssl does not do any parsing or validation of the response itself.
++ */
++SSL_IMPORT const SECItem * SSL_PeerSignedCertTimestamps(PRFileDesc *fd);
++
+ /* SSL_SetStapledOCSPResponses stores an array of one or multiple OCSP responses
+ * in the fd's data, which may be sent as part of a server side cert_status
+ * handshake message. Parameter |responses| is for the server certificate of
+diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
+index 0f1eea4..c2d9eeb 100644
+--- a/net/third_party/nss/ssl/ssl3con.c
++++ b/net/third_party/nss/ssl/ssl3con.c
+@@ -6639,10 +6639,22 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+ sid->u.ssl3.sessionIDLength = sidBytes.len;
+ PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len);
+
++ /* Copy Signed Certificate Timestamps, if any. */
++ if (ss->xtnData.signedCertTimestamps.data) {
++ rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.signedCertTimestamps,
++ &ss->xtnData.signedCertTimestamps);
++ if (rv != SECSuccess)
++ goto loser;
++ }
++
+ ss->ssl3.hs.isResuming = PR_FALSE;
+ ss->ssl3.hs.ws = wait_server_cert;
+
+ winner:
++ /* Clean up the temporary pointer to the handshake buffer. */
++ ss->xtnData.signedCertTimestamps.data = NULL;
++ ss->xtnData.signedCertTimestamps.len = 0;
++
+ /* If we will need a ChannelID key then we make the callback now. This
+ * allows the handshake to be restarted cleanly if the callback returns
+ * SECWouldBlock. */
+@@ -6668,6 +6680,9 @@ alert_loser:
+ (void)SSL3_SendAlert(ss, alert_fatal, desc);
+
+ loser:
++ /* Clean up the temporary pointer to the handshake buffer. */
++ ss->xtnData.signedCertTimestamps.data = NULL;
++ ss->xtnData.signedCertTimestamps.len = 0;
+ errCode = ssl_MapLowLevelError(errCode);
+ return SECFailure;
+ }
+diff --git a/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c
+index adb81ed..02e104d 100644
+--- a/net/third_party/nss/ssl/ssl3ext.c
++++ b/net/third_party/nss/ssl/ssl3ext.c
+@@ -81,6 +81,12 @@ static PRInt32 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append,
+ PRUint32 maxBytes);
+ static SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type,
+ SECItem *data);
++static PRInt32 ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss,
++ PRBool append,
++ PRUint32 maxBytes);
++static SECStatus ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss,
++ PRUint16 ex_type,
++ SECItem *data);
+
+ /*
+ * Write bytes. Using this function means the SECItem structure
+@@ -259,6 +265,8 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
+ { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn },
+ { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
+ { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
++ { ssl_signed_certificate_timestamp_xtn,
++ &ssl3_ClientHandleSignedCertTimestampXtn },
+ { -1, NULL }
+ };
+
+@@ -287,7 +295,9 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
+ { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn },
+ { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
+ { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
+- { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
++ { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
++ { ssl_signed_certificate_timestamp_xtn,
++ &ssl3_ClientSendSignedCertTimestampXtn }
+ /* any extra entries will appear as { 0, NULL } */
+ };
+
+@@ -2364,3 +2374,65 @@ ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
+
+ return extensionLen;
+ }
++
++/* ssl3_ClientSendSignedCertTimestampXtn sends the signed_certificate_timestamp
++ * extension for TLS ClientHellos. */
++static PRInt32
++ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, PRBool append,
++ PRUint32 maxBytes)
++{
++ PRInt32 extension_length = 2 /* extension_type */ +
++ 2 /* length(extension_data) */;
++
++ /* Only send the extension if processing is enabled. */
++ if (!ss->opt.enableSignedCertTimestamps)
++ return 0;
++
++ if (append && maxBytes >= extension_length) {
++ SECStatus rv;
++ /* extension_type */
++ rv = ssl3_AppendHandshakeNumber(ss,
++ ssl_signed_certificate_timestamp_xtn,
++ 2);
++ if (rv != SECSuccess)
++ goto loser;
++ /* zero length */
++ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
++ if (rv != SECSuccess)
++ goto loser;
++ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
++ ssl_signed_certificate_timestamp_xtn;
++ } else if (maxBytes < extension_length) {
++ PORT_Assert(0);
++ return 0;
++ }
++
++ return extension_length;
++loser:
++ return -1;
++}
++
++static SECStatus
++ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type,
++ SECItem *data)
++{
++ /* We do not yet know whether we'll be resuming a session or creating
++ * a new one, so we keep a pointer to the data in the TLSExtensionData
++ * structure. This pointer is only valid in the scope of
++ * ssl3_HandleServerHello, and, if not resuming a session, the data is
++ * copied once a new session structure has been set up.
++ * All parsing is currently left to the application and we accept
++ * everything, including empty data.
++ */
++ SECItem *scts = &ss->xtnData.signedCertTimestamps;
++ PORT_Assert(!scts->data && !scts->len);
++
++ if (!data->len) {
++ /* Empty extension data: RFC 6962 mandates non-empty contents. */
++ return SECFailure;
++ }
++ *scts = *data;
++ /* Keep track of negotiated extensions. */
++ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
++ return SECSuccess;
++}
+diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h
+index 79aca60..1e4655f 100644
+--- a/net/third_party/nss/ssl/sslimpl.h
++++ b/net/third_party/nss/ssl/sslimpl.h
+@@ -312,29 +312,30 @@ typedef struct sslOptionsStr {
+ * list of supported protocols. */
+ SECItem nextProtoNego;
+
+- unsigned int useSecurity : 1; /* 1 */
+- unsigned int useSocks : 1; /* 2 */
+- unsigned int requestCertificate : 1; /* 3 */
+- unsigned int requireCertificate : 2; /* 4-5 */
+- unsigned int handshakeAsClient : 1; /* 6 */
+- unsigned int handshakeAsServer : 1; /* 7 */
+- unsigned int enableSSL2 : 1; /* 8 */
+- unsigned int unusedBit9 : 1; /* 9 */
+- unsigned int unusedBit10 : 1; /* 10 */
+- unsigned int noCache : 1; /* 11 */
+- unsigned int fdx : 1; /* 12 */
+- unsigned int v2CompatibleHello : 1; /* 13 */
+- unsigned int detectRollBack : 1; /* 14 */
+- unsigned int noStepDown : 1; /* 15 */
+- unsigned int bypassPKCS11 : 1; /* 16 */
+- unsigned int noLocks : 1; /* 17 */
+- unsigned int enableSessionTickets : 1; /* 18 */
+- unsigned int enableDeflate : 1; /* 19 */
+- unsigned int enableRenegotiation : 2; /* 20-21 */
+- unsigned int requireSafeNegotiation : 1; /* 22 */
+- unsigned int enableFalseStart : 1; /* 23 */
+- unsigned int cbcRandomIV : 1; /* 24 */
+- unsigned int enableOCSPStapling : 1; /* 25 */
++ unsigned int useSecurity : 1; /* 1 */
++ unsigned int useSocks : 1; /* 2 */
++ unsigned int requestCertificate : 1; /* 3 */
++ unsigned int requireCertificate : 2; /* 4-5 */
++ unsigned int handshakeAsClient : 1; /* 6 */
++ unsigned int handshakeAsServer : 1; /* 7 */
++ unsigned int enableSSL2 : 1; /* 8 */
++ unsigned int unusedBit9 : 1; /* 9 */
++ unsigned int unusedBit10 : 1; /* 10 */
++ unsigned int noCache : 1; /* 11 */
++ unsigned int fdx : 1; /* 12 */
++ unsigned int v2CompatibleHello : 1; /* 13 */
++ unsigned int detectRollBack : 1; /* 14 */
++ unsigned int noStepDown : 1; /* 15 */
++ unsigned int bypassPKCS11 : 1; /* 16 */
++ unsigned int noLocks : 1; /* 17 */
++ unsigned int enableSessionTickets : 1; /* 18 */
++ unsigned int enableDeflate : 1; /* 19 */
++ unsigned int enableRenegotiation : 2; /* 20-21 */
++ unsigned int requireSafeNegotiation : 1; /* 22 */
++ unsigned int enableFalseStart : 1; /* 23 */
++ unsigned int cbcRandomIV : 1; /* 24 */
++ unsigned int enableOCSPStapling : 1; /* 25 */
++ unsigned int enableSignedCertTimestamps : 1; /* 26 */
+ } sslOptions;
+
+ typedef enum { sslHandshakingUndetermined = 0,
+@@ -713,6 +714,11 @@ struct sslSessionIDStr {
+ * negotiated as it's used to bind the ChannelID signature on the
+ * resumption handshake to the original handshake. */
+ SECItem originalHandshakeHash;
++
++ /* Signed certificate timestamps received in a TLS extension.
++ ** (used only in client).
++ */
++ SECItem signedCertTimestamps;
+ } ssl3;
+ } u;
+ };
+@@ -804,6 +810,18 @@ struct TLSExtensionDataStr {
+ * is beyond ssl3_HandleClientHello function. */
+ SECItem *sniNameArr;
+ PRUint32 sniNameArrSize;
++
++ /* Signed Certificate Timestamps extracted from the TLS extension.
++ * (client only).
++ * This container holds a temporary pointer to the extension data,
++ * until a session structure (the sec.ci.sid of an sslSocket) is setup
++ * that can hold a permanent copy of the data
++ * (in sec.ci.sid.u.ssl3.signedCertTimestamps).
++ * The data pointed to by this structure is neither explicitly allocated
++ * nor copied: the pointer points to the handshake message buffer and is
++ * only valid in the scope of ssl3_HandleServerHello.
++ */
++ SECItem signedCertTimestamps;
+ };
+
+ typedef SECStatus (*sslRestartTarget)(sslSocket *);
+diff --git a/net/third_party/nss/ssl/sslnonce.c b/net/third_party/nss/ssl/sslnonce.c
+index eb5004c..1ca19ca 100644
+--- a/net/third_party/nss/ssl/sslnonce.c
++++ b/net/third_party/nss/ssl/sslnonce.c
+@@ -122,7 +122,21 @@ ssl_DestroySID(sslSessionID *sid)
+ if (sid->version < SSL_LIBRARY_VERSION_3_0) {
+ SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE);
+ SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE);
++ } else {
++ if (sid->u.ssl3.sessionTicket.ticket.data) {
++ SECITEM_FreeItem(&sid->u.ssl3.sessionTicket.ticket, PR_FALSE);
++ }
++ if (sid->u.ssl3.srvName.data) {
++ SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE);
++ }
++ if (sid->u.ssl3.signedCertTimestamps.data) {
++ SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE);
++ }
++ if (sid->u.ssl3.originalHandshakeHash.data) {
++ SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE);
++ }
+ }
++
+ if (sid->peerID != NULL)
+ PORT_Free((void *)sid->peerID); /* CONST */
+
+@@ -142,16 +156,7 @@ ssl_DestroySID(sslSessionID *sid)
+ if ( sid->localCert ) {
+ CERT_DestroyCertificate(sid->localCert);
+ }
+- if (sid->u.ssl3.sessionTicket.ticket.data) {
+- SECITEM_FreeItem(&sid->u.ssl3.sessionTicket.ticket, PR_FALSE);
+- }
+- if (sid->u.ssl3.srvName.data) {
+- SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE);
+- }
+- if (sid->u.ssl3.originalHandshakeHash.data) {
+- SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE);
+- }
+-
++
+ PORT_ZFree(sid, sizeof(sslSessionID));
+ }
+
+diff --git a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock.c
+index b5c17f0..965215d 100644
+--- a/net/third_party/nss/ssl/sslsock.c
++++ b/net/third_party/nss/ssl/sslsock.c
+@@ -173,7 +173,8 @@ static sslOptions ssl_defaults = {
+ PR_FALSE, /* requireSafeNegotiation */
+ PR_FALSE, /* enableFalseStart */
+ PR_TRUE, /* cbcRandomIV */
+- PR_FALSE /* enableOCSPStapling */
++ PR_FALSE, /* enableOCSPStapling */
++ PR_FALSE /* enableSignedCertTimestamps */
+ };
+
+ /*
+@@ -865,6 +866,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
+ ss->opt.enableOCSPStapling = on;
+ break;
+
++ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
++ ss->opt.enableSignedCertTimestamps = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+@@ -935,6 +940,9 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
+ case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break;
+ case SSL_CBC_RANDOM_IV: on = ss->opt.cbcRandomIV; break;
+ case SSL_ENABLE_OCSP_STAPLING: on = ss->opt.enableOCSPStapling; break;
++ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
++ on = ss->opt.enableSignedCertTimestamps;
++ break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -996,6 +1004,9 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
+ case SSL_ENABLE_OCSP_STAPLING:
+ on = ssl_defaults.enableOCSPStapling;
+ break;
++ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
++ on = ssl_defaults.enableSignedCertTimestamps;
++ break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -1163,6 +1174,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
+ ssl_defaults.enableOCSPStapling = on;
+ break;
+
++ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
++ ssl_defaults.enableSignedCertTimestamps = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+@@ -1993,6 +2008,29 @@ SSL_PeerStapledOCSPResponses(PRFileDesc *fd)
+ return &ss->sec.ci.sid->peerCertStatus;
+ }
+
++const SECItem *
++SSL_PeerSignedCertTimestamps(PRFileDesc *fd)
++{
++ sslSocket *ss = ssl_FindSocket(fd);
++
++ if (!ss) {
++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerSignedCertTimestamps",
++ SSL_GETPID(), fd));
++ return NULL;
++ }
++
++ if (!ss->sec.ci.sid) {
++ PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
++ return NULL;
++ }
++
++ if (ss->sec.ci.sid->version < SSL_LIBRARY_VERSION_3_0) {
++ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
++ return NULL;
++ }
++ return &ss->sec.ci.sid->u.ssl3.signedCertTimestamps;
++}
++
+ SECStatus
+ SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed) {
+ sslSocket *ss = ssl_FindSocket(fd);
+@@ -3133,4 +3171,3 @@ loser:
+ }
+ return ss;
+ }
+-
+diff --git a/net/third_party/nss/ssl/sslt.h b/net/third_party/nss/ssl/sslt.h
+index b813c04..1f5e2c6 100644
+--- a/net/third_party/nss/ssl/sslt.h
++++ b/net/third_party/nss/ssl/sslt.h
+@@ -202,6 +202,7 @@ typedef enum {
+ ssl_signature_algorithms_xtn = 13,
+ ssl_use_srtp_xtn = 14,
+ ssl_app_layer_protocol_xtn = 16,
++ ssl_signed_certificate_timestamp_xtn = 18, /* RFC 6962 */
+ ssl_session_ticket_xtn = 35,
+ ssl_next_proto_nego_xtn = 13172,
+ ssl_channel_id_xtn = 30032,
+@@ -209,6 +210,6 @@ typedef enum {
+ ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
+ } SSLExtensionType;
+
+-#define SSL_MAX_EXTENSIONS 11 /* doesn't include ssl_padding_xtn. */
++#define SSL_MAX_EXTENSIONS 12 /* doesn't include ssl_padding_xtn. */
+
+ #endif /* __sslt_h_ */
diff --git a/chromium/net/third_party/nss/patches/sslnoncestatics.patch b/chromium/net/third_party/nss/patches/sslnoncestatics.patch
new file mode 100644
index 00000000000..336fe1d5587
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/sslnoncestatics.patch
@@ -0,0 +1,15 @@
+diff --git a/net/third_party/nss/ssl/sslnonce.c b/net/third_party/nss/ssl/sslnonce.c
+index 758aa4e..a3e6e0a 100644
+--- a/net/third_party/nss/ssl/sslnonce.c
++++ b/net/third_party/nss/ssl/sslnonce.c
+@@ -21,8 +21,8 @@
+ PRUint32 ssl_sid_timeout = 100;
+ PRUint32 ssl3_sid_timeout = 86400L; /* 24 hours */
+
+-static sslSessionID *cache = NULL;
+-static PZLock * cacheLock = NULL;
++sslSessionID *cache = NULL;
++PZLock * cacheLock = NULL;
+
+ /* sids can be in one of 4 states:
+ *
diff --git a/chromium/net/third_party/nss/patches/tls12backuphash2.patch b/chromium/net/third_party/nss/patches/tls12backuphash2.patch
new file mode 100644
index 00000000000..85e5308db6b
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/tls12backuphash2.patch
@@ -0,0 +1,127 @@
+diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
+index 06992e0..cf7ef32 100644
+--- a/net/third_party/nss/ssl/ssl3con.c
++++ b/net/third_party/nss/ssl/ssl3con.c
+@@ -6973,14 +6973,27 @@ no_memory: /* no-memory error has already been set. */
+
+
+ /*
+- * Returns true if the client authentication key is an RSA or DSA key that
+- * may be able to sign only SHA-1 hashes.
++ * Returns the TLS signature algorithm for the client authentication key and
++ * whether it is an RSA or DSA key that may be able to sign only SHA-1 hashes.
+ */
+-static PRBool
+-ssl3_ClientKeyPrefersSHA1(sslSocket *ss)
++static SECStatus
++ssl3_ExtractClientKeyInfo(sslSocket *ss,
++ TLSSignatureAlgorithm *sigAlg,
++ PRBool *preferSha1)
+ {
++ SECStatus rv = SECSuccess;
+ SECKEYPublicKey *pubk;
+- PRBool prefer_sha1 = PR_FALSE;
++
++ pubk = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
++ if (pubk == NULL) {
++ rv = SECFailure;
++ goto done;
++ }
++
++ rv = ssl3_TLSSignatureAlgorithmForKeyType(pubk->keyType, sigAlg);
++ if (rv != SECSuccess) {
++ goto done;
++ }
+
+ #if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(_WIN32)
+ /* If the key is in CAPI, assume conservatively that the CAPI service
+@@ -6989,7 +7002,8 @@ ssl3_ClientKeyPrefersSHA1(sslSocket *ss)
+ if (ss->ssl3.platformClientKey->dwKeySpec != CERT_NCRYPT_KEY_SPEC) {
+ /* CAPI only supports RSA and DSA signatures, so we don't need to
+ * check the key type. */
+- return PR_TRUE;
++ *preferSha1 = PR_TRUE;
++ goto done;
+ }
+ #endif /* NSS_PLATFORM_CLIENT_AUTH && _WIN32 */
+
+@@ -6999,38 +7013,61 @@ ssl3_ClientKeyPrefersSHA1(sslSocket *ss)
+ * older, DSA key size is at most 1024 bits and the hash function must
+ * be SHA-1.
+ */
+- pubk = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
+- if (pubk == NULL) {
+- return PR_FALSE;
+- }
+ if (pubk->keyType == rsaKey || pubk->keyType == dsaKey) {
+- prefer_sha1 = SECKEY_PublicKeyStrength(pubk) <= 128;
++ *preferSha1 = SECKEY_PublicKeyStrength(pubk) <= 128;
++ } else {
++ *preferSha1 = PR_FALSE;
+ }
+- SECKEY_DestroyPublicKey(pubk);
+- return prefer_sha1;
++
++ done:
++ if (pubk)
++ SECKEY_DestroyPublicKey(pubk);
++ return rv;
+ }
+
+-/* Destroys the backup handshake hash context if we don't need it. */
++/* Destroys the backup handshake hash context if we don't need it. Note that
++ * this function selects the hash algorithm for client authentication
++ * signatures; ssl3_SendCertificateVerify uses the presence of the backup hash
++ * to determine whether to use SHA-1 or SHA-256. */
+ static void
+ ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss,
+ const SECItem *algorithms)
+ {
+- PRBool need_backup_hash = PR_FALSE;
++ SECStatus rv;
++ TLSSignatureAlgorithm sigAlg;
++ PRBool preferSha1;
++ PRBool supportsSha1 = PR_FALSE;
++ PRBool supportsSha256 = PR_FALSE;
++ PRBool needBackupHash = PR_FALSE;
+ unsigned int i;
+
+ PORT_Assert(ss->ssl3.hs.md5);
+- if (ssl3_ClientKeyPrefersSHA1(ss)) {
+- /* Use SHA-1 if the server supports it. */
+- for (i = 0; i < algorithms->len; i += 2) {
+- if (algorithms->data[i] == tls_hash_sha1 &&
+- (algorithms->data[i+1] == tls_sig_rsa ||
+- algorithms->data[i+1] == tls_sig_dsa)) {
+- need_backup_hash = PR_TRUE;
+- break;
++
++ /* Determine the key's signature algorithm and whether it prefers SHA-1. */
++ rv = ssl3_ExtractClientKeyInfo(ss, &sigAlg, &preferSha1);
++ if (rv != SECSuccess) {
++ goto done;
++ }
++
++ /* Determine the server's hash support for that signature algorithm. */
++ for (i = 0; i < algorithms->len; i += 2) {
++ if (algorithms->data[i+1] == sigAlg) {
++ if (algorithms->data[i] == tls_hash_sha1) {
++ supportsSha1 = PR_TRUE;
++ } else if (algorithms->data[i] == tls_hash_sha256) {
++ supportsSha256 = PR_TRUE;
+ }
+ }
+ }
+- if (!need_backup_hash) {
++
++ /* If either the server does not support SHA-256 or the client key prefers
++ * SHA-1, leave the backup hash. */
++ if (supportsSha1 && (preferSha1 || !supportsSha256)) {
++ needBackupHash = PR_TRUE;
++ }
++
++done:
++ if (!needBackupHash) {
+ PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
+ ss->ssl3.hs.md5 = NULL;
+ }
diff --git a/chromium/net/third_party/nss/ssl/SSLerrs.h b/chromium/net/third_party/nss/ssl/SSLerrs.h
index c0d26ccfadc..4ff0b7ddda4 100644
--- a/chromium/net/third_party/nss/ssl/SSLerrs.h
+++ b/chromium/net/third_party/nss/ssl/SSLerrs.h
@@ -421,3 +421,8 @@ ER3(SSL_ERROR_INVALID_CHANNEL_ID_KEY, (SSL_ERROR_BASE + 130),
ER3(SSL_ERROR_GET_CHANNEL_ID_FAILED, (SSL_ERROR_BASE + 131),
"The application could not get a TLS Channel ID.")
+
+ER3(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT, (SSL_ERROR_BASE + 132),
+"The connection was using a lesser TLS version as a result of a previous"
+" handshake failure, but the server indicated that it should not have been"
+" needed.")
diff --git a/chromium/net/third_party/nss/ssl/exports_win.def b/chromium/net/third_party/nss/ssl/exports_win.def
index 09c70b0b410..a1045bb9212 100644
--- a/chromium/net/third_party/nss/ssl/exports_win.def
+++ b/chromium/net/third_party/nss/ssl/exports_win.def
@@ -50,6 +50,8 @@ SSL_ExportKeyingMaterial
SSL_VersionRangeSet
SSL_GetSRTPCipher
SSL_SetSRTPCiphers
+SSL_RecommendedCanFalseStart
+SSL_SetCanFalseStartCallback
; Chromium patches
SSL_PeerCertificateChain
@@ -58,3 +60,7 @@ SSL_GetPlatformClientAuthDataHook
SSL_HandshakeResumedSession
SSL_RestartHandshakeAfterChannelIDReq
SSL_GetChannelBinding
+SSL_PeerSignedCertTimestamps
+SSL_CipherOrderSet
+SSL_CacheSession
+SSL_CacheSessionUnlocked
diff --git a/chromium/net/third_party/nss/ssl/ssl.h b/chromium/net/third_party/nss/ssl/ssl.h
index 47468a0a289..6f7c9889f00 100644
--- a/chromium/net/third_party/nss/ssl/ssl.h
+++ b/chromium/net/third_party/nss/ssl/ssl.h
@@ -129,13 +129,8 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
* it saves a round trip for client-speaks-first protocols when performing a
* full handshake.
*
- * See SSL_DefaultCanFalseStart for the default criteria that NSS uses to
- * determine whether to false start or not. See SSL_SetCanFalseStartCallback
- * for how to change that criteria. In addition to those criteria, false start
- * will only be done when the server selects a cipher suite with an effective
- * key length of 80 bits or more (including RC4-128). Also, see
- * SSL_HandshakeCallback for a description on how false start affects when the
- * handshake callback gets called.
+ * In addition to enabling this option, the application must register a
+ * callback using the SSL_SetCanFalseStartCallback function.
*/
/* For SSL 3.0 and TLS 1.0, by default we prevent chosen plaintext attacks
@@ -166,6 +161,10 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
*/
#define SSL_CBC_RANDOM_IV 23
#define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */
+/* Request Signed Certificate Timestamps via TLS extension (client) */
+#define SSL_ENABLE_SIGNED_CERT_TIMESTAMPS 25
+#define SSL_ENABLE_FALLBACK_SCSV 26 /* Send fallback SCSV in
+ * handshakes. */
#ifdef SSL_DEPRECATED_FUNCTION
/* Old deprecated function names */
@@ -268,6 +267,13 @@ SSL_IMPORT SECStatus SSL_CipherPrefGetDefault(PRInt32 cipher, PRBool *enabled);
SSL_IMPORT SECStatus SSL_CipherPolicySet(PRInt32 cipher, PRInt32 policy);
SSL_IMPORT SECStatus SSL_CipherPolicyGet(PRInt32 cipher, PRInt32 *policy);
+/* SSL_CipherOrderSet sets the cipher suite preference order from |ciphers|,
+ * which must be an array of cipher suite ids of length |len|. All the given
+ * cipher suite ids must appear in the array that is returned by
+ * |SSL_GetImplementedCiphers| and may only appear once, at most. */
+SSL_IMPORT SECStatus SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers,
+ unsigned int len);
+
/* SSLChannelBindingType enumerates the types of supported channel binding
* values. See RFC 5929. */
typedef enum SSLChannelBindingType {
@@ -469,6 +475,23 @@ SSL_IMPORT CERTCertList *SSL_PeerCertificateChain(PRFileDesc *fd);
*/
SSL_IMPORT const SECItemArray * SSL_PeerStapledOCSPResponses(PRFileDesc *fd);
+/* SSL_PeerSignedCertTimestamps returns the signed_certificate_timestamp
+ * extension data provided by the TLS server. The return value is a pointer
+ * to an internal SECItem that contains the returned response (as a serialized
+ * SignedCertificateTimestampList, see RFC 6962). The returned pointer is only
+ * valid until the callback function that calls SSL_PeerSignedCertTimestamps
+ * (e.g. the authenticate certificate hook, or the handshake callback) returns.
+ *
+ * If no Signed Certificate Timestamps were given by the server then the result
+ * will be empty. If there was an error, then the result will be NULL.
+ *
+ * You must set the SSL_ENABLE_SIGNED_CERT_TIMESTAMPS option to indicate support
+ * for Signed Certificate Timestamps to a server.
+ *
+ * libssl does not do any parsing or validation of the response itself.
+ */
+SSL_IMPORT const SECItem * SSL_PeerSignedCertTimestamps(PRFileDesc *fd);
+
/* SSL_SetStapledOCSPResponses stores an array of one or multiple OCSP responses
* in the fd's data, which may be sent as part of a server side cert_status
* handshake message. Parameter |responses| is for the server certificate of
@@ -749,45 +772,30 @@ SSL_IMPORT SECStatus SSL_SetMaxServerCacheLocks(PRUint32 maxLocks);
SSL_IMPORT SECStatus SSL_InheritMPServerSIDCache(const char * envString);
/*
-** Set the callback that normally gets called when the TLS handshake
-** is complete. If false start is not enabled, then the handshake callback is
-** called after verifying the peer's Finished message and before sending
-** outgoing application data and before processing incoming application data.
-**
-** If false start is enabled and there is a custom CanFalseStartCallback
-** callback set, then the handshake callback gets called after the peer's
-** Finished message has been verified, which may be after application data is
-** sent.
+** Set the callback that gets called when a TLS handshake is complete. The
+** handshake callback is called after verifying the peer's Finished message and
+** before processing incoming application data.
**
-** If false start is enabled and there is not a custom CanFalseStartCallback
-** callback established with SSL_SetCanFalseStartCallback then the handshake
-** callback gets called before any application data is sent, which may be
-** before the peer's Finished message has been verified.
+** For the initial handshake: If the handshake false started (see
+** SSL_ENABLE_FALSE_START), then application data may already have been sent
+** before the handshake callback is called. If we did not false start then the
+** callback will get called before any application data is sent.
*/
typedef void (PR_CALLBACK *SSLHandshakeCallback)(PRFileDesc *fd,
void *client_data);
SSL_IMPORT SECStatus SSL_HandshakeCallback(PRFileDesc *fd,
SSLHandshakeCallback cb, void *client_data);
-/* Applications that wish to customize TLS false start should set this callback
+/* Applications that wish to enable TLS false start must set this callback
** function. NSS will invoke the functon to determine if a particular
** connection should use false start or not. SECSuccess indicates that the
** callback completed successfully, and if so *canFalseStart indicates if false
** start can be used. If the callback does not return SECSuccess then the
-** handshake will be canceled.
-**
-** Applications that do not set the callback will use an internal set of
-** criteria to determine if the connection should false start. If
-** the callback is set false start will never be used without invoking the
-** callback function, but some connections (e.g. resumed connections) will
-** never use false start and therefore will not invoke the callback.
-**
-** NSS's internal criteria for this connection can be evaluated by calling
-** SSL_DefaultCanFalseStart() from the custom callback.
+** handshake will be canceled. NSS's recommended criteria can be evaluated by
+** calling SSL_RecommendedCanFalseStart.
**
-** See the description of SSL_HandshakeCallback for important information on
-** how registering a custom false start callback affects when the handshake
-** callback gets called.
+** If no false start callback is registered then false start will never be
+** done, even if the SSL_ENABLE_FALSE_START option is enabled.
**/
typedef SECStatus (PR_CALLBACK *SSLCanFalseStartCallback)(
PRFileDesc *fd, void *arg, PRBool *canFalseStart);
@@ -795,12 +803,13 @@ typedef SECStatus (PR_CALLBACK *SSLCanFalseStartCallback)(
SSL_IMPORT SECStatus SSL_SetCanFalseStartCallback(
PRFileDesc *fd, SSLCanFalseStartCallback callback, void *arg);
-/* A utility function that can be called from a custom CanFalseStartCallback
-** function to determine what NSS would have done for this connection if the
-** custom callback was not implemented.
-**/
-SSL_IMPORT SECStatus SSL_DefaultCanFalseStart(PRFileDesc *fd,
- PRBool *canFalseStart);
+/* This function sets *canFalseStart according to the recommended criteria for
+** false start. These criteria may change from release to release and may depend
+** on which handshake features have been negotiated and/or properties of the
+** certifciates/keys used on the connection.
+*/
+SSL_IMPORT SECStatus SSL_RecommendedCanFalseStart(PRFileDesc *fd,
+ PRBool *canFalseStart);
/*
** For the server, request a new handshake. For the client, begin a new
@@ -863,6 +872,18 @@ SSL_IMPORT int SSL_DataPending(PRFileDesc *fd);
SSL_IMPORT SECStatus SSL_InvalidateSession(PRFileDesc *fd);
/*
+** Cache the SSL session associated with fd, if it has not already been cached.
+*/
+SSL_IMPORT SECStatus SSL_CacheSession(PRFileDesc *fd);
+
+/*
+** Cache the SSL session associated with fd, if it has not already been cached.
+** This function may only be called when processing within a callback assigned
+** via SSL_HandshakeCallback
+*/
+SSL_IMPORT SECStatus SSL_CacheSessionUnlocked(PRFileDesc *fd);
+
+/*
** Return a SECItem containing the SSL session ID associated with the fd.
*/
SSL_IMPORT SECItem *SSL_GetSessionID(PRFileDesc *fd);
diff --git a/chromium/net/third_party/nss/ssl/ssl3con.c b/chromium/net/third_party/nss/ssl/ssl3con.c
index 8b8b758c0b4..e2be5e6f5da 100644
--- a/chromium/net/third_party/nss/ssl/ssl3con.c
+++ b/chromium/net/third_party/nss/ssl/ssl3con.c
@@ -3469,6 +3469,9 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf)
case certificate_unknown: error = SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT;
break;
case illegal_parameter: error = SSL_ERROR_ILLEGAL_PARAMETER_ALERT;break;
+ case inappropriate_fallback:
+ error = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT;
+ break;
/* All alerts below are TLS only. */
case unknown_ca: error = SSL_ERROR_UNKNOWN_CA_ALERT; break;
@@ -4973,8 +4976,9 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
int num_suites;
int actual_count = 0;
PRBool isTLS = PR_FALSE;
- PRBool requestingResume = PR_FALSE;
+ PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE;
PRInt32 total_exten_len = 0;
+ unsigned paddingExtensionLen;
unsigned numCompressionMethods;
PRInt32 flags;
@@ -5222,8 +5226,15 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE);
if (!num_suites)
return SECFailure; /* count_cipher_suites has set error code. */
+
+ fallbackSCSV = ss->opt.enableFallbackSCSV && (!requestingResume ||
+ ss->version < sid->version);
+ /* make room for SCSV */
if (ss->ssl3.hs.sendingSCSV) {
- ++num_suites; /* make room for SCSV */
+ ++num_suites;
+ }
+ if (fallbackSCSV) {
+ ++num_suites;
}
/* count compression methods */
@@ -5241,6 +5252,20 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
length += 1 + ss->ssl3.hs.cookieLen;
}
+ /* A padding extension may be included to ensure that the record containing
+ * the ClientHello doesn't have a length between 256 and 511 bytes
+ * (inclusive). Initial, ClientHello records with such lengths trigger bugs
+ * in F5 devices.
+ *
+ * This is not done for DTLS nor for renegotiation. */
+ if (!IS_DTLS(ss) && isTLS && !ss->firstHsDone) {
+ paddingExtensionLen = ssl3_CalculatePaddingExtensionLength(length);
+ total_exten_len += paddingExtensionLen;
+ length += paddingExtensionLen;
+ } else {
+ paddingExtensionLen = 0;
+ }
+
rv = ssl3_AppendHandshakeHeader(ss, client_hello, length);
if (rv != SECSuccess) {
return rv; /* err set by ssl3_AppendHandshake* */
@@ -5307,6 +5332,14 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
}
actual_count++;
}
+ if (fallbackSCSV) {
+ rv = ssl3_AppendHandshakeNumber(ss, TLS_FALLBACK_SCSV,
+ sizeof(ssl3CipherSuite));
+ if (rv != SECSuccess) {
+ return rv; /* err set by ssl3_AppendHandshake* */
+ }
+ actual_count++;
+ }
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
if (config_match(suite, ss->ssl3.policy, PR_TRUE, &ss->vrange)) {
@@ -5360,6 +5393,13 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
return SECFailure;
}
maxBytes -= extLen;
+
+ extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes);
+ if (extLen < 0) {
+ return SECFailure;
+ }
+ maxBytes -= extLen;
+
PORT_Assert(!maxBytes);
}
if (ss->ssl3.hs.sendingSCSV) {
@@ -6617,10 +6657,22 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
sid->u.ssl3.sessionIDLength = sidBytes.len;
PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len);
+ /* Copy Signed Certificate Timestamps, if any. */
+ if (ss->xtnData.signedCertTimestamps.data) {
+ rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.signedCertTimestamps,
+ &ss->xtnData.signedCertTimestamps);
+ if (rv != SECSuccess)
+ goto loser;
+ }
+
ss->ssl3.hs.isResuming = PR_FALSE;
ss->ssl3.hs.ws = wait_server_cert;
winner:
+ /* Clean up the temporary pointer to the handshake buffer. */
+ ss->xtnData.signedCertTimestamps.data = NULL;
+ ss->xtnData.signedCertTimestamps.len = 0;
+
/* If we will need a ChannelID key then we make the callback now. This
* allows the handshake to be restarted cleanly if the callback returns
* SECWouldBlock. */
@@ -6646,6 +6698,9 @@ alert_loser:
(void)SSL3_SendAlert(ss, alert_fatal, desc);
loser:
+ /* Clean up the temporary pointer to the handshake buffer. */
+ ss->xtnData.signedCertTimestamps.data = NULL;
+ ss->xtnData.signedCertTimestamps.len = 0;
errCode = ssl_MapLowLevelError(errCode);
return SECFailure;
}
@@ -6936,14 +6991,27 @@ no_memory: /* no-memory error has already been set. */
/*
- * Returns true if the client authentication key is an RSA or DSA key that
- * may be able to sign only SHA-1 hashes.
+ * Returns the TLS signature algorithm for the client authentication key and
+ * whether it is an RSA or DSA key that may be able to sign only SHA-1 hashes.
*/
-static PRBool
-ssl3_ClientKeyPrefersSHA1(sslSocket *ss)
+static SECStatus
+ssl3_ExtractClientKeyInfo(sslSocket *ss,
+ TLSSignatureAlgorithm *sigAlg,
+ PRBool *preferSha1)
{
+ SECStatus rv = SECSuccess;
SECKEYPublicKey *pubk;
- PRBool prefer_sha1 = PR_FALSE;
+
+ pubk = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
+ if (pubk == NULL) {
+ rv = SECFailure;
+ goto done;
+ }
+
+ rv = ssl3_TLSSignatureAlgorithmForKeyType(pubk->keyType, sigAlg);
+ if (rv != SECSuccess) {
+ goto done;
+ }
#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(_WIN32)
/* If the key is in CAPI, assume conservatively that the CAPI service
@@ -6952,7 +7020,8 @@ ssl3_ClientKeyPrefersSHA1(sslSocket *ss)
if (ss->ssl3.platformClientKey->dwKeySpec != CERT_NCRYPT_KEY_SPEC) {
/* CAPI only supports RSA and DSA signatures, so we don't need to
* check the key type. */
- return PR_TRUE;
+ *preferSha1 = PR_TRUE;
+ goto done;
}
#endif /* NSS_PLATFORM_CLIENT_AUTH && _WIN32 */
@@ -6962,38 +7031,61 @@ ssl3_ClientKeyPrefersSHA1(sslSocket *ss)
* older, DSA key size is at most 1024 bits and the hash function must
* be SHA-1.
*/
- pubk = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
- if (pubk == NULL) {
- return PR_FALSE;
- }
if (pubk->keyType == rsaKey || pubk->keyType == dsaKey) {
- prefer_sha1 = SECKEY_PublicKeyStrength(pubk) <= 128;
+ *preferSha1 = SECKEY_PublicKeyStrength(pubk) <= 128;
+ } else {
+ *preferSha1 = PR_FALSE;
}
- SECKEY_DestroyPublicKey(pubk);
- return prefer_sha1;
+
+ done:
+ if (pubk)
+ SECKEY_DestroyPublicKey(pubk);
+ return rv;
}
-/* Destroys the backup handshake hash context if we don't need it. */
+/* Destroys the backup handshake hash context if we don't need it. Note that
+ * this function selects the hash algorithm for client authentication
+ * signatures; ssl3_SendCertificateVerify uses the presence of the backup hash
+ * to determine whether to use SHA-1 or SHA-256. */
static void
ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss,
const SECItem *algorithms)
{
- PRBool need_backup_hash = PR_FALSE;
+ SECStatus rv;
+ TLSSignatureAlgorithm sigAlg;
+ PRBool preferSha1;
+ PRBool supportsSha1 = PR_FALSE;
+ PRBool supportsSha256 = PR_FALSE;
+ PRBool needBackupHash = PR_FALSE;
unsigned int i;
PORT_Assert(ss->ssl3.hs.md5);
- if (ssl3_ClientKeyPrefersSHA1(ss)) {
- /* Use SHA-1 if the server supports it. */
- for (i = 0; i < algorithms->len; i += 2) {
- if (algorithms->data[i] == tls_hash_sha1 &&
- (algorithms->data[i+1] == tls_sig_rsa ||
- algorithms->data[i+1] == tls_sig_dsa)) {
- need_backup_hash = PR_TRUE;
- break;
+
+ /* Determine the key's signature algorithm and whether it prefers SHA-1. */
+ rv = ssl3_ExtractClientKeyInfo(ss, &sigAlg, &preferSha1);
+ if (rv != SECSuccess) {
+ goto done;
+ }
+
+ /* Determine the server's hash support for that signature algorithm. */
+ for (i = 0; i < algorithms->len; i += 2) {
+ if (algorithms->data[i+1] == sigAlg) {
+ if (algorithms->data[i] == tls_hash_sha1) {
+ supportsSha1 = PR_TRUE;
+ } else if (algorithms->data[i] == tls_hash_sha256) {
+ supportsSha256 = PR_TRUE;
}
}
}
- if (!need_backup_hash) {
+
+ /* If either the server does not support SHA-256 or the client key prefers
+ * SHA-1, leave the backup hash. */
+ if (supportsSha1 && (preferSha1 || !supportsSha256)) {
+ needBackupHash = PR_TRUE;
+ }
+
+done:
+ if (!needBackupHash) {
PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
ss->ssl3.hs.md5 = NULL;
}
@@ -7352,40 +7444,69 @@ ssl3_RestartHandshakeAfterCertReq(sslSocket * ss,
static SECStatus
ssl3_CheckFalseStart(sslSocket *ss)
{
- SECStatus rv;
- PRBool maybeFalseStart = PR_TRUE;
-
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
PORT_Assert( !ss->ssl3.hs.authCertificatePending );
-
- /* An attacker can control the selected ciphersuite so we only wish to
- * do False Start in the case that the selected ciphersuite is
- * sufficiently strong that the attack can gain no advantage.
- * Therefore we always require an 80-bit cipher. */
-
- ssl_GetSpecReadLock(ss);
- if (ss->ssl3.cwSpec->cipher_def->secret_key_size < 10) {
- ss->ssl3.hs.canFalseStart = PR_FALSE;
- maybeFalseStart = PR_FALSE;
- }
- ssl_ReleaseSpecReadLock(ss);
- if (!maybeFalseStart) {
- return SECSuccess;
- }
+ PORT_Assert( !ss->ssl3.hs.canFalseStart );
if (!ss->canFalseStartCallback) {
- rv = SSL_DefaultCanFalseStart(ss->fd, &ss->ssl3.hs.canFalseStart);
+ SSL_TRC(3, ("%d: SSL[%d]: no false start callback so no false start",
+ SSL_GETPID(), ss->fd));
} else {
- rv = (ss->canFalseStartCallback)(ss->fd,
- ss->canFalseStartCallbackData,
- &ss->ssl3.hs.canFalseStart);
+ PRBool maybeFalseStart;
+ SECStatus rv;
+
+ /* An attacker can control the selected ciphersuite so we only wish to
+ * do False Start in the case that the selected ciphersuite is
+ * sufficiently strong that the attack can gain no advantage.
+ * Therefore we always require an 80-bit cipher. */
+ ssl_GetSpecReadLock(ss);
+ maybeFalseStart = ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10;
+ ssl_ReleaseSpecReadLock(ss);
+
+ if (!maybeFalseStart) {
+ SSL_TRC(3, ("%d: SSL[%d]: no false start due to weak cipher",
+ SSL_GETPID(), ss->fd));
+ } else {
+ rv = (ss->canFalseStartCallback)(ss->fd,
+ ss->canFalseStartCallbackData,
+ &ss->ssl3.hs.canFalseStart);
+ if (rv == SECSuccess) {
+ SSL_TRC(3, ("%d: SSL[%d]: false start callback returned %s",
+ SSL_GETPID(), ss->fd,
+ ss->ssl3.hs.canFalseStart ? "TRUE" : "FALSE"));
+ } else {
+ SSL_TRC(3, ("%d: SSL[%d]: false start callback failed (%s)",
+ SSL_GETPID(), ss->fd,
+ PR_ErrorToName(PR_GetError())));
+ }
+ return rv;
+ }
}
- if (rv != SECSuccess) {
- ss->ssl3.hs.canFalseStart = PR_FALSE;
+ ss->ssl3.hs.canFalseStart = PR_FALSE;
+ return SECSuccess;
+}
+
+PRBool
+ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss)
+{
+ PRBool result;
+
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+
+ switch (ss->ssl3.hs.ws) {
+ case wait_new_session_ticket:
+ result = PR_TRUE;
+ break;
+ case wait_change_cipher:
+ result = !ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn);
+ break;
+ default:
+ result = PR_FALSE;
+ break;
}
- return rv;
+ return result;
}
static SECStatus ssl3_SendClientSecondRound(sslSocket *ss);
@@ -7475,6 +7596,9 @@ ssl3_SendClientSecondRound(sslSocket *ss)
}
if (ss->ssl3.hs.authCertificatePending &&
(sendClientCert || ss->ssl3.sendEmptyCert || ss->firstHsDone)) {
+ SSL_TRC(3, ("%d: SSL3[%p]: deferring ssl3_SendClientSecondRound because"
+ " certificate authentication is still pending.",
+ SSL_GETPID(), ss->fd));
ss->ssl3.hs.restartTarget = ssl3_SendClientSecondRound;
return SECWouldBlock;
}
@@ -7544,7 +7668,7 @@ ssl3_SendClientSecondRound(sslSocket *ss)
* call ssl3_CheckFalseStart before calling ssl3_SendFinished,
* which includes a call to ssl3_FlushHandshake, so that
* no application develops a reliance on such flushing being
- * done before its false start callback is called.
+ * done before its false start callback is called.
*/
ssl_ReleaseXmitBufLock(ss);
rv = ssl3_CheckFalseStart(ss);
@@ -7572,23 +7696,39 @@ ssl3_SendClientSecondRound(sslSocket *ss)
ssl_ReleaseXmitBufLock(ss); /*******************************/
+ if (!ss->ssl3.hs.isResuming &&
+ ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) {
+ /* If we are negotiating ChannelID on a full handshake then we record
+ * the handshake hashes in |sid| at this point. They will be needed in
+ * the event that we resume this session and use ChannelID on the
+ * resumption handshake. */
+ SSL3Hashes hashes;
+ SECItem *originalHandshakeHash =
+ &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
+ PORT_Assert(ss->sec.ci.sid->cached == never_cached);
+
+ ssl_GetSpecReadLock(ss);
+ PORT_Assert(ss->version > SSL_LIBRARY_VERSION_3_0);
+ rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0);
+ ssl_ReleaseSpecReadLock(ss);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ PORT_Assert(originalHandshakeHash->len == 0);
+ originalHandshakeHash->data = PORT_Alloc(hashes.len);
+ if (!originalHandshakeHash->data)
+ return SECFailure;
+ originalHandshakeHash->len = hashes.len;
+ memcpy(originalHandshakeHash->data, hashes.u.raw, hashes.len);
+ }
+
if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
ss->ssl3.hs.ws = wait_new_session_ticket;
else
ss->ssl3.hs.ws = wait_change_cipher;
- if (ss->handshakeCallback &&
- (ss->ssl3.hs.canFalseStart && !ss->canFalseStartCallback)) {
- /* Call the handshake callback here for backwards compatibility with
- * applications that were using false start before
- * canFalseStartCallback was added. Note that we do this after calling
- * ssl3_SendFinished, which includes a call to ssl3_FlushHandshake,
- * just in case the application is relying on having the handshake
- * messages flushed to the network before its handshake callback is
- * called.
- */
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
- }
+ PORT_Assert(ssl3_WaitingForStartOfServerSecondRound(ss));
return SECSuccess;
@@ -7915,6 +8055,19 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
goto loser; /* malformed */
}
+ /* If the ClientHello version is less than our maximum version, check for a
+ * TLS_FALLBACK_SCSV and reject the connection if found. */
+ if (ss->vrange.max > ss->clientHelloVersion) {
+ for (i = 0; i + 1 < suites.len; i += 2) {
+ PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
+ if (suite_i != TLS_FALLBACK_SCSV)
+ continue;
+ desc = inappropriate_fallback;
+ errCode = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT;
+ goto alert_loser;
+ }
+ }
+
/* grab the list of compression methods. */
rv = ssl3_ConsumeHandshakeVariable(ss, &comps, 1, &b, &length);
if (rv != SECSuccess) {
@@ -10345,36 +10498,24 @@ ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error)
rv = SECSuccess;
}
} else {
- SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race"
- " with peer's finished message", SSL_GETPID(), ss->fd));
+ SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race with"
+ " peer's finished message", SSL_GETPID(), ss->fd));
PORT_Assert(!ss->firstHsDone);
PORT_Assert(!ss->sec.isServer);
PORT_Assert(!ss->ssl3.hs.isResuming);
- PORT_Assert(ss->ssl3.hs.ws == wait_change_cipher ||
- ss->ssl3.hs.ws == wait_finished ||
- ss->ssl3.hs.ws == wait_new_session_ticket);
+ PORT_Assert(ss->ssl3.hs.ws != idle_handshake);
- /* ssl3_SendClientSecondRound deferred the false start check because
- * certificate authentication was pending, so we have to do it now.
- */
if (ss->opt.enableFalseStart &&
!ss->firstHsDone &&
!ss->sec.isServer &&
!ss->ssl3.hs.isResuming &&
- (ss->ssl3.hs.ws == wait_change_cipher ||
- ss->ssl3.hs.ws == wait_finished ||
- ss->ssl3.hs.ws == wait_new_session_ticket)) {
+ ssl3_WaitingForStartOfServerSecondRound(ss)) {
+ /* ssl3_SendClientSecondRound deferred the false start check because
+ * certificate authentication was pending, so we do it now if we still
+ * haven't received any of the server's second round yet.
+ */
rv = ssl3_CheckFalseStart(ss);
- if (rv == SECSuccess &&
- ss->handshakeCallback &&
- (ss->ssl3.hs.canFalseStart && !ss->canFalseStartCallback)) {
- /* Call the handshake callback here for backwards compatibility
- * with applications that were using false start before
- * canFalseStartCallback was added.
- */
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
- }
} else {
rv = SECSuccess;
}
@@ -10568,6 +10709,7 @@ static SECStatus
ssl3_SendEncryptedExtensions(sslSocket *ss)
{
static const char CHANNEL_ID_MAGIC[] = "TLS Channel ID signature";
+ static const char CHANNEL_ID_RESUMPTION_MAGIC[] = "Resumption";
/* This is the ASN.1 prefix for a P-256 public key. Specifically it's:
* SEQUENCE
* SEQUENCE
@@ -10593,7 +10735,10 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
SECItem *spki = NULL;
SSL3Hashes hashes;
const unsigned char *pub_bytes;
- unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) + sizeof(SSL3Hashes)];
+ unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) +
+ sizeof(CHANNEL_ID_RESUMPTION_MAGIC) +
+ sizeof(SSL3Hashes)*2];
+ size_t signed_data_len;
unsigned char digest[SHA256_LENGTH];
SECItem digest_item;
unsigned char signature[64];
@@ -10635,7 +10780,7 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
spki = SECKEY_EncodeDERSubjectPublicKeyInfo(ss->ssl3.channelIDPub);
if (spki->len != sizeof(P256_SPKI_PREFIX) + CHANNEL_ID_PUBLIC_KEY_LENGTH ||
- memcmp(spki->data, P256_SPKI_PREFIX, sizeof(P256_SPKI_PREFIX) != 0)) {
+ memcmp(spki->data, P256_SPKI_PREFIX, sizeof(P256_SPKI_PREFIX)) != 0) {
PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
rv = SECFailure;
goto loser;
@@ -10643,11 +10788,26 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
pub_bytes = spki->data + sizeof(P256_SPKI_PREFIX);
- memcpy(signed_data, CHANNEL_ID_MAGIC, sizeof(CHANNEL_ID_MAGIC));
- memcpy(signed_data + sizeof(CHANNEL_ID_MAGIC), hashes.u.raw, hashes.len);
-
- rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data,
- sizeof(CHANNEL_ID_MAGIC) + hashes.len);
+ signed_data_len = 0;
+ memcpy(signed_data + signed_data_len, CHANNEL_ID_MAGIC,
+ sizeof(CHANNEL_ID_MAGIC));
+ signed_data_len += sizeof(CHANNEL_ID_MAGIC);
+ if (ss->ssl3.hs.isResuming) {
+ SECItem *originalHandshakeHash =
+ &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
+ PORT_Assert(originalHandshakeHash->len > 0);
+
+ memcpy(signed_data + signed_data_len, CHANNEL_ID_RESUMPTION_MAGIC,
+ sizeof(CHANNEL_ID_RESUMPTION_MAGIC));
+ signed_data_len += sizeof(CHANNEL_ID_RESUMPTION_MAGIC);
+ memcpy(signed_data + signed_data_len, originalHandshakeHash->data,
+ originalHandshakeHash->len);
+ signed_data_len += originalHandshakeHash->len;
+ }
+ memcpy(signed_data + signed_data_len, hashes.u.raw, hashes.len);
+ signed_data_len += hashes.len;
+
+ rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, signed_data_len);
if (rv != SECSuccess)
goto loser;
@@ -11003,9 +11163,6 @@ xmit_loser:
return rv;
}
- ss->gs.writeOffset = 0;
- ss->gs.readOffset = 0;
-
if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) {
effectiveExchKeyType = kt_rsa;
} else {
@@ -11070,36 +11227,28 @@ xmit_loser:
return rv;
}
+/* The return type is SECStatus instead of void because this function needs
+ * to have type sslRestartTarget.
+ */
SECStatus
ssl3_FinishHandshake(sslSocket * ss)
{
- PRBool falseStarted;
-
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
PORT_Assert( ss->ssl3.hs.restartTarget == NULL );
/* The first handshake is now completed. */
ss->handshake = NULL;
- ss->firstHsDone = PR_TRUE;
- ss->enoughFirstHsDone = PR_TRUE;
- if (ss->ssl3.hs.cacheSID) {
+ if (ss->ssl3.hs.cacheSID && ss->sec.isServer) {
(*ss->sec.cache)(ss->sec.ci.sid);
ss->ssl3.hs.cacheSID = PR_FALSE;
}
- ss->ssl3.hs.ws = idle_handshake;
- falseStarted = ss->ssl3.hs.canFalseStart;
ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */
+ ss->ssl3.hs.ws = idle_handshake;
- /* Call the handshake callback for sslv3 here, unless we called it already
- * for the case where false start was done without a canFalseStartCallback.
- */
- if (ss->handshakeCallback &&
- !(falseStarted && !ss->canFalseStartCallback)) {
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
- }
+ ssl_FinishHandshake(ss);
return SECSuccess;
}
@@ -12064,7 +12213,6 @@ process_it:
ssl_ReleaseSSL3HandshakeLock(ss);
return rv;
-
}
/*
@@ -12343,6 +12491,46 @@ ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *enabled)
return rv;
}
+SECStatus
+ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *ciphers, unsigned int len)
+{
+ /* |i| iterates over |ciphers| while |done| and |j| iterate over
+ * |ss->cipherSuites|. */
+ unsigned int i, done;
+
+ for (i = done = 0; i < len; i++) {
+ PRUint16 id = ciphers[i];
+ unsigned int existingIndex, j;
+ PRBool found = PR_FALSE;
+
+ for (j = done; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
+ if (ss->cipherSuites[j].cipher_suite == id) {
+ existingIndex = j;
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ continue;
+ }
+
+ if (existingIndex != done) {
+ const ssl3CipherSuiteCfg temp = ss->cipherSuites[done];
+ ss->cipherSuites[done] = ss->cipherSuites[existingIndex];
+ ss->cipherSuites[existingIndex] = temp;
+ }
+ done++;
+ }
+
+ /* Disable all cipher suites that weren't included. */
+ for (; done < ssl_V3_SUITES_IMPLEMENTED; done++) {
+ ss->cipherSuites[done].enabled = 0;
+ }
+
+ return SECSuccess;
+}
+
/* copy global default policy into socket. */
void
ssl3_InitSocketPolicy(sslSocket *ss)
diff --git a/chromium/net/third_party/nss/ssl/ssl3ext.c b/chromium/net/third_party/nss/ssl/ssl3ext.c
index 04157701e90..f2db28c924f 100644
--- a/chromium/net/third_party/nss/ssl/ssl3ext.c
+++ b/chromium/net/third_party/nss/ssl/ssl3ext.c
@@ -81,6 +81,12 @@ static PRInt32 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes);
static SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data);
+static PRInt32 ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss,
+ PRBool append,
+ PRUint32 maxBytes);
+static SECStatus ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss,
+ PRUint16 ex_type,
+ SECItem *data);
/*
* Write bytes. Using this function means the SECItem structure
@@ -259,6 +265,8 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
{ ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn },
{ ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
{ ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
+ { ssl_signed_certificate_timestamp_xtn,
+ &ssl3_ClientHandleSignedCertTimestampXtn },
{ -1, NULL }
};
@@ -287,7 +295,9 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
{ ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn },
{ ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
{ ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
- { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
+ { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
+ { ssl_signed_certificate_timestamp_xtn,
+ &ssl3_ClientSendSignedCertTimestampXtn }
/* any extra entries will appear as { 0, NULL } */
};
@@ -812,6 +822,15 @@ ssl3_ClientSendChannelIDXtn(sslSocket * ss, PRBool append,
return 0;
}
+ if (ss->sec.ci.sid->cached != never_cached &&
+ ss->sec.ci.sid->u.ssl3.originalHandshakeHash.len == 0) {
+ /* We can't do ChannelID on a connection if we're resuming and didn't
+ * do ChannelID on the original connection: without ChannelID on the
+ * original connection we didn't record the handshake hashes needed for
+ * the signature. */
+ return 0;
+ }
+
if (append) {
SECStatus rv;
rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
@@ -2297,3 +2316,118 @@ ssl3_ClientSendSigAlgsXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
loser:
return -1;
}
+
+unsigned int
+ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength)
+{
+ unsigned int recordLength = 1 /* handshake message type */ +
+ 3 /* handshake message length */ +
+ clientHelloLength;
+ unsigned int extensionLength;
+
+ if (recordLength < 256 || recordLength >= 512) {
+ return 0;
+ }
+
+ extensionLength = 512 - recordLength;
+ /* Extensions take at least four bytes to encode. */
+ if (extensionLength < 4) {
+ extensionLength = 4;
+ }
+
+ return extensionLength;
+}
+
+/* ssl3_AppendPaddingExtension possibly adds an extension which ensures that a
+ * ClientHello record is either < 256 bytes or is >= 512 bytes. This ensures
+ * that we don't trigger bugs in F5 products. */
+PRInt32
+ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
+ PRUint32 maxBytes)
+{
+ unsigned int paddingLen = extensionLen - 4;
+ unsigned char padding[256];
+
+ if (extensionLen == 0) {
+ return 0;
+ }
+
+ if (extensionLen < 4 ||
+ extensionLen > maxBytes ||
+ paddingLen > sizeof(padding)) {
+ PORT_Assert(0);
+ return -1;
+ }
+
+ if (SECSuccess != ssl3_AppendHandshakeNumber(ss, ssl_padding_xtn, 2))
+ return -1;
+ if (SECSuccess != ssl3_AppendHandshakeNumber(ss, paddingLen, 2))
+ return -1;
+ memset(padding, 0, paddingLen);
+ if (SECSuccess != ssl3_AppendHandshake(ss, padding, paddingLen))
+ return -1;
+
+ return extensionLen;
+}
+
+/* ssl3_ClientSendSignedCertTimestampXtn sends the signed_certificate_timestamp
+ * extension for TLS ClientHellos. */
+static PRInt32
+ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, PRBool append,
+ PRUint32 maxBytes)
+{
+ PRInt32 extension_length = 2 /* extension_type */ +
+ 2 /* length(extension_data) */;
+
+ /* Only send the extension if processing is enabled. */
+ if (!ss->opt.enableSignedCertTimestamps)
+ return 0;
+
+ if (append && maxBytes >= extension_length) {
+ SECStatus rv;
+ /* extension_type */
+ rv = ssl3_AppendHandshakeNumber(ss,
+ ssl_signed_certificate_timestamp_xtn,
+ 2);
+ if (rv != SECSuccess)
+ goto loser;
+ /* zero length */
+ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
+ ssl_signed_certificate_timestamp_xtn;
+ } else if (maxBytes < extension_length) {
+ PORT_Assert(0);
+ return 0;
+ }
+
+ return extension_length;
+loser:
+ return -1;
+}
+
+static SECStatus
+ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type,
+ SECItem *data)
+{
+ /* We do not yet know whether we'll be resuming a session or creating
+ * a new one, so we keep a pointer to the data in the TLSExtensionData
+ * structure. This pointer is only valid in the scope of
+ * ssl3_HandleServerHello, and, if not resuming a session, the data is
+ * copied once a new session structure has been set up.
+ * All parsing is currently left to the application and we accept
+ * everything, including empty data.
+ */
+ SECItem *scts = &ss->xtnData.signedCertTimestamps;
+ PORT_Assert(!scts->data && !scts->len);
+
+ if (!data->len) {
+ /* Empty extension data: RFC 6962 mandates non-empty contents. */
+ return SECFailure;
+ }
+ *scts = *data;
+ /* Keep track of negotiated extensions. */
+ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
+ return SECSuccess;
+}
diff --git a/chromium/net/third_party/nss/ssl/ssl3gthr.c b/chromium/net/third_party/nss/ssl/ssl3gthr.c
index 7385d6504e8..39cefa7c310 100644
--- a/chromium/net/third_party/nss/ssl/ssl3gthr.c
+++ b/chromium/net/third_party/nss/ssl/ssl3gthr.c
@@ -275,11 +275,17 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
{
SSL3Ciphertext cText;
int rv;
- PRBool canFalseStart = PR_FALSE;
+ PRBool keepGoing = PR_TRUE;
SSL_TRC(30, ("ssl3_GatherCompleteHandshake"));
+ /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake,
+ * which requires the 1stHandshakeLock, which must be acquired before the
+ * RecvBufLock.
+ */
+ PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+
do {
PRBool handleRecordNow = PR_FALSE;
@@ -364,22 +370,52 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
cText.buf = &ss->gs.inbuf;
rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
+
+ if (rv == (int) SECSuccess && ss->gs.buf.len > 0) {
+ /* We have application data to return to the application. This
+ * prioritizes returning application data to the application over
+ * completing any renegotiation handshake we may be doing.
+ */
+ PORT_Assert(ss->firstHsDone);
+ PORT_Assert(cText.type == content_application_data);
+ break;
+ }
}
if (rv < 0) {
return ss->recvdCloseNotify ? 0 : rv;
}
- /* If we kicked off a false start in ssl3_HandleServerHelloDone, break
- * out of this loop early without finishing the handshake.
- */
- if (ss->opt.enableFalseStart) {
- ssl_GetSSL3HandshakeLock(ss);
- canFalseStart = ss->ssl3.hs.canFalseStart;
- ssl_ReleaseSSL3HandshakeLock(ss);
+ PORT_Assert(keepGoing);
+ ssl_GetSSL3HandshakeLock(ss);
+ if (ss->ssl3.hs.ws == idle_handshake) {
+ /* We are done with the current handshake so stop trying to
+ * handshake. Note that it would be safe to test ss->firstHsDone
+ * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead,
+ * we prioritize completing a renegotiation handshake over sending
+ * application data.
+ */
+ PORT_Assert(ss->firstHsDone);
+ PORT_Assert(!ss->ssl3.hs.canFalseStart);
+ keepGoing = PR_FALSE;
+ } else if (ss->ssl3.hs.canFalseStart) {
+ /* Prioritize sending application data over trying to complete
+ * the handshake if we're false starting.
+ *
+ * If we were to do this check at the beginning of the loop instead
+ * of here, then this function would become be a no-op after
+ * receiving the ServerHelloDone in the false start case, and we
+ * would never complete the handshake.
+ */
+ PORT_Assert(!ss->firstHsDone);
+
+ if (ssl3_WaitingForStartOfServerSecondRound(ss)) {
+ keepGoing = PR_FALSE;
+ } else {
+ ss->ssl3.hs.canFalseStart = PR_FALSE;
+ }
}
- } while (ss->ssl3.hs.ws != idle_handshake &&
- !canFalseStart &&
- ss->gs.buf.len == 0);
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ } while (keepGoing);
ss->gs.readOffset = 0;
ss->gs.writeOffset = ss->gs.buf.len;
@@ -402,7 +438,10 @@ ssl3_GatherAppDataRecord(sslSocket *ss, int flags)
{
int rv;
+ /* ssl3_GatherCompleteHandshake requires both of these locks. */
+ PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+
do {
rv = ssl3_GatherCompleteHandshake(ss, flags);
} while (rv > 0 && ss->gs.buf.len == 0);
diff --git a/chromium/net/third_party/nss/ssl/ssl3prot.h b/chromium/net/third_party/nss/ssl/ssl3prot.h
index 0eab970bc6a..4c19ade8d6a 100644
--- a/chromium/net/third_party/nss/ssl/ssl3prot.h
+++ b/chromium/net/third_party/nss/ssl/ssl3prot.h
@@ -98,6 +98,7 @@ typedef enum {
protocol_version = 70,
insufficient_security = 71,
internal_error = 80,
+ inappropriate_fallback = 86, /* could also be sent for SSLv3 */
user_canceled = 90,
no_renegotiation = 100,
diff --git a/chromium/net/third_party/nss/ssl/sslerr.h b/chromium/net/third_party/nss/ssl/sslerr.h
index 5a949c9a248..82ae7dfb1f0 100644
--- a/chromium/net/third_party/nss/ssl/sslerr.h
+++ b/chromium/net/third_party/nss/ssl/sslerr.h
@@ -196,6 +196,7 @@ SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 128),
SSL_ERROR_BAD_CHANNEL_ID_DATA = (SSL_ERROR_BASE + 129),
SSL_ERROR_INVALID_CHANNEL_ID_KEY = (SSL_ERROR_BASE + 130),
SSL_ERROR_GET_CHANNEL_ID_FAILED = (SSL_ERROR_BASE + 131),
+SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT = (SSL_ERROR_BASE + 132),
SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
} SSLErrorCodes;
diff --git a/chromium/net/third_party/nss/ssl/sslimpl.h b/chromium/net/third_party/nss/ssl/sslimpl.h
index 614eed145ec..6d0bc154aaf 100644
--- a/chromium/net/third_party/nss/ssl/sslimpl.h
+++ b/chromium/net/third_party/nss/ssl/sslimpl.h
@@ -237,6 +237,13 @@ extern PRInt32
ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
const ssl3HelloExtensionSender *sender);
+extern unsigned int
+ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength);
+
+extern PRInt32
+ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
+ PRUint32 maxBytes);
+
/* Socket ops */
struct sslSocketOpsStr {
int (*connect) (sslSocket *, const PRNetAddr *);
@@ -305,29 +312,31 @@ typedef struct sslOptionsStr {
* list of supported protocols. */
SECItem nextProtoNego;
- unsigned int useSecurity : 1; /* 1 */
- unsigned int useSocks : 1; /* 2 */
- unsigned int requestCertificate : 1; /* 3 */
- unsigned int requireCertificate : 2; /* 4-5 */
- unsigned int handshakeAsClient : 1; /* 6 */
- unsigned int handshakeAsServer : 1; /* 7 */
- unsigned int enableSSL2 : 1; /* 8 */
- unsigned int unusedBit9 : 1; /* 9 */
- unsigned int unusedBit10 : 1; /* 10 */
- unsigned int noCache : 1; /* 11 */
- unsigned int fdx : 1; /* 12 */
- unsigned int v2CompatibleHello : 1; /* 13 */
- unsigned int detectRollBack : 1; /* 14 */
- unsigned int noStepDown : 1; /* 15 */
- unsigned int bypassPKCS11 : 1; /* 16 */
- unsigned int noLocks : 1; /* 17 */
- unsigned int enableSessionTickets : 1; /* 18 */
- unsigned int enableDeflate : 1; /* 19 */
- unsigned int enableRenegotiation : 2; /* 20-21 */
- unsigned int requireSafeNegotiation : 1; /* 22 */
- unsigned int enableFalseStart : 1; /* 23 */
- unsigned int cbcRandomIV : 1; /* 24 */
- unsigned int enableOCSPStapling : 1; /* 25 */
+ unsigned int useSecurity : 1; /* 1 */
+ unsigned int useSocks : 1; /* 2 */
+ unsigned int requestCertificate : 1; /* 3 */
+ unsigned int requireCertificate : 2; /* 4-5 */
+ unsigned int handshakeAsClient : 1; /* 6 */
+ unsigned int handshakeAsServer : 1; /* 7 */
+ unsigned int enableSSL2 : 1; /* 8 */
+ unsigned int unusedBit9 : 1; /* 9 */
+ unsigned int unusedBit10 : 1; /* 10 */
+ unsigned int noCache : 1; /* 11 */
+ unsigned int fdx : 1; /* 12 */
+ unsigned int v2CompatibleHello : 1; /* 13 */
+ unsigned int detectRollBack : 1; /* 14 */
+ unsigned int noStepDown : 1; /* 15 */
+ unsigned int bypassPKCS11 : 1; /* 16 */
+ unsigned int noLocks : 1; /* 17 */
+ unsigned int enableSessionTickets : 1; /* 18 */
+ unsigned int enableDeflate : 1; /* 19 */
+ unsigned int enableRenegotiation : 2; /* 20-21 */
+ unsigned int requireSafeNegotiation : 1; /* 22 */
+ unsigned int enableFalseStart : 1; /* 23 */
+ unsigned int cbcRandomIV : 1; /* 24 */
+ unsigned int enableOCSPStapling : 1; /* 25 */
+ unsigned int enableSignedCertTimestamps : 1; /* 26 */
+ unsigned int enableFallbackSCSV : 1; /* 27 */
} sslOptions;
typedef enum { sslHandshakingUndetermined = 0,
@@ -698,6 +707,19 @@ struct sslSessionIDStr {
*/
NewSessionTicket sessionTicket;
SECItem srvName;
+
+ /* originalHandshakeHash contains the hash of the original, full
+ * handshake prior to the server's final flow. This is either a
+ * SHA-1/MD5 combination (for TLS < 1.2) or the TLS PRF hash (for
+ * TLS 1.2). This is recorded and used only when ChannelID is
+ * negotiated as it's used to bind the ChannelID signature on the
+ * resumption handshake to the original handshake. */
+ SECItem originalHandshakeHash;
+
+ /* Signed certificate timestamps received in a TLS extension.
+ ** (used only in client).
+ */
+ SECItem signedCertTimestamps;
} ssl3;
} u;
};
@@ -789,6 +811,18 @@ struct TLSExtensionDataStr {
* is beyond ssl3_HandleClientHello function. */
SECItem *sniNameArr;
PRUint32 sniNameArrSize;
+
+ /* Signed Certificate Timestamps extracted from the TLS extension.
+ * (client only).
+ * This container holds a temporary pointer to the extension data,
+ * until a session structure (the sec.ci.sid of an sslSocket) is setup
+ * that can hold a permanent copy of the data
+ * (in sec.ci.sid.u.ssl3.signedCertTimestamps).
+ * The data pointed to by this structure is neither explicitly allocated
+ * nor copied: the pointer points to the handshake message buffer and is
+ * only valid in the scope of ssl3_HandleServerHello.
+ */
+ SECItem signedCertTimestamps;
};
typedef SECStatus (*sslRestartTarget)(sslSocket *);
@@ -1431,6 +1465,19 @@ extern void ssl3_SetAlwaysBlock(sslSocket *ss);
extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled);
+extern void ssl_FinishHandshake(sslSocket *ss);
+
+/* Returns PR_TRUE if we are still waiting for the server to respond to our
+ * client second round. Once we've received any part of the server's second
+ * round then we don't bother trying to false start since it is almost always
+ * the case that the NewSessionTicket, ChangeCipherSoec, and Finished messages
+ * were sent in the same packet and we want to process them all at the same
+ * time. If we were to try to false start in the middle of the server's second
+ * round, then we would increase the number of I/O operations
+ * (SSL_ForceHandshake/PR_Recv/PR_Send/etc.) needed to finish the handshake.
+ */
+extern PRBool ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss);
+
extern SECStatus
ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
PRBool isServer,
@@ -1665,6 +1712,8 @@ extern SECStatus ssl3_CipherPrefSet(sslSocket *ss, ssl3CipherSuite which, PRBool
extern SECStatus ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *on);
extern SECStatus ssl2_CipherPrefSet(sslSocket *ss, PRInt32 which, PRBool enabled);
extern SECStatus ssl2_CipherPrefGet(sslSocket *ss, PRInt32 which, PRBool *enabled);
+extern SECStatus ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *cipher,
+ unsigned int len);
extern SECStatus ssl3_SetPolicy(ssl3CipherSuite which, PRInt32 policy);
extern SECStatus ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *policy);
diff --git a/chromium/net/third_party/nss/ssl/sslnonce.c b/chromium/net/third_party/nss/ssl/sslnonce.c
index a6f734948a3..a3e6e0a33f9 100644
--- a/chromium/net/third_party/nss/ssl/sslnonce.c
+++ b/chromium/net/third_party/nss/ssl/sslnonce.c
@@ -21,8 +21,8 @@
PRUint32 ssl_sid_timeout = 100;
PRUint32 ssl3_sid_timeout = 86400L; /* 24 hours */
-static sslSessionID *cache = NULL;
-static PZLock * cacheLock = NULL;
+sslSessionID *cache = NULL;
+PZLock * cacheLock = NULL;
/* sids can be in one of 4 states:
*
@@ -122,7 +122,21 @@ ssl_DestroySID(sslSessionID *sid)
if (sid->version < SSL_LIBRARY_VERSION_3_0) {
SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE);
SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE);
+ } else {
+ if (sid->u.ssl3.sessionTicket.ticket.data) {
+ SECITEM_FreeItem(&sid->u.ssl3.sessionTicket.ticket, PR_FALSE);
+ }
+ if (sid->u.ssl3.srvName.data) {
+ SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE);
+ }
+ if (sid->u.ssl3.signedCertTimestamps.data) {
+ SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE);
+ }
+ if (sid->u.ssl3.originalHandshakeHash.data) {
+ SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE);
+ }
}
+
if (sid->peerID != NULL)
PORT_Free((void *)sid->peerID); /* CONST */
@@ -142,13 +156,7 @@ ssl_DestroySID(sslSessionID *sid)
if ( sid->localCert ) {
CERT_DestroyCertificate(sid->localCert);
}
- if (sid->u.ssl3.sessionTicket.ticket.data) {
- SECITEM_FreeItem(&sid->u.ssl3.sessionTicket.ticket, PR_FALSE);
- }
- if (sid->u.ssl3.srvName.data) {
- SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE);
- }
-
+
PORT_ZFree(sid, sizeof(sslSessionID));
}
@@ -430,6 +438,12 @@ ssl3_SetSIDSessionTicket(sslSessionID *sid, NewSessionTicket *session_ticket)
/* We need to lock the cache, as this sid might already be in the cache. */
LOCK_CACHE;
+ /* Don't modify sid if it has ever been cached. */
+ if (sid->cached != never_cached) {
+ UNLOCK_CACHE;
+ return SECSuccess;
+ }
+
/* A server might have sent us an empty ticket, which has the
* effect of clearing the previously known ticket.
*/
diff --git a/chromium/net/third_party/nss/ssl/sslproto.h b/chromium/net/third_party/nss/ssl/sslproto.h
index 6b60a28616f..621ef375460 100644
--- a/chromium/net/third_party/nss/ssl/sslproto.h
+++ b/chromium/net/third_party/nss/ssl/sslproto.h
@@ -172,6 +172,11 @@
*/
#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF
+/* TLS_FALLBACK_SCSV is a signaling cipher suite value that indicates that a
+ * handshake is the result of TLS version fallback. This value is not IANA
+ * assigned. */
+#define TLS_FALLBACK_SCSV 0x5600
+
/* Cipher Suite Values starting with 0xC000 are defined in informational
* RFCs.
*/
diff --git a/chromium/net/third_party/nss/ssl/sslsecur.c b/chromium/net/third_party/nss/ssl/sslsecur.c
index 6c7532e2552..99538e532a6 100644
--- a/chromium/net/third_party/nss/ssl/sslsecur.c
+++ b/chromium/net/third_party/nss/ssl/sslsecur.c
@@ -97,14 +97,13 @@ ssl_Do1stHandshake(sslSocket *ss)
ss->securityHandshake = 0;
}
if (ss->handshake == 0) {
- ssl_GetRecvBufLock(ss);
- ss->gs.recordLen = 0;
- ss->gs.writeOffset = 0;
- ss->gs.readOffset = 0;
- ssl_ReleaseRecvBufLock(ss);
-
- SSL_TRC(3, ("%d: SSL[%d]: handshake is completed",
- SSL_GETPID(), ss->fd));
+ /* for v3 this is done in ssl3_FinishHandshake */
+ if (!ss->firstHsDone && ss->version < SSL_LIBRARY_VERSION_3_0) {
+ ssl_GetRecvBufLock(ss);
+ ss->gs.recordLen = 0;
+ ssl_FinishHandshake(ss);
+ ssl_ReleaseRecvBufLock(ss);
+ }
break;
}
rv = (*ss->handshake)(ss);
@@ -125,6 +124,24 @@ ssl_Do1stHandshake(sslSocket *ss)
return rv;
}
+void
+ssl_FinishHandshake(sslSocket *ss)
+{
+ PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+
+ SSL_TRC(3, ("%d: SSL[%d]: handshake is completed", SSL_GETPID(), ss->fd));
+
+ ss->firstHsDone = PR_TRUE;
+ ss->enoughFirstHsDone = PR_TRUE;
+ ss->gs.writeOffset = 0;
+ ss->gs.readOffset = 0;
+
+ if (ss->handshakeCallback) {
+ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
+ }
+}
+
/*
* Handshake function that blocks. Used to force a
* retry on a connection on the next read/write.
@@ -260,7 +277,7 @@ SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache)
/* SSL v2 protocol does not support subsequent handshakes. */
if (ss->version < SSL_LIBRARY_VERSION_3_0) {
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
} else {
ssl_GetSSL3HandshakeLock(ss);
@@ -330,7 +347,7 @@ SSL_HandshakeCallback(PRFileDesc *fd, SSLHandshakeCallback cb,
*/
SECStatus
SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb,
- void *client_data)
+ void *arg)
{
sslSocket *ss;
@@ -350,7 +367,7 @@ SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb,
ssl_GetSSL3HandshakeLock(ss);
ss->canFalseStartCallback = cb;
- ss->canFalseStartCallbackData = client_data;
+ ss->canFalseStartCallbackData = arg;
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss);
@@ -358,19 +375,15 @@ SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb,
return SECSuccess;
}
-/* A utility function that can be called from a custom SSLCanFalseStartCallback
-** function to determine what NSS would have done for this connection if the
-** custom callback was not implemented.
-*/
SECStatus
-SSL_DefaultCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
+SSL_RecommendedCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
{
sslSocket *ss;
*canFalseStart = PR_FALSE;
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_DefaultCanFalseStart",
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RecommendedCanFalseStart",
SSL_GETPID(), fd));
return SECFailure;
}
@@ -587,6 +600,9 @@ DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
int amount;
int available;
+ /* ssl3_GatherAppDataRecord may call ssl_FinishHandshake, which needs the
+ * 1stHandshakeLock. */
+ ssl_Get1stHandshakeLock(ss);
ssl_GetRecvBufLock(ss);
available = ss->gs.writeOffset - ss->gs.readOffset;
@@ -653,6 +669,7 @@ DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
done:
ssl_ReleaseRecvBufLock(ss);
+ ssl_Release1stHandshakeLock(ss);
return rv;
}
@@ -1219,7 +1236,8 @@ ssl_SecureRead(sslSocket *ss, unsigned char *buf, int len)
int
ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
{
- int rv = 0;
+ int rv = 0;
+ PRBool falseStart = PR_FALSE;
SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
SSL_GETPID(), ss->fd, len));
@@ -1254,14 +1272,14 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
ss->writerThread = PR_GetCurrentThread();
/* If any of these is non-zero, the initial handshake is not done. */
if (!ss->firstHsDone) {
- PRBool canFalseStart = PR_FALSE;
ssl_Get1stHandshakeLock(ss);
- if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
+ if (ss->opt.enableFalseStart &&
+ ss->version >= SSL_LIBRARY_VERSION_3_0) {
ssl_GetSSL3HandshakeLock(ss);
- canFalseStart = ss->ssl3.hs.canFalseStart;
+ falseStart = ss->ssl3.hs.canFalseStart;
ssl_ReleaseSSL3HandshakeLock(ss);
}
- if (!canFalseStart &&
+ if (!falseStart &&
(ss->handshake || ss->nextHandshake || ss->securityHandshake)) {
rv = ssl_Do1stHandshake(ss);
}
@@ -1286,6 +1304,17 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
goto done;
}
+ if (!ss->firstHsDone) {
+ PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_3_0);
+#ifdef DEBUG
+ ssl_GetSSL3HandshakeLock(ss);
+ PORT_Assert(ss->ssl3.hs.canFalseStart);
+ ssl_ReleaseSSL3HandshakeLock(ss);
+#endif
+ SSL_TRC(3, ("%d: SSL[%d]: SecureSend: sending data due to false start",
+ SSL_GETPID(), ss->fd));
+ }
+
/* Send out the data using one of these functions:
* ssl2_SendClear, ssl2_SendStream, ssl2_SendBlock,
* ssl3_SendApplicationData
@@ -1445,6 +1474,49 @@ SSL_InvalidateSession(PRFileDesc *fd)
return rv;
}
+static void
+ssl3_CacheSessionUnlocked(sslSocket *ss)
+{
+ PORT_Assert(!ss->sec.isServer);
+
+ if (ss->ssl3.hs.cacheSID) {
+ ss->sec.cache(ss->sec.ci.sid);
+ ss->ssl3.hs.cacheSID = PR_FALSE;
+ }
+}
+
+SECStatus
+SSL_CacheSession(PRFileDesc *fd)
+{
+ sslSocket * ss = ssl_FindSocket(fd);
+ SECStatus rv = SECFailure;
+
+ if (ss) {
+ ssl_Get1stHandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
+
+ ssl3_CacheSessionUnlocked(ss);
+ rv = SECSuccess;
+
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
+ }
+ return rv;
+}
+
+SECStatus
+SSL_CacheSessionUnlocked(PRFileDesc *fd)
+{
+ sslSocket * ss = ssl_FindSocket(fd);
+ SECStatus rv = SECFailure;
+
+ if (ss) {
+ ssl3_CacheSessionUnlocked(ss);
+ rv = SECSuccess;
+ }
+ return rv;
+}
+
SECItem *
SSL_GetSessionID(PRFileDesc *fd)
{
diff --git a/chromium/net/third_party/nss/ssl/sslsock.c b/chromium/net/third_party/nss/ssl/sslsock.c
index 072fad5ba0b..998c1371999 100644
--- a/chromium/net/third_party/nss/ssl/sslsock.c
+++ b/chromium/net/third_party/nss/ssl/sslsock.c
@@ -173,7 +173,9 @@ static sslOptions ssl_defaults = {
PR_FALSE, /* requireSafeNegotiation */
PR_FALSE, /* enableFalseStart */
PR_TRUE, /* cbcRandomIV */
- PR_FALSE /* enableOCSPStapling */
+ PR_FALSE, /* enableOCSPStapling */
+ PR_FALSE, /* enableSignedCertTimestamps */
+ PR_FALSE /* enableFallbackSCSV */
};
/*
@@ -366,6 +368,8 @@ ssl_DupSocket(sslSocket *os)
ss->badCertArg = os->badCertArg;
ss->handshakeCallback = os->handshakeCallback;
ss->handshakeCallbackData = os->handshakeCallbackData;
+ ss->canFalseStartCallback = os->canFalseStartCallback;
+ ss->canFalseStartCallbackData = os->canFalseStartCallbackData;
ss->pkcs11PinArg = os->pkcs11PinArg;
ss->getChannelID = os->getChannelID;
ss->getChannelIDArg = os->getChannelIDArg;
@@ -863,6 +867,14 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
ss->opt.enableOCSPStapling = on;
break;
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ ss->opt.enableSignedCertTimestamps = on;
+ break;
+
+ case SSL_ENABLE_FALLBACK_SCSV:
+ ss->opt.enableFallbackSCSV = on;
+ break;
+
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
@@ -933,6 +945,10 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break;
case SSL_CBC_RANDOM_IV: on = ss->opt.cbcRandomIV; break;
case SSL_ENABLE_OCSP_STAPLING: on = ss->opt.enableOCSPStapling; break;
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ on = ss->opt.enableSignedCertTimestamps;
+ break;
+ case SSL_ENABLE_FALLBACK_SCSV: on = ss->opt.enableFallbackSCSV; break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -994,6 +1010,12 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
case SSL_ENABLE_OCSP_STAPLING:
on = ssl_defaults.enableOCSPStapling;
break;
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ on = ssl_defaults.enableSignedCertTimestamps;
+ break;
+ case SSL_ENABLE_FALLBACK_SCSV:
+ on = ssl_defaults.enableFallbackSCSV;
+ break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -1161,6 +1183,14 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
ssl_defaults.enableOCSPStapling = on;
break;
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ ssl_defaults.enableSignedCertTimestamps = on;
+ break;
+
+ case SSL_ENABLE_FALLBACK_SCSV:
+ ssl_defaults.enableFallbackSCSV = on;
+ break;
+
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
@@ -1327,6 +1357,19 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled)
return rv;
}
+SECStatus
+SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers, unsigned int len)
+{
+ sslSocket *ss = ssl_FindSocket(fd);
+
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in CipherOrderSet", SSL_GETPID(),
+ fd));
+ return SECFailure;
+ }
+ return ssl3_CipherOrderSet(ss, ciphers, len);
+}
+
SECStatus
SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled)
{
@@ -1991,6 +2034,29 @@ SSL_PeerStapledOCSPResponses(PRFileDesc *fd)
return &ss->sec.ci.sid->peerCertStatus;
}
+const SECItem *
+SSL_PeerSignedCertTimestamps(PRFileDesc *fd)
+{
+ sslSocket *ss = ssl_FindSocket(fd);
+
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerSignedCertTimestamps",
+ SSL_GETPID(), fd));
+ return NULL;
+ }
+
+ if (!ss->sec.ci.sid) {
+ PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
+ return NULL;
+ }
+
+ if (ss->sec.ci.sid->version < SSL_LIBRARY_VERSION_3_0) {
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
+ return NULL;
+ }
+ return &ss->sec.ci.sid->u.ssl3.signedCertTimestamps;
+}
+
SECStatus
SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed) {
sslSocket *ss = ssl_FindSocket(fd);
@@ -3131,4 +3197,3 @@ loser:
}
return ss;
}
-
diff --git a/chromium/net/third_party/nss/ssl/sslt.h b/chromium/net/third_party/nss/ssl/sslt.h
index a8007d8b4cf..1f5e2c659ff 100644
--- a/chromium/net/third_party/nss/ssl/sslt.h
+++ b/chromium/net/third_party/nss/ssl/sslt.h
@@ -202,12 +202,14 @@ typedef enum {
ssl_signature_algorithms_xtn = 13,
ssl_use_srtp_xtn = 14,
ssl_app_layer_protocol_xtn = 16,
+ ssl_signed_certificate_timestamp_xtn = 18, /* RFC 6962 */
ssl_session_ticket_xtn = 35,
ssl_next_proto_nego_xtn = 13172,
- ssl_channel_id_xtn = 30031,
+ ssl_channel_id_xtn = 30032,
+ ssl_padding_xtn = 35655,
ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
} SSLExtensionType;
-#define SSL_MAX_EXTENSIONS 11
+#define SSL_MAX_EXTENSIONS 12 /* doesn't include ssl_padding_xtn. */
#endif /* __sslt_h_ */