Bug 958916: Update NSS to NSS 3.15.5 beta 2 (NSS_3_15_5_BETA2) plus private patch for bug 950129, CLOBBER, r=me
authorBrian Smith <brian@briansmith.org>
Thu, 16 Jan 2014 13:18:55 -0800
changeset 163858 cbed774ff9c0050dcc1eecded386bd95538abad4
parent 163857 c040b200b336b3054f221bbda150b4c0d7321fc6
child 163859 6a0e66cae4f8644a4e679069dc056cdb833279a4
push id38570
push userbrian@briansmith.org
push dateThu, 16 Jan 2014 21:24:23 +0000
treeherdermozilla-inbound@6a0e66cae4f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs958916, 950129
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 958916: Update NSS to NSS 3.15.5 beta 2 (NSS_3_15_5_BETA2) plus private patch for bug 950129, CLOBBER, r=me
CLOBBER
security/nss/TAG-INFO
security/nss/coreconf/WIN32.mk
security/nss/coreconf/coreconf.dep
security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c
security/nss/lib/ssl/ssl.h
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3ext.c
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/sslsock.c
security/nss/lib/ssl/sslt.h
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 897735 requires a clobber due to mass mochitest bustage otherwise
+Updates to NSS seem to require a clobber due bug 959928.
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-NSS_3_15_5_BETA1
+NSS_3_15_5_BETA2
--- a/security/nss/coreconf/WIN32.mk
+++ b/security/nss/coreconf/WIN32.mk
@@ -36,17 +36,17 @@ else
 	# Change the dots to spaces.
 	_CC_VERSION_WORDS := $(subst ., ,$(CC_VERSION))
 	_CC_VMAJOR  := $(word 1,$(_CC_VERSION_WORDS))
 	_CC_VMINOR  := $(word 2,$(_CC_VERSION_WORDS))
 	_CC_RELEASE := $(word 3,$(_CC_VERSION_WORDS))
 	_CC_BUILD   := $(word 4,$(_CC_VERSION_WORDS))
 	_MSC_VER     = $(_CC_VMAJOR)$(_CC_VMINOR)
 	_MSC_VER_6   = 1200
-	_MSC_VER_GTE18 := $(shell expr $(_MSC_VER) \>= 1800)
+	_MSC_VER_GE_18 := $(shell expr $(_MSC_VER) \>= 1800)
 	ifeq ($(_CC_VMAJOR),14)
 	    # -DYNAMICBASE is only supported on VC8SP1 or newer,
 	    # so be very specific here!
 	    # VC8 is 14.00.50727.42, VC8SP1 is 14.00.50727.762
 	    ifeq ($(_CC_RELEASE).$(_CC_BUILD),50727.42)
 		USE_DYNAMICBASE =
 	    else
 	    ifeq ($(_CC_RELEASE).$(_CC_BUILD),50727.762)
@@ -168,19 +168,19 @@ endif
 	LDFLAGS    += /FIXED:NO
     endif
 ifneq ($(_MSC_VER),$(_MSC_VER_6))
     # Convert certain deadly warnings to errors (see list at end of file)
     OS_CFLAGS += -we4002 -we4003 -we4004 -we4006 -we4009 -we4013 \
      -we4015 -we4028 -we4033 -we4035 -we4045 -we4047 -we4053 -we4054 -we4063 \
      -we4064 -we4078 -we4087 -we4090 -we4098 -we4390 -we4551 -we4553 -we4715
 
-	ifeq ($(_MSC_VER_GTE18),1)
-		OS_CFLAGS += -FS
-	endif
+    ifeq ($(_MSC_VER_GE_18),1)
+	OS_CFLAGS += -FS
+    endif
 endif # !MSVC6
 endif # NS_USE_GCC
 
 ifdef USE_64
 DEFINES += -DWIN64
 else
 DEFINES += -DWIN32
 endif
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,8 +5,9 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
+
--- a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c
@@ -126,16 +126,18 @@ pkix_pl_AIAMgr_RegisterSelf(void *plCont
  *  collection, and then stored at "pClient".
  *
  * PARAMETERS:
  *  "aiaMgr"
  *      The AIAMgr whose LDAPClient connected are to be managed. Must be
  *      non-NULL.
  *  "domainName"
  *      Address of a string pointing to a server name. Must be non-NULL.
+ *      An empty string (which means no <host> is given in the LDAP URL) is
+ *      not supported.
  *  "pClient"
  *      Address at which the returned LDAPClient is stored. Must be non-NULL.
  *  "plContext"
  *      Platform-specific context pointer.
  * THREAD SAFETY:
  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  * RETURNS:
  *  Returns NULL if the function succeeds.
@@ -150,16 +152,27 @@ pkix_pl_AiaMgr_FindLDAPClient(
         void *plContext)
 {
         PKIX_PL_String *domainString = NULL;
         PKIX_PL_LdapDefaultClient *client = NULL;
 
         PKIX_ENTER(AIAMGR, "pkix_pl_AiaMgr_FindLDAPClient");
         PKIX_NULLCHECK_THREE(aiaMgr, domainName, pClient);
 
+        /*
+         * An LDAP URL may not have a <host> part, for example,
+         *     ldap:///o=University%20of%20Michigan,c=US
+         * PKIX_PL_LdapDefaultClient doesn't know how to discover the default
+         * LDAP server, so we don't support this kind of LDAP URL.
+         */
+        if (*domainName == '\0') {
+                /* Simulate a PKIX_PL_LdapDefaultClient_CreateByName failure. */
+                PKIX_ERROR(PKIX_LDAPDEFAULTCLIENTCREATEBYNAMEFAILED);
+        }
+
         /* create PKIX_PL_String from domain name */
         PKIX_CHECK(PKIX_PL_String_Create
                 (PKIX_ESCASCII, domainName, 0, &domainString, plContext),
                 PKIX_STRINGCREATEFAILED);
 
         /* Is this domainName already in cache? */
         PKIX_CHECK(PKIX_PL_HashTable_Lookup
                 (aiaConnectionCache,
--- a/security/nss/lib/ssl/ssl.h
+++ b/security/nss/lib/ssl/ssl.h
@@ -157,16 +157,35 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRF
  * application_data records. Also, we only split application_data records and
  * not other types of records, because some implementations will not accept
  * fragmented records of some other types (e.g. some versions of NSS do not
  * accept fragmented alerts).
  */
 #define SSL_CBC_RANDOM_IV 23
 #define SSL_ENABLE_OCSP_STAPLING       24 /* Request OCSP stapling (client) */
 
+/* SSL_ENABLE_NPN controls whether the NPN extension is enabled for the initial
+ * handshake when protocol negotiation is used. SSL_SetNextProtoCallback
+ * or SSL_SetNextProtoNego must be used to control the protocol negotiation;
+ * otherwise, the NPN extension will not be negotiated. SSL_ENABLE_NPN is
+ * currently enabled by default but this may change in future versions.
+ */
+#define SSL_ENABLE_NPN 25
+
+/* SSL_ENABLE_ALPN controls whether the ALPN extension is enabled for the
+ * initial handshake when protocol negotiation is used. SSL_SetNextProtoNego
+ * (not SSL_SetNextProtoCallback) must be used to control the protocol
+ * negotiation; otherwise, the ALPN extension will not be negotiated. ALPN is
+ * not negotiated for renegotiation handshakes, even though the ALPN
+ * specification defines a way to use ALPN during renegotiations.
+ * SSL_ENABLE_ALPN is currently disabled by default, but this may change in
+ * future versions.
+ */
+#define SSL_ENABLE_ALPN 26
+
 #ifdef SSL_DEPRECATED_FUNCTION 
 /* Old deprecated function names */
 SSL_IMPORT SECStatus SSL_Enable(PRFileDesc *fd, int option, PRBool on);
 SSL_IMPORT SECStatus SSL_EnableDefault(int option, PRBool on);
 #endif
 
 /* New function names */
 SSL_IMPORT SECStatus SSL_OptionSet(PRFileDesc *fd, PRInt32 option, PRBool on);
@@ -201,26 +220,37 @@ SSL_IMPORT SECStatus SSL_SetNextProtoCal
                                               void *arg);
 
 /* SSL_SetNextProtoNego can be used as an alternative to
  * SSL_SetNextProtoCallback. It also causes a client to advertise NPN and
  * installs a default callback function which selects the first supported
  * protocol in server-preference order. If no matching protocol is found it
  * selects the first supported protocol.
  *
+ * Using this function also allows the client to transparently support ALPN.
+ * The same set of protocols will be advertised via ALPN and, if the server
+ * uses ALPN to select a protocol, SSL_GetNextProto will return
+ * SSL_NEXT_PROTO_SELECTED as the state.
+ *
+ * Since NPN uses the first protocol as the fallback protocol, when sending an
+ * ALPN extension, the first protocol is moved to the end of the list. This
+ * indicates that the fallback protocol is the least preferred. The other
+ * protocols should be in preference order.
+ *
  * The supported protocols are specified in |data| in wire-format (8-bit
  * length-prefixed). For example: "\010http/1.1\006spdy/2". */
 SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd,
 					  const unsigned char *data,
 					  unsigned int length);
 
 typedef enum SSLNextProtoState { 
   SSL_NEXT_PROTO_NO_SUPPORT = 0, /* No peer support                */
   SSL_NEXT_PROTO_NEGOTIATED = 1, /* Mutual agreement               */
-  SSL_NEXT_PROTO_NO_OVERLAP = 2  /* No protocol overlap found      */
+  SSL_NEXT_PROTO_NO_OVERLAP = 2, /* No protocol overlap found      */
+  SSL_NEXT_PROTO_SELECTED   = 3  /* Server selected proto (ALPN)   */
 } SSLNextProtoState;
 
 /* SSL_GetNextProto can be used in the HandshakeCallback or any time after
  * a handshake to retrieve the result of the Next Protocol negotiation.
  *
  * The length of the negotiated protocol, if any, is written into *bufLen.
  * If the negotiated protocol is longer than bufLenMax, then SECFailure is
  * returned. Otherwise, the negotiated protocol, if any, is written into buf,
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -4835,16 +4835,17 @@ ssl3_SendClientHello(sslSocket *ss, PRBo
     ssl3CipherSpec * cwSpec;
     SECStatus        rv;
     int              i;
     int              length;
     int              num_suites;
     int              actual_count = 0;
     PRBool           isTLS = PR_FALSE;
     PRInt32          total_exten_len = 0;
+    unsigned         paddingExtensionLen;
     unsigned         numCompressionMethods;
     PRInt32          flags;
 
     SSL_TRC(3, ("%d: SSL3[%d]: send client_hello handshake", SSL_GETPID(),
 		ss->fd));
 
     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
     PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
@@ -5108,16 +5109,30 @@ ssl3_SendClientHello(sslSocket *ss, PRBo
     length = sizeof(SSL3ProtocolVersion) + SSL3_RANDOM_LENGTH +
 	1 + ((sid == NULL) ? 0 : sid->u.ssl3.sessionIDLength) +
 	2 + num_suites*sizeof(ssl3CipherSuite) +
 	1 + numCompressionMethods + total_exten_len;
     if (IS_DTLS(ss)) {
 	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) {
 	if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
 	return rv;	/* err set by ssl3_AppendHandshake* */
     }
 
     if (ss->firstHsDone) {
 	/* The client hello version must stay unchanged to work around
@@ -5242,16 +5257,24 @@ ssl3_SendClientHello(sslSocket *ss, PRBo
 	}
 
 	extLen = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, maxBytes, NULL);
 	if (extLen < 0) {
 	    if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
 	    return SECFailure;
 	}
 	maxBytes -= extLen;
+
+	extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes);
+	if (extLen < 0) {
+	    if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
+	    return SECFailure;
+	}
+	maxBytes -= extLen;
+
 	PORT_Assert(!maxBytes);
     } 
 
     if (sid->u.ssl3.lock) {
         PR_RWLock_Unlock(sid->u.ssl3.lock);
     }
 
     if (ss->xtnData.sentSessionTicketInClientHello) {
@@ -10157,18 +10180,20 @@ ssl3_TLSPRFWithMasterSecret(ssl3CipherSp
  */
 static SECStatus
 ssl3_SendNextProto(sslSocket *ss)
 {
     SECStatus rv;
     int padding_len;
     static const unsigned char padding[32] = {0};
 
-    if (ss->ssl3.nextProto.len == 0)
+    if (ss->ssl3.nextProto.len == 0 ||
+	ss->ssl3.nextProtoState == SSL_NEXT_PROTO_SELECTED) {
 	return SECSuccess;
+    }
 
     PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     padding_len = 32 - ((ss->ssl3.nextProto.len + 2) % 32);
 
     rv = ssl3_AppendHandshakeHeader(ss, next_proto, ss->ssl3.nextProto.len +
 						    2 + padding_len);
--- a/security/nss/lib/ssl/ssl3ext.c
+++ b/security/nss/lib/ssl/ssl3ext.c
@@ -47,18 +47,22 @@ static SECStatus ssl3_GetSessionTicketKe
     PRUint32 *mac_key_length);
 #endif
 static PRInt32 ssl3_SendRenegotiationInfoXtn(sslSocket * ss,
     PRBool append, PRUint32 maxBytes);
 static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, 
     PRUint16 ex_type, SECItem *data);
 static SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss,
 			PRUint16 ex_type, SECItem *data);
+static SECStatus ssl3_ClientHandleAppProtoXtn(sslSocket *ss,
+			PRUint16 ex_type, SECItem *data);
 static SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss,
 			PRUint16 ex_type, SECItem *data);
+static PRInt32 ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append,
+					  PRUint32 maxBytes);
 static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
 					       PRUint32 maxBytes);
 static PRInt32 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append,
     PRUint32 maxBytes);
 static SECStatus ssl3_HandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type,
     SECItem *data);
 static SECStatus ssl3_ServerSendStatusRequestXtn(sslSocket * ss,
     PRBool append, PRUint32 maxBytes);
@@ -242,16 +246,17 @@ static const ssl3HelloExtensionHandler c
 /* These two tables are used by the client, to handle server hello
  * extensions. */
 static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
     { ssl_server_name_xtn,        &ssl3_HandleServerNameXtn },
     /* TODO: add a handler for ssl_ec_point_formats_xtn */
     { ssl_session_ticket_xtn,     &ssl3_ClientHandleSessionTicketXtn },
     { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
     { ssl_next_proto_nego_xtn,    &ssl3_ClientHandleNextProtoNegoXtn },
+    { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn },
     { ssl_use_srtp_xtn,           &ssl3_HandleUseSRTPXtn },
     { ssl_cert_status_xtn,        &ssl3_ClientHandleStatusRequestXtn },
     { -1, NULL }
 };
 
 static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = {
     { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
     { -1, NULL }
@@ -268,16 +273,17 @@ ssl3HelloExtensionSender clientHelloSend
     { ssl_server_name_xtn,        &ssl3_SendServerNameXtn        },
     { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn },
 #ifdef NSS_ENABLE_ECC
     { ssl_elliptic_curves_xtn,    &ssl3_SendSupportedCurvesXtn },
     { ssl_ec_point_formats_xtn,   &ssl3_SendSupportedPointFormatsXtn },
 #endif
     { ssl_session_ticket_xtn,     &ssl3_SendSessionTicketXtn },
     { ssl_next_proto_nego_xtn,    &ssl3_ClientSendNextProtoNegoXtn },
+    { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn },
     { ssl_use_srtp_xtn,           &ssl3_SendUseSRTPXtn },
     { ssl_cert_status_xtn,        &ssl3_ClientSendStatusRequestXtn },
     { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
     /* any extra entries will appear as { 0, NULL }    */
 };
 
 static const 
 ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] = {
@@ -603,16 +609,26 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSoc
 				  SECItem *data)
 {
     SECStatus rv;
     unsigned char resultBuffer[255];
     SECItem result = { siBuffer, resultBuffer, 0 };
 
     PORT_Assert(!ss->firstHsDone);
 
+    if (ssl3_ExtensionNegotiated(ss, ssl_app_layer_protocol_xtn)) {
+	/* If the server negotiated ALPN then it has already told us what protocol
+	 * to use, so it doesn't make sense for us to try to negotiate a different
+	 * one by sending the NPN handshake message. However, if we've negotiated
+	 * NPN then we're required to send the NPN handshake message. Thus, these
+	 * two extensions cannot both be negotiated on the same connection. */
+	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+	return SECFailure;
+    }
+
     rv = ssl3_ValidateNextProtoNego(data->data, data->len);
     if (rv != SECSuccess)
 	return rv;
 
     /* ss->nextProtoCallback cannot normally be NULL if we negotiated the
      * extension. However, It is possible that an application erroneously
      * cleared the callback between the time we sent the ClientHello and now.
      */
@@ -636,24 +652,61 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSoc
     }
 
     ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
 
     SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
     return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result);
 }
 
+static SECStatus
+ssl3_ClientHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
+{
+    const unsigned char* d = data->data;
+    PRUint16 name_list_len;
+    SECItem protocol_name;
+
+    if (ssl3_ExtensionNegotiated(ss, ssl_next_proto_nego_xtn)) {
+	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+	return SECFailure;
+    }
+
+    /* The extension data from the server has the following format:
+     *   uint16 name_list_len;
+     *   uint8 len;
+     *   uint8 protocol_name[len]; */
+    if (data->len < 4 || data->len > 2 + 1 + 255) {
+	PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
+	return SECFailure;
+    }
+
+    name_list_len = ((PRUint16) d[0]) << 8 |
+	            ((PRUint16) d[1]);
+    if (name_list_len != data->len - 2 || d[2] != data->len - 3) {
+	PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
+	return SECFailure;
+    }
+
+    protocol_name.data = data->data + 3;
+    protocol_name.len = data->len - 3;
+
+    SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
+    ss->ssl3.nextProtoState = SSL_NEXT_PROTO_SELECTED;
+    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
+    return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &protocol_name);
+}
+
 static PRInt32
 ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append,
 				PRUint32 maxBytes)
 {
     PRInt32 extension_length;
 
     /* Renegotiations do not send this extension. */
-    if (!ss->nextProtoCallback || ss->firstHsDone) {
+    if (!ss->opt.enableNPN || !ss->nextProtoCallback || ss->firstHsDone) {
 	return 0;
     }
 
     extension_length = 4;
 
     if (append && maxBytes >= extension_length) {
 	SECStatus rv;
 	rv = ssl3_AppendHandshakeNumber(ss, ssl_next_proto_nego_xtn, 2);
@@ -669,16 +722,84 @@ ssl3_ClientSendNextProtoNegoXtn(sslSocke
     }
 
     return extension_length;
 
 loser:
     return -1;
 }
 
+static PRInt32
+ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
+{
+    PRInt32 extension_length;
+    unsigned char *alpn_protos = NULL;
+
+    /* Renegotiations do not send this extension. */
+    if (!ss->opt.enableALPN || !ss->opt.nextProtoNego.data || ss->firstHsDone) {
+	return 0;
+    }
+
+    extension_length = 2 /* extension type */ + 2 /* extension length */ +
+		       2 /* protocol name list length */ +
+		       ss->opt.nextProtoNego.len;
+
+    if (append && maxBytes >= extension_length) {
+	/* NPN requires that the client's fallback protocol is first in the
+	 * list. However, ALPN sends protocols in preference order. So we
+	 * allocate a buffer and move the first protocol to the end of the
+	 * list. */
+	SECStatus rv;
+	const unsigned int len = ss->opt.nextProtoNego.len;
+
+	alpn_protos = PORT_Alloc(len);
+	if (alpn_protos == NULL) {
+	    return SECFailure;
+	}
+	if (len > 0) {
+	    /* Each protocol string is prefixed with a single byte length. */
+	    unsigned int i = ss->opt.nextProtoNego.data[0] + 1;
+	    if (i <= len) {
+		memcpy(alpn_protos, &ss->opt.nextProtoNego.data[i], len - i);
+		memcpy(alpn_protos + len - i, ss->opt.nextProtoNego.data, i);
+	    } else {
+		/* This seems to be invalid data so we'll send as-is. */
+		memcpy(alpn_protos, ss->opt.nextProtoNego.data, len);
+	    }
+	}
+
+	rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2);
+	if (rv != SECSuccess) {
+	    goto loser;
+	}
+	rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
+	if (rv != SECSuccess) {
+	    goto loser;
+	}
+	rv = ssl3_AppendHandshakeVariable(ss, alpn_protos, len, 2);
+	PORT_Free(alpn_protos);
+	alpn_protos = NULL;
+	if (rv != SECSuccess) {
+	    goto loser;
+	}
+	ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
+		ssl_app_layer_protocol_xtn;
+    } else if (maxBytes < extension_length) {
+	return 0;
+    }
+
+    return extension_length;
+
+loser:
+    if (alpn_protos) {
+	PORT_Free(alpn_protos);
+    }
+    return -1;
+}
+
 static SECStatus
 ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type,
                                  SECItem *data)
 {
     /* The echoed extension must be empty. */
     if (data->len != 0)
        return SECFailure;
 
@@ -2136,8 +2257,60 @@ ssl3_ClientSendSigAlgsXtn(sslSocket * ss
 	return 0;
     }
 
     return extension_length;
 
 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;
+    static 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;
+    if (SECSuccess != ssl3_AppendHandshake(ss, padding, paddingLen))
+	return -1;
+
+    return extensionLen;
+}
--- a/security/nss/lib/ssl/sslimpl.h
+++ b/security/nss/lib/ssl/sslimpl.h
@@ -221,16 +221,23 @@ typedef struct {
 extern SECStatus 
 ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type,
 				        ssl3HelloExtensionSenderFunc cb);
 
 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 *);
     PRFileDesc *(*accept)  (sslSocket *, PRNetAddr *);
     int         (*bind)    (sslSocket *, const PRNetAddr *);
     int         (*listen)  (sslSocket *, int);
     int         (*shutdown)(sslSocket *, int);
     int         (*close)   (sslSocket *);
@@ -312,16 +319,18 @@ typedef struct sslOptionsStr {
     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 enableNPN              : 1;  /* 26 */
+    unsigned int enableALPN             : 1;  /* 27 */
 } sslOptions;
 
 typedef enum { sslHandshakingUndetermined = 0,
 	       sslHandshakingAsClient,
 	       sslHandshakingAsServer 
 } sslHandshakingType;
 
 typedef struct sslServerCertsStr {
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -73,17 +73,19 @@ static sslOptions ssl_defaults = {
     PR_FALSE,   /* bypassPKCS11       */
     PR_FALSE,   /* noLocks            */
     PR_FALSE,   /* enableSessionTickets */
     PR_FALSE,   /* enableDeflate      */
     2,          /* enableRenegotiation (default: requires extension) */
     PR_FALSE,   /* requireSafeNegotiation */
     PR_FALSE,   /* enableFalseStart   */
     PR_TRUE,    /* cbcRandomIV        */
-    PR_FALSE    /* enableOCSPStapling */
+    PR_FALSE,   /* enableOCSPStapling */
+    PR_TRUE,    /* enableNPN          */
+    PR_FALSE    /* enableALPN         */
 };
 
 /*
  * default range of enabled SSL/TLS protocols
  */
 static SSLVersionRange versions_defaults_stream = {
     SSL_LIBRARY_VERSION_3_0,
     SSL_LIBRARY_VERSION_TLS_1_0
@@ -759,16 +761,24 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 wh
       case SSL_CBC_RANDOM_IV:
 	ss->opt.cbcRandomIV = on;
 	break;
 
       case SSL_ENABLE_OCSP_STAPLING:
        ss->opt.enableOCSPStapling = on;
        break;
 
+      case SSL_ENABLE_NPN:
+	ss->opt.enableNPN = on;
+	break;
+
+      case SSL_ENABLE_ALPN:
+	ss->opt.enableALPN = on;
+	break;
+
       default:
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	rv = SECFailure;
     }
 
     /* We can't use the macros for releasing the locks here,
      * because ss->opt.noLocks might have changed just above.
      * We must release these locks (monitors) here, if we aquired them above,
@@ -829,16 +839,18 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 wh
     case SSL_ENABLE_DEFLATE:      on = ss->opt.enableDeflate;      break;
     case SSL_ENABLE_RENEGOTIATION:     
                                   on = ss->opt.enableRenegotiation; break;
     case SSL_REQUIRE_SAFE_NEGOTIATION: 
                                   on = ss->opt.requireSafeNegotiation; break;
     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_NPN:          on = ss->opt.enableNPN;          break;
+    case SSL_ENABLE_ALPN:         on = ss->opt.enableALPN;         break;
 
     default:
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	rv = SECFailure;
     }
 
     ssl_ReleaseSSL3HandshakeLock(ss);
     ssl_Release1stHandshakeLock(ss);
@@ -890,16 +902,18 @@ SSL_OptionGetDefault(PRInt32 which, PRBo
     case SSL_REQUIRE_SAFE_NEGOTIATION: 
                                   on = ssl_defaults.requireSafeNegotiation; 
 				  break;
     case SSL_ENABLE_FALSE_START:  on = ssl_defaults.enableFalseStart;   break;
     case SSL_CBC_RANDOM_IV:       on = ssl_defaults.cbcRandomIV;        break;
     case SSL_ENABLE_OCSP_STAPLING:
        on = ssl_defaults.enableOCSPStapling;
        break;
+    case SSL_ENABLE_NPN:          on = ssl_defaults.enableNPN;          break;
+    case SSL_ENABLE_ALPN:         on = ssl_defaults.enableALPN;         break;
 
     default:
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	rv = SECFailure;
     }
 
     *pOn = on;
     return rv;
@@ -1057,16 +1071,24 @@ SSL_OptionSetDefault(PRInt32 which, PRBo
       case SSL_CBC_RANDOM_IV:
 	ssl_defaults.cbcRandomIV = on;
 	break;
 
       case SSL_ENABLE_OCSP_STAPLING:
        ssl_defaults.enableOCSPStapling = on;
        break;
 
+      case SSL_ENABLE_NPN:
+	ssl_defaults.enableNPN = on;
+	break;
+
+      case SSL_ENABLE_ALPN:
+	ssl_defaults.enableALPN = on;
+	break;
+
       default:
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	return SECFailure;
     }
     return SECSuccess;
 }
 
 /* function tells us if the cipher suite is one that we no longer support. */
--- a/security/nss/lib/ssl/sslt.h
+++ b/security/nss/lib/ssl/sslt.h
@@ -182,16 +182,18 @@ typedef enum {
     ssl_server_name_xtn              = 0,
     ssl_cert_status_xtn              = 5,
 #ifdef NSS_ENABLE_ECC
     ssl_elliptic_curves_xtn          = 10,
     ssl_ec_point_formats_xtn         = 11,
 #endif
     ssl_signature_algorithms_xtn     = 13,
     ssl_use_srtp_xtn                 = 14,
+    ssl_app_layer_protocol_xtn       = 16,
     ssl_session_ticket_xtn           = 35,
     ssl_next_proto_nego_xtn          = 13172,
+    ssl_padding_xtn                  = 35655,
     ssl_renegotiation_info_xtn       = 0xff01	/* experimental number */
 } SSLExtensionType;
 
-#define SSL_MAX_EXTENSIONS             9
+#define SSL_MAX_EXTENSIONS             10 /* doesn't include ssl_padding_xtn. */
 
 #endif /* __sslt_h_ */