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 #ifndef NSSSocketControl_h
8 #define NSSSocketControl_h
10 #include "CommonSocketControl.h"
11 #include "TLSClientAuthCertSelection.h"
12 #include "mozilla/Casting.h"
13 #include "nsNSSIOLayer.h"
14 #include "nsThreadUtils.h"
16 extern mozilla::LazyLogModule gPIPNSSLog
;
18 class SelectClientAuthCertificate
;
20 class NSSSocketControl final
: public CommonSocketControl
{
22 NSSSocketControl(const nsCString
& aHostName
, int32_t aPort
,
23 already_AddRefed
<nsSSLIOLayerHelpers
> aSSLIOLayerHelpers
,
24 uint32_t providerFlags
, uint32_t providerTlsFlags
);
26 NS_INLINE_DECL_REFCOUNTING_INHERITED(NSSSocketControl
, CommonSocketControl
);
28 void SetForSTARTTLS(bool aForSTARTTLS
);
29 bool GetForSTARTTLS();
31 nsresult
GetFileDescPtr(PRFileDesc
** aFilePtr
);
32 nsresult
SetFileDescPtr(PRFileDesc
* aFilePtr
);
34 bool IsHandshakePending() const {
35 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
36 return mHandshakePending
;
38 void SetHandshakeNotPending() {
39 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
40 mHandshakePending
= false;
43 void SetTLSVersionRange(SSLVersionRange range
) {
44 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
45 mTLSVersionRange
= range
;
47 SSLVersionRange
GetTLSVersionRange() const {
48 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
49 return mTLSVersionRange
;
52 void RememberTLSTolerant() {
53 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
54 mSSLIOLayerHelpers
->rememberTolerantAtVersion(
55 GetHostName(), mozilla::AssertedCast
<uint16_t>(GetPort()),
56 mTLSVersionRange
.max
);
59 void RemoveInsecureTLSFallback() {
60 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
61 mSSLIOLayerHelpers
->removeInsecureFallbackSite(
62 GetHostName(), mozilla::AssertedCast
<uint16_t>(GetPort()));
65 PRErrorCode
GetTLSIntoleranceReason() {
66 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
67 return mSSLIOLayerHelpers
->getIntoleranceReason(
68 GetHostName(), mozilla::AssertedCast
<uint16_t>(GetPort()));
71 void ForgetTLSIntolerance() {
72 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
73 mSSLIOLayerHelpers
->forgetIntolerance(
74 GetHostName(), mozilla::AssertedCast
<uint16_t>(GetPort()));
77 bool RememberTLSIntolerant(PRErrorCode err
) {
78 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
79 return mSSLIOLayerHelpers
->rememberIntolerantAtVersion(
80 GetHostName(), mozilla::AssertedCast
<uint16_t>(GetPort()),
81 mTLSVersionRange
.min
, mTLSVersionRange
.max
, err
);
84 void AdjustForTLSIntolerance(SSLVersionRange
& range
) {
85 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
86 mSSLIOLayerHelpers
->adjustForTLSIntolerance(
87 GetHostName(), mozilla::AssertedCast
<uint16_t>(GetPort()), range
);
90 // From nsITLSSocketControl.
91 NS_IMETHOD
ProxyStartSSL(void) override
;
92 NS_IMETHOD
StartTLS(void) override
;
93 NS_IMETHOD
AsyncStartTLS(JSContext
* aCx
,
94 mozilla::dom::Promise
** aPromise
) override
;
95 NS_IMETHOD
SetNPNList(nsTArray
<nsCString
>& aNPNList
) override
;
96 NS_IMETHOD
GetAlpnEarlySelection(nsACString
& _retval
) override
;
97 NS_IMETHOD
GetEarlyDataAccepted(bool* aEarlyDataAccepted
) override
;
98 NS_IMETHOD
DriveHandshake(void) override
;
99 NS_IMETHOD
GetKEAUsed(int16_t* aKEAUsed
) override
;
100 NS_IMETHOD
GetKEAKeyBits(uint32_t* aKEAKeyBits
) override
;
101 NS_IMETHOD
GetSSLVersionOffered(int16_t* aSSLVersionOffered
) override
;
102 NS_IMETHOD
GetMACAlgorithmUsed(int16_t* aMACAlgorithmUsed
) override
;
103 bool GetDenyClientCert() override
;
104 void SetDenyClientCert(bool aDenyClientCert
) override
;
105 NS_IMETHOD
GetEsniTxt(nsACString
& aEsniTxt
) override
;
106 NS_IMETHOD
SetEsniTxt(const nsACString
& aEsniTxt
) override
;
107 NS_IMETHOD
GetEchConfig(nsACString
& aEchConfig
) override
;
108 NS_IMETHOD
SetEchConfig(const nsACString
& aEchConfig
) override
;
109 NS_IMETHOD
GetPeerId(nsACString
& aResult
) override
;
110 NS_IMETHOD
GetRetryEchConfig(nsACString
& aEchConfig
) override
;
111 NS_IMETHOD
DisableEarlyData(void) override
;
112 NS_IMETHOD
SetHandshakeCallbackListener(
113 nsITlsHandshakeCallbackListener
* callback
) override
;
114 NS_IMETHOD
Claim() override
;
115 NS_IMETHOD
SetBrowserId(uint64_t browserId
) override
;
116 NS_IMETHOD
GetBrowserId(uint64_t* browserId
) override
;
118 PRStatus
CloseSocketAndDestroy();
120 void SetNegotiatedNPN(const char* value
, uint32_t length
);
121 void SetEarlyDataAccepted(bool aAccepted
);
123 void SetHandshakeCompleted();
124 bool IsHandshakeCompleted() const {
125 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
126 return mHandshakeCompleted
;
128 void NoteTimeUntilReady();
130 void SetFalseStartCallbackCalled() {
131 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
132 mFalseStartCallbackCalled
= true;
134 void SetFalseStarted() {
135 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
136 mFalseStarted
= true;
139 // Note that this is only valid *during* a handshake; at the end of the
140 // handshake, it gets reset back to false.
141 void SetFullHandshake() {
142 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
143 mIsFullHandshake
= true;
145 bool IsFullHandshake() const {
146 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
147 return mIsFullHandshake
;
150 void UpdateEchExtensionStatus(EchExtensionStatus aEchExtensionStatus
) {
151 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
152 mEchExtensionStatus
= std::max(aEchExtensionStatus
, mEchExtensionStatus
);
154 EchExtensionStatus
GetEchExtensionStatus() const {
155 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
156 return mEchExtensionStatus
;
159 void WillSendMlkemShare() {
160 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
161 mSentMlkemShare
= true;
164 bool SentMlkemShare() {
165 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
166 return mSentMlkemShare
;
169 void SetHasTls13HandshakeSecrets() {
170 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
171 mHasTls13HandshakeSecrets
= true;
174 bool HasTls13HandshakeSecrets() {
175 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
176 return mHasTls13HandshakeSecrets
;
180 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
184 uint32_t GetProviderTlsFlags() const {
185 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
186 return mProviderTlsFlags
;
189 enum CertVerificationState
{
190 BeforeCertVerification
,
191 WaitingForCertVerification
,
192 AfterCertVerification
195 void SetCertVerificationWaiting();
197 // Use errorCode == 0 to indicate success;
198 void SetCertVerificationResult(PRErrorCode errorCode
) override
;
200 void ClientAuthCertificateSelected(
201 nsTArray
<uint8_t>& certBytes
,
202 nsTArray
<nsTArray
<uint8_t>>& certChainBytes
);
204 bool IsWaitingForCertVerification() const {
205 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
206 return mCertVerificationState
== WaitingForCertVerification
;
208 void AddPlaintextBytesRead(uint64_t val
) {
209 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
210 mPlaintextBytesRead
+= val
;
213 bool IsPreliminaryHandshakeDone() const {
214 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
215 return mPreliminaryHandshakeDone
;
217 void SetPreliminaryHandshakeDone() {
218 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
219 mPreliminaryHandshakeDone
= true;
222 void SetKEAUsed(int16_t kea
) {
223 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
227 void SetKEAKeyBits(uint32_t keaBits
) {
228 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
229 mKEAKeyBits
= keaBits
;
232 void SetMACAlgorithmUsed(int16_t mac
) {
233 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
234 mMACAlgorithmUsed
= mac
;
237 void SetShortWritePending(int32_t amount
, unsigned char data
) {
238 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
239 mIsShortWritePending
= true;
240 mShortWriteOriginalAmount
= amount
;
241 mShortWritePendingByte
= data
;
244 bool IsShortWritePending() {
245 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
246 return mIsShortWritePending
;
249 unsigned char const* GetShortWritePendingByteRef() {
250 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
251 return &mShortWritePendingByte
;
254 int32_t ResetShortWritePending() {
255 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
256 mIsShortWritePending
= false;
257 return mShortWriteOriginalAmount
;
261 // These helpers assert that the caller does try to send the same data
262 // as it was previously when we hit the short-write. This is a measure
263 // to make sure we communicate correctly to the consumer.
264 void RememberShortWrittenBuffer(const unsigned char* data
) {
265 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
266 mShortWriteBufferCheck
=
267 mozilla::MakeUnique
<char[]>(mShortWriteOriginalAmount
);
268 memcpy(mShortWriteBufferCheck
.get(), data
, mShortWriteOriginalAmount
);
270 void CheckShortWrittenBuffer(const unsigned char* data
, int32_t amount
) {
271 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
272 if (!mShortWriteBufferCheck
) return;
273 MOZ_ASSERT(amount
>= mShortWriteOriginalAmount
,
274 "unexpected amount length after short write");
276 !memcmp(mShortWriteBufferCheck
.get(), data
, mShortWriteOriginalAmount
),
277 "unexpected buffer content after short write");
278 mShortWriteBufferCheck
= nullptr;
282 nsresult
SetResumptionTokenFromExternalCache(PRFileDesc
* fd
);
284 void SetPreliminaryHandshakeInfo(const SSLChannelInfo
& channelInfo
,
285 const SSLCipherSuiteInfo
& cipherInfo
);
287 void SetPendingSelectClientAuthCertificate(
288 nsCOMPtr
<nsIRunnable
>&& selectClientAuthCertificate
) {
289 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
291 gPIPNSSLog
, mozilla::LogLevel::Debug
,
292 ("[%p] setting pending select client auth certificate", (void*)mFd
));
293 // If the connection corresponding to this socket hasn't been claimed, it
294 // is a speculative connection. The connection will block until the "choose
295 // a client auth certificate" dialog has been shown. The dialog will only
296 // be shown when this connection gets claimed. However, necko will never
297 // claim the connection as long as it is blocking. Thus, this connection
298 // can't proceed, so it's best to cancel it. Necko will create a new,
299 // non-speculative connection instead.
301 SetCanceled(PR_CONNECT_RESET_ERROR
);
303 mPendingSelectClientAuthCertificate
=
304 std::move(selectClientAuthCertificate
);
308 void MaybeDispatchSelectClientAuthCertificate() {
309 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
310 if (!IsWaitingForCertVerification() && mClaimed
&&
311 mPendingSelectClientAuthCertificate
) {
312 MOZ_LOG(gPIPNSSLog
, mozilla::LogLevel::Debug
,
313 ("[%p] dispatching pending select client auth certificate",
315 mozilla::Unused
<< NS_DispatchToMainThread(
316 mPendingSelectClientAuthCertificate
);
317 mPendingSelectClientAuthCertificate
= nullptr;
322 ~NSSSocketControl() = default;
326 CertVerificationState mCertVerificationState
;
328 RefPtr
<nsSSLIOLayerHelpers
> mSSLIOLayerHelpers
;
330 SSLVersionRange mTLSVersionRange
;
331 bool mHandshakePending
;
332 bool mPreliminaryHandshakeDone
; // after false start items are complete
334 nsresult
ActivateSSL();
337 nsCString mEchConfig
;
338 bool mEarlyDataAccepted
;
339 bool mDenyClientCert
;
340 bool mFalseStartCallbackCalled
;
342 bool mIsFullHandshake
;
343 bool mNotedTimeUntilReady
;
344 EchExtensionStatus mEchExtensionStatus
; // Currently only used for telemetry.
345 bool mSentMlkemShare
;
346 bool mHasTls13HandshakeSecrets
;
348 // True when SSL layer has indicated an "SSL short write", i.e. need
349 // to call on send one or more times to push all pending data to write.
350 bool mIsShortWritePending
;
352 // These are only valid if mIsShortWritePending is true.
354 // Value of the last byte pending from the SSL short write that needs
355 // to be passed to subsequent calls to send to perform the flush.
356 unsigned char mShortWritePendingByte
;
358 // Original amount of data the upper layer has requested to write to
359 // return after the successful flush.
360 int32_t mShortWriteOriginalAmount
;
363 mozilla::UniquePtr
<char[]> mShortWriteBufferCheck
;
366 // mKEA* are used in false start and http/2 detetermination
367 // Values are from nsITLSSocketControl
369 uint32_t mKEAKeyBits
;
370 int16_t mMACAlgorithmUsed
;
372 uint32_t mProviderTlsFlags
;
373 mozilla::TimeStamp mSocketCreationTimestamp
;
374 uint64_t mPlaintextBytesRead
;
377 nsCOMPtr
<nsIRunnable
> mPendingSelectClientAuthCertificate
;
379 // Regarding the client certificate message in the TLS handshake, RFC 5246
381 // If the certificate_authorities list in the certificate request
382 // message was non-empty, one of the certificates in the certificate
383 // chain SHOULD be issued by one of the listed CAs.
384 // (RFC 8446 (TLS 1.3) has a similar provision)
385 // These certificates may be known to gecko but not NSS (e.g. enterprise
386 // intermediates). In order to make these certificates discoverable to NSS
387 // so it can include them in the message, we cache them here as temporary
389 mozilla::UniqueCERTCertList mClientCertChain
;
391 nsCOMPtr
<nsITlsHandshakeCallbackListener
> mTlsHandshakeCallback
;
396 #endif // NSSSocketControl_h