diff options
author | rsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-05 02:02:08 +0000 |
---|---|---|
committer | rsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-05 02:02:08 +0000 |
commit | a1cb2cdefd0aabd32581017079fc56eafe369756 (patch) | |
tree | da2ccb1d07a8fd44226182c147a0f8bfe7e89685 /net | |
parent | 08397d5343ddaba1a32a5ac7e0bf3bc03bd3bdf8 (diff) | |
download | chromium_src-a1cb2cdefd0aabd32581017079fc56eafe369756.zip chromium_src-a1cb2cdefd0aabd32581017079fc56eafe369756.tar.gz chromium_src-a1cb2cdefd0aabd32581017079fc56eafe369756.tar.bz2 |
Return more specific error messages when performing a SSL client auth handshake and an error signing with the certificate private key is encountered, rather than using ERR_FAILED/ERR_SSL_PROTOCOL_ERROR.
BUG=69609
TEST=none
Review URL: http://codereview.chromium.org/6371014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73891 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/net_error_list.h | 9 | ||||
-rw-r--r-- | net/http/http_network_transaction.cc | 16 | ||||
-rw-r--r-- | net/socket/nss_ssl_util.cc | 16 | ||||
-rw-r--r-- | net/socket/nss_ssl_util.h | 4 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslplatf.c | 36 |
5 files changed, 58 insertions, 23 deletions
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index 8f94c4a..ab4b45f 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h @@ -220,6 +220,15 @@ NET_ERROR(TEMPORARILY_THROTTLED, -139) // body might include a description of why the request failed. NET_ERROR(HTTPS_PROXY_TUNNEL_RESPONSE, -140) +// We were unable to sign the CertificateVerify data of an SSL client auth +// handshake with the client certificate's private key. +// +// Possible causes for this include the user implicitly or explicitly +// denying access to the private key, the private key may not be valid for +// signing, the key may be relying on a cached handle which is no longer +// valid, or the CSP won't allow arbitrary data to be signed. +NET_ERROR(SSL_CLIENT_AUTH_SIGNATURE_FAILED, -141) + // Certificate error codes // // The values of certificate error codes must be consecutive. diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index a31fb17..e0967c6 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -77,6 +77,19 @@ void ProcessAlternateProtocol(HttpStreamFactory* factory, http_host_port_pair); } +// Returns true if |error| is a client certificate authentication error. +bool IsClientCertificateError(int error) { + switch (error) { + case ERR_BAD_SSL_CLIENT_AUTH_CERT: + case ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED: + case ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY: + case ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED: + return true; + default: + return false; + } +} + } // namespace //----------------------------------------------------------------------------- @@ -1019,8 +1032,7 @@ int HttpNetworkTransaction::HandleCertificateRequest(int error) { int HttpNetworkTransaction::HandleSSLHandshakeError(int error) { DCHECK(request_); if (ssl_config_.send_client_cert && - (error == ERR_SSL_PROTOCOL_ERROR || - error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) { + (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) { session_->ssl_client_auth_cache()->Remove( GetHostAndPort(request_->url)); } diff --git a/net/socket/nss_ssl_util.cc b/net/socket/nss_ssl_util.cc index 1ad1f1c..53318a6 100644 --- a/net/socket/nss_ssl_util.cc +++ b/net/socket/nss_ssl_util.cc @@ -9,6 +9,8 @@ #include <ssl.h> #include <sslerr.h> +#include <string> + #include "base/lazy_instance.h" #include "base/logging.h" #include "base/nss_util.h" @@ -155,6 +157,16 @@ int MapNSSError(PRErrorCode err) { case SEC_ERROR_INVALID_ARGS: return ERR_INVALID_ARGUMENT; + case SEC_ERROR_NO_KEY: + return ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY; + case SEC_ERROR_INVALID_KEY: + case SSL_ERROR_SIGN_HASHES_FAILURE: + return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; + // A handshake (initial or renegotiation) may fail because some signature + // (for example, the signature in the ServerKeyExchange message for an + // ephemeral Diffie-Hellman cipher suite) is invalid. + case SEC_ERROR_BAD_SIGNATURE: + return ERR_SSL_PROTOCOL_ERROR; case SSL_ERROR_SSL_DISABLED: return ERR_NO_SSL_VERSIONS_ENABLED; @@ -193,10 +205,6 @@ int MapNSSHandshakeError(PRErrorCode err) { // If the server closed on us, it is a protocol error. // Some TLS-intolerant servers do this when we request TLS. case PR_END_OF_FILE_ERROR: - // The handshake may fail because some signature (for example, the - // signature in the ServerKeyExchange message for an ephemeral - // Diffie-Hellman cipher suite) is invalid. - case SEC_ERROR_BAD_SIGNATURE: return ERR_SSL_PROTOCOL_ERROR; default: return MapNSSError(err); diff --git a/net/socket/nss_ssl_util.h b/net/socket/nss_ssl_util.h index 64bf3cf..2a53fc7 100644 --- a/net/socket/nss_ssl_util.h +++ b/net/socket/nss_ssl_util.h @@ -6,7 +6,7 @@ // ssl_server_socket_nss.cc to share common functions of NSS. #ifndef NET_SOCKET_NSS_SSL_UTIL_H_ -#define NEt_SOCKET_NSS_SSL_UTIL_H_ +#define NET_SOCKET_NSS_SSL_UTIL_H_ #include <prerror.h> @@ -28,7 +28,7 @@ PRErrorCode MapErrorToNSS(int result); // Map NSS error code to network error code. int MapNSSError(PRErrorCode err); -// Map NSS handshake error to network error code. +// Map NSS error code from the first SSL handshake to network error code. int MapNSSHandshakeError(PRErrorCode err); } // namespace net diff --git a/net/third_party/nss/ssl/sslplatf.c b/net/third_party/nss/ssl/sslplatf.c index 2b006bd..3b2ffb48 100644 --- a/net/third_party/nss/ssl/sslplatf.c +++ b/net/third_party/nss/ssl/sslplatf.c @@ -203,7 +203,11 @@ ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, buf->data = NULL; if (!CryptGetUserKey(key, keySpec, &hKey)) { - PORT_SetError(SEC_ERROR_INVALID_KEY); + if (GetLastError() == NTE_NO_KEY) { + PORT_SetError(SEC_ERROR_NO_KEY); + } else { + PORT_SetError(SEC_ERROR_INVALID_KEY); + } goto done; } @@ -233,31 +237,31 @@ ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, hashItem.len = sizeof(hash->sha); break; default: - PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); + PORT_SetError(SEC_ERROR_INVALID_KEY); goto done; } PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len)); if (!CryptCreateHash(key, hashAlg, 0, 0, &hHash)) { - ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE); + PORT_SetError(SSL_ERROR_SIGN_HASHES_FAILURE); goto done; } argLen = sizeof(hashLen); if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashLen, &argLen, 0)) { - ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE); + PORT_SetError(SSL_ERROR_SIGN_HASHES_FAILURE); goto done; } if (hashLen != hashItem.len) { - ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE); + PORT_SetError(SSL_ERROR_SIGN_HASHES_FAILURE); goto done; } if (!CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*)hashItem.data, 0)) { - ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE); + PORT_SetError(SSL_ERROR_SIGN_HASHES_FAILURE); goto done; } if (!CryptSignHash(hHash, keySpec, NULL, CRYPT_NOHASHOID, NULL, &signatureLen) || signatureLen == 0) { - ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE); + PORT_SetError(SSL_ERROR_SIGN_HASHES_FAILURE); goto done; } buf->data = (unsigned char *)PORT_Alloc(signatureLen); @@ -266,7 +270,7 @@ ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, if (!CryptSignHash(hHash, keySpec, NULL, CRYPT_NOHASHOID, (BYTE*)buf->data, &signatureLen)) { - ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE); + PORT_SetError(SSL_ERROR_SIGN_HASHES_FAILURE); goto done; } buf->len = signatureLen; @@ -288,10 +292,11 @@ ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, } else if (derSig.data) { PORT_Free(derSig.data); } + } else { + rv = SECSuccess; } PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len)); - rv = SECSuccess; done: if (hHash) CryptDestroyHash(hHash); @@ -410,7 +415,7 @@ ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, status = SecKeyGetCSSMKey(key, &cssmKey); if (status != noErr || !cssmKey) { - PORT_SetError(SEC_ERROR_INVALID_KEY); + PORT_SetError(SEC_ERROR_NO_KEY); goto done; } @@ -457,7 +462,7 @@ ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, status = SecKeyGetCredentials(key, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &cssmCreds); if (status != noErr) { - ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE); + PORT_SetError(SSL_ERROR_SIGN_HASHES_FAILURE); goto done; } @@ -467,7 +472,7 @@ ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, cssmRv = CSSM_CSP_CreateSignatureContext(cspHandle, sigAlg, cssmCreds, cssmKey, &cssmSignature); if (cssmRv) { - ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE); + PORT_SetError(SSL_ERROR_SIGN_HASHES_FAILURE); goto done; } @@ -480,7 +485,7 @@ ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, blindingAttr.Attribute.Uint32 = 1; cssmRv = CSSM_UpdateContextAttributes(cssmSignature, 1, &blindingAttr); if (cssmRv) { - ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE); + PORT_SetError(SSL_ERROR_SIGN_HASHES_FAILURE); goto done; } } @@ -488,7 +493,7 @@ ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, cssmRv = CSSM_SignData(cssmSignature, &hashData, 1, CSSM_ALGID_NONE, &signatureData); if (cssmRv) { - ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE); + PORT_SetError(SSL_ERROR_SIGN_HASHES_FAILURE); goto done; } buf->len = signatureData.Length; @@ -504,10 +509,11 @@ ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, } else if (derSig.data) { PORT_Free(derSig.data); } + } else { + rv = SECSuccess; } PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len)); - rv = SECSuccess; done: /* cspHandle, cssmKey, and cssmCreds are owned by the SecKeyRef and * should not be freed. When the PlatformKey is freed, they will be |