1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
10 #include "BRNameMatchingPolicy.h"
11 #include "CTPolicyEnforcer.h"
12 #include "CTVerifyResult.h"
13 #include "EnterpriseRoots.h"
14 #include "OCSPCache.h"
15 #include "RootCertificateTelemetryUtils.h"
16 #include "ScopedNSSTypes.h"
17 #include "mozilla/Telemetry.h"
18 #include "mozilla/TimeStamp.h"
19 #include "mozilla/UniquePtr.h"
21 #include "mozpkix/pkixtypes.h"
25 # pragma warning(push)
26 // Silence "RootingAPI.h(718): warning C4324: 'js::DispatchWrapper<T>':
27 // structure was padded due to alignment specifier with [ T=void * ]"
28 # pragma warning(disable : 4324)
29 #endif /* defined(_MSC_VER) */
30 #include "mozilla/BasePrincipal.h"
32 # pragma warning(pop) /* popping the pragma in this file */
33 #endif /* defined(_MSC_VER) */
38 // Including the headers of the classes below would bring along all of their
39 // dependent headers and force us to export them in moz.build.
40 // Just forward-declare the classes here instead.
41 class MultiLogCTVerifier
;
42 class CTDiversityPolicy
;
45 } // namespace mozilla
50 typedef mozilla::pkix::Result Result
;
52 // These values correspond to the CERT_CHAIN_KEY_SIZE_STATUS telemetry.
53 enum class KeySizeStatus
{
55 LargeMinimumSucceeded
= 1,
56 CompatibilityRisk
= 2,
60 // These values correspond to the CERT_CHAIN_SHA1_POLICY_STATUS telemetry.
61 enum class SHA1ModeResult
{
63 SucceededWithoutSHA1
= 1,
64 SucceededWithImportedRoot
= 2,
65 SucceededWithImportedRootOrSHA1Before2016
= 3,
66 SucceededWithSHA1
= 4,
70 enum class CRLiteMode
{
76 enum class NetscapeStepUpPolicy
: uint32_t;
78 class PinningTelemetryInfo
{
80 PinningTelemetryInfo()
81 : certPinningResultBucket(0), rootBucket(ROOT_CERTIFICATE_UNKNOWN
) {
85 // Should we accumulate pinning telemetry for the result?
86 bool accumulateResult
;
87 Maybe
<Telemetry::HistogramID
> certPinningResultHistogram
;
88 int32_t certPinningResultBucket
;
89 // Should we accumulate telemetry for the root?
90 bool accumulateForRoot
;
94 accumulateForRoot
= false;
95 accumulateResult
= false;
99 class CertificateTransparencyInfo
{
101 CertificateTransparencyInfo()
103 policyCompliance(mozilla::ct::CTPolicyCompliance::Unknown
) {
109 // Verification result of the processed SCTs.
110 mozilla::ct::CTVerifyResult verifyResult
;
111 // Connection compliance to the CT Policy.
112 mozilla::ct::CTPolicyCompliance policyCompliance
;
117 class DelegatedCredentialInfo
{
119 DelegatedCredentialInfo() : scheme(ssl_sig_none
), authKeyBits(0) {}
120 DelegatedCredentialInfo(SSLSignatureScheme scheme
, uint32_t authKeyBits
)
121 : scheme(scheme
), authKeyBits(authKeyBits
) {}
123 // The signature scheme to be used in CertVerify. This tells us
124 // whether to interpret |authKeyBits| in an RSA or ECDSA context.
125 SSLSignatureScheme scheme
;
127 // The size of the key, in bits.
128 uint32_t authKeyBits
;
131 enum class CRLiteLookupResult
{
133 FilterNotAvailable
= 1,
134 IssuerNotEnrolled
= 2,
135 CertificateTooNew
= 3,
136 CertificateValid
= 4,
137 CertificateRevoked
= 5,
139 CertRevokedByStash
= 7,
142 class NSSCertDBTrustDomain
;
146 typedef unsigned int Flags
;
147 // XXX: FLAG_LOCAL_ONLY is ignored in the classic verification case
148 static const Flags FLAG_LOCAL_ONLY
;
149 // Don't perform fallback DV validation on EV validation failure.
150 static const Flags FLAG_MUST_BE_EV
;
151 // TLS feature request_status should be ignored
152 static const Flags FLAG_TLS_IGNORE_STATUS_REQUEST
;
154 // These values correspond to the SSL_OCSP_STAPLING telemetry.
155 enum OCSPStaplingStatus
{
156 OCSP_STAPLING_NEVER_CHECKED
= 0,
157 OCSP_STAPLING_GOOD
= 1,
158 OCSP_STAPLING_NONE
= 2,
159 OCSP_STAPLING_EXPIRED
= 3,
160 OCSP_STAPLING_INVALID
= 4,
163 // *evOidPolicy == SEC_OID_UNKNOWN means the cert is NOT EV
164 // Only one usage per verification is supported.
165 mozilla::pkix::Result
VerifyCert(
166 CERTCertificate
* cert
, SECCertificateUsage usage
,
167 mozilla::pkix::Time time
, void* pinArg
, const char* hostname
,
168 /*out*/ UniqueCERTCertList
& builtChain
, Flags flags
= 0,
170 const Maybe
<nsTArray
<nsTArray
<uint8_t>>>& extraCertificates
= Nothing(),
171 /*optional in*/ const Maybe
<nsTArray
<uint8_t>>& stapledOCSPResponseArg
=
173 /*optional in*/ const Maybe
<nsTArray
<uint8_t>>& sctsFromTLS
= Nothing(),
174 /*optional in*/ const OriginAttributes
& originAttributes
=
176 /*optional out*/ SECOidTag
* evOidPolicy
= nullptr,
177 /*optional out*/ OCSPStaplingStatus
* ocspStaplingStatus
= nullptr,
178 /*optional out*/ KeySizeStatus
* keySizeStatus
= nullptr,
179 /*optional out*/ SHA1ModeResult
* sha1ModeResult
= nullptr,
180 /*optional out*/ PinningTelemetryInfo
* pinningTelemetryInfo
= nullptr,
181 /*optional out*/ CertificateTransparencyInfo
* ctInfo
= nullptr,
182 /*optional out*/ CRLiteLookupResult
* crliteLookupResult
= nullptr);
184 mozilla::pkix::Result
VerifySSLServerCert(
185 const UniqueCERTCertificate
& peerCert
, mozilla::pkix::Time time
,
186 void* pinarg
, const nsACString
& hostname
,
187 /*out*/ UniqueCERTCertList
& builtChain
,
188 /*optional*/ Flags flags
= 0,
189 /*optional*/ const Maybe
<nsTArray
<nsTArray
<uint8_t>>>& extraCertificates
=
191 /*optional*/ const Maybe
<nsTArray
<uint8_t>>& stapledOCSPResponse
=
193 /*optional*/ const Maybe
<nsTArray
<uint8_t>>& sctsFromTLS
= Nothing(),
194 /*optional*/ const Maybe
<DelegatedCredentialInfo
>& dcInfo
= Nothing(),
195 /*optional*/ const OriginAttributes
& originAttributes
=
197 /*optional out*/ SECOidTag
* evOidPolicy
= nullptr,
198 /*optional out*/ OCSPStaplingStatus
* ocspStaplingStatus
= nullptr,
199 /*optional out*/ KeySizeStatus
* keySizeStatus
= nullptr,
200 /*optional out*/ SHA1ModeResult
* sha1ModeResult
= nullptr,
201 /*optional out*/ PinningTelemetryInfo
* pinningTelemetryInfo
= nullptr,
202 /*optional out*/ CertificateTransparencyInfo
* ctInfo
= nullptr,
203 /*optional out*/ CRLiteLookupResult
* crliteLookupResult
= nullptr,
204 /*optional out*/ bool* isBuiltCertChainRootBuiltInRoot
= nullptr);
208 pinningAllowUserCAMITM
= 1,
210 pinningEnforceTestMode
= 3
213 enum class SHA1Mode
{
216 // There used to be a policy that only allowed SHA1 for certificates issued
217 // before 2016. This is no longer available. If a user has selected this
218 // policy in about:config, it now maps to Forbidden.
219 UsedToBeBefore2016ButNowIsForbidden
= 2,
221 ImportedRootOrBefore2016
= 4,
224 enum OcspDownloadConfig
{ ocspOff
= 0, ocspOn
= 1, ocspEVOnly
= 2 };
225 enum OcspStrictConfig
{ ocspRelaxed
= 0, ocspStrict
};
227 enum class CertificateTransparencyMode
{
232 CertVerifier(OcspDownloadConfig odc
, OcspStrictConfig osc
,
233 mozilla::TimeDuration ocspTimeoutSoft
,
234 mozilla::TimeDuration ocspTimeoutHard
,
235 uint32_t certShortLifetimeInDays
, PinningMode pinningMode
,
236 SHA1Mode sha1Mode
, BRNameMatchingPolicy::Mode nameMatchingMode
,
237 NetscapeStepUpPolicy netscapeStepUpPolicy
,
238 CertificateTransparencyMode ctMode
, CRLiteMode crliteMode
,
239 uint64_t crliteCTMergeDelaySeconds
,
240 const Vector
<EnterpriseCert
>& thirdPartyCerts
);
243 void ClearOCSPCache() { mOCSPCache
.Clear(); }
245 const OcspDownloadConfig mOCSPDownloadConfig
;
246 const bool mOCSPStrict
;
247 const mozilla::TimeDuration mOCSPTimeoutSoft
;
248 const mozilla::TimeDuration mOCSPTimeoutHard
;
249 const uint32_t mCertShortLifetimeInDays
;
250 const PinningMode mPinningMode
;
251 const SHA1Mode mSHA1Mode
;
252 const BRNameMatchingPolicy::Mode mNameMatchingMode
;
253 const NetscapeStepUpPolicy mNetscapeStepUpPolicy
;
254 const CertificateTransparencyMode mCTMode
;
255 const CRLiteMode mCRLiteMode
;
256 const uint64_t mCRLiteCTMergeDelaySeconds
;
259 OCSPCache mOCSPCache
;
260 // We keep a copy of the bytes of each third party root to own.
261 Vector
<EnterpriseCert
> mThirdPartyCerts
;
262 // This is a reusable, precomputed list of Inputs corresponding to each root
263 // in mThirdPartyCerts that wasn't too long to make an Input out of.
264 Vector
<mozilla::pkix::Input
> mThirdPartyRootInputs
;
265 // Similarly, but with intermediates.
266 Vector
<mozilla::pkix::Input
> mThirdPartyIntermediateInputs
;
268 // We only have a forward declarations of these classes (see above)
269 // so we must allocate dynamically.
270 UniquePtr
<mozilla::ct::MultiLogCTVerifier
> mCTVerifier
;
271 UniquePtr
<mozilla::ct::CTDiversityPolicy
> mCTDiversityPolicy
;
273 void LoadKnownCTLogs();
274 mozilla::pkix::Result
VerifyCertificateTransparencyPolicy(
275 NSSCertDBTrustDomain
& trustDomain
, const UniqueCERTCertList
& builtChain
,
276 mozilla::pkix::Input sctsFromTLS
, mozilla::pkix::Time time
,
277 /*optional out*/ CertificateTransparencyInfo
* ctInfo
);
279 // Returns true if the configured SHA1 mode is more restrictive than the given
280 // mode. SHA1Mode::Forbidden is more restrictive than any other mode except
281 // Forbidden. Next is ImportedRoot, then ImportedRootOrBefore2016, then
282 // Allowed. (A mode is never more restrictive than itself.)
283 bool SHA1ModeMoreRestrictiveThanGivenMode(SHA1Mode mode
);
286 mozilla::pkix::Result
IsCertBuiltInRoot(CERTCertificate
* cert
, bool& result
);
287 mozilla::pkix::Result
CertListContainsExpectedKeys(
288 const CERTCertList
* certList
, const char* hostname
,
289 mozilla::pkix::Time time
, CertVerifier::PinningMode pinningMode
);
292 } // namespace mozilla
294 #endif // CertVerifier_h