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

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

Issue 18346010: net: support ALPN. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove the new error. Created 7 years, 6 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/alpn.patch
diff --git a/net/third_party/nss/patches/alpn.patch b/net/third_party/nss/patches/alpn.patch
new file mode 100644
index 0000000000000000000000000000000000000000..d9016bed1d9839cfe059119e3a36bdff2bff7eda
--- /dev/null
+++ b/net/third_party/nss/patches/alpn.patch
@@ -0,0 +1,231 @@
+diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h
+index 8e9ba24..077874e 100644
+--- a/net/third_party/nss/ssl/ssl.h
++++ b/net/third_party/nss/ssl/ssl.h
+@@ -204,6 +204,11 @@ SSL_IMPORT SECStatus SSL_SetNextProtoCallback(PRFileDesc *fd,
+ * 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.
++ *
+ * 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,
+@@ -213,7 +218,8 @@ SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd,
+ 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
+diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
+index 00c83db..4916dfc 100644
+--- a/net/third_party/nss/ssl/ssl3con.c
++++ b/net/third_party/nss/ssl/ssl3con.c
+@@ -9907,8 +9907,10 @@ ssl3_SendNextProto(sslSocket *ss)
+ 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));
+diff --git a/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c
+index c0ce548..a059ccb 100644
+--- a/net/third_party/nss/ssl/ssl3ext.c
++++ b/net/third_party/nss/ssl/ssl3ext.c
+@@ -53,8 +53,12 @@ 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,
+@@ -247,14 +251,15 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[] = {
+ /* These two tables are used by the client, to handle server hello
+ * extensions. */
+ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
+- { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
++ { 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_use_srtp_xtn, &ssl3_HandleUseSRTPXtn },
+- { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
+- { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
++ { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
++ { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
++ { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
++ { ssl_application_layer_protocol, &ssl3_ClientHandleAppProtoXtn },
++ { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn },
++ { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
++ { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
+ { -1, NULL }
+ };
+
+@@ -271,17 +276,18 @@ static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = {
+ */
+ static const
+ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
+- { ssl_server_name_xtn, &ssl3_SendServerNameXtn },
+- { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn },
++ { 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 },
++ { 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_use_srtp_xtn, &ssl3_SendUseSRTPXtn },
+- { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
+- { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
++ { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn },
++ { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn },
++ { ssl_application_layer_protocol, &ssl3_ClientSendAppProtoXtn },
++ { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn },
++ { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
++ { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
+ { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
+ /* any extra entries will appear as { 0, NULL } */
+ };
+@@ -606,6 +612,11 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
+
+ PORT_Assert(!ss->firstHsDone);
+
++ if (ssl3_ExtensionNegotiated(ss, ssl_application_layer_protocol)) {
++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++ return SECFailure;
++ }
++
+ rv = ssl3_ValidateNextProtoNego(data->data, data->len);
+ if (rv != SECSuccess)
+ return rv;
+@@ -639,6 +650,44 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
+ 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)
+@@ -672,6 +721,44 @@ loser:
+ return -1;
+ }
+
++static PRInt32
++ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
++{
++ PRInt32 extension_length;
++
++ /* Renegotiations do not send this extension. */
++ if (!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) {
++ SECStatus rv;
++ rv = ssl3_AppendHandshakeNumber(ss, ssl_application_layer_protocol, 2);
++ if (rv != SECSuccess)
++ goto loser;
++ rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
++ if (rv != SECSuccess)
++ goto loser;
++ rv = ssl3_AppendHandshakeVariable(ss, ss->opt.nextProtoNego.data,
++ ss->opt.nextProtoNego.len, 2);
++ if (rv != SECSuccess)
++ goto loser;
++ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
++ ssl_application_layer_protocol;
++ } else if (maxBytes < extension_length) {
++ return 0;
++ }
++
++ return extension_length;
++
++loser:
++ return -1;
++}
++
+ static SECStatus
+ ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type,
+ SECItem *data)
+diff --git a/net/third_party/nss/ssl/sslt.h b/net/third_party/nss/ssl/sslt.h
+index 109640c..96ec04e 100644
+--- a/net/third_party/nss/ssl/sslt.h
++++ b/net/third_party/nss/ssl/sslt.h
+@@ -196,12 +196,13 @@ typedef enum {
+ #endif
+ ssl_signature_algorithms_xtn = 13,
+ ssl_use_srtp_xtn = 14,
++ ssl_application_layer_protocol = 16,
+ ssl_session_ticket_xtn = 35,
+ ssl_next_proto_nego_xtn = 13172,
+ ssl_channel_id_xtn = 30031,
+ ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
+ } SSLExtensionType;
+
+-#define SSL_MAX_EXTENSIONS 10
++#define SSL_MAX_EXTENSIONS 11
+
+ #endif /* __sslt_h_ */

Powered by Google App Engine
This is Rietveld 408576698