--- 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_ */