1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */
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.
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.
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.
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.
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
40 // Timeline of events (for connections managed by the socket transport service):
42 // * libssl calls SSLServerCertVerificationJob::Dispatch on the socket
44 // * SSLServerCertVerificationJob::Dispatch queues a job
45 // (instance of SSLServerCertVerificationJob) to its background thread
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.
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 NSSSocketControl and the
69 // PSM NSS I/O layer are not thread-safe, and because we need the event to
70 // interrupt the PR_Poll that may waiting for I/O on the socket for which we
71 // are validating the cert.
73 // When socket process is enabled, libssl is running on socket process. To
74 // perform certificate authentication with CertVerifier, we have to send all
75 // needed information to parent process and send the result back to socket
76 // process via IPC. The workflow is described below.
77 // 1. In AuthCertificateHookInternal(), we call RemoteProcessCertVerification()
78 // instead of SSLServerCertVerificationJob::Dispatch when we are on socket
80 // 2. In RemoteProcessCertVerification(), PVerifySSLServerCert actors will be
81 // created on IPDL background thread for carrying needed information via IPC.
82 // 3. On parent process, VerifySSLServerCertParent is created and it calls
83 // SSLServerCertVerificationJob::Dispatch for doing certificate verification
84 // on one of CertVerificationThreads.
85 // 4. When validation is done, OnVerifiedSSLServerCertSuccess IPC message is
86 // sent through the IPDL background thread when
87 // CertVerifier::VerifySSLServerCert returns Success. Otherwise,
88 // OnVerifiedSSLServerCertFailure is sent.
89 // 5. After setp 4, PVerifySSLServerCert actors will be released. The
90 // verification result will be dispatched via
91 // SSLServerCertVerificationResult.
93 #include "SSLServerCertVerification.h"
97 #include "CertVerifier.h"
98 #include "CryptoTask.h"
99 #include "ExtendedValidation.h"
100 #include "NSSCertDBTrustDomain.h"
101 #include "NSSSocketControl.h"
102 #include "PSMRunnable.h"
103 #include "RootCertificateTelemetryUtils.h"
104 #include "ScopedNSSTypes.h"
105 #include "SharedCertVerifier.h"
106 #include "SharedSSLState.h"
107 #include "VerifySSLServerCertChild.h"
109 #include "mozilla/Assertions.h"
110 #include "mozilla/Casting.h"
111 #include "mozilla/RefPtr.h"
112 #include "mozilla/Telemetry.h"
113 #include "mozilla/UniquePtr.h"
114 #include "mozilla/Unused.h"
115 #include "nsComponentManagerUtils.h"
116 #include "nsContentUtils.h"
117 #include "nsICertOverrideService.h"
118 #include "nsIPublicKeyPinningService.h"
119 #include "nsISiteSecurityService.h"
120 #include "nsISocketProvider.h"
121 #include "nsThreadPool.h"
122 #include "nsNetUtil.h"
123 #include "nsNSSCertificate.h"
124 #include "nsNSSComponent.h"
125 #include "nsNSSIOLayer.h"
126 #include "nsServiceManagerUtils.h"
127 #include "nsString.h"
128 #include "nsURLHelper.h"
129 #include "nsXPCOMCIDInternal.h"
130 #include "mozpkix/pkix.h"
131 #include "mozpkix/pkixcheck.h"
132 #include "mozpkix/pkixnss.h"
133 #include "mozpkix/pkixutil.h"
140 extern mozilla::LazyLogModule gPIPNSSLog
;
142 using namespace mozilla::pkix
;
147 // do not use a nsCOMPtr to avoid static initializer/destructor
148 nsIThreadPool
* gCertVerificationThreadPool
= nullptr;
150 // Called when the socket transport thread starts, to initialize the SSL cert
151 // verification thread pool. By tying the thread pool startup/shutdown directly
152 // to the STS thread's lifetime, we ensure that they are *always* available for
153 // SSL connections and that there are no races during startup and especially
154 // shutdown. (Previously, we have had multiple problems with races in PSM
155 // background threads, and the race-prevention/shutdown logic used there is
156 // brittle. Since this service is critical to things like downloading updates,
157 // we take no chances.) Also, by doing things this way, we avoid the need for
158 // locks, since gCertVerificationThreadPool is only ever accessed on the socket
160 void InitializeSSLServerCertVerificationThreads() {
161 // TODO: tuning, make parameters preferences
162 gCertVerificationThreadPool
= new nsThreadPool();
163 NS_ADDREF(gCertVerificationThreadPool
);
165 (void)gCertVerificationThreadPool
->SetIdleThreadLimit(5);
166 (void)gCertVerificationThreadPool
->SetIdleThreadTimeout(30 * 1000);
167 (void)gCertVerificationThreadPool
->SetThreadLimit(5);
168 (void)gCertVerificationThreadPool
->SetName("SSL Cert"_ns
);
171 // Called when the socket transport thread finishes, to destroy the thread
172 // pool. Since the socket transport service has stopped processing events, it
173 // will not attempt any more SSL I/O operations, so it is clearly safe to shut
174 // down the SSL cert verification infrastructure. Also, the STS will not
175 // dispatch many SSL verification result events at this point, so any pending
176 // cert verifications will (correctly) fail at the point they are dispatched.
178 // The other shutdown race condition that is possible is a race condition with
179 // shutdown of the nsNSSComponent service. We use the
180 // nsNSSShutdownPreventionLock where needed (not here) to prevent that.
181 void StopSSLServerCertVerificationThreads() {
182 if (gCertVerificationThreadPool
) {
183 gCertVerificationThreadPool
->Shutdown();
184 NS_RELEASE(gCertVerificationThreadPool
);
188 // A probe value of 1 means "no error".
189 uint32_t MapOverridableErrorToProbeValue(PRErrorCode errorCode
) {
191 case SEC_ERROR_UNKNOWN_ISSUER
:
193 case SEC_ERROR_CA_CERT_INVALID
:
195 case SEC_ERROR_UNTRUSTED_ISSUER
:
197 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE
:
199 case SEC_ERROR_UNTRUSTED_CERT
:
201 case SEC_ERROR_INADEQUATE_KEY_USAGE
:
203 case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
:
205 case SSL_ERROR_BAD_CERT_DOMAIN
:
207 case SEC_ERROR_EXPIRED_CERTIFICATE
:
209 case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY
:
211 case mozilla::pkix::MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA
:
213 case mozilla::pkix::MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE
:
215 case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE
:
217 case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE
:
219 case SEC_ERROR_INVALID_TIME
:
221 case mozilla::pkix::MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME
:
223 case mozilla::pkix::MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED
:
225 case mozilla::pkix::MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT
:
227 case mozilla::pkix::MOZILLA_PKIX_ERROR_MITM_DETECTED
:
231 "Unknown certificate error code. Does MapOverridableErrorToProbeValue "
232 "handle everything in CategorizeCertificateError?");
236 static uint32_t MapCertErrorToProbeValue(PRErrorCode errorCode
) {
239 // see security/pkix/include/pkix/Result.h
240 #define MOZILLA_PKIX_MAP(name, value, nss_name) \
242 probeValue = value; \
244 MOZILLA_PKIX_MAP_LIST
245 #undef MOZILLA_PKIX_MAP
250 // Since FATAL_ERROR_FLAG is 0x800, fatal error values are much larger than
251 // non-fatal error values. To conserve space, we remap these so they start at
252 // (decimal) 90 instead of 0x800. Currently there are ~50 non-fatal errors
253 // mozilla::pkix might return, so saving space for 90 should be sufficient
254 // (similarly, there are 4 fatal errors, so saving space for 10 should also
257 FATAL_ERROR_FLAG
== 0x800,
258 "mozilla::pkix::FATAL_ERROR_FLAG is not what we were expecting");
259 if (probeValue
& FATAL_ERROR_FLAG
) {
260 probeValue
^= FATAL_ERROR_FLAG
;
266 // If the given PRErrorCode is an overridable certificate error, return which
267 // category (trust, time, domain mismatch) it falls in. If it is not
268 // overridable, return Nothing.
269 Maybe
<nsITransportSecurityInfo::OverridableErrorCategory
>
270 CategorizeCertificateError(PRErrorCode certificateError
) {
271 switch (certificateError
) {
272 case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
:
273 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE
:
274 case SEC_ERROR_UNKNOWN_ISSUER
:
275 case SEC_ERROR_CA_CERT_INVALID
:
276 case mozilla::pkix::MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED
:
277 case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY
:
278 case mozilla::pkix::MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME
:
279 case mozilla::pkix::MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE
:
280 case mozilla::pkix::MOZILLA_PKIX_ERROR_MITM_DETECTED
:
281 case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE
:
282 case mozilla::pkix::MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT
:
283 case mozilla::pkix::MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA
:
285 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TRUST
);
287 case SSL_ERROR_BAD_CERT_DOMAIN
:
289 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_DOMAIN
);
291 case SEC_ERROR_INVALID_TIME
:
292 case SEC_ERROR_EXPIRED_CERTIFICATE
:
293 case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE
:
295 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TIME
);
303 // Helper function to determine if overrides are allowed for this host.
304 // Overrides are not allowed for known HSTS hosts or hosts with pinning
305 // information. However, IP addresses can never be HSTS hosts and don't have
306 // pinning information.
307 static nsresult
OverrideAllowedForHost(
308 uint64_t aPtrForLog
, const nsACString
& aHostname
,
309 const OriginAttributes
& aOriginAttributes
, /*out*/ bool& aOverrideAllowed
) {
310 aOverrideAllowed
= false;
312 // If this is an IP address, overrides are allowed, because an IP address is
313 // never an HSTS host. nsISiteSecurityService takes this into account
314 // already, but the real problem here is that calling NS_NewURI with an IPv6
315 // address fails. We do this to avoid that. A more comprehensive fix would be
316 // to have Necko provide an nsIURI to PSM and to use that here (and
317 // everywhere). However, that would be a wide-spanning change.
318 if (net_IsValidIPv6Addr(aHostname
)) {
319 aOverrideAllowed
= true;
323 // If this is an HTTP Strict Transport Security host or a pinned host and the
324 // certificate is bad, don't allow overrides (RFC 6797 section 12.1).
325 bool strictTransportSecurityEnabled
= false;
326 bool isStaticallyPinned
= false;
327 nsCOMPtr
<nsISiteSecurityService
> sss(do_GetService(NS_SSSERVICE_CONTRACTID
));
330 gPIPNSSLog
, LogLevel::Debug
,
331 ("[0x%" PRIx64
"] Couldn't get nsISiteSecurityService to check HSTS",
333 return NS_ERROR_FAILURE
;
336 nsCOMPtr
<nsIURI
> uri
;
337 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), "https://"_ns
+ aHostname
);
339 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
340 ("[0x%" PRIx64
"] Creating new URI failed", aPtrForLog
));
345 sss
->IsSecureURI(uri
, aOriginAttributes
, &strictTransportSecurityEnabled
);
347 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
348 ("[0x%" PRIx64
"] checking for HSTS failed", aPtrForLog
));
352 nsCOMPtr
<nsIPublicKeyPinningService
> pkps
=
353 do_GetService(NS_PKPSERVICE_CONTRACTID
, &rv
);
355 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
357 "] Couldn't get nsIPublicKeyPinningService to check pinning",
359 return NS_ERROR_FAILURE
;
361 rv
= pkps
->HostHasPins(uri
, &isStaticallyPinned
);
363 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
364 ("[0x%" PRIx64
"] checking for static pin failed", aPtrForLog
));
368 aOverrideAllowed
= !strictTransportSecurityEnabled
&& !isStaticallyPinned
;
372 // This function assumes that we will only use the SPDY connection coalescing
373 // feature on connections where we have negotiated SPDY using NPN. If we ever
374 // talk SPDY without having negotiated it with SPDY, this code will give wrong
375 // and perhaps unsafe results.
377 // Returns SECSuccess on the initial handshake of all connections, on
378 // renegotiations for any connections where we did not negotiate SPDY, or on any
379 // SPDY connection where the server's certificate did not change.
381 // Prohibit changing the server cert only if we negotiated SPDY,
382 // in order to support SPDY's cross-origin connection pooling.
383 static SECStatus
BlockServerCertChangeForSpdy(
384 NSSSocketControl
* socketControl
, const UniqueCERTCertificate
& serverCert
) {
385 if (!socketControl
->IsHandshakeCompleted()) {
386 // first handshake on this connection, not a
391 // Filter out sockets that did not neogtiate SPDY via NPN
392 nsCOMPtr
<nsITransportSecurityInfo
> securityInfo
;
393 nsresult rv
= socketControl
->GetSecurityInfo(getter_AddRefs(securityInfo
));
394 MOZ_ASSERT(NS_SUCCEEDED(rv
), "GetSecurityInfo() failed during renegotiation");
395 if (NS_FAILED(rv
) || !securityInfo
) {
396 PR_SetError(SEC_ERROR_LIBRARY_FAILURE
, 0);
399 nsAutoCString negotiatedNPN
;
400 rv
= securityInfo
->GetNegotiatedNPN(negotiatedNPN
);
401 MOZ_ASSERT(NS_SUCCEEDED(rv
),
402 "GetNegotiatedNPN() failed during renegotiation");
404 if (NS_SUCCEEDED(rv
) && !StringBeginsWith(negotiatedNPN
, "spdy/"_ns
)) {
407 // If GetNegotiatedNPN() failed we will assume spdy for safety's safe
409 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
410 ("BlockServerCertChangeForSpdy failed GetNegotiatedNPN() call."
414 // Check to see if the cert has actually changed
415 nsCOMPtr
<nsIX509Cert
> cert(socketControl
->GetServerCert());
417 PR_SetError(SEC_ERROR_LIBRARY_FAILURE
, 0);
420 nsTArray
<uint8_t> certDER
;
421 if (NS_FAILED(cert
->GetRawDER(certDER
))) {
422 PR_SetError(SEC_ERROR_LIBRARY_FAILURE
, 0);
425 if (certDER
.Length() == serverCert
->derCert
.len
&&
426 memcmp(certDER
.Elements(), serverCert
->derCert
.data
, certDER
.Length()) ==
431 // Report an error - changed cert is confirmed
432 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
433 ("SPDY refused to allow new cert during renegotiation"));
434 PR_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED
, 0);
438 void GatherTelemetryForSingleSCT(const ct::VerifiedSCT
& verifiedSct
) {
439 // See SSL_SCTS_ORIGIN in Histograms.json.
441 switch (verifiedSct
.origin
) {
442 case ct::VerifiedSCT::Origin::Embedded
:
445 case ct::VerifiedSCT::Origin::TLSExtension
:
448 case ct::VerifiedSCT::Origin::OCSPResponse
:
452 MOZ_ASSERT_UNREACHABLE("Unexpected VerifiedSCT::Origin type");
454 Telemetry::Accumulate(Telemetry::SSL_SCTS_ORIGIN
, origin
);
456 // See SSL_SCTS_VERIFICATION_STATUS in Histograms.json.
457 uint32_t verificationStatus
= 0;
458 switch (verifiedSct
.status
) {
459 case ct::VerifiedSCT::Status::Valid
:
460 verificationStatus
= 1;
462 case ct::VerifiedSCT::Status::UnknownLog
:
463 verificationStatus
= 2;
465 case ct::VerifiedSCT::Status::InvalidSignature
:
466 verificationStatus
= 3;
468 case ct::VerifiedSCT::Status::InvalidTimestamp
:
469 verificationStatus
= 4;
471 case ct::VerifiedSCT::Status::ValidFromDisqualifiedLog
:
472 verificationStatus
= 5;
475 MOZ_ASSERT_UNREACHABLE("Unexpected VerifiedSCT::Status type");
477 Telemetry::Accumulate(Telemetry::SSL_SCTS_VERIFICATION_STATUS
,
481 void GatherCertificateTransparencyTelemetry(
482 const nsTArray
<uint8_t>& rootCert
, bool isEV
,
483 const CertificateTransparencyInfo
& info
) {
485 // No telemetry is gathered when CT is disabled.
489 for (const ct::VerifiedSCT
& sct
: info
.verifyResult
.verifiedScts
) {
490 GatherTelemetryForSingleSCT(sct
);
493 // Decoding errors are reported to the 0th bucket
494 // of the SSL_SCTS_VERIFICATION_STATUS enumerated probe.
495 for (size_t i
= 0; i
< info
.verifyResult
.decodingErrors
; ++i
) {
496 Telemetry::Accumulate(Telemetry::SSL_SCTS_VERIFICATION_STATUS
, 0);
499 // Handle the histogram of SCTs counts.
501 static_cast<uint32_t>(info
.verifyResult
.verifiedScts
.size());
502 // Note that sctsCount can also be 0 in case we've received SCT binary data,
503 // but it failed to parse (e.g. due to unsupported CT protocol version).
504 Telemetry::Accumulate(Telemetry::SSL_SCTS_PER_CONNECTION
, sctsCount
);
506 // Report CT Policy compliance by CA.
507 switch (info
.policyCompliance
) {
508 case ct::CTPolicyCompliance::Compliant
:
509 AccumulateTelemetryForRootCA(
510 Telemetry::SSL_CT_POLICY_COMPLIANT_CONNECTIONS_BY_CA
, rootCert
);
512 case ct::CTPolicyCompliance::NotEnoughScts
:
513 case ct::CTPolicyCompliance::NotDiverseScts
:
514 AccumulateTelemetryForRootCA(
515 Telemetry::SSL_CT_POLICY_NON_COMPLIANT_CONNECTIONS_BY_CA
, rootCert
);
517 case ct::CTPolicyCompliance::Unknown
:
519 MOZ_ASSERT_UNREACHABLE("Unexpected CTPolicyCompliance type");
523 // This function collects telemetry about certs. It will be called on one of
524 // CertVerificationThread. When the socket process is used this will be called
525 // on the parent process.
526 static void CollectCertTelemetry(
527 mozilla::pkix::Result aCertVerificationResult
, EVStatus aEVStatus
,
528 CertVerifier::OCSPStaplingStatus aOcspStaplingStatus
,
529 KeySizeStatus aKeySizeStatus
,
530 const PinningTelemetryInfo
& aPinningTelemetryInfo
,
531 const nsTArray
<nsTArray
<uint8_t>>& aBuiltCertChain
,
532 const CertificateTransparencyInfo
& aCertificateTransparencyInfo
) {
533 uint32_t evStatus
= (aCertVerificationResult
!= Success
) ? 0 // 0 = Failure
534 : (aEVStatus
!= EVStatus::EV
) ? 1 // 1 = DV
536 Telemetry::Accumulate(Telemetry::CERT_EV_STATUS
, evStatus
);
538 if (aOcspStaplingStatus
!= CertVerifier::OCSP_STAPLING_NEVER_CHECKED
) {
539 Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING
, aOcspStaplingStatus
);
542 if (aKeySizeStatus
!= KeySizeStatus::NeverChecked
) {
543 Telemetry::Accumulate(Telemetry::CERT_CHAIN_KEY_SIZE_STATUS
,
544 static_cast<uint32_t>(aKeySizeStatus
));
547 if (aPinningTelemetryInfo
.accumulateForRoot
) {
548 Telemetry::Accumulate(Telemetry::CERT_PINNING_FAILURES_BY_CA
,
549 aPinningTelemetryInfo
.rootBucket
);
552 if (aPinningTelemetryInfo
.accumulateResult
) {
553 MOZ_ASSERT(aPinningTelemetryInfo
.certPinningResultHistogram
.isSome());
554 Telemetry::Accumulate(
555 aPinningTelemetryInfo
.certPinningResultHistogram
.value(),
556 aPinningTelemetryInfo
.certPinningResultBucket
);
559 if (aCertVerificationResult
== Success
&& aBuiltCertChain
.Length() > 0) {
560 const nsTArray
<uint8_t>& rootCert
= aBuiltCertChain
.LastElement();
561 AccumulateTelemetryForRootCA(Telemetry::CERT_VALIDATION_SUCCESS_BY_CA
,
563 GatherCertificateTransparencyTelemetry(rootCert
, aEVStatus
== EVStatus::EV
,
564 aCertificateTransparencyInfo
);
568 // Note: Takes ownership of |peerCertChain| if SECSuccess is not returned.
569 Result
AuthCertificate(
570 CertVerifier
& certVerifier
, void* aPinArg
,
571 const nsTArray
<uint8_t>& certBytes
,
572 const nsTArray
<nsTArray
<uint8_t>>& peerCertChain
,
573 const nsACString
& aHostName
, const OriginAttributes
& aOriginAttributes
,
574 const Maybe
<nsTArray
<uint8_t>>& stapledOCSPResponse
,
575 const Maybe
<nsTArray
<uint8_t>>& sctsFromTLSExtension
,
576 const Maybe
<DelegatedCredentialInfo
>& dcInfo
, uint32_t providerFlags
,
577 Time time
, uint32_t certVerifierFlags
,
578 /*out*/ nsTArray
<nsTArray
<uint8_t>>& builtCertChain
,
579 /*out*/ EVStatus
& evStatus
,
580 /*out*/ CertificateTransparencyInfo
& certificateTransparencyInfo
,
581 /*out*/ bool& aIsBuiltCertChainRootBuiltInRoot
,
582 /*out*/ bool& aMadeOCSPRequests
) {
583 CertVerifier::OCSPStaplingStatus ocspStaplingStatus
=
584 CertVerifier::OCSP_STAPLING_NEVER_CHECKED
;
585 KeySizeStatus keySizeStatus
= KeySizeStatus::NeverChecked
;
586 PinningTelemetryInfo pinningTelemetryInfo
;
588 nsTArray
<nsTArray
<uint8_t>> peerCertsBytes
;
589 // Don't include the end-entity certificate.
590 if (!peerCertChain
.IsEmpty()) {
592 peerCertChain
.cbegin() + 1, peerCertChain
.cend(),
593 MakeBackInserter(peerCertsBytes
),
594 [](const auto& elementArray
) { return elementArray
.Clone(); });
597 Result rv
= certVerifier
.VerifySSLServerCert(
598 certBytes
, time
, aPinArg
, aHostName
, builtCertChain
, certVerifierFlags
,
599 Some(std::move(peerCertsBytes
)), stapledOCSPResponse
,
600 sctsFromTLSExtension
, dcInfo
, aOriginAttributes
, &evStatus
,
601 &ocspStaplingStatus
, &keySizeStatus
, &pinningTelemetryInfo
,
602 &certificateTransparencyInfo
, &aIsBuiltCertChainRootBuiltInRoot
,
605 CollectCertTelemetry(rv
, evStatus
, ocspStaplingStatus
, keySizeStatus
,
606 pinningTelemetryInfo
, builtCertChain
,
607 certificateTransparencyInfo
);
612 PRErrorCode
AuthCertificateParseResults(
613 uint64_t aPtrForLog
, const nsACString
& aHostName
, int32_t aPort
,
614 const OriginAttributes
& aOriginAttributes
,
615 const nsCOMPtr
<nsIX509Cert
>& aCert
, mozilla::pkix::Time aTime
,
616 PRErrorCode aCertVerificationError
,
618 nsITransportSecurityInfo::OverridableErrorCategory
&
619 aOverridableErrorCategory
) {
620 uint32_t probeValue
= MapCertErrorToProbeValue(aCertVerificationError
);
621 Telemetry::Accumulate(Telemetry::SSL_CERT_VERIFICATION_ERRORS
, probeValue
);
623 Maybe
<nsITransportSecurityInfo::OverridableErrorCategory
>
624 maybeOverridableErrorCategory
=
625 CategorizeCertificateError(aCertVerificationError
);
626 // If this isn't an overridable error, return it now. This will stop the
627 // connection and report the given error.
628 if (!maybeOverridableErrorCategory
.isSome()) {
629 return aCertVerificationError
;
631 aOverridableErrorCategory
= *maybeOverridableErrorCategory
;
633 bool overrideAllowed
= false;
634 nsresult rv
= OverrideAllowedForHost(aPtrForLog
, aHostName
, aOriginAttributes
,
637 return aCertVerificationError
;
640 if (!overrideAllowed
) {
641 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
642 ("[0x%" PRIx64
"] HSTS or pinned host - no overrides allowed",
644 return aCertVerificationError
;
647 nsCOMPtr
<nsICertOverrideService
> overrideService
=
648 do_GetService(NS_CERTOVERRIDE_CONTRACTID
);
649 if (!overrideService
) {
650 return aCertVerificationError
;
653 bool isTemporaryOverride
;
654 rv
= overrideService
->HasMatchingOverride(aHostName
, aPort
, aOriginAttributes
,
655 aCert
, &isTemporaryOverride
,
658 return aCertVerificationError
;
660 Unused
<< isTemporaryOverride
;
662 uint32_t probeValue
=
663 MapOverridableErrorToProbeValue(aCertVerificationError
);
664 Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES
, probeValue
);
665 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
666 ("[0x%" PRIx64
"] certificate error overridden", aPtrForLog
));
670 return aCertVerificationError
;
673 static nsTArray
<nsTArray
<uint8_t>> CreateCertBytesArray(
674 const UniqueCERTCertList
& aCertChain
) {
675 nsTArray
<nsTArray
<uint8_t>> certsBytes
;
676 for (CERTCertListNode
* n
= CERT_LIST_HEAD(aCertChain
);
677 !CERT_LIST_END(n
, aCertChain
); n
= CERT_LIST_NEXT(n
)) {
678 nsTArray
<uint8_t> certBytes
;
679 certBytes
.AppendElements(n
->cert
->derCert
.data
, n
->cert
->derCert
.len
);
680 certsBytes
.AppendElement(std::move(certBytes
));
686 SECStatus
SSLServerCertVerificationJob::Dispatch(
687 uint64_t addrForLogging
, void* aPinArg
,
688 nsTArray
<nsTArray
<uint8_t>>&& peerCertChain
, const nsACString
& aHostName
,
689 int32_t aPort
, const OriginAttributes
& aOriginAttributes
,
690 Maybe
<nsTArray
<uint8_t>>& stapledOCSPResponse
,
691 Maybe
<nsTArray
<uint8_t>>& sctsFromTLSExtension
,
692 Maybe
<DelegatedCredentialInfo
>& dcInfo
, uint32_t providerFlags
, Time time
,
693 uint32_t certVerifierFlags
,
694 BaseSSLServerCertVerificationResult
* aResultTask
) {
695 // Runs on the socket transport thread
696 if (!aResultTask
|| peerCertChain
.IsEmpty()) {
697 MOZ_ASSERT_UNREACHABLE(
698 "must have result task and non-empty peer cert chain");
699 PR_SetError(SEC_ERROR_LIBRARY_FAILURE
, 0);
703 if (!gCertVerificationThreadPool
) {
704 PR_SetError(PR_INVALID_STATE_ERROR
, 0);
708 RefPtr
<SSLServerCertVerificationJob
> job(new SSLServerCertVerificationJob(
709 addrForLogging
, aPinArg
, std::move(peerCertChain
), aHostName
, aPort
,
710 aOriginAttributes
, stapledOCSPResponse
, sctsFromTLSExtension
, dcInfo
,
711 providerFlags
, time
, certVerifierFlags
, aResultTask
));
713 nsresult nrv
= gCertVerificationThreadPool
->Dispatch(job
, NS_DISPATCH_NORMAL
);
714 if (NS_FAILED(nrv
)) {
715 // We can't call SetCertVerificationResult here to change
716 // mCertVerificationState because SetCertVerificationResult will call
717 // libssl functions that acquire SSL locks that are already being held at
718 // this point. However, we can set an error with PR_SetError and return
719 // SECFailure, and the correct thing will happen (the error will be
720 // propagated and this connection will be terminated).
721 PRErrorCode error
= nrv
== NS_ERROR_OUT_OF_MEMORY
? PR_OUT_OF_MEMORY_ERROR
722 : PR_INVALID_STATE_ERROR
;
723 PR_SetError(error
, 0);
727 PR_SetError(PR_WOULD_BLOCK_ERROR
, 0);
728 return SECWouldBlock
;
732 SSLServerCertVerificationJob::Run() {
733 // Runs on a cert verification thread and only on parent process.
734 MOZ_ASSERT(XRE_IsParentProcess());
737 gPIPNSSLog
, LogLevel::Debug
,
738 ("[%" PRIx64
"] SSLServerCertVerificationJob::Run\n", mAddrForLogging
));
740 RefPtr
<SharedCertVerifier
> certVerifier(GetDefaultCertVerifier());
742 PR_SetError(SEC_ERROR_NOT_INITIALIZED
, 0);
746 TimeStamp jobStartTime
= TimeStamp::Now();
748 CertificateTransparencyInfo certificateTransparencyInfo
;
749 bool isCertChainRootBuiltInRoot
= false;
750 bool madeOCSPRequests
= false;
751 nsTArray
<nsTArray
<uint8_t>> builtChainBytesArray
;
752 nsTArray
<uint8_t> certBytes(mPeerCertChain
.ElementAt(0).Clone());
753 Result rv
= AuthCertificate(
754 *certVerifier
, mPinArg
, certBytes
, mPeerCertChain
, mHostName
,
755 mOriginAttributes
, mStapledOCSPResponse
, mSCTsFromTLSExtension
, mDCInfo
,
756 mProviderFlags
, mTime
, mCertVerifierFlags
, builtChainBytesArray
, evStatus
,
757 certificateTransparencyInfo
, isCertChainRootBuiltInRoot
,
761 Telemetry::AccumulateTimeDelta(
762 Telemetry::SSL_SUCCESFUL_CERT_VALIDATION_TIME_MOZILLAPKIX
, jobStartTime
,
764 Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES
, 1);
766 mResultTask
->Dispatch(
767 std::move(builtChainBytesArray
), std::move(mPeerCertChain
),
768 TransportSecurityInfo::ConvertCertificateTransparencyInfoToStatus(
769 certificateTransparencyInfo
),
771 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET
,
772 isCertChainRootBuiltInRoot
, mProviderFlags
, madeOCSPRequests
);
776 Telemetry::AccumulateTimeDelta(
777 Telemetry::SSL_INITIAL_FAILED_CERT_VALIDATION_TIME_MOZILLAPKIX
,
778 jobStartTime
, TimeStamp::Now());
780 PRErrorCode error
= MapResultToPRErrorCode(rv
);
781 nsITransportSecurityInfo::OverridableErrorCategory overridableErrorCategory
=
782 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET
;
783 nsCOMPtr
<nsIX509Cert
> cert(new nsNSSCertificate(std::move(certBytes
)));
784 PRErrorCode finalError
= AuthCertificateParseResults(
785 mAddrForLogging
, mHostName
, mPort
, mOriginAttributes
, cert
, mTime
, error
,
786 overridableErrorCategory
);
788 // NB: finalError may be 0 here, in which the connection will continue.
789 mResultTask
->Dispatch(
790 std::move(builtChainBytesArray
), std::move(mPeerCertChain
),
791 nsITransportSecurityInfo::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE
,
792 EVStatus::NotEV
, false, finalError
, overridableErrorCategory
, false,
793 mProviderFlags
, madeOCSPRequests
);
797 // Takes information needed for cert verification, does some consistency
798 // checks and calls SSLServerCertVerificationJob::Dispatch.
799 SECStatus
AuthCertificateHookInternal(
800 CommonSocketControl
* socketControl
, const void* aPtrForLogging
,
801 const nsACString
& hostName
, nsTArray
<nsTArray
<uint8_t>>&& peerCertChain
,
802 Maybe
<nsTArray
<uint8_t>>& stapledOCSPResponse
,
803 Maybe
<nsTArray
<uint8_t>>& sctsFromTLSExtension
,
804 Maybe
<DelegatedCredentialInfo
>& dcInfo
, uint32_t providerFlags
,
805 uint32_t certVerifierFlags
) {
806 // Runs on the socket transport thread
808 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
809 ("[%p] starting AuthCertificateHookInternal\n", aPtrForLogging
));
811 if (!socketControl
|| peerCertChain
.IsEmpty()) {
812 PR_SetError(PR_INVALID_STATE_ERROR
, 0);
818 nsCOMPtr
<nsIEventTarget
> sts
=
819 do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID
, &nrv
);
820 if (NS_SUCCEEDED(nrv
)) {
821 nrv
= sts
->IsOnCurrentThread(&onSTSThread
);
824 if (NS_FAILED(nrv
)) {
825 NS_ERROR("Could not get STS service or IsOnCurrentThread failed");
826 PR_SetError(PR_UNKNOWN_ERROR
, 0);
830 MOZ_ASSERT(onSTSThread
);
833 PR_SetError(PR_INVALID_STATE_ERROR
, 0);
837 uint64_t addr
= reinterpret_cast<uintptr_t>(aPtrForLogging
);
838 RefPtr
<SSLServerCertVerificationResult
> resultTask
=
839 new SSLServerCertVerificationResult(socketControl
);
841 if (XRE_IsSocketProcess()) {
842 return RemoteProcessCertVerification(
843 std::move(peerCertChain
), hostName
, socketControl
->GetPort(),
844 socketControl
->GetOriginAttributes(), stapledOCSPResponse
,
845 sctsFromTLSExtension
, dcInfo
, providerFlags
, certVerifierFlags
,
849 // We *must* do certificate verification on a background thread because
850 // we need the socket transport thread to be free for our OCSP requests,
851 // and we *want* to do certificate verification on a background thread
852 // because of the performance benefits of doing so.
853 return SSLServerCertVerificationJob::Dispatch(
854 addr
, socketControl
, std::move(peerCertChain
), hostName
,
855 socketControl
->GetPort(), socketControl
->GetOriginAttributes(),
856 stapledOCSPResponse
, sctsFromTLSExtension
, dcInfo
, providerFlags
, Now(),
857 certVerifierFlags
, resultTask
);
860 // Extracts whatever information we need out of fd (using SSL_*) and passes it
861 // to AuthCertificateHookInternal. AuthCertificateHookInternal will call
862 // SSLServerCertVerificationJob::Dispatch. SSLServerCertVerificationJob
863 // should never do anything with fd except logging.
864 SECStatus
AuthCertificateHook(void* arg
, PRFileDesc
* fd
, PRBool checkSig
,
866 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
867 ("[%p] starting AuthCertificateHook\n", fd
));
869 // Modern libssl always passes PR_TRUE for checkSig, and we have no means of
870 // doing verification without checking signatures.
871 MOZ_ASSERT(checkSig
, "AuthCertificateHook: checkSig unexpectedly false");
873 // PSM never causes libssl to call this function with PR_TRUE for isServer,
874 // and many things in PSM assume that we are a client.
875 MOZ_ASSERT(!isServer
, "AuthCertificateHook: isServer unexpectedly true");
877 NSSSocketControl
* socketInfo
= static_cast<NSSSocketControl
*>(arg
);
879 UniqueCERTCertificate
serverCert(SSL_PeerCertificate(fd
));
881 if (!checkSig
|| isServer
|| !socketInfo
|| !serverCert
) {
882 PR_SetError(PR_INVALID_STATE_ERROR
, 0);
885 socketInfo
->SetFullHandshake();
887 if (BlockServerCertChangeForSpdy(socketInfo
, serverCert
) != SECSuccess
) {
891 UniqueCERTCertList
peerCertChain(SSL_PeerCertificateChain(fd
));
892 if (!peerCertChain
) {
893 PR_SetError(PR_INVALID_STATE_ERROR
, 0);
897 nsTArray
<nsTArray
<uint8_t>> peerCertsBytes
=
898 CreateCertBytesArray(peerCertChain
);
900 // SSL_PeerStapledOCSPResponses will never return a non-empty response if
901 // OCSP stapling wasn't enabled because libssl wouldn't have let the server
902 // return a stapled OCSP response.
903 // We don't own these pointers.
904 const SECItemArray
* csa
= SSL_PeerStapledOCSPResponses(fd
);
905 Maybe
<nsTArray
<uint8_t>> stapledOCSPResponse
;
906 // we currently only support single stapled responses
907 if (csa
&& csa
->len
== 1) {
908 stapledOCSPResponse
.emplace();
909 stapledOCSPResponse
->SetCapacity(csa
->items
[0].len
);
910 stapledOCSPResponse
->AppendElements(csa
->items
[0].data
, csa
->items
[0].len
);
913 Maybe
<nsTArray
<uint8_t>> sctsFromTLSExtension
;
914 const SECItem
* sctsFromTLSExtensionSECItem
= SSL_PeerSignedCertTimestamps(fd
);
915 if (sctsFromTLSExtensionSECItem
) {
916 sctsFromTLSExtension
.emplace();
917 sctsFromTLSExtension
->SetCapacity(sctsFromTLSExtensionSECItem
->len
);
918 sctsFromTLSExtension
->AppendElements(sctsFromTLSExtensionSECItem
->data
,
919 sctsFromTLSExtensionSECItem
->len
);
922 uint32_t providerFlags
= 0;
923 socketInfo
->GetProviderFlags(&providerFlags
);
925 uint32_t certVerifierFlags
= 0;
926 if (!socketInfo
->SharedState().IsOCSPStaplingEnabled() ||
927 !socketInfo
->SharedState().IsOCSPMustStapleEnabled()) {
928 certVerifierFlags
|= CertVerifier::FLAG_TLS_IGNORE_STATUS_REQUEST
;
931 // Get DC information
932 Maybe
<DelegatedCredentialInfo
> dcInfo
;
933 SSLPreliminaryChannelInfo channelPreInfo
;
934 SECStatus rv
= SSL_GetPreliminaryChannelInfo(fd
, &channelPreInfo
,
935 sizeof(channelPreInfo
));
936 if (rv
!= SECSuccess
) {
937 PR_SetError(PR_INVALID_STATE_ERROR
, 0);
940 if (channelPreInfo
.peerDelegCred
) {
941 dcInfo
.emplace(DelegatedCredentialInfo(channelPreInfo
.signatureScheme
,
942 channelPreInfo
.authKeyBits
));
945 // If we configured an ECHConfig and NSS returned the public name
946 // for verification, ECH was rejected. Proceed, verifying to the
947 // public name. The result determines how NSS will fail (i.e. with
948 // any provided retry_configs if successful). See draft-ietf-tls-esni-08.
950 nsresult nsrv
= socketInfo
->GetEchConfig(echConfig
);
951 bool verifyToEchPublicName
=
952 NS_SUCCEEDED(nsrv
) && echConfig
.Length() && channelPreInfo
.echPublicName
;
954 const nsCString
echPublicName(channelPreInfo
.echPublicName
);
955 const nsACString
& hostname
=
956 verifyToEchPublicName
? echPublicName
: socketInfo
->GetHostName();
957 socketInfo
->SetCertVerificationWaiting();
958 rv
= AuthCertificateHookInternal(socketInfo
, static_cast<const void*>(fd
),
959 hostname
, std::move(peerCertsBytes
),
960 stapledOCSPResponse
, sctsFromTLSExtension
,
961 dcInfo
, providerFlags
, certVerifierFlags
);
965 // Takes information needed for cert verification, does some consistency
966 // checks and calls SSLServerCertVerificationJob::Dispatch.
967 // This function is used for Quic.
968 SECStatus
AuthCertificateHookWithInfo(
969 CommonSocketControl
* socketControl
, const nsACString
& aHostName
,
970 const void* aPtrForLogging
, nsTArray
<nsTArray
<uint8_t>>&& peerCertChain
,
971 Maybe
<nsTArray
<nsTArray
<uint8_t>>>& stapledOCSPResponses
,
972 Maybe
<nsTArray
<uint8_t>>& sctsFromTLSExtension
, uint32_t providerFlags
) {
973 if (peerCertChain
.IsEmpty()) {
974 PR_SetError(PR_INVALID_STATE_ERROR
, 0);
978 // we currently only support single stapled responses
979 Maybe
<nsTArray
<uint8_t>> stapledOCSPResponse
;
980 if (stapledOCSPResponses
&& (stapledOCSPResponses
->Length() == 1)) {
981 stapledOCSPResponse
.emplace(stapledOCSPResponses
->ElementAt(0).Clone());
984 uint32_t certVerifierFlags
= 0;
985 // QuicSocketControl does not have a SharedState as NSSSocketControl.
986 // Here we need prefs for ocsp. This are prefs they are the same for
987 // PublicSSLState and PrivateSSLState, just take them from one of them.
988 if (!PublicSSLState()->IsOCSPStaplingEnabled() ||
989 !PublicSSLState()->IsOCSPMustStapleEnabled()) {
990 certVerifierFlags
|= CertVerifier::FLAG_TLS_IGNORE_STATUS_REQUEST
;
993 // Need to update Quic stack to reflect the PreliminaryInfo fields
994 // for Delegated Credentials.
995 Maybe
<DelegatedCredentialInfo
> dcInfo
;
997 return AuthCertificateHookInternal(socketControl
, aPtrForLogging
, aHostName
,
998 std::move(peerCertChain
),
999 stapledOCSPResponse
, sctsFromTLSExtension
,
1000 dcInfo
, providerFlags
, certVerifierFlags
);
1003 NS_IMPL_ISUPPORTS_INHERITED0(SSLServerCertVerificationResult
, Runnable
)
1005 SSLServerCertVerificationResult::SSLServerCertVerificationResult(
1006 CommonSocketControl
* socketControl
)
1007 : Runnable("psm::SSLServerCertVerificationResult"),
1008 mSocketControl(socketControl
),
1009 mCertificateTransparencyStatus(0),
1010 mEVStatus(EVStatus::NotEV
),
1013 mOverridableErrorCategory(
1014 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET
),
1015 mProviderFlags(0) {}
1017 void SSLServerCertVerificationResult::Dispatch(
1018 nsTArray
<nsTArray
<uint8_t>>&& aBuiltChain
,
1019 nsTArray
<nsTArray
<uint8_t>>&& aPeerCertChain
,
1020 uint16_t aCertificateTransparencyStatus
, EVStatus aEVStatus
,
1021 bool aSucceeded
, PRErrorCode aFinalError
,
1022 nsITransportSecurityInfo::OverridableErrorCategory
1023 aOverridableErrorCategory
,
1024 bool aIsBuiltCertChainRootBuiltInRoot
, uint32_t aProviderFlags
,
1025 bool aMadeOCSPRequests
) {
1026 mBuiltChain
= std::move(aBuiltChain
);
1027 mPeerCertChain
= std::move(aPeerCertChain
);
1028 mCertificateTransparencyStatus
= aCertificateTransparencyStatus
;
1029 mEVStatus
= aEVStatus
;
1030 mSucceeded
= aSucceeded
;
1031 mFinalError
= aFinalError
;
1032 mOverridableErrorCategory
= aOverridableErrorCategory
;
1033 mIsBuiltCertChainRootBuiltInRoot
= aIsBuiltCertChainRootBuiltInRoot
;
1034 mProviderFlags
= aProviderFlags
;
1035 mMadeOCSPRequests
= aMadeOCSPRequests
;
1037 if (mSucceeded
&& mBuiltChain
.IsEmpty()) {
1038 MOZ_ASSERT_UNREACHABLE(
1039 "if the handshake succeeded, the built chain shouldn't be empty");
1041 mFinalError
= SEC_ERROR_LIBRARY_FAILURE
;
1043 if (!mSucceeded
&& mPeerCertChain
.IsEmpty()) {
1044 MOZ_ASSERT_UNREACHABLE(
1045 "if the handshake failed, the peer chain shouldn't be empty");
1046 mFinalError
= SEC_ERROR_LIBRARY_FAILURE
;
1050 nsCOMPtr
<nsIEventTarget
> stsTarget
=
1051 do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID
, &rv
);
1052 MOZ_ASSERT(stsTarget
, "Failed to get socket transport service event target");
1053 rv
= stsTarget
->Dispatch(this, NS_DISPATCH_NORMAL
);
1054 MOZ_ASSERT(NS_SUCCEEDED(rv
),
1055 "Failed to dispatch SSLServerCertVerificationResult");
1059 SSLServerCertVerificationResult::Run() {
1061 bool onSTSThread
= false;
1063 nsCOMPtr
<nsIEventTarget
> sts
=
1064 do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID
, &nrv
);
1065 if (NS_SUCCEEDED(nrv
)) {
1066 nrv
= sts
->IsOnCurrentThread(&onSTSThread
);
1069 MOZ_ASSERT(onSTSThread
);
1072 if (mSucceeded
&& !XRE_IsSocketProcess() &&
1073 !(mProviderFlags
& nsISocketProvider::NO_PERMANENT_STORAGE
)) {
1074 // This dispatches an event that will run when the socket thread is idle.
1075 SaveIntermediateCerts(mBuiltChain
);
1078 mSocketControl
->SetMadeOCSPRequests(mMadeOCSPRequests
);
1081 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
1082 ("SSLServerCertVerificationResult::Run setting NEW cert"));
1083 nsTArray
<uint8_t> certBytes(mBuiltChain
.ElementAt(0).Clone());
1084 nsCOMPtr
<nsIX509Cert
> cert(new nsNSSCertificate(std::move(certBytes
)));
1085 mSocketControl
->SetServerCert(cert
, mEVStatus
);
1086 mSocketControl
->SetSucceededCertChain(std::move(mBuiltChain
));
1088 mSocketControl
->SetIsBuiltCertChainRootBuiltInRoot(
1089 mIsBuiltCertChainRootBuiltInRoot
);
1090 mSocketControl
->SetCertificateTransparencyStatus(
1091 mCertificateTransparencyStatus
);
1093 nsTArray
<uint8_t> certBytes(mPeerCertChain
.ElementAt(0).Clone());
1094 nsCOMPtr
<nsIX509Cert
> cert(new nsNSSCertificate(std::move(certBytes
)));
1095 // Certificate validation failed; store the peer certificate chain on
1096 // mSocketControl so it can be used for error reporting.
1097 mSocketControl
->SetFailedCertChain(std::move(mPeerCertChain
));
1098 if (mOverridableErrorCategory
!=
1099 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET
) {
1100 mSocketControl
->SetStatusErrorBits(cert
, mOverridableErrorCategory
);
1104 mSocketControl
->SetCertVerificationResult(mFinalError
);
1109 } // namespace mozilla