From 5138cd81e1835c8cfeb0b6d12ec9fdb3c5631f28 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Wed, 14 Feb 2024 16:12:03 -0500 Subject: [PATCH] suites: split integrity and confidentiality limit handling Previously the `CipherSuiteCommon` type had a `confidentiality_limit` and a `integrity_limit`. Recent refactoring for better downstream QUIC ergonomics has pulled these limits into the `quic::PacketKey` trait. To reduce duplication this commit adjusts our handling of these two limits. For the `integrity_limit`, it was already documented in `CipherSuiteCommon` as being specific to QUIC and irrelevant for TLS over TCP. For this reason we delete the field from `CipherSuiteCommon`, leaving it only in `quic::PacketKey` where it is actually useful. For the `confidentiality_limit` it was described imprecisely and erred on the side of caution, proposing a limit calculated based on QUIC overhead even for the TCP usecase. Now that we've split this field the `CipherSuiteCommon` version's documentation is updated to use a tighter bound for the TCP use-case, and the associated `PacketKey` field can be documented to use the QUIC bound. --- provider-example/src/lib.rs | 2 -- rustls/src/crypto/aws_lc_rs/tls12.rs | 6 ------ rustls/src/crypto/aws_lc_rs/tls13.rs | 3 --- rustls/src/crypto/ring/quic.rs | 16 ++++------------ rustls/src/crypto/ring/tls12.rs | 6 ------ rustls/src/crypto/ring/tls13.rs | 3 --- rustls/src/quic.rs | 18 +++++++++++++----- rustls/src/suites.rs | 16 ++++------------ 8 files changed, 21 insertions(+), 49 deletions(-) diff --git a/provider-example/src/lib.rs b/provider-example/src/lib.rs index 18f87769..e117d1a7 100644 --- a/provider-example/src/lib.rs +++ b/provider-example/src/lib.rs @@ -71,7 +71,6 @@ pub static TLS13_CHACHA20_POLY1305_SHA256: rustls::SupportedCipherSuite = suite: rustls::CipherSuite::TLS13_CHACHA20_POLY1305_SHA256, hash_provider: &hash::Sha256, confidentiality_limit: u64::MAX, - integrity_limit: 1 << 36, }, hkdf_provider: &rustls::crypto::tls13::HkdfUsingHmac(&hmac::Sha256Hmac), aead_alg: &aead::Chacha20Poly1305, @@ -84,7 +83,6 @@ pub static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: rustls::SupportedCipherS suite: rustls::CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, hash_provider: &hash::Sha256, confidentiality_limit: u64::MAX, - integrity_limit: 1 << 36, }, kx: rustls::crypto::KeyExchangeAlgorithm::ECDHE, sign: &[ diff --git a/rustls/src/crypto/aws_lc_rs/tls12.rs b/rustls/src/crypto/aws_lc_rs/tls12.rs index daff1b20..39aae7c7 100644 --- a/rustls/src/crypto/aws_lc_rs/tls12.rs +++ b/rustls/src/crypto/aws_lc_rs/tls12.rs @@ -25,7 +25,6 @@ pub static TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, hash_provider: &super::hash::SHA256, confidentiality_limit: u64::MAX, - integrity_limit: 1 << 36, }, kx: KeyExchangeAlgorithm::ECDHE, sign: TLS12_ECDSA_SCHEMES, @@ -40,7 +39,6 @@ pub static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, hash_provider: &super::hash::SHA256, confidentiality_limit: u64::MAX, - integrity_limit: 1 << 36, }, kx: KeyExchangeAlgorithm::ECDHE, sign: TLS12_RSA_SCHEMES, @@ -55,7 +53,6 @@ pub static TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, hash_provider: &super::hash::SHA256, confidentiality_limit: 1 << 23, - integrity_limit: 1 << 52, }, kx: KeyExchangeAlgorithm::ECDHE, sign: TLS12_RSA_SCHEMES, @@ -70,7 +67,6 @@ pub static TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, hash_provider: &super::hash::SHA384, confidentiality_limit: 1 << 23, - integrity_limit: 1 << 52, }, kx: KeyExchangeAlgorithm::ECDHE, sign: TLS12_RSA_SCHEMES, @@ -85,7 +81,6 @@ pub static TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, hash_provider: &super::hash::SHA256, confidentiality_limit: 1 << 23, - integrity_limit: 1 << 52, }, kx: KeyExchangeAlgorithm::ECDHE, sign: TLS12_ECDSA_SCHEMES, @@ -100,7 +95,6 @@ pub static TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, hash_provider: &super::hash::SHA384, confidentiality_limit: 1 << 23, - integrity_limit: 1 << 52, }, kx: KeyExchangeAlgorithm::ECDHE, sign: TLS12_ECDSA_SCHEMES, diff --git a/rustls/src/crypto/aws_lc_rs/tls13.rs b/rustls/src/crypto/aws_lc_rs/tls13.rs index cd3c2fcd..711ba709 100644 --- a/rustls/src/crypto/aws_lc_rs/tls13.rs +++ b/rustls/src/crypto/aws_lc_rs/tls13.rs @@ -26,7 +26,6 @@ pub(crate) static TLS13_CHACHA20_POLY1305_SHA256_INTERNAL: &Tls13CipherSuite = & suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256, hash_provider: &super::hash::SHA256, confidentiality_limit: u64::MAX, - integrity_limit: 1 << 36, }, hkdf_provider: &RingHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256), aead_alg: &Chacha20Poly1305Aead(AeadAlgorithm(&aead::CHACHA20_POLY1305)), @@ -45,7 +44,6 @@ pub static TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = suite: CipherSuite::TLS13_AES_256_GCM_SHA384, hash_provider: &super::hash::SHA384, confidentiality_limit: 1 << 23, - integrity_limit: 1 << 52, }, hkdf_provider: &RingHkdf(hkdf::HKDF_SHA384, hmac::HMAC_SHA384), aead_alg: &Aes256GcmAead(AeadAlgorithm(&aead::AES_256_GCM)), @@ -66,7 +64,6 @@ pub(crate) static TLS13_AES_128_GCM_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13C suite: CipherSuite::TLS13_AES_128_GCM_SHA256, hash_provider: &super::hash::SHA256, confidentiality_limit: 1 << 23, - integrity_limit: 1 << 52, }, hkdf_provider: &RingHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256), aead_alg: &Aes128GcmAead(AeadAlgorithm(&aead::AES_128_GCM)), diff --git a/rustls/src/crypto/ring/quic.rs b/rustls/src/crypto/ring/quic.rs index 0cfd9b01..2b216302 100644 --- a/rustls/src/crypto/ring/quic.rs +++ b/rustls/src/crypto/ring/quic.rs @@ -100,13 +100,9 @@ pub(crate) struct PacketKey { key: aead::LessSafeKey, /// Computes unique nonces for each packet iv: Iv, - /// Confidentiality limit (see [`CipherSuiteCommon::confidentiality_limit`][csc-limit]) - /// - /// [csc-limit]: crate::crypto::CipherSuiteCommon::confidentiality_limit + /// Confidentiality limit (see [`quic::PacketKey::confidentiality_limit`]) confidentiality_limit: u64, - /// Integrity limit (see [`CipherSuiteCommon::integrity_limit`][csc-limit]) - /// - /// [csc-limit]: crate::crypto::CipherSuiteCommon::integrity_limit + /// Integrity limit (see [`quic::PacketKey::integrity_limit`]) integrity_limit: u64, } @@ -175,16 +171,12 @@ impl quic::PacketKey for PacketKey { self.key.algorithm().tag_len() } - /// Confidentiality limit (see [`CipherSuiteCommon::confidentiality_limit`][csc-limit]) - /// - /// [csc-limit]: crate::crypto::CipherSuiteCommon::confidentiality_limit + /// Confidentiality limit (see [`quic::PacketKey::confidentiality_limit`]) fn confidentiality_limit(&self) -> u64 { self.confidentiality_limit } - /// Integrity limit (see [`CipherSuiteCommon::integrity_limit`][csc-limit]) - /// - /// [csc-limit]: crate::crypto::CipherSuiteCommon::integrity_limit + /// Integrity limit (see [`quic::PacketKey::integrity_limit`]) fn integrity_limit(&self) -> u64 { self.integrity_limit } diff --git a/rustls/src/crypto/ring/tls12.rs b/rustls/src/crypto/ring/tls12.rs index c7e01b99..88458df8 100644 --- a/rustls/src/crypto/ring/tls12.rs +++ b/rustls/src/crypto/ring/tls12.rs @@ -24,7 +24,6 @@ pub static TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, hash_provider: &super::hash::SHA256, confidentiality_limit: u64::MAX, - integrity_limit: 1 << 36, }, kx: KeyExchangeAlgorithm::ECDHE, sign: TLS12_ECDSA_SCHEMES, @@ -39,7 +38,6 @@ pub static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, hash_provider: &super::hash::SHA256, confidentiality_limit: u64::MAX, - integrity_limit: 1 << 36, }, kx: KeyExchangeAlgorithm::ECDHE, sign: TLS12_RSA_SCHEMES, @@ -54,7 +52,6 @@ pub static TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, hash_provider: &super::hash::SHA256, confidentiality_limit: 1 << 23, - integrity_limit: 1 << 52, }, kx: KeyExchangeAlgorithm::ECDHE, sign: TLS12_RSA_SCHEMES, @@ -69,7 +66,6 @@ pub static TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, hash_provider: &super::hash::SHA384, confidentiality_limit: 1 << 23, - integrity_limit: 1 << 52, }, kx: KeyExchangeAlgorithm::ECDHE, sign: TLS12_RSA_SCHEMES, @@ -84,7 +80,6 @@ pub static TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, hash_provider: &super::hash::SHA256, confidentiality_limit: 1 << 23, - integrity_limit: 1 << 52, }, kx: KeyExchangeAlgorithm::ECDHE, sign: TLS12_ECDSA_SCHEMES, @@ -99,7 +94,6 @@ pub static TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, hash_provider: &super::hash::SHA384, confidentiality_limit: 1 << 23, - integrity_limit: 1 << 52, }, kx: KeyExchangeAlgorithm::ECDHE, sign: TLS12_ECDSA_SCHEMES, diff --git a/rustls/src/crypto/ring/tls13.rs b/rustls/src/crypto/ring/tls13.rs index c2a71c0c..fadefb95 100644 --- a/rustls/src/crypto/ring/tls13.rs +++ b/rustls/src/crypto/ring/tls13.rs @@ -26,7 +26,6 @@ pub(crate) static TLS13_CHACHA20_POLY1305_SHA256_INTERNAL: &Tls13CipherSuite = & suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256, hash_provider: &super::hash::SHA256, confidentiality_limit: u64::MAX, - integrity_limit: 1 << 36, }, hkdf_provider: &RingHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256), aead_alg: &Chacha20Poly1305Aead(AeadAlgorithm(&aead::CHACHA20_POLY1305)), @@ -45,7 +44,6 @@ pub static TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = suite: CipherSuite::TLS13_AES_256_GCM_SHA384, hash_provider: &super::hash::SHA384, confidentiality_limit: 1 << 23, - integrity_limit: 1 << 52, }, hkdf_provider: &RingHkdf(hkdf::HKDF_SHA384, hmac::HMAC_SHA384), aead_alg: &Aes256GcmAead(AeadAlgorithm(&aead::AES_256_GCM)), @@ -66,7 +64,6 @@ pub(crate) static TLS13_AES_128_GCM_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13C suite: CipherSuite::TLS13_AES_128_GCM_SHA256, hash_provider: &super::hash::SHA256, confidentiality_limit: 1 << 23, - integrity_limit: 1 << 52, }, hkdf_provider: &RingHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256), aead_alg: &Aes128GcmAead(AeadAlgorithm(&aead::AES_128_GCM)), diff --git a/rustls/src/quic.rs b/rustls/src/quic.rs index 066ffd48..28f0b19f 100644 --- a/rustls/src/quic.rs +++ b/rustls/src/quic.rs @@ -706,18 +706,26 @@ pub trait PacketKey: Send + Sync { /// Tag length for the underlying AEAD algorithm fn tag_len(&self) -> usize; - /// Number of messages that can be safely encrypted with a single key of this type. + /// Number of QUIC messages that can be safely encrypted with a single key of this type. /// - /// See [`CipherSuiteCommon::confidentiality_limit`][csc-limit]. + /// Once a `MessageEncrypter` produced for this suite has encrypted more than + /// `confidentiality_limit` messages, an attacker gains an advantage in distinguishing it + /// from an ideal pseudorandom permutation (PRP). + /// + /// This is to be set on the assumption that messages are maximally sized -- + /// 2 ** 16. For non-QUIC TCP connections see [`CipherSuiteCommon::confidentiality_limit`][csc-limit]. /// /// [csc-limit]: crate::crypto::CipherSuiteCommon::confidentiality_limit fn confidentiality_limit(&self) -> u64; - /// Number of messages that can be safely authenticated with a single key of this type. + /// Number of QUIC messages that can be safely decrypted with a single key of this type /// - /// See [`CipherSuiteCommon::integrity_limit`][csc-limit]. + /// Once a `MessageDecrypter` produced for this suite has failed to decrypt `integrity_limit` + /// messages, an attacker gains an advantage in forging messages. /// - /// [csc-limit]: crate::crypto::CipherSuiteCommon::integrity_limit + /// This is not relevant for TLS over TCP (which is implemented in this crate) + /// because a single failed decryption is fatal to the connection. However, + /// this quantity is used by QUIC. fn integrity_limit(&self) -> u64; } diff --git a/rustls/src/suites.rs b/rustls/src/suites.rs index ba1eb5c2..36007fd1 100644 --- a/rustls/src/suites.rs +++ b/rustls/src/suites.rs @@ -20,25 +20,17 @@ pub struct CipherSuiteCommon { /// Which hash function the suite uses. pub hash_provider: &'static dyn crypto::hash::Hash, - /// Number of messages that can be safely encrypted with a single key of this type + /// Number of TCP-TLS messages that can be safely encrypted with a single key of this type /// /// Once a `MessageEncrypter` produced for this suite has encrypted more than /// `confidentiality_limit` messages, an attacker gains an advantage in distinguishing it /// from an ideal pseudorandom permutation (PRP). /// /// This is to be set on the assumption that messages are maximally sized -- - /// at least 2 ** 14 bytes for TCP-TLS and 2 ** 16 for QUIC. + /// at least 2 ** 14 bytes. It **does not** consider confidentiality limits for + /// QUIC connections - see the [`quic::KeyBuilder.confidentiality_limit`] field for + /// this context. pub confidentiality_limit: u64, - - /// Number of messages that can be safely decrypted with a single key of this type - /// - /// Once a `MessageDecrypter` produced for this suite has failed to decrypt `integrity_limit` - /// messages, an attacker gains an advantage in forging messages. - /// - /// This is not relevant for TLS over TCP (which is implemented in this crate) - /// because a single failed decryption is fatal to the connection. However, - /// this quantity is used by QUIC. - pub integrity_limit: u64, } impl CipherSuiteCommon {