mirror of https://github.com/ctz/rustls
Expose FIPS "service indicator"
This means a `ClientConfig` and `ServerConfig` can be asked whether it is in fips mode, and it answers by asking the same of all its constituent cryptography.
This commit is contained in:
parent
afe43b0213
commit
327444fdb8
|
@ -284,6 +284,12 @@ impl ClientConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return true if connections made with this `ClientConfig` will
|
||||||
|
/// operate in FIPS mode.
|
||||||
|
pub fn fips_mode(&self) -> bool {
|
||||||
|
self.provider.fips_mode()
|
||||||
|
}
|
||||||
|
|
||||||
/// We support a given TLS version if it's quoted in the configured
|
/// We support a given TLS version if it's quoted in the configured
|
||||||
/// versions *and* at least one ciphersuite for this version is
|
/// versions *and* at least one ciphersuite for this version is
|
||||||
/// also configured.
|
/// also configured.
|
||||||
|
|
|
@ -36,8 +36,17 @@ pub(crate) mod tls13;
|
||||||
/// A `CryptoProvider` backed by aws-lc-rs.
|
/// A `CryptoProvider` backed by aws-lc-rs.
|
||||||
pub fn default_provider() -> CryptoProvider {
|
pub fn default_provider() -> CryptoProvider {
|
||||||
CryptoProvider {
|
CryptoProvider {
|
||||||
cipher_suites: DEFAULT_CIPHER_SUITES.to_vec(),
|
// TODO: make this filtering conditional on fips feature
|
||||||
kx_groups: ALL_KX_GROUPS.to_vec(),
|
cipher_suites: DEFAULT_CIPHER_SUITES
|
||||||
|
.iter()
|
||||||
|
.filter(|cs| cs.fips_mode())
|
||||||
|
.copied()
|
||||||
|
.collect(),
|
||||||
|
kx_groups: ALL_KX_GROUPS
|
||||||
|
.iter()
|
||||||
|
.filter(|kx| kx.fips_mode())
|
||||||
|
.copied()
|
||||||
|
.collect(),
|
||||||
signature_verification_algorithms: SUPPORTED_SIG_ALGS,
|
signature_verification_algorithms: SUPPORTED_SIG_ALGS,
|
||||||
secure_random: &AwsLcRs,
|
secure_random: &AwsLcRs,
|
||||||
key_provider: &AwsLcRs,
|
key_provider: &AwsLcRs,
|
||||||
|
@ -55,6 +64,10 @@ impl SecureRandom for AwsLcRs {
|
||||||
.fill(buf)
|
.fill(buf)
|
||||||
.map_err(|_| GetRandomFailed)
|
.map_err(|_| GetRandomFailed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
aws_lc_rs::try_fips_mode().is_ok()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KeyProvider for AwsLcRs {
|
impl KeyProvider for AwsLcRs {
|
||||||
|
@ -64,6 +77,10 @@ impl KeyProvider for AwsLcRs {
|
||||||
) -> Result<Arc<dyn SigningKey>, Error> {
|
) -> Result<Arc<dyn SigningKey>, Error> {
|
||||||
sign::any_supported_type(&key_der)
|
sign::any_supported_type(&key_der)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
aws_lc_rs::try_fips_mode().is_ok()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The cipher suite configuration that an application should use by default.
|
/// The cipher suite configuration that an application should use by default.
|
||||||
|
@ -207,4 +224,10 @@ mod ring_shim {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// AEAD algorithm that is used by `mod ticketer`.
|
/// AEAD algorithm that is used by `mod ticketer`.
|
||||||
pub(super) static TICKETER_AEAD: &'static ring_like::aead::Algorithm = &ring_like::aead::AES_256_GCM;
|
pub(super) static TICKETER_AEAD: &'static ring_like::aead::Algorithm =
|
||||||
|
&ring_like::aead::AES_256_GCM;
|
||||||
|
|
||||||
|
/// Are we in FIPS mode?
|
||||||
|
pub(super) fn fips_mode() -> bool {
|
||||||
|
aws_lc_rs::try_fips_mode().is_ok()
|
||||||
|
}
|
||||||
|
|
|
@ -188,6 +188,10 @@ impl Tls12AeadAlgorithm for GcmAlgorithm {
|
||||||
iv: gcm_iv(write_iv, explicit),
|
iv: gcm_iv(write_iv, explicit),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
super::fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct ChaCha20Poly1305;
|
pub(crate) struct ChaCha20Poly1305;
|
||||||
|
@ -234,6 +238,10 @@ impl Tls12AeadAlgorithm for ChaCha20Poly1305 {
|
||||||
iv: Iv::new(iv[..].try_into().unwrap()),
|
iv: Iv::new(iv[..].try_into().unwrap()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false // not FIPS approved
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `MessageEncrypter` for AES-GCM AEAD ciphersuites. TLS 1.2 only.
|
/// A `MessageEncrypter` for AES-GCM AEAD ciphersuites. TLS 1.2 only.
|
||||||
|
@ -433,4 +441,8 @@ impl Prf for Tls12Prf {
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
super::fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,6 +106,10 @@ impl Tls13AeadAlgorithm for Chacha20Poly1305Aead {
|
||||||
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
|
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
|
||||||
Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv })
|
Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false // not FIPS approved
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Aes256GcmAead(AeadAlgorithm);
|
struct Aes256GcmAead(AeadAlgorithm);
|
||||||
|
@ -130,6 +134,10 @@ impl Tls13AeadAlgorithm for Aes256GcmAead {
|
||||||
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
|
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
|
||||||
Ok(ConnectionTrafficSecrets::Aes256Gcm { key, iv })
|
Ok(ConnectionTrafficSecrets::Aes256Gcm { key, iv })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
super::fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Aes128GcmAead(AeadAlgorithm);
|
struct Aes128GcmAead(AeadAlgorithm);
|
||||||
|
@ -154,6 +162,10 @@ impl Tls13AeadAlgorithm for Aes128GcmAead {
|
||||||
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
|
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
|
||||||
Ok(ConnectionTrafficSecrets::Aes128Gcm { key, iv })
|
Ok(ConnectionTrafficSecrets::Aes128Gcm { key, iv })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
super::fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// common encrypter/decrypter/key_len items for above Tls13AeadAlgorithm impls
|
// common encrypter/decrypter/key_len items for above Tls13AeadAlgorithm impls
|
||||||
|
@ -346,6 +358,10 @@ impl Hkdf for RingHkdf {
|
||||||
fn hmac_sign(&self, key: &OkmBlock, message: &[u8]) -> crypto::hmac::Tag {
|
fn hmac_sign(&self, key: &OkmBlock, message: &[u8]) -> crypto::hmac::Tag {
|
||||||
crypto::hmac::Tag::new(hmac::sign(&hmac::Key::new(self.1, key.as_ref()), message).as_ref())
|
crypto::hmac::Tag::new(hmac::sign(&hmac::Key::new(self.1, key.as_ref()), message).as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
super::fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RingHkdfExpander {
|
struct RingHkdfExpander {
|
||||||
|
|
|
@ -31,6 +31,11 @@ pub trait Tls13AeadAlgorithm: Send + Sync {
|
||||||
key: AeadKey,
|
key: AeadKey,
|
||||||
iv: Iv,
|
iv: Iv,
|
||||||
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError>;
|
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError>;
|
||||||
|
|
||||||
|
/// Return true if this is backed by a FIPS-approved implementation.
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Factory trait for building `MessageEncrypter` and `MessageDecrypter` for a TLS1.2 cipher suite.
|
/// Factory trait for building `MessageEncrypter` and `MessageDecrypter` for a TLS1.2 cipher suite.
|
||||||
|
@ -72,6 +77,11 @@ pub trait Tls12AeadAlgorithm: Send + Sync + 'static {
|
||||||
iv: &[u8],
|
iv: &[u8],
|
||||||
explicit: &[u8],
|
explicit: &[u8],
|
||||||
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError>;
|
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError>;
|
||||||
|
|
||||||
|
/// Return true if this is backed by a FIPS-approved implementation.
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An error indicating that the AEAD algorithm does not support the requested operation.
|
/// An error indicating that the AEAD algorithm does not support the requested operation.
|
||||||
|
|
|
@ -18,6 +18,11 @@ pub trait Hash: Send + Sync {
|
||||||
|
|
||||||
/// Which hash function this is, eg, `HashAlgorithm::SHA256`.
|
/// Which hash function this is, eg, `HashAlgorithm::SHA256`.
|
||||||
fn algorithm(&self) -> HashAlgorithm;
|
fn algorithm(&self) -> HashAlgorithm;
|
||||||
|
|
||||||
|
/// Return true if this is backed by a FIPS-approved implementation.
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A hash output, stored as a value.
|
/// A hash output, stored as a value.
|
||||||
|
|
|
@ -12,6 +12,11 @@ pub trait Hmac: Send + Sync {
|
||||||
|
|
||||||
/// Give the length of the underlying hash function. In RFC2104 terminology this is `L`.
|
/// Give the length of the underlying hash function. In RFC2104 terminology this is `L`.
|
||||||
fn hash_output_len(&self) -> usize;
|
fn hash_output_len(&self) -> usize;
|
||||||
|
|
||||||
|
/// Return true if this is backed by a FIPS-approved implementation.
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A HMAC tag, stored as a value.
|
/// A HMAC tag, stored as a value.
|
||||||
|
|
|
@ -186,6 +186,21 @@ pub struct CryptoProvider {
|
||||||
pub key_provider: &'static dyn KeyProvider,
|
pub key_provider: &'static dyn KeyProvider,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CryptoProvider {
|
||||||
|
/// Returns if this `CryptoProvider` is operating in FIPS mode.
|
||||||
|
pub fn fips_mode(&self) -> bool {
|
||||||
|
self.cipher_suites
|
||||||
|
.iter()
|
||||||
|
.all(|cs| cs.fips_mode())
|
||||||
|
&& self
|
||||||
|
.kx_groups
|
||||||
|
.iter()
|
||||||
|
.all(|kx| kx.fips_mode())
|
||||||
|
&& self.secure_random.fips_mode()
|
||||||
|
&& self.key_provider.fips_mode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A source of cryptographically secure randomness.
|
/// A source of cryptographically secure randomness.
|
||||||
pub trait SecureRandom: Send + Sync + Debug {
|
pub trait SecureRandom: Send + Sync + Debug {
|
||||||
/// Fill the given buffer with random bytes.
|
/// Fill the given buffer with random bytes.
|
||||||
|
@ -199,6 +214,11 @@ pub trait SecureRandom: Send + Sync + Debug {
|
||||||
/// an ephemeral key exchange key, but this is not included in the interface with
|
/// an ephemeral key exchange key, but this is not included in the interface with
|
||||||
/// rustls: it is assumed that the cryptography library provides for this itself.
|
/// rustls: it is assumed that the cryptography library provides for this itself.
|
||||||
fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed>;
|
fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed>;
|
||||||
|
|
||||||
|
/// Return true if this is backed by a FIPS-approved implementation.
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mechanism for loading private [SigningKey]s from [PrivateKeyDer].
|
/// A mechanism for loading private [SigningKey]s from [PrivateKeyDer].
|
||||||
|
@ -214,6 +234,14 @@ pub trait KeyProvider: Send + Sync + Debug {
|
||||||
&self,
|
&self,
|
||||||
key_der: PrivateKeyDer<'static>,
|
key_der: PrivateKeyDer<'static>,
|
||||||
) -> Result<Arc<dyn SigningKey>, Error>;
|
) -> Result<Arc<dyn SigningKey>, Error>;
|
||||||
|
|
||||||
|
/// Return true if this is backed by a FIPS-approved implementation.
|
||||||
|
///
|
||||||
|
/// If this returns true, that must be the case for all possible key types
|
||||||
|
/// supported by [`load_private_key()`].
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A supported key exchange group.
|
/// A supported key exchange group.
|
||||||
|
@ -240,6 +268,11 @@ pub trait SupportedKxGroup: Send + Sync + Debug {
|
||||||
/// If the `NamedGroup` enum does not have a name for the algorithm you are implementing,
|
/// If the `NamedGroup` enum does not have a name for the algorithm you are implementing,
|
||||||
/// you can use [`NamedGroup::Unknown`].
|
/// you can use [`NamedGroup::Unknown`].
|
||||||
fn name(&self) -> NamedGroup;
|
fn name(&self) -> NamedGroup;
|
||||||
|
|
||||||
|
/// Return true if this is backed by a FIPS-approved implementation.
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An in-progress key exchange originating from a [`SupportedKxGroup`].
|
/// An in-progress key exchange originating from a [`SupportedKxGroup`].
|
||||||
|
|
|
@ -29,6 +29,10 @@ impl crypto::hash::Hash for Hash {
|
||||||
fn algorithm(&self) -> HashAlgorithm {
|
fn algorithm(&self) -> HashAlgorithm {
|
||||||
self.1
|
self.1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
super::fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Context(digest::Context);
|
struct Context(digest::Context);
|
||||||
|
|
|
@ -23,6 +23,10 @@ impl crypto::hmac::Hmac for Hmac {
|
||||||
fn hash_output_len(&self) -> usize {
|
fn hash_output_len(&self) -> usize {
|
||||||
self.0.digest_algorithm().output_len()
|
self.0.digest_algorithm().output_len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
super::fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Key(ring_like::hmac::Key);
|
struct Key(ring_like::hmac::Key);
|
||||||
|
|
|
@ -44,6 +44,10 @@ impl SupportedKxGroup for KxGroup {
|
||||||
fn name(&self) -> NamedGroup {
|
fn name(&self) -> NamedGroup {
|
||||||
self.name
|
self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
super::fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for KxGroup {
|
impl fmt::Debug for KxGroup {
|
||||||
|
|
|
@ -205,3 +205,7 @@ mod ring_shim {
|
||||||
/// AEAD algorithm that is used by `mod ticketer`.
|
/// AEAD algorithm that is used by `mod ticketer`.
|
||||||
pub(super) static TICKETER_AEAD: &'static ring_like::aead::Algorithm =
|
pub(super) static TICKETER_AEAD: &'static ring_like::aead::Algorithm =
|
||||||
&ring_like::aead::CHACHA20_POLY1305;
|
&ring_like::aead::CHACHA20_POLY1305;
|
||||||
|
|
||||||
|
pub(super) fn fips_mode() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
|
@ -177,6 +177,10 @@ impl crate::quic::Algorithm for KeyBuilder {
|
||||||
fn aead_key_len(&self) -> usize {
|
fn aead_key_len(&self) -> usize {
|
||||||
self.0.key_len()
|
self.0.key_len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
super::fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -173,6 +173,10 @@ impl Tls12AeadAlgorithm for GcmAlgorithm {
|
||||||
iv: gcm_iv(write_iv, explicit),
|
iv: gcm_iv(write_iv, explicit),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
super::fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct ChaCha20Poly1305;
|
pub(crate) struct ChaCha20Poly1305;
|
||||||
|
@ -219,6 +223,10 @@ impl Tls12AeadAlgorithm for ChaCha20Poly1305 {
|
||||||
iv: Iv::new(iv[..].try_into().unwrap()),
|
iv: Iv::new(iv[..].try_into().unwrap()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false // not fips approved
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `MessageEncrypter` for AES-GCM AEAD ciphersuites. TLS 1.2 only.
|
/// A `MessageEncrypter` for AES-GCM AEAD ciphersuites. TLS 1.2 only.
|
||||||
|
|
|
@ -94,6 +94,10 @@ impl Tls13AeadAlgorithm for Chacha20Poly1305Aead {
|
||||||
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
|
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
|
||||||
Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv })
|
Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false // chacha20poly1305 not FIPS approved
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Aes256GcmAead(AeadAlgorithm);
|
struct Aes256GcmAead(AeadAlgorithm);
|
||||||
|
@ -118,6 +122,10 @@ impl Tls13AeadAlgorithm for Aes256GcmAead {
|
||||||
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
|
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
|
||||||
Ok(ConnectionTrafficSecrets::Aes256Gcm { key, iv })
|
Ok(ConnectionTrafficSecrets::Aes256Gcm { key, iv })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
super::fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Aes128GcmAead(AeadAlgorithm);
|
struct Aes128GcmAead(AeadAlgorithm);
|
||||||
|
@ -142,6 +150,10 @@ impl Tls13AeadAlgorithm for Aes128GcmAead {
|
||||||
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
|
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
|
||||||
Ok(ConnectionTrafficSecrets::Aes128Gcm { key, iv })
|
Ok(ConnectionTrafficSecrets::Aes128Gcm { key, iv })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
super::fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// common encrypter/decrypter/key_len items for above Tls13AeadAlgorithm impls
|
// common encrypter/decrypter/key_len items for above Tls13AeadAlgorithm impls
|
||||||
|
@ -263,6 +275,10 @@ impl Hkdf for RingHkdf {
|
||||||
fn hmac_sign(&self, key: &OkmBlock, message: &[u8]) -> crypto::hmac::Tag {
|
fn hmac_sign(&self, key: &OkmBlock, message: &[u8]) -> crypto::hmac::Tag {
|
||||||
crypto::hmac::Tag::new(hmac::sign(&hmac::Key::new(self.1, key.as_ref()), message).as_ref())
|
crypto::hmac::Tag::new(hmac::sign(&hmac::Key::new(self.1, key.as_ref()), message).as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
super::fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RingHkdfExpander {
|
struct RingHkdfExpander {
|
||||||
|
|
|
@ -63,6 +63,11 @@ pub trait Prf: Send + Sync {
|
||||||
///
|
///
|
||||||
/// The caller guarantees that `secret`, `label`, and `seed` are non-empty.
|
/// The caller guarantees that `secret`, `label`, and `seed` are non-empty.
|
||||||
fn for_secret(&self, output: &mut [u8], secret: &[u8], label: &[u8], seed: &[u8]);
|
fn for_secret(&self, output: &mut [u8], secret: &[u8], label: &[u8], seed: &[u8]);
|
||||||
|
|
||||||
|
/// Return true if this is backed by a FIPS-approved implementation.
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn prf(out: &mut [u8], hmac_key: &dyn hmac::Key, label: &[u8], seed: &[u8]) {
|
pub(crate) fn prf(out: &mut [u8], hmac_key: &dyn hmac::Key, label: &[u8], seed: &[u8]) {
|
||||||
|
|
|
@ -176,6 +176,11 @@ pub trait Hkdf: Send + Sync {
|
||||||
/// See [RFC2104](https://datatracker.ietf.org/doc/html/rfc2104) for the
|
/// See [RFC2104](https://datatracker.ietf.org/doc/html/rfc2104) for the
|
||||||
/// definition of HMAC.
|
/// definition of HMAC.
|
||||||
fn hmac_sign(&self, key: &OkmBlock, message: &[u8]) -> hmac::Tag;
|
fn hmac_sign(&self, key: &OkmBlock, message: &[u8]) -> hmac::Tag;
|
||||||
|
|
||||||
|
/// Return true if this is backed by a FIPS-approved implementation.
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `HKDF-Expand(PRK, info, L)` to construct any type from a byte array.
|
/// `HKDF-Expand(PRK, info, L)` to construct any type from a byte array.
|
||||||
|
|
|
@ -584,6 +584,11 @@ pub trait Algorithm: Send + Sync {
|
||||||
///
|
///
|
||||||
/// This controls the size of `AeadKey`s presented to `packet_key()` and `header_protection_key()`.
|
/// This controls the size of `AeadKey`s presented to `packet_key()` and `header_protection_key()`.
|
||||||
fn aead_key_len(&self) -> usize;
|
fn aead_key_len(&self) -> usize;
|
||||||
|
|
||||||
|
/// Whether this algorithm is FIPS-approved.
|
||||||
|
fn fips_mode(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A QUIC header protection key
|
/// A QUIC header protection key
|
||||||
|
|
|
@ -387,6 +387,12 @@ impl ServerConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return true if connections made with this `ServerConfig` will
|
||||||
|
/// operate in FIPS mode.
|
||||||
|
pub fn fips_mode(&self) -> bool {
|
||||||
|
self.provider.fips_mode()
|
||||||
|
}
|
||||||
|
|
||||||
/// We support a given TLS version if it's quoted in the configured
|
/// We support a given TLS version if it's quoted in the configured
|
||||||
/// versions *and* at least one ciphersuite for this version is
|
/// versions *and* at least one ciphersuite for this version is
|
||||||
/// also configured.
|
/// also configured.
|
||||||
|
|
|
@ -41,6 +41,15 @@ pub struct CipherSuiteCommon {
|
||||||
pub integrity_limit: u64,
|
pub integrity_limit: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CipherSuiteCommon {
|
||||||
|
/// Return true if this is backed by a FIPS-approved implementation.
|
||||||
|
///
|
||||||
|
/// This means all the constituent parts that do cryptography return true for `fips_mode()`.
|
||||||
|
pub fn fips_mode(&self) -> bool {
|
||||||
|
self.hash_provider.fips_mode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A cipher suite supported by rustls.
|
/// A cipher suite supported by rustls.
|
||||||
///
|
///
|
||||||
/// This type carries both configuration and implementation. Compare with
|
/// This type carries both configuration and implementation. Compare with
|
||||||
|
@ -117,6 +126,15 @@ impl SupportedCipherSuite {
|
||||||
.is_some(),
|
.is_some(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return true if this is backed by a FIPS-approved implementation.
|
||||||
|
pub fn fips_mode(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
Self::Tls12(cs) => cs.fips_mode(),
|
||||||
|
Self::Tls13(cs) => cs.fips_mode(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for SupportedCipherSuite {
|
impl fmt::Debug for SupportedCipherSuite {
|
||||||
|
|
|
@ -62,6 +62,13 @@ impl Tls12CipherSuite {
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return true if this is backed by a FIPS-approved implementation.
|
||||||
|
///
|
||||||
|
/// This means all the constituent parts that do cryptography return true for `fips_mode()`.
|
||||||
|
pub fn fips_mode(&self) -> bool {
|
||||||
|
self.common.fips_mode() && self.prf_provider.fips_mode() && self.aead_alg.fips_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&'static Tls12CipherSuite> for SupportedCipherSuite {
|
impl From<&'static Tls12CipherSuite> for SupportedCipherSuite {
|
||||||
|
|
|
@ -42,6 +42,19 @@ impl Tls13CipherSuite {
|
||||||
(prev.common.hash_provider.algorithm() == self.common.hash_provider.algorithm())
|
(prev.common.hash_provider.algorithm() == self.common.hash_provider.algorithm())
|
||||||
.then(|| prev)
|
.then(|| prev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return true if this is backed by a FIPS-approved implementation.
|
||||||
|
///
|
||||||
|
/// This means all the constituent parts that do cryptography return true for `fips_mode()`.
|
||||||
|
pub fn fips_mode(&self) -> bool {
|
||||||
|
self.common.fips_mode()
|
||||||
|
&& self.hkdf_provider.fips_mode()
|
||||||
|
&& self.aead_alg.fips_mode()
|
||||||
|
&& self
|
||||||
|
.quic
|
||||||
|
.map(|q| q.fips_mode())
|
||||||
|
.unwrap_or(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&'static Tls13CipherSuite> for SupportedCipherSuite {
|
impl From<&'static Tls13CipherSuite> for SupportedCipherSuite {
|
||||||
|
|
|
@ -5707,3 +5707,27 @@ fn test_client_removes_tls12_session_if_server_sends_undecryptable_first_message
|
||||||
ClientStorageOp::RemoveTls12Session(_)
|
ClientStorageOp::RemoveTls12Session(_)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ring")]
|
||||||
|
#[test]
|
||||||
|
fn test_client_fips_service_indicator() {
|
||||||
|
assert_eq!(make_client_config(KeyType::Rsa).fips_mode(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ring")]
|
||||||
|
#[test]
|
||||||
|
fn test_server_fips_service_indicator() {
|
||||||
|
assert_eq!(make_server_config(KeyType::Rsa).fips_mode(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(not(feature = "ring"), feature = "aws_lc_rs"))]
|
||||||
|
#[test]
|
||||||
|
fn test_client_fips_service_indicator() {
|
||||||
|
assert_eq!(make_client_config(KeyType::Rsa).fips_mode(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(not(feature = "ring"), feature = "aws_lc_rs"))]
|
||||||
|
#[test]
|
||||||
|
fn test_server_fips_service_indicator() {
|
||||||
|
assert_eq!(make_server_config(KeyType::Rsa).fips_mode(), true);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue