Line data Source code
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/. */
6 :
7 : #ifndef CertVerifier_h
8 : #define CertVerifier_h
9 :
10 : #include "BRNameMatchingPolicy.h"
11 : #include "CTPolicyEnforcer.h"
12 : #include "CTVerifyResult.h"
13 : #include "OCSPCache.h"
14 : #include "ScopedNSSTypes.h"
15 : #include "mozilla/Telemetry.h"
16 : #include "mozilla/TimeStamp.h"
17 : #include "mozilla/UniquePtr.h"
18 : #include "nsString.h"
19 : #include "pkix/pkixtypes.h"
20 :
21 : #if defined(_MSC_VER)
22 : #pragma warning(push)
23 : // Silence "RootingAPI.h(718): warning C4324: 'js::DispatchWrapper<T>':
24 : // structure was padded due to alignment specifier with [ T=void * ]"
25 : #pragma warning(disable:4324)
26 : #endif /* defined(_MSC_VER) */
27 : #include "mozilla/BasePrincipal.h"
28 : #if defined(_MSC_VER)
29 : #pragma warning(pop) /* popping the pragma in this file */
30 : #endif /* defined(_MSC_VER) */
31 :
32 : namespace mozilla { namespace ct {
33 :
34 : // Including the headers of the classes below would bring along all of their
35 : // dependent headers and force us to export them in moz.build.
36 : // Just forward-declare the classes here instead.
37 : class MultiLogCTVerifier;
38 : class CTDiversityPolicy;
39 :
40 : } } // namespace mozilla::ct
41 :
42 : namespace mozilla { namespace psm {
43 :
44 : typedef mozilla::pkix::Result Result;
45 :
46 : // These values correspond to the CERT_CHAIN_KEY_SIZE_STATUS telemetry.
47 : enum class KeySizeStatus {
48 : NeverChecked = 0,
49 : LargeMinimumSucceeded = 1,
50 : CompatibilityRisk = 2,
51 : AlreadyBad = 3,
52 : };
53 :
54 : // These values correspond to the CERT_CHAIN_SHA1_POLICY_STATUS telemetry.
55 : enum class SHA1ModeResult {
56 : NeverChecked = 0,
57 : SucceededWithoutSHA1 = 1,
58 : SucceededWithImportedRoot = 2,
59 : SucceededWithImportedRootOrSHA1Before2016 = 3,
60 : SucceededWithSHA1 = 4,
61 : Failed = 5,
62 : };
63 :
64 : enum class NetscapeStepUpPolicy : uint32_t;
65 :
66 : class PinningTelemetryInfo
67 : {
68 : public:
69 0 : PinningTelemetryInfo() { Reset(); }
70 :
71 : // Should we accumulate pinning telemetry for the result?
72 : bool accumulateResult;
73 : Telemetry::HistogramID certPinningResultHistogram;
74 : int32_t certPinningResultBucket;
75 : // Should we accumulate telemetry for the root?
76 : bool accumulateForRoot;
77 : int32_t rootBucket;
78 :
79 0 : void Reset() { accumulateForRoot = false; accumulateResult = false; }
80 : };
81 :
82 0 : class CertificateTransparencyInfo
83 : {
84 : public:
85 0 : CertificateTransparencyInfo() { Reset(); }
86 :
87 : // Was CT enabled?
88 : bool enabled;
89 : // Verification result of the processed SCTs.
90 : mozilla::ct::CTVerifyResult verifyResult;
91 : // Connection compliance to the CT Policy.
92 : mozilla::ct::CTPolicyCompliance policyCompliance;
93 :
94 : void Reset();
95 : };
96 :
97 : class NSSCertDBTrustDomain;
98 :
99 : class CertVerifier
100 : {
101 : public:
102 : typedef unsigned int Flags;
103 : // XXX: FLAG_LOCAL_ONLY is ignored in the classic verification case
104 : static const Flags FLAG_LOCAL_ONLY;
105 : // Don't perform fallback DV validation on EV validation failure.
106 : static const Flags FLAG_MUST_BE_EV;
107 : // TLS feature request_status should be ignored
108 : static const Flags FLAG_TLS_IGNORE_STATUS_REQUEST;
109 :
110 : // These values correspond to the SSL_OCSP_STAPLING telemetry.
111 : enum OCSPStaplingStatus {
112 : OCSP_STAPLING_NEVER_CHECKED = 0,
113 : OCSP_STAPLING_GOOD = 1,
114 : OCSP_STAPLING_NONE = 2,
115 : OCSP_STAPLING_EXPIRED = 3,
116 : OCSP_STAPLING_INVALID = 4,
117 : };
118 :
119 : // As an optimization, a pointer to the certificate chain sent by the peer
120 : // may be specified as peerCertChain. This can prevent NSSCertDBTrustDomain
121 : // from calling CERT_CreateSubjectCertList to find potential issuers, which
122 : // can be expensive.
123 : //
124 : // *evOidPolicy == SEC_OID_UNKNOWN means the cert is NOT EV
125 : // Only one usage per verification is supported.
126 : mozilla::pkix::Result VerifyCert(
127 : CERTCertificate* cert,
128 : SECCertificateUsage usage,
129 : mozilla::pkix::Time time,
130 : void* pinArg,
131 : const char* hostname,
132 : /*out*/ UniqueCERTCertList& builtChain,
133 : /*optional in*/ UniqueCERTCertList* peerCertChain = nullptr,
134 : /*optional in*/ Flags flags = 0,
135 : /*optional in*/ const SECItem* stapledOCSPResponse = nullptr,
136 : /*optional in*/ const SECItem* sctsFromTLS = nullptr,
137 : /*optional in*/ const OriginAttributes& originAttributes =
138 : OriginAttributes(),
139 : /*optional out*/ SECOidTag* evOidPolicy = nullptr,
140 : /*optional out*/ OCSPStaplingStatus* ocspStaplingStatus = nullptr,
141 : /*optional out*/ KeySizeStatus* keySizeStatus = nullptr,
142 : /*optional out*/ SHA1ModeResult* sha1ModeResult = nullptr,
143 : /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo = nullptr,
144 : /*optional out*/ CertificateTransparencyInfo* ctInfo = nullptr);
145 :
146 : mozilla::pkix::Result VerifySSLServerCert(
147 : const UniqueCERTCertificate& peerCert,
148 : /*optional*/ const SECItem* stapledOCSPResponse,
149 : /*optional*/ const SECItem* sctsFromTLS,
150 : mozilla::pkix::Time time,
151 : /*optional*/ void* pinarg,
152 : const nsACString& hostname,
153 : /*out*/ UniqueCERTCertList& builtChain,
154 : /*optional*/ UniqueCERTCertList* peerCertChain = nullptr,
155 : /*optional*/ bool saveIntermediatesInPermanentDatabase = false,
156 : /*optional*/ Flags flags = 0,
157 : /*optional*/ const OriginAttributes& originAttributes =
158 : OriginAttributes(),
159 : /*optional out*/ SECOidTag* evOidPolicy = nullptr,
160 : /*optional out*/ OCSPStaplingStatus* ocspStaplingStatus = nullptr,
161 : /*optional out*/ KeySizeStatus* keySizeStatus = nullptr,
162 : /*optional out*/ SHA1ModeResult* sha1ModeResult = nullptr,
163 : /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo = nullptr,
164 : /*optional out*/ CertificateTransparencyInfo* ctInfo = nullptr);
165 :
166 : enum PinningMode {
167 : pinningDisabled = 0,
168 : pinningAllowUserCAMITM = 1,
169 : pinningStrict = 2,
170 : pinningEnforceTestMode = 3
171 : };
172 :
173 : enum class SHA1Mode {
174 : Allowed = 0,
175 : Forbidden = 1,
176 : // There used to be a policy that only allowed SHA1 for certificates issued
177 : // before 2016. This is no longer available. If a user has selected this
178 : // policy in about:config, it now maps to Forbidden.
179 : UsedToBeBefore2016ButNowIsForbidden = 2,
180 : ImportedRoot = 3,
181 : ImportedRootOrBefore2016 = 4,
182 : };
183 :
184 : enum OcspDownloadConfig {
185 : ocspOff = 0,
186 : ocspOn = 1,
187 : ocspEVOnly = 2
188 : };
189 : enum OcspStrictConfig { ocspRelaxed = 0, ocspStrict };
190 : enum OcspGetConfig { ocspGetDisabled = 0, ocspGetEnabled = 1 };
191 :
192 : enum class CertificateTransparencyMode {
193 : Disabled = 0,
194 : TelemetryOnly = 1,
195 : };
196 :
197 : CertVerifier(OcspDownloadConfig odc, OcspStrictConfig osc, OcspGetConfig ogc,
198 : mozilla::TimeDuration ocspTimeoutSoft,
199 : mozilla::TimeDuration ocspTimeoutHard,
200 : uint32_t certShortLifetimeInDays,
201 : PinningMode pinningMode, SHA1Mode sha1Mode,
202 : BRNameMatchingPolicy::Mode nameMatchingMode,
203 : NetscapeStepUpPolicy netscapeStepUpPolicy,
204 : CertificateTransparencyMode ctMode);
205 : ~CertVerifier();
206 :
207 0 : void ClearOCSPCache() { mOCSPCache.Clear(); }
208 :
209 : const OcspDownloadConfig mOCSPDownloadConfig;
210 : const bool mOCSPStrict;
211 : const bool mOCSPGETEnabled;
212 : const mozilla::TimeDuration mOCSPTimeoutSoft;
213 : const mozilla::TimeDuration mOCSPTimeoutHard;
214 : const uint32_t mCertShortLifetimeInDays;
215 : const PinningMode mPinningMode;
216 : const SHA1Mode mSHA1Mode;
217 : const BRNameMatchingPolicy::Mode mNameMatchingMode;
218 : const NetscapeStepUpPolicy mNetscapeStepUpPolicy;
219 : const CertificateTransparencyMode mCTMode;
220 :
221 : private:
222 : OCSPCache mOCSPCache;
223 :
224 : // We only have a forward declarations of these classes (see above)
225 : // so we must allocate dynamically.
226 : UniquePtr<mozilla::ct::MultiLogCTVerifier> mCTVerifier;
227 : UniquePtr<mozilla::ct::CTDiversityPolicy> mCTDiversityPolicy;
228 :
229 : void LoadKnownCTLogs();
230 : mozilla::pkix::Result VerifyCertificateTransparencyPolicy(
231 : NSSCertDBTrustDomain& trustDomain,
232 : const UniqueCERTCertList& builtChain,
233 : mozilla::pkix::Input sctsFromTLS,
234 : mozilla::pkix::Time time,
235 : /*optional out*/ CertificateTransparencyInfo* ctInfo);
236 :
237 : // Returns true if the configured SHA1 mode is more restrictive than the given
238 : // mode. SHA1Mode::Forbidden is more restrictive than any other mode except
239 : // Forbidden. Next is ImportedRoot, then ImportedRootOrBefore2016, then
240 : // Allowed. (A mode is never more restrictive than itself.)
241 : bool SHA1ModeMoreRestrictiveThanGivenMode(SHA1Mode mode);
242 : };
243 :
244 : mozilla::pkix::Result IsCertBuiltInRoot(CERTCertificate* cert, bool& result);
245 : mozilla::pkix::Result CertListContainsExpectedKeys(
246 : const CERTCertList* certList, const char* hostname, mozilla::pkix::Time time,
247 : CertVerifier::PinningMode pinningMode);
248 :
249 : } } // namespace mozilla::psm
250 :
251 : #endif // CertVerifier_h
|