summaryrefslogtreecommitdiffstats
path: root/net/third_party
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-16 22:33:16 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-16 22:33:16 +0000
commit7c119f189c7f30f3938ceb9c86fd3a95102b8687 (patch)
tree11b38c0c5c17a209bc8b892bb3dbd9415faf089b /net/third_party
parent9d94337a7b89cdec3dd212c3dbf780d1d82ccf92 (diff)
downloadchromium_src-7c119f189c7f30f3938ceb9c86fd3a95102b8687.zip
chromium_src-7c119f189c7f30f3938ceb9c86fd3a95102b8687.tar.gz
chromium_src-7c119f189c7f30f3938ceb9c86fd3a95102b8687.tar.bz2
Add the NSS patch for SSL client auth with native crypto APIs on Mac
and Windows. The original dheclientauth.patch is subsumed by this patch because it is hard to separate the two patches. R=rsleevi BUG=37560,45369,62027 TEST=none Review URL: http://codereview.chromium.org/6528039 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75191 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/third_party')
-rw-r--r--net/third_party/nss/README.chromium6
-rw-r--r--net/third_party/nss/patches/clientauth.patch703
-rw-r--r--net/third_party/nss/patches/dheclientauth.patch98
3 files changed, 708 insertions, 99 deletions
diff --git a/net/third_party/nss/README.chromium b/net/third_party/nss/README.chromium
index 7dc9de0..d1fa694 100644
--- a/net/third_party/nss/README.chromium
+++ b/net/third_party/nss/README.chromium
@@ -45,10 +45,14 @@ Patches:
* Add OCSP stapling support
patches/ocspstapling.patch
+ * Add support for client auth with native crypto APIs on Mac and Windows
+ patches/clientauth.patch
+ ssl/sslplatf.c
+
* Don't send a client certificate when renegotiating if the peer does not
request one. This only happened if the previous key exchange algorithm
was non-RSA.
- patches/dheclientauth.patch
+ patches/clientauth.patch
https://bugzilla.mozilla.org/show_bug.cgi?id=616757
The ssl/bodge directory contains files taken from the NSS repo that we required
diff --git a/net/third_party/nss/patches/clientauth.patch b/net/third_party/nss/patches/clientauth.patch
new file mode 100644
index 0000000..5128566
--- /dev/null
+++ b/net/third_party/nss/patches/clientauth.patch
@@ -0,0 +1,703 @@
+Index: mozilla/security/nss/lib/ssl/ssl.h
+===================================================================
+RCS file: /cvsroot/mozilla/security/nss/lib/ssl/ssl.h,v
+retrieving revision 1.38
+diff -p -u -8 -r1.38 ssl.h
+--- mozilla/security/nss/lib/ssl/ssl.h 17 Feb 2010 02:29:07 -0000 1.38
++++ mozilla/security/nss/lib/ssl/ssl.h 16 Feb 2011 02:40:21 -0000
+@@ -275,16 +275,49 @@ typedef SECStatus (PR_CALLBACK *SSLGetCl
+ * and certificate.
+ * fd - the file descriptor for the connection in question
+ * f - the application's callback that delivers the key and cert
+ * a - application specific data
+ */
+ SSL_IMPORT SECStatus SSL_GetClientAuthDataHook(PRFileDesc *fd,
+ SSLGetClientAuthData f, void *a);
+
++/*
++ * Prototype for SSL callback to get client auth data from the application,
++ * when using the underlying platform's cryptographic primitives. Returning
++ * SECFailure will cause the socket to send no client certificate.
++ * arg - application passed argument
++ * caNames - pointer to distinguished names of CAs that the server likes
++ * pRetCerts - pointer to pointer to list of certs, with the first being
++ * the client cert, and any following being used for chain
++ * building
++ * pRetKey - pointer to native key pointer, for return of key
++ * - Windows: A pointer to a PCERT_KEY_CONTEXT that was allocated
++ * via PORT_Alloc(). Ownership of the PCERT_KEY_CONTEXT
++ * is transferred to NSS, which will free via
++ * PORT_Free().
++ * - Mac OS X: A pointer to a SecKeyRef. Ownership is
++ * transferred to NSS, which will free via CFRelease().
++ */
++typedef SECStatus (PR_CALLBACK *SSLGetPlatformClientAuthData)(void *arg,
++ PRFileDesc *fd,
++ CERTDistNames *caNames,
++ CERTCertList **pRetCerts,/*return */
++ void **pRetKey);/* return */
++
++/*
++ * Set the client side callback for SSL to retrieve user's private key
++ * and certificate.
++ * fd - the file descriptor for the connection in question
++ * f - the application's callback that delivers the key and cert
++ * a - application specific data
++ */
++SSL_IMPORT SECStatus
++SSL_GetPlatformClientAuthDataHook(PRFileDesc *fd,
++ SSLGetPlatformClientAuthData f, void *a);
+
+ /*
+ ** SNI extension processing callback function.
+ ** It is called when SSL socket receives SNI extension in ClientHello message.
+ ** Upon this callback invocation, application is responsible to reconfigure the
+ ** socket with the data for a particular server name.
+ ** There are three potential outcomes of this function invocation:
+ ** * application does not recognize the name or the type and wants the
+Index: mozilla/security/nss/lib/ssl/ssl3con.c
+===================================================================
+RCS file: /cvsroot/mozilla/security/nss/lib/ssl/ssl3con.c,v
+retrieving revision 1.142
+diff -p -u -8 -r1.142 ssl3con.c
+--- mozilla/security/nss/lib/ssl/ssl3con.c 24 Jun 2010 19:53:20 -0000 1.142
++++ mozilla/security/nss/lib/ssl/ssl3con.c 16 Feb 2011 02:40:21 -0000
+@@ -2007,16 +2007,19 @@ ssl3_ComputeRecordMAC(
+ rv = SECFailure;
+ ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
+ }
+ return rv;
+ }
+
+ static PRBool
+ ssl3_ClientAuthTokenPresent(sslSessionID *sid) {
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ return PR_TRUE;
++#else
+ PK11SlotInfo *slot = NULL;
+ PRBool isPresent = PR_TRUE;
+
+ /* we only care if we are doing client auth */
+ if (!sid || !sid->u.ssl3.clAuthValid) {
+ return PR_TRUE;
+ }
+
+@@ -2030,16 +2033,17 @@ ssl3_ClientAuthTokenPresent(sslSessionID
+ sid->u.ssl3.clAuthModuleID != PK11_GetModuleID(slot) ||
+ (PK11_NeedLogin(slot) && !PK11_IsLoggedIn(slot, NULL))) {
+ isPresent = PR_FALSE;
+ }
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ return isPresent;
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
+ }
+
+ static SECStatus
+ ssl3_CompressMACEncryptRecord(sslSocket * ss,
+ SSL3ContentType type,
+ const SSL3Opaque * pIn,
+ PRUint32 contentLen)
+ {
+@@ -4812,40 +4816,41 @@ ssl3_SendCertificateVerify(sslSocket *ss
+ ssl_GetSpecReadLock(ss);
+ rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0);
+ ssl_ReleaseSpecReadLock(ss);
+ if (rv != SECSuccess) {
+ goto done; /* err code was set by ssl3_ComputeHandshakeHashes */
+ }
+
+ isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ rv = ssl3_PlatformSignHashes(&hashes, ss->ssl3.platformClientKey,
++ &buf, isTLS);
++ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
++ ss->ssl3.platformClientKey = (PlatformKey)NULL;
++#else /* NSS_PLATFORM_CLIENT_AUTH */
+ rv = ssl3_SignHashes(&hashes, ss->ssl3.clientPrivateKey, &buf, isTLS);
+ if (rv == SECSuccess) {
+ PK11SlotInfo * slot;
+ sslSessionID * sid = ss->sec.ci.sid;
+
+ /* Remember the info about the slot that did the signing.
+ ** Later, when doing an SSL restart handshake, verify this.
+ ** These calls are mere accessors, and can't fail.
+ */
+ slot = PK11_GetSlotFromPrivateKey(ss->ssl3.clientPrivateKey);
+ sid->u.ssl3.clAuthSeries = PK11_GetSlotSeries(slot);
+ sid->u.ssl3.clAuthSlotID = PK11_GetSlotID(slot);
+ sid->u.ssl3.clAuthModuleID = PK11_GetModuleID(slot);
+ sid->u.ssl3.clAuthValid = PR_TRUE;
+ PK11_FreeSlot(slot);
+ }
+- /* If we're doing RSA key exchange, we're all done with the private key
+- * here. Diffie-Hellman key exchanges need the client's
+- * private key for the key exchange.
+- */
+- if (ss->ssl3.hs.kea_def->exchKeyType == kt_rsa) {
+- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
+- ss->ssl3.clientPrivateKey = NULL;
+- }
++ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
++ ss->ssl3.clientPrivateKey = NULL;
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
+ if (rv != SECSuccess) {
+ goto done; /* err code was set by ssl3_SignHashes */
+ }
+
+ rv = ssl3_AppendHandshakeHeader(ss, certificate_verify, buf.len + 2);
+ if (rv != SECSuccess) {
+ goto done; /* error code set by AppendHandshake */
+ }
+@@ -4890,16 +4895,36 @@ ssl3_HandleServerHello(sslSocket *ss, SS
+ goto alert_loser;
+ }
+ if (ss->ssl3.hs.ws != wait_server_hello) {
+ errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO;
+ desc = unexpected_message;
+ goto alert_loser;
+ }
+
++ /* clean up anything left from previous handshake. */
++ if (ss->ssl3.clientCertChain != NULL) {
++ CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
++ ss->ssl3.clientCertChain = NULL;
++ }
++ if (ss->ssl3.clientCertificate != NULL) {
++ CERT_DestroyCertificate(ss->ssl3.clientCertificate);
++ ss->ssl3.clientCertificate = NULL;
++ }
++ if (ss->ssl3.clientPrivateKey != NULL) {
++ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
++ ss->ssl3.clientPrivateKey = NULL;
++ }
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ if (ss->ssl3.platformClientKey) {
++ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
++ ss->ssl3.platformClientKey = (PlatformKey)NULL;
++ }
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
++
+ temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
+ if (temp < 0) {
+ goto loser; /* alert has been sent */
+ }
+ version = (SSL3ProtocolVersion)temp;
+
+ /* this is appropriate since the negotiation is complete, and we only
+ ** know SSL 3.x.
+@@ -5430,42 +5455,39 @@ ssl3_HandleCertificateRequest(sslSocket
+ PRBool isTLS = PR_FALSE;
+ int i;
+ int errCode = SSL_ERROR_RX_MALFORMED_CERT_REQUEST;
+ int nnames = 0;
+ SECStatus rv;
+ SSL3AlertDescription desc = illegal_parameter;
+ SECItem cert_types = {siBuffer, NULL, 0};
+ CERTDistNames ca_list;
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ CERTCertList * platform_cert_list = NULL;
++ CERTCertListNode * certNode = NULL;
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
+
+ SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_request handshake",
+ SSL_GETPID(), ss->fd));
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+
+ if (ss->ssl3.hs.ws != wait_cert_request &&
+ ss->ssl3.hs.ws != wait_server_key) {
+ desc = unexpected_message;
+ errCode = SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST;
+ goto alert_loser;
+ }
+
+- /* clean up anything left from previous handshake. */
+- if (ss->ssl3.clientCertChain != NULL) {
+- CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
+- ss->ssl3.clientCertChain = NULL;
+- }
+- if (ss->ssl3.clientCertificate != NULL) {
+- CERT_DestroyCertificate(ss->ssl3.clientCertificate);
+- ss->ssl3.clientCertificate = NULL;
+- }
+- if (ss->ssl3.clientPrivateKey != NULL) {
+- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
+- ss->ssl3.clientPrivateKey = NULL;
+- }
++ PORT_Assert(ss->ssl3.clientCertChain == NULL);
++ PORT_Assert(ss->ssl3.clientCertificate == NULL);
++ PORT_Assert(ss->ssl3.clientPrivateKey == NULL);
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ PORT_Assert(ss->ssl3.platformClientKey == (PlatformKey)NULL);
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
+
+ isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
+ rv = ssl3_ConsumeHandshakeVariable(ss, &cert_types, 1, &b, &length);
+ if (rv != SECSuccess)
+ goto loser; /* malformed, alert has been sent */
+
+ arena = ca_list.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL)
+@@ -5522,31 +5544,82 @@ ssl3_HandleCertificateRequest(sslSocket
+ }
+
+ if (length != 0)
+ goto alert_loser; /* malformed */
+
+ desc = no_certificate;
+ ss->ssl3.hs.ws = wait_hello_done;
+
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ if (ss->getPlatformClientAuthData == NULL) {
++ rv = SECFailure; /* force it to send a no_certificate alert */
++ } else {
++ /* XXX Should pass cert_types in this call!! */
++ rv = (SECStatus)(*ss->getPlatformClientAuthData)(
++ ss->getPlatformClientAuthDataArg,
++ ss->fd, &ca_list,
++ &platform_cert_list,
++ (void**)&ss->ssl3.platformClientKey);
++ }
++#else
+ if (ss->getClientAuthData == NULL) {
+ rv = SECFailure; /* force it to send a no_certificate alert */
+ } else {
+ /* XXX Should pass cert_types in this call!! */
+ rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg,
+ ss->fd, &ca_list,
+ &ss->ssl3.clientCertificate,
+ &ss->ssl3.clientPrivateKey);
+ }
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
+ switch (rv) {
+ case SECWouldBlock: /* getClientAuthData has put up a dialog box. */
+ ssl_SetAlwaysBlock(ss);
+ break; /* not an error */
+
+ case SECSuccess:
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ if (!platform_cert_list || CERT_LIST_EMPTY(platform_cert_list) ||
++ !ss->ssl3.platformClientKey) {
++ if (platform_cert_list) {
++ CERT_DestroyCertList(platform_cert_list);
++ platform_cert_list = NULL;
++ }
++ if (ss->ssl3.platformClientKey) {
++ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
++ ss->ssl3.platformClientKey = (PlatformKey)NULL;
++ }
++ goto send_no_certificate;
++ }
++
++ certNode = CERT_LIST_HEAD(platform_cert_list);
++ ss->ssl3.clientCertificate = CERT_DupCertificate(certNode->cert);
++
++ /* Setting ssl3.clientCertChain non-NULL will cause
++ * ssl3_HandleServerHelloDone to call SendCertificate.
++ * Note: clientCertChain should include the EE cert as
++ * clientCertificate is ignored during the actual sending
++ */
++ ss->ssl3.clientCertChain =
++ hack_NewCertificateListFromCertList(platform_cert_list);
++ CERT_DestroyCertList(platform_cert_list);
++ platform_cert_list = NULL;
++ if (ss->ssl3.clientCertChain == NULL) {
++ if (ss->ssl3.clientCertificate != NULL) {
++ CERT_DestroyCertificate(ss->ssl3.clientCertificate);
++ ss->ssl3.clientCertificate = NULL;
++ }
++ if (ss->ssl3.platformClientKey) {
++ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
++ ss->ssl3.platformClientKey = (PlatformKey)NULL;
++ }
++ goto send_no_certificate;
++ }
++#else
+ /* check what the callback function returned */
+ if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) {
+ /* we are missing either the key or cert */
+ if (ss->ssl3.clientCertificate) {
+ /* got a cert, but no key - free it */
+ CERT_DestroyCertificate(ss->ssl3.clientCertificate);
+ ss->ssl3.clientCertificate = NULL;
+ }
+@@ -5569,16 +5642,17 @@ ssl3_HandleCertificateRequest(sslSocket
+ ss->ssl3.clientCertificate = NULL;
+ }
+ if (ss->ssl3.clientPrivateKey != NULL) {
+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
+ ss->ssl3.clientPrivateKey = NULL;
+ }
+ goto send_no_certificate;
+ }
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
+ break; /* not an error */
+
+ case SECFailure:
+ default:
+ send_no_certificate:
+ if (isTLS) {
+ ss->ssl3.sendEmptyCert = PR_TRUE;
+ } else {
+@@ -5599,16 +5673,20 @@ alert_loser:
+ desc = decode_error;
+ (void)SSL3_SendAlert(ss, alert_fatal, desc);
+ loser:
+ PORT_SetError(errCode);
+ rv = SECFailure;
+ done:
+ if (arena != NULL)
+ PORT_FreeArena(arena, PR_FALSE);
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ if (platform_cert_list)
++ CERT_DestroyCertList(platform_cert_list);
++#endif
+ return rv;
+ }
+
+ /*
+ * attempt to restart the handshake after asynchronously handling
+ * a request for the client's certificate.
+ *
+ * inputs:
+@@ -5697,24 +5775,35 @@ ssl3_HandleServerHelloDone(sslSocket *ss
+ if (ss->ssl3.sendEmptyCert) {
+ ss->ssl3.sendEmptyCert = PR_FALSE;
+ rv = ssl3_SendEmptyCertificate(ss);
+ /* Don't send verify */
+ if (rv != SECSuccess) {
+ goto loser; /* error code is set. */
+ }
+ } else
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ if (ss->ssl3.clientCertChain != NULL &&
++ ss->ssl3.platformClientKey) {
++ send_verify = PR_TRUE;
++ rv = ssl3_SendCertificate(ss);
++ if (rv != SECSuccess) {
++ goto loser; /* error code is set. */
++ }
++ }
++#else
+ if (ss->ssl3.clientCertChain != NULL &&
+ ss->ssl3.clientPrivateKey != NULL) {
+ send_verify = PR_TRUE;
+ rv = ssl3_SendCertificate(ss);
+ if (rv != SECSuccess) {
+ goto loser; /* error code is set. */
+ }
+ }
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
+
+ rv = ssl3_SendClientKeyExchange(ss);
+ if (rv != SECSuccess) {
+ goto loser; /* err is set. */
+ }
+
+ if (send_verify) {
+ rv = ssl3_SendCertificateVerify(ss);
+@@ -9426,16 +9515,20 @@ void
+ ssl3_DestroySSL3Info(sslSocket *ss)
+ {
+
+ if (ss->ssl3.clientCertificate != NULL)
+ CERT_DestroyCertificate(ss->ssl3.clientCertificate);
+
+ if (ss->ssl3.clientPrivateKey != NULL)
+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ if (ss->ssl3.platformClientKey)
++ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
+
+ if (ss->ssl3.peerCertArena != NULL)
+ ssl3_CleanupPeerCerts(ss);
+
+ if (ss->ssl3.clientCertChain != NULL) {
+ CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
+ ss->ssl3.clientCertChain = NULL;
+ }
+Index: mozilla/security/nss/lib/ssl/ssl3ext.c
+===================================================================
+RCS file: /cvsroot/mozilla/security/nss/lib/ssl/ssl3ext.c,v
+retrieving revision 1.14
+diff -p -u -8 -r1.14 ssl3ext.c
+--- mozilla/security/nss/lib/ssl/ssl3ext.c 3 Apr 2010 19:19:07 -0000 1.14
++++ mozilla/security/nss/lib/ssl/ssl3ext.c 16 Feb 2011 02:40:21 -0000
+@@ -41,18 +41,18 @@
+ * ***** END LICENSE BLOCK ***** */
+
+ /* TLS extension code moved here from ssl3ecc.c */
+ /* $Id: ssl3ext.c,v 1.14 2010/04/03 19:19:07 nelson%bolyard.com Exp $ */
+
+ #include "nssrenam.h"
+ #include "nss.h"
+ #include "ssl.h"
+-#include "sslproto.h"
+ #include "sslimpl.h"
++#include "sslproto.h"
+ #include "pk11pub.h"
+ #include "blapi.h"
+ #include "prinit.h"
+
+ static unsigned char key_name[SESS_TICKET_KEY_NAME_LEN];
+ static PK11SymKey *session_ticket_enc_key_pkcs11 = NULL;
+ static PK11SymKey *session_ticket_mac_key_pkcs11 = NULL;
+
+Index: mozilla/security/nss/lib/ssl/sslauth.c
+===================================================================
+RCS file: /cvsroot/mozilla/security/nss/lib/ssl/sslauth.c,v
+retrieving revision 1.16
+diff -p -u -8 -r1.16 sslauth.c
+--- mozilla/security/nss/lib/ssl/sslauth.c 20 Apr 2006 00:20:45 -0000 1.16
++++ mozilla/security/nss/lib/ssl/sslauth.c 16 Feb 2011 02:40:21 -0000
+@@ -204,16 +204,38 @@ SSL_GetClientAuthDataHook(PRFileDesc *s,
+ return SECFailure;
+ }
+
+ ss->getClientAuthData = func;
+ ss->getClientAuthDataArg = arg;
+ return SECSuccess;
+ }
+
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++/* NEED LOCKS IN HERE. */
++SECStatus
++SSL_GetPlatformClientAuthDataHook(PRFileDesc *s,
++ SSLGetPlatformClientAuthData func,
++ void *arg)
++{
++ sslSocket *ss;
++
++ ss = ssl_FindSocket(s);
++ if (!ss) {
++ SSL_DBG(("%d: SSL[%d]: bad socket in GetPlatformClientAuthDataHook",
++ SSL_GETPID(), s));
++ return SECFailure;
++ }
++
++ ss->getPlatformClientAuthData = func;
++ ss->getPlatformClientAuthDataArg = arg;
++ return SECSuccess;
++}
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
++
+ /* NEED LOCKS IN HERE. */
+ SECStatus
+ SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
+ {
+ sslSocket *ss;
+
+ ss = ssl_FindSocket(s);
+ if (!ss) {
+Index: mozilla/security/nss/lib/ssl/sslimpl.h
+===================================================================
+RCS file: /cvsroot/mozilla/security/nss/lib/ssl/sslimpl.h,v
+retrieving revision 1.77
+diff -p -u -8 -r1.77 sslimpl.h
+--- mozilla/security/nss/lib/ssl/sslimpl.h 10 Feb 2010 00:33:50 -0000 1.77
++++ mozilla/security/nss/lib/ssl/sslimpl.h 16 Feb 2011 02:40:21 -0000
+@@ -60,16 +60,25 @@
+ #if defined(XP_UNIX) || defined(XP_BEOS)
+ #include "unistd.h"
+ #endif
+ #include "nssrwlk.h"
+ #include "prthread.h"
+
+ #include "sslt.h" /* for some formerly private types, now public */
+
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++#if defined(XP_WIN32)
++#include <windows.h>
++#include <wincrypt.h>
++#elif defined(XP_MACOSX)
++#include <Security/Security.h>
++#endif
++#endif
++
+ /* to make some of these old enums public without namespace pollution,
+ ** it was necessary to prepend ssl_ to the names.
+ ** These #defines preserve compatibility with the old code here in libssl.
+ */
+ typedef SSLKEAType SSL3KEAType;
+ typedef SSLMACAlgorithm SSL3MACAlgorithm;
+ typedef SSLSignType SSL3SignType;
+
+@@ -782,16 +791,25 @@ const ssl3CipherSuiteDef *suite_def;
+ SSL3Hashes sFinished[2];
+ SSL3Opaque data[72];
+ } finishedMsgs;
+ #ifdef NSS_ENABLE_ECC
+ PRUint32 negotiatedECCurves; /* bit mask */
+ #endif /* NSS_ENABLE_ECC */
+ } SSL3HandshakeState;
+
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++#if defined(XP_WIN32)
++typedef PCERT_KEY_CONTEXT PlatformKey;
++#elif defined(XP_MACOSX)
++typedef SecKeyRef PlatformKey;
++#else
++typedef void *PlatformKey;
++#endif
++#endif
+
+
+ /*
+ ** This is the "ssl3" struct, as in "ss->ssl3".
+ ** note:
+ ** usually, crSpec == cwSpec and prSpec == pwSpec.
+ ** Sometimes, crSpec == pwSpec and prSpec == cwSpec.
+ ** But there are never more than 2 actual specs.
+@@ -805,16 +823,19 @@ struct ssl3StateStr {
+ */
+ ssl3CipherSpec * crSpec; /* current read spec. */
+ ssl3CipherSpec * prSpec; /* pending read spec. */
+ ssl3CipherSpec * cwSpec; /* current write spec. */
+ ssl3CipherSpec * pwSpec; /* pending write spec. */
+
+ CERTCertificate * clientCertificate; /* used by client */
+ SECKEYPrivateKey * clientPrivateKey; /* used by client */
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ PlatformKey platformClientKey; /* used by client */
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
+ CERTCertificateList *clientCertChain; /* used by client */
+ PRBool sendEmptyCert; /* used by client */
+
+ int policy;
+ /* This says what cipher suites we can do, and should
+ * be either SSL_ALLOWED or SSL_RESTRICTED
+ */
+ PRArenaPool * peerCertArena;
+@@ -1045,16 +1066,20 @@ const unsigned char * preferredCipher;
+
+ ssl3KeyPair * stepDownKeyPair; /* RSA step down keys */
+
+ /* Callbacks */
+ SSLAuthCertificate authCertificate;
+ void *authCertificateArg;
+ SSLGetClientAuthData getClientAuthData;
+ void *getClientAuthDataArg;
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ SSLGetPlatformClientAuthData getPlatformClientAuthData;
++ void *getPlatformClientAuthDataArg;
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
+ SSLSNISocketConfig sniSocketConfig;
+ void *sniSocketConfigArg;
+ SSLBadCertHandler handleBadCert;
+ void *badCertArg;
+ SSLHandshakeCallback handshakeCallback;
+ void *handshakeCallbackData;
+ void *pkcs11PinArg;
+
+@@ -1587,16 +1612,36 @@ extern SECStatus SSL3_ShutdownServerCach
+ extern SECStatus ssl_InitSymWrapKeysLock(void);
+
+ extern SECStatus ssl_FreeSymWrapKeysLock(void);
+
+ extern SECStatus ssl_InitSessionCacheLocks(PRBool lazyInit);
+
+ extern SECStatus ssl_FreeSessionCacheLocks(void);
+
++/***************** platform client auth ****************/
++
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++// Releases the platform key.
++extern void ssl_FreePlatformKey(PlatformKey key);
++
++// Implement the client CertificateVerify message for SSL3/TLS1.0
++extern SECStatus ssl3_PlatformSignHashes(SSL3Hashes *hash,
++ PlatformKey key, SECItem *buf,
++ PRBool isTLS);
++
++// Converts a CERTCertList* (A collection of CERTCertificates) into a
++// CERTCertificateList* (A collection of SECItems), or returns NULL if
++// it cannot be converted.
++// This is to allow the platform-supplied chain to be created with purely
++// public API functions, using the preferred CERTCertList mutators, rather
++// pushing this hack to clients.
++extern CERTCertificateList* hack_NewCertificateListFromCertList(
++ CERTCertList* list);
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
+
+ /********************** misc calls *********************/
+
+ extern int ssl_MapLowLevelError(int hiLevelError);
+
+ extern PRUint32 ssl_Time(void);
+
+ extern void SSL_AtomicIncrementLong(long * x);
+Index: mozilla/security/nss/lib/ssl/sslsock.c
+===================================================================
+RCS file: /cvsroot/mozilla/security/nss/lib/ssl/sslsock.c,v
+retrieving revision 1.67
+diff -p -u -8 -r1.67 sslsock.c
+--- mozilla/security/nss/lib/ssl/sslsock.c 25 Apr 2010 23:37:38 -0000 1.67
++++ mozilla/security/nss/lib/ssl/sslsock.c 16 Feb 2011 02:40:21 -0000
+@@ -329,16 +329,20 @@ ssl_DupSocket(sslSocket *os)
+ /*
+ * XXX the preceding CERT_ and SECKEY_ functions can fail and return NULL.
+ * XXX We should detect this, and not just march on with NULL pointers.
+ */
+ ss->authCertificate = os->authCertificate;
+ ss->authCertificateArg = os->authCertificateArg;
+ ss->getClientAuthData = os->getClientAuthData;
+ ss->getClientAuthDataArg = os->getClientAuthDataArg;
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ ss->getPlatformClientAuthData = os->getPlatformClientAuthData;
++ ss->getPlatformClientAuthDataArg = os->getPlatformClientAuthDataArg;
++#endif
+ ss->sniSocketConfig = os->sniSocketConfig;
+ ss->sniSocketConfigArg = os->sniSocketConfigArg;
+ ss->handleBadCert = os->handleBadCert;
+ ss->badCertArg = os->badCertArg;
+ ss->handshakeCallback = os->handshakeCallback;
+ ss->handshakeCallbackData = os->handshakeCallbackData;
+ ss->pkcs11PinArg = os->pkcs11PinArg;
+
+@@ -1338,16 +1342,22 @@ SSL_ReconfigFD(PRFileDesc *model, PRFile
+ if (sm->authCertificate)
+ ss->authCertificate = sm->authCertificate;
+ if (sm->authCertificateArg)
+ ss->authCertificateArg = sm->authCertificateArg;
+ if (sm->getClientAuthData)
+ ss->getClientAuthData = sm->getClientAuthData;
+ if (sm->getClientAuthDataArg)
+ ss->getClientAuthDataArg = sm->getClientAuthDataArg;
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ if (sm->getPlatformClientAuthData)
++ ss->getPlatformClientAuthData = sm->getPlatformClientAuthData;
++ if (sm->getPlatformClientAuthDataArg)
++ ss->getPlatformClientAuthDataArg = sm->getPlatformClientAuthDataArg;
++#endif
+ if (sm->sniSocketConfig)
+ ss->sniSocketConfig = sm->sniSocketConfig;
+ if (sm->sniSocketConfigArg)
+ ss->sniSocketConfigArg = sm->sniSocketConfigArg;
+ if (sm->handleBadCert)
+ ss->handleBadCert = sm->handleBadCert;
+ if (sm->badCertArg)
+ ss->badCertArg = sm->badCertArg;
+@@ -2350,16 +2360,20 @@ ssl_NewSocket(PRBool makeLocks)
+ ss->dbHandle = CERT_GetDefaultCertDB();
+
+ /* Provide default implementation of hooks */
+ ss->authCertificate = SSL_AuthCertificate;
+ ss->authCertificateArg = (void *)ss->dbHandle;
+ ss->sniSocketConfig = NULL;
+ ss->sniSocketConfigArg = NULL;
+ ss->getClientAuthData = NULL;
++#ifdef NSS_PLATFORM_CLIENT_AUTH
++ ss->getPlatformClientAuthData = NULL;
++ ss->getPlatformClientAuthDataArg = NULL;
++#endif /* NSS_PLATFORM_CLIENT_AUTH */
+ ss->handleBadCert = NULL;
+ ss->badCertArg = NULL;
+ ss->pkcs11PinArg = NULL;
+
+ ssl_ChooseOps(ss);
+ ssl2_InitSocketPolicy(ss);
+ ssl3_InitSocketPolicy(ss);
+
diff --git a/net/third_party/nss/patches/dheclientauth.patch b/net/third_party/nss/patches/dheclientauth.patch
deleted file mode 100644
index 92d1d97..0000000
--- a/net/third_party/nss/patches/dheclientauth.patch
+++ /dev/null
@@ -1,98 +0,0 @@
-Index: mozilla/security/nss/lib/ssl/ssl3con.c
-===================================================================
-RCS file: /cvsroot/mozilla/security/nss/lib/ssl/ssl3con.c,v
-retrieving revision 1.142.2.4
-diff -u -p -u -8 -r1.142.2.4 ssl3con.c
---- mozilla/security/nss/lib/ssl/ssl3con.c 1 Sep 2010 19:47:11 -0000 1.142.2.4
-+++ mozilla/security/nss/lib/ssl/ssl3con.c 8 Dec 2010 06:55:49 -0000
-@@ -4832,24 +4832,18 @@ ssl3_SendCertificateVerify(sslSocket *ss
- */
- slot = PK11_GetSlotFromPrivateKey(ss->ssl3.clientPrivateKey);
- sid->u.ssl3.clAuthSeries = PK11_GetSlotSeries(slot);
- sid->u.ssl3.clAuthSlotID = PK11_GetSlotID(slot);
- sid->u.ssl3.clAuthModuleID = PK11_GetModuleID(slot);
- sid->u.ssl3.clAuthValid = PR_TRUE;
- PK11_FreeSlot(slot);
- }
-- /* If we're doing RSA key exchange, we're all done with the private key
-- * here. Diffie-Hellman key exchanges need the client's
-- * private key for the key exchange.
-- */
-- if (ss->ssl3.hs.kea_def->exchKeyType == kt_rsa) {
-- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-- ss->ssl3.clientPrivateKey = NULL;
-- }
-+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-+ ss->ssl3.clientPrivateKey = NULL;
- if (rv != SECSuccess) {
- goto done; /* err code was set by ssl3_SignHashes */
- }
-
- rv = ssl3_AppendHandshakeHeader(ss, certificate_verify, buf.len + 2);
- if (rv != SECSuccess) {
- goto done; /* error code set by AppendHandshake */
- }
-@@ -4894,16 +4888,30 @@ ssl3_HandleServerHello(sslSocket *ss, SS
- goto alert_loser;
- }
- if (ss->ssl3.hs.ws != wait_server_hello) {
- errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO;
- desc = unexpected_message;
- goto alert_loser;
- }
-
-+ /* clean up anything left from previous handshake. */
-+ if (ss->ssl3.clientCertChain != NULL) {
-+ CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
-+ ss->ssl3.clientCertChain = NULL;
-+ }
-+ if (ss->ssl3.clientCertificate != NULL) {
-+ CERT_DestroyCertificate(ss->ssl3.clientCertificate);
-+ ss->ssl3.clientCertificate = NULL;
-+ }
-+ if (ss->ssl3.clientPrivateKey != NULL) {
-+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-+ ss->ssl3.clientPrivateKey = NULL;
-+ }
-+
- temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
- if (temp < 0) {
- goto loser; /* alert has been sent */
- }
- version = (SSL3ProtocolVersion)temp;
-
- /* this is appropriate since the negotiation is complete, and we only
- ** know SSL 3.x.
-@@ -5449,29 +5457,19 @@ ssl3_HandleCertificateRequest(sslSocket
-
- if (ss->ssl3.hs.ws != wait_cert_request &&
- ss->ssl3.hs.ws != wait_server_key) {
- desc = unexpected_message;
- errCode = SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST;
- goto alert_loser;
- }
-
-- /* clean up anything left from previous handshake. */
-- if (ss->ssl3.clientCertChain != NULL) {
-- CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
-- ss->ssl3.clientCertChain = NULL;
-- }
-- if (ss->ssl3.clientCertificate != NULL) {
-- CERT_DestroyCertificate(ss->ssl3.clientCertificate);
-- ss->ssl3.clientCertificate = NULL;
-- }
-- if (ss->ssl3.clientPrivateKey != NULL) {
-- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-- ss->ssl3.clientPrivateKey = NULL;
-- }
-+ PORT_Assert(ss->ssl3.clientCertChain == NULL);
-+ PORT_Assert(ss->ssl3.clientCertificate == NULL);
-+ PORT_Assert(ss->ssl3.clientPrivateKey == NULL);
-
- isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
- rv = ssl3_ConsumeHandshakeVariable(ss, &cert_types, 1, &b, &length);
- if (rv != SECSuccess)
- goto loser; /* malformed, alert has been sent */
-
- arena = ca_list.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL)