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