зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1713605 - Avoid NSS usage in CertVerifier::VerifySSLServerCert r=keeler
Differential Revision: https://phabricator.services.mozilla.com/D118030
This commit is contained in:
Родитель
45b533e45e
Коммит
4fa1dee9c4
|
@ -483,8 +483,8 @@ bool CertVerifier::SHA1ModeMoreRestrictiveThanGivenMode(SHA1Mode mode) {
|
|||
}
|
||||
|
||||
Result CertVerifier::VerifyCert(
|
||||
CERTCertificate* cert, SECCertificateUsage usage, Time time, void* pinArg,
|
||||
const char* hostname,
|
||||
const nsTArray<uint8_t>& certBytes, SECCertificateUsage usage, Time time,
|
||||
void* pinArg, const char* hostname,
|
||||
/*out*/ nsTArray<nsTArray<uint8_t>>& builtChain,
|
||||
/*optional*/ const Flags flags,
|
||||
/*optional*/ const Maybe<nsTArray<nsTArray<uint8_t>>>& extraCertificates,
|
||||
|
@ -499,7 +499,6 @@ Result CertVerifier::VerifyCert(
|
|||
/*optional out*/ CertificateTransparencyInfo* ctInfo) {
|
||||
MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("Top of VerifyCert\n"));
|
||||
|
||||
MOZ_ASSERT(cert);
|
||||
MOZ_ASSERT(usage == certificateUsageSSLServer || !(flags & FLAG_MUST_BE_EV));
|
||||
MOZ_ASSERT(usage == certificateUsageSSLServer || !keySizeStatus);
|
||||
MOZ_ASSERT(usage == certificateUsageSSLServer || !sha1ModeResult);
|
||||
|
@ -535,13 +534,12 @@ Result CertVerifier::VerifyCert(
|
|||
*sha1ModeResult = SHA1ModeResult::NeverChecked;
|
||||
}
|
||||
|
||||
if (!cert ||
|
||||
(usage != certificateUsageSSLServer && (flags & FLAG_MUST_BE_EV))) {
|
||||
if (usage != certificateUsageSSLServer && (flags & FLAG_MUST_BE_EV)) {
|
||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
Input certDER;
|
||||
Result rv = certDER.Init(cert->derCert.data, cert->derCert.len);
|
||||
Result rv = certDER.Init(certBytes.Elements(), certBytes.Length());
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -630,7 +628,6 @@ Result CertVerifier::VerifyCert(
|
|||
: NSSCertDBTrustDomain::FetchOCSPForEV;
|
||||
|
||||
CertPolicyId evPolicy;
|
||||
nsTArray<uint8_t> certBytes(cert->derCert.data, cert->derCert.len);
|
||||
bool foundEVPolicy = GetFirstEVPolicy(certBytes, evPolicy);
|
||||
rv = Result::ERROR_UNKNOWN_ERROR;
|
||||
for (size_t i = 0;
|
||||
|
@ -878,20 +875,7 @@ Result CertVerifier::VerifyCert(
|
|||
return Success;
|
||||
}
|
||||
|
||||
static bool CertIsSelfSigned(const UniqueCERTCertificate& cert, void* pinarg) {
|
||||
Input certInput;
|
||||
Result rv = certInput.Init(cert->derCert.data, cert->derCert.len);
|
||||
if (rv != Success) {
|
||||
return false;
|
||||
}
|
||||
// we don't use the certificate for path building, so this parameter doesn't
|
||||
// matter
|
||||
EndEntityOrCA notUsedForPaths = EndEntityOrCA::MustBeEndEntity;
|
||||
BackCert backCert(certInput, notUsedForPaths, nullptr);
|
||||
rv = backCert.Init();
|
||||
if (rv != Success) {
|
||||
return false;
|
||||
}
|
||||
static bool CertIsSelfSigned(const BackCert& backCert, void* pinarg) {
|
||||
if (!InputsAreEqual(backCert.GetIssuer(), backCert.GetSubject())) {
|
||||
return false;
|
||||
}
|
||||
|
@ -899,13 +883,13 @@ static bool CertIsSelfSigned(const UniqueCERTCertificate& cert, void* pinarg) {
|
|||
nsTArray<nsTArray<uint8_t>> emptyCertList;
|
||||
// CSTrustDomain is only used for the signature verification callbacks
|
||||
mozilla::psm::CSTrustDomain trustDomain(emptyCertList);
|
||||
rv = VerifySignedData(trustDomain, backCert.GetSignedData(),
|
||||
backCert.GetSubjectPublicKeyInfo());
|
||||
Result rv = VerifySignedData(trustDomain, backCert.GetSignedData(),
|
||||
backCert.GetSubjectPublicKeyInfo());
|
||||
return rv == Success;
|
||||
}
|
||||
|
||||
Result CertVerifier::VerifySSLServerCert(
|
||||
const UniqueCERTCertificate& peerCert, Time time,
|
||||
const nsTArray<uint8_t>& peerCertBytes, Time time,
|
||||
/*optional*/ void* pinarg, const nsACString& hostname,
|
||||
/*out*/ nsTArray<nsTArray<uint8_t>>& builtChain,
|
||||
/*optional*/ Flags flags,
|
||||
|
@ -921,7 +905,6 @@ Result CertVerifier::VerifySSLServerCert(
|
|||
/*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo,
|
||||
/*optional out*/ CertificateTransparencyInfo* ctInfo,
|
||||
/*optional out*/ bool* isBuiltCertChainRootBuiltInRoot) {
|
||||
MOZ_ASSERT(peerCert);
|
||||
// XXX: MOZ_ASSERT(pinarg);
|
||||
MOZ_ASSERT(!hostname.IsEmpty());
|
||||
|
||||
|
@ -939,15 +922,27 @@ Result CertVerifier::VerifySSLServerCert(
|
|||
|
||||
// CreateCertErrorRunnable assumes that CheckCertHostname is only called
|
||||
// if VerifyCert succeeded.
|
||||
Input peerCertInput;
|
||||
Result rv =
|
||||
VerifyCert(peerCert.get(), certificateUsageSSLServer, time, pinarg,
|
||||
PromiseFlatCString(hostname).get(), builtChain, flags,
|
||||
extraCertificates, stapledOCSPResponse, sctsFromTLS,
|
||||
originAttributes, evStatus, ocspStaplingStatus, keySizeStatus,
|
||||
sha1ModeResult, pinningTelemetryInfo, ctInfo);
|
||||
peerCertInput.Init(peerCertBytes.Elements(), peerCertBytes.Length());
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
rv = VerifyCert(peerCertBytes, certificateUsageSSLServer, time, pinarg,
|
||||
PromiseFlatCString(hostname).get(), builtChain, flags,
|
||||
extraCertificates, stapledOCSPResponse, sctsFromTLS,
|
||||
originAttributes, evStatus, ocspStaplingStatus, keySizeStatus,
|
||||
sha1ModeResult, pinningTelemetryInfo, ctInfo);
|
||||
if (rv != Success) {
|
||||
// we don't use the certificate for path building, so this parameter doesn't
|
||||
// matter
|
||||
EndEntityOrCA notUsedForPaths = EndEntityOrCA::MustBeEndEntity;
|
||||
BackCert peerBackCert(peerCertInput, notUsedForPaths, nullptr);
|
||||
if (peerBackCert.Init() != Success) {
|
||||
return rv;
|
||||
}
|
||||
if (rv == Result::ERROR_UNKNOWN_ISSUER &&
|
||||
CertIsSelfSigned(peerCert, pinarg)) {
|
||||
CertIsSelfSigned(peerBackCert, pinarg)) {
|
||||
// In this case we didn't find any issuer for the certificate and the
|
||||
// certificate is self-signed.
|
||||
return Result::ERROR_SELF_SIGNED_CERT;
|
||||
|
@ -965,7 +960,13 @@ Result CertVerifier::VerifySSLServerCert(
|
|||
}
|
||||
// IssuerMatchesMitmCanary succeeds if the issuer matches the canary and
|
||||
// the feature is enabled.
|
||||
nsresult rv = component->IssuerMatchesMitmCanary(peerCert->issuerName);
|
||||
Input issuerNameInput = peerBackCert.GetIssuer();
|
||||
SECItem issuerNameItem = UnsafeMapInputToSECItem(issuerNameInput);
|
||||
UniquePORTString issuerName(CERT_DerNameToAscii(&issuerNameItem));
|
||||
if (!issuerName) {
|
||||
return Result::ERROR_BAD_DER;
|
||||
}
|
||||
nsresult rv = component->IssuerMatchesMitmCanary(issuerName.get());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return Result::ERROR_MITM_DETECTED;
|
||||
}
|
||||
|
@ -980,12 +981,6 @@ Result CertVerifier::VerifySSLServerCert(
|
|||
}
|
||||
}
|
||||
|
||||
Input peerCertInput;
|
||||
rv = peerCertInput.Init(peerCert->derCert.data, peerCert->derCert.len);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
Input stapledOCSPResponseInput;
|
||||
Input* responseInputPtr = nullptr;
|
||||
if (stapledOCSPResponse) {
|
||||
|
|
|
@ -157,7 +157,7 @@ class CertVerifier {
|
|||
// *evOidPolicy == SEC_OID_UNKNOWN means the cert is NOT EV
|
||||
// Only one usage per verification is supported.
|
||||
mozilla::pkix::Result VerifyCert(
|
||||
CERTCertificate* cert, SECCertificateUsage usage,
|
||||
const nsTArray<uint8_t>& certBytes, SECCertificateUsage usage,
|
||||
mozilla::pkix::Time time, void* pinArg, const char* hostname,
|
||||
/*out*/ nsTArray<nsTArray<uint8_t>>& builtChain, Flags flags = 0,
|
||||
/*optional in*/
|
||||
|
@ -175,8 +175,8 @@ class CertVerifier {
|
|||
/*optional out*/ CertificateTransparencyInfo* ctInfo = nullptr);
|
||||
|
||||
mozilla::pkix::Result VerifySSLServerCert(
|
||||
const UniqueCERTCertificate& peerCert, mozilla::pkix::Time time,
|
||||
void* pinarg, const nsACString& hostname,
|
||||
const nsTArray<uint8_t>& peerCert, mozilla::pkix::Time time, void* pinarg,
|
||||
const nsACString& hostname,
|
||||
/*out*/ nsTArray<nsTArray<uint8_t>>& builtChain,
|
||||
/*optional*/ Flags flags = 0,
|
||||
/*optional*/ const Maybe<nsTArray<nsTArray<uint8_t>>>& extraCertificates =
|
||||
|
|
|
@ -857,7 +857,7 @@ static void AuthCertificateSetResults(
|
|||
// Note: Takes ownership of |peerCertChain| if SECSuccess is not returned.
|
||||
Result AuthCertificate(
|
||||
CertVerifier& certVerifier, void* aPinArg,
|
||||
const UniqueCERTCertificate& cert,
|
||||
const nsTArray<uint8_t>& certBytes,
|
||||
const nsTArray<nsTArray<uint8_t>>& peerCertChain,
|
||||
const nsACString& aHostName, const OriginAttributes& aOriginAttributes,
|
||||
const Maybe<nsTArray<uint8_t>>& stapledOCSPResponse,
|
||||
|
@ -868,8 +868,6 @@ Result AuthCertificate(
|
|||
/*out*/ EVStatus& evStatus,
|
||||
/*out*/ CertificateTransparencyInfo& certificateTransparencyInfo,
|
||||
/*out*/ bool& aIsCertChainRootBuiltInRoot) {
|
||||
MOZ_ASSERT(cert);
|
||||
|
||||
CertVerifier::OCSPStaplingStatus ocspStaplingStatus =
|
||||
CertVerifier::OCSP_STAPLING_NEVER_CHECKED;
|
||||
KeySizeStatus keySizeStatus = KeySizeStatus::NeverChecked;
|
||||
|
@ -886,7 +884,7 @@ Result AuthCertificate(
|
|||
}
|
||||
|
||||
Result rv = certVerifier.VerifySSLServerCert(
|
||||
cert, time, aPinArg, aHostName, builtCertChain, certVerifierFlags,
|
||||
certBytes, time, aPinArg, aHostName, builtCertChain, certVerifierFlags,
|
||||
Some(std::move(peerCertsBytes)), stapledOCSPResponse,
|
||||
sctsFromTLSExtension, dcInfo, aOriginAttributes, &evStatus,
|
||||
&ocspStaplingStatus, &keySizeStatus, &sha1ModeResult,
|
||||
|
@ -1093,11 +1091,12 @@ SSLServerCertVerificationJob::Run() {
|
|||
EVStatus evStatus;
|
||||
CertificateTransparencyInfo certificateTransparencyInfo;
|
||||
bool isCertChainRootBuiltInRoot = false;
|
||||
nsTArray<nsTArray<uint8_t>> certBytesArray;
|
||||
nsTArray<nsTArray<uint8_t>> builtChainBytesArray;
|
||||
nsTArray<uint8_t> certBytes(mCert->derCert.data, mCert->derCert.len);
|
||||
Result rv = AuthCertificate(
|
||||
*certVerifier, mPinArg, mCert, mPeerCertChain, mHostName,
|
||||
*certVerifier, mPinArg, certBytes, mPeerCertChain, mHostName,
|
||||
mOriginAttributes, mStapledOCSPResponse, mSCTsFromTLSExtension, mDCInfo,
|
||||
mProviderFlags, mTime, mCertVerifierFlags, certBytesArray, evStatus,
|
||||
mProviderFlags, mTime, mCertVerifierFlags, builtChainBytesArray, evStatus,
|
||||
certificateTransparencyInfo, isCertChainRootBuiltInRoot);
|
||||
|
||||
RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(mCert.get());
|
||||
|
@ -1108,7 +1107,7 @@ SSLServerCertVerificationJob::Run() {
|
|||
Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES, 1);
|
||||
|
||||
mResultTask->Dispatch(
|
||||
nsc, std::move(certBytesArray), std::move(mPeerCertChain),
|
||||
nsc, std::move(builtChainBytesArray), std::move(mPeerCertChain),
|
||||
TransportSecurityInfo::ConvertCertificateTransparencyInfoToStatus(
|
||||
certificateTransparencyInfo),
|
||||
evStatus, true, 0, 0, isCertChainRootBuiltInRoot, mProviderFlags);
|
||||
|
@ -1127,7 +1126,7 @@ SSLServerCertVerificationJob::Run() {
|
|||
|
||||
// NB: finalError may be 0 here, in which the connection will continue.
|
||||
mResultTask->Dispatch(
|
||||
nsc, std::move(certBytesArray), std::move(mPeerCertChain),
|
||||
nsc, std::move(builtChainBytesArray), std::move(mPeerCertChain),
|
||||
nsITransportSecurityInfo::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE,
|
||||
EVStatus::NotEV, false, finalError, collectedErrors, false,
|
||||
mProviderFlags);
|
||||
|
|
|
@ -1094,11 +1094,12 @@ static void RebuildVerifiedCertificateInformation(PRFileDesc* fd,
|
|||
|
||||
EVStatus evStatus;
|
||||
CertificateTransparencyInfo certificateTransparencyInfo;
|
||||
nsTArray<nsTArray<uint8_t>> certBytesArray;
|
||||
nsTArray<nsTArray<uint8_t>> builtChainCertBytes;
|
||||
nsTArray<uint8_t> certBytes(cert->derCert.data, cert->derCert.len);
|
||||
bool isBuiltCertChainRootBuiltInRoot = false;
|
||||
mozilla::pkix::Result rv = certVerifier->VerifySSLServerCert(
|
||||
cert, mozilla::pkix::Now(), infoObject, infoObject->GetHostName(),
|
||||
certBytesArray, flags, maybePeerCertsBytes, stapledOCSPResponse,
|
||||
certBytes, mozilla::pkix::Now(), infoObject, infoObject->GetHostName(),
|
||||
builtChainCertBytes, flags, maybePeerCertsBytes, stapledOCSPResponse,
|
||||
sctsFromTLSExtension, Nothing(), infoObject->GetOriginAttributes(),
|
||||
&evStatus,
|
||||
nullptr, // OCSP stapling telemetry
|
||||
|
@ -1128,7 +1129,7 @@ static void RebuildVerifiedCertificateInformation(PRFileDesc* fd,
|
|||
TransportSecurityInfo::ConvertCertificateTransparencyInfoToStatus(
|
||||
certificateTransparencyInfo);
|
||||
infoObject->SetCertificateTransparencyStatus(status);
|
||||
infoObject->SetSucceededCertChain(std::move(certBytesArray));
|
||||
infoObject->SetSucceededCertChain(std::move(builtChainCertBytes));
|
||||
infoObject->SetIsBuiltCertChainRootBuiltInRoot(
|
||||
isBuiltCertChainRootBuiltInRoot);
|
||||
}
|
||||
|
|
|
@ -1266,9 +1266,15 @@ nsresult VerifyCertAtTime(nsIX509Cert* aCert,
|
|||
EVStatus evStatus;
|
||||
mozilla::pkix::Result result;
|
||||
|
||||
nsTArray<uint8_t> certBytes;
|
||||
nsresult nsrv = aCert->GetRawDER(certBytes);
|
||||
if (NS_FAILED(nsrv)) {
|
||||
return nsrv;
|
||||
}
|
||||
|
||||
if (!aHostname.IsVoid() && aUsage == certificateUsageSSLServer) {
|
||||
result =
|
||||
certVerifier->VerifySSLServerCert(nssCert, aTime,
|
||||
certVerifier->VerifySSLServerCert(certBytes, aTime,
|
||||
nullptr, // Assume no context
|
||||
aHostname, resultChain, aFlags,
|
||||
Nothing(), // extraCertificates
|
||||
|
@ -1279,7 +1285,7 @@ nsresult VerifyCertAtTime(nsIX509Cert* aCert,
|
|||
} else {
|
||||
const nsCString& flatHostname = PromiseFlatCString(aHostname);
|
||||
result = certVerifier->VerifyCert(
|
||||
nssCert.get(), aUsage, aTime,
|
||||
certBytes, aUsage, aTime,
|
||||
nullptr, // Assume no context
|
||||
aHostname.IsVoid() ? nullptr : flatHostname.get(), resultChain, aFlags,
|
||||
Nothing(), // extraCertificates
|
||||
|
|
Загрузка…
Ссылка в новой задаче