summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-05 02:02:08 +0000
committerrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-05 02:02:08 +0000
commita1cb2cdefd0aabd32581017079fc56eafe369756 (patch)
treeda2ccb1d07a8fd44226182c147a0f8bfe7e89685 /net
parent08397d5343ddaba1a32a5ac7e0bf3bc03bd3bdf8 (diff)
downloadchromium_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.h9
-rw-r--r--net/http/http_network_transaction.cc16
-rw-r--r--net/socket/nss_ssl_util.cc16
-rw-r--r--net/socket/nss_ssl_util.h4
-rw-r--r--net/third_party/nss/ssl/sslplatf.c36
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