summaryrefslogtreecommitdiffstats
path: root/security/manager/ssl/CSTrustDomain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'security/manager/ssl/CSTrustDomain.cpp')
-rw-r--r--security/manager/ssl/CSTrustDomain.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/security/manager/ssl/CSTrustDomain.cpp b/security/manager/ssl/CSTrustDomain.cpp
new file mode 100644
index 0000000000..3f19d080ef
--- /dev/null
+++ b/security/manager/ssl/CSTrustDomain.cpp
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 "CSTrustDomain.h"
+#include "NSSCertDBTrustDomain.h"
+#include "cert_storage/src/cert_storage.h"
+#include "mozilla/Base64.h"
+#include "mozilla/Logging.h"
+#include "mozilla/Preferences.h"
+#include "mozpkix/pkixnss.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsNSSComponent.h"
+#include "nsServiceManagerUtils.h"
+
+using namespace mozilla::pkix;
+
+namespace mozilla {
+namespace psm {
+
+static LazyLogModule gTrustDomainPRLog("CSTrustDomain");
+#define CSTrust_LOG(args) MOZ_LOG(gTrustDomainPRLog, LogLevel::Debug, args)
+
+CSTrustDomain::CSTrustDomain(nsTArray<nsTArray<uint8_t>>& certList)
+ : mCertList(certList), mCertBlocklist(do_GetService(NS_CERT_STORAGE_CID)) {}
+
+Result CSTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
+ const CertPolicyId& policy,
+ Input candidateCertDER,
+ /*out*/ TrustLevel& trustLevel) {
+ MOZ_ASSERT(policy.IsAnyPolicy());
+ if (!policy.IsAnyPolicy()) {
+ return Result::FATAL_ERROR_INVALID_ARGS;
+ }
+
+ nsTArray<uint8_t> issuerBytes;
+ nsTArray<uint8_t> serialBytes;
+ nsTArray<uint8_t> subjectBytes;
+ nsTArray<uint8_t> pubKeyBytes;
+
+ Result result =
+ BuildRevocationCheckArrays(candidateCertDER, endEntityOrCA, issuerBytes,
+ serialBytes, subjectBytes, pubKeyBytes);
+ if (result != Success) {
+ return result;
+ }
+
+ int16_t revocationState;
+ nsresult nsrv = mCertBlocklist->GetRevocationState(
+ issuerBytes, serialBytes, subjectBytes, pubKeyBytes, &revocationState);
+ if (NS_FAILED(nsrv)) {
+ return Result::FATAL_ERROR_LIBRARY_FAILURE;
+ }
+
+ if (revocationState == nsICertStorage::STATE_ENFORCE) {
+ CSTrust_LOG(("CSTrustDomain: certificate is revoked\n"));
+ return Result::ERROR_REVOKED_CERTIFICATE;
+ }
+
+ // Is this cert our built-in content signing root?
+ bool isRoot = false;
+ nsCOMPtr<nsINSSComponent> component(do_GetService(PSM_COMPONENT_CONTRACTID));
+ if (!component) {
+ return Result::FATAL_ERROR_LIBRARY_FAILURE;
+ }
+ nsTArray<uint8_t> candidateCert(candidateCertDER.UnsafeGetData(),
+ candidateCertDER.GetLength());
+ nsrv = component->IsCertContentSigningRoot(candidateCert, &isRoot);
+ if (NS_FAILED(nsrv)) {
+ return Result::FATAL_ERROR_LIBRARY_FAILURE;
+ }
+ if (isRoot) {
+ CSTrust_LOG(("CSTrustDomain: certificate is a trust anchor\n"));
+ trustLevel = TrustLevel::TrustAnchor;
+ return Success;
+ }
+ CSTrust_LOG(("CSTrustDomain: certificate is *not* a trust anchor\n"));
+
+ trustLevel = TrustLevel::InheritsTrust;
+ return Success;
+}
+
+Result CSTrustDomain::FindIssuer(Input encodedIssuerName,
+ IssuerChecker& checker, Time time) {
+ // Loop over the chain, look for a matching subject
+ for (const auto& certBytes : mCertList) {
+ Input certInput;
+ Result rv = certInput.Init(certBytes.Elements(), certBytes.Length());
+ if (rv != Success) {
+ continue; // probably too big
+ }
+ bool keepGoing;
+ rv = checker.Check(certInput, nullptr /*additionalNameConstraints*/,
+ keepGoing);
+ if (rv != Success) {
+ return rv;
+ }
+ if (!keepGoing) {
+ CSTrust_LOG(("CSTrustDomain: don't keep going\n"));
+ break;
+ }
+ }
+
+ return Success;
+}
+
+Result CSTrustDomain::CheckRevocation(
+ EndEntityOrCA endEntityOrCA, const CertID& certID, Time time,
+ Duration validityDuration,
+ /*optional*/ const Input* stapledOCSPresponse,
+ /*optional*/ const Input* aiaExtension,
+ /*optional*/ const Input* sctExtension) {
+ // We're relying solely on the CertBlocklist for revocation - and we're
+ // performing checks on this in GetCertTrust (as per nsNSSCertDBTrustDomain)
+ return Success;
+}
+
+Result CSTrustDomain::IsChainValid(const DERArray& certChain, Time time,
+ const CertPolicyId& requiredPolicy) {
+ MOZ_ASSERT(requiredPolicy.IsAnyPolicy());
+ // Check that our chain is not empty
+ if (certChain.GetLength() == 0) {
+ return Result::FATAL_ERROR_LIBRARY_FAILURE;
+ }
+
+ return Success;
+}
+
+Result CSTrustDomain::CheckSignatureDigestAlgorithm(DigestAlgorithm digestAlg,
+ EndEntityOrCA endEntityOrCA,
+ Time notBefore) {
+ if (digestAlg == DigestAlgorithm::sha1) {
+ return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED;
+ }
+ return Success;
+}
+
+Result CSTrustDomain::CheckRSAPublicKeyModulusSizeInBits(
+ EndEntityOrCA endEntityOrCA, unsigned int modulusSizeInBits) {
+ if (modulusSizeInBits < 2048) {
+ return Result::ERROR_INADEQUATE_KEY_SIZE;
+ }
+ return Success;
+}
+
+Result CSTrustDomain::VerifyRSAPKCS1SignedDigest(
+ const SignedDigest& signedDigest, Input subjectPublicKeyInfo) {
+ return VerifyRSAPKCS1SignedDigestNSS(signedDigest, subjectPublicKeyInfo,
+ nullptr);
+}
+
+Result CSTrustDomain::CheckECDSACurveIsAcceptable(EndEntityOrCA endEntityOrCA,
+ NamedCurve curve) {
+ switch (curve) {
+ case NamedCurve::secp256r1: // fall through
+ case NamedCurve::secp384r1: // fall through
+ case NamedCurve::secp521r1:
+ return Success;
+ }
+
+ return Result::ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
+}
+
+Result CSTrustDomain::VerifyECDSASignedDigest(const SignedDigest& signedDigest,
+ Input subjectPublicKeyInfo) {
+ return VerifyECDSASignedDigestNSS(signedDigest, subjectPublicKeyInfo,
+ nullptr);
+}
+
+Result CSTrustDomain::CheckValidityIsAcceptable(Time notBefore, Time notAfter,
+ EndEntityOrCA endEntityOrCA,
+ KeyPurposeId keyPurpose) {
+ return Success;
+}
+
+Result CSTrustDomain::NetscapeStepUpMatchesServerAuth(Time notBefore,
+ /*out*/ bool& matches) {
+ matches = false;
+ return Success;
+}
+
+void CSTrustDomain::NoteAuxiliaryExtension(AuxiliaryExtension /*extension*/,
+ Input /*extensionData*/) {}
+
+Result CSTrustDomain::DigestBuf(Input item, DigestAlgorithm digestAlg,
+ /*out*/ uint8_t* digestBuf,
+ size_t digestBufLen) {
+ return DigestBufNSS(item, digestAlg, digestBuf, digestBufLen);
+}
+
+} // namespace psm
+} // namespace mozilla