nsNSSCallbacks.cpp (37871B)
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 #include "nsNSSCallbacks.h" 8 9 #include "NSSSocketControl.h" 10 #include "PSMRunnable.h" 11 #include "ScopedNSSTypes.h" 12 #include "SharedCertVerifier.h" 13 #include "mozilla/Assertions.h" 14 #include "mozilla/Casting.h" 15 #include "mozilla/Logging.h" 16 #include "mozilla/RefPtr.h" 17 #include "mozilla/ScopeExit.h" 18 #include "mozilla/Span.h" 19 #include "mozilla/SpinEventLoopUntil.h" 20 #include "mozilla/StaticPrefs_security.h" 21 #include "mozilla/glean/SecurityManagerSslMetrics.h" 22 #include "mozilla/intl/Localization.h" 23 #include "nsContentUtils.h" 24 #include "nsIChannel.h" 25 #include "nsIHttpChannel.h" 26 #include "nsIHttpChannelInternal.h" 27 #include "nsIPrompt.h" 28 #include "nsIProtocolProxyService.h" 29 #include "nsISupportsPriority.h" 30 #include "nsIStreamLoader.h" 31 #include "nsIUploadChannel.h" 32 #include "nsIWebProgressListener.h" 33 #include "nsNSSCertHelper.h" 34 #include "nsNSSCertificate.h" 35 #include "nsNSSComponent.h" 36 #include "nsNSSHelper.h" 37 #include "nsNSSIOLayer.h" 38 #include "nsNetUtil.h" 39 #include "nsProxyRelease.h" 40 #include "nsStringStream.h" 41 #include "mozpkix/pkixtypes.h" 42 #include "ssl.h" 43 #include "sslproto.h" 44 #include "SSLTokensCache.h" 45 46 using namespace mozilla; 47 using namespace mozilla::pkix; 48 using namespace mozilla::psm; 49 50 extern LazyLogModule gPIPNSSLog; 51 52 namespace { 53 54 // Bits in bit mask for SSL_REASONS_FOR_NOT_FALSE_STARTING telemetry probe 55 // These bits are numbered so that the least subtle issues have higher values. 56 // This should make it easier for us to interpret the results. 57 const uint32_t POSSIBLE_VERSION_DOWNGRADE = 4; 58 const uint32_t POSSIBLE_CIPHER_SUITE_DOWNGRADE = 2; 59 const uint32_t KEA_NOT_SUPPORTED = 1; 60 61 } // namespace 62 63 class OCSPRequest final : public nsIStreamLoaderObserver, public nsIRunnable { 64 public: 65 OCSPRequest(const nsACString& aiaLocation, 66 const OriginAttributes& originAttributes, 67 const uint8_t (&ocspRequest)[OCSP_REQUEST_MAX_LENGTH], 68 size_t ocspRequestLength, TimeDuration timeout); 69 70 NS_DECL_THREADSAFE_ISUPPORTS 71 NS_DECL_NSISTREAMLOADEROBSERVER 72 NS_DECL_NSIRUNNABLE 73 74 nsresult DispatchToMainThreadAndWait(); 75 nsresult GetResponse(/*out*/ Vector<uint8_t>& response); 76 77 private: 78 ~OCSPRequest() = default; 79 80 static void OnTimeout(nsITimer* timer, void* closure); 81 nsresult NotifyDone(nsresult rv, MonitorAutoLock& proofOfLock); 82 83 // mMonitor provides the memory barrier protecting these member variables. 84 // What happens is the originating thread creates an OCSPRequest object with 85 // the information necessary to perform an OCSP request. It sends the object 86 // to the main thread and waits on the monitor for the operation to complete. 87 // On the main thread, a channel is set up to perform the request. This gets 88 // dispatched to necko. At the same time, a timeout timer is initialized. If 89 // the necko request completes, the response data is filled out, mNotifiedDone 90 // is set to true, and the monitor is notified. The original thread then wakes 91 // up and continues with the results that have been filled out. If the request 92 // times out, again the response data is filled out, mNotifiedDone is set to 93 // true, and the monitor is notified. The first of these two events wins. That 94 // is, if the timeout timer fires but the request completes shortly after, the 95 // caller will see the request as having timed out. 96 // When the request completes (i.e. OnStreamComplete runs), the timer will be 97 // cancelled. This is how we know the closure in OnTimeout is valid. If the 98 // timer fires before OnStreamComplete runs, it should be safe to not cancel 99 // the request because necko has a strong reference to it. 100 Monitor mMonitor MOZ_UNANNOTATED; 101 bool mNotifiedDone; 102 nsCOMPtr<nsIStreamLoader> mLoader; 103 const nsCString mAIALocation; 104 const OriginAttributes mOriginAttributes; 105 const mozilla::Span<const char> mPOSTData; 106 const TimeDuration mTimeout; 107 nsCOMPtr<nsITimer> mTimeoutTimer; 108 TimeStamp mStartTime; 109 nsresult mResponseResult; 110 Vector<uint8_t> mResponseBytes; 111 }; 112 113 NS_IMPL_ISUPPORTS(OCSPRequest, nsIStreamLoaderObserver, nsIRunnable) 114 115 OCSPRequest::OCSPRequest(const nsACString& aiaLocation, 116 const OriginAttributes& originAttributes, 117 const uint8_t (&ocspRequest)[OCSP_REQUEST_MAX_LENGTH], 118 size_t ocspRequestLength, TimeDuration timeout) 119 : mMonitor("OCSPRequest.mMonitor"), 120 mNotifiedDone(false), 121 mLoader(nullptr), 122 mAIALocation(aiaLocation), 123 mOriginAttributes(originAttributes), 124 mPOSTData(reinterpret_cast<const char*>(ocspRequest), ocspRequestLength), 125 mTimeout(timeout), 126 mTimeoutTimer(nullptr), 127 mResponseResult(NS_ERROR_FAILURE) { 128 MOZ_ASSERT(ocspRequestLength <= OCSP_REQUEST_MAX_LENGTH); 129 } 130 131 nsresult OCSPRequest::DispatchToMainThreadAndWait() { 132 MOZ_ASSERT(!NS_IsMainThread()); 133 if (NS_IsMainThread()) { 134 return NS_ERROR_FAILURE; 135 } 136 137 MonitorAutoLock lock(mMonitor); 138 nsresult rv = NS_DispatchToMainThread(this); 139 if (NS_FAILED(rv)) { 140 return rv; 141 } 142 while (!mNotifiedDone) { 143 lock.Wait(); 144 } 145 146 // CERT_VALIDATION_HTTP_REQUEST_RESULT: 147 // 0: request timed out 148 // 1: request succeeded 149 // 2: request failed 150 // 3: internal error 151 // If mStartTime was never set, we consider this an internal error. 152 // Otherwise, we managed to at least send the request. 153 if (mStartTime.IsNull()) { 154 glean::cert::validation_http_request_result.AccumulateSingleSample(3); 155 } else if (mResponseResult == NS_ERROR_NET_TIMEOUT) { 156 glean::cert::validation_http_request_result.AccumulateSingleSample(0); 157 mozilla::glean::ocsp_request_time::cancel.AccumulateRawDuration( 158 TimeStamp::Now() - mStartTime); 159 } else if (NS_SUCCEEDED(mResponseResult)) { 160 glean::cert::validation_http_request_result.AccumulateSingleSample(1); 161 mozilla::glean::ocsp_request_time::success.AccumulateRawDuration( 162 TimeStamp::Now() - mStartTime); 163 } else { 164 glean::cert::validation_http_request_result.AccumulateSingleSample(2); 165 mozilla::glean::ocsp_request_time::failure.AccumulateRawDuration( 166 TimeStamp::Now() - mStartTime); 167 } 168 return rv; 169 } 170 171 nsresult OCSPRequest::GetResponse(/*out*/ Vector<uint8_t>& response) { 172 MOZ_ASSERT(!NS_IsMainThread()); 173 if (NS_IsMainThread()) { 174 return NS_ERROR_FAILURE; 175 } 176 177 MonitorAutoLock lock(mMonitor); 178 if (!mNotifiedDone) { 179 return NS_ERROR_IN_PROGRESS; 180 } 181 if (NS_FAILED(mResponseResult)) { 182 return mResponseResult; 183 } 184 response.clear(); 185 if (!response.append(mResponseBytes.begin(), mResponseBytes.length())) { 186 return NS_ERROR_OUT_OF_MEMORY; 187 } 188 return NS_OK; 189 } 190 191 static constexpr auto OCSP_REQUEST_MIME_TYPE = "application/ocsp-request"_ns; 192 static constexpr auto OCSP_REQUEST_METHOD = "POST"_ns; 193 194 NS_IMETHODIMP 195 OCSPRequest::Run() { 196 MOZ_ASSERT(NS_IsMainThread()); 197 if (!NS_IsMainThread()) { 198 return NS_ERROR_FAILURE; 199 } 200 201 MonitorAutoLock lock(mMonitor); 202 203 nsCOMPtr<nsIIOService> ios = do_GetIOService(); 204 if (!ios) { 205 return NotifyDone(NS_ERROR_FAILURE, lock); 206 } 207 208 nsCOMPtr<nsIURI> uri; 209 nsresult rv = NS_NewURI(getter_AddRefs(uri), mAIALocation); 210 if (NS_FAILED(rv)) { 211 return NotifyDone(NS_ERROR_MALFORMED_URI, lock); 212 } 213 nsAutoCString scheme; 214 rv = uri->GetScheme(scheme); 215 if (NS_FAILED(rv)) { 216 return NotifyDone(rv, lock); 217 } 218 if (!scheme.LowerCaseEqualsLiteral("http")) { 219 return NotifyDone(NS_ERROR_MALFORMED_URI, lock); 220 } 221 222 // See bug 1219935. 223 // We should not send OCSP request if the PAC is still loading. 224 nsCOMPtr<nsIProtocolProxyService> pps = 225 do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv); 226 if (NS_FAILED(rv)) { 227 return NotifyDone(rv, lock); 228 } 229 230 if (pps->GetIsPACLoading()) { 231 return NotifyDone(NS_ERROR_FAILURE, lock); 232 } 233 234 nsCOMPtr<nsIChannel> channel; 235 rv = ios->NewChannel(mAIALocation, nullptr, nullptr, 236 nullptr, // aLoadingNode 237 nsContentUtils::GetSystemPrincipal(), 238 nullptr, // aTriggeringPrincipal 239 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, 240 nsIContentPolicy::TYPE_OTHER, getter_AddRefs(channel)); 241 if (NS_FAILED(rv)) { 242 return NotifyDone(rv, lock); 243 } 244 245 // Security operations scheduled through normal HTTP channels are given 246 // high priority to accommodate real time OCSP transactions. 247 nsCOMPtr<nsISupportsPriority> priorityChannel = do_QueryInterface(channel); 248 if (priorityChannel) { 249 priorityChannel->AdjustPriority(nsISupportsPriority::PRIORITY_HIGHEST); 250 } 251 252 channel->SetLoadFlags( 253 nsIRequest::LOAD_ANONYMOUS | nsIRequest::LOAD_BYPASS_CACHE | 254 nsIRequest::INHIBIT_CACHING | nsIChannel::LOAD_BYPASS_SERVICE_WORKER | 255 nsIChannel::LOAD_BYPASS_URL_CLASSIFIER); 256 257 nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo(); 258 259 // Prevent HTTPS-Only Mode from upgrading the OCSP request. 260 uint32_t httpsOnlyStatus = loadInfo->GetHttpsOnlyStatus(); 261 httpsOnlyStatus |= nsILoadInfo::HTTPS_ONLY_EXEMPT; 262 loadInfo->SetHttpsOnlyStatus(httpsOnlyStatus); 263 264 // allow deprecated HTTP request from SystemPrincipal 265 loadInfo->SetAllowDeprecatedSystemRequests(true); 266 267 // For OCSP requests, only the first party domain and private browsing id 268 // aspects of origin attributes are used. This means that: 269 // a) if first party isolation is enabled, OCSP requests will be isolated 270 // according to the first party domain of the original https request 271 // b) OCSP requests are shared across different containers as long as first 272 // party isolation is not enabled and none of the containers are in private 273 // browsing mode. 274 if (mOriginAttributes != OriginAttributes()) { 275 OriginAttributes attrs; 276 attrs.mFirstPartyDomain = mOriginAttributes.mFirstPartyDomain; 277 attrs.mPrivateBrowsingId = mOriginAttributes.mPrivateBrowsingId; 278 279 rv = loadInfo->SetOriginAttributes(attrs); 280 if (NS_FAILED(rv)) { 281 return NotifyDone(rv, lock); 282 } 283 } 284 285 nsCOMPtr<nsIInputStream> uploadStream; 286 rv = NS_NewByteInputStream(getter_AddRefs(uploadStream), mPOSTData, 287 NS_ASSIGNMENT_COPY); 288 if (NS_FAILED(rv)) { 289 return NotifyDone(rv, lock); 290 } 291 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(channel)); 292 if (!uploadChannel) { 293 return NotifyDone(NS_ERROR_FAILURE, lock); 294 } 295 rv = uploadChannel->SetUploadStream(uploadStream, OCSP_REQUEST_MIME_TYPE, -1); 296 if (NS_FAILED(rv)) { 297 return NotifyDone(rv, lock); 298 } 299 // Do not use SPDY or HTTP3 for internal security operations. It could result 300 // in the silent upgrade to ssl, which in turn could require an SSL 301 // operation to fulfill something like an OCSP fetch, which is an 302 // endless loop. 303 nsCOMPtr<nsIHttpChannelInternal> internalChannel = do_QueryInterface(channel); 304 if (!internalChannel) { 305 return NotifyDone(rv, lock); 306 } 307 rv = internalChannel->SetAllowSpdy(false); 308 if (NS_FAILED(rv)) { 309 return NotifyDone(rv, lock); 310 } 311 rv = internalChannel->SetAllowHttp3(false); 312 if (NS_FAILED(rv)) { 313 return NotifyDone(rv, lock); 314 } 315 rv = internalChannel->SetIsOCSP(true); 316 if (NS_FAILED(rv)) { 317 return NotifyDone(rv, lock); 318 } 319 nsCOMPtr<nsIHttpChannel> hchan = do_QueryInterface(channel); 320 if (!hchan) { 321 return NotifyDone(NS_ERROR_FAILURE, lock); 322 } 323 rv = hchan->SetAllowSTS(false); 324 if (NS_FAILED(rv)) { 325 return NotifyDone(rv, lock); 326 } 327 rv = hchan->SetRequestMethod(OCSP_REQUEST_METHOD); 328 if (NS_FAILED(rv)) { 329 return NotifyDone(rv, lock); 330 } 331 332 rv = NS_NewStreamLoader(getter_AddRefs(mLoader), this); 333 if (NS_FAILED(rv)) { 334 return NotifyDone(rv, lock); 335 } 336 337 rv = NS_NewTimerWithFuncCallback( 338 getter_AddRefs(mTimeoutTimer), OCSPRequest::OnTimeout, this, 339 mTimeout.ToMilliseconds(), nsITimer::TYPE_ONE_SHOT, 340 "OCSPRequest::Run"_ns); 341 if (NS_FAILED(rv)) { 342 return NotifyDone(rv, lock); 343 } 344 rv = hchan->AsyncOpen(this->mLoader); 345 if (NS_FAILED(rv)) { 346 return NotifyDone(rv, lock); 347 } 348 mStartTime = TimeStamp::Now(); 349 return NS_OK; 350 } 351 352 nsresult OCSPRequest::NotifyDone(nsresult rv, MonitorAutoLock& lock) { 353 MOZ_ASSERT(NS_IsMainThread()); 354 if (!NS_IsMainThread()) { 355 return NS_ERROR_FAILURE; 356 } 357 358 if (mNotifiedDone) { 359 return mResponseResult; 360 } 361 mLoader = nullptr; 362 mResponseResult = rv; 363 if (mTimeoutTimer) { 364 (void)mTimeoutTimer->Cancel(); 365 } 366 mNotifiedDone = true; 367 lock.Notify(); 368 return rv; 369 } 370 371 NS_IMETHODIMP 372 OCSPRequest::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext, 373 nsresult aStatus, uint32_t responseLen, 374 const uint8_t* responseBytes) { 375 MOZ_ASSERT(NS_IsMainThread()); 376 if (!NS_IsMainThread()) { 377 return NS_ERROR_FAILURE; 378 } 379 380 MonitorAutoLock lock(mMonitor); 381 382 nsCOMPtr<nsIRequest> req; 383 nsresult rv = aLoader->GetRequest(getter_AddRefs(req)); 384 if (NS_FAILED(rv)) { 385 return NotifyDone(rv, lock); 386 } 387 388 if (NS_FAILED(aStatus)) { 389 return NotifyDone(aStatus, lock); 390 } 391 392 nsCOMPtr<nsIHttpChannel> hchan = do_QueryInterface(req); 393 if (!hchan) { 394 return NotifyDone(NS_ERROR_FAILURE, lock); 395 } 396 397 bool requestSucceeded; 398 rv = hchan->GetRequestSucceeded(&requestSucceeded); 399 if (NS_FAILED(rv)) { 400 return NotifyDone(rv, lock); 401 } 402 if (!requestSucceeded) { 403 return NotifyDone(NS_ERROR_FAILURE, lock); 404 } 405 406 unsigned int rcode; 407 rv = hchan->GetResponseStatus(&rcode); 408 if (NS_FAILED(rv)) { 409 return NotifyDone(rv, lock); 410 } 411 if (rcode != 200) { 412 return NotifyDone(NS_ERROR_FAILURE, lock); 413 } 414 415 mResponseBytes.clear(); 416 if (!mResponseBytes.append(responseBytes, responseLen)) { 417 return NotifyDone(NS_ERROR_OUT_OF_MEMORY, lock); 418 } 419 mResponseResult = aStatus; 420 421 return NotifyDone(NS_OK, lock); 422 } 423 424 void OCSPRequest::OnTimeout(nsITimer* timer, void* closure) { 425 MOZ_ASSERT(NS_IsMainThread()); 426 if (!NS_IsMainThread()) { 427 return; 428 } 429 430 // We know the OCSPRequest is still alive because if the request had completed 431 // (i.e. OnStreamComplete ran), the timer would have been cancelled in 432 // NotifyDone. 433 OCSPRequest* self = static_cast<OCSPRequest*>(closure); 434 MonitorAutoLock lock(self->mMonitor); 435 self->mTimeoutTimer = nullptr; 436 self->NotifyDone(NS_ERROR_NET_TIMEOUT, lock); 437 } 438 439 mozilla::pkix::Result DoOCSPRequest( 440 const nsCString& aiaLocation, const OriginAttributes& originAttributes, 441 uint8_t (&ocspRequest)[OCSP_REQUEST_MAX_LENGTH], size_t ocspRequestLength, 442 TimeDuration timeout, /*out*/ Vector<uint8_t>& result) { 443 MOZ_ASSERT(!NS_IsMainThread()); 444 if (NS_IsMainThread()) { 445 return mozilla::pkix::Result::ERROR_OCSP_UNKNOWN_CERT; 446 } 447 448 if (ocspRequestLength > OCSP_REQUEST_MAX_LENGTH) { 449 return mozilla::pkix::Result::FATAL_ERROR_LIBRARY_FAILURE; 450 } 451 452 result.clear(); 453 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 454 ("DoOCSPRequest to '%s'", aiaLocation.get())); 455 456 nsCOMPtr<nsIEventTarget> sts = 457 do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID); 458 MOZ_ASSERT(sts); 459 if (!sts) { 460 return mozilla::pkix::Result::FATAL_ERROR_INVALID_STATE; 461 } 462 bool onSTSThread; 463 nsresult rv = sts->IsOnCurrentThread(&onSTSThread); 464 if (NS_FAILED(rv)) { 465 return mozilla::pkix::Result::FATAL_ERROR_LIBRARY_FAILURE; 466 } 467 MOZ_ASSERT(!onSTSThread); 468 if (onSTSThread) { 469 return mozilla::pkix::Result::FATAL_ERROR_INVALID_STATE; 470 } 471 472 RefPtr<OCSPRequest> request(new OCSPRequest( 473 aiaLocation, originAttributes, ocspRequest, ocspRequestLength, timeout)); 474 rv = request->DispatchToMainThreadAndWait(); 475 if (NS_FAILED(rv)) { 476 return mozilla::pkix::Result::FATAL_ERROR_LIBRARY_FAILURE; 477 } 478 rv = request->GetResponse(result); 479 if (NS_FAILED(rv)) { 480 if (rv == NS_ERROR_MALFORMED_URI) { 481 return mozilla::pkix::Result::ERROR_CERT_BAD_ACCESS_LOCATION; 482 } 483 return mozilla::pkix::Result::ERROR_OCSP_SERVER_ERROR; 484 } 485 return Success; 486 } 487 488 static char* ShowProtectedAuthPrompt(PK11SlotInfo* slot, nsIPrompt* prompt) { 489 MOZ_ASSERT(NS_IsMainThread()); 490 MOZ_ASSERT(slot); 491 MOZ_ASSERT(prompt); 492 if (!NS_IsMainThread() || !slot || !prompt) { 493 return nullptr; 494 } 495 496 // Dispatch a background task to (eventually) call C_Login. The call will 497 // block until the protected authentication succeeds or fails. 498 Atomic<bool> done; 499 Atomic<SECStatus> result; 500 nsresult rv = 501 NS_DispatchBackgroundTask(NS_NewRunnableFunction(__func__, [&]() mutable { 502 result = PK11_CheckUserPassword(slot, nullptr); 503 done = true; 504 })); 505 if (NS_FAILED(rv)) { 506 return nullptr; 507 } 508 509 nsTArray<nsCString> resIds = { 510 "security/pippki/pippki.ftl"_ns, 511 }; 512 RefPtr<mozilla::intl::Localization> l10n = 513 mozilla::intl::Localization::Create(resIds, true); 514 auto l10nId = "protected-auth-alert"_ns; 515 auto l10nArgs = mozilla::dom::Optional<intl::L10nArgs>(); 516 l10nArgs.Construct(); 517 auto dirArg = l10nArgs.Value().Entries().AppendElement(); 518 dirArg->mKey = "tokenName"_ns; 519 dirArg->mValue.SetValue().SetAsUTF8String().Assign(PK11_GetTokenName(slot)); 520 nsAutoCString promptString; 521 ErrorResult errorResult; 522 l10n->FormatValueSync(l10nId, l10nArgs, promptString, errorResult); 523 if (NS_FAILED(errorResult.StealNSResult())) { 524 return nullptr; 525 } 526 rv = prompt->Alert(nullptr, NS_ConvertUTF8toUTF16(promptString).get()); 527 if (NS_FAILED(rv)) { 528 return nullptr; 529 } 530 531 MOZ_ALWAYS_TRUE(SpinEventLoopUntil( 532 "ShowProtectedAuthPrompt"_ns, [&]() { return static_cast<bool>(done); })); 533 534 switch (result) { 535 case SECSuccess: 536 return ToNewCString(nsDependentCString(PK11_PW_AUTHENTICATED)); 537 case SECWouldBlock: 538 return ToNewCString(nsDependentCString(PK11_PW_RETRY)); 539 default: 540 return nullptr; 541 } 542 } 543 544 class PK11PasswordPromptRunnable : public SyncRunnableBase { 545 public: 546 PK11PasswordPromptRunnable(PK11SlotInfo* slot, nsIInterfaceRequestor* ir) 547 : mResult(nullptr), mSlot(slot), mIR(ir) {} 548 virtual ~PK11PasswordPromptRunnable() = default; 549 550 char* mResult; // out 551 virtual void RunOnTargetThread() override; 552 553 private: 554 static bool mRunning; 555 556 PK11SlotInfo* mSlot; 557 nsIInterfaceRequestor* mIR; 558 }; 559 560 bool PK11PasswordPromptRunnable::mRunning = false; 561 562 void PK11PasswordPromptRunnable::RunOnTargetThread() { 563 MOZ_ASSERT(NS_IsMainThread()); 564 if (!NS_IsMainThread()) { 565 return; 566 } 567 568 // If we've reentered due to the nested event loop implicit in using 569 // nsIPrompt synchronously (or indeed the explicit nested event loop in the 570 // protected authentication case), bail early, cancelling the password 571 // prompt. This will probably cause the operation that resulted in the prompt 572 // to fail, but this is better than littering the screen with a bunch of 573 // password prompts that the user will probably just cancel anyway. 574 if (mRunning) { 575 return; 576 } 577 mRunning = true; 578 auto setRunningToFalseOnExit = MakeScopeExit([&]() { mRunning = false; }); 579 580 nsresult rv; 581 nsCOMPtr<nsIPrompt> prompt; 582 if (!mIR) { 583 rv = nsNSSComponent::GetNewPrompter(getter_AddRefs(prompt)); 584 if (NS_FAILED(rv)) { 585 return; 586 } 587 } else { 588 prompt = do_GetInterface(mIR); 589 MOZ_ASSERT(prompt, "Interface requestor should implement nsIPrompt"); 590 } 591 592 if (!prompt) { 593 return; 594 } 595 596 if (PK11_ProtectedAuthenticationPath(mSlot)) { 597 mResult = ShowProtectedAuthPrompt(mSlot, prompt); 598 return; 599 } 600 601 nsAutoString promptString; 602 if (PK11_IsInternal(mSlot)) { 603 rv = GetPIPNSSBundleString("CertPasswordPromptDefault", promptString); 604 } else { 605 AutoTArray<nsString, 1> formatStrings = { 606 NS_ConvertUTF8toUTF16(PK11_GetTokenName(mSlot))}; 607 rv = PIPBundleFormatStringFromName("CertPasswordPrompt", formatStrings, 608 promptString); 609 } 610 if (NS_FAILED(rv)) { 611 return; 612 } 613 614 nsString password; 615 bool userClickedOK = false; 616 rv = prompt->PromptPassword(nullptr, promptString.get(), 617 getter_Copies(password), &userClickedOK); 618 if (NS_FAILED(rv) || !userClickedOK) { 619 return; 620 } 621 622 mResult = ToNewUTF8String(password); 623 } 624 625 char* PK11PasswordPrompt(PK11SlotInfo* slot, PRBool /*retry*/, void* arg) { 626 if (!slot) { 627 return nullptr; 628 } 629 RefPtr<PK11PasswordPromptRunnable> runnable(new PK11PasswordPromptRunnable( 630 slot, static_cast<nsIInterfaceRequestor*>(arg))); 631 runnable->DispatchToMainThreadAndWait(); 632 return runnable->mResult; 633 } 634 635 nsCString getKeaGroupName(uint32_t aKeaGroup) { 636 nsCString groupName; 637 switch (aKeaGroup) { 638 case ssl_grp_ec_secp256r1: 639 groupName = "P256"_ns; 640 break; 641 case ssl_grp_ec_secp384r1: 642 groupName = "P384"_ns; 643 break; 644 case ssl_grp_ec_secp521r1: 645 groupName = "P521"_ns; 646 break; 647 case ssl_grp_ec_curve25519: 648 groupName = "x25519"_ns; 649 break; 650 case ssl_grp_kem_xyber768d00: 651 groupName = "xyber768d00"_ns; 652 break; 653 case ssl_grp_kem_mlkem768x25519: 654 groupName = "mlkem768x25519"_ns; 655 break; 656 case ssl_grp_kem_secp256r1mlkem768: 657 groupName = "secp256r1mlkem768"_ns; 658 break; 659 case ssl_grp_kem_secp384r1mlkem1024: 660 groupName = "secp384r1mlkem1024"_ns; 661 break; 662 case ssl_grp_ffdhe_2048: 663 groupName = "FF 2048"_ns; 664 break; 665 case ssl_grp_ffdhe_3072: 666 groupName = "FF 3072"_ns; 667 break; 668 case ssl_grp_none: 669 groupName = "none"_ns; 670 break; 671 case ssl_grp_ffdhe_custom: 672 groupName = "custom"_ns; 673 break; 674 // All other groups are not enabled in Firefox. See namedGroups in 675 // nsNSSIOLayer.cpp. 676 default: 677 // This really shouldn't happen! 678 MOZ_ASSERT_UNREACHABLE("Invalid key exchange group."); 679 groupName = "unknown group"_ns; 680 } 681 return groupName; 682 } 683 684 nsCString getSignatureName(uint32_t aSignatureScheme) { 685 nsCString signatureName; 686 switch (aSignatureScheme) { 687 case ssl_sig_none: 688 signatureName = "none"_ns; 689 break; 690 case ssl_sig_rsa_pkcs1_sha1: 691 signatureName = "RSA-PKCS1-SHA1"_ns; 692 break; 693 case ssl_sig_rsa_pkcs1_sha256: 694 signatureName = "RSA-PKCS1-SHA256"_ns; 695 break; 696 case ssl_sig_rsa_pkcs1_sha384: 697 signatureName = "RSA-PKCS1-SHA384"_ns; 698 break; 699 case ssl_sig_rsa_pkcs1_sha512: 700 signatureName = "RSA-PKCS1-SHA512"_ns; 701 break; 702 case ssl_sig_ecdsa_secp256r1_sha256: 703 signatureName = "ECDSA-P256-SHA256"_ns; 704 break; 705 case ssl_sig_ecdsa_secp384r1_sha384: 706 signatureName = "ECDSA-P384-SHA384"_ns; 707 break; 708 case ssl_sig_ecdsa_secp521r1_sha512: 709 signatureName = "ECDSA-P521-SHA512"_ns; 710 break; 711 case ssl_sig_rsa_pss_sha256: 712 signatureName = "RSA-PSS-SHA256"_ns; 713 break; 714 case ssl_sig_rsa_pss_sha384: 715 signatureName = "RSA-PSS-SHA384"_ns; 716 break; 717 case ssl_sig_rsa_pss_sha512: 718 signatureName = "RSA-PSS-SHA512"_ns; 719 break; 720 case ssl_sig_ecdsa_sha1: 721 signatureName = "ECDSA-SHA1"_ns; 722 break; 723 case ssl_sig_rsa_pkcs1_sha1md5: 724 signatureName = "RSA-PKCS1-SHA1MD5"_ns; 725 break; 726 // All other groups are not enabled in Firefox. See sEnabledSignatureSchemes 727 // in nsNSSIOLayer.cpp. 728 default: 729 // This really shouldn't happen! 730 MOZ_ASSERT_UNREACHABLE("Invalid signature scheme."); 731 signatureName = "unknown signature"_ns; 732 } 733 return signatureName; 734 } 735 736 static void PreliminaryHandshakeDone(PRFileDesc* fd) { 737 NSSSocketControl* socketControl = (NSSSocketControl*)fd->higher->secret; 738 if (!socketControl) { 739 return; 740 } 741 if (socketControl->IsPreliminaryHandshakeDone()) { 742 return; 743 } 744 745 SSLChannelInfo channelInfo; 746 if (SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)) != SECSuccess) { 747 return; 748 } 749 SSLCipherSuiteInfo cipherInfo; 750 if (SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, 751 sizeof(cipherInfo)) != SECSuccess) { 752 return; 753 } 754 socketControl->SetPreliminaryHandshakeInfo(channelInfo, cipherInfo); 755 socketControl->SetSSLVersionUsed(channelInfo.protocolVersion); 756 socketControl->SetEarlyDataAccepted(channelInfo.earlyDataAccepted); 757 socketControl->SetKEAUsed(channelInfo.keaType); 758 socketControl->SetKEAKeyBits(channelInfo.keaKeyBits); 759 socketControl->SetMACAlgorithmUsed(cipherInfo.macAlgorithm); 760 761 // Get the NPN value. 762 SSLNextProtoState state; 763 unsigned char npnbuf[256]; 764 unsigned int npnlen; 765 766 if (SSL_GetNextProto(fd, &state, npnbuf, &npnlen, 767 AssertedCast<unsigned int>(std::size(npnbuf))) == 768 SECSuccess) { 769 if (state == SSL_NEXT_PROTO_NEGOTIATED || 770 state == SSL_NEXT_PROTO_SELECTED) { 771 socketControl->SetNegotiatedNPN( 772 BitwiseCast<char*, unsigned char*>(npnbuf), npnlen); 773 } else { 774 socketControl->SetNegotiatedNPN(nullptr, 0); 775 } 776 mozilla::glean::ssl::npn_type.AccumulateSingleSample(state); 777 } else { 778 socketControl->SetNegotiatedNPN(nullptr, 0); 779 } 780 781 socketControl->SetPreliminaryHandshakeDone(); 782 } 783 784 SECStatus CanFalseStartCallback(PRFileDesc* fd, void* client_data, 785 PRBool* canFalseStart) { 786 *canFalseStart = false; 787 788 NSSSocketControl* infoObject = (NSSSocketControl*)fd->higher->secret; 789 if (!infoObject) { 790 PR_SetError(PR_INVALID_STATE_ERROR, 0); 791 return SECFailure; 792 } 793 794 infoObject->SetFalseStartCallbackCalled(); 795 796 PreliminaryHandshakeDone(fd); 797 798 uint32_t reasonsForNotFalseStarting = 0; 799 800 SSLChannelInfo channelInfo; 801 if (SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)) != SECSuccess) { 802 return SECSuccess; 803 } 804 805 SSLCipherSuiteInfo cipherInfo; 806 if (SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, 807 sizeof(cipherInfo)) != SECSuccess) { 808 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 809 ("CanFalseStartCallback [%p] failed - " 810 " KEA %d\n", 811 fd, static_cast<int32_t>(channelInfo.keaType))); 812 return SECSuccess; 813 } 814 815 // Prevent version downgrade attacks from TLS 1.2, and avoid False Start for 816 // TLS 1.3 and later. See Bug 861310 for all the details as to why. 817 if (channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_2) { 818 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 819 ("CanFalseStartCallback [%p] failed - " 820 "SSL Version must be TLS 1.2, was %x\n", 821 fd, static_cast<int32_t>(channelInfo.protocolVersion))); 822 reasonsForNotFalseStarting |= POSSIBLE_VERSION_DOWNGRADE; 823 } 824 825 // See bug 952863 for why ECDHE is allowed, but DHE (and RSA) are not. 826 // Also note that ecdh_hybrid groups are not supported in TLS 1.2 and are out 827 // of scope. 828 if (channelInfo.keaType != ssl_kea_ecdh) { 829 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 830 ("CanFalseStartCallback [%p] failed - " 831 "unsupported KEA %d\n", 832 fd, static_cast<int32_t>(channelInfo.keaType))); 833 reasonsForNotFalseStarting |= KEA_NOT_SUPPORTED; 834 } 835 836 // Prevent downgrade attacks on the symmetric cipher. We do not allow CBC 837 // mode due to BEAST, POODLE, and other attacks on the MAC-then-Encrypt 838 // design. See bug 1109766 for more details. 839 if (cipherInfo.macAlgorithm != ssl_mac_aead) { 840 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 841 ("CanFalseStartCallback [%p] failed - non-AEAD cipher used, %d, " 842 "is not supported with False Start.\n", 843 fd, static_cast<int32_t>(cipherInfo.symCipher))); 844 reasonsForNotFalseStarting |= POSSIBLE_CIPHER_SUITE_DOWNGRADE; 845 } 846 847 // XXX: An attacker can choose which protocols are advertised in the 848 // NPN extension. TODO(Bug 861311): We should restrict the ability 849 // of an attacker leverage this capability by restricting false start 850 // to the same protocol we previously saw for the server, after the 851 // first successful connection to the server. 852 853 glean::ssl::reasons_for_not_false_starting.AccumulateSingleSample( 854 reasonsForNotFalseStarting); 855 856 if (reasonsForNotFalseStarting == 0) { 857 *canFalseStart = PR_TRUE; 858 infoObject->SetFalseStarted(); 859 infoObject->NoteTimeUntilReady(); 860 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 861 ("CanFalseStartCallback [%p] ok\n", fd)); 862 } 863 864 return SECSuccess; 865 } 866 867 static unsigned int NonECCKeySize(uint32_t bits) { 868 return bits < 512 ? 1 869 : bits == 512 ? 2 870 : bits < 768 ? 3 871 : bits == 768 ? 4 872 : bits < 1024 ? 5 873 : bits == 1024 ? 6 874 : bits < 1280 ? 7 875 : bits == 1280 ? 8 876 : bits < 1536 ? 9 877 : bits == 1536 ? 10 878 : bits < 2048 ? 11 879 : bits == 2048 ? 12 880 : bits < 3072 ? 13 881 : bits == 3072 ? 14 882 : bits < 4096 ? 15 883 : bits == 4096 ? 16 884 : bits < 8192 ? 17 885 : bits == 8192 ? 18 886 : bits < 16384 ? 19 887 : bits == 16384 ? 20 888 : 0; 889 } 890 891 // XXX: This attempts to map a bit count to an ECC named curve identifier. In 892 // the vast majority of situations, we only have the Suite B curves available. 893 // In that case, this mapping works fine. If we were to have more curves 894 // available, the mapping would be ambiguous since there could be multiple 895 // named curves for a given size (e.g. secp256k1 vs. secp256r1). We punt on 896 // that for now. See also NSS bug 323674. 897 static unsigned int ECCCurve(uint32_t bits) { 898 return bits == 255 ? 29 // Curve25519 899 : bits == 256 ? 23 // P-256 900 : bits == 384 ? 24 // P-384 901 : bits == 521 ? 25 // P-521 902 : 0; // Unknown 903 } 904 905 static void AccumulateCipherSuite(const SSLChannelInfo& channelInfo) { 906 uint32_t value; 907 // Note: this list must include every cipher suite it is possible to enable 908 // in nsNSSComponent.cpp (see sCipherPrefs and sDeprecatedTLS1CipherPrefs). 909 switch (channelInfo.cipherSuite) { 910 case TLS_RSA_WITH_3DES_EDE_CBC_SHA: // 0x000A 911 value = 1; 912 break; 913 case TLS_RSA_WITH_AES_128_CBC_SHA: // 0x002F 914 value = 2; 915 break; 916 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: // 0x0033 917 value = 3; 918 break; 919 case TLS_RSA_WITH_AES_256_CBC_SHA: // 0x0035 920 value = 4; 921 break; 922 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: // 0x0039 923 value = 5; 924 break; 925 case TLS_RSA_WITH_AES_128_GCM_SHA256: // 0x009C 926 value = 6; 927 break; 928 case TLS_RSA_WITH_AES_256_GCM_SHA384: // 0x009D 929 value = 7; 930 break; 931 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: // 0xC009 932 value = 8; 933 break; 934 case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: // 0xC00A 935 value = 9; 936 break; 937 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: // 0xC013 938 value = 10; 939 break; 940 case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: // 0xC014 941 value = 11; 942 break; 943 case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: // 0xC02B 944 value = 12; 945 break; 946 case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: // 0xC02C 947 value = 13; 948 break; 949 case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: // 0xC02F 950 value = 14; 951 break; 952 case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: // 0xC030 953 value = 15; 954 break; 955 case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: // 0xCCA8 956 value = 16; 957 break; 958 case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: // 0xCCA9 959 value = 17; 960 break; 961 962 // TLS 1.3 cipher suites 963 case TLS_AES_128_GCM_SHA256: // 0x1301 964 value = 18; 965 break; 966 case TLS_AES_256_GCM_SHA384: // 0x1302 967 value = 19; 968 break; 969 case TLS_CHACHA20_POLY1305_SHA256: // 0x1303 970 value = 20; 971 break; 972 973 // unknown 974 default: 975 value = 0; 976 break; 977 } 978 MOZ_ASSERT(value != 0); 979 glean::tls::cipher_suite.AccumulateSingleSample(value); 980 } 981 982 void HandshakeCallback(PRFileDesc* fd, void* client_data) { 983 // Do the bookkeeping that needs to be done after the 984 // server's ServerHello...ServerHelloDone have been processed, but that 985 // doesn't need the handshake to be completed. 986 PreliminaryHandshakeDone(fd); 987 988 NSSSocketControl* infoObject = (NSSSocketControl*)fd->higher->secret; 989 990 SSLVersionRange versions(infoObject->GetTLSVersionRange()); 991 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 992 ("[%p] HandshakeCallback: succeeded using TLS version range " 993 "(0x%04x,0x%04x)\n", 994 fd, static_cast<unsigned int>(versions.min), 995 static_cast<unsigned int>(versions.max))); 996 // If the handshake completed, then we know the site is TLS tolerant 997 infoObject->RememberTLSTolerant(); 998 999 SSLChannelInfo channelInfo; 1000 SECStatus rv = SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)); 1001 MOZ_ASSERT(rv == SECSuccess); 1002 if (rv != SECSuccess) { 1003 return; 1004 } 1005 AccumulateCipherSuite(channelInfo); 1006 1007 // Get the protocol version for telemetry 1008 // 1=tls1, 2=tls1.1, 3=tls1.2, 4=tls1.3 1009 unsigned int versionEnum = channelInfo.protocolVersion & 0xFF; 1010 MOZ_ASSERT(versionEnum > 0); 1011 glean::ssl_handshake::version.AccumulateSingleSample(versionEnum); 1012 1013 SSLCipherSuiteInfo cipherInfo; 1014 rv = SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, 1015 sizeof cipherInfo); 1016 MOZ_ASSERT(rv == SECSuccess); 1017 if (rv != SECSuccess) { 1018 return; 1019 } 1020 // keyExchange null=0, rsa=1, dh=2, fortezza=3, ecdh=4, ecdh_hybrid=8 1021 if (infoObject->IsFullHandshake()) { 1022 glean::ssl::key_exchange_algorithm_full.AccumulateSingleSample( 1023 channelInfo.keaType); 1024 } else { 1025 glean::ssl::key_exchange_algorithm_resumed.AccumulateSingleSample( 1026 channelInfo.keaType); 1027 } 1028 1029 if (infoObject->IsFullHandshake()) { 1030 switch (channelInfo.keaType) { 1031 case ssl_kea_rsa: 1032 glean::ssl::kea_rsa_key_size_full.AccumulateSingleSample( 1033 NonECCKeySize(channelInfo.keaKeyBits)); 1034 break; 1035 case ssl_kea_dh: 1036 glean::ssl::kea_dhe_key_size_full.AccumulateSingleSample( 1037 NonECCKeySize(channelInfo.keaKeyBits)); 1038 break; 1039 case ssl_kea_ecdh: 1040 glean::ssl::kea_ecdhe_curve_full.AccumulateSingleSample( 1041 ECCCurve(channelInfo.keaKeyBits)); 1042 break; 1043 case ssl_kea_ecdh_hybrid: 1044 break; 1045 default: 1046 MOZ_CRASH("impossible KEA"); 1047 break; 1048 } 1049 1050 glean::ssl::auth_algorithm_full.AccumulateSingleSample( 1051 channelInfo.authType); 1052 1053 // RSA key exchange doesn't use a signature for auth. 1054 if (channelInfo.keaType != ssl_kea_rsa) { 1055 switch (channelInfo.authType) { 1056 case ssl_auth_rsa: 1057 case ssl_auth_rsa_sign: 1058 glean::ssl::auth_rsa_key_size_full.AccumulateSingleSample( 1059 NonECCKeySize(channelInfo.authKeyBits)); 1060 break; 1061 case ssl_auth_ecdsa: 1062 glean::ssl::auth_ecdsa_curve_full.AccumulateSingleSample( 1063 ECCCurve(channelInfo.authKeyBits)); 1064 break; 1065 default: 1066 MOZ_CRASH("impossible auth algorithm"); 1067 break; 1068 } 1069 } 1070 } 1071 1072 PRBool siteSupportsSafeRenego; 1073 if (channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_3) { 1074 rv = SSL_HandshakeNegotiatedExtension(fd, ssl_renegotiation_info_xtn, 1075 &siteSupportsSafeRenego); 1076 MOZ_ASSERT(rv == SECSuccess); 1077 if (rv != SECSuccess) { 1078 siteSupportsSafeRenego = false; 1079 } 1080 } else { 1081 // TLS 1.3 dropped support for renegotiation. 1082 siteSupportsSafeRenego = true; 1083 } 1084 bool renegotiationUnsafe = 1085 !siteSupportsSafeRenego && 1086 StaticPrefs::security_ssl_treat_unsafe_negotiation_as_broken(); 1087 1088 bool deprecatedTlsVer = 1089 (channelInfo.protocolVersion < SSL_LIBRARY_VERSION_TLS_1_2); 1090 1091 uint32_t state; 1092 if (renegotiationUnsafe || deprecatedTlsVer) { 1093 state = nsIWebProgressListener::STATE_IS_BROKEN; 1094 } else { 1095 state = nsIWebProgressListener::STATE_IS_SECURE; 1096 SSLVersionRange defVersion; 1097 rv = SSL_VersionRangeGetDefault(ssl_variant_stream, &defVersion); 1098 if (rv == SECSuccess && versions.max >= defVersion.max) { 1099 // we know this site no longer requires a version fallback 1100 infoObject->RemoveInsecureTLSFallback(); 1101 } 1102 } 1103 1104 if (infoObject->HasServerCert()) { 1105 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 1106 ("HandshakeCallback KEEPING existing cert\n")); 1107 } else { 1108 infoObject->RebuildCertificateInfoFromSSLTokenCache(); 1109 } 1110 1111 // Check if the user has added an override for a certificate error. 1112 if (infoObject->HasUserOverriddenCertificateError()) { 1113 state |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN; 1114 } 1115 1116 infoObject->SetSecurityState(state); 1117 1118 // XXX Bug 883674: We shouldn't be formatting messages here in PSM; instead, 1119 // we should set a flag on the channel that higher (UI) level code can check 1120 // to log the warning. In particular, these warnings should go to the web 1121 // console instead of to the error console. Also, the warning is not 1122 // localized. 1123 if (!siteSupportsSafeRenego) { 1124 NS_ConvertASCIItoUTF16 msg(infoObject->GetHostName()); 1125 msg.AppendLiteral(" : server does not support RFC 5746, see CVE-2009-3555"); 1126 1127 nsContentUtils::LogSimpleConsoleError( 1128 msg, "SSL"_ns, infoObject->GetOriginAttributes().IsPrivateBrowsing(), 1129 true /* from chrome context */); 1130 } 1131 1132 infoObject->NoteTimeUntilReady(); 1133 infoObject->SetHandshakeCompleted(); 1134 } 1135 1136 void SecretCallback(PRFileDesc* fd, PRUint16 epoch, SSLSecretDirection dir, 1137 PK11SymKey* secret, void* arg) { 1138 // arg must be set to an NSSSocketControl* in SSL_SecretCallback 1139 MOZ_ASSERT(arg); 1140 NSSSocketControl* infoObject = (NSSSocketControl*)arg; 1141 if (epoch == 2 && dir == ssl_secret_read) { 1142 // |secret| is the server_handshake_traffic_secret. Set a flag to indicate 1143 // that the Server Hello has been processed successfully. We use this when 1144 // deciding whether to retry a connection in which an mlkem768x25519 share 1145 // was sent. 1146 infoObject->SetHasTls13HandshakeSecrets(); 1147 } 1148 }