bug 1042889 - use a separate error for untrusted x509v1 certificates used as CAs r=briansmith
--- a/security/manager/locales/en-US/chrome/pipnss/nsserrors.properties
+++ b/security/manager/locales/en-US/chrome/pipnss/nsserrors.properties
@@ -309,8 +309,9 @@ SEC_ERROR_CRL_IMPORT_FAILED=Error attemp
SEC_ERROR_EXPIRED_PASSWORD=The password expired.
SEC_ERROR_LOCKED_PASSWORD=The password is locked.
SEC_ERROR_UNKNOWN_PKCS11_ERROR=Unknown PKCS #11 error.
SEC_ERROR_BAD_CRL_DP_URL=Invalid or unsupported URL in CRL distribution point name.
SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED=The certificate was signed using a signature algorithm that is disabled because it is not secure.
MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE=The server uses key pinning (HPKP) but no trusted certificate chain could be constructed that matches the pinset. Key pinning violations cannot be overridden.
MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY=The server uses a certificate with a basic constraints extension identifying it as a certificate authority. For a properly-issued certificate, this should not be the case.
MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE=The server presented a certificate with a key size that is too small to establish a secure connection.
+MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA=An X.509 version 1 certificate that is not a trust anchor was used to issue the server's certificate. X.509 version 1 certificates are deprecated and should not be used to sign other certificates.
--- a/security/pkix/include/pkix/Result.h
+++ b/security/pkix/include/pkix/Result.h
@@ -119,16 +119,18 @@ static const unsigned int FATAL_ERROR_FL
MOZILLA_PKIX_MAP(ERROR_UNSUPPORTED_KEYALG, 37, \
SEC_ERROR_UNSUPPORTED_KEYALG) \
MOZILLA_PKIX_MAP(ERROR_EXPIRED_ISSUER_CERTIFICATE, 38, \
SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE) \
MOZILLA_PKIX_MAP(ERROR_CA_CERT_USED_AS_END_ENTITY, 39, \
MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY) \
MOZILLA_PKIX_MAP(ERROR_INADEQUATE_KEY_SIZE, 40, \
MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE) \
+ MOZILLA_PKIX_MAP(ERROR_V1_CERT_USED_AS_CA, 41, \
+ MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA) \
MOZILLA_PKIX_MAP(FATAL_ERROR_INVALID_ARGS, FATAL_ERROR_FLAG | 1, \
SEC_ERROR_INVALID_ARGS) \
MOZILLA_PKIX_MAP(FATAL_ERROR_INVALID_STATE, FATAL_ERROR_FLAG | 2, \
PR_INVALID_STATE_ERROR) \
MOZILLA_PKIX_MAP(FATAL_ERROR_LIBRARY_FAILURE, FATAL_ERROR_FLAG | 3, \
SEC_ERROR_LIBRARY_FAILURE) \
MOZILLA_PKIX_MAP(FATAL_ERROR_NO_MEMORY, FATAL_ERROR_FLAG | 4, \
SEC_ERROR_NO_MEMORY) \
--- a/security/pkix/include/pkix/pkixnss.h
+++ b/security/pkix/include/pkix/pkixnss.h
@@ -64,17 +64,18 @@ PRErrorCode MapResultToPRErrorCode(Resul
// a negative value that both doesn't overlap with the current value
// ranges for NSS errors and that will fit in 16 bits when negated.
static const PRErrorCode ERROR_BASE = -0x4000;
static const PRErrorCode ERROR_LIMIT = ERROR_BASE + 1000;
enum ErrorCode {
MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE = ERROR_BASE + 0,
MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY = ERROR_BASE + 1,
- MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE = ERROR_BASE + 2
+ MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE = ERROR_BASE + 2,
+ MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA = ERROR_BASE + 3,
};
void RegisterErrorTable();
inline SECItem UnsafeMapInputToSECItem(Input input)
{
SECItem result = {
siBuffer,
--- a/security/pkix/lib/pkixcheck.cpp
+++ b/security/pkix/lib/pkixcheck.cpp
@@ -343,20 +343,28 @@ CheckBasicConstraints(EndEntityOrCA endE
// "If the basic constraints extension is not present in a version 3
// certificate, or the extension is present but the cA boolean is not
// asserted, then the certified public key MUST NOT be used to verify
// certificate signatures."
//
// For compatibility, we must accept v1 trust anchors without basic
// constraints as CAs.
//
+ // There are devices with v1 certificates that are unlikely to be trust
+ // anchors. In order to allow applications to treat this case differently
+ // from other basic constraints violations (e.g. allowing certificate error
+ // overrides for only this case), we return a different error code.
+ //
// TODO: add check for self-signedness?
- if (endEntityOrCA == EndEntityOrCA::MustBeCA &&
- trustLevel == TrustLevel::TrustAnchor && version == der::Version::v1) {
- isCA = true;
+ if (endEntityOrCA == EndEntityOrCA::MustBeCA && version == der::Version::v1) {
+ if (trustLevel == TrustLevel::TrustAnchor) {
+ isCA = true;
+ } else {
+ return Result::ERROR_V1_CERT_USED_AS_CA;
+ }
}
}
if (endEntityOrCA == EndEntityOrCA::MustBeEndEntity) {
// CA certificates are not trusted as EE certs.
if (isCA) {
// Note that this check prevents a delegated OCSP response signing
--- a/security/pkix/lib/pkixnss.cpp
+++ b/security/pkix/lib/pkixnss.cpp
@@ -237,17 +237,21 @@ RegisterErrorTable()
"could be constructed that matches the pinset. Key pinning violations "
"cannot be overridden." },
{ "MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY",
"The server uses a certificate with a basic constraints extension "
"identifying it as a certificate authority. For a properly-issued "
"certificate, this should not be the case." },
{ "MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE",
"The server presented a certificate with a key size that is too small "
- "to establish a secure connection." }
+ "to establish a secure connection." },
+ { "MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA",
+ "An X.509 version 1 certificate that is not a trust anchor was used to "
+ "issue the server's certificate. X.509 version 1 certificates are "
+ "deprecated and should not be used to sign other certificates." },
};
// Note that these error strings are not localizable.
// When these strings change, update the localization information too.
static const struct PRErrorTable ErrorTable = {
ErrorTableText,
"pkixerrors",
ERROR_BASE,