Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/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
  {
86
    Reset();
87
  }
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
0
  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
  {
107
    Reset();
108
  }
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
0
  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