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