summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-03 04:06:24 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-03 04:06:24 +0000
commitbffc22ec4e9abd681c996c78adddc74291a0716a (patch)
tree965e3be547209252d03c388713e4f98187be50ac /net
parent136525df1b4749c9e9ac07d95ca3a7d0a0633f61 (diff)
downloadchromium_src-bffc22ec4e9abd681c996c78adddc74291a0716a.zip
chromium_src-bffc22ec4e9abd681c996c78adddc74291a0716a.tar.gz
chromium_src-bffc22ec4e9abd681c996c78adddc74291a0716a.tar.bz2
net: support ALPN.
BUG=254178 Review URL: https://chromiumcodereview.appspot.com/18346010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@209878 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/socket/ssl_client_socket_nss.cc1
-rw-r--r--net/third_party/nss/patches/alpn.patch231
-rwxr-xr-xnet/third_party/nss/patches/applypatches.sh2
-rw-r--r--net/third_party/nss/ssl/ssl.h8
-rw-r--r--net/third_party/nss/ssl/ssl3con.c4
-rw-r--r--net/third_party/nss/ssl/ssl3ext.c119
-rw-r--r--net/third_party/nss/ssl/sslt.h3
7 files changed, 349 insertions, 19 deletions
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index bffadfa..f483b11 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -2498,6 +2498,7 @@ void SSLClientSocketNSS::Core::UpdateNextProto() {
std::string(reinterpret_cast<char*>(buf), buf_len);
switch (state) {
case SSL_NEXT_PROTO_NEGOTIATED:
+ case SSL_NEXT_PROTO_SELECTED:
nss_handshake_state_.next_proto_status = kNextProtoNegotiated;
break;
case SSL_NEXT_PROTO_NO_OVERLAP:
diff --git a/net/third_party/nss/patches/alpn.patch b/net/third_party/nss/patches/alpn.patch
new file mode 100644
index 0000000..d9016be
--- /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_ */
diff --git a/net/third_party/nss/patches/applypatches.sh b/net/third_party/nss/patches/applypatches.sh
index e8d9f5f..9506afd 100755
--- a/net/third_party/nss/patches/applypatches.sh
+++ b/net/third_party/nss/patches/applypatches.sh
@@ -57,3 +57,5 @@ patch -p4 < $patches_dir/tls12certrequest.patch
patch -p4 < $patches_dir/tls12hmacsha256.patch
patch -p4 < $patches_dir/tls12handshakehashes.patch
+
+patch -p5 < $patches_dir/alpn.patch
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_ */