nsNSSIOLayer.cpp (72211B)
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 "nsNSSIOLayer.h" 8 9 #include <algorithm> 10 #include <utility> 11 #include <vector> 12 13 #include "NSSCertDBTrustDomain.h" 14 #include "NSSErrorsService.h" 15 #include "NSSSocketControl.h" 16 #include "PSMRunnable.h" 17 #include "SSLServerCertVerification.h" 18 #include "ScopedNSSTypes.h" 19 #include "TLSClientAuthCertSelection.h" 20 #include "keyhi.h" 21 #include "mozilla/Base64.h" 22 #include "mozilla/Logging.h" 23 #include "mozilla/Preferences.h" 24 #include "mozilla/RandomNum.h" 25 #include "mozilla/ScopeExit.h" 26 #include "mozilla/StaticPrefs_security.h" 27 #include "mozilla/glean/SecurityManagerSslMetrics.h" 28 #include "mozilla/net/SSLTokensCache.h" 29 #include "mozilla/net/SocketProcessChild.h" 30 #include "mozilla/psm/IPCClientCertsChild.h" 31 #include "mozilla/psm/mozilla_abridged_certs_generated.h" 32 #include "mozilla/psm/PIPCClientCertsChild.h" 33 #include "mozpkix/pkixnss.h" 34 #include "mozpkix/pkixtypes.h" 35 #include "mozpkix/pkixutil.h" 36 #include "nsArray.h" 37 #include "nsArrayUtils.h" 38 #include "nsCRT.h" 39 #include "nsCharSeparatedTokenizer.h" 40 #include "nsClientAuthRemember.h" 41 #include "nsContentUtils.h" 42 #include "nsISocketProvider.h" 43 #include "nsIWebProgressListener.h" 44 #include "nsNSSComponent.h" 45 #include "nsNSSHelper.h" 46 #include "nsPrintfCString.h" 47 #include "nsServiceManagerUtils.h" 48 #include "prmem.h" 49 #include "prnetdb.h" 50 #include "secder.h" 51 #include "secerr.h" 52 #include "ssl.h" 53 #include "sslerr.h" 54 #include "sslexp.h" 55 #include "sslproto.h" 56 #include "zlib.h" 57 #include "brotli/decode.h" 58 #include "zstd/zstd.h" 59 60 #if defined(__arm__) 61 # include "mozilla/arm.h" 62 #endif 63 64 #ifdef MOZ_WIDGET_ANDROID 65 # include "mozilla/java/ClientAuthCertificateManagerWrappers.h" 66 #endif // MOZ_WIDGET_ANDROID 67 68 using namespace mozilla; 69 using namespace mozilla::psm; 70 using namespace mozilla::ipc; 71 72 // #define DEBUG_SSL_VERBOSE //Enable this define to get minimal 73 // reports when doing SSL read/write 74 75 // #define DUMP_BUFFER //Enable this define along with 76 // DEBUG_SSL_VERBOSE to dump SSL 77 // read/write buffer to a log. 78 // Uses PR_LOG except on Mac where 79 // we always write out to our own 80 // file. 81 82 namespace { 83 84 // The NSSSocketInfo tls flags are meant to be opaque to most calling 85 // applications but provide a mechanism for direct TLS manipulation when 86 // experimenting with new features in the scope of a single socket. They do not 87 // create a persistent ABI. 88 // 89 // Use of these flags creates a new 'sharedSSLState' so existing states for 90 // intolerance are not carried to sockets that use these flags (and intolerance 91 // they discover does not impact other normal sockets not using the flags.) 92 // 93 // Their current definitions are: 94 // 95 // bits 0-2 (mask 0x07) specify the max tls version 96 // 0 means no override 1->4 are 1.0, 1.1, 1.2, 1.3, 4->7 unused 97 // bits 3-5 (mask 0x38) specify the tls fallback limit 98 // 0 means no override, values 1->4 match prefs 99 // bit 6 (mask 0x40) was used to specify compat mode. Temporarily reserved. 100 101 enum { 102 kTLSProviderFlagMaxVersion10 = 0x01, 103 kTLSProviderFlagMaxVersion11 = 0x02, 104 kTLSProviderFlagMaxVersion12 = 0x03, 105 kTLSProviderFlagMaxVersion13 = 0x04, 106 }; 107 108 static uint32_t getTLSProviderFlagMaxVersion(uint32_t flags) { 109 return (flags & 0x07); 110 } 111 112 static uint32_t getTLSProviderFlagFallbackLimit(uint32_t flags) { 113 return (flags & 0x38) >> 3; 114 } 115 116 void getSiteKey(const nsACString& hostName, uint16_t port, 117 /*out*/ nsACString& key) { 118 key = hostName; 119 key.AppendLiteral(":"); 120 key.AppendInt(port); 121 } 122 123 } // unnamed namespace 124 125 extern LazyLogModule gPIPNSSLog; 126 127 namespace { 128 129 enum Operation { reading, writing, not_reading_or_writing }; 130 131 int32_t checkHandshake(int32_t bytesTransfered, bool wasReading, 132 PRFileDesc* ssl_layer_fd, NSSSocketControl* socketInfo); 133 134 NSSSocketControl* getSocketInfoIfRunning(PRFileDesc* fd, Operation op) { 135 if (!fd || !fd->lower || !fd->secret || 136 fd->identity != nsSSLIOLayerHelpers::nsSSLIOLayerIdentity) { 137 NS_ERROR("bad file descriptor passed to getSocketInfoIfRunning"); 138 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); 139 return nullptr; 140 } 141 142 NSSSocketControl* socketInfo = (NSSSocketControl*)fd->secret; 143 144 if (socketInfo->IsCanceled()) { 145 PRErrorCode err = socketInfo->GetErrorCode(); 146 PR_SetError(err, 0); 147 if (op == reading || op == writing) { 148 // We must do TLS intolerance checks for reads and writes, for timeouts 149 // in particular. 150 (void)checkHandshake(-1, op == reading, fd, socketInfo); 151 } 152 153 // If we get here, it is probably because cert verification failed and this 154 // is the first I/O attempt since that failure. 155 return nullptr; 156 } 157 158 return socketInfo; 159 } 160 161 } // namespace 162 163 static PRStatus nsSSLIOLayerConnect(PRFileDesc* fd, const PRNetAddr* addr, 164 PRIntervalTime timeout) { 165 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 166 ("[%p] connecting SSL socket\n", (void*)fd)); 167 if (!getSocketInfoIfRunning(fd, not_reading_or_writing)) return PR_FAILURE; 168 169 PRStatus status = fd->lower->methods->connect(fd->lower, addr, timeout); 170 if (status != PR_SUCCESS) { 171 MOZ_LOG(gPIPNSSLog, LogLevel::Error, 172 ("[%p] Lower layer connect error: %d\n", (void*)fd, PR_GetError())); 173 return status; 174 } 175 176 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("[%p] Connect\n", (void*)fd)); 177 return status; 178 } 179 180 void nsSSLIOLayerHelpers::rememberTolerantAtVersion(const nsACString& hostName, 181 uint16_t port, 182 uint16_t tolerant) { 183 nsCString key; 184 getSiteKey(hostName, port, key); 185 186 MutexAutoLock lock(mutex); 187 188 IntoleranceEntry entry; 189 if (mTLSIntoleranceInfo.Get(key, &entry)) { 190 entry.AssertInvariant(); 191 entry.tolerant = std::max(entry.tolerant, tolerant); 192 if (entry.intolerant != 0 && entry.intolerant <= entry.tolerant) { 193 entry.intolerant = entry.tolerant + 1; 194 entry.intoleranceReason = 0; // lose the reason 195 } 196 } else { 197 entry.tolerant = tolerant; 198 entry.intolerant = 0; 199 entry.intoleranceReason = 0; 200 } 201 202 entry.AssertInvariant(); 203 204 mTLSIntoleranceInfo.InsertOrUpdate(key, entry); 205 } 206 207 void nsSSLIOLayerHelpers::forgetIntolerance(const nsACString& hostName, 208 uint16_t port) { 209 nsCString key; 210 getSiteKey(hostName, port, key); 211 212 MutexAutoLock lock(mutex); 213 214 IntoleranceEntry entry; 215 if (mTLSIntoleranceInfo.Get(key, &entry)) { 216 entry.AssertInvariant(); 217 218 entry.intolerant = 0; 219 entry.intoleranceReason = 0; 220 221 entry.AssertInvariant(); 222 mTLSIntoleranceInfo.InsertOrUpdate(key, entry); 223 } 224 } 225 226 bool nsSSLIOLayerHelpers::fallbackLimitReached(const nsACString& hostName, 227 uint16_t intolerant) { 228 if (isInsecureFallbackSite(hostName)) { 229 return intolerant <= SSL_LIBRARY_VERSION_TLS_1_0; 230 } 231 return intolerant <= mVersionFallbackLimit; 232 } 233 234 // returns true if we should retry the handshake 235 bool nsSSLIOLayerHelpers::rememberIntolerantAtVersion( 236 const nsACString& hostName, uint16_t port, uint16_t minVersion, 237 uint16_t intolerant, PRErrorCode intoleranceReason) { 238 if (intolerant <= minVersion || fallbackLimitReached(hostName, intolerant)) { 239 // We can't fall back any further. Assume that intolerance isn't the issue. 240 forgetIntolerance(hostName, port); 241 return false; 242 } 243 244 nsCString key; 245 getSiteKey(hostName, port, key); 246 247 MutexAutoLock lock(mutex); 248 249 IntoleranceEntry entry; 250 if (mTLSIntoleranceInfo.Get(key, &entry)) { 251 entry.AssertInvariant(); 252 if (intolerant <= entry.tolerant) { 253 // We already know the server is tolerant at an equal or higher version. 254 return false; 255 } 256 if ((entry.intolerant != 0 && intolerant >= entry.intolerant)) { 257 // We already know that the server is intolerant at a lower version. 258 return true; 259 } 260 } else { 261 entry.tolerant = 0; 262 } 263 264 entry.intolerant = intolerant; 265 entry.intoleranceReason = intoleranceReason; 266 entry.AssertInvariant(); 267 mTLSIntoleranceInfo.InsertOrUpdate(key, entry); 268 269 return true; 270 } 271 272 void nsSSLIOLayerHelpers::adjustForTLSIntolerance( 273 const nsACString& hostName, uint16_t port, 274 /*in/out*/ SSLVersionRange& range) { 275 IntoleranceEntry entry; 276 277 { 278 nsCString key; 279 getSiteKey(hostName, port, key); 280 281 MutexAutoLock lock(mutex); 282 if (!mTLSIntoleranceInfo.Get(key, &entry)) { 283 return; 284 } 285 } 286 287 entry.AssertInvariant(); 288 289 if (entry.intolerant != 0) { 290 // We've tried connecting at a higher range but failed, so try at the 291 // version we haven't tried yet, unless we have reached the minimum. 292 if (range.min < entry.intolerant) { 293 range.max = entry.intolerant - 1; 294 } 295 } 296 } 297 298 PRErrorCode nsSSLIOLayerHelpers::getIntoleranceReason( 299 const nsACString& hostName, uint16_t port) { 300 IntoleranceEntry entry; 301 302 { 303 nsCString key; 304 getSiteKey(hostName, port, key); 305 306 MutexAutoLock lock(mutex); 307 if (!mTLSIntoleranceInfo.Get(key, &entry)) { 308 return 0; 309 } 310 } 311 312 entry.AssertInvariant(); 313 return entry.intoleranceReason; 314 } 315 316 bool nsSSLIOLayerHelpers::nsSSLIOLayerInitialized = false; 317 PRDescIdentity nsSSLIOLayerHelpers::nsSSLIOLayerIdentity; 318 PRDescIdentity nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity; 319 PRIOMethods nsSSLIOLayerHelpers::nsSSLIOLayerMethods; 320 PRIOMethods nsSSLIOLayerHelpers::nsSSLPlaintextLayerMethods; 321 322 static PRStatus nsSSLIOLayerClose(PRFileDesc* fd) { 323 if (!fd) { 324 return PR_FAILURE; 325 } 326 327 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("[%p] Shutting down socket", fd)); 328 329 // Take the owning reference from the layer. See the corresponding comment in 330 // nsSSLIOLayerAddToSocket where this gets set. 331 RefPtr<NSSSocketControl> socketInfo( 332 already_AddRefed((NSSSocketControl*)fd->secret)); 333 fd->secret = nullptr; 334 if (!socketInfo) { 335 return PR_FAILURE; 336 } 337 338 return socketInfo->CloseSocketAndDestroy(); 339 } 340 341 #if defined(DEBUG_SSL_VERBOSE) && defined(DUMP_BUFFER) 342 // Dumps a (potentially binary) buffer using SSM_DEBUG. (We could have used 343 // the version in ssltrace.c, but that's specifically tailored to SSLTRACE.) 344 # define DUMPBUF_LINESIZE 24 345 static void nsDumpBuffer(unsigned char* buf, int len) { 346 char hexbuf[DUMPBUF_LINESIZE * 3 + 1]; 347 char chrbuf[DUMPBUF_LINESIZE + 1]; 348 static const char* hex = "0123456789abcdef"; 349 int i = 0; 350 int l = 0; 351 char ch; 352 char* c; 353 char* h; 354 if (len == 0) return; 355 hexbuf[DUMPBUF_LINESIZE * 3] = '\0'; 356 chrbuf[DUMPBUF_LINESIZE] = '\0'; 357 (void)memset(hexbuf, 0x20, DUMPBUF_LINESIZE * 3); 358 (void)memset(chrbuf, 0x20, DUMPBUF_LINESIZE); 359 h = hexbuf; 360 c = chrbuf; 361 362 while (i < len) { 363 ch = buf[i]; 364 365 if (l == DUMPBUF_LINESIZE) { 366 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("%s%s\n", hexbuf, chrbuf)); 367 (void)memset(hexbuf, 0x20, DUMPBUF_LINESIZE * 3); 368 (void)memset(chrbuf, 0x20, DUMPBUF_LINESIZE); 369 h = hexbuf; 370 c = chrbuf; 371 l = 0; 372 } 373 374 // Convert a character to hex. 375 *h++ = hex[(ch >> 4) & 0xf]; 376 *h++ = hex[ch & 0xf]; 377 h++; 378 379 // Put the character (if it's printable) into the character buffer. 380 if ((ch >= 0x20) && (ch <= 0x7e)) { 381 *c++ = ch; 382 } else { 383 *c++ = '.'; 384 } 385 i++; 386 l++; 387 } 388 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("%s%s\n", hexbuf, chrbuf)); 389 } 390 391 # define DEBUG_DUMP_BUFFER(buf, len) nsDumpBuffer(buf, len) 392 #else 393 # define DEBUG_DUMP_BUFFER(buf, len) 394 #endif 395 396 namespace { 397 398 uint32_t tlsIntoleranceTelemetryBucket(PRErrorCode err) { 399 // returns a numeric code for where we track various errors in telemetry 400 // only errors that cause version fallback are tracked, 401 // so this is also used to determine which errors can cause version fallback 402 switch (err) { 403 case SSL_ERROR_BAD_MAC_ALERT: 404 return 1; 405 case SSL_ERROR_BAD_MAC_READ: 406 return 2; 407 case SSL_ERROR_HANDSHAKE_FAILURE_ALERT: 408 return 3; 409 case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT: 410 return 4; 411 case SSL_ERROR_ILLEGAL_PARAMETER_ALERT: 412 return 6; 413 case SSL_ERROR_NO_CYPHER_OVERLAP: 414 return 7; 415 case SSL_ERROR_UNSUPPORTED_VERSION: 416 return 10; 417 case SSL_ERROR_PROTOCOL_VERSION_ALERT: 418 return 11; 419 case SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE: 420 return 13; 421 case SSL_ERROR_DECODE_ERROR_ALERT: 422 return 14; 423 case PR_CONNECT_RESET_ERROR: 424 return 16; 425 case PR_END_OF_FILE_ERROR: 426 return 17; 427 case SSL_ERROR_INTERNAL_ERROR_ALERT: 428 return 18; 429 default: 430 return 0; 431 } 432 } 433 434 bool retryDueToTLSIntolerance(PRErrorCode err, NSSSocketControl* socketInfo) { 435 // This function is supposed to decide which error codes should 436 // be used to conclude server is TLS intolerant. 437 // Note this only happens during the initial SSL handshake. 438 439 if (StaticPrefs::security_tls_ech_disable_grease_on_fallback() && 440 socketInfo->GetEchExtensionStatus() == EchExtensionStatus::kGREASE) { 441 // Don't record any intolerances if we used ECH GREASE but force a retry. 442 return true; 443 } 444 445 if (!socketInfo->IsPreliminaryHandshakeDone() && 446 !socketInfo->HasTls13HandshakeSecrets() && socketInfo->SentMlkemShare()) { 447 nsAutoCString errorName; 448 const char* prErrorName = PR_ErrorToName(err); 449 if (prErrorName) { 450 errorName.AppendASCII(prErrorName); 451 } 452 mozilla::glean::tls::xyber_intolerance_reason.Get(errorName).Add(1); 453 // Don't record version intolerance if we sent mlkem768x25519, just force a 454 // retry. 455 return true; 456 } 457 458 SSLVersionRange range = socketInfo->GetTLSVersionRange(); 459 460 if (err == SSL_ERROR_UNSUPPORTED_VERSION && 461 range.min == SSL_LIBRARY_VERSION_TLS_1_0) { 462 socketInfo->SetSecurityState(nsIWebProgressListener::STATE_IS_INSECURE | 463 nsIWebProgressListener::STATE_USES_SSL_3); 464 } 465 466 // NSS will return SSL_ERROR_RX_MALFORMED_SERVER_HELLO if anti-downgrade 467 // detected the downgrade. 468 if (err == SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT || 469 err == SSL_ERROR_RX_MALFORMED_SERVER_HELLO) { 470 // This is a clear signal that we've fallen back too many versions. Treat 471 // this as a hard failure, but forget any intolerance so that later attempts 472 // don't use this version (i.e., range.max) and trigger the error again. 473 474 // First, track the original cause of the version fallback. This uses the 475 // same buckets as the telemetry below, except that bucket 0 will include 476 // all cases where there wasn't an original reason. 477 PRErrorCode originalReason = socketInfo->GetTLSIntoleranceReason(); 478 glean::ssl::version_fallback_inappropriate.AccumulateSingleSample( 479 tlsIntoleranceTelemetryBucket(originalReason)); 480 481 socketInfo->ForgetTLSIntolerance(); 482 483 return false; 484 } 485 486 // When not using a proxy we'll see a connection reset error. 487 // When using a proxy, we'll see an end of file error. 488 489 // Don't allow STARTTLS connections to fall back on connection resets or 490 // EOF. 491 if ((err == PR_CONNECT_RESET_ERROR || err == PR_END_OF_FILE_ERROR) && 492 socketInfo->GetForSTARTTLS()) { 493 return false; 494 } 495 496 uint32_t reason = tlsIntoleranceTelemetryBucket(err); 497 if (reason == 0) { 498 return false; 499 } 500 501 // The difference between _PRE and _POST represents how often we avoided 502 // TLS intolerance fallback due to remembered tolerance. 503 504 switch (range.max) { 505 case SSL_LIBRARY_VERSION_TLS_1_3: 506 glean::ssl::tls13_intolerance_reason_pre.AccumulateSingleSample(reason); 507 break; 508 case SSL_LIBRARY_VERSION_TLS_1_2: 509 glean::ssl::tls12_intolerance_reason_pre.AccumulateSingleSample(reason); 510 break; 511 case SSL_LIBRARY_VERSION_TLS_1_1: 512 glean::ssl::tls11_intolerance_reason_pre.AccumulateSingleSample(reason); 513 break; 514 case SSL_LIBRARY_VERSION_TLS_1_0: 515 glean::ssl::tls10_intolerance_reason_pre.AccumulateSingleSample(reason); 516 break; 517 default: 518 MOZ_CRASH("impossible TLS version"); 519 return false; 520 } 521 522 if (!socketInfo->RememberTLSIntolerant(err)) { 523 return false; 524 } 525 526 switch (range.max) { 527 case SSL_LIBRARY_VERSION_TLS_1_3: 528 glean::ssl::tls13_intolerance_reason_post.AccumulateSingleSample(reason); 529 break; 530 case SSL_LIBRARY_VERSION_TLS_1_2: 531 glean::ssl::tls12_intolerance_reason_post.AccumulateSingleSample(reason); 532 break; 533 case SSL_LIBRARY_VERSION_TLS_1_1: 534 glean::ssl::tls11_intolerance_reason_post.AccumulateSingleSample(reason); 535 break; 536 case SSL_LIBRARY_VERSION_TLS_1_0: 537 glean::ssl::tls10_intolerance_reason_post.AccumulateSingleSample(reason); 538 break; 539 default: 540 MOZ_CRASH("impossible TLS version"); 541 return false; 542 } 543 544 return true; 545 } 546 547 // Ensure that we haven't added too many errors to fit. 548 static_assert((SSL_ERROR_END_OF_LIST - SSL_ERROR_BASE) <= 256, 549 "too many SSL errors"); 550 static_assert((SEC_ERROR_END_OF_LIST - SEC_ERROR_BASE) <= 256, 551 "too many SEC errors"); 552 static_assert((PR_MAX_ERROR - PR_NSPR_ERROR_BASE) <= 128, 553 "too many NSPR errors"); 554 static_assert((mozilla::pkix::ERROR_BASE - mozilla::pkix::END_OF_LIST) < 31, 555 "too many moz::pkix errors"); 556 557 static void reportHandshakeResult(int32_t bytesTransferred, bool wasReading, 558 PRErrorCode err, 559 NSSSocketControl* socketInfo) { 560 uint32_t bucket; 561 562 // A negative bytesTransferred or a 0 read are errors. 563 if (bytesTransferred > 0) { 564 bucket = 0; 565 } else if ((bytesTransferred == 0) && !wasReading) { 566 // PR_Write() is defined to never return 0, but let's make sure. 567 // https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR/Reference/PR_Write. 568 MOZ_ASSERT(false); 569 bucket = 671; 570 } else if (IS_SSL_ERROR(err)) { 571 bucket = err - SSL_ERROR_BASE; 572 MOZ_ASSERT(bucket > 0); // SSL_ERROR_EXPORT_ONLY_SERVER isn't used. 573 } else if (IS_SEC_ERROR(err)) { 574 bucket = (err - SEC_ERROR_BASE) + 256; 575 } else if ((err >= PR_NSPR_ERROR_BASE) && (err < PR_MAX_ERROR)) { 576 bucket = (err - PR_NSPR_ERROR_BASE) + 512; 577 } else if ((err >= mozilla::pkix::ERROR_BASE) && 578 (err < mozilla::pkix::ERROR_LIMIT)) { 579 bucket = (err - mozilla::pkix::ERROR_BASE) + 640; 580 } else { 581 bucket = 671; 582 } 583 584 uint32_t flags = socketInfo->GetProviderFlags(); 585 if (!(flags & nsISocketProvider::IS_RETRY)) { 586 glean::ssl_handshake::result_first_try.AccumulateSingleSample(bucket); 587 } 588 589 if (flags & nsISocketProvider::BE_CONSERVATIVE) { 590 glean::ssl_handshake::result_conservative.AccumulateSingleSample(bucket); 591 } 592 593 switch (socketInfo->GetEchExtensionStatus()) { 594 case EchExtensionStatus::kGREASE: 595 glean::ssl_handshake::result_ech_grease.AccumulateSingleSample(bucket); 596 break; 597 case EchExtensionStatus::kReal: 598 glean::ssl_handshake::result_ech.AccumulateSingleSample(bucket); 599 break; 600 default: 601 break; 602 } 603 glean::ssl_handshake::result.AccumulateSingleSample(bucket); 604 605 if (bucket == 0) { 606 nsCOMPtr<nsITransportSecurityInfo> securityInfo; 607 if (NS_FAILED(socketInfo->GetSecurityInfo(getter_AddRefs(securityInfo))) || 608 !securityInfo) { 609 return; 610 } 611 // Web Privacy Telemetry for successful connections. 612 bool success = true; 613 614 bool usedPrivateDNS = false; 615 success &= securityInfo->GetUsedPrivateDNS(&usedPrivateDNS) == NS_OK; 616 617 bool madeOCSPRequest = false; 618 success &= securityInfo->GetMadeOCSPRequests(&madeOCSPRequest) == NS_OK; 619 620 uint16_t protocolVersion = 0; 621 success &= securityInfo->GetProtocolVersion(&protocolVersion) == NS_OK; 622 bool usedTLS13 = protocolVersion == 4; 623 624 bool usedECH = false; 625 success &= securityInfo->GetIsAcceptedEch(&usedECH) == NS_OK; 626 627 // As bucket is 0 we are reporting the results of a sucessful connection 628 // and so TransportSecurityInfo should be populated. However, this isn't 629 // happening in all cases, see Bug 1789458. 630 if (success) { 631 uint8_t TLSPrivacyResult = 0; 632 TLSPrivacyResult |= usedTLS13 << 0; 633 TLSPrivacyResult |= !madeOCSPRequest << 1; 634 TLSPrivacyResult |= usedPrivateDNS << 2; 635 TLSPrivacyResult |= usedECH << 3; 636 637 glean::ssl_handshake::privacy.AccumulateSingleSample(TLSPrivacyResult); 638 } 639 } 640 } 641 642 // Check the status of the handshake. This is where PSM checks for TLS 643 // intolerance and potentially sets up TLS intolerance fallback by noting the 644 // intolerance, setting the NSPR error to PR_CONNECT_RESET_ERROR, and returning 645 // -1 as the bytes transferred so that necko retries the connection. 646 // Otherwise, PSM returns the bytes transferred unchanged. 647 int32_t checkHandshake(int32_t bytesTransferred, bool wasReading, 648 PRFileDesc* ssl_layer_fd, NSSSocketControl* socketInfo) { 649 const PRErrorCode originalError = PR_GetError(); 650 651 // If the connection would block, return early. 652 if (bytesTransferred < 0 && originalError == PR_WOULD_BLOCK_ERROR) { 653 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); 654 return bytesTransferred; 655 } 656 657 // We only need to do TLS intolerance checking for the first transfer. 658 bool handleHandshakeResultNow = socketInfo->IsHandshakePending(); 659 if (!handleHandshakeResultNow) { 660 // If we've encountered an error since the handshake, ensure the socket 661 // control is cancelled, so that getSocketInfoIfRunning will correctly 662 // cause us to fail if another part of Gecko (erroneously) calls an I/O 663 // function (PR_Send/PR_Recv/etc.) again on this socket. 664 if (bytesTransferred < 0) { 665 if (!socketInfo->IsCanceled()) { 666 socketInfo->SetCanceled(originalError); 667 } 668 PR_SetError(originalError, 0); 669 } 670 return bytesTransferred; 671 } 672 673 // TLS intolerant servers only cause the first transfer to fail, so let's 674 // set the HandshakePending attribute to false so that we don't try this logic 675 // again in a subsequent transfer. 676 socketInfo->SetHandshakeNotPending(); 677 // Report the result once for each handshake. Note that this does not 678 // get handshakes which are cancelled before any reads or writes 679 // happen. 680 reportHandshakeResult(bytesTransferred, wasReading, originalError, 681 socketInfo); 682 683 // If there was no error, return early. The case where we read 0 bytes is not 684 // considered an error by NSS, but PSM interprets this as TLS intolerance, so 685 // we turn it into an error. Writes of 0 bytes are an error, because PR_Write 686 // is never supposed to return 0. 687 if (bytesTransferred > 0) { 688 return bytesTransferred; 689 } 690 691 // There was some sort of error. Determine what it was and if we want to 692 // retry the connection due to TLS intolerance. 693 PRErrorCode errorToUse = originalError; 694 // Turn zero-length reads into errors and handle zero-length write errors. 695 if (bytesTransferred == 0) { 696 if (wasReading) { 697 errorToUse = PR_END_OF_FILE_ERROR; 698 } else { 699 errorToUse = SEC_ERROR_LIBRARY_FAILURE; 700 } 701 bytesTransferred = -1; 702 } 703 bool wantRetry = retryDueToTLSIntolerance(errorToUse, socketInfo); 704 // Set the error on the socket control and cancel it. 705 if (!socketInfo->IsCanceled()) { 706 socketInfo->SetCanceled(errorToUse); 707 } 708 709 if (wantRetry) { 710 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 711 ("[%p] checkHandshake: will retry with lower max TLS version", 712 ssl_layer_fd)); 713 // Setting the error PR_CONNECT_RESET_ERROR causes necko to retry the 714 // connection. 715 PR_SetError(PR_CONNECT_RESET_ERROR, 0); 716 } else { 717 PR_SetError(originalError, 0); 718 } 719 720 return bytesTransferred; 721 } 722 723 } // namespace 724 725 static int16_t nsSSLIOLayerPoll(PRFileDesc* fd, int16_t in_flags, 726 int16_t* out_flags) { 727 if (!out_flags) { 728 NS_WARNING("nsSSLIOLayerPoll called with null out_flags"); 729 return 0; 730 } 731 732 *out_flags = 0; 733 734 NSSSocketControl* socketInfo = 735 getSocketInfoIfRunning(fd, not_reading_or_writing); 736 737 if (!socketInfo) { 738 // If we get here, it is probably because certificate validation failed 739 // and this is the first I/O operation after the failure. 740 MOZ_LOG( 741 gPIPNSSLog, LogLevel::Debug, 742 ("[%p] polling SSL socket right after certificate verification failed " 743 "or NSS shutdown or SDR logout %d\n", 744 fd, (int)in_flags)); 745 746 MOZ_ASSERT(in_flags & PR_POLL_EXCEPT, 747 "Caller did not poll for EXCEPT (canceled)"); 748 // Since this poll method cannot return errors, we want the caller to call 749 // PR_Send/PR_Recv right away to get the error, so we tell that we are 750 // ready for whatever I/O they are asking for. (See getSocketInfoIfRunning). 751 *out_flags = in_flags | PR_POLL_EXCEPT; // see also bug 480619 752 return in_flags; 753 } 754 755 MOZ_LOG(gPIPNSSLog, LogLevel::Verbose, 756 (socketInfo->IsWaitingForCertVerification() 757 ? "[%p] polling SSL socket during certificate verification " 758 "using lower %d\n" 759 : "[%p] poll SSL socket using lower %d\n", 760 fd, (int)in_flags)); 761 762 socketInfo->MaybeSelectClientAuthCertificate(); 763 764 // We want the handshake to continue during certificate validation, so we 765 // don't need to do anything special here. libssl automatically blocks when 766 // it reaches any point that would be unsafe to send/receive something before 767 // cert validation is complete. 768 int16_t result = fd->lower->methods->poll(fd->lower, in_flags, out_flags); 769 MOZ_LOG(gPIPNSSLog, LogLevel::Verbose, 770 ("[%p] poll SSL socket returned %d\n", (void*)fd, (int)result)); 771 return result; 772 } 773 774 nsSSLIOLayerHelpers::nsSSLIOLayerHelpers(PublicOrPrivate aPublicOrPrivate, 775 uint32_t aTlsFlags) 776 : mVersionFallbackLimit(SSL_LIBRARY_VERSION_TLS_1_0), 777 mPublicOrPrivate(aPublicOrPrivate), 778 mutex("nsSSLIOLayerHelpers.mutex"), 779 mTlsFlags(aTlsFlags) {} 780 781 // PSMAvailable and PSMAvailable64 are reachable, but they're unimplemented in 782 // PSM, so we set an error and return -1. 783 static int32_t PSMAvailable(PRFileDesc*) { 784 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 785 return -1; 786 } 787 788 static int64_t PSMAvailable64(PRFileDesc*) { 789 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 790 return -1; 791 } 792 793 static PRStatus PSMGetsockname(PRFileDesc* fd, PRNetAddr* addr) { 794 if (!getSocketInfoIfRunning(fd, not_reading_or_writing)) return PR_FAILURE; 795 796 return fd->lower->methods->getsockname(fd->lower, addr); 797 } 798 799 static PRStatus PSMGetpeername(PRFileDesc* fd, PRNetAddr* addr) { 800 if (!getSocketInfoIfRunning(fd, not_reading_or_writing)) return PR_FAILURE; 801 802 return fd->lower->methods->getpeername(fd->lower, addr); 803 } 804 805 static PRStatus PSMGetsocketoption(PRFileDesc* fd, PRSocketOptionData* data) { 806 if (!getSocketInfoIfRunning(fd, not_reading_or_writing)) return PR_FAILURE; 807 808 return fd->lower->methods->getsocketoption(fd, data); 809 } 810 811 static PRStatus PSMSetsocketoption(PRFileDesc* fd, 812 const PRSocketOptionData* data) { 813 if (!getSocketInfoIfRunning(fd, not_reading_or_writing)) return PR_FAILURE; 814 815 return fd->lower->methods->setsocketoption(fd, data); 816 } 817 818 static int32_t PSMRecv(PRFileDesc* fd, void* buf, int32_t amount, int flags, 819 PRIntervalTime timeout) { 820 NSSSocketControl* socketInfo = getSocketInfoIfRunning(fd, reading); 821 if (!socketInfo) return -1; 822 823 if (flags != PR_MSG_PEEK && flags != 0) { 824 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 825 return -1; 826 } 827 828 int32_t bytesRead = 829 fd->lower->methods->recv(fd->lower, buf, amount, flags, timeout); 830 831 MOZ_LOG(gPIPNSSLog, LogLevel::Verbose, 832 ("[%p] read %d bytes\n", (void*)fd, bytesRead)); 833 834 #ifdef DEBUG_SSL_VERBOSE 835 DEBUG_DUMP_BUFFER((unsigned char*)buf, bytesRead); 836 #endif 837 838 return checkHandshake(bytesRead, true, fd, socketInfo); 839 } 840 841 static int32_t PSMSend(PRFileDesc* fd, const void* buf, int32_t amount, 842 int flags, PRIntervalTime timeout) { 843 NSSSocketControl* socketInfo = getSocketInfoIfRunning(fd, writing); 844 if (!socketInfo) return -1; 845 846 if (flags != 0) { 847 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 848 return -1; 849 } 850 851 #ifdef DEBUG_SSL_VERBOSE 852 DEBUG_DUMP_BUFFER((unsigned char*)buf, amount); 853 #endif 854 855 if (socketInfo->IsShortWritePending() && amount > 0) { 856 // We got "SSL short write" last time, try to flush the pending byte. 857 #ifdef DEBUG 858 socketInfo->CheckShortWrittenBuffer(static_cast<const unsigned char*>(buf), 859 amount); 860 #endif 861 862 buf = socketInfo->GetShortWritePendingByteRef(); 863 amount = 1; 864 865 MOZ_LOG(gPIPNSSLog, LogLevel::Verbose, 866 ("[%p] pushing 1 byte after SSL short write", fd)); 867 } 868 869 int32_t bytesWritten = 870 fd->lower->methods->send(fd->lower, buf, amount, flags, timeout); 871 872 // NSS indicates that it can't write all requested data (due to network 873 // congestion, for example) by returning either one less than the amount 874 // of data requested or 16383, if the requested amount is greater than 875 // 16384. We refer to this as a "short write". If we simply returned 876 // the amount that NSS did write, the layer above us would then call 877 // PSMSend with a very small amount of data (often 1). This is inefficient 878 // and can lead to alternating between sending large packets and very small 879 // packets. To prevent this, we alert the layer calling us that the operation 880 // would block and that it should be retried later, with the same data. 881 // When it does, we tell NSS to write the remaining byte it didn't write 882 // in the previous call. We then return the total number of bytes written, 883 // which is the number that caused the short write plus the additional byte 884 // we just wrote out. 885 886 // The 16384 value is based on libssl's maximum buffer size: 887 // MAX_FRAGMENT_LENGTH - 1 888 // 889 // It's in a private header, though, filed bug 1394822 to expose it. 890 static const int32_t kShortWrite16k = 16383; 891 892 if ((amount > 1 && bytesWritten == (amount - 1)) || 893 (amount > kShortWrite16k && bytesWritten == kShortWrite16k)) { 894 // This is indication of an "SSL short write", block to force retry. 895 socketInfo->SetShortWritePending( 896 bytesWritten + 1, // The amount to return after the flush 897 *(static_cast<const unsigned char*>(buf) + bytesWritten)); 898 899 MOZ_LOG( 900 gPIPNSSLog, LogLevel::Verbose, 901 ("[%p] indicated SSL short write for %d bytes (written just %d bytes)", 902 fd, amount, bytesWritten)); 903 904 bytesWritten = -1; 905 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); 906 907 #ifdef DEBUG 908 socketInfo->RememberShortWrittenBuffer( 909 static_cast<const unsigned char*>(buf)); 910 #endif 911 912 } else if (socketInfo->IsShortWritePending() && bytesWritten == 1) { 913 // We have now flushed all pending data in the SSL socket 914 // after the indicated short write. Tell the upper layer 915 // it has sent all its data now. 916 MOZ_LOG(gPIPNSSLog, LogLevel::Verbose, 917 ("[%p] finished SSL short write", fd)); 918 919 bytesWritten = socketInfo->ResetShortWritePending(); 920 } 921 922 MOZ_LOG(gPIPNSSLog, LogLevel::Verbose, 923 ("[%p] wrote %d bytes\n", fd, bytesWritten)); 924 925 return checkHandshake(bytesWritten, false, fd, socketInfo); 926 } 927 928 static PRStatus PSMBind(PRFileDesc* fd, const PRNetAddr* addr) { 929 if (!getSocketInfoIfRunning(fd, not_reading_or_writing)) return PR_FAILURE; 930 931 return fd->lower->methods->bind(fd->lower, addr); 932 } 933 934 static int32_t nsSSLIOLayerRead(PRFileDesc* fd, void* buf, int32_t amount) { 935 return PSMRecv(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT); 936 } 937 938 static int32_t nsSSLIOLayerWrite(PRFileDesc* fd, const void* buf, 939 int32_t amount) { 940 return PSMSend(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT); 941 } 942 943 static PRStatus PSMConnectcontinue(PRFileDesc* fd, int16_t out_flags) { 944 if (!getSocketInfoIfRunning(fd, not_reading_or_writing)) { 945 return PR_FAILURE; 946 } 947 948 return fd->lower->methods->connectcontinue(fd, out_flags); 949 } 950 951 NS_IMPL_ISUPPORTS(nsSSLIOLayerHelpers, nsIObserver) 952 953 NS_IMETHODIMP 954 nsSSLIOLayerHelpers::Observe(nsISupports* aSubject, const char* aTopic, 955 const char16_t* someData) { 956 if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) { 957 NS_ConvertUTF16toUTF8 prefName(someData); 958 959 if (prefName.EqualsLiteral("security.tls.version.fallback-limit")) { 960 loadVersionFallbackLimit(); 961 } else if (prefName.EqualsLiteral("security.tls.insecure_fallback_hosts")) { 962 initInsecureFallbackSites(); 963 } 964 } else if (nsCRT::strcmp(aTopic, "last-pb-context-exited") == 0) { 965 clearStoredData(); 966 } 967 return NS_OK; 968 } 969 970 void nsSSLIOLayerHelpers::GlobalInit() { 971 MOZ_ASSERT(NS_IsMainThread(), "Not on main thread"); 972 gPublicSSLIOLayerHelpers = new nsSSLIOLayerHelpers(PublicOrPrivate::Public); 973 gPublicSSLIOLayerHelpers->Init(); 974 gPrivateSSLIOLayerHelpers = new nsSSLIOLayerHelpers(PublicOrPrivate::Private); 975 gPrivateSSLIOLayerHelpers->Init(); 976 } 977 978 /*static*/ 979 void nsSSLIOLayerHelpers::GlobalCleanup() { 980 MOZ_ASSERT(NS_IsMainThread(), "Not on main thread"); 981 982 if (gPrivateSSLIOLayerHelpers) { 983 gPrivateSSLIOLayerHelpers = nullptr; 984 } 985 986 if (gPublicSSLIOLayerHelpers) { 987 gPublicSSLIOLayerHelpers = nullptr; 988 } 989 } 990 991 already_AddRefed<nsSSLIOLayerHelpers> PublicSSLIOLayerHelpers() { 992 return do_AddRef(gPublicSSLIOLayerHelpers); 993 } 994 995 already_AddRefed<nsSSLIOLayerHelpers> PrivateSSLIOLayerHelpers() { 996 return do_AddRef(gPrivateSSLIOLayerHelpers); 997 } 998 999 static int32_t PlaintextRecv(PRFileDesc* fd, void* buf, int32_t amount, 1000 int flags, PRIntervalTime timeout) { 1001 NSSSocketControl* socketInfo = nullptr; 1002 1003 int32_t bytesRead = 1004 fd->lower->methods->recv(fd->lower, buf, amount, flags, timeout); 1005 if (fd->identity == nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity) { 1006 socketInfo = (NSSSocketControl*)fd->secret; 1007 } 1008 1009 if ((bytesRead > 0) && socketInfo) { 1010 socketInfo->AddPlaintextBytesRead(bytesRead); 1011 } 1012 return bytesRead; 1013 } 1014 1015 nsSSLIOLayerHelpers::~nsSSLIOLayerHelpers() { 1016 Preferences::RemoveObserver(this, "security.tls.version.fallback-limit"); 1017 Preferences::RemoveObserver(this, "security.tls.insecure_fallback_hosts"); 1018 } 1019 1020 template <typename R, R return_value, typename... Args> 1021 static R InvalidPRIOMethod(Args...) { 1022 MOZ_ASSERT_UNREACHABLE("I/O method is invalid"); 1023 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 1024 return return_value; 1025 } 1026 1027 nsresult nsSSLIOLayerHelpers::Init() { 1028 if (!nsSSLIOLayerInitialized) { 1029 MOZ_ASSERT(NS_IsMainThread()); 1030 nsSSLIOLayerInitialized = true; 1031 nsSSLIOLayerIdentity = PR_GetUniqueIdentity("NSS layer"); 1032 nsSSLIOLayerMethods = *PR_GetDefaultIOMethods(); 1033 1034 nsSSLIOLayerMethods.fsync = 1035 InvalidPRIOMethod<PRStatus, PR_FAILURE, PRFileDesc*>; 1036 nsSSLIOLayerMethods.seek = 1037 InvalidPRIOMethod<int32_t, -1, PRFileDesc*, int32_t, PRSeekWhence>; 1038 nsSSLIOLayerMethods.seek64 = 1039 InvalidPRIOMethod<int64_t, -1, PRFileDesc*, int64_t, PRSeekWhence>; 1040 nsSSLIOLayerMethods.fileInfo = 1041 InvalidPRIOMethod<PRStatus, PR_FAILURE, PRFileDesc*, PRFileInfo*>; 1042 nsSSLIOLayerMethods.fileInfo64 = 1043 InvalidPRIOMethod<PRStatus, PR_FAILURE, PRFileDesc*, PRFileInfo64*>; 1044 nsSSLIOLayerMethods.writev = 1045 InvalidPRIOMethod<int32_t, -1, PRFileDesc*, const PRIOVec*, int32_t, 1046 PRIntervalTime>; 1047 nsSSLIOLayerMethods.accept = 1048 InvalidPRIOMethod<PRFileDesc*, nullptr, PRFileDesc*, PRNetAddr*, 1049 PRIntervalTime>; 1050 nsSSLIOLayerMethods.listen = 1051 InvalidPRIOMethod<PRStatus, PR_FAILURE, PRFileDesc*, int>; 1052 nsSSLIOLayerMethods.shutdown = 1053 InvalidPRIOMethod<PRStatus, PR_FAILURE, PRFileDesc*, int>; 1054 nsSSLIOLayerMethods.recvfrom = 1055 InvalidPRIOMethod<int32_t, -1, PRFileDesc*, void*, int32_t, int, 1056 PRNetAddr*, PRIntervalTime>; 1057 nsSSLIOLayerMethods.sendto = 1058 InvalidPRIOMethod<int32_t, -1, PRFileDesc*, const void*, int32_t, int, 1059 const PRNetAddr*, PRIntervalTime>; 1060 nsSSLIOLayerMethods.acceptread = 1061 InvalidPRIOMethod<int32_t, -1, PRFileDesc*, PRFileDesc**, PRNetAddr**, 1062 void*, int32_t, PRIntervalTime>; 1063 nsSSLIOLayerMethods.transmitfile = 1064 InvalidPRIOMethod<int32_t, -1, PRFileDesc*, PRFileDesc*, const void*, 1065 int32_t, PRTransmitFileFlags, PRIntervalTime>; 1066 nsSSLIOLayerMethods.sendfile = 1067 InvalidPRIOMethod<int32_t, -1, PRFileDesc*, PRSendFileData*, 1068 PRTransmitFileFlags, PRIntervalTime>; 1069 1070 nsSSLIOLayerMethods.available = PSMAvailable; 1071 nsSSLIOLayerMethods.available64 = PSMAvailable64; 1072 nsSSLIOLayerMethods.getsockname = PSMGetsockname; 1073 nsSSLIOLayerMethods.getpeername = PSMGetpeername; 1074 nsSSLIOLayerMethods.getsocketoption = PSMGetsocketoption; 1075 nsSSLIOLayerMethods.setsocketoption = PSMSetsocketoption; 1076 nsSSLIOLayerMethods.recv = PSMRecv; 1077 nsSSLIOLayerMethods.send = PSMSend; 1078 nsSSLIOLayerMethods.connectcontinue = PSMConnectcontinue; 1079 nsSSLIOLayerMethods.bind = PSMBind; 1080 1081 nsSSLIOLayerMethods.connect = nsSSLIOLayerConnect; 1082 nsSSLIOLayerMethods.close = nsSSLIOLayerClose; 1083 nsSSLIOLayerMethods.write = nsSSLIOLayerWrite; 1084 nsSSLIOLayerMethods.read = nsSSLIOLayerRead; 1085 nsSSLIOLayerMethods.poll = nsSSLIOLayerPoll; 1086 1087 nsSSLPlaintextLayerIdentity = PR_GetUniqueIdentity("Plaintxext PSM layer"); 1088 nsSSLPlaintextLayerMethods = *PR_GetDefaultIOMethods(); 1089 nsSSLPlaintextLayerMethods.recv = PlaintextRecv; 1090 } 1091 1092 loadVersionFallbackLimit(); 1093 1094 // non main thread helpers will need to use defaults 1095 if (NS_IsMainThread()) { 1096 initInsecureFallbackSites(); 1097 1098 Preferences::AddStrongObserver(this, "security.tls.version.fallback-limit"); 1099 if (isPublic()) { 1100 // Changes to the allowlist on the public side will update the pref. 1101 // Don't propagate the changes to the private side. 1102 Preferences::AddStrongObserver(this, 1103 "security.tls.insecure_fallback_hosts"); 1104 } else { 1105 nsCOMPtr<nsIObserverService> obsSvc = 1106 mozilla::services::GetObserverService(); 1107 if (obsSvc) { 1108 obsSvc->AddObserver(this, "last-pb-context-exited", false); 1109 } 1110 } 1111 } else { 1112 MOZ_ASSERT(mTlsFlags, "Only per socket version can ignore prefs"); 1113 } 1114 1115 return NS_OK; 1116 } 1117 1118 void nsSSLIOLayerHelpers::loadVersionFallbackLimit() { 1119 // see nsNSSComponent::SetEnabledTLSVersions for pref handling rules 1120 uint32_t limit = StaticPrefs::security_tls_version_fallback_limit(); 1121 1122 // set fallback limit if it is set in the tls flags 1123 uint32_t tlsFlagsFallbackLimit = getTLSProviderFlagFallbackLimit(mTlsFlags); 1124 1125 if (tlsFlagsFallbackLimit) { 1126 limit = tlsFlagsFallbackLimit; 1127 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 1128 ("loadVersionFallbackLimit overriden by tlsFlags %d\n", limit)); 1129 } 1130 1131 SSLVersionRange defaults = {SSL_LIBRARY_VERSION_TLS_1_2, 1132 SSL_LIBRARY_VERSION_TLS_1_2}; 1133 SSLVersionRange filledInRange; 1134 nsNSSComponent::FillTLSVersionRange(filledInRange, limit, limit, defaults); 1135 if (filledInRange.max < SSL_LIBRARY_VERSION_TLS_1_2) { 1136 filledInRange.max = SSL_LIBRARY_VERSION_TLS_1_2; 1137 } 1138 1139 mVersionFallbackLimit = filledInRange.max; 1140 } 1141 1142 void nsSSLIOLayerHelpers::clearStoredData() { 1143 MOZ_ASSERT(NS_IsMainThread()); 1144 initInsecureFallbackSites(); 1145 1146 MutexAutoLock lock(mutex); 1147 mTLSIntoleranceInfo.Clear(); 1148 } 1149 1150 void nsSSLIOLayerHelpers::setInsecureFallbackSites(const nsCString& str) { 1151 MutexAutoLock lock(mutex); 1152 1153 mInsecureFallbackSites.Clear(); 1154 1155 for (const nsACString& host : nsCCharSeparatedTokenizer(str, ',').ToRange()) { 1156 if (!host.IsEmpty()) { 1157 mInsecureFallbackSites.PutEntry(host); 1158 } 1159 } 1160 } 1161 1162 void nsSSLIOLayerHelpers::initInsecureFallbackSites() { 1163 MOZ_ASSERT(NS_IsMainThread()); 1164 nsAutoCString insecureFallbackHosts; 1165 Preferences::GetCString("security.tls.insecure_fallback_hosts", 1166 insecureFallbackHosts); 1167 setInsecureFallbackSites(insecureFallbackHosts); 1168 } 1169 1170 bool nsSSLIOLayerHelpers::isPublic() const { 1171 return mPublicOrPrivate == PublicOrPrivate::Public; 1172 } 1173 1174 class FallbackPrefRemover final : public Runnable { 1175 public: 1176 explicit FallbackPrefRemover(const nsACString& aHost) 1177 : mozilla::Runnable("FallbackPrefRemover"), mHost(aHost) {} 1178 NS_IMETHOD Run() override; 1179 1180 private: 1181 nsCString mHost; 1182 }; 1183 1184 NS_IMETHODIMP 1185 FallbackPrefRemover::Run() { 1186 MOZ_ASSERT(NS_IsMainThread()); 1187 nsAutoCString oldValue; 1188 Preferences::GetCString("security.tls.insecure_fallback_hosts", oldValue); 1189 nsCString newValue; 1190 for (const nsACString& host : 1191 nsCCharSeparatedTokenizer(oldValue, ',').ToRange()) { 1192 if (host.Equals(mHost)) { 1193 continue; 1194 } 1195 if (!newValue.IsEmpty()) { 1196 newValue.Append(','); 1197 } 1198 newValue.Append(host); 1199 } 1200 Preferences::SetCString("security.tls.insecure_fallback_hosts", newValue); 1201 return NS_OK; 1202 } 1203 1204 void nsSSLIOLayerHelpers::removeInsecureFallbackSite(const nsACString& hostname, 1205 uint16_t port) { 1206 forgetIntolerance(hostname, port); 1207 { 1208 MutexAutoLock lock(mutex); 1209 if (!mInsecureFallbackSites.Contains(hostname)) { 1210 return; 1211 } 1212 mInsecureFallbackSites.RemoveEntry(hostname); 1213 } 1214 if (!isPublic()) { 1215 return; 1216 } 1217 RefPtr<Runnable> runnable = new FallbackPrefRemover(hostname); 1218 if (NS_IsMainThread()) { 1219 runnable->Run(); 1220 } else { 1221 NS_DispatchToMainThread(runnable); 1222 } 1223 } 1224 1225 bool nsSSLIOLayerHelpers::isInsecureFallbackSite(const nsACString& hostname) { 1226 MutexAutoLock lock(mutex); 1227 return mInsecureFallbackSites.Contains(hostname); 1228 } 1229 1230 nsresult nsSSLIOLayerNewSocket(int32_t family, const char* host, int32_t port, 1231 nsIProxyInfo* proxy, 1232 const OriginAttributes& originAttributes, 1233 PRFileDesc** fd, 1234 nsITLSSocketControl** tlsSocketControl, 1235 bool forSTARTTLS, uint32_t flags, 1236 uint32_t tlsFlags) { 1237 PRFileDesc* sock = PR_OpenTCPSocket(family); 1238 if (!sock) return NS_ERROR_OUT_OF_MEMORY; 1239 1240 nsresult rv = 1241 nsSSLIOLayerAddToSocket(family, host, port, proxy, originAttributes, sock, 1242 tlsSocketControl, forSTARTTLS, flags, tlsFlags); 1243 if (NS_FAILED(rv)) { 1244 PR_Close(sock); 1245 return rv; 1246 } 1247 1248 *fd = sock; 1249 return NS_OK; 1250 } 1251 1252 static PRFileDesc* nsSSLIOLayerImportFD(PRFileDesc* fd, 1253 NSSSocketControl* infoObject, 1254 const char* host, bool haveHTTPSProxy) { 1255 // Memory allocated here is released when fd is closed, regardless of the 1256 // success of this function. 1257 PRFileDesc* sslSock = SSL_ImportFD(nullptr, fd); 1258 if (!sslSock) { 1259 return nullptr; 1260 } 1261 if (SSL_HandshakeCallback(sslSock, HandshakeCallback, infoObject) != 1262 SECSuccess) { 1263 return nullptr; 1264 } 1265 if (SSL_SecretCallback(sslSock, SecretCallback, infoObject) != SECSuccess) { 1266 return nullptr; 1267 } 1268 if (SSL_SetCanFalseStartCallback(sslSock, CanFalseStartCallback, 1269 infoObject) != SECSuccess) { 1270 return nullptr; 1271 } 1272 1273 // Disable this hook if we connect anonymously. See bug 466080. 1274 uint32_t flags = infoObject->GetProviderFlags(); 1275 SSLGetClientAuthData clientAuthDataHook = SSLGetClientAuthDataHook; 1276 // Provide the client cert to HTTPS proxy no matter if it is anonymous. 1277 if (flags & nsISocketProvider::ANONYMOUS_CONNECT && !haveHTTPSProxy && 1278 !(flags & nsISocketProvider::ANONYMOUS_CONNECT_ALLOW_CLIENT_CERT)) { 1279 clientAuthDataHook = nullptr; 1280 } 1281 if (SSL_GetClientAuthDataHook(sslSock, clientAuthDataHook, infoObject) != 1282 SECSuccess) { 1283 return nullptr; 1284 } 1285 1286 if (SSL_AuthCertificateHook(sslSock, AuthCertificateHook, infoObject) != 1287 SECSuccess) { 1288 return nullptr; 1289 } 1290 if (SSL_SetURL(sslSock, host) != SECSuccess) { 1291 return nullptr; 1292 } 1293 1294 return sslSock; 1295 } 1296 1297 // Please change getSignatureName in nsNSSCallbacks.cpp when changing the list 1298 // here. See NOTE at SSL_SignatureSchemePrefSet call site. 1299 static const SSLSignatureScheme sEnabledSignatureSchemes[] = { 1300 ssl_sig_ecdsa_secp256r1_sha256, 1301 ssl_sig_ecdsa_secp384r1_sha384, 1302 ssl_sig_ecdsa_secp521r1_sha512, 1303 ssl_sig_rsa_pss_sha256, 1304 ssl_sig_rsa_pss_sha384, 1305 ssl_sig_rsa_pss_sha512, 1306 ssl_sig_rsa_pkcs1_sha256, 1307 ssl_sig_rsa_pkcs1_sha384, 1308 ssl_sig_rsa_pkcs1_sha512, 1309 #if !defined(EARLY_BETA_OR_EARLIER) 1310 ssl_sig_ecdsa_sha1, 1311 #endif 1312 ssl_sig_rsa_pkcs1_sha1, 1313 }; 1314 1315 enum CertificateCompressionAlgorithms { 1316 zlib = 0x01, 1317 brotli = 0x02, 1318 zstd = 0x03 1319 }; 1320 1321 void GatherCertificateCompressionTelemetry(SECStatus rv, 1322 CertificateCompressionAlgorithms alg, 1323 PRUint64 actualCertLen, 1324 PRUint64 encodedCertLen) { 1325 nsAutoCString decoder; 1326 1327 switch (alg) { 1328 case zlib: 1329 decoder.AssignLiteral("zlib"); 1330 break; 1331 case brotli: 1332 decoder.AssignLiteral("brotli"); 1333 break; 1334 case zstd: 1335 decoder.AssignLiteral("zstd"); 1336 break; 1337 } 1338 1339 if (rv != SECSuccess) { 1340 mozilla::glean::cert_compression::failures.Get(decoder).Add(1); 1341 return; 1342 } 1343 // Glam requires us to send 0 in case of success. 1344 mozilla::glean::cert_compression::failures.Get(decoder).Add(0); 1345 } 1346 1347 SECStatus abridgedCertificatePass1Decode(const SECItem* input, 1348 unsigned char* output, 1349 size_t outputLen, size_t* usedLen) { 1350 if (!input || !input->data || input->len == 0 || !output || outputLen == 0) { 1351 PR_SetError(SEC_ERROR_INVALID_ARGS, 0); 1352 return SECFailure; 1353 } 1354 if (NS_FAILED(mozilla::psm::abridged_certs::decompress( 1355 input->data, input->len, output, outputLen, usedLen))) { 1356 PR_SetError(SEC_ERROR_BAD_DATA, 0); 1357 return SECFailure; 1358 } 1359 return SECSuccess; 1360 } 1361 1362 SECStatus abridgedCertificateDecode(const SECItem* input, unsigned char* output, 1363 size_t outputLen, size_t* usedLen) { 1364 if (!input || !input->data || input->len == 0 || !output || outputLen == 0) { 1365 MOZ_LOG(gPIPNSSLog, LogLevel::Error, 1366 ("AbridgedCerts: Invalid arguments passed to " 1367 "abridgedCertificateDecode")); 1368 PR_SetError(SEC_ERROR_INVALID_ARGS, 0); 1369 return SECFailure; 1370 } 1371 // Pass 2 - Brotli with no dictionary 1372 UniqueSECItem tempBuffer(::SECITEM_AllocItem(nullptr, nullptr, outputLen)); 1373 if (!tempBuffer) { 1374 PR_SetError(SEC_ERROR_NO_MEMORY, 0); 1375 return SECFailure; 1376 } 1377 size_t tempUsed; 1378 SECStatus rv = brotliCertificateDecode(input, tempBuffer->data, 1379 (size_t)tempBuffer->len, &tempUsed); 1380 if (rv != SECSuccess) { 1381 MOZ_LOG(gPIPNSSLog, LogLevel::Error, 1382 ("AbridgedCerts: Brotli Decoder failed")); 1383 // Error code set by brotliCertificateDecode 1384 return rv; 1385 } 1386 tempBuffer->len = tempUsed; 1387 // Error code (if any) set by abridgedCertificatePass1Decode 1388 return abridgedCertificatePass1Decode(tempBuffer.get(), output, outputLen, 1389 usedLen); 1390 } 1391 1392 SECStatus zlibCertificateDecode(const SECItem* input, unsigned char* output, 1393 size_t outputLen, size_t* usedLen) { 1394 SECStatus rv = SECFailure; 1395 if (!input || !input->data || input->len == 0 || !output || outputLen == 0) { 1396 PR_SetError(SEC_ERROR_INVALID_ARGS, 0); 1397 return rv; 1398 } 1399 1400 z_stream strm = {}; 1401 1402 if (inflateInit(&strm) != Z_OK) { 1403 PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0); 1404 return rv; 1405 } 1406 1407 auto cleanup = MakeScopeExit([&] { 1408 GatherCertificateCompressionTelemetry(rv, zlib, *usedLen, input->len); 1409 (void)inflateEnd(&strm); 1410 }); 1411 1412 strm.avail_in = input->len; 1413 strm.next_in = input->data; 1414 1415 strm.avail_out = outputLen; 1416 strm.next_out = output; 1417 1418 int ret = inflate(&strm, Z_FINISH); 1419 bool ok = ret == Z_STREAM_END && strm.avail_in == 0 && strm.avail_out == 0; 1420 if (!ok) { 1421 PR_SetError(SEC_ERROR_BAD_DATA, 0); 1422 return rv; 1423 } 1424 1425 *usedLen = strm.total_out; 1426 rv = SECSuccess; 1427 return rv; 1428 } 1429 1430 SECStatus brotliCertificateDecode(const SECItem* input, unsigned char* output, 1431 size_t outputLen, size_t* usedLen) { 1432 SECStatus rv = SECFailure; 1433 1434 if (!input || !input->data || input->len == 0 || !output || outputLen == 0) { 1435 PR_SetError(SEC_ERROR_INVALID_ARGS, 0); 1436 return rv; 1437 } 1438 1439 auto cleanup = MakeScopeExit([&] { 1440 GatherCertificateCompressionTelemetry(rv, brotli, *usedLen, input->len); 1441 }); 1442 1443 size_t uncompressedSize = outputLen; 1444 BrotliDecoderResult result = BrotliDecoderDecompress( 1445 input->len, input->data, &uncompressedSize, output); 1446 1447 if (result != BROTLI_DECODER_RESULT_SUCCESS) { 1448 PR_SetError(SEC_ERROR_BAD_DATA, 0); 1449 return rv; 1450 } 1451 1452 *usedLen = uncompressedSize; 1453 rv = SECSuccess; 1454 return rv; 1455 } 1456 1457 SECStatus zstdCertificateDecode(const SECItem* input, unsigned char* output, 1458 size_t outputLen, size_t* usedLen) { 1459 SECStatus rv = SECFailure; 1460 1461 if (!input || !input->data || input->len == 0 || !output || outputLen == 0) { 1462 PR_SetError(SEC_ERROR_INVALID_ARGS, 0); 1463 return rv; 1464 } 1465 1466 auto cleanup = MakeScopeExit([&] { 1467 GatherCertificateCompressionTelemetry(rv, zstd, *usedLen, input->len); 1468 }); 1469 1470 size_t result = ZSTD_decompress(output, outputLen, input->data, input->len); 1471 1472 if (ZSTD_isError(result)) { 1473 PR_SetError(SEC_ERROR_BAD_DATA, 0); 1474 return rv; 1475 } 1476 1477 *usedLen = result; 1478 rv = SECSuccess; 1479 return rv; 1480 } 1481 1482 static nsresult nsSSLIOLayerSetOptions(PRFileDesc* fd, bool forSTARTTLS, 1483 bool haveProxy, const char* host, 1484 int32_t port, 1485 NSSSocketControl* infoObject) { 1486 if (forSTARTTLS || haveProxy) { 1487 if (SECSuccess != SSL_OptionSet(fd, SSL_SECURITY, false)) { 1488 return NS_ERROR_FAILURE; 1489 } 1490 } 1491 1492 SSLVersionRange range; 1493 if (SSL_VersionRangeGet(fd, &range) != SECSuccess) { 1494 return NS_ERROR_FAILURE; 1495 } 1496 1497 // Set TLS 1.3 compat mode. 1498 if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_TLS13_COMPAT_MODE, PR_TRUE)) { 1499 MOZ_LOG(gPIPNSSLog, LogLevel::Error, 1500 ("[%p] nsSSLIOLayerSetOptions: Setting compat mode failed\n", fd)); 1501 } 1502 1503 // setting TLS max version 1504 uint32_t versionFlags = 1505 getTLSProviderFlagMaxVersion(infoObject->GetProviderTlsFlags()); 1506 if (versionFlags) { 1507 MOZ_LOG( 1508 gPIPNSSLog, LogLevel::Debug, 1509 ("[%p] nsSSLIOLayerSetOptions: version flags %d\n", fd, versionFlags)); 1510 if (versionFlags == kTLSProviderFlagMaxVersion10) { 1511 range.max = SSL_LIBRARY_VERSION_TLS_1_0; 1512 } else if (versionFlags == kTLSProviderFlagMaxVersion11) { 1513 range.max = SSL_LIBRARY_VERSION_TLS_1_1; 1514 } else if (versionFlags == kTLSProviderFlagMaxVersion12) { 1515 range.max = SSL_LIBRARY_VERSION_TLS_1_2; 1516 } else if (versionFlags == kTLSProviderFlagMaxVersion13) { 1517 range.max = SSL_LIBRARY_VERSION_TLS_1_3; 1518 } else { 1519 MOZ_LOG(gPIPNSSLog, LogLevel::Error, 1520 ("[%p] nsSSLIOLayerSetOptions: unknown version flags %d\n", fd, 1521 versionFlags)); 1522 } 1523 } 1524 1525 if ((infoObject->GetProviderFlags() & nsISocketProvider::BE_CONSERVATIVE) && 1526 (range.max > SSL_LIBRARY_VERSION_TLS_1_2)) { 1527 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 1528 ("[%p] nsSSLIOLayerSetOptions: range.max limited to 1.2 due to " 1529 "BE_CONSERVATIVE flag\n", 1530 fd)); 1531 range.max = SSL_LIBRARY_VERSION_TLS_1_2; 1532 } 1533 1534 uint16_t maxEnabledVersion = range.max; 1535 infoObject->AdjustForTLSIntolerance(range); 1536 MOZ_LOG( 1537 gPIPNSSLog, LogLevel::Debug, 1538 ("[%p] nsSSLIOLayerSetOptions: using TLS version range (0x%04x,0x%04x)\n", 1539 fd, static_cast<unsigned int>(range.min), 1540 static_cast<unsigned int>(range.max))); 1541 1542 // If the user has set their minimum version to something higher than what 1543 // we've now set the maximum to, this will result in an inconsistent version 1544 // range unless we fix it up. This will override their preference, but we only 1545 // do this for sites critical to the operation of the browser (e.g. update 1546 // servers) and telemetry experiments. 1547 if (range.min > range.max) { 1548 range.min = range.max; 1549 } 1550 1551 if (SSL_VersionRangeSet(fd, &range) != SECSuccess) { 1552 return NS_ERROR_FAILURE; 1553 } 1554 infoObject->SetTLSVersionRange(range); 1555 1556 // when adjustForTLSIntolerance tweaks the maximum version downward, 1557 // we tell the server using this SCSV so they can detect a downgrade attack 1558 if (range.max < maxEnabledVersion) { 1559 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 1560 ("[%p] nsSSLIOLayerSetOptions: enabling TLS_FALLBACK_SCSV\n", fd)); 1561 // Some servers will choke if we send the fallback SCSV with TLS 1.2. 1562 if (range.max < SSL_LIBRARY_VERSION_TLS_1_2) { 1563 if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_FALLBACK_SCSV, true)) { 1564 return NS_ERROR_FAILURE; 1565 } 1566 } 1567 // tell NSS the max enabled version to make anti-downgrade effective 1568 if (SECSuccess != SSL_SetDowngradeCheckVersion(fd, maxEnabledVersion)) { 1569 return NS_ERROR_FAILURE; 1570 } 1571 } 1572 1573 // Enable ECH GREASE if suitable. Has no impact if 'real' ECH is being used. 1574 if (range.max >= SSL_LIBRARY_VERSION_TLS_1_3 && 1575 !(infoObject->GetProviderFlags() & (nsISocketProvider::BE_CONSERVATIVE | 1576 nsISocketProvider::DONT_TRY_ECH)) && 1577 StaticPrefs::security_tls_ech_grease_probability()) { 1578 if ((RandomUint64().valueOr(0) % 100) >= 1579 100 - StaticPrefs::security_tls_ech_grease_probability()) { 1580 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 1581 ("[%p] nsSSLIOLayerSetOptions: enabling TLS ECH Grease\n", fd)); 1582 if (SECSuccess != SSL_EnableTls13GreaseEch(fd, PR_TRUE)) { 1583 return NS_ERROR_FAILURE; 1584 } 1585 // ECH Padding can be between 1 and 255 1586 if (SECSuccess != 1587 SSL_SetTls13GreaseEchSize( 1588 fd, std::clamp(StaticPrefs::security_tls_ech_grease_size(), 1U, 1589 255U))) { 1590 return NS_ERROR_FAILURE; 1591 } 1592 infoObject->UpdateEchExtensionStatus(EchExtensionStatus::kGREASE); 1593 } 1594 } 1595 1596 // Include a modest set of named groups in supported_groups and determine how 1597 // many key shares to send. Please change getKeaGroupName in 1598 // nsNSSCallbacks.cpp when changing the lists here. 1599 unsigned int additional_shares = 1600 StaticPrefs::security_tls_client_hello_send_p256_keyshare(); 1601 if (StaticPrefs::security_tls_enable_kyber() && 1602 range.max >= SSL_LIBRARY_VERSION_TLS_1_3 && 1603 !(infoObject->GetProviderFlags() & 1604 (nsISocketProvider::BE_CONSERVATIVE | nsISocketProvider::IS_RETRY))) { 1605 const SSLNamedGroup namedGroups[] = { 1606 ssl_grp_kem_mlkem768x25519, ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, 1607 ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1, ssl_grp_ffdhe_2048, 1608 ssl_grp_ffdhe_3072}; 1609 if (SECSuccess != 1610 SSL_NamedGroupConfig(fd, namedGroups, std::size(namedGroups))) { 1611 return NS_ERROR_FAILURE; 1612 } 1613 additional_shares += 1; 1614 infoObject->WillSendMlkemShare(); 1615 } else { 1616 const SSLNamedGroup namedGroups[] = { 1617 ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, 1618 ssl_grp_ec_secp521r1, ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072}; 1619 // Skip the |ssl_grp_kem_mlkem768x25519| entry. 1620 if (SECSuccess != 1621 SSL_NamedGroupConfig(fd, namedGroups, std::size(namedGroups))) { 1622 return NS_ERROR_FAILURE; 1623 } 1624 } 1625 1626 // If additional_shares == 2, send mlkem768x25519, x25519, and p256. 1627 // If additional_shares == 1, send {mlkem768x25519, x25519} or {x25519, p256}. 1628 // If additional_shares == 0, send x25519. 1629 if (SECSuccess != SSL_SendAdditionalKeyShares(fd, additional_shares)) { 1630 return NS_ERROR_FAILURE; 1631 } 1632 1633 // Enabling Certificate Compression Decoding mechanisms. 1634 if (range.max >= SSL_LIBRARY_VERSION_TLS_1_3 && 1635 !(infoObject->GetProviderFlags() & 1636 (nsISocketProvider::BE_CONSERVATIVE | nsISocketProvider::IS_RETRY))) { 1637 SSLCertificateCompressionAlgorithm zlibAlg = {1, "zlib", nullptr, 1638 zlibCertificateDecode}; 1639 1640 SSLCertificateCompressionAlgorithm brotliAlg = {2, "brotli", nullptr, 1641 brotliCertificateDecode}; 1642 1643 SSLCertificateCompressionAlgorithm zstdAlg = {3, "zstd", nullptr, 1644 zstdCertificateDecode}; 1645 1646 SSLCertificateCompressionAlgorithm abridgedAlg = { 1647 0xab00, "abridged-00", nullptr, abridgedCertificateDecode}; 1648 1649 if (StaticPrefs::security_tls_enable_certificate_compression_zlib() && 1650 SSL_SetCertificateCompressionAlgorithm(fd, zlibAlg) != SECSuccess) { 1651 return NS_ERROR_FAILURE; 1652 } 1653 1654 if (StaticPrefs::security_tls_enable_certificate_compression_brotli() && 1655 SSL_SetCertificateCompressionAlgorithm(fd, brotliAlg) != SECSuccess) { 1656 return NS_ERROR_FAILURE; 1657 } 1658 1659 if (StaticPrefs::security_tls_enable_certificate_compression_zstd() && 1660 SSL_SetCertificateCompressionAlgorithm(fd, zstdAlg) != SECSuccess) { 1661 return NS_ERROR_FAILURE; 1662 } 1663 1664 if (StaticPrefs::security_tls_enable_certificate_compression_abridged() && 1665 mozilla::psm::abridged_certs::certs_are_available() && 1666 SSL_SetCertificateCompressionAlgorithm(fd, abridgedAlg) != SECSuccess) { 1667 return NS_ERROR_FAILURE; 1668 } 1669 } 1670 1671 // NOTE: Should this list ever include ssl_sig_rsa_pss_pss_sha* (or should 1672 // it become possible to enable this scheme via a pref), it is required 1673 // to test that a Delegated Credential containing a small-modulus RSA-PSS SPKI 1674 // is properly rejected. NSS will not advertise PKCS1 or RSAE schemes (which 1675 // the |ssl_sig_rsa_pss_*| defines alias, meaning we will not currently accept 1676 // any RSA DC. 1677 if (SECSuccess != 1678 SSL_SignatureSchemePrefSet(fd, sEnabledSignatureSchemes, 1679 std::size(sEnabledSignatureSchemes))) { 1680 return NS_ERROR_FAILURE; 1681 } 1682 1683 bool enabled = StaticPrefs::security_ssl_enable_ocsp_stapling(); 1684 if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_OCSP_STAPLING, enabled)) { 1685 return NS_ERROR_FAILURE; 1686 } 1687 1688 bool sctsEnabled = GetCertificateTransparencyMode() != 1689 CertVerifier::CertificateTransparencyMode::Disabled; 1690 if (SECSuccess != 1691 SSL_OptionSet(fd, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, sctsEnabled)) { 1692 return NS_ERROR_FAILURE; 1693 } 1694 1695 if (SECSuccess != SSL_OptionSet(fd, SSL_HANDSHAKE_AS_CLIENT, true)) { 1696 return NS_ERROR_FAILURE; 1697 } 1698 1699 #if defined(__arm__) 1700 if (!mozilla::supports_arm_aes()) { 1701 unsigned int enabledCiphers = 0; 1702 std::vector<uint16_t> ciphers(SSL_GetNumImplementedCiphers()); 1703 1704 // Returns only the enabled (reflecting prefs) ciphers, ordered 1705 // by their occurence in 1706 // https://hg.mozilla.org/projects/nss/file/a75ea4cdacd95282c6c245ebb849c25e84ccd908/lib/ssl/ssl3con.c#l87 1707 if (SSL_CipherSuiteOrderGet(fd, ciphers.data(), &enabledCiphers) != 1708 SECSuccess) { 1709 return NS_ERROR_FAILURE; 1710 } 1711 1712 // On ARM, prefer (TLS_CHACHA20_POLY1305_SHA256) over AES when hardware 1713 // support for AES isn't available. However, it may be disabled. If enabled, 1714 // it will either be element [0] or [1]*. If [0], we're done. If [1], swap 1715 // it with [0] (TLS_AES_128_GCM_SHA256). 1716 // *(assuming the compile-time order remains unchanged) 1717 if (enabledCiphers > 1) { 1718 if (ciphers[0] != TLS_CHACHA20_POLY1305_SHA256 && 1719 ciphers[1] == TLS_CHACHA20_POLY1305_SHA256) { 1720 std::swap(ciphers[0], ciphers[1]); 1721 1722 if (SSL_CipherSuiteOrderSet(fd, ciphers.data(), enabledCiphers) != 1723 SECSuccess) { 1724 return NS_ERROR_FAILURE; 1725 } 1726 } 1727 } 1728 } 1729 #endif 1730 1731 // Set the Peer ID so that SSL proxy connections work properly and to 1732 // separate anonymous and/or private browsing connections. 1733 nsAutoCString peerId; 1734 infoObject->GetPeerId(peerId); 1735 if (SECSuccess != SSL_SetSockPeerID(fd, peerId.get())) { 1736 return NS_ERROR_FAILURE; 1737 } 1738 1739 uint32_t flags = infoObject->GetProviderFlags(); 1740 if (flags & nsISocketProvider::NO_PERMANENT_STORAGE) { 1741 if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_SESSION_TICKETS, false) || 1742 SECSuccess != SSL_OptionSet(fd, SSL_NO_CACHE, true)) { 1743 return NS_ERROR_FAILURE; 1744 } 1745 } 1746 1747 return NS_OK; 1748 } 1749 1750 SECStatus StoreResumptionToken(PRFileDesc* fd, const PRUint8* resumptionToken, 1751 unsigned int len, void* ctx) { 1752 PRIntn val; 1753 if (SSL_OptionGet(fd, SSL_ENABLE_SESSION_TICKETS, &val) != SECSuccess || 1754 val == 0) { 1755 return SECFailure; 1756 } 1757 1758 NSSSocketControl* infoObject = (NSSSocketControl*)ctx; 1759 if (!infoObject) { 1760 return SECFailure; 1761 } 1762 1763 nsAutoCString peerId; 1764 infoObject->GetPeerId(peerId); 1765 if (NS_FAILED( 1766 net::SSLTokensCache::Put(peerId, resumptionToken, len, infoObject))) { 1767 return SECFailure; 1768 } 1769 1770 return SECSuccess; 1771 } 1772 1773 nsresult nsSSLIOLayerAddToSocket(int32_t family, const char* host, int32_t port, 1774 nsIProxyInfo* proxy, 1775 const OriginAttributes& originAttributes, 1776 PRFileDesc* fd, 1777 nsITLSSocketControl** tlsSocketControl, 1778 bool forSTARTTLS, uint32_t providerFlags, 1779 uint32_t providerTlsFlags) { 1780 RefPtr<nsSSLIOLayerHelpers> sslIOLayerHelpers; 1781 if (providerTlsFlags) { 1782 sslIOLayerHelpers = 1783 new nsSSLIOLayerHelpers(PublicOrPrivate::Public, providerTlsFlags); 1784 sslIOLayerHelpers->Init(); 1785 } else { 1786 bool isPrivate = providerFlags & nsISocketProvider::NO_PERMANENT_STORAGE || 1787 originAttributes.IsPrivateBrowsing(); 1788 sslIOLayerHelpers = 1789 isPrivate ? PrivateSSLIOLayerHelpers() : PublicSSLIOLayerHelpers(); 1790 } 1791 1792 RefPtr<NSSSocketControl> infoObject(new NSSSocketControl( 1793 nsDependentCString(host), port, sslIOLayerHelpers.forget(), providerFlags, 1794 providerTlsFlags)); 1795 if (!infoObject) { 1796 return NS_ERROR_FAILURE; 1797 } 1798 1799 infoObject->SetForSTARTTLS(forSTARTTLS); 1800 infoObject->SetOriginAttributes(originAttributes); 1801 1802 bool haveProxy = false; 1803 bool haveHTTPSProxy = false; 1804 if (proxy) { 1805 nsAutoCString proxyHost; 1806 nsresult rv = proxy->GetHost(proxyHost); 1807 if (NS_FAILED(rv)) { 1808 return rv; 1809 } 1810 haveProxy = !proxyHost.IsEmpty(); 1811 nsAutoCString type; 1812 haveHTTPSProxy = haveProxy && NS_SUCCEEDED(proxy->GetType(type)) && 1813 type.EqualsLiteral("https"); 1814 } 1815 1816 // A plaintext observer shim is inserted so we can observe some protocol 1817 // details without modifying nss 1818 PRFileDesc* plaintextLayer = 1819 PR_CreateIOLayerStub(nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity, 1820 &nsSSLIOLayerHelpers::nsSSLPlaintextLayerMethods); 1821 if (!plaintextLayer) { 1822 return NS_ERROR_FAILURE; 1823 } 1824 plaintextLayer->secret = (PRFilePrivate*)infoObject.get(); 1825 if (PR_PushIOLayer(fd, PR_TOP_IO_LAYER, plaintextLayer) != PR_SUCCESS) { 1826 plaintextLayer->dtor(plaintextLayer); 1827 return NS_ERROR_FAILURE; 1828 } 1829 auto plaintextLayerCleanup = MakeScopeExit([&fd] { 1830 // Note that PR_*IOLayer operations may modify the stack of fds, so a 1831 // previously-valid pointer may no longer point to what we think it points 1832 // to after calling PR_PopIOLayer. We must operate on the pointer returned 1833 // by PR_PopIOLayer. 1834 PRFileDesc* plaintextLayer = 1835 PR_PopIOLayer(fd, nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity); 1836 if (plaintextLayer) { 1837 plaintextLayer->dtor(plaintextLayer); 1838 } 1839 }); 1840 1841 PRFileDesc* sslSock = 1842 nsSSLIOLayerImportFD(fd, infoObject, host, haveHTTPSProxy); 1843 if (!sslSock) { 1844 return NS_ERROR_FAILURE; 1845 } 1846 1847 nsresult rv = nsSSLIOLayerSetOptions(sslSock, forSTARTTLS, haveProxy, host, 1848 port, infoObject); 1849 if (NS_FAILED(rv)) { 1850 return rv; 1851 } 1852 1853 // Now, layer ourselves on top of the SSL socket... 1854 PRFileDesc* layer = 1855 PR_CreateIOLayerStub(nsSSLIOLayerHelpers::nsSSLIOLayerIdentity, 1856 &nsSSLIOLayerHelpers::nsSSLIOLayerMethods); 1857 if (!layer) { 1858 return NS_ERROR_FAILURE; 1859 } 1860 // Give the layer an owning reference to the NSSSocketControl. 1861 // This is the simplest way to prevent the layer from outliving the 1862 // NSSSocketControl (otherwise, the layer could potentially use it in 1863 // nsSSLIOLayerClose after it has been released). 1864 // nsSSLIOLayerClose takes the owning reference when the underlying fd gets 1865 // closed. If the fd never gets closed (as in, leaks), the NSSSocketControl 1866 // will also leak. 1867 layer->secret = (PRFilePrivate*)do_AddRef(infoObject).take(); 1868 1869 if (PR_PushIOLayer(sslSock, PR_GetLayersIdentity(sslSock), layer) != 1870 PR_SUCCESS) { 1871 layer->dtor(layer); 1872 return NS_ERROR_FAILURE; 1873 } 1874 auto layerCleanup = MakeScopeExit([&fd] { 1875 PRFileDesc* layer = 1876 PR_PopIOLayer(fd, nsSSLIOLayerHelpers::nsSSLIOLayerIdentity); 1877 if (layer) { 1878 layer->dtor(layer); 1879 } 1880 }); 1881 1882 // We are going use a clear connection first // 1883 if (forSTARTTLS || haveProxy) { 1884 infoObject->SetHandshakeNotPending(); 1885 } 1886 1887 rv = infoObject->SetResumptionTokenFromExternalCache(sslSock); 1888 if (NS_FAILED(rv)) { 1889 return rv; 1890 } 1891 if (SSL_SetResumptionTokenCallback(sslSock, &StoreResumptionToken, 1892 infoObject) != SECSuccess) { 1893 return NS_ERROR_FAILURE; 1894 } 1895 1896 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("[%p] Socket set up", (void*)sslSock)); 1897 1898 (void)infoObject->SetFileDescPtr(sslSock); 1899 layerCleanup.release(); 1900 plaintextLayerCleanup.release(); 1901 *tlsSocketControl = infoObject.forget().take(); 1902 return NS_OK; 1903 } 1904 1905 extern "C" { 1906 1907 const uint8_t kIPCClientCertsObjectTypeCert = 1; 1908 const uint8_t kIPCClientCertsObjectTypeRSAKey = 2; 1909 const uint8_t kIPCClientCertsObjectTypeECKey = 3; 1910 1911 // This function is provided to the IPC client certs module so it can cause the 1912 // parent process to find certificates and keys and send identifying 1913 // information about them over IPC. 1914 void DoFindObjects(FindObjectsCallback cb, void* ctx) { 1915 net::SocketProcessChild* socketChild = 1916 net::SocketProcessChild::GetSingleton(); 1917 if (!socketChild) { 1918 return; 1919 } 1920 1921 RefPtr<IPCClientCertsChild> ipcClientCertsActor( 1922 socketChild->GetIPCClientCertsActor()); 1923 if (!ipcClientCertsActor) { 1924 return; 1925 } 1926 nsTArray<IPCClientCertObject> objects; 1927 if (!ipcClientCertsActor->SendFindObjects(&objects)) { 1928 return; 1929 } 1930 for (const auto& object : objects) { 1931 switch (object.type()) { 1932 case IPCClientCertObject::TECKey: 1933 cb(kIPCClientCertsObjectTypeECKey, object.get_ECKey().params().Length(), 1934 object.get_ECKey().params().Elements(), 1935 object.get_ECKey().cert().Length(), 1936 object.get_ECKey().cert().Elements(), ctx); 1937 break; 1938 case IPCClientCertObject::TRSAKey: 1939 cb(kIPCClientCertsObjectTypeRSAKey, 1940 object.get_RSAKey().modulus().Length(), 1941 object.get_RSAKey().modulus().Elements(), 1942 object.get_RSAKey().cert().Length(), 1943 object.get_RSAKey().cert().Elements(), ctx); 1944 break; 1945 case IPCClientCertObject::TCertificate: 1946 cb(kIPCClientCertsObjectTypeCert, 1947 object.get_Certificate().der().Length(), 1948 object.get_Certificate().der().Elements(), 0, nullptr, ctx); 1949 break; 1950 default: 1951 MOZ_ASSERT_UNREACHABLE("unhandled IPCClientCertObject type"); 1952 break; 1953 } 1954 } 1955 } 1956 1957 // This function is provided to the IPC client certs module so it can cause the 1958 // parent process to sign the given data using the key corresponding to the 1959 // given certificate, using the given parameters. 1960 void DoSign(size_t cert_len, const uint8_t* cert, size_t data_len, 1961 const uint8_t* data, size_t params_len, const uint8_t* params, 1962 SignCallback cb, void* ctx) { 1963 net::SocketProcessChild* socketChild = 1964 net::SocketProcessChild::GetSingleton(); 1965 if (!socketChild) { 1966 return; 1967 } 1968 1969 RefPtr<IPCClientCertsChild> ipcClientCertsActor( 1970 socketChild->GetIPCClientCertsActor()); 1971 if (!ipcClientCertsActor) { 1972 return; 1973 } 1974 ByteArray certBytes(nsTArray<uint8_t>(cert, cert_len)); 1975 ByteArray dataBytes(nsTArray<uint8_t>(data, data_len)); 1976 ByteArray paramsBytes(nsTArray<uint8_t>(params, params_len)); 1977 ByteArray signature; 1978 if (!ipcClientCertsActor->SendSign(certBytes, dataBytes, paramsBytes, 1979 &signature)) { 1980 return; 1981 } 1982 cb(signature.data().Length(), signature.data().Elements(), ctx); 1983 } 1984 1985 #ifdef MOZ_WIDGET_ANDROID 1986 // Similar to `DoFindObjects`, this function implements searching for client 1987 // authentication certificates on Android. When a TLS server requests a client 1988 // auth certificate, the backend will forward that request to the frontend, 1989 // which calls KeyChain.choosePrivateKeyAlias. The user can choose a 1990 // certificate, which causes it to become available for use. The 1991 // `ClientAuthCertificateManager` singleton keeps track of these certificates. 1992 // This function is called by osclientcerts when the backend looks for new 1993 // certificates and keys. It gets a list of all known client auth certificates 1994 // from `ClientAuthCertificateManager` and returns them via the callback. 1995 void AndroidDoFindObjects(FindObjectsCallback cb, void* ctx) { 1996 if (!jni::IsAvailable()) { 1997 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, 1998 ("AndroidDoFindObjects: JNI not available")); 1999 return; 2000 } 2001 jni::ObjectArray::LocalRef clientAuthCertificates = 2002 java::ClientAuthCertificateManager::GetClientAuthCertificates(); 2003 for (size_t i = 0; i < clientAuthCertificates->Length(); i++) { 2004 java::ClientAuthCertificateManager::ClientAuthCertificate::LocalRef 2005 clientAuthCertificate = clientAuthCertificates->GetElement(i); 2006 jni::ByteArray::LocalRef der = clientAuthCertificate->GetCertificateBytes(); 2007 jni::ByteArray::LocalRef keyParameters = 2008 clientAuthCertificate->GetKeyParameters(); 2009 cb(kIPCClientCertsObjectTypeCert, der->Length(), 2010 reinterpret_cast<uint8_t*>(der->GetElements().Elements()), 0, nullptr, 2011 ctx); 2012 cb(clientAuthCertificate->GetType(), keyParameters->Length(), 2013 reinterpret_cast<uint8_t*>(keyParameters->GetElements().Elements()), 2014 der->Length(), reinterpret_cast<uint8_t*>(der->GetElements().Elements()), 2015 ctx); 2016 jni::ObjectArray::LocalRef issuersBytes = 2017 clientAuthCertificate->GetIssuersBytes(); 2018 if (issuersBytes) { 2019 for (size_t i = 0; i < issuersBytes->Length(); i++) { 2020 jni::ByteArray::LocalRef issuer = issuersBytes->GetElement(i); 2021 cb(kIPCClientCertsObjectTypeCert, issuer->Length(), 2022 reinterpret_cast<uint8_t*>(issuer->GetElements().Elements()), 0, 2023 nullptr, ctx); 2024 } 2025 } 2026 } 2027 } 2028 2029 // Similar to `DoSign`, this function implements signing for client 2030 // authentication certificates on Android. `ClientAuthCertificateManager` keeps 2031 // track of any available client auth certificates and does the actual work of 2032 // signing - this function just passes in the appropriate parameters. 2033 void AndroidDoSign(size_t certLen, const uint8_t* cert, size_t dataLen, 2034 const uint8_t* data, const char* algorithm, SignCallback cb, 2035 void* ctx) { 2036 if (!jni::IsAvailable()) { 2037 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("AndroidDoSign: JNI not available")); 2038 return; 2039 } 2040 jni::ByteArray::LocalRef certBytes = 2041 jni::ByteArray::New(reinterpret_cast<const int8_t*>(cert), certLen); 2042 jni::ByteArray::LocalRef dataBytes = 2043 jni::ByteArray::New(reinterpret_cast<const int8_t*>(data), dataLen); 2044 jni::String::LocalRef algorithmStr = jni::StringParam(algorithm); 2045 jni::ByteArray::LocalRef signature = java::ClientAuthCertificateManager::Sign( 2046 certBytes, dataBytes, algorithmStr); 2047 if (signature) { 2048 cb(signature->Length(), 2049 reinterpret_cast<const uint8_t*>(signature->GetElements().Elements()), 2050 ctx); 2051 } 2052 } 2053 #endif // MOZ_WIDGET_ANDROID 2054 } // extern "C"