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 #include "NSSSocketControl.h"
11 #include "nsISocketProvider.h"
13 #include "mozilla/Base64.h"
14 #include "mozilla/dom/Promise.h"
15 #include "nsNSSCallbacks.h"
16 #include "nsProxyRelease.h"
18 using namespace mozilla
;
19 using namespace mozilla::psm
;
21 extern LazyLogModule gPIPNSSLog
;
23 NSSSocketControl::NSSSocketControl(
24 const nsCString
& aHostName
, int32_t aPort
,
25 already_AddRefed
<nsSSLIOLayerHelpers
> aSSLIOLayerHelpers
,
26 uint32_t providerFlags
, uint32_t providerTlsFlags
)
27 : CommonSocketControl(aHostName
, aPort
, providerFlags
),
29 mCertVerificationState(BeforeCertVerification
),
30 mSSLIOLayerHelpers(aSSLIOLayerHelpers
),
32 mTLSVersionRange
{0, 0},
33 mHandshakePending(true),
34 mPreliminaryHandshakeDone(false),
35 mEarlyDataAccepted(false),
36 mDenyClientCert(false),
37 mFalseStartCallbackCalled(false),
39 mIsFullHandshake(false),
40 mNotedTimeUntilReady(false),
41 mEchExtensionStatus(EchExtensionStatus::kNotPresent
),
42 mSentMlkemShare(false),
43 mHasTls13HandshakeSecrets(false),
44 mIsShortWritePending(false),
45 mShortWritePendingByte(0),
46 mShortWriteOriginalAmount(-1),
47 mKEAUsed(nsITLSSocketControl::KEY_EXCHANGE_UNKNOWN
),
49 mMACAlgorithmUsed(nsITLSSocketControl::SSL_MAC_UNKNOWN
),
50 mProviderTlsFlags(providerTlsFlags
),
51 mSocketCreationTimestamp(TimeStamp::Now()),
52 mPlaintextBytesRead(0),
53 mClaimed(!(providerFlags
& nsISocketProvider::IS_SPECULATIVE_CONNECTION
)),
54 mPendingSelectClientAuthCertificate(nullptr),
58 NSSSocketControl::GetKEAUsed(int16_t* aKea
) {
59 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
65 NSSSocketControl::GetKEAKeyBits(uint32_t* aKeyBits
) {
66 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
67 *aKeyBits
= mKEAKeyBits
;
72 NSSSocketControl::GetSSLVersionOffered(int16_t* aSSLVersionOffered
) {
73 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
74 *aSSLVersionOffered
= mTLSVersionRange
.max
;
79 NSSSocketControl::GetMACAlgorithmUsed(int16_t* aMac
) {
80 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
81 *aMac
= mMACAlgorithmUsed
;
85 void NSSSocketControl::NoteTimeUntilReady() {
86 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
87 if (mNotedTimeUntilReady
) {
90 mNotedTimeUntilReady
= true;
92 auto timestampNow
= TimeStamp::Now();
93 if (!(mProviderFlags
& nsISocketProvider::IS_RETRY
)) {
94 Telemetry::AccumulateTimeDelta(Telemetry::SSL_TIME_UNTIL_READY_FIRST_TRY
,
95 mSocketCreationTimestamp
, timestampNow
);
98 if (mProviderFlags
& nsISocketProvider::BE_CONSERVATIVE
) {
99 Telemetry::AccumulateTimeDelta(Telemetry::SSL_TIME_UNTIL_READY_CONSERVATIVE
,
100 mSocketCreationTimestamp
, timestampNow
);
103 switch (GetEchExtensionStatus()) {
104 case EchExtensionStatus::kGREASE
:
105 Telemetry::AccumulateTimeDelta(Telemetry::SSL_TIME_UNTIL_READY_ECH_GREASE
,
106 mSocketCreationTimestamp
, timestampNow
);
108 case EchExtensionStatus::kReal
:
109 Telemetry::AccumulateTimeDelta(Telemetry::SSL_TIME_UNTIL_READY_ECH
,
110 mSocketCreationTimestamp
, timestampNow
);
115 // This will include TCP and proxy tunnel wait time
116 Telemetry::AccumulateTimeDelta(Telemetry::SSL_TIME_UNTIL_READY
,
117 mSocketCreationTimestamp
, timestampNow
);
119 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
120 ("[%p] NSSSocketControl::NoteTimeUntilReady\n", mFd
));
123 void NSSSocketControl::SetHandshakeCompleted() {
124 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
125 if (!mHandshakeCompleted
) {
129 ChoseNotToFalseStart
= 3,
130 NotAllowedToFalseStart
= 4,
133 HandshakeType handshakeType
= !IsFullHandshake() ? Resumption
134 : mFalseStarted
? FalseStarted
135 : mFalseStartCallbackCalled
136 ? ChoseNotToFalseStart
137 : NotAllowedToFalseStart
;
138 // This will include TCP and proxy tunnel wait time
139 if (mKeaGroupName
.isSome()) {
140 Telemetry::AccumulateTimeDelta(
141 Telemetry::SSL_TIME_UNTIL_HANDSHAKE_FINISHED_KEYED_BY_KA
,
142 *mKeaGroupName
, mSocketCreationTimestamp
, TimeStamp::Now());
145 // If the handshake is completed for the first time from just 1 callback
146 // that means that TLS session resumption must have been used.
147 Telemetry::Accumulate(Telemetry::SSL_RESUMED_SESSION
,
148 handshakeType
== Resumption
);
149 Telemetry::Accumulate(Telemetry::SSL_HANDSHAKE_TYPE
, handshakeType
);
152 // Remove the plaintext layer as it is not needed anymore.
153 // The plaintext layer is not always present - so it's not a fatal error if it
154 // cannot be removed.
155 // Note that PR_PopIOLayer may modify its stack, so a pointer returned by
156 // PR_GetIdentitiesLayer may not point to what we think it points to after
157 // calling PR_PopIOLayer. We must operate on the pointer returned by
159 if (PR_GetIdentitiesLayer(mFd
,
160 nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity
)) {
161 PRFileDesc
* poppedPlaintext
=
162 PR_PopIOLayer(mFd
, nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity
);
163 poppedPlaintext
->dtor(poppedPlaintext
);
166 mHandshakeCompleted
= true;
168 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
169 ("[%p] NSSSocketControl::SetHandshakeCompleted\n", (void*)mFd
));
171 mIsFullHandshake
= false; // reset for next handshake on this connection
173 if (mTlsHandshakeCallback
) {
174 auto callback
= std::move(mTlsHandshakeCallback
);
175 Unused
<< callback
->HandshakeDone();
179 void NSSSocketControl::SetNegotiatedNPN(const char* value
, uint32_t length
) {
180 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
182 mNegotiatedNPN
.Truncate();
184 mNegotiatedNPN
.Assign(value
, length
);
186 mNPNCompleted
= true;
189 #define MAX_ALPN_LENGTH 255
192 NSSSocketControl::GetAlpnEarlySelection(nsACString
& aAlpnSelected
) {
193 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
194 aAlpnSelected
.Truncate();
196 SSLPreliminaryChannelInfo info
;
197 SECStatus rv
= SSL_GetPreliminaryChannelInfo(mFd
, &info
, sizeof(info
));
198 if (rv
!= SECSuccess
|| !info
.canSendEarlyData
) {
199 return NS_ERROR_NOT_AVAILABLE
;
202 SSLNextProtoState alpnState
;
203 unsigned char chosenAlpn
[MAX_ALPN_LENGTH
];
204 unsigned int chosenAlpnLen
;
205 rv
= SSL_GetNextProto(mFd
, &alpnState
, chosenAlpn
, &chosenAlpnLen
,
206 AssertedCast
<unsigned int>(std::size(chosenAlpn
)));
208 if (rv
!= SECSuccess
) {
209 return NS_ERROR_NOT_AVAILABLE
;
212 if (alpnState
== SSL_NEXT_PROTO_EARLY_VALUE
) {
213 aAlpnSelected
.Assign(BitwiseCast
<char*, unsigned char*>(chosenAlpn
),
221 NSSSocketControl::GetEarlyDataAccepted(bool* aAccepted
) {
222 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
223 *aAccepted
= mEarlyDataAccepted
;
227 void NSSSocketControl::SetEarlyDataAccepted(bool aAccepted
) {
228 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
229 mEarlyDataAccepted
= aAccepted
;
232 bool NSSSocketControl::GetDenyClientCert() {
233 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
234 return mDenyClientCert
;
237 void NSSSocketControl::SetDenyClientCert(bool aDenyClientCert
) {
238 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
239 mDenyClientCert
= aDenyClientCert
;
243 NSSSocketControl::DriveHandshake() {
244 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
246 return NS_ERROR_FAILURE
;
249 PRErrorCode errorCode
= GetErrorCode();
250 MOZ_DIAGNOSTIC_ASSERT(errorCode
, "handshake cancelled without error code");
251 return GetXPCOMFromNSSError(errorCode
);
254 SECStatus rv
= SSL_ForceHandshake(mFd
);
256 if (rv
!= SECSuccess
) {
257 PRErrorCode errorCode
= PR_GetError();
258 MOZ_ASSERT(errorCode
, "handshake failed without error code");
259 // There is a bug in NSS. Sometimes SSL_ForceHandshake will return
260 // SECFailure without setting an error code. In these cases, cancel
261 // the connection with SEC_ERROR_LIBRARY_FAILURE.
263 errorCode
= SEC_ERROR_LIBRARY_FAILURE
;
265 if (errorCode
== PR_WOULD_BLOCK_ERROR
) {
266 return NS_BASE_STREAM_WOULD_BLOCK
;
269 SetCanceled(errorCode
);
270 return GetXPCOMFromNSSError(errorCode
);
275 bool NSSSocketControl::GetForSTARTTLS() {
276 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
280 void NSSSocketControl::SetForSTARTTLS(bool aForSTARTTLS
) {
281 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
282 mForSTARTTLS
= aForSTARTTLS
;
286 NSSSocketControl::ProxyStartSSL() {
287 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
288 return ActivateSSL();
292 NSSSocketControl::StartTLS() {
293 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
294 return ActivateSSL();
298 NSSSocketControl::AsyncStartTLS(JSContext
* aCx
,
299 mozilla::dom::Promise
** aPromise
) {
300 MOZ_RELEASE_ASSERT(NS_IsMainThread());
301 NS_ENSURE_ARG_POINTER(aCx
);
302 NS_ENSURE_ARG_POINTER(aPromise
);
304 nsIGlobalObject
* globalObject
= xpc::CurrentNativeGlobal(aCx
);
306 return NS_ERROR_UNEXPECTED
;
310 RefPtr
<mozilla::dom::Promise
> promise
=
311 mozilla::dom::Promise::Create(globalObject
, result
);
312 if (result
.Failed()) {
313 return result
.StealNSResult();
316 nsCOMPtr
<nsIEventTarget
> target(
317 do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID
));
319 return NS_ERROR_UNEXPECTED
;
322 auto promiseHolder
= MakeRefPtr
<nsMainThreadPtrHolder
<dom::Promise
>>(
323 "AsyncStartTLS promise", promise
);
325 nsCOMPtr
<nsIRunnable
> runnable(NS_NewRunnableFunction(
326 "AsyncStartTLS::StartTLS",
327 [promiseHolder
= std::move(promiseHolder
), self
= RefPtr
{this}]() {
328 nsresult rv
= self
->StartTLS();
329 NS_DispatchToMainThread(NS_NewRunnableFunction(
330 "AsyncStartTLS::Resolve", [rv
, promiseHolder
]() {
331 dom::Promise
* promise
= promiseHolder
.get()->get();
333 promise
->MaybeReject(rv
);
335 promise
->MaybeResolveWithUndefined();
340 nsresult rv
= target
->Dispatch(runnable
, NS_DISPATCH_NORMAL
);
345 promise
.forget(aPromise
);
350 NSSSocketControl::SetNPNList(nsTArray
<nsCString
>& protocolArray
) {
351 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
352 if (!mFd
) return NS_ERROR_FAILURE
;
354 // the npn list is a concatenated list of 8 bit byte strings.
357 for (uint32_t index
= 0; index
< protocolArray
.Length(); ++index
) {
358 if (protocolArray
[index
].IsEmpty() || protocolArray
[index
].Length() > 255)
359 return NS_ERROR_ILLEGAL_VALUE
;
361 npnList
.Append(protocolArray
[index
].Length());
362 npnList
.Append(protocolArray
[index
]);
365 if (SSL_SetNextProtoNego(
366 mFd
, BitwiseCast
<const unsigned char*, const char*>(npnList
.get()),
367 npnList
.Length()) != SECSuccess
)
368 return NS_ERROR_FAILURE
;
373 nsresult
NSSSocketControl::ActivateSSL() {
374 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
375 if (SECSuccess
!= SSL_OptionSet(mFd
, SSL_SECURITY
, true))
376 return NS_ERROR_FAILURE
;
377 if (SECSuccess
!= SSL_ResetHandshake(mFd
, false)) return NS_ERROR_FAILURE
;
379 mHandshakePending
= true;
381 return SetResumptionTokenFromExternalCache(mFd
);
384 nsresult
NSSSocketControl::GetFileDescPtr(PRFileDesc
** aFilePtr
) {
385 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
390 nsresult
NSSSocketControl::SetFileDescPtr(PRFileDesc
* aFilePtr
) {
391 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
396 void NSSSocketControl::SetCertVerificationWaiting() {
397 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
398 // mCertVerificationState may be BeforeCertVerification for the first
399 // handshake on the connection, or AfterCertVerification for subsequent
400 // renegotiation handshakes.
401 MOZ_ASSERT(mCertVerificationState
!= WaitingForCertVerification
,
402 "Invalid state transition to WaitingForCertVerification");
403 mCertVerificationState
= WaitingForCertVerification
;
406 // Be careful that SetCertVerificationResult does NOT get called while we are
407 // processing a SSL callback function, because SSL_AuthCertificateComplete will
408 // attempt to acquire locks that are already held by libssl when it calls
410 void NSSSocketControl::SetCertVerificationResult(PRErrorCode errorCode
) {
411 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
412 SetUsedPrivateDNS(GetProviderFlags() & nsISocketProvider::USED_PRIVATE_DNS
);
413 MOZ_ASSERT(mCertVerificationState
== WaitingForCertVerification
,
414 "Invalid state transition to AfterCertVerification");
417 SECStatus rv
= SSL_AuthCertificateComplete(mFd
, errorCode
);
418 // Only replace errorCode if there was originally no error.
419 // SSL_AuthCertificateComplete will return SECFailure with the error code
420 // set to PR_WOULD_BLOCK_ERROR if there is a pending event to select a
421 // client authentication certificate. This is not an error.
422 if (rv
!= SECSuccess
&& PR_GetError() != PR_WOULD_BLOCK_ERROR
&&
424 errorCode
= PR_GetError();
425 if (errorCode
== 0) {
426 NS_ERROR("SSL_AuthCertificateComplete didn't set error code");
427 errorCode
= PR_INVALID_STATE_ERROR
;
433 mFailedVerification
= true;
434 SetCanceled(errorCode
);
437 if (mPlaintextBytesRead
&& !errorCode
) {
438 Telemetry::Accumulate(Telemetry::SSL_BYTES_BEFORE_CERT_CALLBACK
,
439 AssertedCast
<uint32_t>(mPlaintextBytesRead
));
442 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
443 ("[%p] SetCertVerificationResult to AfterCertVerification, "
444 "mTlsHandshakeCallback=%p",
445 (void*)mFd
, mTlsHandshakeCallback
.get()));
447 mCertVerificationState
= AfterCertVerification
;
448 if (mTlsHandshakeCallback
) {
449 Unused
<< mTlsHandshakeCallback
->CertVerificationDone();
453 void NSSSocketControl::ClientAuthCertificateSelected(
454 nsTArray
<uint8_t>& certBytes
, nsTArray
<nsTArray
<uint8_t>>& certChainBytes
) {
455 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
456 // If mFd is nullptr, the connection has been closed already, so we don't
457 // need to do anything here.
463 const_cast<uint8_t*>(certBytes
.Elements()),
464 static_cast<unsigned int>(certBytes
.Length()),
466 UniqueCERTCertificate
cert(CERT_NewTempCertificate(
467 CERT_GetDefaultCertDB(), &certItem
, nullptr, false, true));
468 UniqueSECKEYPrivateKey key
;
470 key
.reset(PK11_FindKeyByAnyCert(cert
.get(), nullptr));
471 mClientCertChain
.reset(CERT_NewCertList());
472 if (key
&& mClientCertChain
) {
473 for (const auto& certBytes
: certChainBytes
) {
476 const_cast<uint8_t*>(certBytes
.Elements()),
477 static_cast<unsigned int>(certBytes
.Length()),
479 UniqueCERTCertificate
cert(CERT_NewTempCertificate(
480 CERT_GetDefaultCertDB(), &certItem
, nullptr, false, true));
482 if (CERT_AddCertToListTail(mClientCertChain
.get(), cert
.get()) ==
484 Unused
<< cert
.release();
491 bool sendingClientAuthCert
= cert
&& key
;
492 if (sendingClientAuthCert
) {
493 mSentClientCert
= true;
494 glean::security::client_auth_cert_usage
.Get("sent"_ns
).Add(1);
497 Unused
<< SSL_ClientCertCallbackComplete(
498 mFd
, sendingClientAuthCert
? SECSuccess
: SECFailure
,
499 sendingClientAuthCert
? key
.release() : nullptr,
500 sendingClientAuthCert
? cert
.release() : nullptr);
502 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
503 ("[%p] ClientAuthCertificateSelected mTlsHandshakeCallback=%p",
504 (void*)mFd
, mTlsHandshakeCallback
.get()));
505 if (mTlsHandshakeCallback
) {
506 Unused
<< mTlsHandshakeCallback
->ClientAuthCertificateSelected();
511 NSSSocketControl::DisableEarlyData() {
512 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
520 if (SSL_OptionSet(mFd
, SSL_ENABLE_0RTT_DATA
, false) != SECSuccess
) {
521 return NS_ERROR_FAILURE
;
527 NSSSocketControl::SetHandshakeCallbackListener(
528 nsITlsHandshakeCallbackListener
* callback
) {
529 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
530 mTlsHandshakeCallback
= callback
;
534 PRStatus
NSSSocketControl::CloseSocketAndDestroy() {
535 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
537 mPendingSelectClientAuthCertificate
= nullptr;
539 PRFileDesc
* popped
= PR_PopIOLayer(mFd
, PR_TOP_IO_LAYER
);
541 popped
&& popped
->identity
== nsSSLIOLayerHelpers::nsSSLIOLayerIdentity
,
542 "SSL Layer not on top of stack");
544 // The plaintext layer is not always present - so it's not a fatal error if it
545 // cannot be removed.
546 // Note that PR_PopIOLayer may modify its stack, so a pointer returned by
547 // PR_GetIdentitiesLayer may not point to what we think it points to after
548 // calling PR_PopIOLayer. We must operate on the pointer returned by
550 if (PR_GetIdentitiesLayer(mFd
,
551 nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity
)) {
552 PRFileDesc
* poppedPlaintext
=
553 PR_PopIOLayer(mFd
, nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity
);
554 poppedPlaintext
->dtor(poppedPlaintext
);
557 // We need to clear the callback to make sure the ssl layer cannot call the
558 // callback after mFD is nulled.
559 SSL_SetResumptionTokenCallback(mFd
, nullptr, nullptr);
561 PRStatus status
= mFd
->methods
->close(mFd
);
563 // the NSSSocketControl instance can out-live the connection, so we need some
564 // indication that the connection has been closed. mFd == nullptr is that
565 // indication. This is needed, for example, when the connection is closed
566 // before we have finished validating the server's certificate.
569 if (status
!= PR_SUCCESS
) return status
;
571 popped
->identity
= PR_INVALID_IO_LAYER
;
572 popped
->dtor(popped
);
578 NSSSocketControl::GetEsniTxt(nsACString
& aEsniTxt
) {
579 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
585 NSSSocketControl::SetEsniTxt(const nsACString
& aEsniTxt
) {
586 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
589 if (mEsniTxt
.Length()) {
590 nsAutoCString esniBin
;
591 if (NS_OK
!= Base64Decode(mEsniTxt
, esniBin
)) {
592 MOZ_LOG(gPIPNSSLog
, LogLevel::Error
,
593 ("[%p] Invalid ESNIKeys record. Couldn't base64 decode\n",
599 SSL_EnableESNI(mFd
, reinterpret_cast<const PRUint8
*>(esniBin
.get()),
600 esniBin
.Length(), nullptr)) {
601 MOZ_LOG(gPIPNSSLog
, LogLevel::Error
,
602 ("[%p] Invalid ESNIKeys record %s\n", (void*)mFd
,
603 PR_ErrorToName(PR_GetError())));
612 NSSSocketControl::GetEchConfig(nsACString
& aEchConfig
) {
613 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
614 aEchConfig
= mEchConfig
;
619 NSSSocketControl::SetEchConfig(const nsACString
& aEchConfig
) {
620 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
621 mEchConfig
= aEchConfig
;
623 if (mEchConfig
.Length()) {
625 SSL_SetClientEchConfigs(
626 mFd
, reinterpret_cast<const PRUint8
*>(aEchConfig
.BeginReading()),
627 aEchConfig
.Length())) {
628 MOZ_LOG(gPIPNSSLog
, LogLevel::Error
,
629 ("[%p] Invalid EchConfig record %s\n", (void*)mFd
,
630 PR_ErrorToName(PR_GetError())));
633 UpdateEchExtensionStatus(EchExtensionStatus::kReal
);
639 NSSSocketControl::GetRetryEchConfig(nsACString
& aEchConfig
) {
640 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
642 return NS_ERROR_FAILURE
;
645 ScopedAutoSECItem retryConfigItem
;
646 SECStatus rv
= SSL_GetEchRetryConfigs(mFd
, &retryConfigItem
);
647 if (rv
!= SECSuccess
) {
648 return NS_ERROR_FAILURE
;
650 aEchConfig
= nsCString(reinterpret_cast<const char*>(retryConfigItem
.data
),
651 retryConfigItem
.len
);
656 NSSSocketControl::GetPeerId(nsACString
& aResult
) {
657 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
658 if (!mPeerId
.IsEmpty()) {
659 aResult
.Assign(mPeerId
);
664 nsISocketProvider::ANONYMOUS_CONNECT
) { // See bug 466080
665 mPeerId
.AppendLiteral("anon:");
667 if (mProviderFlags
& nsISocketProvider::NO_PERMANENT_STORAGE
) {
668 mPeerId
.AppendLiteral("private:");
670 if (mProviderFlags
& nsISocketProvider::BE_CONSERVATIVE
) {
671 mPeerId
.AppendLiteral("beConservative:");
674 mPeerId
.AppendPrintf("tlsflags0x%08x:", mProviderTlsFlags
);
676 mPeerId
.Append(mHostName
);
678 mPeerId
.AppendInt(GetPort());
679 nsAutoCString suffix
;
680 mOriginAttributes
.CreateSuffix(suffix
);
681 mPeerId
.Append(suffix
);
683 aResult
.Assign(mPeerId
);
687 nsresult
NSSSocketControl::SetResumptionTokenFromExternalCache(PRFileDesc
* fd
) {
688 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
690 return NS_ERROR_INVALID_ARG
;
693 // If SSL_NO_CACHE option was set, we must not use the cache
695 if (SSL_OptionGet(fd
, SSL_NO_CACHE
, &val
) != SECSuccess
) {
696 return NS_ERROR_FAILURE
;
703 nsTArray
<uint8_t> token
;
704 nsAutoCString peerId
;
705 nsresult rv
= GetPeerId(peerId
);
710 uint64_t tokenId
= 0;
711 mozilla::net::SessionCacheInfo info
;
712 rv
= mozilla::net::SSLTokensCache::Get(peerId
, token
, info
, &tokenId
);
714 if (rv
== NS_ERROR_NOT_AVAILABLE
) {
715 // It's ok if we can't find the token.
722 SECStatus srv
= SSL_SetResumptionToken(fd
, token
.Elements(), token
.Length());
723 if (srv
== SECFailure
) {
724 PRErrorCode error
= PR_GetError();
725 mozilla::net::SSLTokensCache::Remove(peerId
, tokenId
);
726 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
727 ("Setting token failed with NSS error %d [id=%s]", error
,
728 PromiseFlatCString(peerId
).get()));
729 // We don't consider SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR as a hard error,
730 // since this error means this token is just expired or can't be decoded
732 if (error
== SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR
) {
736 return NS_ERROR_FAILURE
;
739 SetSessionCacheInfo(std::move(info
));
744 void NSSSocketControl::SetPreliminaryHandshakeInfo(
745 const SSLChannelInfo
& channelInfo
, const SSLCipherSuiteInfo
& cipherInfo
) {
746 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
747 mResumed
= channelInfo
.resumed
;
748 mCipherSuite
.emplace(channelInfo
.cipherSuite
);
749 mProtocolVersion
.emplace(channelInfo
.protocolVersion
& 0xFF);
750 mKeaGroupName
.emplace(getKeaGroupName(channelInfo
.keaGroup
));
751 mSignatureSchemeName
.emplace(getSignatureName(channelInfo
.signatureScheme
));
752 mIsDelegatedCredential
.emplace(channelInfo
.peerDelegCred
);
753 mIsAcceptedEch
.emplace(channelInfo
.echAccepted
);
756 NS_IMETHODIMP
NSSSocketControl::Claim() {
757 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
762 NS_IMETHODIMP
NSSSocketControl::SetBrowserId(uint64_t browserId
) {
763 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
764 mBrowserId
= browserId
;
768 NS_IMETHODIMP
NSSSocketControl::GetBrowserId(uint64_t* browserId
) {
769 COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
771 return NS_ERROR_INVALID_ARG
;
773 *browserId
= mBrowserId
;