Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(758)

Unified Diff: net/third_party/nss/patches/falsestart.patch

Issue 518065: Disable Nagle on Linux and TLS cut through support (Closed)
Patch Set: ... Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/third_party/nss/patches/falsestart.patch
diff --git a/net/third_party/nss/patches/falsestart.patch b/net/third_party/nss/patches/falsestart.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2bcb88f749b29cfcbd2fb1ab093751d6a5fa84ad
--- /dev/null
+++ b/net/third_party/nss/patches/falsestart.patch
@@ -0,0 +1,806 @@
+diff --git a/mozilla/security/nss/cmd/strsclnt/strsclnt.c b/mozilla/security/nss/cmd/strsclnt/strsclnt.c
wtc 2010/02/20 00:39:51 Remove the NPN changes from this patch.
+index c266644..1f71434 100644
+--- a/mozilla/security/nss/cmd/strsclnt/strsclnt.c
++++ b/mozilla/security/nss/cmd/strsclnt/strsclnt.c
+@@ -162,6 +162,7 @@ static PRBool disableLocking = PR_FALSE;
+ static PRBool ignoreErrors = PR_FALSE;
+ static PRBool enableSessionTickets = PR_FALSE;
+ static PRBool enableCompression = PR_FALSE;
++static PRBool enableFalseStart = PR_FALSE;
+
+ PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT;
+
+@@ -197,7 +198,8 @@ Usage(const char *progName)
+ " -U means enable throttling up threads\n"
+ " -B bypasses the PKCS11 layer for SSL encryption and MACing\n"
+ " -u enable TLS Session Ticket extension\n"
+- " -z enable compression\n",
++ " -z enable compression\n"
++ " -g enable false start\n",
+ progName);
+ exit(1);
+ }
+@@ -1244,6 +1246,12 @@ client_main(
+ errExit("SSL_OptionSet SSL_ENABLE_DEFLATE");
+ }
+
++ if (enableFalseStart) {
++ rv = SSL_OptionSet(model_sock, SSL_ENABLE_FALSE_START, PR_TRUE);
++ if (rv != SECSuccess)
++ errExit("SSL_OptionSet SSL_ENABLE_FALSE_START");
++ }
++
+ SSL_SetURL(model_sock, hostName);
+
+ SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate,
+@@ -1354,7 +1362,7 @@ main(int argc, char **argv)
+
+
+ optstate = PL_CreateOptState(argc, argv,
+- "23BC:DNP:TUW:a:c:d:f:in:op:qst:uvw:z");
++ "23BC:DNP:TUW:a:c:d:f:gin:op:qst:uvw:z");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch(optstate->option) {
+
+@@ -1384,6 +1392,8 @@ main(int argc, char **argv)
+
+ case 'f': fileName = optstate->value; break;
+
++ case 'g': enableFalseStart = PR_TRUE; break;
++
+ case 'i': ignoreErrors = PR_TRUE; break;
+
+ case 'n': nickName = PL_strdup(optstate->value); break;
+diff --git a/mozilla/security/nss/cmd/tstclnt/tstclnt.c b/mozilla/security/nss/cmd/tstclnt/tstclnt.c
+index c15a0ad..d209a33 100644
+--- a/mozilla/security/nss/cmd/tstclnt/tstclnt.c
++++ b/mozilla/security/nss/cmd/tstclnt/tstclnt.c
+@@ -225,6 +225,7 @@ static void Usage(const char *progName)
+ fprintf(stderr, "%-20s Renegotiate N times (resuming session if N>1).\n", "-r N");
+ fprintf(stderr, "%-20s Enable the session ticket extension.\n", "-u");
+ fprintf(stderr, "%-20s Enable compression.\n", "-z");
++ fprintf(stderr, "%-20s Enable false start.\n", "-g");
+ fprintf(stderr, "%-20s Letter(s) chosen from the following list\n",
+ "-c ciphers");
+ fprintf(stderr,
+@@ -521,6 +522,7 @@ int main(int argc, char **argv)
+ int useExportPolicy = 0;
+ int enableSessionTickets = 0;
+ int enableCompression = 0;
++ int enableFalseStart = 0;
+ PRSocketOptionData opt;
+ PRNetAddr addr;
+ PRPollDesc pollset[2];
+@@ -551,7 +553,7 @@ int main(int argc, char **argv)
+ }
+
+ optstate = PL_CreateOptState(argc, argv,
+- "23BSTW:a:c:d:fh:m:n:op:qr:suvw:xz");
++ "23BSTW:a:c:d:fgh:m:n:op:qr:suvw:xz");
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+@@ -578,6 +580,8 @@ int main(int argc, char **argv)
+
+ case 'c': cipherString = PORT_Strdup(optstate->value); break;
+
++ case 'g': enableFalseStart = 1; break;
++
+ case 'd': certDir = PORT_Strdup(optstate->value); break;
+
+ case 'f': clientSpeaksFirst = PR_TRUE; break;
+@@ -863,7 +867,20 @@ int main(int argc, char **argv)
+ SECU_PrintError(progName, "error enabling compression");
+ return 1;
+ }
+-
++
++ rv = SSL_SetNextProtoNego(s, "\004flip\004http1.1", 10);
++ if (rv != SECSuccess) {
++ SECU_PrintError(progName, "error enabling next protocol negotiation");
++ return 1;
++ }
++
++ /* enable false start. */
++ rv = SSL_OptionSet(s, SSL_ENABLE_FALSE_START, enableFalseStart);
++ if (rv != SECSuccess) {
++ SECU_PrintError(progName, "error enabling false start");
++ return 1;
++ }
++
+ SSL_SetPKCS11PinArg(s, &pwdata);
+
+ SSL_AuthCertificateHook(s, SSL_AuthCertificate, (void *)handle);
+diff --git a/mozilla/security/nss/lib/ssl/ssl.def b/mozilla/security/nss/lib/ssl/ssl.def
+index d3f455c..a1f4b51 100644
+--- a/mozilla/security/nss/lib/ssl/ssl.def
++++ b/mozilla/security/nss/lib/ssl/ssl.def
+@@ -152,3 +152,10 @@ SSL_SNISocketConfigHook;
+ ;+ local:
+ ;+*;
+ ;+};
++;+NSS_CHROMIUM {
++;+ global:
++SSL_GetNextProto;
++SSL_SetNextProtoNego;
++;+ local:
++;+*;
++;+};
+diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/ssl.h
+index e285ab4..60fc9b5 100644
+--- a/mozilla/security/nss/lib/ssl/ssl.h
++++ b/mozilla/security/nss/lib/ssl/ssl.h
+@@ -128,6 +128,17 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd);
+ /* Renegotiation Info (RI) */
+ /* extension in ALL handshakes. */
+ /* default: off */
++#define SSL_ENABLE_FALSE_START 22 /* Enable SSL false start (off by */
++ /* default, applies only to */
++ /* clients). False start is a */
++/* mode where an SSL client will start sending application data before */
++/* verifing the server's Finished message. This means that we could end up */
++/* sending data to an imposter. However, the data will be encrypted and */
++/* only the true server can decrypt the session key. Thus, so long as the */
++/* cipher isn't broken this is safe. Because of this, False Start will only */
++/* occur on RSA ciphersuites where the cipher's key length is >= 80 bits. */
++/* The advantage of False Start is that it saves a round trip for */
++/* client-speaks-first protocols when performing a full handshake. */
+
+ #ifdef SSL_DEPRECATED_FUNCTION
+ /* Old deprecated function names */
+@@ -142,6 +153,18 @@ SSL_IMPORT SECStatus SSL_OptionSetDefault(PRInt32 option, PRBool on);
+ SSL_IMPORT SECStatus SSL_OptionGetDefault(PRInt32 option, PRBool *on);
+ SSL_IMPORT SECStatus SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle);
+
++SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd,
++ const unsigned char *data,
++ unsigned short length);
++SSL_IMPORT SECStatus SSL_GetNextProto(PRFileDesc *fd,
++ int *state,
++ unsigned char *buf,
++ unsigned *length,
++ unsigned buf_len);
++#define SSL_NEXT_PROTO_NO_SUPPORT 0 /* No peer support */
++#define SSL_NEXT_PROTO_NEGOTIATED 1 /* Mutual agreement */
++#define SSL_NEXT_PROTO_NO_OVERLAP 2 /* No protocol overlap found */
++
+ /*
+ ** Control ciphers that SSL uses. If on is non-zero then the named cipher
+ ** is enabled, otherwise it is disabled.
+diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c
+index 6b37c4f..dd1ac73 100644
+--- a/mozilla/security/nss/lib/ssl/ssl3con.c
++++ b/mozilla/security/nss/lib/ssl/ssl3con.c
+@@ -81,6 +81,7 @@ static SECStatus ssl3_InitState( sslSocket *ss);
+ static SECStatus ssl3_SendCertificate( sslSocket *ss);
+ static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss);
+ static SECStatus ssl3_SendCertificateRequest(sslSocket *ss);
++static SECStatus ssl3_SendNextProto( sslSocket *ss);
+ static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags);
+ static SECStatus ssl3_SendServerHello( sslSocket *ss);
+ static SECStatus ssl3_SendServerHelloDone( sslSocket *ss);
+@@ -5656,7 +5657,15 @@ ssl3_RestartHandshakeAfterCertReq(sslSocket * ss,
+ return rv;
+ }
+
+-
++PRBool
++ssl3_CanFalseStart(sslSocket *ss) {
++ return ss->opt.enableFalseStart &&
++ !ss->sec.isServer &&
++ !ss->ssl3.hs.isResuming &&
++ ss->ssl3.cwSpec &&
++ ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10 &&
++ ss->ssl3.hs.kea_def->exchKeyType == kt_rsa;
++}
+
+ /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
+ * ssl3 Server Hello Done message.
+@@ -5717,6 +5726,12 @@ ssl3_HandleServerHelloDone(sslSocket *ss)
+ if (rv != SECSuccess) {
+ goto loser; /* err code was set. */
+ }
++
++ rv = ssl3_SendNextProto(ss);
++ if (rv != SECSuccess) {
++ goto loser; /* err code was set. */
++ }
++
+ rv = ssl3_SendFinished(ss, 0);
+ if (rv != SECSuccess) {
+ goto loser; /* err code was set. */
+@@ -5728,6 +5743,12 @@ ssl3_HandleServerHelloDone(sslSocket *ss)
+ ss->ssl3.hs.ws = wait_new_session_ticket;
+ else
+ ss->ssl3.hs.ws = wait_change_cipher;
++
++ /* Do the handshake callback for sslv3 here. */
++ if (ss->handshakeCallback != NULL && ssl3_CanFalseStart(ss)) {
++ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
++ }
++
+ return SECSuccess;
+
+ loser:
+@@ -8138,6 +8159,40 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
+ }
+
+ /* called from ssl3_HandleServerHelloDone
++ */
++static SECStatus
++ssl3_SendNextProto(sslSocket *ss)
++{
++ SECStatus rv;
++ int padding_len;
++ static const unsigned char padding[32] = {0};
++
++ if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NO_SUPPORT)
++ 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);
++ if (rv != SECSuccess) {
++ return rv; /* error code set by AppendHandshakeHeader */
++ }
++ rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.nextProto.data,
++ ss->ssl3.nextProto.len, 1);
++ if (rv != SECSuccess) {
++ return rv; /* error code set by AppendHandshake */
++ }
++ rv = ssl3_AppendHandshakeVariable(ss, padding, padding_len, 1);
++ if (rv != SECSuccess) {
++ return rv; /* error code set by AppendHandshake */
++ }
++ return rv;
++}
++
++/* called from ssl3_HandleServerHelloDone
+ * ssl3_HandleClientHello
+ * ssl3_HandleFinished
+ */
+@@ -8468,7 +8523,7 @@ xmit_loser:
+ ss->ssl3.hs.ws = idle_handshake;
+
+ /* Do the handshake callback for sslv3 here. */
+- if (ss->handshakeCallback != NULL) {
++ if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) {
+ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
+ }
+
+@@ -9457,6 +9512,11 @@ ssl3_DestroySSL3Info(sslSocket *ss)
+ ssl3_DestroyCipherSpec(&ss->ssl3.specs[1], PR_TRUE/*freeSrvName*/);
+
+ ss->ssl3.initialized = PR_FALSE;
++
++ if (ss->ssl3.nextProto.data) {
++ PORT_Free(ss->ssl3.nextProto.data);
++ ss->ssl3.nextProto.data = NULL;
++ }
+ }
+
+ /* End of ssl3con.c */
+diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/ssl/ssl3ext.c
+index fd0d9b9..ead0cfd 100644
+--- a/mozilla/security/nss/lib/ssl/ssl3ext.c
++++ b/mozilla/security/nss/lib/ssl/ssl3ext.c
+@@ -235,6 +235,7 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[] = {
+ #endif
+ { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn },
+ { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
++ { ssl_next_proto_neg_xtn, &ssl3_ServerHandleNextProtoNegoXtn },
+ { -1, NULL }
+ };
+
+@@ -245,6 +246,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
+ /* 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_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
+ { -1, NULL }
+ };
+
+@@ -267,7 +269,8 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
+ { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn },
+ { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn },
+ #endif
+- { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }
++ { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn },
++ { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn }
+ /* any extra entries will appear as { 0, NULL } */
+ };
+
+@@ -532,6 +535,123 @@ ssl3_SendSessionTicketXtn(
+ return -1;
+ }
+
++/* handle an incoming Next Protocol Negotiation extension. */
++SECStatus
++ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
++{
++ if (data->len != 0) {
++ /* Clients MUST send an empty NPN extension, if any. */
++ return SECFailure;
++ }
++
++ ss->ssl3.hs.nextProtoNego = PR_TRUE;
++ return SECSuccess;
++}
++
++/* ssl3_ValidateNextProtoNego checks that the given block of data is valid: none
++ * of the length may be 0 and the sum of the lengths must equal the length of
++ * the block. */
++SECStatus
++ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned short length)
++{
++ unsigned int offset = 0;
++
++ while (offset < length) {
++ if (data[offset] == 0) {
++ return SECFailure;
++ }
++ offset += (unsigned int)data[offset] + 1;
++ }
++
++ if (offset > length)
++ return SECFailure;
++
++ return SECSuccess;
++}
++
++SECStatus
++ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
++ SECItem *data)
++{
++ unsigned int i, j;
++ SECStatus rv;
++ unsigned char *result;
++
++ if (data->len == 0) {
++ /* The server supports the extension, but doesn't have any
++ * protocols configured. In this case we request our favoured
++ * protocol. */
++ goto pick_first;
++ }
++
++ rv = ssl3_ValidateNextProtoNego(data->data, data->len);
++ if (rv != SECSuccess)
++ return rv;
++
++ /* For each protocol in server preference order, see if we support it. */
++ for (i = 0; i < data->len; ) {
++ for (j = 0; j < ss->opt.nextProtoNego.len; ) {
++ if (data->data[i] == ss->opt.nextProtoNego.data[j] &&
++ memcmp(&data->data[i+1], &ss->opt.nextProtoNego.data[j+1],
++ data->data[i]) == 0) {
++ /* We found a match */
++ ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED;
++ result = &data->data[i];
++ goto found;
++ }
++ j += (unsigned int)ss->opt.nextProtoNego.data[j] + 1;
++ }
++
++ i += (unsigned int)data->data[i] + 1;
++ }
++
++ pick_first:
++ ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP;
++ result = ss->opt.nextProtoNego.data;
++
++ found:
++ if (ss->ssl3.nextProto.data)
++ PORT_Free(ss->ssl3.nextProto.data);
++ ss->ssl3.nextProto.data = PORT_Alloc(result[0]);
++ PORT_Memcpy(ss->ssl3.nextProto.data, result + 1, result[0]);
++ ss->ssl3.nextProto.len = result[0];
++ return SECSuccess;
++}
++
++PRInt32
++ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss,
++ PRBool append,
++ PRUint32 maxBytes)
++{
++ PRInt32 extension_length;
++
++ /* Renegotiations do not send this extension. */
++ if (ss->opt.nextProtoNego.len == 0 || ss->firstHsDone) {
++ return 0;
++ }
++
++ extension_length = 4;
++
++ if (append && maxBytes >= extension_length) {
++ SECStatus rv;
++ rv = ssl3_AppendHandshakeNumber(ss, ssl_next_proto_neg_xtn, 2);
++ if (rv != SECSuccess)
++ goto loser;
++ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
++ if (rv != SECSuccess)
++ goto loser;
++ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
++ ssl_next_proto_neg_xtn;
++ } else if (maxBytes < extension_length) {
++ return 0;
++ }
++
++ return extension_length;
++
++ loser:
++ return -1;
++}
++
+ /*
+ * NewSessionTicket
+ * Called from ssl3_HandleFinished
+diff --git a/mozilla/security/nss/lib/ssl/ssl3gthr.c b/mozilla/security/nss/lib/ssl/ssl3gthr.c
+index bdd2958..28fe154 100644
+--- a/mozilla/security/nss/lib/ssl/ssl3gthr.c
++++ b/mozilla/security/nss/lib/ssl/ssl3gthr.c
+@@ -188,6 +188,7 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
+ {
+ SSL3Ciphertext cText;
+ int rv;
++ PRBool canFalseStart = PR_FALSE;
+
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ do {
+@@ -207,7 +208,17 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
+ if (rv < 0) {
+ return ss->recvdCloseNotify ? 0 : rv;
+ }
+- } while (ss->ssl3.hs.ws != idle_handshake && ss->gs.buf.len == 0);
++
++ 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);
++ ssl_ReleaseSSL3HandshakeLock(ss);
++ }
++ } while (ss->ssl3.hs.ws != idle_handshake &&
++ !canFalseStart &&
++ ss->gs.buf.len == 0);
+
+ ss->gs.readOffset = 0;
+ ss->gs.writeOffset = ss->gs.buf.len;
+diff --git a/mozilla/security/nss/lib/ssl/ssl3prot.h b/mozilla/security/nss/lib/ssl/ssl3prot.h
+index 0fc1675..c82c891 100644
+--- a/mozilla/security/nss/lib/ssl/ssl3prot.h
++++ b/mozilla/security/nss/lib/ssl/ssl3prot.h
+@@ -157,7 +157,8 @@ typedef enum {
+ server_hello_done = 14,
+ certificate_verify = 15,
+ client_key_exchange = 16,
+- finished = 20
++ finished = 20,
++ next_proto = 67
+ } SSL3HandshakeType;
+
+ typedef struct {
+diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/ssl/sslimpl.h
+index 7581b98..a800d56 100644
+--- a/mozilla/security/nss/lib/ssl/sslimpl.h
++++ b/mozilla/security/nss/lib/ssl/sslimpl.h
+@@ -313,6 +313,11 @@ typedef struct {
+ #endif /* NSS_ENABLE_ECC */
+
+ typedef struct sslOptionsStr {
++ /* For clients, this is a validated list of protocols in preference order
++ * and wire format. For servers, this is the list of support protocols,
++ * also in wire format. */
++ SECItem nextProtoNego;
++
+ unsigned int useSecurity : 1; /* 1 */
+ unsigned int useSocks : 1; /* 2 */
+ unsigned int requestCertificate : 1; /* 3 */
+@@ -333,6 +338,7 @@ typedef struct sslOptionsStr {
+ unsigned int enableDeflate : 1; /* 19 */
+ unsigned int enableRenegotiation : 2; /* 20-21 */
+ unsigned int requireSafeNegotiation : 1; /* 22 */
++ unsigned int enableFalseStart : 1; /* 23 */
+ } sslOptions;
+
+ typedef enum { sslHandshakingUndetermined = 0,
+@@ -785,6 +791,7 @@ const ssl3CipherSuiteDef *suite_def;
+ #ifdef NSS_ENABLE_ECC
+ PRUint32 negotiatedECCurves; /* bit mask */
+ #endif /* NSS_ENABLE_ECC */
++ PRBool nextProtoNego;/* Our peer has sent this extension */
+ } SSL3HandshakeState;
+
+
+@@ -826,6 +833,16 @@ struct ssl3StateStr {
+ PRBool initialized;
+ SSL3HandshakeState hs;
+ ssl3CipherSpec specs[2]; /* one is current, one is pending. */
++
++ /* In a client: if the server supports Next Protocol Negotiation, then
++ * this is the protocol that was requested.
++ * In a server: this is the protocol that the client requested via Next
++ * Protocol Negotiation.
++ *
++ * In either case, if the data pointer is non-NULL, then it is malloced
++ * data. */
++ SECItem nextProto;
++ int nextProtoState; /* See SSL_NEXT_PROTO_* defines */
+ };
+
+ typedef struct {
+@@ -1250,6 +1267,8 @@ extern void ssl_SetAlwaysBlock(sslSocket *ss);
+
+ extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled);
+
++extern PRBool ssl3_CanFalseStart(sslSocket *ss);
++
+ #define SSL_LOCK_READER(ss) if (ss->recvLock) PZ_Lock(ss->recvLock)
+ #define SSL_UNLOCK_READER(ss) if (ss->recvLock) PZ_Unlock(ss->recvLock)
+ #define SSL_LOCK_WRITER(ss) if (ss->sendLock) PZ_Lock(ss->sendLock)
+@@ -1491,8 +1510,12 @@ extern SECStatus ssl3_HandleSupportedPointFormatsXtn(sslSocket * ss,
+ PRUint16 ex_type, SECItem *data);
+ extern SECStatus ssl3_ClientHandleSessionTicketXtn(sslSocket *ss,
+ PRUint16 ex_type, SECItem *data);
++extern SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss,
++ PRUint16 ex_type, SECItem *data);
+ extern SECStatus ssl3_ServerHandleSessionTicketXtn(sslSocket *ss,
+ PRUint16 ex_type, SECItem *data);
++extern SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss,
++ PRUint16 ex_type, SECItem *data);
+
+ /* ClientHello and ServerHello extension senders.
+ * Note that not all extension senders are exposed here; only those that
+@@ -1523,6 +1546,10 @@ extern PRInt32 ssl3_SendSupportedCurvesXtn(sslSocket *ss,
+ extern PRInt32 ssl3_SendSupportedPointFormatsXtn(sslSocket *ss,
+ PRBool append, PRUint32 maxBytes);
+ #endif
++extern PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
++ PRUint32 maxBytes);
++extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data,
++ unsigned short length);
+
+ /* call the registered extension handlers. */
+ extern SECStatus ssl3_HandleHelloExtensions(sslSocket *ss,
+diff --git a/mozilla/security/nss/lib/ssl/sslsecur.c b/mozilla/security/nss/lib/ssl/sslsecur.c
+index 8f79135..33ad2c3 100644
+--- a/mozilla/security/nss/lib/ssl/sslsecur.c
++++ b/mozilla/security/nss/lib/ssl/sslsecur.c
+@@ -148,6 +148,12 @@ ssl_Do1stHandshake(sslSocket *ss)
+ ss->gs.readOffset = 0;
+ break;
+ }
++ if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
++ ssl3_CanFalseStart(ss) &&
++ (ss->ssl3.hs.ws == wait_change_cipher ||
++ ss->ssl3.hs.ws == wait_new_session_ticket)) {
++ break;
++ }
+ rv = (*ss->handshake)(ss);
+ ++loopCount;
+ /* This code must continue to loop on SECWouldBlock,
+@@ -1307,6 +1313,10 @@ SSL_SetURL(PRFileDesc *fd, const char *url)
+ SECStatus
+ SSL_SetTrustAnchors(PRFileDesc *fd, CERTCertList *certList)
+ {
++ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
++ PR_NOT_REACHED("not implemented");
++ return SECFailure;
++#if 0
+ sslSocket * ss = ssl_FindSocket(fd);
+ CERTDistNames *names = NULL;
+
+@@ -1334,6 +1344,7 @@ SSL_SetTrustAnchors(PRFileDesc *fd, CERTCertList *certList)
+ ssl_Release1stHandshakeLock(ss);
+
+ return SECSuccess;
++#endif
+ }
+
+ /*
+diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/ssl/sslsock.c
+index aab48d6..c4611a0 100644
+--- a/mozilla/security/nss/lib/ssl/sslsock.c
++++ b/mozilla/security/nss/lib/ssl/sslsock.c
+@@ -163,6 +163,7 @@ static const sslSocketOps ssl_secure_ops = { /* SSL. */
+ ** default settings for socket enables
+ */
+ static sslOptions ssl_defaults = {
++ { siBuffer, NULL, 0 }, /* nextProtoNego */
+ PR_TRUE, /* useSecurity */
+ PR_FALSE, /* useSocks */
+ PR_FALSE, /* requestCertificate */
+@@ -183,6 +184,7 @@ static sslOptions ssl_defaults = {
+ PR_FALSE, /* enableDeflate */
+ 2, /* enableRenegotiation (default: requires extension) */
+ PR_FALSE, /* requireSafeNegotiation */
++ PR_FALSE, /* enableFalseStart */
+ };
+
+ sslSessionIDLookupFunc ssl_sid_lookup;
+@@ -437,6 +439,10 @@ ssl_DestroySocketContents(sslSocket *ss)
+ ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair);
+ ss->ephemeralECDHKeyPair = NULL;
+ }
++ if (ss->opt.nextProtoNego.data) {
++ PORT_Free(ss->opt.nextProtoNego.data);
++ ss->opt.nextProtoNego.data = NULL;
++ }
+ PORT_Assert(!ss->xtnData.sniNameArr);
+ if (ss->xtnData.sniNameArr) {
+ PORT_Free(ss->xtnData.sniNameArr);
+@@ -728,6 +734,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
+ ss->opt.requireSafeNegotiation = on;
+ break;
+
++ case SSL_ENABLE_FALSE_START:
++ ss->opt.enableFalseStart = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+@@ -791,6 +801,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
+ 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;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -841,6 +852,7 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
+ case SSL_REQUIRE_SAFE_NEGOTIATION:
+ on = ssl_defaults.requireSafeNegotiation;
+ break;
++ case SSL_ENABLE_FALSE_START: on = ssl_defaults.enableFalseStart; break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -984,6 +996,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
+ ssl_defaults.requireSafeNegotiation = on;
+ break;
+
++ case SSL_ENABLE_FALSE_START:
++ ssl_defaults.enableFalseStart = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+@@ -1255,9 +1271,83 @@ SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd)
+ return fd;
+ }
+
++/* SSL_SetNextProtoNego sets the list of supported protocols for the given
++ * socket. The list is a series of 8-bit, length prefixed strings. */
++SECStatus
++SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data,
++ unsigned short length)
++{
++ sslSocket *ss = ssl_FindSocket(fd);
++
++ if (!ss) {
++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetNextProtoNego", SSL_GETPID(),
++ fd));
++ return SECFailure;
++ }
++
++ if (ssl3_ValidateNextProtoNego(data, length) != SECSuccess)
++ return SECFailure;
++
++ ssl_GetSSL3HandshakeLock(ss);
++ if (ss->opt.nextProtoNego.data)
++ PORT_Free(ss->opt.nextProtoNego.data);
++ ss->opt.nextProtoNego.data = PORT_Alloc(length);
++ if (!ss->opt.nextProtoNego.data) {
++ ssl_ReleaseSSL3HandshakeLock(ss);
++ return SECFailure;
++ }
++ memcpy(ss->opt.nextProtoNego.data, data, length);
++ ss->opt.nextProtoNego.len = length;
++ ss->opt.nextProtoNego.type = siBuffer;
++ ssl_ReleaseSSL3HandshakeLock(ss);
++
++ return SECSuccess;
++}
++
++/* SSL_GetNextProto reads the resulting Next Protocol Negotiation result for
++ * the given socket. It's only valid to call this once the handshake has
++ * completed.
++ *
++ * state is set to one of the SSL_NEXT_PROTO_* constants. The negotiated
++ * protocol, if any, is written into buf, which must be at least buf_len
++ * bytes long. If the negotiated protocol is longer than this, it is truncated.
++ * The number of bytes copied is written into length.
++ */
++SECStatus
++SSL_GetNextProto(PRFileDesc *fd, int *state, unsigned char *buf,
++ unsigned int *length, unsigned int buf_len)
++{
++ sslSocket *ss = ssl_FindSocket(fd);
++
++ if (!ss) {
++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNextProto", SSL_GETPID(),
++ fd));
++ return SECFailure;
++ }
++
++ *state = ss->ssl3.nextProtoState;
++
++ if (ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT &&
++ ss->ssl3.nextProto.data) {
++ *length = ss->ssl3.nextProto.len;
++ if (*length > buf_len)
++ *length = buf_len;
++ PORT_Memcpy(buf, ss->ssl3.nextProto.data, *length);
++ } else {
++ *length = 0;
++ }
++
++ return SECSuccess;
++}
++
+ PRFileDesc *
+ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
+ {
++ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
++ PR_NOT_REACHED("not implemented");
++ return NULL;
++
++#if 0
+ sslSocket * sm = NULL, *ss = NULL;
+ int i;
+ sslServerCerts * mc = sm->serverCerts;
+@@ -1360,6 +1450,7 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
+ return fd;
+ loser:
+ return NULL;
++#endif
+ }
+
+ /************************************************************************/
+diff --git a/mozilla/security/nss/lib/ssl/sslt.h b/mozilla/security/nss/lib/ssl/sslt.h
+index c7d4553..f6e0b62 100644
+--- a/mozilla/security/nss/lib/ssl/sslt.h
++++ b/mozilla/security/nss/lib/ssl/sslt.h
+@@ -203,9 +203,10 @@ typedef enum {
+ ssl_ec_point_formats_xtn = 11,
+ #endif
+ ssl_session_ticket_xtn = 35,
++ ssl_next_proto_neg_xtn = 13172,
+ ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
+ } SSLExtensionType;
+
+-#define SSL_MAX_EXTENSIONS 5
++#define SSL_MAX_EXTENSIONS 6
+
+ #endif /* __sslt_h_ */
+diff --git a/mozilla/security/nss/tests/ssl/sslstress.txt b/mozilla/security/nss/tests/ssl/sslstress.txt
+index 9a3aae8..c2a5c76 100644
+--- a/mozilla/security/nss/tests/ssl/sslstress.txt
++++ b/mozilla/security/nss/tests/ssl/sslstress.txt
+@@ -42,9 +42,11 @@
+ noECC 0 _ -c_1000_-C_A Stress SSL2 RC4 128 with MD5
+ noECC 0 _ -c_1000_-C_c_-T Stress SSL3 RC4 128 with MD5
+ noECC 0 _ -c_1000_-C_c Stress TLS RC4 128 with MD5
++ noECC 0 _ -c_1000_-C_c_-h Stress TLS RC4 128 with MD5 (false start)
+ noECC 0 -u -2_-c_1000_-C_c_-u Stress TLS RC4 128 with MD5 (session ticket)
+ noECC 0 -z -2_-c_1000_-C_c_-z Stress TLS RC4 128 with MD5 (compression)
+ noECC 0 -u_-z -2_-c_1000_-C_c_-u_-z Stress TLS RC4 128 with MD5 (session ticket, compression)
++ noECC 0 -u_-z -2_-c_1000_-C_c_-u_-z_-h Stress TLS RC4 128 with MD5 (session ticket, compression, false start)
+ SNI 0 -u_-a_Host-sni.Dom -2_-3_-c_1000_-C_c_-u Stress TLS RC4 128 with MD5 (session ticket, SNI)
+
+ #
+@@ -55,7 +57,9 @@
+ noECC 0 -r_-r -c_100_-C_c_-N_-n_TestUser Stress TLS RC4 128 with MD5 (no reuse, client auth)
+ noECC 0 -r_-r_-u -2_-c_100_-C_c_-n_TestUser_-u Stress TLS RC4 128 with MD5 (session ticket, client auth)
+ noECC 0 -r_-r_-z -2_-c_100_-C_c_-n_TestUser_-z Stress TLS RC4 128 with MD5 (compression, client auth)
++ noECC 0 -r_-r_-z -2_-c_100_-C_c_-n_TestUser_-z_-h Stress TLS RC4 128 with MD5 (compression, client auth, false start)
+ noECC 0 -r_-r_-u_-z -2_-c_100_-C_c_-n_TestUser_-u_-z Stress TLS RC4 128 with MD5 (session ticket, compression, client auth)
++ noECC 0 -r_-r_-u_-z -2_-c_100_-C_c_-n_TestUser_-u_-z_-h Stress TLS RC4 128 with MD5 (session ticket, compression, client auth, false start)
+ SNI 0 -r_-r_-u_-a_Host-sni.Dom -2_-3_-c_1000_-C_c_-u Stress TLS RC4 128 with MD5 (session ticket, SNI, client auth, default virt host)
+ SNI 0 -r_-r_-u_-a_Host-sni.Dom_-k_Host-sni.Dom -2_-3_-c_1000_-C_c_-u_-a_Host-sni.Dom Stress TLS RC4 128 with MD5 (session ticket, SNI, client auth, change virt host)
+

Powered by Google App Engine
This is Rietveld 408576698