bug 1040446 - mozilla::pkix: add error code for CA cert used as end-entity cert r=briansmith
authorDavid Keeler <dkeeler@mozilla.com>
Mon, 11 Aug 2014 12:35:45 -0700
changeset 198984 ce8b92c9ad6389fb55e108ca992e0bdb312619d6
parent 198983 957e7446d3f7473571e5d56bb08aa7f835e9727e
child 198985 a8138c05044d8ab72aaf7361e6c2514017db29fa
push id27293
push useremorley@mozilla.com
push dateTue, 12 Aug 2014 14:29:39 +0000
treeherdermozilla-central@ee1ad12a3939 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbriansmith
bugs1040446
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1040446 - mozilla::pkix: add error code for CA cert used as end-entity cert r=briansmith
security/manager/ssl/src/nsUsageArrayHelper.cpp
security/pkix/include/pkix/Result.h
security/pkix/include/pkix/pkixnss.h
security/pkix/lib/pkixcheck.cpp
security/pkix/lib/pkixnss.cpp
--- a/security/manager/ssl/src/nsUsageArrayHelper.cpp
+++ b/security/manager/ssl/src/nsUsageArrayHelper.cpp
@@ -1,24 +1,24 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUsageArrayHelper.h"
 
 #include "mozilla/Assertions.h"
 #include "nsCOMPtr.h"
-#include "nsIDateTimeFormat.h"
+#include "nsComponentManagerUtils.h"
 #include "nsDateTimeFormatCID.h"
-#include "nsComponentManagerUtils.h"
+#include "nsIDateTimeFormat.h"
+#include "nsNSSCertificate.h"
 #include "nsReadableUtils.h"
-#include "nsNSSCertificate.h"
 #include "nsServiceManagerUtils.h"
-
 #include "nspr.h"
+#include "pkix/pkixnss.h"
 #include "secerr.h"
 
 using namespace mozilla;
 using namespace mozilla::psm;
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gPIPNSSLog;
 #endif
@@ -144,16 +144,17 @@ nsUsageArrayHelper::check(uint32_t previ
 void
 nsUsageArrayHelper::verifyFailed(uint32_t *_verified, int err)
 {
   switch (err) {
   /* For these cases, verify only failed for the particular usage */
   case SEC_ERROR_INADEQUATE_KEY_USAGE:
   case SEC_ERROR_INADEQUATE_CERT_TYPE:
   case SEC_ERROR_CA_CERT_INVALID:
+  case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY:
     *_verified = nsNSSCertificate::USAGE_NOT_ALLOWED; break;
   /* These are the cases that have individual error messages */
   case SEC_ERROR_REVOKED_CERTIFICATE:
     *_verified = nsNSSCertificate::CERT_REVOKED; break;
   case SEC_ERROR_EXPIRED_CERTIFICATE:
     *_verified = nsNSSCertificate::CERT_EXPIRED; break;
   case SEC_ERROR_UNTRUSTED_CERT:
     *_verified = nsNSSCertificate::CERT_NOT_TRUSTED; break;
--- a/security/pkix/include/pkix/Result.h
+++ b/security/pkix/include/pkix/Result.h
@@ -72,16 +72,17 @@ MOZILLA_PKIX_ENUM_CLASS Result
   ERROR_OCSP_UNKNOWN_RESPONSE_STATUS = 32,
   ERROR_OCSP_UNKNOWN_CERT = 33,
   ERROR_OCSP_FUTURE_RESPONSE = 34,
 
   ERROR_UNKNOWN_ERROR = 35,
   ERROR_INVALID_KEY = 36,
   ERROR_UNSUPPORTED_KEYALG = 37,
   ERROR_EXPIRED_ISSUER_CERTIFICATE = 38,
+  ERROR_CA_CERT_USED_AS_END_ENTITY = 39,
 
   // Keep this in sync with MAP_LIST in pkixnss.cpp
 
   FATAL_ERROR_INVALID_ARGS = FATAL_ERROR_FLAG | 1,
   FATAL_ERROR_INVALID_STATE = FATAL_ERROR_FLAG | 2,
   FATAL_ERROR_LIBRARY_FAILURE = FATAL_ERROR_FLAG | 3,
   FATAL_ERROR_NO_MEMORY = FATAL_ERROR_FLAG | 4,
 
--- a/security/pkix/include/pkix/pkixnss.h
+++ b/security/pkix/include/pkix/pkixnss.h
@@ -66,17 +66,18 @@ const char* MapResultToName(Result resul
 // involves negating the value of the error and then synthesizing an error
 // in the NS_ERROR_MODULE_SECURITY module. Hence, PSM errors will start at
 // 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_KEY_PINNING_FAILURE = ERROR_BASE + 0,
+  MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY = ERROR_BASE + 1
 };
 
 void RegisterErrorTable();
 
 inline SECItem UnsafeMapInputToSECItem(Input input)
 {
   SECItem result = {
     siBuffer,
--- a/security/pkix/lib/pkixcheck.cpp
+++ b/security/pkix/lib/pkixcheck.cpp
@@ -357,27 +357,20 @@ CheckBasicConstraints(EndEntityOrCA endE
       isCA = true;
     }
   }
 
   if (endEntityOrCA == EndEntityOrCA::MustBeEndEntity) {
     // CA certificates are not trusted as EE certs.
 
     if (isCA) {
-      // TODO(bug 1040446): We use Result::ERROR_CA_CERT_INVALID here so we can
-      // distinguish this error from other errors, given that NSS does not have
-      // a "CA cert used as end-entity" error code since it doesn't have such a
-      // prohibition. We should add such an error code and stop abusing
-      // Result::ERROR_CA_CERT_INVALID this way.
-      //
-      // Note, in particular, that this check prevents a delegated OCSP
-      // response signing certificate with the CA bit from successfully
-      // validating when we check it from pkixocsp.cpp, which is a good thing.
-      //
-      return Result::ERROR_CA_CERT_INVALID;
+      // Note that this check prevents a delegated OCSP response signing
+      // certificate with the CA bit from successfully validating when we check
+      // it from pkixocsp.cpp, which is a good thing.
+      return Result::ERROR_CA_CERT_USED_AS_END_ENTITY;
     }
 
     return Success;
   }
 
   PORT_Assert(endEntityOrCA == EndEntityOrCA::MustBeCA);
 
   // End-entity certificates are not allowed to act as CA certs.
--- a/security/pkix/lib/pkixnss.cpp
+++ b/security/pkix/lib/pkixnss.cpp
@@ -226,16 +226,17 @@ DigestBuf(Input item, /*out*/ uint8_t* d
     MAP(Result::ERROR_OCSP_TRY_SERVER_LATER, SEC_ERROR_OCSP_TRY_SERVER_LATER) \
     MAP(Result::ERROR_OCSP_UNAUTHORIZED_REQUEST, SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST) \
     MAP(Result::ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS) \
     MAP(Result::ERROR_OCSP_UNKNOWN_CERT, SEC_ERROR_OCSP_UNKNOWN_CERT) \
     MAP(Result::ERROR_OCSP_FUTURE_RESPONSE, SEC_ERROR_OCSP_FUTURE_RESPONSE) \
     MAP(Result::ERROR_INVALID_KEY, SEC_ERROR_INVALID_KEY) \
     MAP(Result::ERROR_UNSUPPORTED_KEYALG, SEC_ERROR_UNSUPPORTED_KEYALG) \
     MAP(Result::ERROR_EXPIRED_ISSUER_CERTIFICATE, SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE) \
+    MAP(Result::ERROR_CA_CERT_USED_AS_END_ENTITY, MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY) \
     MAP(Result::FATAL_ERROR_INVALID_ARGS, SEC_ERROR_INVALID_ARGS) \
     MAP(Result::FATAL_ERROR_INVALID_STATE, PR_INVALID_STATE_ERROR) \
     MAP(Result::FATAL_ERROR_LIBRARY_FAILURE, SEC_ERROR_LIBRARY_FAILURE) \
     MAP(Result::FATAL_ERROR_NO_MEMORY, SEC_ERROR_NO_MEMORY) \
     /* nothing here */
 
 Result
 MapPRErrorCodeToResult(PRErrorCode error)
@@ -292,17 +293,21 @@ MapResultToName(Result result)
 
 void
 RegisterErrorTable()
 {
   static const struct PRErrorMessage ErrorTableText[] = {
     { "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." }
+      "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." }
   };
 
   static const struct PRErrorTable ErrorTable = {
     ErrorTableText,
     "pkixerrors",
     ERROR_BASE,
     PR_ARRAY_SIZE(ErrorTableText)
   };