Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2
*
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
// During certificate authentication, we call CertVerifier::VerifySSLServerCert.
8
// This function may make zero or more HTTP requests (e.g. to gather revocation
9
// information). Our fetching logic for these requests processes them on the
10
// socket transport service thread.
11
//
12
// Because the connection for which we are verifying the certificate is
13
// happening on the socket transport thread, if our cert auth hook were to call
14
// VerifySSLServerCert directly, there would be a deadlock: VerifySSLServerCert
15
// would cause an event to be asynchronously posted to the socket transport
16
// thread, and then it would block the socket transport thread waiting to be
17
// notified of the HTTP response. However, the HTTP request would never actually
18
// be processed because the socket transport thread would be blocked and so it
19
// wouldn't be able process HTTP requests.
20
//
21
// Consequently, when we are asked to verify a certificate, we must always call
22
// VerifySSLServerCert on another thread. To accomplish this, our auth cert hook
23
// dispatches a SSLServerCertVerificationJob to a pool of background threads,
24
// and then immediately returns SECWouldBlock to libssl. These jobs are where
25
// VerifySSLServerCert is actually called.
26
//
27
// When our auth cert hook returns SECWouldBlock, libssl will carry on the
28
// handshake while we validate the certificate. This will free up the socket
29
// transport thread so that HTTP requests--including the OCSP requests needed
30
// for cert verification as mentioned above--can be processed.
31
//
32
// Once VerifySSLServerCert returns, the cert verification job dispatches a
33
// SSLServerCertVerificationResult to the socket transport thread; the
34
// SSLServerCertVerificationResult will notify libssl that the certificate
35
// authentication is complete. Once libssl is notified that the authentication
36
// is complete, it will continue the TLS handshake (if it hasn't already
37
// finished) and it will begin allowing us to send/receive data on the
38
// connection.
39
//
40
// Timeline of events (for connections managed by the socket transport service):
41
//
42
// * libssl calls SSLServerCertVerificationJob::Dispatch on the socket
43
// transport thread.
44
// * SSLServerCertVerificationJob::Dispatch queues a job
45
// (instance of SSLServerCertVerificationJob) to its background thread
46
// pool and returns.
47
// * One of the background threads calls CertVerifier::VerifySSLServerCert,
48
// which may enqueue some HTTP request(s) onto the socket transport thread,
49
// and then blocks that background thread waiting for the responses and/or
50
// timeouts or errors for those requests.
51
// * Once those HTTP responses have all come back or failed, the
52
// CertVerifier::VerifySSLServerCert function returns a result indicating
53
// that the validation succeeded or failed.
54
// * If the validation succeeded, then a SSLServerCertVerificationResult
55
// event is posted to the socket transport thread, and the cert
56
// verification thread becomes free to verify other certificates.
57
// * Otherwise, we do cert override processing to see if the validation
58
// error can be convered by override rules. The result of this processing
59
// is similarly dispatched in a SSLServerCertVerificationResult.
60
// * The SSLServerCertVerificationResult event will either wake up the
61
// socket (using SSL_AuthCertificateComplete) if validation succeeded or
62
// there was an error override, or it will set an error flag so that the
63
// next I/O operation on the socket will fail, causing the socket transport
64
// thread to close the connection.
65
//
66
// SSLServerCertVerificationResult must be dispatched to the socket transport
67
// thread because we must only call SSL_* functions on the socket transport
68
// thread since they may do I/O, because many parts of nsNSSSocketInfo (the
69
// subclass of TransportSecurityInfo used when validating certificates during
70
// an SSL handshake) and the PSM NSS I/O layer are not thread-safe, and because
71
// we need the event to interrupt the PR_Poll that may waiting for I/O on the
72
// socket for which we are validating the cert.
73
74
#include "SSLServerCertVerification.h"
75
76
#include <cstring>
77
78
#include "BRNameMatchingPolicy.h"
79
#include "CertVerifier.h"
80
#include "CryptoTask.h"
81
#include "ExtendedValidation.h"
82
#include "NSSCertDBTrustDomain.h"
83
#include "PSMRunnable.h"
84
#include "RootCertificateTelemetryUtils.h"
85
#include "ScopedNSSTypes.h"
86
#include "SharedCertVerifier.h"
87
#include "SharedSSLState.h"
88
#include "TransportSecurityInfo.h" // For RememberCertErrorsTable
89
#include "cert.h"
90
#include "mozilla/Assertions.h"
91
#include "mozilla/Casting.h"
92
#include "mozilla/RefPtr.h"
93
#include "mozilla/Telemetry.h"
94
#include "mozilla/UniquePtr.h"
95
#include "mozilla/Unused.h"
96
#include "mozilla/net/DNS.h"
97
#include "nsComponentManagerUtils.h"
98
#include "nsContentUtils.h"
99
#include "nsICertOverrideService.h"
100
#include "nsISiteSecurityService.h"
101
#include "nsISocketProvider.h"
102
#include "nsThreadPool.h"
103
#include "nsNetUtil.h"
104
#include "nsNSSCertificate.h"
105
#include "nsNSSComponent.h"
106
#include "nsNSSIOLayer.h"
107
#include "nsServiceManagerUtils.h"
108
#include "nsString.h"
109
#include "nsURLHelper.h"
110
#include "nsXPCOMCIDInternal.h"
111
#include "mozpkix/pkix.h"
112
#include "mozpkix/pkixnss.h"
113
#include "secerr.h"
114
#include "secoidt.h"
115
#include "secport.h"
116
#include "ssl.h"
117
#include "sslerr.h"
118
#include "sslexp.h"
119
120
extern mozilla::LazyLogModule gPIPNSSLog;
121
122
using namespace mozilla::pkix;
123
124
namespace mozilla {
125
namespace psm {
126
127
namespace {
128
129
// do not use a nsCOMPtr to avoid static initializer/destructor
130
nsIThreadPool* gCertVerificationThreadPool = nullptr;
131
132
} // unnamed namespace
133
134
// Called when the socket transport thread starts, to initialize the SSL cert
135
// verification thread pool. By tying the thread pool startup/shutdown directly
136
// to the STS thread's lifetime, we ensure that they are *always* available for
137
// SSL connections and that there are no races during startup and especially
138
// shutdown. (Previously, we have had multiple problems with races in PSM
139
// background threads, and the race-prevention/shutdown logic used there is
140
// brittle. Since this service is critical to things like downloading updates,
141
// we take no chances.) Also, by doing things this way, we avoid the need for
142
// locks, since gCertVerificationThreadPool is only ever accessed on the socket
143
// transport thread.
144
void InitializeSSLServerCertVerificationThreads() {
145
// TODO: tuning, make parameters preferences
146
gCertVerificationThreadPool = new nsThreadPool();
147
NS_ADDREF(gCertVerificationThreadPool);
148
149
(void)gCertVerificationThreadPool->SetIdleThreadLimit(5);
150
(void)gCertVerificationThreadPool->SetIdleThreadTimeout(30 * 1000);
151
(void)gCertVerificationThreadPool->SetThreadLimit(5);
152
(void)gCertVerificationThreadPool->SetName(NS_LITERAL_CSTRING("SSL Cert"));
153
}
154
155
// Called when the socket transport thread finishes, to destroy the thread
156
// pool. Since the socket transport service has stopped processing events, it
157
// will not attempt any more SSL I/O operations, so it is clearly safe to shut
158
// down the SSL cert verification infrastructure. Also, the STS will not
159
// dispatch many SSL verification result events at this point, so any pending
160
// cert verifications will (correctly) fail at the point they are dispatched.
161
//
162
// The other shutdown race condition that is possible is a race condition with
163
// shutdown of the nsNSSComponent service. We use the
164
// nsNSSShutdownPreventionLock where needed (not here) to prevent that.
165
void StopSSLServerCertVerificationThreads() {
166
if (gCertVerificationThreadPool) {
167
gCertVerificationThreadPool->Shutdown();
168
NS_RELEASE(gCertVerificationThreadPool);
169
}
170
}
171
172
namespace {
173
174
// Dispatched to the STS thread to notify the infoObject of the verification
175
// result.
176
//
177
// This will cause the PR_Poll in the STS thread to return, so things work
178
// correctly even if the STS thread is blocked polling (only) on the file
179
// descriptor that is waiting for this result.
180
class SSLServerCertVerificationResult : public Runnable {
181
public:
182
NS_DECL_NSIRUNNABLE
183
184
explicit SSLServerCertVerificationResult(TransportSecurityInfo* infoObject);
185
186
void Dispatch(nsNSSCertificate* aCert,
187
nsTArray<nsTArray<uint8_t>>&& aBuiltChain,
188
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
189
uint16_t aCertificateTransparencyStatus, EVStatus aEVStatus,
190
bool aSucceeded, PRErrorCode aFinalError,
191
uint32_t aCollectedErrors);
192
193
private:
194
const RefPtr<TransportSecurityInfo> mInfoObject;
195
RefPtr<nsNSSCertificate> mCert;
196
nsTArray<nsTArray<uint8_t>> mBuiltChain;
197
nsTArray<nsTArray<uint8_t>> mPeerCertChain;
198
uint16_t mCertificateTransparencyStatus;
199
EVStatus mEVStatus;
200
bool mSucceeded;
201
PRErrorCode mFinalError;
202
uint32_t mCollectedErrors;
203
};
204
205
// A probe value of 1 means "no error".
206
uint32_t MapOverridableErrorToProbeValue(PRErrorCode errorCode) {
207
switch (errorCode) {
208
case SEC_ERROR_UNKNOWN_ISSUER:
209
return 2;
210
case SEC_ERROR_CA_CERT_INVALID:
211
return 3;
212
case SEC_ERROR_UNTRUSTED_ISSUER:
213
return 4;
214
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
215
return 5;
216
case SEC_ERROR_UNTRUSTED_CERT:
217
return 6;
218
case SEC_ERROR_INADEQUATE_KEY_USAGE:
219
return 7;
220
case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
221
return 8;
222
case SSL_ERROR_BAD_CERT_DOMAIN:
223
return 9;
224
case SEC_ERROR_EXPIRED_CERTIFICATE:
225
return 10;
226
case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY:
227
return 11;
228
case mozilla::pkix::MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA:
229
return 12;
230
case mozilla::pkix::MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE:
231
return 13;
232
case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE:
233
return 14;
234
case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE:
235
return 15;
236
case SEC_ERROR_INVALID_TIME:
237
return 16;
238
case mozilla::pkix::MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME:
239
return 17;
240
case mozilla::pkix::MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED:
241
return 18;
242
case mozilla::pkix::MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT:
243
return 19;
244
case mozilla::pkix::MOZILLA_PKIX_ERROR_MITM_DETECTED:
245
return 20;
246
}
247
NS_WARNING(
248
"Unknown certificate error code. Does MapOverridableErrorToProbeValue "
249
"handle everything in DetermineCertOverrideErrors?");
250
return 0;
251
}
252
253
static uint32_t MapCertErrorToProbeValue(PRErrorCode errorCode) {
254
uint32_t probeValue;
255
switch (errorCode) {
256
// see security/pkix/include/pkix/Result.h
257
#define MOZILLA_PKIX_MAP(name, value, nss_name) \
258
case nss_name: \
259
probeValue = value; \
260
break;
261
MOZILLA_PKIX_MAP_LIST
262
#undef MOZILLA_PKIX_MAP
263
default:
264
return 0;
265
}
266
267
// Since FATAL_ERROR_FLAG is 0x800, fatal error values are much larger than
268
// non-fatal error values. To conserve space, we remap these so they start at
269
// (decimal) 90 instead of 0x800. Currently there are ~50 non-fatal errors
270
// mozilla::pkix might return, so saving space for 90 should be sufficient
271
// (similarly, there are 4 fatal errors, so saving space for 10 should also
272
// be sufficient).
273
static_assert(
274
FATAL_ERROR_FLAG == 0x800,
275
"mozilla::pkix::FATAL_ERROR_FLAG is not what we were expecting");
276
if (probeValue & FATAL_ERROR_FLAG) {
277
probeValue ^= FATAL_ERROR_FLAG;
278
probeValue += 90;
279
}
280
return probeValue;
281
}
282
283
SECStatus DetermineCertOverrideErrors(const UniqueCERTCertificate& cert,
284
const nsACString& hostName, PRTime now,
285
PRErrorCode defaultErrorCodeToReport,
286
/*out*/ uint32_t& collectedErrors,
287
/*out*/ PRErrorCode& errorCodeTrust,
288
/*out*/ PRErrorCode& errorCodeMismatch,
289
/*out*/ PRErrorCode& errorCodeTime) {
290
MOZ_ASSERT(cert);
291
MOZ_ASSERT(collectedErrors == 0);
292
MOZ_ASSERT(errorCodeTrust == 0);
293
MOZ_ASSERT(errorCodeMismatch == 0);
294
MOZ_ASSERT(errorCodeTime == 0);
295
296
// Assumes the error prioritization described in mozilla::pkix's
297
// BuildForward function. Also assumes that CheckCertHostname was only
298
// called if CertVerifier::VerifyCert succeeded.
299
switch (defaultErrorCodeToReport) {
300
case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
301
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
302
case SEC_ERROR_UNKNOWN_ISSUER:
303
case SEC_ERROR_CA_CERT_INVALID:
304
case mozilla::pkix::MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED:
305
case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY:
306
case mozilla::pkix::MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME:
307
case mozilla::pkix::MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE:
308
case mozilla::pkix::MOZILLA_PKIX_ERROR_MITM_DETECTED:
309
case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE:
310
case mozilla::pkix::MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT:
311
case mozilla::pkix::MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA: {
312
collectedErrors = nsICertOverrideService::ERROR_UNTRUSTED;
313
errorCodeTrust = defaultErrorCodeToReport;
314
315
SECCertTimeValidity validity =
316
CERT_CheckCertValidTimes(cert.get(), now, false);
317
if (validity == secCertTimeUndetermined) {
318
// This only happens if cert is null. CERT_CheckCertValidTimes will
319
// have set the error code to SEC_ERROR_INVALID_ARGS. We should really
320
// be using mozilla::pkix here anyway.
321
MOZ_ASSERT(PR_GetError() == SEC_ERROR_INVALID_ARGS);
322
return SECFailure;
323
}
324
if (validity == secCertTimeExpired) {
325
collectedErrors |= nsICertOverrideService::ERROR_TIME;
326
errorCodeTime = SEC_ERROR_EXPIRED_CERTIFICATE;
327
} else if (validity == secCertTimeNotValidYet) {
328
collectedErrors |= nsICertOverrideService::ERROR_TIME;
329
errorCodeTime =
330
mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE;
331
}
332
break;
333
}
334
335
case SEC_ERROR_INVALID_TIME:
336
case SEC_ERROR_EXPIRED_CERTIFICATE:
337
case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE:
338
collectedErrors = nsICertOverrideService::ERROR_TIME;
339
errorCodeTime = defaultErrorCodeToReport;
340
break;
341
342
case SSL_ERROR_BAD_CERT_DOMAIN:
343
collectedErrors = nsICertOverrideService::ERROR_MISMATCH;
344
errorCodeMismatch = SSL_ERROR_BAD_CERT_DOMAIN;
345
break;
346
347
case 0:
348
NS_ERROR("No error code set during certificate validation failure.");
349
PR_SetError(PR_INVALID_STATE_ERROR, 0);
350
return SECFailure;
351
352
default:
353
PR_SetError(defaultErrorCodeToReport, 0);
354
return SECFailure;
355
}
356
357
if (defaultErrorCodeToReport != SSL_ERROR_BAD_CERT_DOMAIN) {
358
Input certInput;
359
if (certInput.Init(cert->derCert.data, cert->derCert.len) != Success) {
360
PR_SetError(SEC_ERROR_BAD_DER, 0);
361
return SECFailure;
362
}
363
Input hostnameInput;
364
Result result = hostnameInput.Init(
365
BitwiseCast<const uint8_t*, const char*>(hostName.BeginReading()),
366
hostName.Length());
367
if (result != Success) {
368
PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
369
return SECFailure;
370
}
371
// Use a lax policy so as to not generate potentially spurious name
372
// mismatch "hints".
373
BRNameMatchingPolicy nameMatchingPolicy(
374
BRNameMatchingPolicy::Mode::DoNotEnforce);
375
// CheckCertHostname expects that its input represents a certificate that
376
// has already been successfully validated by BuildCertChain. This is
377
// obviously not the case, however, because we're in the error path of
378
// certificate verification. Thus, this is problematic. In the future, it
379
// would be nice to remove this optimistic additional error checking and
380
// simply punt to the front-end, which can more easily (and safely) perform
381
// extra checks to give the user hints as to why verification failed.
382
result = CheckCertHostname(certInput, hostnameInput, nameMatchingPolicy);
383
// Treat malformed name information as a domain mismatch.
384
if (result == Result::ERROR_BAD_DER ||
385
result == Result::ERROR_BAD_CERT_DOMAIN) {
386
collectedErrors |= nsICertOverrideService::ERROR_MISMATCH;
387
errorCodeMismatch = SSL_ERROR_BAD_CERT_DOMAIN;
388
} else if (IsFatalError(result)) {
389
// Because its input has not been validated by BuildCertChain,
390
// CheckCertHostname can return an error that is less important than the
391
// original certificate verification error. Only return an error result
392
// from this function if we've encountered a fatal error.
393
PR_SetError(MapResultToPRErrorCode(result), 0);
394
return SECFailure;
395
}
396
}
397
398
return SECSuccess;
399
}
400
401
// Helper function to determine if overrides are allowed for this host.
402
// Overrides are not allowed for known HSTS or HPKP hosts. However, an IP
403
// address is never considered an HSTS or HPKP host.
404
static nsresult OverrideAllowedForHost(
405
uint64_t aPtrForLog, const nsACString& aHostname,
406
const OriginAttributes& aOriginAttributes, uint32_t aProviderFlags,
407
/*out*/ bool& aOverrideAllowed) {
408
aOverrideAllowed = false;
409
410
// If this is an IP address, overrides are allowed, because an IP address is
411
// never an HSTS or HPKP host. nsISiteSecurityService takes this into account
412
// already, but the real problem here is that calling NS_NewURI with an IPv6
413
// address fails. We do this to avoid that. A more comprehensive fix would be
414
// to have Necko provide an nsIURI to PSM and to use that here (and
415
// everywhere). However, that would be a wide-spanning change.
416
if (net_IsValidIPv6Addr(aHostname)) {
417
aOverrideAllowed = true;
418
return NS_OK;
419
}
420
421
// If this is an HTTP Strict Transport Security host or a pinned host and the
422
// certificate is bad, don't allow overrides (RFC 6797 section 12.1,
423
// HPKP draft spec section 2.6).
424
bool strictTransportSecurityEnabled = false;
425
bool hasPinningInformation = false;
426
nsCOMPtr<nsISiteSecurityService> sss(do_GetService(NS_SSSERVICE_CONTRACTID));
427
if (!sss) {
428
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
429
("[0x%" PRIx64
430
"] Couldn't get nsISiteSecurityService to check HSTS/HPKP",
431
aPtrForLog));
432
return NS_ERROR_FAILURE;
433
}
434
435
nsCOMPtr<nsIURI> uri;
436
nsresult rv = NS_NewURI(getter_AddRefs(uri),
437
NS_LITERAL_CSTRING("https://") + aHostname);
438
if (NS_FAILED(rv)) {
439
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
440
("[0x%" PRIx64 "] Creating new URI failed", aPtrForLog));
441
return rv;
442
}
443
444
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, uri,
445
aProviderFlags, aOriginAttributes, nullptr, nullptr,
446
&strictTransportSecurityEnabled);
447
if (NS_FAILED(rv)) {
448
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
449
("[0x%" PRIx64 "] checking for HSTS failed", aPtrForLog));
450
return rv;
451
}
452
453
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HPKP, uri,
454
aProviderFlags, aOriginAttributes, nullptr, nullptr,
455
&hasPinningInformation);
456
if (NS_FAILED(rv)) {
457
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
458
("[0x%" PRIx64 "] checking for HPKP failed", aPtrForLog));
459
return rv;
460
}
461
462
aOverrideAllowed = !strictTransportSecurityEnabled && !hasPinningInformation;
463
return NS_OK;
464
}
465
466
class SSLServerCertVerificationJob : public Runnable {
467
public:
468
// Must be called only on the socket transport thread
469
static SECStatus Dispatch(uint64_t addrForLogging, void* aPinArg,
470
const UniqueCERTCertificate& serverCert,
471
nsTArray<nsTArray<uint8_t>>&& peerCertChain,
472
const nsACString& aHostName, int32_t aPort,
473
const OriginAttributes& aOriginAttributes,
474
Maybe<nsTArray<uint8_t>>& stapledOCSPResponse,
475
Maybe<nsTArray<uint8_t>>& sctsFromTLSExtension,
476
Maybe<DelegatedCredentialInfo>& dcInfo,
477
uint32_t providerFlags, Time time, PRTime prtime,
478
uint32_t certVerifierFlags,
479
SSLServerCertVerificationResult* aResultTask);
480
481
private:
482
NS_DECL_NSIRUNNABLE
483
484
// Must be called only on the socket transport thread
485
SSLServerCertVerificationJob(uint64_t addrForLogging, void* aPinArg,
486
const UniqueCERTCertificate& cert,
487
nsTArray<nsTArray<uint8_t>>&& peerCertChain,
488
const nsACString& aHostName, int32_t aPort,
489
const OriginAttributes& aOriginAttributes,
490
Maybe<nsTArray<uint8_t>>& stapledOCSPResponse,
491
Maybe<nsTArray<uint8_t>>& sctsFromTLSExtension,
492
Maybe<DelegatedCredentialInfo>& dcInfo,
493
uint32_t providerFlags, Time time, PRTime prtime,
494
uint32_t certVerifierFlags,
495
SSLServerCertVerificationResult* aResultTask);
496
uint64_t mAddrForLogging;
497
void* mPinArg;
498
const UniqueCERTCertificate mCert;
499
nsTArray<nsTArray<uint8_t>> mPeerCertChain;
500
nsCString mHostName;
501
int32_t mPort;
502
OriginAttributes mOriginAttributes;
503
const uint32_t mProviderFlags;
504
const uint32_t mCertVerifierFlags;
505
const Time mTime;
506
const PRTime mPRTime;
507
Maybe<nsTArray<uint8_t>> mStapledOCSPResponse;
508
Maybe<nsTArray<uint8_t>> mSCTsFromTLSExtension;
509
Maybe<DelegatedCredentialInfo> mDCInfo;
510
RefPtr<SSLServerCertVerificationResult> mResultTask;
511
};
512
513
SSLServerCertVerificationJob::SSLServerCertVerificationJob(
514
uint64_t addrForLogging, void* aPinArg, const UniqueCERTCertificate& cert,
515
nsTArray<nsTArray<uint8_t>>&& peerCertChain, const nsACString& aHostName,
516
int32_t aPort, const OriginAttributes& aOriginAttributes,
517
Maybe<nsTArray<uint8_t>>& stapledOCSPResponse,
518
Maybe<nsTArray<uint8_t>>& sctsFromTLSExtension,
519
Maybe<DelegatedCredentialInfo>& dcInfo, uint32_t providerFlags, Time time,
520
PRTime prtime, uint32_t certVerifierFlags,
521
SSLServerCertVerificationResult* aResultTask)
522
: Runnable("psm::SSLServerCertVerificationJob"),
523
mAddrForLogging(addrForLogging),
524
mPinArg(aPinArg),
525
mCert(CERT_DupCertificate(cert.get())),
526
mPeerCertChain(std::move(peerCertChain)),
527
mHostName(aHostName),
528
mPort(aPort),
529
mOriginAttributes(aOriginAttributes),
530
mProviderFlags(providerFlags),
531
mCertVerifierFlags(certVerifierFlags),
532
mTime(time),
533
mPRTime(prtime),
534
mStapledOCSPResponse(std::move(stapledOCSPResponse)),
535
mSCTsFromTLSExtension(std::move(sctsFromTLSExtension)),
536
mDCInfo(std::move(dcInfo)),
537
mResultTask(aResultTask) {}
538
539
// This function assumes that we will only use the SPDY connection coalescing
540
// feature on connections where we have negotiated SPDY using NPN. If we ever
541
// talk SPDY without having negotiated it with SPDY, this code will give wrong
542
// and perhaps unsafe results.
543
//
544
// Returns SECSuccess on the initial handshake of all connections, on
545
// renegotiations for any connections where we did not negotiate SPDY, or on any
546
// SPDY connection where the server's certificate did not change.
547
//
548
// Prohibit changing the server cert only if we negotiated SPDY,
549
// in order to support SPDY's cross-origin connection pooling.
550
static SECStatus BlockServerCertChangeForSpdy(
551
nsNSSSocketInfo* infoObject, const UniqueCERTCertificate& serverCert) {
552
// Get the existing cert. If there isn't one, then there is
553
// no cert change to worry about.
554
nsCOMPtr<nsIX509Cert> cert;
555
556
if (!infoObject->IsHandshakeCompleted()) {
557
// first handshake on this connection, not a
558
// renegotiation.
559
return SECSuccess;
560
}
561
562
infoObject->GetServerCert(getter_AddRefs(cert));
563
if (!cert) {
564
MOZ_ASSERT_UNREACHABLE(
565
"TransportSecurityInfo must have a cert implementing nsIX509Cert");
566
PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
567
return SECFailure;
568
}
569
570
// Filter out sockets that did not neogtiate SPDY via NPN
571
nsAutoCString negotiatedNPN;
572
nsresult rv = infoObject->GetNegotiatedNPN(negotiatedNPN);
573
MOZ_ASSERT(NS_SUCCEEDED(rv),
574
"GetNegotiatedNPN() failed during renegotiation");
575
576
if (NS_SUCCEEDED(rv) &&
577
!StringBeginsWith(negotiatedNPN, NS_LITERAL_CSTRING("spdy/"))) {
578
return SECSuccess;
579
}
580
// If GetNegotiatedNPN() failed we will assume spdy for safety's safe
581
if (NS_FAILED(rv)) {
582
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
583
("BlockServerCertChangeForSpdy failed GetNegotiatedNPN() call."
584
" Assuming spdy.\n"));
585
}
586
587
// Check to see if the cert has actually changed
588
UniqueCERTCertificate c(cert->GetCert());
589
MOZ_ASSERT(c, "Somehow couldn't get underlying cert from nsIX509Cert");
590
bool sameCert = CERT_CompareCerts(c.get(), serverCert.get());
591
if (sameCert) {
592
return SECSuccess;
593
}
594
595
// Report an error - changed cert is confirmed
596
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
597
("SPDY Refused to allow new cert during renegotiation\n"));
598
PR_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED, 0);
599
return SECFailure;
600
}
601
602
void AccumulateSubjectCommonNameTelemetry(const char* commonName,
603
bool commonNameInSubjectAltNames) {
604
if (!commonName) {
605
// 1 means no common name present
606
Telemetry::Accumulate(Telemetry::BR_9_2_2_SUBJECT_COMMON_NAME, 1);
607
} else if (!commonNameInSubjectAltNames) {
608
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
609
("BR telemetry: common name '%s' not in subject alt. names "
610
"(or the subject alt. names extension is not present)\n",
611
commonName));
612
// 2 means the common name is not present in subject alt names
613
Telemetry::Accumulate(Telemetry::BR_9_2_2_SUBJECT_COMMON_NAME, 2);
614
} else {
615
// 0 means the common name is present in subject alt names
616
Telemetry::Accumulate(Telemetry::BR_9_2_2_SUBJECT_COMMON_NAME, 0);
617
}
618
}
619
620
// Returns true if and only if commonName ends with altName (minus its leading
621
// "*"). altName has already been checked to be of the form "*.<something>".
622
// commonName may be NULL.
623
static bool TryMatchingWildcardSubjectAltName(const char* commonName,
624
const nsACString& altName) {
625
return commonName &&
626
StringEndsWith(nsDependentCString(commonName), Substring(altName, 1));
627
}
628
629
// Gathers telemetry on Baseline Requirements 9.2.1 (Subject Alternative
630
// Names Extension) and 9.2.2 (Subject Common Name Field).
631
// Specifically:
632
// - whether or not the subject common name field is present
633
// - whether or not the subject alternative names extension is present
634
// - if there is a malformed entry in the subject alt. names extension
635
// - if there is an entry in the subject alt. names extension corresponding
636
// to the subject common name
637
// Telemetry is only gathered for certificates that chain to a trusted root
638
// in Mozilla's Root CA program.
639
// certList consists of a validated certificate chain. The end-entity
640
// certificate is first and the root (trust anchor) is last.
641
void GatherBaselineRequirementsTelemetry(const UniqueCERTCertList& certList) {
642
CERTCertListNode* endEntityNode = CERT_LIST_HEAD(certList);
643
CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
644
MOZ_ASSERT(!(CERT_LIST_END(endEntityNode, certList) ||
645
CERT_LIST_END(rootNode, certList)));
646
if (CERT_LIST_END(endEntityNode, certList) ||
647
CERT_LIST_END(rootNode, certList)) {
648
return;
649
}
650
CERTCertificate* cert = endEntityNode->cert;
651
MOZ_ASSERT(cert);
652
if (!cert) {
653
return;
654
}
655
UniquePORTString commonName(CERT_GetCommonName(&cert->subject));
656
// This only applies to certificates issued by authorities in our root
657
// program.
658
CERTCertificate* rootCert = rootNode->cert;
659
MOZ_ASSERT(rootCert);
660
if (!rootCert) {
661
return;
662
}
663
bool isBuiltIn = false;
664
Result result = IsCertBuiltInRoot(rootCert, isBuiltIn);
665
if (result != Success || !isBuiltIn) {
666
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
667
("BR telemetry: root certificate for '%s' is not a built-in root "
668
"(or IsCertBuiltInRoot failed)\n",
669
commonName.get()));
670
return;
671
}
672
ScopedAutoSECItem altNameExtension;
673
SECStatus rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME,
674
&altNameExtension);
675
if (rv != SECSuccess) {
676
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
677
("BR telemetry: no subject alt names extension for '%s'\n",
678
commonName.get()));
679
// 1 means there is no subject alt names extension
680
Telemetry::Accumulate(Telemetry::BR_9_2_1_SUBJECT_ALT_NAMES, 1);
681
AccumulateSubjectCommonNameTelemetry(commonName.get(), false);
682
return;
683
}
684
685
UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
686
CERTGeneralName* subjectAltNames =
687
CERT_DecodeAltNameExtension(arena.get(), &altNameExtension);
688
if (!subjectAltNames) {
689
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
690
("BR telemetry: could not decode subject alt names for '%s'\n",
691
commonName.get()));
692
// 2 means the subject alt names extension could not be decoded
693
Telemetry::Accumulate(Telemetry::BR_9_2_1_SUBJECT_ALT_NAMES, 2);
694
AccumulateSubjectCommonNameTelemetry(commonName.get(), false);
695
return;
696
}
697
698
CERTGeneralName* currentName = subjectAltNames;
699
bool commonNameInSubjectAltNames = false;
700
bool nonDNSNameOrIPAddressPresent = false;
701
bool malformedDNSNameOrIPAddressPresent = false;
702
bool nonFQDNPresent = false;
703
do {
704
nsAutoCString altName;
705
if (currentName->type == certDNSName) {
706
altName.Assign(
707
BitwiseCast<char*, unsigned char*>(currentName->name.other.data),
708
currentName->name.other.len);
709
nsDependentCString altNameWithoutWildcard(altName, 0);
710
if (StringBeginsWith(altNameWithoutWildcard, NS_LITERAL_CSTRING("*."))) {
711
altNameWithoutWildcard.Rebind(altName, 2);
712
commonNameInSubjectAltNames |=
713
TryMatchingWildcardSubjectAltName(commonName.get(), altName);
714
}
715
// net_IsValidHostName appears to return true for valid IP addresses,
716
// which would be invalid for a DNS name.
717
// Note that the net_IsValidHostName check will catch things like
718
// "a.*.example.com".
719
if (!net_IsValidHostName(altNameWithoutWildcard) ||
720
net_IsValidIPv4Addr(altName) || net_IsValidIPv6Addr(altName)) {
721
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
722
("BR telemetry: DNSName '%s' not valid (for '%s')\n",
723
altName.get(), commonName.get()));
724
malformedDNSNameOrIPAddressPresent = true;
725
}
726
if (!altName.Contains('.')) {
727
nonFQDNPresent = true;
728
}
729
} else if (currentName->type == certIPAddress) {
730
// According to DNS.h, this includes space for the null-terminator
731
char buf[net::kNetAddrMaxCStrBufSize] = {0};
732
PRNetAddr addr;
733
memset(&addr, 0, sizeof(addr));
734
if (currentName->name.other.len == 4) {
735
addr.inet.family = PR_AF_INET;
736
memcpy(&addr.inet.ip, currentName->name.other.data,
737
currentName->name.other.len);
738
if (PR_NetAddrToString(&addr, buf, sizeof(buf) - 1) != PR_SUCCESS) {
739
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
740
("BR telemetry: IPAddress (v4) not valid (for '%s')\n",
741
commonName.get()));
742
malformedDNSNameOrIPAddressPresent = true;
743
} else {
744
altName.Assign(buf);
745
}
746
} else if (currentName->name.other.len == 16) {
747
addr.inet.family = PR_AF_INET6;
748
memcpy(&addr.ipv6.ip, currentName->name.other.data,
749
currentName->name.other.len);
750
if (PR_NetAddrToString(&addr, buf, sizeof(buf) - 1) != PR_SUCCESS) {
751
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
752
("BR telemetry: IPAddress (v6) not valid (for '%s')\n",
753
commonName.get()));
754
malformedDNSNameOrIPAddressPresent = true;
755
} else {
756
altName.Assign(buf);
757
}
758
} else {
759
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
760
("BR telemetry: IPAddress not valid (for '%s')\n",
761
commonName.get()));
762
malformedDNSNameOrIPAddressPresent = true;
763
}
764
} else {
765
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
766
("BR telemetry: non-DNSName, non-IPAddress present for '%s'\n",
767
commonName.get()));
768
nonDNSNameOrIPAddressPresent = true;
769
}
770
if (commonName && altName.Equals(commonName.get())) {
771
commonNameInSubjectAltNames = true;
772
}
773
currentName = CERT_GetNextGeneralName(currentName);
774
} while (currentName && currentName != subjectAltNames);
775
776
if (nonDNSNameOrIPAddressPresent) {
777
// 3 means there's an entry that isn't an ip address or dns name
778
Telemetry::Accumulate(Telemetry::BR_9_2_1_SUBJECT_ALT_NAMES, 3);
779
}
780
if (malformedDNSNameOrIPAddressPresent) {
781
// 4 means there's a malformed ip address or dns name entry
782
Telemetry::Accumulate(Telemetry::BR_9_2_1_SUBJECT_ALT_NAMES, 4);
783
}
784
if (nonFQDNPresent) {
785
// 5 means there's a DNS name entry with a non-fully-qualified domain name
786
Telemetry::Accumulate(Telemetry::BR_9_2_1_SUBJECT_ALT_NAMES, 5);
787
}
788
if (!nonDNSNameOrIPAddressPresent && !malformedDNSNameOrIPAddressPresent &&
789
!nonFQDNPresent) {
790
// 0 means the extension is acceptable
791
Telemetry::Accumulate(Telemetry::BR_9_2_1_SUBJECT_ALT_NAMES, 0);
792
}
793
794
AccumulateSubjectCommonNameTelemetry(commonName.get(),
795
commonNameInSubjectAltNames);
796
}
797
798
// Gather telemetry on whether the end-entity cert for a server has the
799
// required TLS Server Authentication EKU, or any others
800
void GatherEKUTelemetry(const UniqueCERTCertList& certList) {
801
CERTCertListNode* endEntityNode = CERT_LIST_HEAD(certList);
802
CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
803
MOZ_ASSERT(!(CERT_LIST_END(endEntityNode, certList) ||
804
CERT_LIST_END(rootNode, certList)));
805
if (CERT_LIST_END(endEntityNode, certList) ||
806
CERT_LIST_END(rootNode, certList)) {
807
return;
808
}
809
CERTCertificate* endEntityCert = endEntityNode->cert;
810
MOZ_ASSERT(endEntityCert);
811
if (!endEntityCert) {
812
return;
813
}
814
815
// Only log telemetry if the root CA is built-in
816
CERTCertificate* rootCert = rootNode->cert;
817
MOZ_ASSERT(rootCert);
818
if (!rootCert) {
819
return;
820
}
821
bool isBuiltIn = false;
822
Result rv = IsCertBuiltInRoot(rootCert, isBuiltIn);
823
if (rv != Success || !isBuiltIn) {
824
return;
825
}
826
827
// Find the EKU extension, if present
828
bool foundEKU = false;
829
SECOidTag oidTag;
830
CERTCertExtension* ekuExtension = nullptr;
831
for (size_t i = 0; endEntityCert->extensions && endEntityCert->extensions[i];
832
i++) {
833
oidTag = SECOID_FindOIDTag(&endEntityCert->extensions[i]->id);
834
if (oidTag == SEC_OID_X509_EXT_KEY_USAGE) {
835
foundEKU = true;
836
ekuExtension = endEntityCert->extensions[i];
837
}
838
}
839
840
if (!foundEKU) {
841
Telemetry::Accumulate(Telemetry::SSL_SERVER_AUTH_EKU, 0);
842
return;
843
}
844
845
// Parse the EKU extension
846
UniqueCERTOidSequence ekuSequence(
847
CERT_DecodeOidSequence(&ekuExtension->value));
848
if (!ekuSequence) {
849
return;
850
}
851
852
// Search through the available EKUs
853
bool foundServerAuth = false;
854
bool foundOther = false;
855
for (SECItem** oids = ekuSequence->oids; oids && *oids; oids++) {
856
oidTag = SECOID_FindOIDTag(*oids);
857
if (oidTag == SEC_OID_EXT_KEY_USAGE_SERVER_AUTH) {
858
foundServerAuth = true;
859
} else {
860
foundOther = true;
861
}
862
}
863
864
// Cases 3 is included only for completeness. It should never
865
// appear in these statistics, because CheckExtendedKeyUsage()
866
// should require the EKU extension, if present, to contain the
867
// value id_kp_serverAuth.
868
if (foundServerAuth && !foundOther) {
869
Telemetry::Accumulate(Telemetry::SSL_SERVER_AUTH_EKU, 1);
870
} else if (foundServerAuth && foundOther) {
871
Telemetry::Accumulate(Telemetry::SSL_SERVER_AUTH_EKU, 2);
872
} else if (!foundServerAuth) {
873
Telemetry::Accumulate(Telemetry::SSL_SERVER_AUTH_EKU, 3);
874
}
875
}
876
877
// Gathers telemetry on which CA is the root of a given cert chain.
878
// If the root is a built-in root, then the telemetry makes a count
879
// by root. Roots that are not built-in are counted in one bin.
880
void GatherRootCATelemetry(const UniqueCERTCertList& certList) {
881
CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
882
MOZ_ASSERT(rootNode);
883
if (!rootNode) {
884
return;
885
}
886
MOZ_ASSERT(!CERT_LIST_END(rootNode, certList));
887
if (CERT_LIST_END(rootNode, certList)) {
888
return;
889
}
890
CERTCertificate* rootCert = rootNode->cert;
891
MOZ_ASSERT(rootCert);
892
if (!rootCert) {
893
return;
894
}
895
AccumulateTelemetryForRootCA(Telemetry::CERT_VALIDATION_SUCCESS_BY_CA,
896
rootCert);
897
}
898
899
// There are various things that we want to measure about certificate
900
// chains that we accept. This is a single entry point for all of them.
901
void GatherSuccessfulValidationTelemetry(const UniqueCERTCertList& certList) {
902
GatherBaselineRequirementsTelemetry(certList);
903
GatherEKUTelemetry(certList);
904
GatherRootCATelemetry(certList);
905
}
906
907
void GatherTelemetryForSingleSCT(const ct::VerifiedSCT& verifiedSct) {
908
// See SSL_SCTS_ORIGIN in Histograms.json.
909
uint32_t origin = 0;
910
switch (verifiedSct.origin) {
911
case ct::VerifiedSCT::Origin::Embedded:
912
origin = 1;
913
break;
914
case ct::VerifiedSCT::Origin::TLSExtension:
915
origin = 2;
916
break;
917
case ct::VerifiedSCT::Origin::OCSPResponse:
918
origin = 3;
919
break;
920
default:
921
MOZ_ASSERT_UNREACHABLE("Unexpected VerifiedSCT::Origin type");
922
}
923
Telemetry::Accumulate(Telemetry::SSL_SCTS_ORIGIN, origin);
924
925
// See SSL_SCTS_VERIFICATION_STATUS in Histograms.json.
926
uint32_t verificationStatus = 0;
927
switch (verifiedSct.status) {
928
case ct::VerifiedSCT::Status::Valid:
929
verificationStatus = 1;
930
break;
931
case ct::VerifiedSCT::Status::UnknownLog:
932
verificationStatus = 2;
933
break;
934
case ct::VerifiedSCT::Status::InvalidSignature:
935
verificationStatus = 3;
936
break;
937
case ct::VerifiedSCT::Status::InvalidTimestamp:
938
verificationStatus = 4;
939
break;
940
case ct::VerifiedSCT::Status::ValidFromDisqualifiedLog:
941
verificationStatus = 5;
942
break;
943
default:
944
MOZ_ASSERT_UNREACHABLE("Unexpected VerifiedSCT::Status type");
945
}
946
Telemetry::Accumulate(Telemetry::SSL_SCTS_VERIFICATION_STATUS,
947
verificationStatus);
948
}
949
950
void GatherCertificateTransparencyTelemetry(
951
const UniqueCERTCertList& certList, bool isEV,
952
const CertificateTransparencyInfo& info) {
953
if (!info.enabled) {
954
// No telemetry is gathered when CT is disabled.
955
return;
956
}
957
958
for (const ct::VerifiedSCT& sct : info.verifyResult.verifiedScts) {
959
GatherTelemetryForSingleSCT(sct);
960
}
961
962
// Decoding errors are reported to the 0th bucket
963
// of the SSL_SCTS_VERIFICATION_STATUS enumerated probe.
964
for (size_t i = 0; i < info.verifyResult.decodingErrors; ++i) {
965
Telemetry::Accumulate(Telemetry::SSL_SCTS_VERIFICATION_STATUS, 0);
966
}
967
968
// Handle the histogram of SCTs counts.
969
uint32_t sctsCount =
970
static_cast<uint32_t>(info.verifyResult.verifiedScts.size());
971
// Note that sctsCount can also be 0 in case we've received SCT binary data,
972
// but it failed to parse (e.g. due to unsupported CT protocol version).
973
Telemetry::Accumulate(Telemetry::SSL_SCTS_PER_CONNECTION, sctsCount);
974
975
// Report CT Policy compliance of EV certificates.
976
if (isEV) {
977
uint32_t evCompliance = 0;
978
switch (info.policyCompliance) {
979
case ct::CTPolicyCompliance::Compliant:
980
evCompliance = 1;
981
break;
982
case ct::CTPolicyCompliance::NotEnoughScts:
983
evCompliance = 2;
984
break;
985
case ct::CTPolicyCompliance::NotDiverseScts:
986
evCompliance = 3;
987
break;
988
case ct::CTPolicyCompliance::Unknown:
989
default:
990
MOZ_ASSERT_UNREACHABLE("Unexpected CTPolicyCompliance type");
991
}
992
Telemetry::Accumulate(Telemetry::SSL_CT_POLICY_COMPLIANCE_OF_EV_CERTS,
993
evCompliance);
994
}
995
996
// Get the root cert.
997
CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
998
MOZ_ASSERT(rootNode);
999
if (!rootNode) {
1000
return;
1001
}
1002
MOZ_ASSERT(!CERT_LIST_END(rootNode, certList));
1003
if (CERT_LIST_END(rootNode, certList)) {
1004
return;
1005
}
1006
CERTCertificate* rootCert = rootNode->cert;
1007
MOZ_ASSERT(rootCert);
1008
if (!rootCert) {
1009
return;
1010
}
1011
1012
// Report CT Policy compliance by CA.
1013
switch (info.policyCompliance) {
1014
case ct::CTPolicyCompliance::Compliant:
1015
AccumulateTelemetryForRootCA(
1016
Telemetry::SSL_CT_POLICY_COMPLIANT_CONNECTIONS_BY_CA, rootCert);
1017
break;
1018
case ct::CTPolicyCompliance::NotEnoughScts:
1019
case ct::CTPolicyCompliance::NotDiverseScts:
1020
AccumulateTelemetryForRootCA(
1021
Telemetry::SSL_CT_POLICY_NON_COMPLIANT_CONNECTIONS_BY_CA, rootCert);
1022
break;
1023
case ct::CTPolicyCompliance::Unknown:
1024
default:
1025
MOZ_ASSERT_UNREACHABLE("Unexpected CTPolicyCompliance type");
1026
}
1027
}
1028
1029
// This function collects telemetry about certs. It will be called on one of
1030
// CertVerificationThread. When the socket process is used this will be called
1031
// on the parent process.
1032
static void CollectCertTelemetry(
1033
mozilla::pkix::Result aCertVerificationResult, SECOidTag aEvOidPolicy,
1034
CertVerifier::OCSPStaplingStatus aOcspStaplingStatus,
1035
KeySizeStatus aKeySizeStatus, SHA1ModeResult aSha1ModeResult,
1036
const PinningTelemetryInfo& aPinningTelemetryInfo,
1037
const UniqueCERTCertList& aBuiltCertChain,
1038
const CertificateTransparencyInfo& aCertificateTransparencyInfo,
1039
const CRLiteTelemetryInfo& aCRLiteTelemetryInfo) {
1040
uint32_t evStatus = (aCertVerificationResult != Success)
1041
? 0 // 0 = Failure
1042
: (aEvOidPolicy == SEC_OID_UNKNOWN) ? 1 // 1 = DV
1043
: 2; // 2 = EV
1044
Telemetry::Accumulate(Telemetry::CERT_EV_STATUS, evStatus);
1045
1046
if (aOcspStaplingStatus != CertVerifier::OCSP_STAPLING_NEVER_CHECKED) {
1047
Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, aOcspStaplingStatus);
1048
}
1049
1050
if (aKeySizeStatus != KeySizeStatus::NeverChecked) {
1051
Telemetry::Accumulate(Telemetry::CERT_CHAIN_KEY_SIZE_STATUS,
1052
static_cast<uint32_t>(aKeySizeStatus));
1053
}
1054
1055
if (aSha1ModeResult != SHA1ModeResult::NeverChecked) {
1056
Telemetry::Accumulate(Telemetry::CERT_CHAIN_SHA1_POLICY_STATUS,
1057
static_cast<uint32_t>(aSha1ModeResult));
1058
}
1059
1060
if (aPinningTelemetryInfo.accumulateForRoot) {
1061
Telemetry::Accumulate(Telemetry::CERT_PINNING_FAILURES_BY_CA,
1062
aPinningTelemetryInfo.rootBucket);
1063
}
1064
1065
if (aPinningTelemetryInfo.accumulateResult) {
1066
MOZ_ASSERT(aPinningTelemetryInfo.certPinningResultHistogram.isSome());
1067
Telemetry::Accumulate(
1068
aPinningTelemetryInfo.certPinningResultHistogram.value(),
1069
aPinningTelemetryInfo.certPinningResultBucket);
1070
}
1071
1072
if (aCertVerificationResult == Success) {
1073
GatherSuccessfulValidationTelemetry(aBuiltCertChain);
1074
GatherCertificateTransparencyTelemetry(
1075
aBuiltCertChain,
1076
/*isEV*/ aEvOidPolicy != SEC_OID_UNKNOWN, aCertificateTransparencyInfo);
1077
}
1078
1079
switch (aCRLiteTelemetryInfo.mLookupResult) {
1080
case CRLiteLookupResult::FilterNotAvailable:
1081
Telemetry::AccumulateCategorical(
1082
Telemetry::LABELS_CRLITE_RESULT::FilterNotAvailable);
1083
break;
1084
case CRLiteLookupResult::IssuerNotEnrolled:
1085
Telemetry::AccumulateCategorical(
1086
Telemetry::LABELS_CRLITE_RESULT::IssuerNotEnrolled);
1087
break;
1088
case CRLiteLookupResult::CertificateTooNew:
1089
Telemetry::AccumulateCategorical(
1090
Telemetry::LABELS_CRLITE_RESULT::CertificateTooNew);
1091
break;
1092
case CRLiteLookupResult::CertificateValid:
1093
Telemetry::AccumulateCategorical(
1094
Telemetry::LABELS_CRLITE_RESULT::CertificateValid);
1095
break;
1096
case CRLiteLookupResult::CertificateRevoked:
1097
Telemetry::AccumulateCategorical(
1098
Telemetry::LABELS_CRLITE_RESULT::CertificateRevoked);
1099
break;
1100
case CRLiteLookupResult::LibraryFailure:
1101
Telemetry::AccumulateCategorical(
1102
Telemetry::LABELS_CRLITE_RESULT::LibraryFailure);
1103
break;
1104
case CRLiteLookupResult::NeverChecked:
1105
break;
1106
default:
1107
MOZ_ASSERT_UNREACHABLE("Unhandled CRLiteLookupResult value?");
1108
break;
1109
}
1110
1111
if (aCRLiteTelemetryInfo.mCRLiteFasterThanOCSPMillis.isSome()) {
1112
Telemetry::Accumulate(
1113
Telemetry::CRLITE_FASTER_THAN_OCSP_MS,
1114
static_cast<uint32_t>(
1115
*aCRLiteTelemetryInfo.mCRLiteFasterThanOCSPMillis));
1116
}
1117
if (aCRLiteTelemetryInfo.mOCSPFasterThanCRLiteMillis.isSome()) {
1118
Telemetry::Accumulate(
1119
Telemetry::OCSP_FASTER_THAN_CRLITE_MS,
1120
static_cast<uint32_t>(
1121
*aCRLiteTelemetryInfo.mOCSPFasterThanCRLiteMillis));
1122
}
1123
}
1124
1125
static void AuthCertificateSetResults(
1126
TransportSecurityInfo* aInfoObject, nsNSSCertificate* aCert,
1127
nsTArray<nsTArray<uint8_t>>&& aBuiltCertChain,
1128
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
1129
uint16_t aCertificateTransparencyStatus, EVStatus aEvStatus,
1130
bool aSucceeded) {
1131
MOZ_ASSERT(aInfoObject);
1132
1133
if (aSucceeded) {
1134
// Certificate verification succeeded. Delete any potential record of
1135
// certificate error bits.
1136
RememberCertErrorsTable::GetInstance().RememberCertHasError(aInfoObject,
1137
SECSuccess);
1138
1139
aInfoObject->SetServerCert(aCert, aEvStatus);
1140
aInfoObject->SetSucceededCertChain(std::move(aBuiltCertChain));
1141
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1142
("AuthCertificate setting NEW cert %p", aCert));
1143
1144
aInfoObject->SetCertificateTransparencyStatus(
1145
aCertificateTransparencyStatus);
1146
} else {
1147
// Certificate validation failed; store the peer certificate chain on
1148
// infoObject so it can be used for error reporting.
1149
aInfoObject->SetFailedCertChain(std::move(aPeerCertChain));
1150
}
1151
}
1152
1153
// Note: Takes ownership of |peerCertChain| if SECSuccess is not returned.
1154
Result AuthCertificate(
1155
CertVerifier& certVerifier, void* aPinArg,
1156
const UniqueCERTCertificate& cert,
1157
const nsTArray<nsTArray<uint8_t>>& peerCertChain,
1158
const nsACString& aHostName, const OriginAttributes& aOriginAttributes,
1159
const Maybe<nsTArray<uint8_t>>& stapledOCSPResponse,
1160
const Maybe<nsTArray<uint8_t>>& sctsFromTLSExtension,
1161
const Maybe<DelegatedCredentialInfo>& dcInfo, uint32_t providerFlags,
1162
Time time, uint32_t certVerifierFlags,
1163
/*out*/ UniqueCERTCertList& builtCertChain,
1164
/*out*/ SECOidTag& evOidPolicy,
1165
/*out*/ CertificateTransparencyInfo& certificateTransparencyInfo) {
1166
MOZ_ASSERT(cert);
1167
1168
// We want to avoid storing any intermediate cert information when browsing
1169
// in private, transient contexts.
1170
bool saveIntermediates =
1171
!(providerFlags & nsISocketProvider::NO_PERMANENT_STORAGE);
1172
1173
CertVerifier::OCSPStaplingStatus ocspStaplingStatus =
1174
CertVerifier::OCSP_STAPLING_NEVER_CHECKED;
1175
KeySizeStatus keySizeStatus = KeySizeStatus::NeverChecked;
1176
SHA1ModeResult sha1ModeResult = SHA1ModeResult::NeverChecked;
1177
PinningTelemetryInfo pinningTelemetryInfo;
1178
CRLiteTelemetryInfo crliteTelemetryInfo;
1179
1180
nsTArray<nsTArray<uint8_t>> peerCertsBytes;
1181
// Don't include the end-entity certificate.
1182
if (!peerCertChain.IsEmpty()) {
1183
peerCertsBytes.AppendElements(peerCertChain.Elements() + 1,
1184
peerCertChain.Length() - 1);
1185
}
1186
1187
Result rv = certVerifier.VerifySSLServerCert(
1188
cert, time, aPinArg, aHostName, builtCertChain, certVerifierFlags,
1189
Some(peerCertsBytes), stapledOCSPResponse, sctsFromTLSExtension, dcInfo,
1190
aOriginAttributes, saveIntermediates, &evOidPolicy, &ocspStaplingStatus,
1191
&keySizeStatus, &sha1ModeResult, &pinningTelemetryInfo,
1192
&certificateTransparencyInfo, &crliteTelemetryInfo);
1193
1194
CollectCertTelemetry(rv, evOidPolicy, ocspStaplingStatus, keySizeStatus,
1195
sha1ModeResult, pinningTelemetryInfo, builtCertChain,
1196
certificateTransparencyInfo, crliteTelemetryInfo);
1197
1198
return rv;
1199
}
1200
1201
/*static*/
1202
SECStatus SSLServerCertVerificationJob::Dispatch(
1203
uint64_t addrForLogging, void* aPinArg,
1204
const UniqueCERTCertificate& serverCert,
1205
nsTArray<nsTArray<uint8_t>>&& peerCertChain, const nsACString& aHostName,
1206
int32_t aPort, const OriginAttributes& aOriginAttributes,
1207
Maybe<nsTArray<uint8_t>>& stapledOCSPResponse,
1208
Maybe<nsTArray<uint8_t>>& sctsFromTLSExtension,
1209
Maybe<DelegatedCredentialInfo>& dcInfo, uint32_t providerFlags, Time time,
1210
PRTime prtime, uint32_t certVerifierFlags,
1211
SSLServerCertVerificationResult* aResultTask) {
1212
// Runs on the socket transport thread
1213
if (!aResultTask || !serverCert) {
1214
NS_ERROR("Invalid parameters for SSL server cert validation");
1215
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
1216
return SECFailure;
1217
}
1218
1219
if (!gCertVerificationThreadPool) {
1220
PR_SetError(PR_INVALID_STATE_ERROR, 0);
1221
return SECFailure;
1222
}
1223
1224
RefPtr<SSLServerCertVerificationJob> job(new SSLServerCertVerificationJob(
1225
addrForLogging, aPinArg, serverCert, std::move(peerCertChain), aHostName,
1226
aPort, aOriginAttributes, stapledOCSPResponse, sctsFromTLSExtension,
1227
dcInfo, providerFlags, time, prtime, certVerifierFlags, aResultTask));
1228
1229
nsresult nrv = gCertVerificationThreadPool->Dispatch(job, NS_DISPATCH_NORMAL);
1230
if (NS_FAILED(nrv)) {
1231
// We can't call SetCertVerificationResult here to change
1232
// mCertVerificationState because SetCertVerificationResult will call
1233
// libssl functions that acquire SSL locks that are already being held at
1234
// this point. However, we can set an error with PR_SetError and return
1235
// SECFailure, and the correct thing will happen (the error will be
1236
// propagated and this connection will be terminated).
1237
PRErrorCode error = nrv == NS_ERROR_OUT_OF_MEMORY ? PR_OUT_OF_MEMORY_ERROR
1238
: PR_INVALID_STATE_ERROR;
1239
PR_SetError(error, 0);
1240
return SECFailure;
1241
}
1242
1243
PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
1244
return SECWouldBlock;
1245
}
1246
1247
PRErrorCode AuthCertificateParseResults(
1248
uint64_t aPtrForLog, const nsACString& aHostName, int32_t aPort,
1249
const OriginAttributes& aOriginAttributes,
1250
const UniqueCERTCertificate& aCert, uint32_t aProviderFlags, PRTime aPRTime,
1251
PRErrorCode aDefaultErrorCodeToReport,
1252
/* out */ uint32_t& aCollectedErrors) {
1253
if (aDefaultErrorCodeToReport == 0) {
1254
MOZ_ASSERT_UNREACHABLE(
1255
"No error set during certificate validation failure");
1256
return SEC_ERROR_LIBRARY_FAILURE;
1257
}
1258
1259
uint32_t probeValue = MapCertErrorToProbeValue(aDefaultErrorCodeToReport);
1260
Telemetry::Accumulate(Telemetry::SSL_CERT_VERIFICATION_ERRORS, probeValue);
1261
1262
aCollectedErrors = 0;
1263
PRErrorCode errorCodeTrust = 0;
1264
PRErrorCode errorCodeMismatch = 0;
1265
PRErrorCode errorCodeTime = 0;
1266
if (DetermineCertOverrideErrors(aCert, aHostName, aPRTime,
1267
aDefaultErrorCodeToReport, aCollectedErrors,
1268
errorCodeTrust, errorCodeMismatch,
1269
errorCodeTime) != SECSuccess) {
1270
PRErrorCode errorCode = PR_GetError();
1271
MOZ_ASSERT(!ErrorIsOverridable(errorCode));
1272
if (errorCode == 0) {
1273
MOZ_ASSERT_UNREACHABLE(
1274
"No error set during DetermineCertOverrideErrors failure");
1275
return SEC_ERROR_LIBRARY_FAILURE;
1276
}
1277
return errorCode;
1278
}
1279
1280
if (!aCollectedErrors) {
1281
MOZ_ASSERT_UNREACHABLE("aCollectedErrors should not be 0");
1282
return SEC_ERROR_LIBRARY_FAILURE;
1283
}
1284
1285
bool overrideAllowed = false;
1286
if (NS_FAILED(OverrideAllowedForHost(aPtrForLog, aHostName, aOriginAttributes,
1287
aProviderFlags, overrideAllowed))) {
1288
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1289
("[0x%" PRIx64 "] AuthCertificateParseResults - "
1290
"OverrideAllowedForHost failed\n",
1291
aPtrForLog));
1292
return aDefaultErrorCodeToReport;
1293
}
1294
1295
if (overrideAllowed) {
1296
nsCOMPtr<nsICertOverrideService> overrideService =
1297
do_GetService(NS_CERTOVERRIDE_CONTRACTID);
1298
1299
uint32_t overrideBits = 0;
1300
uint32_t remainingDisplayErrors = aCollectedErrors;
1301
1302
// it is fine to continue without the nsICertOverrideService
1303
if (overrideService) {
1304
bool haveOverride;
1305
bool isTemporaryOverride; // we don't care
1306
RefPtr<nsIX509Cert> nssCert(nsNSSCertificate::Create(aCert.get()));
1307
if (!nssCert) {
1308
MOZ_ASSERT(false, "nsNSSCertificate::Create failed");
1309
return SEC_ERROR_NO_MEMORY;
1310
}
1311
nsresult rv = overrideService->HasMatchingOverride(
1312
aHostName, aPort, nssCert, &overrideBits, &isTemporaryOverride,
1313
&haveOverride);
1314
if (NS_SUCCEEDED(rv) && haveOverride) {
1315
// remove the errors that are already overriden
1316
remainingDisplayErrors &= ~overrideBits;
1317
}
1318
}
1319
1320
if (!remainingDisplayErrors) {
1321
// This can double- or triple-count one certificate with multiple
1322
// different types of errors. Since this is telemetry and we just
1323
// want a ballpark answer, we don't care.
1324
if (errorCodeTrust != 0) {
1325
uint32_t probeValue = MapOverridableErrorToProbeValue(errorCodeTrust);
1326
Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES, probeValue);
1327
}
1328
if (errorCodeMismatch != 0) {
1329
uint32_t probeValue =
1330
MapOverridableErrorToProbeValue(errorCodeMismatch);
1331
Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES, probeValue);
1332
}
1333
if (errorCodeTime != 0) {
1334
uint32_t probeValue = MapOverridableErrorToProbeValue(errorCodeTime);
1335
Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES, probeValue);
1336
}
1337
1338
// all errors are covered by override rules, so let's accept the cert
1339
MOZ_LOG(
1340
gPIPNSSLog, LogLevel::Debug,
1341
("[0x%" PRIx64 "] All errors covered by override rules", aPtrForLog));
1342
return 0;
1343
}
1344
} else {
1345
MOZ_LOG(
1346
gPIPNSSLog, LogLevel::Debug,
1347
("[0x%" PRIx64 "] HSTS or HPKP - no overrides allowed\n", aPtrForLog));
1348
}
1349
1350
MOZ_LOG(
1351
gPIPNSSLog, LogLevel::Debug,
1352
("[0x%" PRIx64 "] Certificate error was not overridden\n", aPtrForLog));
1353
1354
// pick the error code to report by priority
1355
return errorCodeTrust
1356
? errorCodeTrust
1357
: errorCodeMismatch
1358
? errorCodeMismatch
1359
: errorCodeTime ? errorCodeTime : aDefaultErrorCodeToReport;
1360
}
1361
1362
NS_IMETHODIMP
1363
SSLServerCertVerificationJob::Run() {
1364
// Runs on a cert verification thread and only on parent process.
1365
MOZ_ASSERT(XRE_IsParentProcess());
1366
1367
MOZ_LOG(
1368
gPIPNSSLog, LogLevel::Debug,
1369
("[%" PRIx64 "] SSLServerCertVerificationJob::Run\n", mAddrForLogging));
1370
1371
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
1372
if (!certVerifier) {
1373
PR_SetError(SEC_ERROR_NOT_INITIALIZED, 0);
1374
return NS_OK;
1375
}
1376
1377
TimeStamp jobStartTime = TimeStamp::Now();
1378
UniqueCERTCertList builtCertChain;
1379
SECOidTag evOidPolicy;
1380
CertificateTransparencyInfo certificateTransparencyInfo;
1381
Result rv = AuthCertificate(
1382
*certVerifier, mPinArg, mCert, mPeerCertChain, mHostName,
1383
mOriginAttributes, mStapledOCSPResponse, mSCTsFromTLSExtension, mDCInfo,
1384
mProviderFlags, mTime, mCertVerifierFlags, builtCertChain, evOidPolicy,
1385
certificateTransparencyInfo);
1386
1387
RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(mCert.get());
1388
nsTArray<nsTArray<uint8_t>> certBytesArray;
1389
if (rv == Success) {
1390
Telemetry::AccumulateTimeDelta(
1391
Telemetry::SSL_SUCCESFUL_CERT_VALIDATION_TIME_MOZILLAPKIX, jobStartTime,
1392
TimeStamp::Now());
1393
Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES, 1);
1394
1395
certBytesArray =
1396
TransportSecurityInfo::CreateCertBytesArray(builtCertChain);
1397
EVStatus evStatus =
1398
evOidPolicy == SEC_OID_UNKNOWN ? EVStatus::NotEV : EVStatus::EV;
1399
mResultTask->Dispatch(
1400
nsc, std::move(certBytesArray), std::move(mPeerCertChain),
1401
TransportSecurityInfo::ConvertCertificateTransparencyInfoToStatus(
1402
certificateTransparencyInfo),
1403
evStatus, true, 0, 0);
1404
return NS_OK;
1405
}
1406
1407
Telemetry::AccumulateTimeDelta(
1408
Telemetry::SSL_INITIAL_FAILED_CERT_VALIDATION_TIME_MOZILLAPKIX,
1409
jobStartTime, TimeStamp::Now());
1410
1411
PRErrorCode error = MapResultToPRErrorCode(rv);
1412
uint32_t collectedErrors = 0;
1413
PRErrorCode finalError = AuthCertificateParseResults(
1414
mAddrForLogging, mHostName, mPort, mOriginAttributes, mCert,
1415
mProviderFlags, mPRTime, error, collectedErrors);
1416
1417
// NB: finalError may be 0 here, in which the connection will continue.
1418
mResultTask->Dispatch(
1419
nsc, std::move(certBytesArray), std::move(mPeerCertChain),
1420
nsITransportSecurityInfo::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE,
1421
EVStatus::NotEV, false, finalError, collectedErrors);
1422
return NS_OK;
1423
}
1424
1425
} // unnamed namespace
1426
1427
// Takes information needed for cert verification, does some consistency
1428
// checks and calls SSLServerCertVerificationJob::Dispatch.
1429
SECStatus AuthCertificateHookInternal(
1430
TransportSecurityInfo* infoObject, const void* aPtrForLogging,
1431
const UniqueCERTCertificate& serverCert,
1432
nsTArray<nsTArray<uint8_t>>&& peerCertChain,
1433
Maybe<nsTArray<uint8_t>>& stapledOCSPResponse,
1434
Maybe<nsTArray<uint8_t>>& sctsFromTLSExtension,
1435
Maybe<DelegatedCredentialInfo>& dcInfo, uint32_t providerFlags,
1436
uint32_t certVerifierFlags) {
1437
// Runs on the socket transport thread
1438
1439
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1440
("[%p] starting AuthCertificateHookInternal\n", aPtrForLogging));
1441
1442
if (!infoObject || !serverCert) {
1443
PR_SetError(PR_INVALID_STATE_ERROR, 0);
1444
return SECFailure;
1445
}
1446
1447
bool onSTSThread;
1448
nsresult nrv;
1449
nsCOMPtr<nsIEventTarget> sts =
1450
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &nrv);
1451
if (NS_SUCCEEDED(nrv)) {
1452
nrv = sts->IsOnCurrentThread(&onSTSThread);
1453
}
1454
1455
if (NS_FAILED(nrv)) {
1456
NS_ERROR("Could not get STS service or IsOnCurrentThread failed");
1457
PR_SetError(PR_UNKNOWN_ERROR, 0);
1458
return SECFailure;
1459
}
1460
1461
MOZ_ASSERT(onSTSThread);
1462
1463
if (!onSTSThread) {
1464
PR_SetError(PR_INVALID_STATE_ERROR, 0);
1465
return SECFailure;
1466
}
1467
1468
uint64_t addr = reinterpret_cast<uintptr_t>(aPtrForLogging);
1469
RefPtr<SSLServerCertVerificationResult> resultTask =
1470
new SSLServerCertVerificationResult(infoObject);
1471
// We *must* do certificate verification on a background thread because
1472
// we need the socket transport thread to be free for our OCSP requests,
1473
// and we *want* to do certificate verification on a background thread
1474
// because of the performance benefits of doing so.
1475
return SSLServerCertVerificationJob::Dispatch(
1476
addr, infoObject, serverCert, std::move(peerCertChain),
1477
infoObject->GetHostName(), infoObject->GetPort(),
1478
infoObject->GetOriginAttributes(), stapledOCSPResponse,
1479
sctsFromTLSExtension, dcInfo, providerFlags, Now(), PR_Now(),
1480
certVerifierFlags, resultTask);
1481
}
1482
1483
// Extracts whatever information we need out of fd (using SSL_*) and passes it
1484
// to AuthCertificateHookInternal. AuthCertificateHookInternal will call
1485
// SSLServerCertVerificationJob::Dispatch. SSLServerCertVerificationJob
1486
// should never do anything with fd except logging.
1487
SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checkSig,
1488
PRBool isServer) {
1489
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1490
("[%p] starting AuthCertificateHook\n", fd));
1491
1492
// Modern libssl always passes PR_TRUE for checkSig, and we have no means of
1493
// doing verification without checking signatures.
1494
MOZ_ASSERT(checkSig, "AuthCertificateHook: checkSig unexpectedly false");
1495
1496
// PSM never causes libssl to call this function with PR_TRUE for isServer,
1497
// and many things in PSM assume that we are a client.
1498
MOZ_ASSERT(!isServer, "AuthCertificateHook: isServer unexpectedly true");
1499
1500
nsNSSSocketInfo* socketInfo = static_cast<nsNSSSocketInfo*>(arg);
1501
1502
UniqueCERTCertificate serverCert(SSL_PeerCertificate(fd));
1503
1504
if (!checkSig || isServer || !socketInfo || !serverCert) {
1505
PR_SetError(PR_INVALID_STATE_ERROR, 0);
1506
return SECFailure;
1507
}
1508
socketInfo->SetFullHandshake();
1509
1510
if (BlockServerCertChangeForSpdy(socketInfo, serverCert) != SECSuccess) {
1511
return SECFailure;
1512
}
1513
1514
UniqueCERTCertList peerCertChain(SSL_PeerCertificateChain(fd));
1515
if (!peerCertChain) {
1516
PR_SetError(PR_INVALID_STATE_ERROR, 0);
1517
return SECFailure;
1518
}
1519
1520
nsTArray<nsTArray<uint8_t>> peerCertsBytes =
1521
TransportSecurityInfo::CreateCertBytesArray(peerCertChain);
1522
1523
// SSL_PeerStapledOCSPResponses will never return a non-empty response if
1524
// OCSP stapling wasn't enabled because libssl wouldn't have let the server
1525
// return a stapled OCSP response.
1526
// We don't own these pointers.
1527
const SECItemArray* csa = SSL_PeerStapledOCSPResponses(fd);
1528
Maybe<nsTArray<uint8_t>> stapledOCSPResponse;
1529
// we currently only support single stapled responses
1530
if (csa && csa->len == 1) {
1531
stapledOCSPResponse.emplace();
1532
stapledOCSPResponse->SetCapacity(csa->items[0].len);
1533
stapledOCSPResponse->AppendElements(csa->items[0].data, csa->items[0].len);
1534
}
1535
1536
Maybe<nsTArray<uint8_t>> sctsFromTLSExtension;
1537
const SECItem* sctsFromTLSExtensionSECItem = SSL_PeerSignedCertTimestamps(fd);
1538
if (sctsFromTLSExtensionSECItem) {
1539
sctsFromTLSExtension.emplace();
1540
sctsFromTLSExtension->SetCapacity(sctsFromTLSExtensionSECItem->len);
1541
sctsFromTLSExtension->AppendElements(sctsFromTLSExtensionSECItem->data,
1542
sctsFromTLSExtensionSECItem->len);
1543
}
1544
1545
uint32_t providerFlags = 0;
1546
socketInfo->GetProviderFlags(&providerFlags);
1547
1548
uint32_t certVerifierFlags = 0;
1549
if (!socketInfo->SharedState().IsOCSPStaplingEnabled() ||
1550
!socketInfo->SharedState().IsOCSPMustStapleEnabled()) {
1551
certVerifierFlags |= CertVerifier::FLAG_TLS_IGNORE_STATUS_REQUEST;
1552
}
1553
1554
// Get DC information
1555
Maybe<DelegatedCredentialInfo> dcInfo;
1556
SSLPreliminaryChannelInfo channelPreInfo;
1557
SECStatus rv = SSL_GetPreliminaryChannelInfo(fd, &channelPreInfo,
1558
sizeof(channelPreInfo));
1559
if (rv != SECSuccess) {
1560
PR_SetError(PR_INVALID_STATE_ERROR, 0);
1561
return SECFailure;
1562
}
1563
if (channelPreInfo.peerDelegCred) {
1564
dcInfo.emplace(DelegatedCredentialInfo(channelPreInfo.signatureScheme,
1565
channelPreInfo.authKeyBits));
1566
}
1567
1568
socketInfo->SetCertVerificationWaiting();
1569
return AuthCertificateHookInternal(socketInfo, static_cast<const void*>(fd),
1570
serverCert, std::move(peerCertsBytes),
1571
stapledOCSPResponse, sctsFromTLSExtension,
1572
dcInfo, providerFlags, certVerifierFlags);
1573
}
1574
1575
// Takes information needed for cert verification, does some consistency
1576
// checks and calls SSLServerCertVerificationJob::Dispatch.
1577
// This function is used for Quic.
1578
SECStatus AuthCertificateHookWithInfo(
1579
TransportSecurityInfo* infoObject, const void* aPtrForLogging,
1580
nsTArray<nsTArray<uint8_t>>&& peerCertChain,
1581
Maybe<nsTArray<nsTArray<uint8_t>>>& stapledOCSPResponses,
1582
Maybe<nsTArray<uint8_t>>& sctsFromTLSExtension, uint32_t providerFlags) {
1583
if (peerCertChain.IsEmpty()) {
1584
PR_SetError(PR_INVALID_STATE_ERROR, 0);
1585
return SECFailure;
1586
}
1587
1588
SECItem der = {SECItemType::siBuffer, peerCertChain[0].Elements(),
1589
(uint32_t)peerCertChain[0].Length()};
1590
UniqueCERTCertificate cert(CERT_NewTempCertificate(
1591
CERT_GetDefaultCertDB(), &der, nullptr, false, true));
1592
if (!cert) {
1593
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1594
("AuthCertificateHookWithInfo: cert failed"));
1595
return SECFailure;
1596
}
1597
1598
// we currently only support single stapled responses
1599
Maybe<nsTArray<uint8_t>> stapledOCSPResponse;
1600
if (stapledOCSPResponses && (stapledOCSPResponses->Length() == 1)) {
1601
stapledOCSPResponse.emplace(stapledOCSPResponses->ElementAt(0));
1602
}
1603
1604
uint32_t certVerifierFlags = 0;
1605
// QuicTransportSecInfo does not have a SharedState as nsNSSSocketInfo.
1606
// Here we need prefs for ocsp. This are prefs they are the same for
1607
// PublicSSLState and PrivateSSLState, just take them from one of them.
1608
if (!PublicSSLState()->IsOCSPStaplingEnabled() ||
1609
!PublicSSLState()->IsOCSPMustStapleEnabled()) {
1610
certVerifierFlags |= CertVerifier::FLAG_TLS_IGNORE_STATUS_REQUEST;
1611
}
1612
1613
// Need to update Quic stack to reflect the PreliminaryInfo fields
1614
// for Delegated Credentials.
1615
Maybe<DelegatedCredentialInfo> dcInfo;
1616
1617
return AuthCertificateHookInternal(infoObject, aPtrForLogging, cert,
1618
std::move(peerCertChain),
1619
stapledOCSPResponse, sctsFromTLSExtension,
1620
dcInfo, providerFlags, certVerifierFlags);
1621
}
1622
1623
SSLServerCertVerificationResult::SSLServerCertVerificationResult(
1624
TransportSecurityInfo* infoObject)
1625
: Runnable("psm::SSLServerCertVerificationResult"),
1626
mInfoObject(infoObject),
1627
mCertificateTransparencyStatus(0),
1628
mEVStatus(EVStatus::NotEV),
1629
mSucceeded(false),
1630
mFinalError(0),
1631
mCollectedErrors(0) {}
1632
1633
void SSLServerCertVerificationResult::Dispatch(
1634
nsNSSCertificate* aCert, nsTArray<nsTArray<uint8_t>>&& aBuiltChain,
1635
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
1636
uint16_t aCertificateTransparencyStatus, EVStatus aEVStatus,
1637
bool aSucceeded, PRErrorCode aFinalError, uint32_t aCollectedErrors) {
1638
mCert = aCert;
1639
mBuiltChain = std::move(aBuiltChain);
1640
mPeerCertChain = std::move(aPeerCertChain);
1641
mCertificateTransparencyStatus = aCertificateTransparencyStatus;
1642
mEVStatus = aEVStatus;
1643
mSucceeded = aSucceeded;
1644
mFinalError = aFinalError;
1645
mCollectedErrors = aCollectedErrors;
1646
1647
nsresult rv;
1648
nsCOMPtr<nsIEventTarget> stsTarget =
1649
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
1650
MOZ_ASSERT(stsTarget, "Failed to get socket transport service event target");
1651
rv = stsTarget->Dispatch(this, NS_DISPATCH_NORMAL);
1652
MOZ_ASSERT(NS_SUCCEEDED(rv),
1653
"Failed to dispatch SSLServerCertVerificationResult");
1654
}
1655
1656
NS_IMETHODIMP
1657
SSLServerCertVerificationResult::Run() {
1658
#ifdef DEBUG
1659
bool onSTSThread = false;
1660
nsresult nrv;
1661
nsCOMPtr<nsIEventTarget> sts =
1662
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &nrv);
1663
if (NS_SUCCEEDED(nrv)) {
1664
nrv = sts->IsOnCurrentThread(&onSTSThread);
1665
}
1666
1667
MOZ_ASSERT(onSTSThread);
1668
#endif
1669
1670
AuthCertificateSetResults(
1671
mInfoObject, mCert, std::move(mBuiltChain), std::move(mPeerCertChain),
1672
mCertificateTransparencyStatus, mEVStatus, mSucceeded);
1673
1674
if (!mSucceeded && mCollectedErrors != 0) {
1675
mInfoObject->SetStatusErrorBits(mCert, mCollectedErrors);
1676
}
1677
mInfoObject->SetCertVerificationResult(mFinalError);
1678
return NS_OK;
1679
}
1680
1681
} // namespace psm
1682
} // namespace mozilla