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

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

Issue 8156001: net: rework the NPN patch. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ... Created 9 years, 2 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/nextproto.patch
diff --git a/net/third_party/nss/patches/nextproto.patch b/net/third_party/nss/patches/nextproto.patch
index a01f2404b15b992ae578bcd462e360ef5de5797a..46021b425f3cbed78b4aef4119069982274b9206 100644
--- a/net/third_party/nss/patches/nextproto.patch
+++ b/net/third_party/nss/patches/nextproto.patch
@@ -1,68 +1,89 @@
-From 6b594dc531e7a1d1d5bca2f0f78e7bc0ac3ff937 Mon Sep 17 00:00:00 2001
+From 3caa0f573d2637bfed99dcc0e5887fe3a52462ba Mon Sep 17 00:00:00 2001
From: Adam Langley <agl@chromium.org>
Date: Mon, 3 Oct 2011 12:19:28 -0400
-Subject: [PATCH] nextproto.patch
+Subject: [PATCH 01/15] nextproto.patch
---
- mozilla/security/nss/cmd/tstclnt/tstclnt.c | 6 ++
- mozilla/security/nss/lib/ssl/ssl.def | 7 ++
- mozilla/security/nss/lib/ssl/ssl.h | 12 +++
- mozilla/security/nss/lib/ssl/ssl3con.c | 54 ++++++++++++
- mozilla/security/nss/lib/ssl/ssl3ext.c | 122 +++++++++++++++++++++++++++-
- mozilla/security/nss/lib/ssl/ssl3prot.h | 3 +-
- mozilla/security/nss/lib/ssl/sslimpl.h | 24 ++++++
- mozilla/security/nss/lib/ssl/sslsock.c | 74 +++++++++++++++++
- mozilla/security/nss/lib/ssl/sslt.h | 3 +-
- 9 files changed, 302 insertions(+), 3 deletions(-)
+ mozilla/security/nss/lib/ssl/ssl.def | 6 ++
+ mozilla/security/nss/lib/ssl/ssl.h | 51 ++++++++++++
+ mozilla/security/nss/lib/ssl/ssl3con.c | 54 +++++++++++++
+ mozilla/security/nss/lib/ssl/ssl3ext.c | 104 ++++++++++++++++++++++++-
+ mozilla/security/nss/lib/ssl/ssl3prot.h | 3 +-
+ mozilla/security/nss/lib/ssl/sslerr.h | 2 +
+ mozilla/security/nss/lib/ssl/sslimpl.h | 21 +++++
+ mozilla/security/nss/lib/ssl/sslsock.c | 131 +++++++++++++++++++++++++++++++
+ mozilla/security/nss/lib/ssl/sslt.h | 3 +-
+ 9 files changed, 372 insertions(+), 3 deletions(-)
-diff --git a/mozilla/security/nss/cmd/tstclnt/tstclnt.c b/mozilla/security/nss/cmd/tstclnt/tstclnt.c
-index 55684e6..d209a33 100644
---- a/mozilla/security/nss/cmd/tstclnt/tstclnt.c
-+++ b/mozilla/security/nss/cmd/tstclnt/tstclnt.c
-@@ -868,6 +868,12 @@ int main(int argc, char **argv)
- 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) {
diff --git a/mozilla/security/nss/lib/ssl/ssl.def b/mozilla/security/nss/lib/ssl/ssl.def
-index d3f455c..a1f4b51 100644
+index d3f455c..5256ae2 100644
--- a/mozilla/security/nss/lib/ssl/ssl.def
+++ b/mozilla/security/nss/lib/ssl/ssl.def
-@@ -152,3 +152,10 @@ SSL_SNISocketConfigHook;
+@@ -152,3 +152,9 @@ SSL_SNISocketConfigHook;
;+ local:
;+*;
;+};
+;+NSS_CHROMIUM {
+;+ global:
-+SSL_GetNextProto;
-+SSL_SetNextProtoNego;
++SSL_SetNextProtoCallback;
+;+ local:
+;+*;
+;+};
diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/ssl.h
-index 4a9e89d..ffa973c 100644
+index 4a9e89d..2cf777d 100644
--- a/mozilla/security/nss/lib/ssl/ssl.h
+++ b/mozilla/security/nss/lib/ssl/ssl.h
-@@ -153,6 +153,18 @@ SSL_IMPORT SECStatus SSL_OptionSetDefault(PRInt32 option, PRBool on);
+@@ -153,6 +153,57 @@ 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);
++/* SSLNextProtoCallback is called, during the handshake, when the server has
++ * sent a Next Protocol Negotiation extension. |protos| and |protosLen| define
++ * a buffer which contains the server's advertisement. This data is guaranteed
++ * to be well formed per the NPN spec. |protoOut| is a buffer provided by the
++ * caller, of length 255 (the maximum allowed by the protocol).
++ * On successful return, the protocol to be announced to the server will be in
++ * |protoOut| and its length in |protoOutLen|. */
++typedef SECStatus (PR_CALLBACK *SSLNextProtoCallback)(
++ void *arg,
++ PRFileDesc *fd,
++ const unsigned char* protos,
++ unsigned int protosLen,
++ unsigned char* protoOut,
++ unsigned int* protoOutLen);
++
++/* SSL_SetNextProtoCallback sets a callback function to handle Next Protocol
++ * Negotiation. It causes a client to advertise NPN. */
++SSL_IMPORT SECStatus SSL_SetNextProtoCallback(PRFileDesc *fd,
++ SSLNextProtoCallback callback,
++ 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.
++ *
++ * 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 short length);
++ unsigned int length);
++/* SSL_GetNextProto can be used after a handshake on a socket where
++ * SSL_SetNextProtoNego was called to retrieve the result of the Next Protocol
++ * negotiation.
++ *
++ * 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. */
+SSL_IMPORT SECStatus SSL_GetNextProto(PRFileDesc *fd,
+ int *state,
+ unsigned char *buf,
-+ unsigned *length,
-+ unsigned buf_len);
++ unsigned int *length,
++ unsigned int buf_len);
++
++// TODO(wtc): it may be a good idea to define these as an enum type.
+#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 */
@@ -71,7 +92,7 @@ index 4a9e89d..ffa973c 100644
** 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 8048913..e0cb4e9 100644
+index 8048913..8f860a9 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);
@@ -107,7 +128,7 @@ index 8048913..e0cb4e9 100644
+ int padding_len;
+ static const unsigned char padding[32] = {0};
+
-+ if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NO_SUPPORT)
++ if (ss->ssl3.nextProto.len == 0)
+ return SECSuccess;
+
+ PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
@@ -164,7 +185,7 @@ index 8048913..e0cb4e9 100644
/* End of ssl3con.c */
diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/ssl/ssl3ext.c
-index becbfe9..fbd5a91 100644
+index becbfe9..36ac4de 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[] = {
@@ -193,7 +214,7 @@ index becbfe9..fbd5a91 100644
/* any extra entries will appear as { 0, NULL } */
};
-@@ -534,6 +537,123 @@ ssl3_SendSessionTicketXtn(
+@@ -534,6 +537,105 @@ ssl3_SendSessionTicketXtn(
return -1;
}
@@ -206,12 +227,11 @@ index becbfe9..fbd5a91 100644
+ 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
++ * of the lengths 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)
@@ -220,63 +240,46 @@ index becbfe9..fbd5a91 100644
+
+ while (offset < length) {
+ if (data[offset] == 0) {
++ PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
+ return SECFailure;
+ }
+ offset += (unsigned int)data[offset] + 1;
+ }
+
-+ if (offset > length)
++ if (offset > length) {
++ PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
+ return SECFailure;
++ }
+
+ return SECSuccess;
+}
+
+SECStatus
+ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
-+ SECItem *data)
++ 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;
-+ }
++ unsigned char result[255];
++ unsigned int result_len;
+
+ 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;
++ rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd,
++ data->data, data->len,
++ result, &result_len);
++ if (rv != SECSuccess)
++ return rv;
++ // If the callback wrote more than allowed to |result| it has corrupted our
++ // stack.
++ PORT_Assert(result_len <= sizeof(result));
+
-+ 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];
++ ss->ssl3.nextProto.data = PORT_Alloc(result_len);
++ PORT_Memcpy(ss->ssl3.nextProto.data, result, result_len);
++ ss->ssl3.nextProto.len = result_len;
+ return SECSuccess;
+}
+
@@ -288,7 +291,7 @@ index becbfe9..fbd5a91 100644
+ PRInt32 extension_length;
+
+ /* Renegotiations do not send this extension. */
-+ if (ss->opt.nextProtoNego.len == 0 || ss->firstHsDone) {
++ if (!ss->nextProtoCallback || ss->firstHsDone) {
+ return 0;
+ }
+
@@ -331,48 +334,58 @@ index 4702fcc..f3c950e 100644
} SSL3HandshakeType;
typedef struct {
+diff --git a/mozilla/security/nss/lib/ssl/sslerr.h b/mozilla/security/nss/lib/ssl/sslerr.h
+index a2f6524..c76ffa9 100644
+--- a/mozilla/security/nss/lib/ssl/sslerr.h
++++ b/mozilla/security/nss/lib/ssl/sslerr.h
+@@ -203,6 +203,8 @@ SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD = (SSL_ERROR_BASE + 114),
+
+ SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY = (SSL_ERROR_BASE + 115),
+
++SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID = (SSL_ERROR_BASE + 117),
++
+ SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
+ } SSLErrorCodes;
+ #endif /* NO_SECURITY_ERROR_ENUM */
diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/ssl/sslimpl.h
-index 9af471d..d1c1181 100644
+index 9af471d..199c573 100644
--- a/mozilla/security/nss/lib/ssl/sslimpl.h
+++ b/mozilla/security/nss/lib/ssl/sslimpl.h
-@@ -313,6 +313,11 @@ typedef struct {
+@@ -313,6 +313,10 @@ 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. */
++ /* If SSL_SetNextProtoNego has been called, then this contains the
++ * list of supported protocols. */
+ SECItem nextProtoNego;
+
unsigned int useSecurity : 1; /* 1 */
unsigned int useSocks : 1; /* 2 */
unsigned int requestCertificate : 1; /* 3 */
-@@ -786,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;
-
-
-@@ -827,6 +833,16 @@ struct ssl3StateStr {
+@@ -827,6 +831,13 @@ 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.
++ * this is the protocol that was negotiated.
+ *
-+ * In either case, if the data pointer is non-NULL, then it is malloced
-+ * data. */
++ * If the data pointer is non-NULL, then it is malloced data. */
+ SECItem nextProto;
-+ int nextProtoState; /* See SSL_NEXT_PROTO_* defines */
++ int nextProtoState; /* See NEXT_PROTO_* defines */
};
typedef struct {
-@@ -1494,8 +1510,12 @@ extern SECStatus ssl3_HandleSupportedPointFormatsXtn(sslSocket * ss,
+@@ -1058,6 +1069,8 @@ const unsigned char * preferredCipher;
+ SSLHandshakeCallback handshakeCallback;
+ void *handshakeCallbackData;
+ void *pkcs11PinArg;
++ SSLNextProtoCallback nextProtoCallback;
++ void *nextProtoArg;
+
+ PRIntervalTime rTimeout; /* timeout for NSPR I/O */
+ PRIntervalTime wTimeout; /* timeout for NSPR I/O */
+@@ -1494,8 +1507,12 @@ extern SECStatus ssl3_HandleSupportedPointFormatsXtn(sslSocket * ss,
PRUint16 ex_type, SECItem *data);
extern SECStatus ssl3_ClientHandleSessionTicketXtn(sslSocket *ss,
PRUint16 ex_type, SECItem *data);
@@ -385,7 +398,7 @@ index 9af471d..d1c1181 100644
/* ClientHello and ServerHello extension senders.
* Note that not all extension senders are exposed here; only those that
-@@ -1526,6 +1546,10 @@ extern PRInt32 ssl3_SendSupportedCurvesXtn(sslSocket *ss,
+@@ -1526,6 +1543,10 @@ extern PRInt32 ssl3_SendSupportedCurvesXtn(sslSocket *ss,
extern PRInt32 ssl3_SendSupportedPointFormatsXtn(sslSocket *ss,
PRBool append, PRUint32 maxBytes);
#endif
@@ -397,7 +410,7 @@ index 9af471d..d1c1181 100644
/* call the registered extension handlers. */
extern SECStatus ssl3_HandleHelloExtensions(sslSocket *ss,
diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/ssl/sslsock.c
-index bc770a1..4c8fbfd 100644
+index bc770a1..769ea0a 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. */
@@ -419,16 +432,14 @@ index bc770a1..4c8fbfd 100644
PORT_Assert(!ss->xtnData.sniNameArr);
if (ss->xtnData.sniNameArr) {
PORT_Free(ss->xtnData.sniNameArr);
-@@ -1266,6 +1271,75 @@ SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd)
+@@ -1266,6 +1271,132 @@ 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)
-+{
++SSL_SetNextProtoCallback(PRFileDesc *fd,
++ SSLNextProtoCallback callback,
++ void *arg) {
+ sslSocket *ss = ssl_FindSocket(fd);
+
+ if (!ss) {
@@ -437,6 +448,74 @@ index bc770a1..4c8fbfd 100644
+ return SECFailure;
+ }
+
++ ssl_GetSSL3HandshakeLock(ss);
++ ss->nextProtoCallback = callback;
++ ss->nextProtoArg = arg;
++ ssl_ReleaseSSL3HandshakeLock(ss);
++}
++
++/* NextProtoStandardCallback is set as an NPN callback for the case when the
++ * user of the sockets wants the standard selection algorithm. */
++static SECStatus
++NextProtoStandardCallback(void *arg,
++ PRFileDesc *fd,
++ const unsigned char *protos,
++ unsigned int protos_len,
++ unsigned char *protoOut,
++ unsigned int *protoOutLen)
++{
++ unsigned int i, j;
++ const unsigned char *result;
++
++ sslSocket *ss = ssl_FindSocket(fd);
++ PORT_Assert(ss);
++
++ if (protos_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;
++ }
++
++ /* For each protocol in server preference, see if we support it. */
++ for (i = 0; i < protos_len; ) {
++ for (j = 0; j < ss->opt.nextProtoNego.len; ) {
++ if (protos[i] == ss->opt.nextProtoNego.data[j] &&
++ memcmp(&protos[i+1], &ss->opt.nextProtoNego.data[j+1],
++ protos[i]) == 0) {
++ /* We found a match. */
++ ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED;
++ result = &protos[i];
++ goto found;
++ }
++ j += (unsigned int)ss->opt.nextProtoNego.data[j] + 1;
++ }
++ i += (unsigned int)protos[i] + 1;
++ }
++
++pick_first:
++ ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP;
++ result = ss->opt.nextProtoNego.data;
++
++found:
++ memcpy(protoOut, result + 1, result[0]);
++ *protoOutLen = result[0];
++ return SECSuccess;
++}
++
++SECStatus
++SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data,
++ unsigned int length)
++{
++ SECStatus rv;
++
++ 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;
+
@@ -453,18 +532,9 @@ index bc770a1..4c8fbfd 100644
+ ss->opt.nextProtoNego.type = siBuffer;
+ ssl_ReleaseSSL3HandshakeLock(ss);
+
-+ return SECSuccess;
++ return SSL_SetNextProtoCallback(fd, NextProtoStandardCallback, NULL);
+}
+
-+/* 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)

Powered by Google App Engine
This is Rietveld 408576698