From 8c244360cc73eaa67c9573e15d40faf147dc5ff1 Mon Sep 17 00:00:00 2001 From: Dana Keeler Date: Wed, 8 Nov 2023 21:37:56 +0000 Subject: [PATCH] Bug 1862062 - rework PSM TLS cipher suite telemetry r=jschanck Differential Revision: https://phabricator.services.mozilla.com/D192402 --- security/manager/ssl/nsNSSCallbacks.cpp | 265 +++++++----------- toolkit/components/telemetry/Histograms.json | 51 +--- .../telemetry/histogram-allowlists.json | 2 - 3 files changed, 111 insertions(+), 207 deletions(-) diff --git a/security/manager/ssl/nsNSSCallbacks.cpp b/security/manager/ssl/nsNSSCallbacks.cpp index d1667e0161be..e343ac89abeb 100644 --- a/security/manager/ssl/nsNSSCallbacks.cpp +++ b/security/manager/ssl/nsNSSCallbacks.cpp @@ -55,9 +55,6 @@ using namespace mozilla::psm; extern LazyLogModule gPIPNSSLog; -static void AccumulateCipherSuite(Telemetry::HistogramID probe, - const SSLChannelInfo& channelInfo); - namespace { // Bits in bit mask for SSL_REASONS_FOR_NOT_FALSE_STARTING telemetry probe @@ -903,159 +900,94 @@ static void AccumulateECCCurve(Telemetry::HistogramID probe, uint32_t bits) { Telemetry::Accumulate(probe, value); } -static void AccumulateCipherSuite(Telemetry::HistogramID probe, - const SSLChannelInfo& channelInfo) { +static void AccumulateCipherSuite(const SSLChannelInfo& channelInfo) { uint32_t value; + // Note: this list must include every cipher suite it is possible to enable + // in nsNSSComponent.cpp (see sCipherPrefs and sDeprecatedTLS1CipherPrefs). switch (channelInfo.cipherSuite) { - // ECDHE key exchange - case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case TLS_RSA_WITH_3DES_EDE_CBC_SHA: // 0x000A value = 1; break; - case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case TLS_RSA_WITH_AES_128_CBC_SHA: // 0x002F value = 2; break; - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: // 0x0033 value = 3; break; - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + case TLS_RSA_WITH_AES_256_CBC_SHA: // 0x0035 value = 4; break; - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: // 0x0039 value = 5; break; - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + case TLS_RSA_WITH_AES_128_GCM_SHA256: // 0x009C value = 6; break; - case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + case TLS_RSA_WITH_AES_256_GCM_SHA384: // 0x009D value = 7; break; - case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: // 0xC009 + value = 8; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: // 0xC00A + value = 9; + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: // 0xC013 value = 10; break; - case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: // 0xC014 value = 11; break; - case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: // 0xC02B value = 12; break; - case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: // 0xC02C value = 13; break; - case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: // 0xC02F value = 14; break; - // DHE key exchange - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - value = 21; + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: // 0xC030 + value = 15; break; - case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: - value = 22; + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: // 0xCCA8 + value = 16; break; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - value = 23; + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: // 0xCCA9 + value = 17; break; - case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: - value = 24; + + // TLS 1.3 cipher suites + case TLS_AES_128_GCM_SHA256: // 0x1301 + value = 18; break; - case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - value = 25; + case TLS_AES_256_GCM_SHA384: // 0x1302 + value = 19; break; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - value = 26; - break; - case TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: - value = 27; - break; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - value = 28; - break; - case TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: - value = 29; - break; - case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - value = 30; - break; - // ECDH key exchange - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - value = 41; - break; - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - value = 42; - break; - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - value = 43; - break; - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - value = 44; - break; - case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - value = 45; - break; - case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - value = 46; - break; - // RSA key exchange - case TLS_RSA_WITH_AES_128_CBC_SHA: - value = 61; - break; - case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: - value = 62; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA: - value = 63; - break; - case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: - value = 64; - break; - case SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA: - value = 65; - break; - case TLS_RSA_WITH_3DES_EDE_CBC_SHA: - value = 66; - break; - case TLS_RSA_WITH_SEED_CBC_SHA: - value = 67; - break; - case TLS_RSA_WITH_AES_128_GCM_SHA256: - value = 68; - break; - case TLS_RSA_WITH_AES_256_GCM_SHA384: - value = 69; - break; - // TLS 1.3 PSK resumption - case TLS_AES_128_GCM_SHA256: - value = 70; - break; - case TLS_CHACHA20_POLY1305_SHA256: - value = 71; - break; - case TLS_AES_256_GCM_SHA384: - value = 72; + case TLS_CHACHA20_POLY1305_SHA256: // 0x1303 + value = 20; break; + // unknown default: value = 0; break; } MOZ_ASSERT(value != 0); - Telemetry::Accumulate(probe, value); + Telemetry::Accumulate(Telemetry::TLS_CIPHER_SUITE, value); } void HandshakeCallback(PRFileDesc* fd, void* client_data) { - SECStatus rv; - - NSSSocketControl* infoObject = (NSSSocketControl*)fd->higher->secret; - // Do the bookkeeping that needs to be done after the // server's ServerHello...ServerHelloDone have been processed, but that // doesn't need the handshake to be completed. PreliminaryHandshakeDone(fd); + NSSSocketControl* infoObject = (NSSSocketControl*)fd->higher->secret; nsSSLIOLayerHelpers& ioLayerHelpers = infoObject->SharedState().IOLayerHelpers(); SSLVersionRange versions(infoObject->GetTLSVersionRange()); - MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("[%p] HandshakeCallback: succeeded using TLS version range " "(0x%04x,0x%04x)\n", @@ -1067,75 +999,70 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) { infoObject->GetPort(), versions.max); SSLChannelInfo channelInfo; - rv = SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)); + SECStatus rv = SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)); MOZ_ASSERT(rv == SECSuccess); - if (rv == SECSuccess) { - // Get the protocol version for telemetry - // 1=tls1, 2=tls1.1, 3=tls1.2 - unsigned int versionEnum = channelInfo.protocolVersion & 0xFF; - MOZ_ASSERT(versionEnum > 0); - Telemetry::Accumulate(Telemetry::SSL_HANDSHAKE_VERSION, versionEnum); - AccumulateCipherSuite(infoObject->IsFullHandshake() - ? Telemetry::SSL_CIPHER_SUITE_FULL - : Telemetry::SSL_CIPHER_SUITE_RESUMED, - channelInfo); + if (rv != SECSuccess) { + return; + } + AccumulateCipherSuite(channelInfo); - SSLCipherSuiteInfo cipherInfo; - rv = SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, - sizeof cipherInfo); - MOZ_ASSERT(rv == SECSuccess); - if (rv == SECSuccess) { - // keyExchange null=0, rsa=1, dh=2, fortezza=3, ecdh=4 - Telemetry::Accumulate(infoObject->IsFullHandshake() - ? Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_FULL - : Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_RESUMED, - channelInfo.keaType); + // Get the protocol version for telemetry + // 1=tls1, 2=tls1.1, 3=tls1.2, 4=tls1.3 + unsigned int versionEnum = channelInfo.protocolVersion & 0xFF; + MOZ_ASSERT(versionEnum > 0); + Telemetry::Accumulate(Telemetry::SSL_HANDSHAKE_VERSION, versionEnum); - if (infoObject->IsFullHandshake()) { - switch (channelInfo.keaType) { - case ssl_kea_rsa: - AccumulateNonECCKeySize(Telemetry::SSL_KEA_RSA_KEY_SIZE_FULL, - channelInfo.keaKeyBits); - break; - case ssl_kea_dh: - AccumulateNonECCKeySize(Telemetry::SSL_KEA_DHE_KEY_SIZE_FULL, - channelInfo.keaKeyBits); - break; - case ssl_kea_ecdh: - AccumulateECCCurve(Telemetry::SSL_KEA_ECDHE_CURVE_FULL, - channelInfo.keaKeyBits); - break; - default: - MOZ_CRASH("impossible KEA"); - break; - } + SSLCipherSuiteInfo cipherInfo; + rv = SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, + sizeof cipherInfo); + MOZ_ASSERT(rv == SECSuccess); + if (rv != SECSuccess) { + return; + } + // keyExchange null=0, rsa=1, dh=2, fortezza=3, ecdh=4 + Telemetry::Accumulate(infoObject->IsFullHandshake() + ? Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_FULL + : Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_RESUMED, + channelInfo.keaType); - Telemetry::Accumulate(Telemetry::SSL_AUTH_ALGORITHM_FULL, - channelInfo.authType); + if (infoObject->IsFullHandshake()) { + switch (channelInfo.keaType) { + case ssl_kea_rsa: + AccumulateNonECCKeySize(Telemetry::SSL_KEA_RSA_KEY_SIZE_FULL, + channelInfo.keaKeyBits); + break; + case ssl_kea_dh: + AccumulateNonECCKeySize(Telemetry::SSL_KEA_DHE_KEY_SIZE_FULL, + channelInfo.keaKeyBits); + break; + case ssl_kea_ecdh: + AccumulateECCCurve(Telemetry::SSL_KEA_ECDHE_CURVE_FULL, + channelInfo.keaKeyBits); + break; + default: + MOZ_CRASH("impossible KEA"); + break; + } - // RSA key exchange doesn't use a signature for auth. - if (channelInfo.keaType != ssl_kea_rsa) { - switch (channelInfo.authType) { - case ssl_auth_rsa: - case ssl_auth_rsa_sign: - AccumulateNonECCKeySize(Telemetry::SSL_AUTH_RSA_KEY_SIZE_FULL, - channelInfo.authKeyBits); - break; - case ssl_auth_ecdsa: - AccumulateECCCurve(Telemetry::SSL_AUTH_ECDSA_CURVE_FULL, - channelInfo.authKeyBits); - break; - default: - MOZ_CRASH("impossible auth algorithm"); - break; - } - } + Telemetry::Accumulate(Telemetry::SSL_AUTH_ALGORITHM_FULL, + channelInfo.authType); + + // RSA key exchange doesn't use a signature for auth. + if (channelInfo.keaType != ssl_kea_rsa) { + switch (channelInfo.authType) { + case ssl_auth_rsa: + case ssl_auth_rsa_sign: + AccumulateNonECCKeySize(Telemetry::SSL_AUTH_RSA_KEY_SIZE_FULL, + channelInfo.authKeyBits); + break; + case ssl_auth_ecdsa: + AccumulateECCCurve(Telemetry::SSL_AUTH_ECDSA_CURVE_FULL, + channelInfo.authKeyBits); + break; + default: + MOZ_CRASH("impossible auth algorithm"); + break; } - - Telemetry::Accumulate(infoObject->IsFullHandshake() - ? Telemetry::SSL_SYMMETRIC_CIPHER_FULL - : Telemetry::SSL_SYMMETRIC_CIPHER_RESUMED, - cipherInfo.symCipher); } } diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 06bf029d5e47..8d40582258ce 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -3849,18 +3849,22 @@ "description": "ms elapsed time of OCSP etc.. that failed" }, "SSL_KEY_EXCHANGE_ALGORITHM_FULL": { - "record_in_processes": ["main", "content"], - "products": ["firefox", "fennec"], + "record_in_processes": ["main"], + "products": ["firefox"], "alert_emails": ["seceng-telemetry@mozilla.com"], + "bug_numbers": [1862062], + "releaseChannelCollection": "opt-out", "expires_in_version": "never", "kind": "enumerated", "n_values": 16, "description": "SSL Handshake Key Exchange Algorithm for full handshake (null=0, rsa=1, dh=2, fortezza=3, ecdh=4)" }, "SSL_KEY_EXCHANGE_ALGORITHM_RESUMED": { - "record_in_processes": ["main", "content"], - "products": ["firefox", "fennec"], + "record_in_processes": ["main"], + "products": ["firefox"], "alert_emails": ["seceng-telemetry@mozilla.com"], + "bug_numbers": [1862062], + "releaseChannelCollection": "opt-out", "expires_in_version": "never", "kind": "enumerated", "n_values": 16, @@ -13232,23 +13236,16 @@ "n_values": 64, "description": "TLS/SSL version intolerance was falsely detected, server rejected handshake (see tlsIntoleranceTelemetryBucket() in nsNSSIOLayer.cpp)." }, - "SSL_CIPHER_SUITE_FULL": { - "record_in_processes": ["main", "content"], - "products": ["firefox", "fennec"], + "TLS_CIPHER_SUITE": { + "record_in_processes": ["main"], + "products": ["firefox"], "alert_emails": ["seceng-telemetry@mozilla.com"], + "bug_numbers": [1862062], + "releaseChannelCollection": "opt-out", "expires_in_version": "never", "kind": "enumerated", - "n_values": 128, - "description": "Negotiated cipher suite in full handshake (see key in AccumulateCipherSuite in nsNSSCallbacks.cpp). Entries #8, 9, 47, 48, 68, and 69 correspond to ciphers that use RC4." - }, - "SSL_CIPHER_SUITE_RESUMED": { - "record_in_processes": ["main", "content"], - "products": ["firefox", "fennec"], - "alert_emails": ["seceng-telemetry@mozilla.com"], - "expires_in_version": "never", - "kind": "enumerated", - "n_values": 128, - "description": "Negotiated cipher suite in resumed handshake (see key in AccumulateCipherSuite in nsNSSCallbacks.cpp)" + "n_values": 64, + "description": "Negotiated cipher suite in TLS handshake (see key in AccumulateCipherSuite in nsNSSCallbacks.cpp)" }, "SSL_KEA_RSA_KEY_SIZE_FULL": { "record_in_processes": ["main"], @@ -13316,24 +13313,6 @@ "n_values": 36, "description": "ECDSA signature curve for TLS_*_ECDSA_* in full handshake (23=P-256, 24=P-384, 25=P-521)" }, - "SSL_SYMMETRIC_CIPHER_FULL": { - "record_in_processes": ["main", "content"], - "products": ["firefox", "fennec"], - "alert_emails": ["seceng-telemetry@mozilla.com"], - "expires_in_version": "never", - "kind": "enumerated", - "n_values": 32, - "description": "Symmetric cipher used in full handshake (null=0, 3des=4, aes-cbc=7, aes-gcm=10, chacha20=11)" - }, - "SSL_SYMMETRIC_CIPHER_RESUMED": { - "record_in_processes": ["main", "content"], - "products": ["firefox", "fennec"], - "alert_emails": ["seceng-telemetry@mozilla.com"], - "expires_in_version": "never", - "kind": "enumerated", - "n_values": 32, - "description": "Symmetric cipher used in resumed handshake (null=0, 3des=4, aes-cbc=7, aes-gcm=10, chacha20=11)" - }, "SSL_REASONS_FOR_NOT_FALSE_STARTING": { "record_in_processes": ["main"], "products": ["firefox"], diff --git a/toolkit/components/telemetry/histogram-allowlists.json b/toolkit/components/telemetry/histogram-allowlists.json index 54b4286a4fb6..833d62a83b25 100644 --- a/toolkit/components/telemetry/histogram-allowlists.json +++ b/toolkit/components/telemetry/histogram-allowlists.json @@ -849,8 +849,6 @@ "DEVTOOLS_HEAP_SNAPSHOT_NODE_COUNT", "DEVTOOLS_HEAP_SNAPSHOT_EDGE_COUNT", "NETWORK_CACHE_HIT_RATE_PER_CACHE_SIZE", - "SSL_CIPHER_SUITE_FULL", - "SSL_CIPHER_SUITE_RESUMED", "SSL_HANDSHAKE_RESULT", "SSL_HANDSHAKE_RESULT_FIRST_TRY", "SSL_HANDSHAKE_RESULT_CONSERVATIVE",