/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=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"AppTrustDomain.h"
#include"MainThreadUtils.h" #include"cert_storage/src/cert_storage.h" // FIXME: these two must be included before certdb.h { #include"seccomon.h" #include"certt.h" // } #include"certdb.h" #include"mozilla/ArrayUtils.h" #include"mozilla/Casting.h" #include"mozilla/Logging.h" #include"mozilla/Preferences.h" #include"mozpkix/pkixnss.h" #include"NSSCertDBTrustDomain.h" #include"nsComponentManagerUtils.h" #include"nsDirectoryServiceUtils.h" #include"nsIContentSignatureVerifier.h" #include"nsIX509CertDB.h" #include"nsNSSCertificate.h" #include"nsNetUtil.h" #include"prerror.h"
// Generated by gen_cert_header.py, which gets called by the build system. #include"xpcshell.inc" // Add-on signing Certificates #include"addons-public.inc" #include"addons-public-intermediate.inc" #include"addons-stage.inc" #include"addons-stage-intermediate.inc" // Content signature root certificates #include"content-signature-dev.inc" #include"content-signature-local.inc" #include"content-signature-prod.inc" #include"content-signature-stage.inc"
nsresult AppTrustDomain::SetTrustedRoot(AppTrustedRoot trustedRoot) { if (!mTrustedRoots.IsEmpty()) { return NS_ERROR_ALREADY_INITIALIZED;
} switch (trustedRoot) { case nsIX509CertDB::AppXPCShellRoot:
mTrustedRoots.AppendElements(xpcshellRoots, std::size(xpcshellRoots)); break;
case nsIX509CertDB::AddonsPublicRoot:
mTrustedRoots.AppendElements(addonsPublicRoots,
std::size(addonsPublicRoots)); break;
case nsIX509CertDB::AddonsStageRoot:
mTrustedRoots.AppendElements(addonsStageRoots,
std::size(addonsStageRoots)); break;
case nsIContentSignatureVerifier::ContentSignatureLocalRoot:
mTrustedRoots.AppendElements(contentSignatureLocalRoots,
std::size(contentSignatureLocalRoots)); break;
case nsIContentSignatureVerifier::ContentSignatureProdRoot:
mTrustedRoots.AppendElements(contentSignatureProdRoots,
std::size(contentSignatureProdRoots)); break;
case nsIContentSignatureVerifier::ContentSignatureStageRoot:
mTrustedRoots.AppendElements(contentSignatureStageRoots,
std::size(contentSignatureStageRoots)); break;
case nsIContentSignatureVerifier::ContentSignatureDevRoot:
mTrustedRoots.AppendElements(contentSignatureDevRoots,
std::size(contentSignatureDevRoots)); break;
default: return NS_ERROR_INVALID_ARG;
}
// If we're verifying add-ons signed by our production root, we want to make // sure a valid intermediate certificate is available for path building. // The intermediate bundled with signed XPI files may have expired and be // considered invalid, which can result in bug 1548973. if (trustedRoot == nsIX509CertDB::AddonsPublicRoot) {
mAddonsIntermediates.AppendElements(addonsPublicIntermediates,
std::size(addonsPublicIntermediates));
} // Similarly to the above logic for production, we hardcode the intermediate // stage certificate here, so that stage is equivalent to production. if (trustedRoot == nsIX509CertDB::AddonsStageRoot) {
mAddonsIntermediates.AppendElements(addonsStageIntermediates,
std::size(addonsStageIntermediates));
}
nsTArray<Input> candidates; for (constauto& root : mTrustedRoots) {
Input rootInput;
pkix::Result rv = rootInput.Init(root.Elements(), root.Length()); // This should never fail, since the possible roots are all hard-coded and // they should never be too long. if (rv != Success) { return rv;
}
candidates.AppendElement(std::move(rootInput));
} for (constauto& intermediate : mAddonsIntermediates) {
Input intermediateInput;
pkix::Result rv =
intermediateInput.Init(intermediate.Elements(), intermediate.Length()); // Again, this should never fail for the same reason as above. if (rv != Success) { return rv;
}
candidates.AppendElement(std::move(intermediateInput));
} for (constauto& intermediate : mIntermediates) {
Input intermediateInput;
pkix::Result rv =
intermediateInput.Init(intermediate.Elements(), intermediate.Length()); // This is untrusted input, so skip any intermediates that are too large. if (rv != Success) { continue;
}
candidates.AppendElement(std::move(intermediateInput));
}
// If the above did not succeed in building a verified certificate chain, // fall back to searching for candidates in NSS. This is important in case an // intermediate involved in add-on signing expires before it is replaced. See // bug 1548973.
SECItem encodedIssuerNameSECItem = UnsafeMapInputToSECItem(encodedIssuerName);
UniqueCERTCertList nssCandidates(CERT_CreateSubjectCertList(
nullptr, CERT_GetDefaultCertDB(), &encodedIssuerNameSECItem, 0, false)); if (nssCandidates) { for (CERTCertListNode* n = CERT_LIST_HEAD(nssCandidates);
!CERT_LIST_END(n, nssCandidates); n = CERT_LIST_NEXT(n)) {
Input certDER;
pkix::Result rv =
certDER.Init(n->cert->derCert.data, n->cert->derCert.len); if (rv != Success) { continue; // probably too big
}
if (revocationState == nsICertStorage::STATE_ENFORCE) { return pkix::Result::ERROR_REVOKED_CERTIFICATE;
}
// mTrustedRoots are the only trust anchors for this validation.
Span<const uint8_t> candidateCertDERSpan = {candidateCertDER.UnsafeGetData(),
candidateCertDER.GetLength()}; for (constauto& trustedRoot : mTrustedRoots) { if (trustedRoot == candidateCertDERSpan) {
trustLevel = TrustLevel::TrustAnchor; return Success;
}
}
pkix::Result AppTrustDomain::CheckRevocation(EndEntityOrCA, const CertID&, Time,
Duration, /*optional*/ const Input*, /*optional*/ const Input*, /*optional*/ const Input*) { // We don't currently do revocation checking. If we need to distrust an Apps // certificate, we will use the active distrust mechanism. return Success;
}
pkix::Result AppTrustDomain::IsChainValid(const DERArray& certChain, Time time, const CertPolicyId& requiredPolicy) {
MOZ_ASSERT(requiredPolicy.IsAnyPolicy()); return Success;
}
pkix::Result AppTrustDomain::CheckSignatureDigestAlgorithm(
DigestAlgorithm digestAlg, EndEntityOrCA, Time) { switch (digestAlg) { case DigestAlgorithm::sha256: // fall through case DigestAlgorithm::sha384: // fall through case DigestAlgorithm::sha512: return Success; case DigestAlgorithm::sha1: return pkix::Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED;
} return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
}
pkix::Result AppTrustDomain::CheckRSAPublicKeyModulusSizeInBits(
EndEntityOrCA /*endEntityOrCA*/, unsigned int modulusSizeInBits) { if (modulusSizeInBits < 2048u) { return pkix::Result::ERROR_INADEQUATE_KEY_SIZE;
} return Success;
}
pkix::Result AppTrustDomain::VerifyRSAPKCS1SignedData(
Input data, DigestAlgorithm digestAlgorithm, Input signature,
Input subjectPublicKeyInfo) { // TODO: We should restrict signatures to SHA-256 or better. return VerifyRSAPKCS1SignedDataNSS(data, digestAlgorithm, signature,
subjectPublicKeyInfo, nullptr);
}
pkix::Result AppTrustDomain::CheckECDSACurveIsAcceptable(
EndEntityOrCA /*endEntityOrCA*/, NamedCurve curve) { switch (curve) { case NamedCurve::secp256r1: // fall through case NamedCurve::secp384r1: // fall through case NamedCurve::secp521r1: return Success;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.