mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1159155 - Add telemetry probe for SHA-1 usage (r=keeler)
This commit is contained in:
parent
b625ffc87b
commit
fc2d7be9e8
@ -255,7 +255,7 @@ AppTrustDomain::IsChainValid(const DERArray& certChain, Time time)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result
|
Result
|
||||||
AppTrustDomain::CheckSignatureDigestAlgorithm(DigestAlgorithm)
|
AppTrustDomain::CheckSignatureDigestAlgorithm(DigestAlgorithm, EndEntityOrCA)
|
||||||
{
|
{
|
||||||
// TODO: We should restrict signatures to SHA-256 or better.
|
// TODO: We should restrict signatures to SHA-256 or better.
|
||||||
return Success;
|
return Success;
|
||||||
|
@ -40,7 +40,8 @@ public:
|
|||||||
virtual Result IsChainValid(const mozilla::pkix::DERArray& certChain,
|
virtual Result IsChainValid(const mozilla::pkix::DERArray& certChain,
|
||||||
mozilla::pkix::Time time) override;
|
mozilla::pkix::Time time) override;
|
||||||
virtual Result CheckSignatureDigestAlgorithm(
|
virtual Result CheckSignatureDigestAlgorithm(
|
||||||
mozilla::pkix::DigestAlgorithm digestAlg) override;
|
mozilla::pkix::DigestAlgorithm digestAlg,
|
||||||
|
mozilla::pkix::EndEntityOrCA endEntityOrCA) override;
|
||||||
virtual Result CheckRSAPublicKeyModulusSizeInBits(
|
virtual Result CheckRSAPublicKeyModulusSizeInBits(
|
||||||
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
||||||
unsigned int modulusSizeInBits) override;
|
unsigned int modulusSizeInBits) override;
|
||||||
|
@ -123,13 +123,15 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
/*optional out*/ ScopedCERTCertList* builtChain,
|
/*optional out*/ ScopedCERTCertList* builtChain,
|
||||||
/*optional out*/ SECOidTag* evOidPolicy,
|
/*optional out*/ SECOidTag* evOidPolicy,
|
||||||
/*optional out*/ OCSPStaplingStatus* ocspStaplingStatus,
|
/*optional out*/ OCSPStaplingStatus* ocspStaplingStatus,
|
||||||
/*optional out*/ KeySizeStatus* keySizeStatus)
|
/*optional out*/ KeySizeStatus* keySizeStatus,
|
||||||
|
/*optional out*/ SignatureDigestStatus* sigDigestStatus)
|
||||||
{
|
{
|
||||||
MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("Top of VerifyCert\n"));
|
MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("Top of VerifyCert\n"));
|
||||||
|
|
||||||
PR_ASSERT(cert);
|
PR_ASSERT(cert);
|
||||||
PR_ASSERT(usage == certificateUsageSSLServer || !(flags & FLAG_MUST_BE_EV));
|
PR_ASSERT(usage == certificateUsageSSLServer || !(flags & FLAG_MUST_BE_EV));
|
||||||
PR_ASSERT(usage == certificateUsageSSLServer || !keySizeStatus);
|
PR_ASSERT(usage == certificateUsageSSLServer || !keySizeStatus);
|
||||||
|
PR_ASSERT(usage == certificateUsageSSLServer || !sigDigestStatus);
|
||||||
|
|
||||||
if (builtChain) {
|
if (builtChain) {
|
||||||
*builtChain = nullptr;
|
*builtChain = nullptr;
|
||||||
@ -153,6 +155,14 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
*keySizeStatus = KeySizeStatus::NeverChecked;
|
*keySizeStatus = KeySizeStatus::NeverChecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sigDigestStatus) {
|
||||||
|
if (usage != certificateUsageSSLServer) {
|
||||||
|
PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
|
||||||
|
return SECFailure;
|
||||||
|
}
|
||||||
|
*sigDigestStatus = SignatureDigestStatus::NeverChecked;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cert ||
|
if (!cert ||
|
||||||
(usage != certificateUsageSSLServer && (flags & FLAG_MUST_BE_EV))) {
|
(usage != certificateUsageSSLServer && (flags & FLAG_MUST_BE_EV))) {
|
||||||
PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
|
PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
|
||||||
@ -197,13 +207,13 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
case certificateUsageSSLClient: {
|
case certificateUsageSSLClient: {
|
||||||
// XXX: We don't really have a trust bit for SSL client authentication so
|
// XXX: We don't really have a trust bit for SSL client authentication so
|
||||||
// just use trustEmail as it is the closest alternative.
|
// just use trustEmail as it is the closest alternative.
|
||||||
NSSCertDBTrustDomain trustDomain(trustEmail, defaultOCSPFetching, mOCSPCache,
|
NSSCertDBTrustDomain trustDomain(trustEmail, defaultOCSPFetching,
|
||||||
pinArg, ocspGETConfig,
|
mOCSPCache, pinArg, ocspGETConfig,
|
||||||
mCertShortLifetimeInDays,
|
mCertShortLifetimeInDays,
|
||||||
pinningDisabled,
|
pinningDisabled, MIN_RSA_BITS_WEAK,
|
||||||
MIN_RSA_BITS_WEAK,
|
|
||||||
ValidityCheckingMode::CheckingOff,
|
ValidityCheckingMode::CheckingOff,
|
||||||
nullptr, builtChain);
|
AcceptAllAlgorithms, nullptr,
|
||||||
|
builtChain);
|
||||||
rv = BuildCertChain(trustDomain, certDER, time,
|
rv = BuildCertChain(trustDomain, certDER, time,
|
||||||
EndEntityOrCA::MustBeEndEntity,
|
EndEntityOrCA::MustBeEndEntity,
|
||||||
KeyUsage::digitalSignature,
|
KeyUsage::digitalSignature,
|
||||||
@ -217,6 +227,28 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
// restrict the acceptable key usage based on the key exchange method
|
// restrict the acceptable key usage based on the key exchange method
|
||||||
// chosen by the server.
|
// chosen by the server.
|
||||||
|
|
||||||
|
SignatureDigestOption digestAlgorithmOptions[] = {
|
||||||
|
DisableSHA1Everywhere,
|
||||||
|
DisableSHA1ForCA,
|
||||||
|
DisableSHA1ForEE,
|
||||||
|
AcceptAllAlgorithms
|
||||||
|
};
|
||||||
|
|
||||||
|
SignatureDigestStatus digestAlgorithmStatuses[] = {
|
||||||
|
SignatureDigestStatus::GoodAlgorithmsOnly,
|
||||||
|
SignatureDigestStatus::WeakEECert,
|
||||||
|
SignatureDigestStatus::WeakCACert,
|
||||||
|
SignatureDigestStatus::WeakCAAndEE
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t digestAlgorithmOptionsCount = MOZ_ARRAY_LENGTH(digestAlgorithmStatuses);
|
||||||
|
|
||||||
|
static_assert(MOZ_ARRAY_LENGTH(digestAlgorithmOptions) ==
|
||||||
|
MOZ_ARRAY_LENGTH(digestAlgorithmStatuses),
|
||||||
|
"digestAlgorithm array lengths differ");
|
||||||
|
|
||||||
|
rv = Result::ERROR_UNKNOWN_ERROR;
|
||||||
|
|
||||||
#ifndef MOZ_NO_EV_CERTS
|
#ifndef MOZ_NO_EV_CERTS
|
||||||
// Try to validate for EV first.
|
// Try to validate for EV first.
|
||||||
NSSCertDBTrustDomain::OCSPFetching evOCSPFetching
|
NSSCertDBTrustDomain::OCSPFetching evOCSPFetching
|
||||||
@ -227,12 +259,15 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
CertPolicyId evPolicy;
|
CertPolicyId evPolicy;
|
||||||
SECOidTag evPolicyOidTag;
|
SECOidTag evPolicyOidTag;
|
||||||
SECStatus srv = GetFirstEVPolicy(cert, evPolicy, evPolicyOidTag);
|
SECStatus srv = GetFirstEVPolicy(cert, evPolicy, evPolicyOidTag);
|
||||||
if (srv == SECSuccess) {
|
for (size_t i=0;
|
||||||
|
i < digestAlgorithmOptionsCount && rv != Success && srv == SECSuccess;
|
||||||
|
i++) {
|
||||||
NSSCertDBTrustDomain
|
NSSCertDBTrustDomain
|
||||||
trustDomain(trustSSL, evOCSPFetching,
|
trustDomain(trustSSL, evOCSPFetching,
|
||||||
mOCSPCache, pinArg, ocspGETConfig,
|
mOCSPCache, pinArg, ocspGETConfig,
|
||||||
mCertShortLifetimeInDays, mPinningMode, MIN_RSA_BITS,
|
mCertShortLifetimeInDays, mPinningMode, MIN_RSA_BITS,
|
||||||
ValidityCheckingMode::CheckForEV, hostname, builtChain);
|
ValidityCheckingMode::CheckForEV,
|
||||||
|
digestAlgorithmOptions[i], hostname, builtChain);
|
||||||
rv = BuildCertChainForOneKeyUsage(trustDomain, certDER, time,
|
rv = BuildCertChainForOneKeyUsage(trustDomain, certDER, time,
|
||||||
KeyUsage::digitalSignature,// (EC)DHE
|
KeyUsage::digitalSignature,// (EC)DHE
|
||||||
KeyUsage::keyEncipherment, // RSA
|
KeyUsage::keyEncipherment, // RSA
|
||||||
@ -241,12 +276,19 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
evPolicy, stapledOCSPResponse,
|
evPolicy, stapledOCSPResponse,
|
||||||
ocspStaplingStatus);
|
ocspStaplingStatus);
|
||||||
if (rv == Success) {
|
if (rv == Success) {
|
||||||
|
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
|
||||||
|
("cert is EV with status %i\n", digestAlgorithmStatuses[i]));
|
||||||
if (evOidPolicy) {
|
if (evOidPolicy) {
|
||||||
*evOidPolicy = evPolicyOidTag;
|
*evOidPolicy = evPolicyOidTag;
|
||||||
}
|
}
|
||||||
break;
|
if (sigDigestStatus) {
|
||||||
|
*sigDigestStatus = digestAlgorithmStatuses[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rv == Success) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (flags & FLAG_MUST_BE_EV) {
|
if (flags & FLAG_MUST_BE_EV) {
|
||||||
@ -255,48 +297,59 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now try non-EV.
|
// Now try non-EV.
|
||||||
NSSCertDBTrustDomain trustDomain(trustSSL, defaultOCSPFetching,
|
unsigned int keySizeOptions[] = {
|
||||||
mOCSPCache, pinArg, ocspGETConfig,
|
MIN_RSA_BITS,
|
||||||
mCertShortLifetimeInDays, mPinningMode,
|
MIN_RSA_BITS_WEAK
|
||||||
MIN_RSA_BITS,
|
};
|
||||||
ValidityCheckingMode::CheckingOff,
|
|
||||||
hostname, builtChain);
|
KeySizeStatus keySizeStatuses[] = {
|
||||||
rv = BuildCertChainForOneKeyUsage(trustDomain, certDER, time,
|
KeySizeStatus::LargeMinimumSucceeded,
|
||||||
KeyUsage::digitalSignature, // (EC)DHE
|
KeySizeStatus::CompatibilityRisk
|
||||||
KeyUsage::keyEncipherment, // RSA
|
};
|
||||||
KeyUsage::keyAgreement, // (EC)DH
|
|
||||||
KeyPurposeId::id_kp_serverAuth,
|
static_assert(MOZ_ARRAY_LENGTH(keySizeOptions) ==
|
||||||
CertPolicyId::anyPolicy,
|
MOZ_ARRAY_LENGTH(keySizeStatuses),
|
||||||
stapledOCSPResponse,
|
"keySize array lengths differ");
|
||||||
ocspStaplingStatus);
|
|
||||||
if (rv == Success) {
|
size_t keySizeOptionsCount = MOZ_ARRAY_LENGTH(keySizeStatuses);
|
||||||
if (keySizeStatus) {
|
|
||||||
*keySizeStatus = KeySizeStatus::LargeMinimumSucceeded;
|
for (size_t i=0; i<keySizeOptionsCount && rv != Success; i++) {
|
||||||
|
for (size_t j=0; j<digestAlgorithmOptionsCount && rv != Success; j++) {
|
||||||
|
NSSCertDBTrustDomain trustDomain(trustSSL, defaultOCSPFetching,
|
||||||
|
mOCSPCache, pinArg, ocspGETConfig,
|
||||||
|
mCertShortLifetimeInDays,
|
||||||
|
mPinningMode, keySizeOptions[i],
|
||||||
|
ValidityCheckingMode::CheckingOff,
|
||||||
|
digestAlgorithmOptions[j],
|
||||||
|
hostname, builtChain);
|
||||||
|
rv = BuildCertChainForOneKeyUsage(trustDomain, certDER, time,
|
||||||
|
KeyUsage::digitalSignature,//(EC)DHE
|
||||||
|
KeyUsage::keyEncipherment,//RSA
|
||||||
|
KeyUsage::keyAgreement,//(EC)DH
|
||||||
|
KeyPurposeId::id_kp_serverAuth,
|
||||||
|
CertPolicyId::anyPolicy,
|
||||||
|
stapledOCSPResponse,
|
||||||
|
ocspStaplingStatus);
|
||||||
|
if (rv == Success) {
|
||||||
|
if (keySizeStatus) {
|
||||||
|
*keySizeStatus = keySizeStatuses[i];
|
||||||
|
}
|
||||||
|
if (sigDigestStatus) {
|
||||||
|
*sigDigestStatus = digestAlgorithmStatuses[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rv == Success) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If that failed, try again with a smaller minimum key size.
|
|
||||||
NSSCertDBTrustDomain trustDomainWeak(trustSSL, defaultOCSPFetching,
|
|
||||||
mOCSPCache, pinArg, ocspGETConfig,
|
|
||||||
mCertShortLifetimeInDays,
|
|
||||||
mPinningMode, MIN_RSA_BITS_WEAK,
|
|
||||||
ValidityCheckingMode::CheckingOff,
|
|
||||||
hostname, builtChain);
|
|
||||||
rv = BuildCertChainForOneKeyUsage(trustDomainWeak, certDER, time,
|
|
||||||
KeyUsage::digitalSignature, // (EC)DHE
|
|
||||||
KeyUsage::keyEncipherment, // RSA
|
|
||||||
KeyUsage::keyAgreement, // (EC)DH
|
|
||||||
KeyPurposeId::id_kp_serverAuth,
|
|
||||||
CertPolicyId::anyPolicy,
|
|
||||||
stapledOCSPResponse,
|
|
||||||
ocspStaplingStatus);
|
|
||||||
if (keySizeStatus) {
|
if (keySizeStatus) {
|
||||||
if (rv == Success) {
|
*keySizeStatus = KeySizeStatus::AlreadyBad;
|
||||||
*keySizeStatus = KeySizeStatus::CompatibilityRisk;
|
}
|
||||||
} else {
|
if (sigDigestStatus) {
|
||||||
*keySizeStatus = KeySizeStatus::AlreadyBad;
|
*sigDigestStatus = SignatureDigestStatus::AlreadyBad;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -308,7 +361,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
mCertShortLifetimeInDays,
|
mCertShortLifetimeInDays,
|
||||||
pinningDisabled, MIN_RSA_BITS_WEAK,
|
pinningDisabled, MIN_RSA_BITS_WEAK,
|
||||||
ValidityCheckingMode::CheckingOff,
|
ValidityCheckingMode::CheckingOff,
|
||||||
nullptr, builtChain);
|
AcceptAllAlgorithms, nullptr,
|
||||||
|
builtChain);
|
||||||
rv = BuildCertChain(trustDomain, certDER, time,
|
rv = BuildCertChain(trustDomain, certDER, time,
|
||||||
EndEntityOrCA::MustBeCA, KeyUsage::keyCertSign,
|
EndEntityOrCA::MustBeCA, KeyUsage::keyCertSign,
|
||||||
KeyPurposeId::id_kp_serverAuth,
|
KeyPurposeId::id_kp_serverAuth,
|
||||||
@ -322,7 +376,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
mCertShortLifetimeInDays,
|
mCertShortLifetimeInDays,
|
||||||
pinningDisabled, MIN_RSA_BITS_WEAK,
|
pinningDisabled, MIN_RSA_BITS_WEAK,
|
||||||
ValidityCheckingMode::CheckingOff,
|
ValidityCheckingMode::CheckingOff,
|
||||||
nullptr, builtChain);
|
AcceptAllAlgorithms, nullptr,
|
||||||
|
builtChain);
|
||||||
rv = BuildCertChain(trustDomain, certDER, time,
|
rv = BuildCertChain(trustDomain, certDER, time,
|
||||||
EndEntityOrCA::MustBeEndEntity,
|
EndEntityOrCA::MustBeEndEntity,
|
||||||
KeyUsage::digitalSignature,
|
KeyUsage::digitalSignature,
|
||||||
@ -347,7 +402,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
mCertShortLifetimeInDays,
|
mCertShortLifetimeInDays,
|
||||||
pinningDisabled, MIN_RSA_BITS_WEAK,
|
pinningDisabled, MIN_RSA_BITS_WEAK,
|
||||||
ValidityCheckingMode::CheckingOff,
|
ValidityCheckingMode::CheckingOff,
|
||||||
nullptr, builtChain);
|
AcceptAllAlgorithms, nullptr,
|
||||||
|
builtChain);
|
||||||
rv = BuildCertChain(trustDomain, certDER, time,
|
rv = BuildCertChain(trustDomain, certDER, time,
|
||||||
EndEntityOrCA::MustBeEndEntity,
|
EndEntityOrCA::MustBeEndEntity,
|
||||||
KeyUsage::keyEncipherment, // RSA
|
KeyUsage::keyEncipherment, // RSA
|
||||||
@ -369,7 +425,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
mCertShortLifetimeInDays,
|
mCertShortLifetimeInDays,
|
||||||
pinningDisabled, MIN_RSA_BITS_WEAK,
|
pinningDisabled, MIN_RSA_BITS_WEAK,
|
||||||
ValidityCheckingMode::CheckingOff,
|
ValidityCheckingMode::CheckingOff,
|
||||||
nullptr, builtChain);
|
AcceptAllAlgorithms, nullptr,
|
||||||
|
builtChain);
|
||||||
rv = BuildCertChain(trustDomain, certDER, time,
|
rv = BuildCertChain(trustDomain, certDER, time,
|
||||||
EndEntityOrCA::MustBeEndEntity,
|
EndEntityOrCA::MustBeEndEntity,
|
||||||
KeyUsage::digitalSignature,
|
KeyUsage::digitalSignature,
|
||||||
@ -400,7 +457,7 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
pinArg, ocspGETConfig, mCertShortLifetimeInDays,
|
pinArg, ocspGETConfig, mCertShortLifetimeInDays,
|
||||||
pinningDisabled, MIN_RSA_BITS_WEAK,
|
pinningDisabled, MIN_RSA_BITS_WEAK,
|
||||||
ValidityCheckingMode::CheckingOff,
|
ValidityCheckingMode::CheckingOff,
|
||||||
nullptr, builtChain);
|
AcceptAllAlgorithms, nullptr, builtChain);
|
||||||
rv = BuildCertChain(sslTrust, certDER, time, endEntityOrCA,
|
rv = BuildCertChain(sslTrust, certDER, time, endEntityOrCA,
|
||||||
keyUsage, eku, CertPolicyId::anyPolicy,
|
keyUsage, eku, CertPolicyId::anyPolicy,
|
||||||
stapledOCSPResponse);
|
stapledOCSPResponse);
|
||||||
@ -410,7 +467,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
mCertShortLifetimeInDays,
|
mCertShortLifetimeInDays,
|
||||||
pinningDisabled, MIN_RSA_BITS_WEAK,
|
pinningDisabled, MIN_RSA_BITS_WEAK,
|
||||||
ValidityCheckingMode::CheckingOff,
|
ValidityCheckingMode::CheckingOff,
|
||||||
nullptr, builtChain);
|
AcceptAllAlgorithms, nullptr,
|
||||||
|
builtChain);
|
||||||
rv = BuildCertChain(emailTrust, certDER, time, endEntityOrCA,
|
rv = BuildCertChain(emailTrust, certDER, time, endEntityOrCA,
|
||||||
keyUsage, eku, CertPolicyId::anyPolicy,
|
keyUsage, eku, CertPolicyId::anyPolicy,
|
||||||
stapledOCSPResponse);
|
stapledOCSPResponse);
|
||||||
@ -422,6 +480,7 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||||||
pinningDisabled,
|
pinningDisabled,
|
||||||
MIN_RSA_BITS_WEAK,
|
MIN_RSA_BITS_WEAK,
|
||||||
ValidityCheckingMode::CheckingOff,
|
ValidityCheckingMode::CheckingOff,
|
||||||
|
AcceptAllAlgorithms,
|
||||||
nullptr, builtChain);
|
nullptr, builtChain);
|
||||||
rv = BuildCertChain(objectSigningTrust, certDER, time,
|
rv = BuildCertChain(objectSigningTrust, certDER, time,
|
||||||
endEntityOrCA, keyUsage, eku,
|
endEntityOrCA, keyUsage, eku,
|
||||||
@ -455,7 +514,8 @@ CertVerifier::VerifySSLServerCert(CERTCertificate* peerCert,
|
|||||||
/*optional out*/ ScopedCERTCertList* builtChain,
|
/*optional out*/ ScopedCERTCertList* builtChain,
|
||||||
/*optional out*/ SECOidTag* evOidPolicy,
|
/*optional out*/ SECOidTag* evOidPolicy,
|
||||||
/*optional out*/ OCSPStaplingStatus* ocspStaplingStatus,
|
/*optional out*/ OCSPStaplingStatus* ocspStaplingStatus,
|
||||||
/*optional out*/ KeySizeStatus* keySizeStatus)
|
/*optional out*/ KeySizeStatus* keySizeStatus,
|
||||||
|
/*optional out*/ SignatureDigestStatus* sigDigestStatus)
|
||||||
{
|
{
|
||||||
PR_ASSERT(peerCert);
|
PR_ASSERT(peerCert);
|
||||||
// XXX: PR_ASSERT(pinarg)
|
// XXX: PR_ASSERT(pinarg)
|
||||||
@ -480,7 +540,7 @@ CertVerifier::VerifySSLServerCert(CERTCertificate* peerCert,
|
|||||||
SECStatus rv = VerifyCert(peerCert, certificateUsageSSLServer, time, pinarg,
|
SECStatus rv = VerifyCert(peerCert, certificateUsageSSLServer, time, pinarg,
|
||||||
hostname, flags, stapledOCSPResponse,
|
hostname, flags, stapledOCSPResponse,
|
||||||
&builtChainTemp, evOidPolicy, ocspStaplingStatus,
|
&builtChainTemp, evOidPolicy, ocspStaplingStatus,
|
||||||
keySizeStatus);
|
keySizeStatus, sigDigestStatus);
|
||||||
if (rv != SECSuccess) {
|
if (rv != SECSuccess) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,16 @@ enum class KeySizeStatus {
|
|||||||
AlreadyBad = 3,
|
AlreadyBad = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// These values correspond to the CERT_CHAIN_SIGNATURE_DIGEST telemetry.
|
||||||
|
enum class SignatureDigestStatus {
|
||||||
|
NeverChecked = 0,
|
||||||
|
GoodAlgorithmsOnly = 1,
|
||||||
|
WeakEECert = 2,
|
||||||
|
WeakCACert = 3,
|
||||||
|
WeakCAAndEE = 4,
|
||||||
|
AlreadyBad = 5,
|
||||||
|
};
|
||||||
|
|
||||||
class CertVerifier
|
class CertVerifier
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -51,7 +61,8 @@ public:
|
|||||||
/*optional out*/ ScopedCERTCertList* builtChain = nullptr,
|
/*optional out*/ ScopedCERTCertList* builtChain = nullptr,
|
||||||
/*optional out*/ SECOidTag* evOidPolicy = nullptr,
|
/*optional out*/ SECOidTag* evOidPolicy = nullptr,
|
||||||
/*optional out*/ OCSPStaplingStatus* ocspStaplingStatus = nullptr,
|
/*optional out*/ OCSPStaplingStatus* ocspStaplingStatus = nullptr,
|
||||||
/*optional out*/ KeySizeStatus* keySizeStatus = nullptr);
|
/*optional out*/ KeySizeStatus* keySizeStatus = nullptr,
|
||||||
|
/*optional out*/ SignatureDigestStatus* sigDigestStatus = nullptr);
|
||||||
|
|
||||||
SECStatus VerifySSLServerCert(
|
SECStatus VerifySSLServerCert(
|
||||||
CERTCertificate* peerCert,
|
CERTCertificate* peerCert,
|
||||||
@ -64,7 +75,8 @@ public:
|
|||||||
/*optional out*/ ScopedCERTCertList* builtChain = nullptr,
|
/*optional out*/ ScopedCERTCertList* builtChain = nullptr,
|
||||||
/*optional out*/ SECOidTag* evOidPolicy = nullptr,
|
/*optional out*/ SECOidTag* evOidPolicy = nullptr,
|
||||||
/*optional out*/ OCSPStaplingStatus* ocspStaplingStatus = nullptr,
|
/*optional out*/ OCSPStaplingStatus* ocspStaplingStatus = nullptr,
|
||||||
/*optional out*/ KeySizeStatus* keySizeStatus = nullptr);
|
/*optional out*/ KeySizeStatus* keySizeStatus = nullptr,
|
||||||
|
/*optional out*/ SignatureDigestStatus* sigDigestStatus = nullptr);
|
||||||
|
|
||||||
enum PinningMode {
|
enum PinningMode {
|
||||||
pinningDisabled = 0,
|
pinningDisabled = 0,
|
||||||
|
@ -49,6 +49,7 @@ NSSCertDBTrustDomain::NSSCertDBTrustDomain(SECTrustType certDBTrustType,
|
|||||||
CertVerifier::PinningMode pinningMode,
|
CertVerifier::PinningMode pinningMode,
|
||||||
unsigned int minRSABits,
|
unsigned int minRSABits,
|
||||||
ValidityCheckingMode validityCheckingMode,
|
ValidityCheckingMode validityCheckingMode,
|
||||||
|
SignatureDigestOption signatureDigestOption,
|
||||||
/*optional*/ const char* hostname,
|
/*optional*/ const char* hostname,
|
||||||
/*optional*/ ScopedCERTCertList* builtChain)
|
/*optional*/ ScopedCERTCertList* builtChain)
|
||||||
: mCertDBTrustType(certDBTrustType)
|
: mCertDBTrustType(certDBTrustType)
|
||||||
@ -60,6 +61,7 @@ NSSCertDBTrustDomain::NSSCertDBTrustDomain(SECTrustType certDBTrustType,
|
|||||||
, mPinningMode(pinningMode)
|
, mPinningMode(pinningMode)
|
||||||
, mMinRSABits(minRSABits)
|
, mMinRSABits(minRSABits)
|
||||||
, mValidityCheckingMode(validityCheckingMode)
|
, mValidityCheckingMode(validityCheckingMode)
|
||||||
|
, mSignatureDigestOption(signatureDigestOption)
|
||||||
, mHostname(hostname)
|
, mHostname(hostname)
|
||||||
, mBuiltChain(builtChain)
|
, mBuiltChain(builtChain)
|
||||||
, mCertBlocklist(do_GetService(NS_CERTBLOCKLIST_CONTRACTID))
|
, mCertBlocklist(do_GetService(NS_CERTBLOCKLIST_CONTRACTID))
|
||||||
@ -796,8 +798,28 @@ NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result
|
Result
|
||||||
NSSCertDBTrustDomain::CheckSignatureDigestAlgorithm(DigestAlgorithm)
|
NSSCertDBTrustDomain::CheckSignatureDigestAlgorithm(DigestAlgorithm aAlg,
|
||||||
|
EndEntityOrCA endEntityOrCA)
|
||||||
{
|
{
|
||||||
|
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
|
||||||
|
("NSSCertDBTrustDomain: CheckSignatureDigestAlgorithm"));
|
||||||
|
if (aAlg == DigestAlgorithm::sha1) {
|
||||||
|
if (mSignatureDigestOption == DisableSHA1Everywhere) {
|
||||||
|
return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endEntityOrCA == EndEntityOrCA::MustBeCA) {
|
||||||
|
MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("CA cert is SHA1"));
|
||||||
|
return mSignatureDigestOption == DisableSHA1ForCA
|
||||||
|
? Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
|
||||||
|
: Success;
|
||||||
|
} else {
|
||||||
|
MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("EE cert is SHA1"));
|
||||||
|
return mSignatureDigestOption == DisableSHA1ForEE
|
||||||
|
? Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
|
||||||
|
: Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,13 @@ char* DefaultServerNicknameForCert(CERTCertificate* cert);
|
|||||||
|
|
||||||
void SaveIntermediateCerts(const ScopedCERTCertList& certList);
|
void SaveIntermediateCerts(const ScopedCERTCertList& certList);
|
||||||
|
|
||||||
|
enum SignatureDigestOption {
|
||||||
|
AcceptAllAlgorithms,
|
||||||
|
DisableSHA1ForEE,
|
||||||
|
DisableSHA1ForCA,
|
||||||
|
DisableSHA1Everywhere,
|
||||||
|
};
|
||||||
|
|
||||||
class NSSCertDBTrustDomain : public mozilla::pkix::TrustDomain
|
class NSSCertDBTrustDomain : public mozilla::pkix::TrustDomain
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -62,6 +69,7 @@ public:
|
|||||||
CertVerifier::PinningMode pinningMode,
|
CertVerifier::PinningMode pinningMode,
|
||||||
unsigned int minRSABits,
|
unsigned int minRSABits,
|
||||||
ValidityCheckingMode validityCheckingMode,
|
ValidityCheckingMode validityCheckingMode,
|
||||||
|
SignatureDigestOption,
|
||||||
/*optional*/ const char* hostname = nullptr,
|
/*optional*/ const char* hostname = nullptr,
|
||||||
/*optional out*/ ScopedCERTCertList* builtChain = nullptr);
|
/*optional out*/ ScopedCERTCertList* builtChain = nullptr);
|
||||||
|
|
||||||
@ -76,7 +84,8 @@ public:
|
|||||||
override;
|
override;
|
||||||
|
|
||||||
virtual Result CheckSignatureDigestAlgorithm(
|
virtual Result CheckSignatureDigestAlgorithm(
|
||||||
mozilla::pkix::DigestAlgorithm digestAlg) override;
|
mozilla::pkix::DigestAlgorithm digestAlg,
|
||||||
|
mozilla::pkix::EndEntityOrCA endEntityOrCA) override;
|
||||||
|
|
||||||
virtual Result CheckRSAPublicKeyModulusSizeInBits(
|
virtual Result CheckRSAPublicKeyModulusSizeInBits(
|
||||||
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
||||||
@ -144,6 +153,7 @@ private:
|
|||||||
CertVerifier::PinningMode mPinningMode;
|
CertVerifier::PinningMode mPinningMode;
|
||||||
const unsigned int mMinRSABits;
|
const unsigned int mMinRSABits;
|
||||||
ValidityCheckingMode mValidityCheckingMode;
|
ValidityCheckingMode mValidityCheckingMode;
|
||||||
|
SignatureDigestOption mSignatureDigestOption;
|
||||||
const char* mHostname; // non-owning - only used for pinning checks
|
const char* mHostname; // non-owning - only used for pinning checks
|
||||||
ScopedCERTCertList* mBuiltChain; // non-owning
|
ScopedCERTCertList* mBuiltChain; // non-owning
|
||||||
nsCOMPtr<nsICertBlocklist> mCertBlocklist;
|
nsCOMPtr<nsICertBlocklist> mCertBlocklist;
|
||||||
|
@ -1177,13 +1177,14 @@ AuthCertificate(CertVerifier& certVerifier,
|
|||||||
CertVerifier::OCSPStaplingStatus ocspStaplingStatus =
|
CertVerifier::OCSPStaplingStatus ocspStaplingStatus =
|
||||||
CertVerifier::OCSP_STAPLING_NEVER_CHECKED;
|
CertVerifier::OCSP_STAPLING_NEVER_CHECKED;
|
||||||
KeySizeStatus keySizeStatus = KeySizeStatus::NeverChecked;
|
KeySizeStatus keySizeStatus = KeySizeStatus::NeverChecked;
|
||||||
|
SignatureDigestStatus sigDigestStatus = SignatureDigestStatus::NeverChecked;
|
||||||
|
|
||||||
rv = certVerifier.VerifySSLServerCert(cert, stapledOCSPResponse,
|
rv = certVerifier.VerifySSLServerCert(cert, stapledOCSPResponse,
|
||||||
time, infoObject,
|
time, infoObject,
|
||||||
infoObject->GetHostNameRaw(),
|
infoObject->GetHostNameRaw(),
|
||||||
saveIntermediates, 0, &certList,
|
saveIntermediates, 0, &certList,
|
||||||
&evOidPolicy, &ocspStaplingStatus,
|
&evOidPolicy, &ocspStaplingStatus,
|
||||||
&keySizeStatus);
|
&keySizeStatus, &sigDigestStatus);
|
||||||
PRErrorCode savedErrorCode;
|
PRErrorCode savedErrorCode;
|
||||||
if (rv != SECSuccess) {
|
if (rv != SECSuccess) {
|
||||||
savedErrorCode = PR_GetError();
|
savedErrorCode = PR_GetError();
|
||||||
@ -1196,6 +1197,10 @@ AuthCertificate(CertVerifier& certVerifier,
|
|||||||
Telemetry::Accumulate(Telemetry::CERT_CHAIN_KEY_SIZE_STATUS,
|
Telemetry::Accumulate(Telemetry::CERT_CHAIN_KEY_SIZE_STATUS,
|
||||||
static_cast<uint32_t>(keySizeStatus));
|
static_cast<uint32_t>(keySizeStatus));
|
||||||
}
|
}
|
||||||
|
if (sigDigestStatus != SignatureDigestStatus::NeverChecked) {
|
||||||
|
Telemetry::Accumulate(Telemetry::CERT_CHAIN_SIGNATURE_DIGEST_STATUS,
|
||||||
|
static_cast<uint32_t>(sigDigestStatus));
|
||||||
|
}
|
||||||
|
|
||||||
// We want to remember the CA certs in the temp db, so that the application can find the
|
// We want to remember the CA certs in the temp db, so that the application can find the
|
||||||
// complete chain at any time it might need it.
|
// complete chain at any time it might need it.
|
||||||
|
@ -277,7 +277,8 @@ public:
|
|||||||
// Return Success if the algorithm is acceptable,
|
// Return Success if the algorithm is acceptable,
|
||||||
// Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED if the algorithm is not
|
// Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED if the algorithm is not
|
||||||
// acceptable, or another error code if another error occurred.
|
// acceptable, or another error code if another error occurred.
|
||||||
virtual Result CheckSignatureDigestAlgorithm(DigestAlgorithm digestAlg) = 0;
|
virtual Result CheckSignatureDigestAlgorithm(DigestAlgorithm digestAlg,
|
||||||
|
EndEntityOrCA endEntityOrCA) = 0;
|
||||||
|
|
||||||
// Check that the RSA public key size is acceptable.
|
// Check that the RSA public key size is acceptable.
|
||||||
//
|
//
|
||||||
|
@ -91,7 +91,7 @@ CheckSignatureAlgorithm(TrustDomain& trustDomain,
|
|||||||
// more generally it short-circuits any path building with them (which, of
|
// more generally it short-circuits any path building with them (which, of
|
||||||
// course, is even slower).
|
// course, is even slower).
|
||||||
|
|
||||||
rv = trustDomain.CheckSignatureDigestAlgorithm(digestAlg);
|
rv = trustDomain.CheckSignatureDigestAlgorithm(digestAlg, endEntityOrCA);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -203,7 +203,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CheckSignatureDigestAlgorithm(DigestAlgorithm) override
|
Result CheckSignatureDigestAlgorithm(DigestAlgorithm, EndEntityOrCA) override
|
||||||
{
|
{
|
||||||
checkedDigestAlgorithm = true;
|
checkedDigestAlgorithm = true;
|
||||||
return Success;
|
return Success;
|
||||||
|
@ -125,7 +125,8 @@ public:
|
|||||||
Result::FATAL_ERROR_LIBRARY_FAILURE);
|
Result::FATAL_ERROR_LIBRARY_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CheckSignatureDigestAlgorithm(DigestAlgorithm) override
|
Result CheckSignatureDigestAlgorithm(DigestAlgorithm,
|
||||||
|
EndEntityOrCA) override
|
||||||
{
|
{
|
||||||
ADD_FAILURE();
|
ADD_FAILURE();
|
||||||
return NotReached("CheckSignatureDigestAlgorithm should not be called",
|
return NotReached("CheckSignatureDigestAlgorithm should not be called",
|
||||||
@ -178,7 +179,7 @@ class DefaultCryptoTrustDomain : public EverythingFailsByDefaultTrustDomain
|
|||||||
return TestDigestBuf(item, digestAlg, digestBuf, digestBufLen);
|
return TestDigestBuf(item, digestAlg, digestBuf, digestBufLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CheckSignatureDigestAlgorithm(DigestAlgorithm) override
|
Result CheckSignatureDigestAlgorithm(DigestAlgorithm, EndEntityOrCA) override
|
||||||
{
|
{
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
@ -7502,6 +7502,12 @@
|
|||||||
"n_values": 4,
|
"n_values": 4,
|
||||||
"description": "Does enforcing a larger minimum RSA key size cause verification failures? 1 = no, 2 = yes, 3 = another error prevented finding a verified chain"
|
"description": "Does enforcing a larger minimum RSA key size cause verification failures? 1 = no, 2 = yes, 3 = another error prevented finding a verified chain"
|
||||||
},
|
},
|
||||||
|
"CERT_CHAIN_SIGNATURE_DIGEST_STATUS": {
|
||||||
|
"expires_in_version": "default",
|
||||||
|
"kind": "enumerated",
|
||||||
|
"n_values": 6,
|
||||||
|
"description": "Information on weak signature digest algorithms in the chain: 1 = Only good algorithms, 2 = a weak algorithm was present in an end entity, 3 = a weak algorithm was present in a CA cert, 4 = a weak algorithm was present in both EE and CA certs, 5 = another error prevented signature algorithm from being determined"
|
||||||
|
},
|
||||||
"WEAVE_CONFIGURED": {
|
"WEAVE_CONFIGURED": {
|
||||||
"expires_in_version": "default",
|
"expires_in_version": "default",
|
||||||
"kind": "boolean",
|
"kind": "boolean",
|
||||||
|
Loading…
Reference in New Issue
Block a user