summaryrefslogtreecommitdiffstats
path: root/net/third_party/nss/patches/encryptedclientcerts.patch
diff options
context:
space:
mode:
Diffstat (limited to 'net/third_party/nss/patches/encryptedclientcerts.patch')
-rw-r--r--net/third_party/nss/patches/encryptedclientcerts.patch483
1 files changed, 230 insertions, 253 deletions
diff --git a/net/third_party/nss/patches/encryptedclientcerts.patch b/net/third_party/nss/patches/encryptedclientcerts.patch
index 15a5e78..7612092 100644
--- a/net/third_party/nss/patches/encryptedclientcerts.patch
+++ b/net/third_party/nss/patches/encryptedclientcerts.patch
@@ -1,208 +1,34 @@
-Index: net/third_party/nss/ssl/ssl.h
-===================================================================
---- net/third_party/nss/ssl/ssl.h (revision 108962)
-+++ net/third_party/nss/ssl/ssl.h (working copy)
-@@ -143,6 +143,7 @@
- #define SSL_ENABLE_CACHED_INFO 24 /* Enable TLS cached information */
- /* extension, off by default. */
+diff -up a/src/net/third_party/nss/ssl/ssl.h b/src/net/third_party/nss/ssl/ssl.h
+--- a/src/net/third_party/nss/ssl/ssl.h 2012-02-29 19:15:20.975171099 -0800
++++ b/src/net/third_party/nss/ssl/ssl.h 2012-02-29 19:18:21.947702106 -0800
+@@ -169,6 +169,7 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFi
+ #define SSL_CBC_RANDOM_IV 23
+ #define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */
#define SSL_ENABLE_OB_CERTS 25 /* Enable origin bound certs. */
+#define SSL_ENCRYPT_CLIENT_CERTS 26 /* Enable encrypted client certs. */
#ifdef SSL_DEPRECATED_FUNCTION
/* Old deprecated function names */
-Index: net/third_party/nss/ssl/sslimpl.h
-===================================================================
---- net/third_party/nss/ssl/sslimpl.h (revision 108962)
-+++ net/third_party/nss/ssl/sslimpl.h (working copy)
-@@ -350,6 +350,7 @@
- unsigned int enableOCSPStapling : 1; /* 24 */
- unsigned int enableCachedInfo : 1; /* 25 */
+diff -up a/src/net/third_party/nss/ssl/sslimpl.h b/src/net/third_party/nss/ssl/sslimpl.h
+--- a/src/net/third_party/nss/ssl/sslimpl.h 2012-02-29 19:15:20.975171099 -0800
++++ b/src/net/third_party/nss/ssl/sslimpl.h 2012-02-29 19:19:26.478604857 -0800
+@@ -350,6 +350,7 @@ typedef struct sslOptionsStr {
+ unsigned int cbcRandomIV : 1; /* 24 */
+ unsigned int enableOCSPStapling : 1; /* 25 */
unsigned int enableOBCerts : 1; /* 26 */
+ unsigned int encryptClientCerts : 1; /* 27 */
} sslOptions;
typedef enum { sslHandshakingUndetermined = 0,
-Index: net/third_party/nss/ssl/ssl3ext.c
-===================================================================
---- net/third_party/nss/ssl/ssl3ext.c (revision 108962)
-+++ net/third_party/nss/ssl/ssl3ext.c (working copy)
-@@ -78,6 +78,12 @@
- PRBool append, PRUint32 maxBytes);
- static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss,
- PRUint16 ex_type, SECItem *data);
-+static SECStatus ssl3_ServerHandleEncryptedClientCertsXtn(sslSocket *ss,
-+ PRUint16 ex_type, SECItem *data);
-+static SECStatus ssl3_ClientHandleEncryptedClientCertsXtn(sslSocket *ss,
-+ PRUint16 ex_type, SECItem *data);
-+static PRInt32 ssl3_SendEncryptedClientCertsXtn(sslSocket *ss,
-+ PRBool append, PRUint32 maxBytes);
-
- /*
- * Write bytes. Using this function means the SECItem structure
-@@ -234,6 +240,7 @@
- { ssl_ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn },
- #endif
- { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn },
-+ { ssl_encrypted_client_certs, &ssl3_ServerHandleEncryptedClientCertsXtn },
- { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
- { ssl_next_proto_neg_xtn, &ssl3_ServerHandleNextProtoNegoXtn },
- { ssl_cached_info_xtn, &ssl3_ServerHandleCachedInfoXtn },
-@@ -247,6 +254,7 @@
- { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
- /* TODO: add a handler for ssl_ec_point_formats_xtn */
- { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
-+ { ssl_encrypted_client_certs, &ssl3_ClientHandleEncryptedClientCertsXtn },
- { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
- { ssl_next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
- { ssl_cached_info_xtn, &ssl3_ClientHandleCachedInfoXtn },
-@@ -275,6 +283,7 @@
- { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn },
- #endif
- { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn },
-+ { ssl_encrypted_client_certs, &ssl3_SendEncryptedClientCertsXtn },
- { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn },
- { ssl_cached_info_xtn, &ssl3_ClientSendCachedInfoXtn },
- { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
-@@ -1318,6 +1327,18 @@
- return SECSuccess;
- }
-
-+static SECStatus
-+ssl3_ClientHandleEncryptedClientCertsXtn(sslSocket *ss, PRUint16 ex_type,
-+ SECItem *data)
-+{
-+ if (data->len != 0)
-+ return SECFailure;
-+
-+ /* Keep track of negotiated extensions. */
-+ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-+ return SECSuccess;
-+}
-+
- SECStatus
- ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
- SECItem *data)
-@@ -1728,6 +1749,24 @@
- return rv;
- }
-
-+static SECStatus
-+ssl3_ServerHandleEncryptedClientCertsXtn(sslSocket *ss, PRUint16 ex_type,
-+ SECItem *data)
-+{
-+ SECStatus rv = SECSuccess;
-+
-+ if (data->len != 0)
-+ return SECFailure;
-+
-+ if (ss->opt.encryptClientCerts) {
-+ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-+ rv = ssl3_RegisterServerHelloExtensionSender(
-+ ss, ex_type, ssl3_SendEncryptedClientCertsXtn);
-+ }
-+
-+ return rv;
-+}
-+
- /*
- * Read bytes. Using this function means the SECItem structure
- * cannot be freed. The caller is expected to call this function
-@@ -1927,6 +1966,33 @@
- return needed;
- }
-
-+static PRInt32
-+ssl3_SendEncryptedClientCertsXtn(
-+ sslSocket * ss,
-+ PRBool append,
-+ PRUint32 maxBytes)
-+{
-+ PRInt32 needed;
-+
-+ if (!ss->opt.encryptClientCerts)
-+ return 0;
-+
-+ needed = 4; /* two bytes of type and two of length. */
-+ if (append && maxBytes >= needed) {
-+ SECStatus rv;
-+ rv = ssl3_AppendHandshakeNumber(ss, ssl_encrypted_client_certs, 2);
-+ if (rv != SECSuccess)
-+ return -1;
-+ rv = ssl3_AppendHandshakeNumber(ss, 0 /* length */, 2);
-+ if (rv != SECSuccess)
-+ return -1;
-+ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
-+ ssl_encrypted_client_certs;
-+ }
-+
-+ return needed;
-+}
-+
- /* This function runs in both the client and server. */
- static SECStatus
- ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
-Index: net/third_party/nss/ssl/sslsock.c
-===================================================================
---- net/third_party/nss/ssl/sslsock.c (revision 108962)
-+++ net/third_party/nss/ssl/sslsock.c (working copy)
-@@ -188,6 +188,7 @@
- PR_FALSE, /* enableOCSPStapling */
- PR_FALSE, /* enableCachedInfo */
- PR_FALSE, /* enableOBCerts */
-+ PR_FALSE, /* encryptClientCerts */
- };
-
- sslSessionIDLookupFunc ssl_sid_lookup;
-@@ -757,6 +758,10 @@
- ss->opt.enableOBCerts = on;
- break;
-
-+ case SSL_ENCRYPT_CLIENT_CERTS:
-+ ss->opt.encryptClientCerts = on;
-+ break;
-+
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure;
-@@ -824,6 +829,8 @@
- case SSL_ENABLE_OCSP_STAPLING: on = ss->opt.enableOCSPStapling; break;
- case SSL_ENABLE_CACHED_INFO: on = ss->opt.enableCachedInfo; break;
- case SSL_ENABLE_OB_CERTS: on = ss->opt.enableOBCerts; break;
-+ case SSL_ENCRYPT_CLIENT_CERTS:
-+ on = ss->opt.encryptClientCerts; break;
-
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
-@@ -880,6 +887,8 @@
- break;
- case SSL_ENABLE_CACHED_INFO: on = ssl_defaults.enableCachedInfo; break;
- case SSL_ENABLE_OB_CERTS: on = ssl_defaults.enableOBCerts; break;
-+ case SSL_ENCRYPT_CLIENT_CERTS:
-+ on = ssl_defaults.encryptClientCerts; break;
-
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
-@@ -1039,6 +1048,10 @@
- ssl_defaults.enableOBCerts = on;
- break;
-
-+ case SSL_ENCRYPT_CLIENT_CERTS:
-+ ssl_defaults.encryptClientCerts = on;
-+ break;
-+
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
-Index: net/third_party/nss/ssl/ssl3con.c
-===================================================================
---- net/third_party/nss/ssl/ssl3con.c (revision 108962)
-+++ net/third_party/nss/ssl/ssl3con.c (working copy)
-@@ -2835,8 +2835,15 @@
+diff -up a/src/net/third_party/nss/ssl/ssl3con.c b/src/net/third_party/nss/ssl/ssl3con.c
+--- a/src/net/third_party/nss/ssl/ssl3con.c 2012-02-29 19:15:20.975171099 -0800
++++ b/src/net/third_party/nss/ssl/ssl3con.c 2012-02-29 20:00:15.851981917 -0800
+@@ -2863,7 +2863,14 @@ ssl3_HandleChangeCipherSpecs(sslSocket *
ss->ssl3.prSpec = ss->ssl3.crSpec;
ss->ssl3.crSpec = prSpec;
- ss->ssl3.hs.ws = wait_finished;
-
++
+ if (ss->sec.isServer &&
+ ss->opt.requestCertificate &&
+ ssl3_ExtensionNegotiated(ss, ssl_encrypted_client_certs)) {
@@ -210,11 +36,10 @@ Index: net/third_party/nss/ssl/ssl3con.c
+ } else {
+ ss->ssl3.hs.ws = wait_finished;
+ }
-+
+
SSL_TRC(3, ("%d: SSL3[%d] Set Current Read Cipher Suite to Pending",
SSL_GETPID(), ss->fd ));
-
-@@ -4850,10 +4857,11 @@
+@@ -4877,10 +4884,11 @@ loser:
static SECStatus
ssl3_SendCertificateVerify(sslSocket *ss)
{
@@ -230,7 +55,7 @@ Index: net/third_party/nss/ssl/ssl3con.c
PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-@@ -4862,13 +4870,17 @@
+@@ -4889,13 +4897,17 @@ ssl3_SendCertificateVerify(sslSocket *ss
SSL_GETPID(), ss->fd));
ssl_GetSpecReadLock(ss);
@@ -250,19 +75,18 @@ Index: net/third_party/nss/ssl/ssl3con.c
if (ss->ssl3.platformClientKey) {
#ifdef NSS_PLATFORM_CLIENT_AUTH
rv = ssl3_PlatformSignHashes(&hashes, ss->ssl3.platformClientKey,
-@@ -5840,7 +5852,10 @@
+@@ -5912,6 +5924,10 @@ ssl3_SendClientSecondRound(sslSocket *ss
{
- SECStatus rv;
- SSL3WaitState ws = ss->ssl3.hs.ws;
-- PRBool send_verify = PR_FALSE;
-+ PRBool sendEmptyCert, sendCert;
-+ int n = 0, i;
+ SECStatus rv;
+ PRBool sendClientCert;
++ PRBool sendEmptyCert;
++ int n = 0, i;
+ typedef SECStatus (*SendFunction)(sslSocket*);
+ SendFunction send_funcs[5];
- SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello_done handshake",
- SSL_GETPID(), ss->fd));
-@@ -5858,46 +5873,45 @@
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+@@ -5958,35 +5974,40 @@ ssl3_SendClientSecondRound(sslSocket *ss
ssl_GetXmitBufLock(ss); /*******************************/
@@ -273,18 +97,7 @@ Index: net/third_party/nss/ssl/ssl3con.c
- if (rv != SECSuccess) {
- goto loser; /* error code is set. */
- }
-- } else if (ss->ssl3.clientCertChain != NULL &&
-- ss->ssl3.platformClientKey) {
--#ifdef NSS_PLATFORM_CLIENT_AUTH
-- send_verify = PR_TRUE;
-- rv = ssl3_SendCertificate(ss);
-- if (rv != SECSuccess) {
-- goto loser; /* error code is set. */
-- }
--#endif /* NSS_PLATFORM_CLIENT_AUTH */
-- } else if (ss->ssl3.clientCertChain != NULL &&
-- ss->ssl3.clientPrivateKey != NULL) {
-- send_verify = PR_TRUE;
+- } else if (sendClientCert) {
- rv = ssl3_SendCertificate(ss);
- if (rv != SECSuccess) {
- goto loser; /* error code is set. */
@@ -292,10 +105,6 @@ Index: net/third_party/nss/ssl/ssl3con.c
- }
+ sendEmptyCert = ss->ssl3.sendEmptyCert;
+ ss->ssl3.sendEmptyCert = PR_FALSE;
-+ sendCert = !sendEmptyCert &&
-+ ss->ssl3.clientCertChain != NULL &&
-+ (ss->ssl3.platformClientKey ||
-+ ss->ssl3.clientPrivateKey != NULL);
- rv = ssl3_SendClientKeyExchange(ss);
- if (rv != SECSuccess) {
@@ -306,7 +115,7 @@ Index: net/third_party/nss/ssl/ssl3con.c
+ if (sendEmptyCert) {
+ send_funcs[n++] = ssl3_SendEmptyCertificate;
+ }
-+ if (sendCert) {
++ if (sendClientCert) {
+ send_funcs[n++] = ssl3_SendCertificate;
+ send_funcs[n++] = ssl3_SendCertificateVerify;
+ }
@@ -314,36 +123,36 @@ Index: net/third_party/nss/ssl/ssl3con.c
+ if (sendEmptyCert) {
+ send_funcs[n++] = ssl3_SendEmptyCertificate;
+ }
-+ if (sendCert) {
++ if (sendClientCert) {
+ send_funcs[n++] = ssl3_SendCertificate;
+ }
+ send_funcs[n++] = ssl3_SendClientKeyExchange;
-+ if (sendCert) {
++ if (sendClientCert) {
+ send_funcs[n++] = ssl3_SendCertificateVerify;
+ }
+ send_funcs[n++] = ssl3_SendChangeCipherSpecs;
}
-- if (send_verify) {
+- if (sendClientCert) {
- rv = ssl3_SendCertificateVerify(ss);
+- if (rv != SECSuccess) {
+- goto loser; /* err is set. */
+- }
+- }
+ PORT_Assert(n <= sizeof(send_funcs)/sizeof(send_funcs[0]));
-+
+
+- rv = ssl3_SendChangeCipherSpecs(ss);
+- if (rv != SECSuccess) {
+- goto loser; /* err code was set. */
+ for (i = 0; i < n; i++) {
+ rv = send_funcs[i](ss);
- if (rv != SECSuccess) {
-- goto loser; /* err is set. */
-- }
++ if (rv != SECSuccess) {
+ goto loser; /* err code was set. */
+ }
}
-- rv = ssl3_SendChangeCipherSpecs(ss);
-- if (rv != SECSuccess) {
-- goto loser; /* err code was set. */
-- }
- /* We don't send NPN in a renegotiation as it's explicitly disallowed by
- * the spec. */
-@@ -6110,8 +6124,13 @@
+ /* XXX: If the server's certificate hasn't been authenticated by this
+@@ -6201,8 +6222,13 @@ ssl3_SendServerHelloSequence(sslSocket *
return rv; /* err code is set. */
}
@@ -359,7 +168,7 @@ Index: net/third_party/nss/ssl/ssl3con.c
return SECSuccess;
}
-@@ -7355,7 +7374,11 @@
+@@ -7446,7 +7472,11 @@ ssl3_HandleCertificateVerify(sslSocket *
desc = isTLS ? decode_error : illegal_parameter;
goto alert_loser; /* malformed */
}
@@ -372,20 +181,20 @@ Index: net/third_party/nss/ssl/ssl3con.c
return SECSuccess;
alert_loser:
-@@ -8348,7 +8371,11 @@
-
- cert_block:
- if (ss->sec.isServer) {
+@@ -8346,7 +8376,11 @@ ssl3_HandleCertificate(sslSocket *ss, SS
+ }
+ } else {
+ server_no_cert:
- ss->ssl3.hs.ws = wait_client_key;
+ if (ssl3_ExtensionNegotiated(ss, ssl_encrypted_client_certs)) {
+ ss->ssl3.hs.ws = wait_cert_verify;
+ } else {
+ ss->ssl3.hs.ws = wait_client_key;
+ }
- } else {
- ss->ssl3.hs.ws = wait_cert_request; /* disallow server_key_exchange */
- if (ss->ssl3.hs.kea_def->is_limited ||
-@@ -8978,6 +9005,8 @@
+ }
+
+ PORT_Assert(rv == SECSuccess);
+@@ -8959,6 +8993,8 @@ ssl3_HandleHandshakeMessage(sslSocket *s
if (type == finished) {
sender = ss->sec.isServer ? sender_client : sender_server;
rSpec = ss->ssl3.crSpec;
@@ -394,20 +203,188 @@ Index: net/third_party/nss/ssl/ssl3con.c
}
rv = ssl3_ComputeHandshakeHashes(ss, rSpec, &hashes, sender);
}
-Index: net/third_party/nss/ssl/sslt.h
-===================================================================
---- net/third_party/nss/ssl/sslt.h (revision 108962)
-+++ net/third_party/nss/ssl/sslt.h (working copy)
-@@ -206,10 +206,11 @@
+diff -up a/src/net/third_party/nss/ssl/ssl3ext.c b/src/net/third_party/nss/ssl/ssl3ext.c
+--- a/src/net/third_party/nss/ssl/ssl3ext.c 2012-02-29 17:12:15.720044263 -0800
++++ b/src/net/third_party/nss/ssl/ssl3ext.c 2012-02-29 20:00:15.851981917 -0800
+@@ -84,6 +84,12 @@ static SECStatus ssl3_ServerHandleNextPr
+ PRUint16 ex_type, SECItem *data);
+ static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
+ PRUint32 maxBytes);
++static SECStatus ssl3_ServerHandleEncryptedClientCertsXtn(sslSocket *ss,
++ PRUint16 ex_type, SECItem *data);
++static SECStatus ssl3_ClientHandleEncryptedClientCertsXtn(sslSocket *ss,
++ PRUint16 ex_type, SECItem *data);
++static PRInt32 ssl3_SendEncryptedClientCertsXtn(sslSocket *ss,
++ PRBool append, PRUint32 maxBytes);
+
+ /*
+ * Write bytes. Using this function means the SECItem structure
+@@ -240,6 +246,7 @@ static const ssl3HelloExtensionHandler c
+ { ssl_ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn },
+ #endif
+ { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn },
++ { ssl_encrypted_client_certs, &ssl3_ServerHandleEncryptedClientCertsXtn },
+ { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
+ { ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn },
+ { ssl_ob_cert_xtn, &ssl3_ServerHandleOBCertXtn },
+@@ -252,6 +259,7 @@ static const ssl3HelloExtensionHandler s
+ { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
+ /* TODO: add a handler for ssl_ec_point_formats_xtn */
+ { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
++ { ssl_encrypted_client_certs, &ssl3_ClientHandleEncryptedClientCertsXtn },
+ { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
+ { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
+ { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
+@@ -279,6 +287,7 @@ ssl3HelloExtensionSender clientHelloSend
+ { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn },
+ #endif
+ { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn },
++ { ssl_encrypted_client_certs, &ssl3_SendEncryptedClientCertsXtn },
+ { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn },
+ { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
+ { ssl_ob_cert_xtn, &ssl3_SendOBCertXtn }
+@@ -1083,6 +1092,18 @@ ssl3_ClientHandleSessionTicketXtn(sslSoc
+ return SECSuccess;
+ }
+
++static SECStatus
++ssl3_ClientHandleEncryptedClientCertsXtn(sslSocket *ss, PRUint16 ex_type,
++ SECItem *data)
++{
++ if (data->len != 0)
++ return SECFailure;
++
++ /* Keep track of negotiated extensions. */
++ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
++ return SECSuccess;
++}
++
+ SECStatus
+ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
+ SECItem *data)
+@@ -1496,6 +1517,24 @@ loser:
+ return rv;
+ }
+
++static SECStatus
++ssl3_ServerHandleEncryptedClientCertsXtn(sslSocket *ss, PRUint16 ex_type,
++ SECItem *data)
++{
++ SECStatus rv = SECSuccess;
++
++ if (data->len != 0)
++ return SECFailure;
++
++ if (ss->opt.encryptClientCerts) {
++ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
++ rv = ssl3_RegisterServerHelloExtensionSender(
++ ss, ex_type, ssl3_SendEncryptedClientCertsXtn);
++ }
++
++ return rv;
++}
++
+ /*
+ * Read bytes. Using this function means the SECItem structure
+ * cannot be freed. The caller is expected to call this function
+@@ -1695,6 +1734,33 @@ ssl3_SendRenegotiationInfoXtn(
+ return needed;
+ }
+
++static PRInt32
++ssl3_SendEncryptedClientCertsXtn(
++ sslSocket * ss,
++ PRBool append,
++ PRUint32 maxBytes)
++{
++ PRInt32 needed;
++
++ if (!ss->opt.encryptClientCerts)
++ return 0;
++
++ needed = 4; /* two bytes of type and two of length. */
++ if (append && maxBytes >= needed) {
++ SECStatus rv;
++ rv = ssl3_AppendHandshakeNumber(ss, ssl_encrypted_client_certs, 2);
++ if (rv != SECSuccess)
++ return -1;
++ rv = ssl3_AppendHandshakeNumber(ss, 0 /* length */, 2);
++ if (rv != SECSuccess)
++ return -1;
++ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
++ ssl_encrypted_client_certs;
++ }
++
++ return needed;
++}
++
+ /* This function runs in both the client and server. */
+ static SECStatus
+ ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
+diff -up a/src/net/third_party/nss/ssl/sslsock.c b/src/net/third_party/nss/ssl/sslsock.c
+--- a/src/net/third_party/nss/ssl/sslsock.c 2012-02-29 17:49:08.431530583 -0800
++++ b/src/net/third_party/nss/ssl/sslsock.c 2012-02-29 20:00:15.851981917 -0800
+@@ -188,6 +188,7 @@ static sslOptions ssl_defaults = {
+ PR_TRUE, /* cbcRandomIV */
+ PR_FALSE, /* enableOCSPStapling */
+ PR_FALSE, /* enableOBCerts */
++ PR_FALSE, /* encryptClientCerts */
+ };
+
+ sslSessionIDLookupFunc ssl_sid_lookup;
+@@ -755,6 +756,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 wh
+ ss->opt.enableOBCerts = on;
+ break;
+
++ case SSL_ENCRYPT_CLIENT_CERTS:
++ ss->opt.encryptClientCerts = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+@@ -822,6 +827,8 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 wh
+ case SSL_CBC_RANDOM_IV: on = ss->opt.cbcRandomIV; break;
+ case SSL_ENABLE_OCSP_STAPLING: on = ss->opt.enableOCSPStapling; break;
+ case SSL_ENABLE_OB_CERTS: on = ss->opt.enableOBCerts; break;
++ case SSL_ENCRYPT_CLIENT_CERTS:
++ on = ss->opt.encryptClientCerts; break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -880,6 +887,8 @@ SSL_OptionGetDefault(PRInt32 which, PRBo
+ on = ssl_defaults.enableOCSPStapling;
+ break;
+ case SSL_ENABLE_OB_CERTS: on = ssl_defaults.enableOBCerts; break;
++ case SSL_ENCRYPT_CLIENT_CERTS:
++ on = ssl_defaults.encryptClientCerts; break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -1047,6 +1056,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBo
+ ssl_defaults.enableOBCerts = on;
+ break;
+
++ case SSL_ENCRYPT_CLIENT_CERTS:
++ ssl_defaults.encryptClientCerts = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+diff -up a/src/net/third_party/nss/ssl/sslt.h b/src/net/third_party/nss/ssl/sslt.h
+--- a/src/net/third_party/nss/ssl/sslt.h 2012-02-29 17:12:15.780045080 -0800
++++ b/src/net/third_party/nss/ssl/sslt.h 2012-02-29 19:34:43.921452065 -0800
+@@ -205,10 +205,11 @@ typedef enum {
+ #endif
ssl_session_ticket_xtn = 35,
- ssl_next_proto_neg_xtn = 13172,
- ssl_cached_info_xtn = 13173,
+ ssl_next_proto_nego_xtn = 13172,
+ ssl_encrypted_client_certs = 13180, /* not IANA assigned. */
ssl_renegotiation_info_xtn = 0xff01, /* experimental number */
ssl_ob_cert_xtn = 13175 /* experimental number */
} SSLExtensionType;
--#define SSL_MAX_EXTENSIONS 9
-+#define SSL_MAX_EXTENSIONS 10
+-#define SSL_MAX_EXTENSIONS 8
++#define SSL_MAX_EXTENSIONS 9
#endif /* __sslt_h_ */