use crate::{
ciphersuite::Secret, test_utils::*, tree::secret_tree::SecretTreeError, tree::sender_ratchet::*,
};
#[openmls_test::openmls_test]
fn test_max_forward_distance() {
let provider = &Provider::default();
let configuration = &SenderRatchetConfiguration::default();
let secret = Secret::random(ciphersuite, provider.rand()).expect("Not enough randomness.");
let mut ratchet1 = DecryptionRatchet::new(secret.clone());
let mut ratchet2 = DecryptionRatchet::new(secret);
let _secret = ratchet1
.secret_for_decryption(
ciphersuite,
provider.crypto(),
configuration.maximum_forward_distance(),
configuration,
)
.expect("Expected decryption secret.");
let err = ratchet2
.secret_for_decryption(
ciphersuite,
provider.crypto(),
configuration.maximum_forward_distance() + 1,
configuration,
)
.expect_err("Expected error.");
assert_eq!(err, SecretTreeError::TooDistantInTheFuture);
ratchet1.ratchet_secret_mut().set_generation(u32::MAX - 5);
ratchet1
.secret_for_decryption(ciphersuite, provider.crypto(), u32::MAX - 1, configuration)
.expect("Error ratcheting to very high generation");
}
#[openmls_test::openmls_test]
fn test_out_of_order_generations() {
let provider = &Provider::default();
let configuration = &SenderRatchetConfiguration::default();
let secret = Secret::random(ciphersuite, provider.rand()).expect("Not enough randomness.");
let mut ratchet1 = DecryptionRatchet::new(secret);
for i in 0..configuration.out_of_order_tolerance() * 2 {
let _secret = ratchet1
.secret_for_decryption(ciphersuite, provider.crypto(), i, configuration)
.expect("Expected decryption secret.");
}
let err = ratchet1
.secret_for_decryption(
ciphersuite,
provider.crypto(),
configuration.out_of_order_tolerance() - 1,
configuration,
)
.expect_err("Expected error.");
assert_eq!(err, SecretTreeError::TooDistantInThePast);
for i in configuration.out_of_order_tolerance()..configuration.out_of_order_tolerance() * 2 {
assert_eq!(
ratchet1
.secret_for_decryption(ciphersuite, provider.crypto(), i, configuration)
.expect_err("Expected decryption secret."),
SecretTreeError::SecretReuseError
);
}
}
#[openmls_test::openmls_test]
fn test_forward_secrecy() {
let provider = &Provider::default();
let configuration = &SenderRatchetConfiguration::default();
let secret = Secret::random(ciphersuite, provider.rand()).expect("Not enough randomness.");
let mut ratchet = DecryptionRatchet::new(secret);
let _ratchet_secrets = ratchet
.secret_for_decryption(ciphersuite, provider.crypto(), 0, configuration)
.expect("Error ratcheting forward.");
assert_eq!(ratchet.generation(), 1);
let err = ratchet
.secret_for_decryption(ciphersuite, provider.crypto(), 0, configuration)
.expect_err("No error when trying to retrieve key outside of tolerance window.");
assert_eq!(err, SecretTreeError::SecretReuseError);
let _ratchet_secrets = ratchet
.secret_for_decryption(ciphersuite, provider.crypto(), 10, configuration)
.expect("Error ratcheting forward.");
let err = ratchet
.secret_for_decryption(ciphersuite, provider.crypto(), 5, configuration)
.expect_err("No error when trying to retrieve key outside of tolerance window.");
assert_eq!(err, SecretTreeError::TooDistantInThePast);
for generation in 10 - configuration.out_of_order_tolerance() + 1..10 {
let keys = ratchet.secret_for_decryption(
ciphersuite,
provider.crypto(),
generation,
configuration,
);
assert!(keys.is_ok());
let err = ratchet
.secret_for_decryption(ciphersuite, provider.crypto(), generation, configuration)
.expect_err("No error when trying to retrieve deleted key.");
assert_eq!(err, SecretTreeError::SecretReuseError);
}
}
#[test]
fn sender_ratchet_generation_overflow() {
let provider = OpenMlsRustCrypto::default();
let ciphersuite = Ciphersuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519;
let secret = Secret::random(ciphersuite, provider.rand()).expect("Not enough randomness.");
let mut ratchet = RatchetSecret::initial_ratchet_secret(secret);
ratchet.set_generation(u32::MAX - 1);
let _ = ratchet
.ratchet_forward(provider.crypto(), ciphersuite)
.expect("error ratcheting forward");
let err = ratchet
.ratchet_forward(provider.crypto(), ciphersuite)
.expect_err("no error exceeding generation u32::MAX");
assert_eq!(err, SecretTreeError::RatchetTooLong)
}