Bug 1002933: Use Strongly-typed enums more often in mozilla::pkix, r=mmc
authorBrian Smith <brian@briansmith.org>
Fri, 25 Apr 2014 16:29:26 -0700
changeset 181275 c968e47ef70893902ed49f65ade8a2ffe116ea11
parent 181274 f8cb84a2584fe157f056fb1c3aa8910a98513a4a
child 181276 9bca81260db48b5a1b92e1e505c99782db48dabc
push id26699
push usercbook@mozilla.com
push dateFri, 02 May 2014 12:30:59 +0000
treeherdermozilla-central@66ea09d0c951 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmmc
bugs1002933
milestone32.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 1002933: Use Strongly-typed enums more often in mozilla::pkix, r=mmc
security/apps/AppSignatureVerification.cpp
security/apps/AppTrustDomain.cpp
security/apps/AppTrustDomain.h
security/certverifier/CertVerifier.cpp
security/certverifier/NSSCertDBTrustDomain.cpp
security/certverifier/NSSCertDBTrustDomain.h
security/pkix/include/pkix/enumclass.h
security/pkix/include/pkix/pkixtypes.h
security/pkix/lib/pkixbuild.cpp
security/pkix/lib/pkixcheck.cpp
security/pkix/lib/pkixcheck.h
security/pkix/lib/pkixder.h
security/pkix/lib/pkixocsp.cpp
security/pkix/lib/pkixutil.h
security/pkix/test/gtest/pkixder_input_tests.cpp
--- a/security/apps/AppSignatureVerification.cpp
+++ b/security/apps/AppSignatureVerification.cpp
@@ -598,18 +598,19 @@ VerifySignature(AppTrustedRoot trustedRo
     return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
   }
 
   // Verify certificate.
   AppTrustDomain trustDomain(nullptr); // TODO: null pinArg
   if (trustDomain.SetTrustedRoot(trustedRoot) != SECSuccess) {
     return MapSECStatus(SECFailure);
   }
-  if (BuildCertChain(trustDomain, signerCert, PR_Now(), MustBeEndEntity,
-                     KU_DIGITAL_SIGNATURE, SEC_OID_EXT_KEY_USAGE_CODE_SIGN,
+  if (BuildCertChain(trustDomain, signerCert, PR_Now(),
+                     EndEntityOrCA::MustBeEndEntity, KU_DIGITAL_SIGNATURE,
+                     SEC_OID_EXT_KEY_USAGE_CODE_SIGN,
                      SEC_OID_X509_ANY_POLICY, nullptr, builtChain)
         != SECSuccess) {
     return MapSECStatus(SECFailure);
   }
 
   // See NSS_CMSContentInfo_GetContentTypeOID, which isn't exported from NSS.
   SECOidData* contentTypeOidData =
     SECOID_FindOID(&signedData->contentInfo.contentType);
--- a/security/apps/AppTrustDomain.cpp
+++ b/security/apps/AppTrustDomain.cpp
@@ -125,47 +125,47 @@ AppTrustDomain::GetCertTrust(EndEntityOr
   if (CERT_GetCertTrust(candidateCert, &trust) == SECSuccess) {
     PRUint32 flags = SEC_GET_TRUST_FLAGS(&trust, trustObjectSigning);
 
     // For DISTRUST, we use the CERTDB_TRUSTED or CERTDB_TRUSTED_CA bit,
     // because we can have active distrust for either type of cert. Note that
     // CERTDB_TERMINAL_RECORD means "stop trying to inherit trust" so if the
     // relevant trust bit isn't set then that means the cert must be considered
     // distrusted.
-    PRUint32 relevantTrustBit = endEntityOrCA == MustBeCA
+    PRUint32 relevantTrustBit = endEntityOrCA == EndEntityOrCA::MustBeCA
                               ? CERTDB_TRUSTED_CA
                               : CERTDB_TRUSTED;
     if (((flags & (relevantTrustBit | CERTDB_TERMINAL_RECORD)))
             == CERTDB_TERMINAL_RECORD) {
-      *trustLevel = ActivelyDistrusted;
+      *trustLevel = TrustLevel::ActivelyDistrusted;
       return SECSuccess;
     }
 
 #ifdef MOZ_B2G_CERTDATA
     // XXX(Bug 972201): We have to allow the old way of supporting additional
     // roots until we fix bug 889744. Remove this along with the rest of the
     // MOZ_B2G_CERTDATA stuff.
 
     // For TRUST, we only use the CERTDB_TRUSTED_CA bit, because Gecko hasn't
     // needed to consider end-entity certs to be their own trust anchors since
     // Gecko implemented nsICertOverrideService.
     if (flags & CERTDB_TRUSTED_CA) {
-      *trustLevel = TrustAnchor;
+      *trustLevel = TrustLevel::TrustAnchor;
       return SECSuccess;
     }
 #endif
   }
 
   // mTrustedRoot is the only trust anchor for this validation.
   if (CERT_CompareCerts(mTrustedRoot.get(), candidateCert)) {
-    *trustLevel = TrustAnchor;
+    *trustLevel = TrustLevel::TrustAnchor;
     return SECSuccess;
   }
 
-  *trustLevel = InheritsTrust;
+  *trustLevel = TrustLevel::InheritsTrust;
   return SECSuccess;
 }
 
 SECStatus
 AppTrustDomain::VerifySignedData(const CERTSignedData* signedData,
                                   const CERTCertificate* cert)
 {
   return ::mozilla::pkix::VerifySignedData(signedData, cert, mPinArg);
--- a/security/apps/AppTrustDomain.h
+++ b/security/apps/AppTrustDomain.h
@@ -18,17 +18,17 @@ class AppTrustDomain MOZ_FINAL : public 
 public:
   AppTrustDomain(void* pinArg);
 
   SECStatus SetTrustedRoot(AppTrustedRoot trustedRoot);
 
   SECStatus GetCertTrust(mozilla::pkix::EndEntityOrCA endEntityOrCA,
                          SECOidTag policy,
                          const CERTCertificate* candidateCert,
-                 /*out*/ TrustLevel* trustLevel) MOZ_OVERRIDE;
+                 /*out*/ mozilla::pkix::TrustLevel* trustLevel) MOZ_OVERRIDE;
   SECStatus FindPotentialIssuers(const SECItem* encodedIssuerName,
                                  PRTime time,
                          /*out*/ mozilla::pkix::ScopedCERTCertList& results)
                                  MOZ_OVERRIDE;
   SECStatus VerifySignedData(const CERTSignedData* signedData,
                              const CERTCertificate* cert) MOZ_OVERRIDE;
   SECStatus CheckRevocation(mozilla::pkix::EndEntityOrCA endEntityOrCA,
                             const CERTCertificate* cert,
--- a/security/certverifier/CertVerifier.cpp
+++ b/security/certverifier/CertVerifier.cpp
@@ -303,29 +303,32 @@ BuildCertChainForOneKeyUsage(TrustDomain
                              KeyUsages ku3, SECOidTag eku,
                              SECOidTag requiredPolicy,
                              const SECItem* stapledOCSPResponse,
                              ScopedCERTCertList& builtChain)
 {
   PR_ASSERT(ku1);
   PR_ASSERT(ku2);
 
-  SECStatus rv = BuildCertChain(trustDomain, cert, time, MustBeEndEntity,
-                                ku1, eku, requiredPolicy, stapledOCSPResponse,
-                                builtChain);
+  SECStatus rv = BuildCertChain(trustDomain, cert, time,
+                                EndEntityOrCA::MustBeEndEntity, ku1,
+                                eku, requiredPolicy,
+                                stapledOCSPResponse, builtChain);
   if (rv != SECSuccess && ku2 &&
       PR_GetError() == SEC_ERROR_INADEQUATE_KEY_USAGE) {
-    rv = BuildCertChain(trustDomain, cert, time, MustBeEndEntity,
-                        ku2, eku, requiredPolicy, stapledOCSPResponse,
-                        builtChain);
+    rv = BuildCertChain(trustDomain, cert, time,
+                        EndEntityOrCA::MustBeEndEntity, ku2,
+                        eku, requiredPolicy,
+                        stapledOCSPResponse, builtChain);
     if (rv != SECSuccess && ku3 &&
         PR_GetError() == SEC_ERROR_INADEQUATE_KEY_USAGE) {
-      rv = BuildCertChain(trustDomain, cert, time, MustBeEndEntity,
-                          ku3, eku, requiredPolicy, stapledOCSPResponse,
-                          builtChain);
+      rv = BuildCertChain(trustDomain, cert, time,
+                          EndEntityOrCA::MustBeEndEntity, ku3,
+                          eku, requiredPolicy,
+                          stapledOCSPResponse, builtChain);
       if (rv != SECSuccess) {
         PR_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE, 0);
       }
     }
   }
   return rv;
 }
 
@@ -381,18 +384,18 @@ CertVerifier::MozillaPKIXVerifyCert(
 
   mozilla::pkix::ScopedCERTCertList builtChain;
   switch (usage) {
     case certificateUsageSSLClient: {
       // XXX: We don't really have a trust bit for SSL client authentication so
       // just use trustEmail as it is the closest alternative.
       NSSCertDBTrustDomain trustDomain(trustEmail, ocspFetching, mOCSPCache,
                                        pinArg);
-      rv = BuildCertChain(trustDomain, cert, time, MustBeEndEntity,
-                          KU_DIGITAL_SIGNATURE,
+      rv = BuildCertChain(trustDomain, cert, time,
+                          EndEntityOrCA::MustBeEndEntity, KU_DIGITAL_SIGNATURE,
                           SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH,
                           SEC_OID_X509_ANY_POLICY,
                           stapledOCSPResponse, builtChain);
       break;
     }
 
     case certificateUsageSSLServer: {
       // TODO: When verifying a certificate in an SSL handshake, we should
@@ -444,29 +447,29 @@ CertVerifier::MozillaPKIXVerifyCert(
                                         SEC_OID_X509_ANY_POLICY,
                                         stapledOCSPResponse, builtChain);
       break;
     }
 
     case certificateUsageSSLCA: {
       NSSCertDBTrustDomain trustDomain(trustSSL, ocspFetching, mOCSPCache,
                                        pinArg);
-      rv = BuildCertChain(trustDomain, cert, time, MustBeCA,
+      rv = BuildCertChain(trustDomain, cert, time, EndEntityOrCA::MustBeCA,
                           KU_KEY_CERT_SIGN,
                           SEC_OID_EXT_KEY_USAGE_SERVER_AUTH,
                           SEC_OID_X509_ANY_POLICY,
                           stapledOCSPResponse, builtChain);
       break;
     }
 
     case certificateUsageEmailSigner: {
       NSSCertDBTrustDomain trustDomain(trustEmail, ocspFetching, mOCSPCache,
                                        pinArg);
-      rv = BuildCertChain(trustDomain, cert, time, MustBeEndEntity,
-                          KU_DIGITAL_SIGNATURE,
+      rv = BuildCertChain(trustDomain, cert, time,
+                          EndEntityOrCA::MustBeEndEntity, KU_DIGITAL_SIGNATURE,
                           SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT,
                           SEC_OID_X509_ANY_POLICY,
                           stapledOCSPResponse, builtChain);
       break;
     }
 
     case certificateUsageEmailRecipient: {
       // TODO: The higher level S/MIME processing should pass in which key
@@ -482,39 +485,39 @@ CertVerifier::MozillaPKIXVerifyCert(
                                         SEC_OID_X509_ANY_POLICY,
                                         stapledOCSPResponse, builtChain);
       break;
     }
 
     case certificateUsageObjectSigner: {
       NSSCertDBTrustDomain trustDomain(trustObjectSigning, ocspFetching,
                                        mOCSPCache, pinArg);
-      rv = BuildCertChain(trustDomain, cert, time, MustBeEndEntity,
-                          KU_DIGITAL_SIGNATURE,
+      rv = BuildCertChain(trustDomain, cert, time,
+                          EndEntityOrCA::MustBeEndEntity, KU_DIGITAL_SIGNATURE,
                           SEC_OID_EXT_KEY_USAGE_CODE_SIGN,
                           SEC_OID_X509_ANY_POLICY,
                           stapledOCSPResponse, builtChain);
       break;
     }
 
     case certificateUsageVerifyCA:
     case certificateUsageStatusResponder: {
       // XXX This is a pretty useless way to verify a certificate. It is used
       // by the implementation of window.crypto.importCertificates and in the
       // certificate viewer UI. Because we don't know what trust bit is
       // interesting, we just try them all.
       mozilla::pkix::EndEntityOrCA endEntityOrCA;
       mozilla::pkix::KeyUsages keyUsage;
       SECOidTag eku;
       if (usage == certificateUsageVerifyCA) {
-        endEntityOrCA = MustBeCA;
+        endEntityOrCA = EndEntityOrCA::MustBeCA;
         keyUsage = KU_KEY_CERT_SIGN;
         eku = SEC_OID_UNKNOWN;
       } else {
-        endEntityOrCA = MustBeEndEntity;
+        endEntityOrCA = EndEntityOrCA::MustBeEndEntity;
         keyUsage = KU_DIGITAL_SIGNATURE;
         eku = SEC_OID_OCSP_RESPONDER;
       }
 
       NSSCertDBTrustDomain sslTrust(trustSSL, ocspFetching, mOCSPCache,
                                     pinArg);
       rv = BuildCertChain(sslTrust, cert, time, endEntityOrCA,
                           keyUsage, eku, SEC_OID_X509_ANY_POLICY,
--- a/security/certverifier/NSSCertDBTrustDomain.cpp
+++ b/security/certverifier/NSSCertDBTrustDomain.cpp
@@ -95,42 +95,43 @@ NSSCertDBTrustDomain::GetCertTrust(EndEn
   if (CERT_GetCertTrust(candidateCert, &trust) == SECSuccess) {
     PRUint32 flags = SEC_GET_TRUST_FLAGS(&trust, mCertDBTrustType);
 
     // For DISTRUST, we use the CERTDB_TRUSTED or CERTDB_TRUSTED_CA bit,
     // because we can have active distrust for either type of cert. Note that
     // CERTDB_TERMINAL_RECORD means "stop trying to inherit trust" so if the
     // relevant trust bit isn't set then that means the cert must be considered
     // distrusted.
-    PRUint32 relevantTrustBit = endEntityOrCA == MustBeCA ? CERTDB_TRUSTED_CA
-                                                          : CERTDB_TRUSTED;
+    PRUint32 relevantTrustBit =
+      endEntityOrCA == EndEntityOrCA::MustBeCA ? CERTDB_TRUSTED_CA
+                                               : CERTDB_TRUSTED;
     if (((flags & (relevantTrustBit|CERTDB_TERMINAL_RECORD)))
             == CERTDB_TERMINAL_RECORD) {
-      *trustLevel = ActivelyDistrusted;
+      *trustLevel = TrustLevel::ActivelyDistrusted;
       return SECSuccess;
     }
 
     // For TRUST, we only use the CERTDB_TRUSTED_CA bit, because Gecko hasn't
     // needed to consider end-entity certs to be their own trust anchors since
     // Gecko implemented nsICertOverrideService.
     if (flags & CERTDB_TRUSTED_CA) {
       if (policy == SEC_OID_X509_ANY_POLICY) {
-        *trustLevel = TrustAnchor;
+        *trustLevel = TrustLevel::TrustAnchor;
         return SECSuccess;
       }
 #ifndef MOZ_NO_EV_CERTS
       if (CertIsAuthoritativeForEVPolicy(candidateCert, policy)) {
-        *trustLevel = TrustAnchor;
+        *trustLevel = TrustLevel::TrustAnchor;
         return SECSuccess;
       }
 #endif
     }
   }
 
-  *trustLevel = InheritsTrust;
+  *trustLevel = TrustLevel::InheritsTrust;
   return SECSuccess;
 }
 
 SECStatus
 NSSCertDBTrustDomain::VerifySignedData(const CERTSignedData* signedData,
                                        const CERTCertificate* cert)
 {
   return ::mozilla::pkix::VerifySignedData(signedData, cert, mPinArg);
@@ -160,17 +161,17 @@ NSSCertDBTrustDomain::CheckRevocation(
     return SECFailure;
   }
 
   // If we have a stapled OCSP response then the verification of that response
   // determines the result unless the OCSP response is expired. We make an
   // exception for expired responses because some servers, nginx in particular,
   // are known to serve expired responses due to bugs.
   if (stapledOCSPResponse) {
-    PR_ASSERT(endEntityOrCA == MustBeEndEntity);
+    PR_ASSERT(endEntityOrCA == EndEntityOrCA::MustBeEndEntity);
     SECStatus rv = VerifyAndMaybeCacheEncodedOCSPResponse(cert, issuerCert,
                                                           time,
                                                           stapledOCSPResponse,
                                                           ResponseWasStapled);
     if (rv == SECSuccess) {
       // stapled OCSP response present and good
       Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, 1);
       PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
@@ -245,18 +246,19 @@ NSSCertDBTrustDomain::CheckRevocation(
             (cachedResponsePresent && cachedResponseErrorCode != 0));
 
   // TODO: We still need to handle the fallback for expired responses. But,
   // if/when we disable OCSP fetching by default, it would be ambiguous whether
   // security.OCSP.enable==0 means "I want the default" or "I really never want
   // you to ever fetch OCSP."
 
   if ((mOCSPFetching == NeverFetchOCSP) ||
-      (endEntityOrCA == MustBeCA && (mOCSPFetching == FetchOCSPForDVHardFail ||
-                                     mOCSPFetching == FetchOCSPForDVSoftFail))) {
+      (endEntityOrCA == EndEntityOrCA::MustBeCA &&
+       (mOCSPFetching == FetchOCSPForDVHardFail ||
+        mOCSPFetching == FetchOCSPForDVSoftFail))) {
     // We're not going to be doing any fetching, so if there was a cached
     // "unknown" response, say so.
     if (cachedResponseErrorCode == SEC_ERROR_OCSP_UNKNOWN_CERT) {
       PR_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT, 0);
       return SECFailure;
     }
     // If we're doing hard-fail, we want to know if we have a cached response
     // that has expired.
--- a/security/certverifier/NSSCertDBTrustDomain.h
+++ b/security/certverifier/NSSCertDBTrustDomain.h
@@ -63,17 +63,17 @@ public:
   virtual SECStatus FindPotentialIssuers(
                         const SECItem* encodedIssuerName,
                         PRTime time,
                 /*out*/ mozilla::pkix::ScopedCERTCertList& results);
 
   virtual SECStatus GetCertTrust(mozilla::pkix::EndEntityOrCA endEntityOrCA,
                                  SECOidTag policy,
                                  const CERTCertificate* candidateCert,
-                         /*out*/ TrustLevel* trustLevel);
+                         /*out*/ mozilla::pkix::TrustLevel* trustLevel);
 
   virtual SECStatus VerifySignedData(const CERTSignedData* signedData,
                                      const CERTCertificate* cert);
 
   virtual SECStatus CheckRevocation(mozilla::pkix::EndEntityOrCA endEntityOrCA,
                                     const CERTCertificate* cert,
                           /*const*/ CERTCertificate* issuerCert,
                                     PRTime time,
new file mode 100644
--- /dev/null
+++ b/security/pkix/include/pkix/enumclass.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* Copyright 2013 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Work around missing std::bind, std::ref, std::cref in older compilers. This
+// implementation isn't intended to be complete; rather, it is the minimal
+// implementation needed to make our use of std::bind work.
+
+#ifndef mozilla_pkix__enumclass_h
+#define mozilla_pkix__enumclass_h
+
+#if defined(_MSC_VER) && (_MSC_VER < 1700)
+// Microsoft added support for "enum class" in Visual C++ 2012. Before that,
+// Visual C++ has supported typed enums for longer than that, but using typed
+// enums results in C4480: nonstandard extension used: specifying underlying
+// type for enum.
+#define MOZILLA_PKIX_ENUM_CLASS  __pragma(warning(disable: 4480)) enum
+#else
+#define MOZILLA_PKIX_ENUM_CLASS enum class
+#endif
+
+#endif // mozilla_pkix__enumclass_h
--- a/security/pkix/include/pkix/pkixtypes.h
+++ b/security/pkix/include/pkix/pkixtypes.h
@@ -13,16 +13,17 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef mozilla_pkix__pkixtypes_h
 #define mozilla_pkix__pkixtypes_h
 
+#include "pkix/enumclass.h"
 #include "pkix/ScopedPtr.h"
 #include "plarena.h"
 #include "cert.h"
 #include "keyhi.h"
 
 namespace mozilla { namespace pkix {
 
 typedef ScopedPtr<PLArenaPool, PL_FreeArenaPool> ScopedPLArenaPool;
@@ -30,34 +31,34 @@ typedef ScopedPtr<PLArenaPool, PL_FreeAr
 typedef ScopedPtr<CERTCertificate, CERT_DestroyCertificate>
         ScopedCERTCertificate;
 typedef ScopedPtr<CERTCertList, CERT_DestroyCertList> ScopedCERTCertList;
 typedef ScopedPtr<SECKEYPublicKey, SECKEY_DestroyPublicKey>
         ScopedSECKEYPublicKey;
 
 typedef unsigned int KeyUsages;
 
-enum EndEntityOrCA { MustBeEndEntity, MustBeCA };
+MOZILLA_PKIX_ENUM_CLASS EndEntityOrCA { MustBeEndEntity = 0, MustBeCA = 1 };
+
+MOZILLA_PKIX_ENUM_CLASS TrustLevel {
+  TrustAnchor = 1,        // certificate is a trusted root CA certificate or
+                          // equivalent *for the given policy*.
+  ActivelyDistrusted = 2, // certificate is known to be bad
+  InheritsTrust = 3       // certificate must chain to a trust anchor
+};
 
 // Applications control the behavior of path building and verification by
 // implementing the TrustDomain interface. The TrustDomain is used for all
 // cryptography and for determining which certificates are trusted or
 // distrusted.
 class TrustDomain
 {
 public:
   virtual ~TrustDomain() { }
 
-  enum TrustLevel {
-    TrustAnchor = 1,        // certificate is a trusted root CA certificate or
-                            // equivalent *for the given policy*.
-    ActivelyDistrusted = 2, // certificate is known to be bad
-    InheritsTrust = 3       // certificate must chain to a trust anchor
-  };
-
   // Determine the level of trust in the given certificate for the given role.
   // This will be called for every certificate encountered during path
   // building.
   //
   // When policy == SEC_OID_X509_ANY_POLICY, then no policy-related checking
   // should be done. When policy != SEC_OID_X509_ANY_POLICY, then GetCertTrust
   // MUST NOT return with *trustLevel == TrustAnchor unless the given cert is
   // considered a trust anchor *for that policy*. In particular, if the user
--- a/security/pkix/lib/pkixbuild.cpp
+++ b/security/pkix/lib/pkixbuild.cpp
@@ -123,17 +123,17 @@ BuildForwardInner(TrustDomain& trustDoma
                   SECOidTag requiredPolicy,
                   CERTCertificate* potentialIssuerCertToDup,
                   unsigned int subCACount,
                   ScopedCERTCertList& results)
 {
   PORT_Assert(potentialIssuerCertToDup);
 
   BackCert potentialIssuer(potentialIssuerCertToDup, &subject,
-                           BackCert::ExcludeCN);
+                           BackCert::IncludeCN::No);
   Result rv = potentialIssuer.Init();
   if (rv != Success) {
     return rv;
   }
 
   // RFC5280 4.2.1.1. Authority Key Identifier
   // RFC5280 4.2.1.2. Subject Key Identifier
 
@@ -152,22 +152,22 @@ BuildForwardInner(TrustDomain& trustDoma
   }
 
   rv = CheckNameConstraints(potentialIssuer);
   if (rv != Success) {
     return rv;
   }
 
   unsigned int newSubCACount = subCACount;
-  if (endEntityOrCA == MustBeCA) {
+  if (endEntityOrCA == EndEntityOrCA::MustBeCA) {
     newSubCACount = subCACount + 1;
   } else {
     PR_ASSERT(newSubCACount == 0);
   }
-  rv = BuildForward(trustDomain, potentialIssuer, time, MustBeCA,
+  rv = BuildForward(trustDomain, potentialIssuer, time, EndEntityOrCA::MustBeCA,
                     KU_KEY_CERT_SIGN, requiredEKUIfPresent, requiredPolicy,
                     nullptr, newSubCACount, results);
   if (rv != Success) {
     return rv;
   }
 
   if (trustDomain.VerifySignedData(&subject.GetNSSCert()->signatureWrap,
                                    potentialIssuer.GetNSSCert()) != SECSuccess) {
@@ -199,36 +199,36 @@ BuildForward(TrustDomain& trustDomain,
   // XXX: 6 is not enough for chains.sh anypolicywithlevel.cfg tests
   static const size_t MAX_DEPTH = 8;
   if (subCACount >= MAX_DEPTH - 1) {
     return RecoverableError;
   }
 
   Result rv;
 
-  TrustDomain::TrustLevel trustLevel;
+  TrustLevel trustLevel;
   // If this is an end-entity and not a trust anchor, we defer reporting
   // any error found here until after attempting to find a valid chain.
   // See the explanation of error prioritization in pkix.h.
   rv = CheckIssuerIndependentProperties(trustDomain, subject, time,
                                         endEntityOrCA,
                                         requiredKeyUsagesIfPresent,
                                         requiredEKUIfPresent, requiredPolicy,
                                         subCACount, &trustLevel);
   PRErrorCode deferredEndEntityError = 0;
   if (rv != Success) {
-    if (endEntityOrCA == MustBeEndEntity &&
-        trustLevel != TrustDomain::TrustAnchor) {
+    if (endEntityOrCA == EndEntityOrCA::MustBeEndEntity &&
+        trustLevel != TrustLevel::TrustAnchor) {
       deferredEndEntityError = PR_GetError();
     } else {
       return rv;
     }
   }
 
-  if (trustLevel == TrustDomain::TrustAnchor) {
+  if (trustLevel == TrustLevel::TrustAnchor) {
     ScopedCERTCertList certChain(CERT_NewCertList());
     if (!certChain) {
       PR_SetError(SEC_ERROR_NO_MEMORY, 0);
       return MapSECStatus(SECFailure);
     }
 
     rv = subject.PrependNSSCertToList(certChain.get());
     if (rv != Success) {
@@ -341,23 +341,23 @@ BuildCertChain(TrustDomain& trustDomain,
     return SECFailure;
   }
 
   // The only non-const operation on the cert we are allowed to do is
   // CERT_DupCertificate.
 
   // XXX: Support the legacy use of the subject CN field for indicating the
   // domain name the certificate is valid for.
-  BackCert::ConstrainedNameOptions cnOptions
-    = endEntityOrCA == MustBeEndEntity &&
+  BackCert::IncludeCN includeCN
+    = endEntityOrCA == EndEntityOrCA::MustBeEndEntity &&
       requiredEKUIfPresent == SEC_OID_EXT_KEY_USAGE_SERVER_AUTH
-    ? BackCert::IncludeCN
-    : BackCert::ExcludeCN;
+    ? BackCert::IncludeCN::Yes
+    : BackCert::IncludeCN::No;
 
-  BackCert cert(certToDup, nullptr, cnOptions);
+  BackCert cert(certToDup, nullptr, includeCN);
   Result rv = cert.Init();
   if (rv != Success) {
     return SECFailure;
   }
 
   rv = BuildForward(trustDomain, cert, time, endEntityOrCA,
                     requiredKeyUsagesIfPresent, requiredEKUIfPresent,
                     requiredPolicy, stapledOCSPResponse, 0, results);
--- a/security/pkix/lib/pkixcheck.cpp
+++ b/security/pkix/lib/pkixcheck.cpp
@@ -46,17 +46,17 @@ CheckKeyUsage(EndEntityOrCA endEntityOrC
               KeyUsages requiredKeyUsagesIfPresent,
               PLArenaPool* arena)
 {
   if (!encodedKeyUsage) {
     // TODO(bug 970196): Reject certificates that are being used to verify
     // certificate signatures unless the certificate is a trust anchor, to
     // reduce the chances of an end-entity certificate being abused as a CA
     // certificate.
-    // if (endEntityOrCA == MustBeCA && !isTrustAnchor) {
+    // if (endEntityOrCA == EndEntityOrCA::MustBeCA && !isTrustAnchor) {
     //   return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
     // }
     //
     // TODO: Users may configure arbitrary certificates as trust anchors, not
     // just roots. We should only allow a certificate without a key usage to be
     // used as a CA when it is self-issued and self-signed.
     return Success;
   }
@@ -72,17 +72,17 @@ CheckKeyUsage(EndEntityOrCA endEntityOrC
   // TODO XXX: Why is tmpItem.len > 1?
 
   KeyUsages allowedKeyUsages = tmpItem.data[0];
   if ((allowedKeyUsages & requiredKeyUsagesIfPresent)
         != requiredKeyUsagesIfPresent) {
     return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
   }
 
-  if (endEntityOrCA == MustBeCA) {
+  if (endEntityOrCA == EndEntityOrCA::MustBeCA) {
    // "If the keyUsage extension is present, then the subject public key
    //  MUST NOT be used to verify signatures on certificates or CRLs unless
    //  the corresponding keyCertSign or cRLSign bit is set."
    if ((allowedKeyUsages & KU_KEY_CERT_SIGN) == 0) {
       return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
     }
   } else {
     // "The keyCertSign bit is asserted when the subject public key is
@@ -124,17 +124,17 @@ CheckCertificatePolicies(BackCert& cert,
   if (cert.encodedInhibitAnyPolicy) {
     return Fail(RecoverableError, SEC_ERROR_POLICY_VALIDATION_FAILED);
   }
 
   // The root CA certificate may omit the policies that it has been
   // trusted for, so we cannot require the policies to be present in those
   // certificates. Instead, the determination of which roots are trusted for
   // which policies is made by the TrustDomain's GetCertTrust method.
-  if (isTrustAnchor && endEntityOrCA == MustBeCA) {
+  if (isTrustAnchor && endEntityOrCA == EndEntityOrCA::MustBeCA) {
     return Success;
   }
 
   if (!cert.encodedCertificatePolicies) {
     return Fail(RecoverableError, SEC_ERROR_POLICY_VALIDATION_FAILED);
   }
 
   ScopedPtr<CERTCertificatePolicies, CERT_DestroyCertificatePoliciesExtension>
@@ -145,17 +145,17 @@ CheckCertificatePolicies(BackCert& cert,
   }
 
   for (const CERTPolicyInfo* const* policyInfos = policies->policyInfos;
        *policyInfos; ++policyInfos) {
     if ((*policyInfos)->oid == requiredPolicy) {
       return Success;
     }
     // Intermediate certs are allowed to have the anyPolicy OID
-    if (endEntityOrCA == MustBeCA &&
+    if (endEntityOrCA == EndEntityOrCA::MustBeCA &&
         (*policyInfos)->oid == SEC_OID_X509_ANY_POLICY) {
       return Success;
     }
   }
 
   return Fail(RecoverableError, SEC_ERROR_POLICY_VALIDATION_FAILED);
 }
 
@@ -243,29 +243,29 @@ CheckBasicConstraints(const BackCert& ce
     //  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.
     //
     // TODO: add check for self-signedness?
-    if (endEntityOrCA == MustBeCA && isTrustAnchor) {
+    if (endEntityOrCA == EndEntityOrCA::MustBeCA && isTrustAnchor) {
       const CERTCertificate* nssCert = cert.GetNSSCert();
       // We only allow trust anchor CA certs to omit the
       // basicConstraints extension if they are v1. v1 is encoded
       // implicitly.
       if (!nssCert->version.data && !nssCert->version.len) {
         basicConstraints.isCA = true;
         basicConstraints.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
       }
     }
   }
 
-  if (endEntityOrCA == MustBeEndEntity) {
+  if (endEntityOrCA == EndEntityOrCA::MustBeEndEntity) {
     // CA certificates are not trusted as EE certs.
 
     if (basicConstraints.isCA) {
       // XXX: We use SEC_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
       // SEC_ERROR_CA_CERT_INVALID this way.
@@ -275,17 +275,17 @@ CheckBasicConstraints(const BackCert& ce
       // validating when we check it from pkixocsp.cpp, which is a good thing.
       //
       return Fail(RecoverableError, SEC_ERROR_CA_CERT_INVALID);
     }
 
     return Success;
   }
 
-  PORT_Assert(endEntityOrCA == MustBeCA);
+  PORT_Assert(endEntityOrCA == EndEntityOrCA::MustBeCA);
 
   // End-entity certificates are not allowed to act as CA certs.
   if (!basicConstraints.isCA) {
     return Fail(RecoverableError, SEC_ERROR_CA_CERT_INVALID);
   }
 
   if (basicConstraints.pathLenConstraint >= 0) {
     if (subCACount >
@@ -302,17 +302,17 @@ BackCert::GetConstrainedNames(/*out*/ co
 {
   if (!constrainedNames) {
     if (!GetArena()) {
       return FatalError;
     }
 
     constrainedNames =
       CERT_GetConstrainedCertificateNames(nssCert, arena.get(),
-                                          cnOptions == IncludeCN);
+                                          includeCN == IncludeCN::Yes);
     if (!constrainedNames) {
       return MapSECStatus(SECFailure);
     }
   }
 
   *result = constrainedNames;
   return Success;
 }
@@ -392,17 +392,17 @@ CheckExtendedKeyUsage(EndEntityOrCA endE
       SECOidTag oidTag = SECOID_FindOIDTag(*oids);
       if (requiredEKU != SEC_OID_UNKNOWN && oidTag == requiredEKU) {
         found = true;
       } else {
         // Treat CA certs with step-up OID as also having SSL server type.
         // COMODO has issued certificates that require this behavior
         // that don't expire until June 2020!
         // TODO 982932: Limit this expection to old certificates
-        if (endEntityOrCA == MustBeCA &&
+        if (endEntityOrCA == EndEntityOrCA::MustBeCA &&
             requiredEKU == SEC_OID_EXT_KEY_USAGE_SERVER_AUTH &&
             oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) {
           found = true;
         }
       }
       if (oidTag == SEC_OID_OCSP_RESPONDER) {
         foundOCSPSigning = true;
       }
@@ -412,17 +412,17 @@ CheckExtendedKeyUsage(EndEntityOrCA endE
     // list.
     if (!found) {
       return Fail(RecoverableError, SEC_ERROR_INADEQUATE_CERT_TYPE);
     }
   }
 
   // pkixocsp.cpp depends on the following additional checks.
 
-  if (endEntityOrCA == MustBeEndEntity) {
+  if (endEntityOrCA == EndEntityOrCA::MustBeEndEntity) {
     // When validating anything other than an delegated OCSP signing cert,
     // reject any cert that also claims to be an OCSP responder, because such
     // a cert does not make sense. For example, if an SSL certificate were to
     // assert id-kp-OCSPSigning then it could sign OCSP responses for itself,
     // if not for this check.
     // That said, we accept CA certificates with id-kp-OCSPSigning because
     // some CAs in Mozilla's CA program have issued such intermediate
     // certificates, and because some CAs have reported some Microsoft server
@@ -456,43 +456,43 @@ Result
 CheckIssuerIndependentProperties(TrustDomain& trustDomain,
                                  BackCert& cert,
                                  PRTime time,
                                  EndEntityOrCA endEntityOrCA,
                                  KeyUsages requiredKeyUsagesIfPresent,
                                  SECOidTag requiredEKUIfPresent,
                                  SECOidTag requiredPolicy,
                                  unsigned int subCACount,
-                /*optional out*/ TrustDomain::TrustLevel* trustLevelOut)
+                /*optional out*/ TrustLevel* trustLevelOut)
 {
   Result rv;
 
-  TrustDomain::TrustLevel trustLevel;
+  TrustLevel trustLevel;
   rv = MapSECStatus(trustDomain.GetCertTrust(endEntityOrCA,
                                              requiredPolicy,
                                              cert.GetNSSCert(),
                                              &trustLevel));
   if (rv != Success) {
     return rv;
   }
-  if (trustLevel == TrustDomain::ActivelyDistrusted) {
+  if (trustLevel == TrustLevel::ActivelyDistrusted) {
     return Fail(RecoverableError, SEC_ERROR_UNTRUSTED_CERT);
   }
-  if (trustLevel != TrustDomain::TrustAnchor &&
-      trustLevel != TrustDomain::InheritsTrust) {
+  if (trustLevel != TrustLevel::TrustAnchor &&
+      trustLevel != TrustLevel::InheritsTrust) {
     // The TrustDomain returned a trust level that we weren't expecting.
     PORT_SetError(PR_INVALID_STATE_ERROR);
     return FatalError;
   }
   if (trustLevelOut) {
     *trustLevelOut = trustLevel;
   }
 
-  bool isTrustAnchor = endEntityOrCA == MustBeCA &&
-                       trustLevel == TrustDomain::TrustAnchor;
+  bool isTrustAnchor = endEntityOrCA == EndEntityOrCA::MustBeCA &&
+                       trustLevel == TrustLevel::TrustAnchor;
 
   PLArenaPool* arena = cert.GetArena();
   if (!arena) {
     return FatalError;
   }
 
   // 4.2.1.1. Authority Key Identifier is ignored (see bug 965136).
 
--- a/security/pkix/lib/pkixcheck.h
+++ b/security/pkix/lib/pkixcheck.h
@@ -27,15 +27,15 @@ Result CheckIssuerIndependentProperties(
           TrustDomain& trustDomain,
           BackCert& cert,
           PRTime time,
           EndEntityOrCA endEntityOrCA,
           KeyUsages requiredKeyUsagesIfPresent,
           SECOidTag requiredEKUIfPresent,
           SECOidTag requiredPolicy,
           unsigned int subCACount,
-          /*optional out*/ TrustDomain::TrustLevel* trustLevel = nullptr);
+          /*optional out*/ TrustLevel* trustLevel = nullptr);
 
 Result CheckNameConstraints(BackCert& cert);
 
 } } // namespace mozilla::pkix
 
 #endif // mozilla_pkix__pkixcheck_h
--- a/security/pkix/lib/pkixder.h
+++ b/security/pkix/lib/pkixder.h
@@ -13,16 +13,17 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef mozilla_pkix__pkixder_h
 #define mozilla_pkix__pkixder_h
 
+#include "pkix/enumclass.h"
 #include "pkix/nullptr.h"
 
 #include "prerror.h"
 #include "prlog.h"
 #include "secder.h"
 #include "secerr.h"
 #include "secoidt.h"
 #include "stdint.h"
@@ -56,17 +57,17 @@ enum Tag
 };
 
 enum Result
 {
   Failure = -1,
   Success = 0
 };
 
-enum EmptyAllowed { MayBeEmpty = 0, MustNotBeEmpty = 1 };
+MOZILLA_PKIX_ENUM_CLASS EmptyAllowed { No = 0, Yes = 1 };
 
 Result Fail(PRErrorCode errorCode);
 
 class Input
 {
 public:
   Input()
     : input(nullptr)
@@ -319,17 +320,17 @@ NestedOf(Input& input, uint8_t outerTag,
   }
 
   Input inner;
   if (input.Skip(responsesLength, inner) != Success) {
     return Failure;
   }
 
   if (inner.AtEnd()) {
-    if (mayBeEmpty != MayBeEmpty) {
+    if (mayBeEmpty != EmptyAllowed::Yes) {
       return Fail(SEC_ERROR_BAD_DER);
     }
     return Success;
   }
 
   do {
     if (Nested(inner, innerTag, decoder) != Success) {
       return Failure;
--- a/security/pkix/lib/pkixocsp.cpp
+++ b/security/pkix/lib/pkixocsp.cpp
@@ -21,34 +21,27 @@
 #include "pkix/pkix.h"
 #include "pkixcheck.h"
 #include "pkixder.h"
 
 #include "hasht.h"
 #include "pk11pub.h"
 #include "secder.h"
 
-#ifdef _MSC_VER
-// C4480: nonstandard extension used: specifying underlying type for enum
-#define ENUM_CLASS  __pragma(warning(disable: 4480)) enum
-#else
-#define ENUM_CLASS enum class
-#endif
-
 // TODO: use typed/qualified typedefs everywhere?
 // TODO: When should we return SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE?
 
 namespace mozilla { namespace pkix {
 
 static const PRTime ONE_DAY
   = INT64_C(24) * INT64_C(60) * INT64_C(60) * PR_USEC_PER_SEC;
 static const PRTime SLOP = ONE_DAY;
 
 // These values correspond to the tag values in the ASN.1 CertStatus
-ENUM_CLASS CertStatus : uint8_t {
+MOZILLA_PKIX_ENUM_CLASS CertStatus : uint8_t {
   Good = der::CONTEXT_SPECIFIC | 0,
   Revoked = der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
   Unknown = der::CONTEXT_SPECIFIC | 2
 };
 
 class Context
 {
 public:
@@ -91,17 +84,17 @@ private:
 // according to RFC 6960 section 4.2.2.2.
 static Result
 CheckOCSPResponseSignerCert(TrustDomain& trustDomain,
                             CERTCertificate& potentialSigner,
                             const CERTCertificate& issuerCert, PRTime time)
 {
   Result rv;
 
-  BackCert cert(&potentialSigner, nullptr, BackCert::ExcludeCN);
+  BackCert cert(&potentialSigner, nullptr, BackCert::IncludeCN::No);
   rv = cert.Init();
   if (rv != Success) {
     return rv;
   }
 
   // We don't need to do a complete verification of the signer (i.e. we don't
   // have to call BuildCertChain to verify the entire chain) because we
   // already know that the issuerCert is valid, since revocation checking is
@@ -121,17 +114,17 @@ CheckOCSPResponseSignerCert(TrustDomain&
   // Note that CheckIssuerIndependentProperties processes
   // SEC_OID_OCSP_RESPONDER in the way that the OCSP specification requires us
   // to--in particular, it doesn't allow SEC_OID_OCSP_RESPONDER to be implied
   // by a missing EKU extension, unlike other EKUs.
   //
   // TODO(bug 926261): If we're validating for a policy then the policy OID we
   // are validating for should be passed to CheckIssuerIndependentProperties.
   rv = CheckIssuerIndependentProperties(trustDomain, cert, time,
-                                        MustBeEndEntity, 0,
+                                        EndEntityOrCA::MustBeEndEntity, 0,
                                         SEC_OID_OCSP_RESPONDER,
                                         SEC_OID_X509_ANY_POLICY, 0);
   if (rv != Success) {
     return rv;
   }
 
   // It is possible that there exists a certificate with the same key as the
   // issuer but with a different name, so we need to compare names
@@ -152,22 +145,17 @@ CheckOCSPResponseSignerCert(TrustDomain&
 
   // TODO: check for revocation of the OCSP responder certificate unless no-check
   // or the caller forcing no-check. To properly support the no-check policy, we'd
   // need to enforce policy constraints from the issuerChain.
 
   return Success;
 }
 
-//typedef enum {
-//    ocspResponderID_byName = 1,
-//    ocspResponderID_byKey = 2
-//} ResponderIDType;
-
-ENUM_CLASS ResponderIDType : uint8_t
+MOZILLA_PKIX_ENUM_CLASS ResponderIDType : uint8_t
 {
   byName = der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
   byKey = der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 2
 };
 
 static inline der::Result OCSPResponse(der::Input&, Context&);
 static inline der::Result ResponseBytes(der::Input&, Context&);
 static inline der::Result BasicResponse(der::Input&, Context&);
@@ -575,17 +563,17 @@ ResponseData(der::Input& input, Context&
   if (der::GeneralizedTime(input, producedAt) != der::Success) {
     return der::Failure;
   }
 
   // We don't accept an empty sequence of responses. In practice, a legit OCSP
   // responder will never return an empty response, and handling the case of an
   // empty response makes things unnecessarily complicated.
   if (der::NestedOf(input, der::SEQUENCE, der::SEQUENCE,
-                    der::MustNotBeEmpty,
+                    der::EmptyAllowed::No,
                     bind(SingleResponse, _1, ref(context))) != der::Success) {
     return der::Failure;
   }
 
   if (!input.AtEnd()) {
     if (der::Nested(input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
                     CheckExtensionsForCriticality) != der::Success) {
       return der::Failure;
@@ -861,17 +849,17 @@ CheckExtensionForCriticality(der::Input&
 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
 static der::Result
 CheckExtensionsForCriticality(der::Input& input)
 {
   // TODO(bug 997994): some responders include an empty SEQUENCE OF
   // Extension, which is invalid (der::MayBeEmpty should really be
   // der::MustNotBeEmpty).
   return der::NestedOf(input, der::SEQUENCE, der::SEQUENCE,
-                       der::MayBeEmpty, CheckExtensionForCriticality);
+                       der::EmptyAllowed::Yes, CheckExtensionForCriticality);
 }
 
 //   1. The certificate identified in a received response corresponds to
 //      the certificate that was identified in the corresponding request;
 //   2. The signature on the response is valid;
 //   3. The identity of the signer matches the intended recipient of the
 //      request;
 //   4. The signer is currently authorized to provide a response for the
--- a/security/pkix/lib/pkixutil.h
+++ b/security/pkix/lib/pkixutil.h
@@ -13,16 +13,17 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef mozilla_pkix__pkixutil_h
 #define mozilla_pkix__pkixutil_h
 
+#include "pkix/enumclass.h"
 #include "pkix/pkixtypes.h"
 #include "prerror.h"
 #include "seccomon.h"
 #include "secerr.h"
 
 namespace mozilla { namespace pkix {
 
 enum Result
@@ -76,34 +77,33 @@ MapSECStatus(SECStatus srv)
 // such as name constraints.
 //
 // Each BackCert contains pointers to all the given certificate's extensions
 // so that we can parse the extension block once and then process the
 // extensions in an order that may be different than they appear in the cert.
 class BackCert
 {
 public:
-  // ExcludeCN means that GetConstrainedNames won't include the subject CN in
-  // its results. IncludeCN means that GetConstrainedNames will include the
-  // subject CN in its results.
-  enum ConstrainedNameOptions { ExcludeCN = 0, IncludeCN = 1 };
+  // IncludeCN::No means that GetConstrainedNames won't include the subject CN
+  // in its results. IncludeCN::Yes means that GetConstrainedNames will include
+  // the subject CN in its results.
+  MOZILLA_PKIX_ENUM_CLASS IncludeCN { No = 0, Yes = 1 };
 
   // nssCert and childCert must be valid for the lifetime of BackCert
-  BackCert(CERTCertificate* nssCert, BackCert* childCert,
-           ConstrainedNameOptions cnOptions)
+  BackCert(CERTCertificate* nssCert, BackCert* childCert, IncludeCN includeCN)
     : encodedBasicConstraints(nullptr)
     , encodedCertificatePolicies(nullptr)
     , encodedExtendedKeyUsage(nullptr)
     , encodedKeyUsage(nullptr)
     , encodedNameConstraints(nullptr)
     , encodedInhibitAnyPolicy(nullptr)
     , childCert(childCert)
     , nssCert(nssCert)
     , constrainedNames(nullptr)
-    , cnOptions(cnOptions)
+    , includeCN(includeCN)
   {
   }
 
   Result Init();
 
   const SECItem* encodedBasicConstraints;
   const SECItem* encodedCertificatePolicies;
   const SECItem* encodedExtendedKeyUsage;
@@ -132,17 +132,17 @@ public:
 
   PLArenaPool* GetArena();
 
 private:
   CERTCertificate* nssCert;
 
   ScopedPLArenaPool arena;
   CERTGeneralName* constrainedNames;
-  ConstrainedNameOptions cnOptions;
+  IncludeCN includeCN;
 
   BackCert(const BackCert&) /* = delete */;
   void operator=(const BackCert&); /* = delete */;
 };
 
 } } // namespace mozilla::pkix
 
 #endif // mozilla_pkix__pkixutil_h
--- a/security/pkix/test/gtest/pkixder_input_tests.cpp
+++ b/security/pkix/test/gtest/pkixder_input_tests.cpp
@@ -545,17 +545,17 @@ Result NestedOfHelper(Input& input, std:
 TEST_F(pkixder_input_tests, NestedOf)
 {
   Input input;
   ASSERT_EQ(Success,
             input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8));
 
   std::vector<uint8_t> readValues;
   ASSERT_EQ(Success,
-    NestedOf(input, SEQUENCE, INTEGER, MustNotBeEmpty,
+    NestedOf(input, SEQUENCE, INTEGER, EmptyAllowed::No,
              mozilla::pkix::bind(NestedOfHelper, mozilla::pkix::_1,
                                  mozilla::pkix::ref(readValues))));
   ASSERT_EQ((size_t) 3, readValues.size());
   ASSERT_EQ(0x01, readValues[0]);
   ASSERT_EQ(0x02, readValues[1]);
   ASSERT_EQ(0x03, readValues[2]);
   ASSERT_EQ(Success, End(input));
 }
@@ -563,15 +563,15 @@ TEST_F(pkixder_input_tests, NestedOf)
 TEST_F(pkixder_input_tests, NestedOfWithTruncatedData)
 {
   Input input;
   ASSERT_EQ(Success, input.Init(DER_TRUNCATED_SEQUENCE_OF_INT8,
                                 sizeof DER_TRUNCATED_SEQUENCE_OF_INT8));
 
   std::vector<uint8_t> readValues;
   ASSERT_EQ(Failure,
-    NestedOf(input, SEQUENCE, INTEGER, MustNotBeEmpty,
+    NestedOf(input, SEQUENCE, INTEGER, EmptyAllowed::No,
              mozilla::pkix::bind(NestedOfHelper, mozilla::pkix::_1,
                                  mozilla::pkix::ref(readValues))));
   ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
   ASSERT_EQ((size_t) 0, readValues.size());
 }
 } // unnamed namespace