diff options
author | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-27 02:52:00 +0000 |
---|---|---|
committer | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-27 02:52:00 +0000 |
commit | 007c5d2383e8f9b7c8d8f79a26f9a016bea1916b (patch) | |
tree | 245cd55ca33a68f130e400aec97bb6e6108907dc /net | |
parent | 09c7f0e70cbd6b5236d040db3e39118fcccc38ff (diff) | |
download | chromium_src-007c5d2383e8f9b7c8d8f79a26f9a016bea1916b.zip chromium_src-007c5d2383e8f9b7c8d8f79a26f9a016bea1916b.tar.gz chromium_src-007c5d2383e8f9b7c8d8f79a26f9a016bea1916b.tar.bz2 |
Fallback from platform client auth to NSS client auth.
Adds support for origin bound certs on Win and Mac.
BUG=88782
TEST=normal SSL client auth still works & origin-bound auth works following origin-bound testing doc.
Review URL: http://codereview.chromium.org/7839025
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@102877 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 104 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.h | 25 | ||||
-rwxr-xr-x | net/third_party/nss/patches/applypatches.sh | 2 | ||||
-rw-r--r-- | net/third_party/nss/patches/clientauth.patch | 319 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl.h | 12 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3con.c | 128 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslimpl.h | 11 |
7 files changed, 321 insertions, 280 deletions
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index cca0591..41e3413 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -1543,13 +1543,6 @@ int SSLClientSocketNSS::DoHandshake() { return net_error; } -#if defined(NSS_PLATFORM_CLIENT_AUTH) -int SSLClientSocketNSS::ImportOBCertAndKey(CERTCertificate** cert, - SECKEYPrivateKey** key) { - NOTREACHED(); - return ERR_NOT_IMPLEMENTED; -} -#else int SSLClientSocketNSS::ImportOBCertAndKey(CERTCertificate** cert, SECKEYPrivateKey** key) { // Set the certificate. @@ -1583,14 +1576,7 @@ int SSLClientSocketNSS::ImportOBCertAndKey(CERTCertificate** cert, return OK; } -#endif -#if defined(NSS_PLATFORM_CLIENT_AUTH) -int SSLClientSocketNSS::DoGetOBCertComplete(int result) { - NOTREACHED(); - return ERR_NOT_IMPLEMENTED; -} -#else int SSLClientSocketNSS::DoGetOBCertComplete(int result) { ob_cert_request_handle_ = NULL; @@ -1614,7 +1600,6 @@ int SSLClientSocketNSS::DoGetOBCertComplete(int result) { GotoState(STATE_HANDSHAKE); return OK; } -#endif int SSLClientSocketNSS::DoVerifyDNSSEC(int result) { if (ssl_config_.dns_cert_provenance_checking_enabled && @@ -2120,6 +2105,49 @@ SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg, return SECSuccess; } +// static +bool SSLClientSocketNSS::OriginBoundCertNegotiated(PRFileDesc* socket) { + PRBool xtn_negotiated = PR_FALSE; + SECStatus rv = SSL_HandshakeNegotiatedExtension( + socket, ssl_ob_cert_xtn, &xtn_negotiated); + DCHECK_EQ(SECSuccess, rv); + + return xtn_negotiated ? true : false; +} + +SECStatus SSLClientSocketNSS::OriginBoundClientAuthHandler( + CERTCertificate** result_certificate, + SECKEYPrivateKey** result_private_key) { + ob_cert_xtn_negotiated_ = true; + + // We have negotiated the origin-bound certificate extension. + std::string origin = "https://" + host_and_port_.ToString(); + int error = origin_bound_cert_service_->GetOriginBoundCert( + origin, + &ob_private_key_, + &ob_cert_, + &handshake_io_callback_, + &ob_cert_request_handle_); + + if (error == OK) { + // Synchronous success. + int result = ImportOBCertAndKey(result_certificate, + result_private_key); + if (result != OK) + return SECFailure; + + return SECSuccess; + } + + if (error == ERR_IO_PENDING) { + // Asynchronous case. + client_auth_cert_needed_ = true; + return SECWouldBlock; + } + + return SECFailure; // Synchronous failure. +} + #if defined(NSS_PLATFORM_CLIENT_AUTH) // static // NSS calls this if a client certificate is needed. @@ -2128,9 +2156,17 @@ SECStatus SSLClientSocketNSS::PlatformClientAuthHandler( PRFileDesc* socket, CERTDistNames* ca_names, CERTCertList** result_certs, - void** result_private_key) { + void** result_private_key, + CERTCertificate** result_nss_certificate, + SECKEYPrivateKey** result_nss_private_key) { SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); + // Check if an origin-bound certificate is requested. + if (OriginBoundCertNegotiated(socket)) { + return that->OriginBoundClientAuthHandler( + result_nss_certificate, result_nss_private_key); + } + that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert; #if defined(OS_WIN) if (that->ssl_config_.send_client_cert) { @@ -2385,39 +2421,9 @@ SECStatus SSLClientSocketNSS::ClientAuthHandler( SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); // Check if an origin-bound certificate is requested. - PRBool xtn_negotiated = PR_FALSE; - SECStatus rv = SSL_HandshakeNegotiatedExtension( - socket, ssl_ob_cert_xtn, &xtn_negotiated); - DCHECK_EQ(SECSuccess, rv); - that->ob_cert_xtn_negotiated_ = xtn_negotiated ? true : false; - - if (that->ob_cert_xtn_negotiated_) { - // We have negotiated the origin-bound certificate extension. - std::string origin = "https://" + that->host_and_port_.ToString(); - int error = that->origin_bound_cert_service_->GetOriginBoundCert( - origin, - &that->ob_private_key_, - &that->ob_cert_, - &that->handshake_io_callback_, - &that->ob_cert_request_handle_); - - if (error == OK) { - // Synchronous success. - int result = that->ImportOBCertAndKey(result_certificate, - result_private_key); - if (result != OK) - return SECFailure; - - return SECSuccess; - } - - if (error == ERR_IO_PENDING) { - // Asynchronous case - that->client_auth_cert_needed_ = true; - return SECWouldBlock; - } - - return SECFailure; // Synchronous failure. + if (OriginBoundCertNegotiated(socket)) { + return that->OriginBoundClientAuthHandler( + result_certificate, result_private_key); } // Regular client certificate requested. diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h index 0d0b342..6d403f7 100644 --- a/net/socket/ssl_client_socket_nss.h +++ b/net/socket/ssl_client_socket_nss.h @@ -157,14 +157,27 @@ class SSLClientSocketNSS : public SSLClientSocket { // argument. static SECStatus OwnAuthCertHandler(void* arg, PRFileDesc* socket, PRBool checksig, PRBool is_server); - // NSS calls this when client authentication is requested. + // Returns true if connection negotiated the origin bound cert extension. + static bool OriginBoundCertNegotiated(PRFileDesc* socket); + // Origin bound cert client auth handler. + // Returns the value the ClientAuthHandler function should return. + SECStatus OriginBoundClientAuthHandler(CERTCertificate** result_certificate, + SECKEYPrivateKey** result_private_key); #if defined(NSS_PLATFORM_CLIENT_AUTH) - static SECStatus PlatformClientAuthHandler(void* arg, - PRFileDesc* socket, - CERTDistNames* ca_names, - CERTCertList** result_certs, - void** result_private_key); + // On platforms where we use the native certificate store, NSS calls this + // instead when client authentication is requested. At most one of + // (result_certs, result_private_key) or + // (result_nss_certificate, result_nss_private_key) should be set. + static SECStatus PlatformClientAuthHandler( + void* arg, + PRFileDesc* socket, + CERTDistNames* ca_names, + CERTCertList** result_certs, + void** result_private_key, + CERTCertificate** result_nss_certificate, + SECKEYPrivateKey** result_nss_private_key); #else + // NSS calls this when client authentication is requested. static SECStatus ClientAuthHandler(void* arg, PRFileDesc* socket, CERTDistNames* ca_names, diff --git a/net/third_party/nss/patches/applypatches.sh b/net/third_party/nss/patches/applypatches.sh index 8540a40..ecf526f 100755 --- a/net/third_party/nss/patches/applypatches.sh +++ b/net/third_party/nss/patches/applypatches.sh @@ -21,7 +21,7 @@ patch -p6 < $patches_dir/peercertchain.patch patch -p6 < $patches_dir/ocspstapling.patch -patch -p6 < $patches_dir/clientauth.patch +patch -p4 < $patches_dir/clientauth.patch patch -p6 < $patches_dir/cachedinfo.patch diff --git a/net/third_party/nss/patches/clientauth.patch b/net/third_party/nss/patches/clientauth.patch index 76fba67..97d549f 100644 --- a/net/third_party/nss/patches/clientauth.patch +++ b/net/third_party/nss/patches/clientauth.patch @@ -1,21 +1,20 @@ -commit 33952cd5de867c82987e1e9eb9bc8edd56938daa -Author: Adam Langley <agl@chromium.org> -Date: Mon Jun 20 16:19:32 2011 -0400 - - clientauth.patch - -diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/ssl.h -index 221fe2d..563cfd5 100644 ---- a/mozilla/security/nss/lib/ssl/ssl.h -+++ b/mozilla/security/nss/lib/ssl/ssl.h -@@ -332,6 +332,39 @@ typedef SECStatus (PR_CALLBACK *SSLGetClientAuthData)(void *arg, +Index: security/nss/lib/ssl/ssl.h +=================================================================== +RCS file: /cvsroot/mozilla/security/nss/lib/ssl/ssl.h,v +retrieving revision 1.38.2.1 +diff -u -r1.38.2.1 ssl.h +--- security/nss/lib/ssl/ssl.h 31 Jul 2010 04:33:52 -0000 1.38.2.1 ++++ security/nss/lib/ssl/ssl.h 22 Sep 2011 00:21:33 -0000 +@@ -291,6 +291,45 @@ 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. ++ * optionally using the underlying platform's cryptographic primitives. ++ * To use the platform cryptographic primitives, caNames and pRetCerts ++ * should be set. To use NSS, pRetNSSCert and pRetNSSKey should be set. ++ * 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 @@ -28,12 +27,16 @@ index 221fe2d..563cfd5 100644 + * PORT_Free(). + * - Mac OS X: A pointer to a SecKeyRef. Ownership is + * transferred to NSS, which will free via CFRelease(). ++ * pRetNSSCert - pointer to pointer to NSS cert, for return of cert. ++ * pRetNSSKey - pointer to NSS key pointer, for return of key. + */ +typedef SECStatus (PR_CALLBACK *SSLGetPlatformClientAuthData)(void *arg, + PRFileDesc *fd, + CERTDistNames *caNames, + CERTCertList **pRetCerts,/*return */ -+ void **pRetKey);/* return */ ++ void **pRetKey,/* return */ ++ CERTCertificate **pRetNSSCert,/*return */ ++ SECKEYPrivateKey **pRetNSSKey);/* return */ + +/* + * Set the client side callback for SSL to retrieve user's private key @@ -48,60 +51,75 @@ index 221fe2d..563cfd5 100644 /* ** SNI extension processing callback function. -diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c -index ca2793f..0997e18 100644 ---- a/mozilla/security/nss/lib/ssl/ssl3con.c -+++ b/mozilla/security/nss/lib/ssl/ssl3con.c -@@ -2014,6 +2014,9 @@ ssl3_ComputeRecordMAC( - - static PRBool - ssl3_ClientAuthTokenPresent(sslSessionID *sid) { -+#ifdef NSS_PLATFORM_CLIENT_AUTH -+ return PR_TRUE; -+#else - PK11SlotInfo *slot = NULL; +Index: 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 -r1.142.2.4 ssl3con.c +--- security/nss/lib/ssl/ssl3con.c 1 Sep 2010 19:47:11 -0000 1.142.2.4 ++++ security/nss/lib/ssl/ssl3con.c 22 Sep 2011 00:21:33 -0000 +@@ -2016,6 +2016,9 @@ PRBool isPresent = PR_TRUE; -@@ -2037,6 +2040,7 @@ ssl3_ClientAuthTokenPresent(sslSessionID *sid) { - PK11_FreeSlot(slot); + /* we only care if we are doing client auth */ ++ /* If NSS_PLATFORM_CLIENT_AUTH is defined and a platformClientKey is being ++ * used, u.ssl3.clAuthValid will be false and this function will always ++ * return PR_TRUE. */ + if (!sid || !sid->u.ssl3.clAuthValid) { + return PR_TRUE; } - return isPresent; -+#endif /* NSS_PLATFORM_CLIENT_AUTH */ - } - - static SECStatus -@@ -4823,6 +4827,12 @@ ssl3_SendCertificateVerify(sslSocket *ss) +@@ -4821,27 +4824,30 @@ } isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); +- rv = ssl3_SignHashes(&hashes, ss->ssl3.clientPrivateKey, &buf, isTLS); +- if (rv == SECSuccess) { +- PK11SlotInfo * slot; +- sslSessionID * sid = ss->sec.ci.sid; ++ if (ss->ssl3.platformClientKey) { +#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; -@@ -4839,14 +4849,9 @@ ssl3_SendCertificateVerify(sslSocket *ss) - sid->u.ssl3.clAuthValid = PR_TRUE; - PK11_FreeSlot(slot); - } ++ rv = ssl3_PlatformSignHashes(&hashes, ss->ssl3.platformClientKey, ++ &buf, isTLS); ++ ssl_FreePlatformKey(ss->ssl3.platformClientKey); ++ ss->ssl3.platformClientKey = (PlatformKey)NULL; ++#endif /* NSS_PLATFORM_CLIENT_AUTH */ ++ } else { ++ 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 */ ++ /* 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); ++ } + SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); + ss->ssl3.clientPrivateKey = NULL; } -@@ -4901,6 +4906,26 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +@@ -4899,6 +4905,26 @@ goto alert_loser; } @@ -128,7 +146,7 @@ index ca2793f..0997e18 100644 temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); if (temp < 0) { goto loser; /* alert has been sent */ -@@ -5444,6 +5469,10 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +@@ -5441,6 +5467,10 @@ SSL3AlertDescription desc = illegal_parameter; SECItem cert_types = {siBuffer, NULL, 0}; CERTDistNames ca_list; @@ -139,7 +157,7 @@ index ca2793f..0997e18 100644 SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_request handshake", SSL_GETPID(), ss->fd)); -@@ -5457,19 +5486,12 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +@@ -5454,19 +5484,10 @@ goto alert_loser; } @@ -159,13 +177,11 @@ index ca2793f..0997e18 100644 + 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); -@@ -5536,6 +5558,18 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +@@ -5533,6 +5554,20 @@ desc = no_certificate; ss->ssl3.hs.ws = wait_hello_done; @@ -178,13 +194,15 @@ index ca2793f..0997e18 100644 + ss->getPlatformClientAuthDataArg, + ss->fd, &ca_list, + &platform_cert_list, -+ (void**)&ss->ssl3.platformClientKey); ++ (void**)&ss->ssl3.platformClientKey, ++ &ss->ssl3.clientCertificate, ++ &ss->ssl3.clientPrivateKey); + } +#else if (ss->getClientAuthData == NULL) { rv = SECFailure; /* force it to send a no_certificate alert */ } else { -@@ -5545,12 +5579,51 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +@@ -5542,12 +5577,52 @@ &ss->ssl3.clientCertificate, &ss->ssl3.clientPrivateKey); } @@ -206,45 +224,38 @@ index ca2793f..0997e18 100644 + 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 ++ /* Fall through to NSS client auth check */ ++ } else { ++ 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; ++ } ++ break; /* not an error */ ++ } ++#endif /* NSS_PLATFORM_CLIENT_AUTH */ /* check what the callback function returned */ if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) { /* we are missing either the key or cert */ -@@ -5583,6 +5656,7 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) - } - goto send_no_certificate; - } -+#endif /* NSS_PLATFORM_CLIENT_AUTH */ - break; /* not an error */ - - case SECFailure: -@@ -5613,6 +5687,10 @@ loser: +@@ -5610,6 +5685,10 @@ done: if (arena != NULL) PORT_FreeArena(arena, PR_FALSE); @@ -255,32 +266,28 @@ index ca2793f..0997e18 100644 return rv; } -@@ -5721,6 +5799,16 @@ ssl3_HandleServerHelloDone(sslSocket *ss) +@@ -5717,9 +5796,17 @@ + if (rv != SECSuccess) { goto loser; /* error code is set. */ } - } else +- } else +- if (ss->ssl3.clientCertChain != NULL && +- ss->ssl3.clientPrivateKey != NULL) { ++ } else if (ss->ssl3.clientCertChain != NULL && ++ ss->ssl3.platformClientKey) { +#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; -@@ -5729,6 +5817,7 @@ ssl3_HandleServerHelloDone(sslSocket *ss) - goto loser; /* error code is set. */ - } - } +#endif /* NSS_PLATFORM_CLIENT_AUTH */ - - rv = ssl3_SendClientKeyExchange(ss); - if (rv != SECSuccess) { -@@ -9657,6 +9746,10 @@ ssl3_DestroySSL3Info(sslSocket *ss) ++ } else if (ss->ssl3.clientCertChain != NULL && ++ ss->ssl3.clientPrivateKey != NULL) { + send_verify = PR_TRUE; + rv = ssl3_SendCertificate(ss); + if (rv != SECSuccess) { +@@ -9453,6 +9540,10 @@ if (ss->ssl3.clientPrivateKey != NULL) SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); @@ -291,10 +298,13 @@ index ca2793f..0997e18 100644 if (ss->ssl3.peerCertArena != NULL) ssl3_CleanupPeerCerts(ss); -diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/ssl/ssl3ext.c -index 4e3d9cc..94dab58 100644 ---- a/mozilla/security/nss/lib/ssl/ssl3ext.c -+++ b/mozilla/security/nss/lib/ssl/ssl3ext.c +Index: security/nss/lib/ssl/ssl3ext.c +=================================================================== +RCS file: /cvsroot/mozilla/security/nss/lib/ssl/ssl3ext.c,v +retrieving revision 1.14 +diff -u -r1.14 ssl3ext.c +--- security/nss/lib/ssl/ssl3ext.c 3 Apr 2010 19:19:07 -0000 1.14 ++++ security/nss/lib/ssl/ssl3ext.c 22 Sep 2011 00:21:33 -0000 @@ -46,8 +46,8 @@ #include "nssrenam.h" #include "nss.h" @@ -305,11 +315,14 @@ index 4e3d9cc..94dab58 100644 #include "pk11pub.h" #include "blapi.h" #include "prinit.h" -diff --git a/mozilla/security/nss/lib/ssl/sslauth.c b/mozilla/security/nss/lib/ssl/sslauth.c -index df40f30..447aaf8 100644 ---- a/mozilla/security/nss/lib/ssl/sslauth.c -+++ b/mozilla/security/nss/lib/ssl/sslauth.c -@@ -252,6 +252,28 @@ SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func, +Index: security/nss/lib/ssl/sslauth.c +=================================================================== +RCS file: /cvsroot/mozilla/security/nss/lib/ssl/sslauth.c,v +retrieving revision 1.16.66.1 +diff -u -r1.16.66.1 sslauth.c +--- security/nss/lib/ssl/sslauth.c 3 Aug 2010 18:52:13 -0000 1.16.66.1 ++++ security/nss/lib/ssl/sslauth.c 22 Sep 2011 00:21:33 -0000 +@@ -216,6 +216,28 @@ return SECSuccess; } @@ -338,10 +351,13 @@ index df40f30..447aaf8 100644 /* NEED LOCKS IN HERE. */ SECStatus SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg) -diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/ssl/sslimpl.h -index 8e2bd14..2e1364e 100644 ---- a/mozilla/security/nss/lib/ssl/sslimpl.h -+++ b/mozilla/security/nss/lib/ssl/sslimpl.h +Index: security/nss/lib/ssl/sslimpl.h +=================================================================== +RCS file: /cvsroot/mozilla/security/nss/lib/ssl/sslimpl.h,v +retrieving revision 1.77.2.1 +diff -u -r1.77.2.1 sslimpl.h +--- security/nss/lib/ssl/sslimpl.h 31 Jul 2010 04:33:52 -0000 1.77.2.1 ++++ security/nss/lib/ssl/sslimpl.h 22 Sep 2011 00:21:33 -0000 @@ -65,6 +65,15 @@ #include "sslt.h" /* for some formerly private types, now public */ @@ -358,34 +374,33 @@ index 8e2bd14..2e1364e 100644 /* 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. -@@ -462,6 +471,16 @@ typedef SECStatus (*SSLCompressor)(void * context, +@@ -456,6 +465,14 @@ int inlen); typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit); -+#ifdef NSS_PLATFORM_CLIENT_AUTH -+#if defined(XP_WIN32) ++#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_WIN32) +typedef PCERT_KEY_CONTEXT PlatformKey; -+#elif defined(XP_MACOSX) ++#elif defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_MACOSX) +typedef SecKeyRef PlatformKey; +#else +typedef void *PlatformKey; +#endif -+#endif + /* -@@ -829,6 +848,9 @@ struct ssl3StateStr { +@@ -811,6 +828,10 @@ CERTCertificate * clientCertificate; /* used by client */ SECKEYPrivateKey * clientPrivateKey; /* used by client */ -+#ifdef NSS_PLATFORM_CLIENT_AUTH ++ /* platformClientKey is present even when NSS_PLATFORM_CLIENT_AUTH is not ++ * defined in order to allow cleaner conditional code. ++ * At most one of clientPrivateKey and platformClientKey may be set. */ + PlatformKey platformClientKey; /* used by client */ -+#endif /* NSS_PLATFORM_CLIENT_AUTH */ CERTCertificateList *clientCertChain; /* used by client */ PRBool sendEmptyCert; /* used by client */ -@@ -1079,6 +1101,10 @@ const unsigned char * preferredCipher; +@@ -1051,6 +1072,10 @@ void *authCertificateArg; SSLGetClientAuthData getClientAuthData; void *getClientAuthDataArg; @@ -396,7 +411,7 @@ index 8e2bd14..2e1364e 100644 SSLSNISocketConfig sniSocketConfig; void *sniSocketConfigArg; SSLBadCertHandler handleBadCert; -@@ -1635,6 +1661,26 @@ extern SECStatus ssl_InitSessionCacheLocks(PRBool lazyInit); +@@ -1595,6 +1620,26 @@ extern SECStatus ssl_FreeSessionCacheLocks(void); @@ -423,11 +438,12 @@ index 8e2bd14..2e1364e 100644 /********************** misc calls *********************/ -diff --git a/mozilla/security/nss/lib/ssl/sslplatf.c b/mozilla/security/nss/lib/ssl/sslplatf.c -new file mode 100644 -index 0000000..208956f ---- /dev/null -+++ b/mozilla/security/nss/lib/ssl/sslplatf.c +Index: security/nss/lib/ssl/sslplatf.c +=================================================================== +RCS file: security/nss/lib/ssl/sslplatf.c +diff -N security/nss/lib/ssl/sslplatf.c +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ security/nss/lib/ssl/sslplatf.c 22 Sep 2011 00:21:33 -0000 @@ -0,0 +1,399 @@ +/* + * Platform specific crypto wrappers @@ -828,11 +844,14 @@ index 0000000..208956f +#endif + +#endif /* NSS_PLATFORM_CLIENT_AUTH */ -diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/ssl/sslsock.c -index 4c4df3f..1bb211e 100644 ---- a/mozilla/security/nss/lib/ssl/sslsock.c -+++ b/mozilla/security/nss/lib/ssl/sslsock.c -@@ -337,6 +337,10 @@ ssl_DupSocket(sslSocket *os) +Index: security/nss/lib/ssl/sslsock.c +=================================================================== +RCS file: /cvsroot/mozilla/security/nss/lib/ssl/sslsock.c,v +retrieving revision 1.67.2.1 +diff -u -r1.67.2.1 sslsock.c +--- security/nss/lib/ssl/sslsock.c 31 Jul 2010 04:33:52 -0000 1.67.2.1 ++++ security/nss/lib/ssl/sslsock.c 22 Sep 2011 00:21:33 -0000 +@@ -335,6 +335,10 @@ ss->authCertificateArg = os->authCertificateArg; ss->getClientAuthData = os->getClientAuthData; ss->getClientAuthDataArg = os->getClientAuthDataArg; @@ -843,7 +862,7 @@ index 4c4df3f..1bb211e 100644 ss->sniSocketConfig = os->sniSocketConfig; ss->sniSocketConfigArg = os->sniSocketConfigArg; ss->handleBadCert = os->handleBadCert; -@@ -1446,6 +1450,12 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd) +@@ -1354,6 +1358,12 @@ ss->getClientAuthData = sm->getClientAuthData; if (sm->getClientAuthDataArg) ss->getClientAuthDataArg = sm->getClientAuthDataArg; @@ -856,7 +875,7 @@ index 4c4df3f..1bb211e 100644 if (sm->sniSocketConfig) ss->sniSocketConfig = sm->sniSocketConfig; if (sm->sniSocketConfigArg) -@@ -2489,6 +2499,10 @@ ssl_NewSocket(PRBool makeLocks) +@@ -2366,6 +2376,10 @@ ss->sniSocketConfig = NULL; ss->sniSocketConfigArg = NULL; ss->getClientAuthData = NULL; diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h index d0e0595..03535f3 100644 --- a/net/third_party/nss/ssl/ssl.h +++ b/net/third_party/nss/ssl/ssl.h @@ -355,8 +355,10 @@ SSL_IMPORT SECStatus SSL_GetClientAuthDataHook(PRFileDesc *fd, /* * 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. + * optionally using the underlying platform's cryptographic primitives. + * To use the platform cryptographic primitives, caNames and pRetCerts + * should be set. To use NSS, pRetNSSCert and pRetNSSKey should be set. + * 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 @@ -369,12 +371,16 @@ SSL_IMPORT SECStatus SSL_GetClientAuthDataHook(PRFileDesc *fd, * PORT_Free(). * - Mac OS X: A pointer to a SecKeyRef. Ownership is * transferred to NSS, which will free via CFRelease(). + * pRetNSSCert - pointer to pointer to NSS cert, for return of cert. + * pRetNSSKey - pointer to NSS key pointer, for return of key. */ typedef SECStatus (PR_CALLBACK *SSLGetPlatformClientAuthData)(void *arg, PRFileDesc *fd, CERTDistNames *caNames, CERTCertList **pRetCerts,/*return */ - void **pRetKey);/* return */ + void **pRetKey,/* return */ + CERTCertificate **pRetNSSCert,/*return */ + SECKEYPrivateKey **pRetNSSKey);/* return */ /* * Set the client side callback for SSL to retrieve user's private key diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c index 20be3e0..f305acb 100644 --- a/net/third_party/nss/ssl/ssl3con.c +++ b/net/third_party/nss/ssl/ssl3con.c @@ -2014,13 +2014,13 @@ ssl3_ComputeRecordMAC( 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 NSS_PLATFORM_CLIENT_AUTH is defined and a platformClientKey is being + * used, u.ssl3.clAuthValid will be false and this function will always + * return PR_TRUE. */ if (!sid || !sid->u.ssl3.clAuthValid) { return PR_TRUE; } @@ -2040,7 +2040,6 @@ ssl3_ClientAuthTokenPresent(sslSessionID *sid) { PK11_FreeSlot(slot); } return isPresent; -#endif /* NSS_PLATFORM_CLIENT_AUTH */ } static SECStatus @@ -4856,31 +4855,33 @@ ssl3_SendCertificateVerify(sslSocket *ss) } isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); + if (ss->ssl3.platformClientKey) { #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; + rv = ssl3_PlatformSignHashes(&hashes, ss->ssl3.platformClientKey, + &buf, isTLS); + ssl_FreePlatformKey(ss->ssl3.platformClientKey); + ss->ssl3.platformClientKey = (PlatformKey)NULL; +#endif /* NSS_PLATFORM_CLIENT_AUTH */ + } else { + 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); + /* 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); + } + 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 */ } @@ -5517,9 +5518,7 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) 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); @@ -5595,7 +5594,9 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ss->getPlatformClientAuthDataArg, ss->fd, &ca_list, &platform_cert_list, - (void**)&ss->ssl3.platformClientKey); + (void**)&ss->ssl3.platformClientKey, + &ss->ssl3.clientCertificate, + &ss->ssl3.clientPrivateKey); } #else if (ss->getClientAuthData == NULL) { @@ -5625,33 +5626,34 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) 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 + /* Fall through to NSS client auth check */ + } else { + 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; + } + break; /* not an error */ + } +#endif /* NSS_PLATFORM_CLIENT_AUTH */ /* check what the callback function returned */ if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) { /* we are missing either the key or cert */ @@ -5684,7 +5686,6 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } goto send_no_certificate; } -#endif /* NSS_PLATFORM_CLIENT_AUTH */ break; /* not an error */ case SECFailure: @@ -5850,26 +5851,23 @@ ssl3_HandleServerHelloDone(sslSocket *ss) if (rv != SECSuccess) { goto loser; /* error code is set. */ } - } else + } else if (ss->ssl3.clientCertChain != NULL && + ss->ssl3.platformClientKey) { #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) { +#endif /* NSS_PLATFORM_CLIENT_AUTH */ + } 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) { diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h index e447a7d..d73a0e3 100644 --- a/net/third_party/nss/ssl/sslimpl.h +++ b/net/third_party/nss/ssl/sslimpl.h @@ -473,15 +473,13 @@ typedef SECStatus (*SSLCompressor)(void * context, int inlen); typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit); -#ifdef NSS_PLATFORM_CLIENT_AUTH -#if defined(XP_WIN32) +#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_WIN32) typedef PCERT_KEY_CONTEXT PlatformKey; -#elif defined(XP_MACOSX) +#elif defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_MACOSX) typedef SecKeyRef PlatformKey; #else typedef void *PlatformKey; #endif -#endif @@ -855,9 +853,10 @@ struct ssl3StateStr { CERTCertificate * clientCertificate; /* used by client */ SECKEYPrivateKey * clientPrivateKey; /* used by client */ -#ifdef NSS_PLATFORM_CLIENT_AUTH + /* platformClientKey is present even when NSS_PLATFORM_CLIENT_AUTH is not + * defined in order to allow cleaner conditional code. + * At most one of clientPrivateKey and platformClientKey may be set. */ PlatformKey platformClientKey; /* used by client */ -#endif /* NSS_PLATFORM_CLIENT_AUTH */ CERTCertificateList *clientCertChain; /* used by client */ PRBool sendEmptyCert; /* used by client */ |