mirror of
https://github.com/signalapp/libsignal.git
synced 2024-09-19 19:42:19 +02:00
protocol: Remove legacy SSv2 receive support
This commit is contained in:
parent
192fbbd2a9
commit
2dd3896bba
@ -68,8 +68,7 @@ pub use ratchet::{
|
||||
};
|
||||
pub use sealed_sender::{
|
||||
sealed_sender_decrypt, sealed_sender_decrypt_to_usmc, sealed_sender_encrypt,
|
||||
sealed_sender_encrypt_from_usmc, sealed_sender_multi_recipient_encrypt,
|
||||
sealed_sender_multi_recipient_encrypt_using_legacy_ephemeral_key_derivation, ContentHint,
|
||||
sealed_sender_encrypt_from_usmc, sealed_sender_multi_recipient_encrypt, ContentHint,
|
||||
SealedSenderDecryptionResult, SealedSenderV2SentMessage, SealedSenderV2SentMessageRecipient,
|
||||
SenderCertificate, ServerCertificate, UnidentifiedSenderMessageContent,
|
||||
};
|
||||
|
@ -15,7 +15,6 @@ use crate::{crypto, curve, proto, session_cipher};
|
||||
use aes_gcm_siv::aead::generic_array::typenum::Unsigned;
|
||||
use aes_gcm_siv::{AeadInPlace, Aes256GcmSiv, KeyInit};
|
||||
use arrayref::array_ref;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
use indexmap::IndexMap;
|
||||
use itertools::Itertools;
|
||||
use prost::Message;
|
||||
@ -916,7 +915,6 @@ mod sealed_sender_v2 {
|
||||
|
||||
// Static byte strings used as part of a MAC in HKDF.
|
||||
const LABEL_R: &[u8] = b"Sealed Sender v2: r (2023-08)";
|
||||
const LABEL_R_LEGACY: &[u8] = b"Sealed Sender v2: r";
|
||||
const LABEL_K: &[u8] = b"Sealed Sender v2: K";
|
||||
const LABEL_DH: &[u8] = b"Sealed Sender v2: DH";
|
||||
const LABEL_DH_S: &[u8] = b"Sealed Sender v2: DH-sender";
|
||||
@ -926,9 +924,6 @@ mod sealed_sender_v2 {
|
||||
<Aes256GcmSiv as aes_gcm_siv::aead::KeySizeUser>::KeySize::USIZE;
|
||||
pub const AUTH_TAG_LEN: usize = 16;
|
||||
|
||||
// Change this to false after all clients have receive support.
|
||||
pub const USE_LEGACY_EPHEMERAL_KEY_DERIVATION_FOR_ENCRYPT: bool = false;
|
||||
|
||||
/// An asymmetric and a symmetric cipher key.
|
||||
pub(super) struct DerivedKeys {
|
||||
kdf: hkdf::Hkdf<sha2::Sha256>,
|
||||
@ -952,17 +947,6 @@ mod sealed_sender_v2 {
|
||||
KeyPair::try_from(e).expect("can derive public key")
|
||||
}
|
||||
|
||||
/// Derive the ephemeral asymmetric keys using the legacy implementation.
|
||||
pub(super) fn derive_e_legacy(&self) -> KeyPair {
|
||||
let mut r = [0; 64];
|
||||
self.kdf
|
||||
.expand(LABEL_R_LEGACY, &mut r)
|
||||
.expect("valid output length");
|
||||
let e_raw = Scalar::from_bytes_mod_order_wide(&r);
|
||||
let e = PrivateKey::try_from(&e_raw.as_bytes()[..]).expect("valid PrivateKey");
|
||||
KeyPair::try_from(e).expect("can derive public key")
|
||||
}
|
||||
|
||||
/// Derive the symmetric cipher key.
|
||||
pub(super) fn derive_k(&self) -> [u8; CIPHER_KEY_LEN] {
|
||||
let mut k = [0; CIPHER_KEY_LEN];
|
||||
@ -1277,34 +1261,6 @@ where
|
||||
usmc,
|
||||
identity_store,
|
||||
rng,
|
||||
sealed_sender_v2::USE_LEGACY_EPHEMERAL_KEY_DERIVATION_FOR_ENCRYPT,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// For testing only.
|
||||
pub async fn sealed_sender_multi_recipient_encrypt_using_legacy_ephemeral_key_derivation<
|
||||
R: Rng + CryptoRng,
|
||||
X: IntoIterator<Item = ServiceId>,
|
||||
>(
|
||||
destinations: &[&ProtocolAddress],
|
||||
destination_sessions: &[&SessionRecord],
|
||||
excluded_recipients: X,
|
||||
usmc: &UnidentifiedSenderMessageContent,
|
||||
identity_store: &dyn IdentityKeyStore,
|
||||
rng: &mut R,
|
||||
) -> Result<Vec<u8>>
|
||||
where
|
||||
X::IntoIter: ExactSizeIterator,
|
||||
{
|
||||
sealed_sender_multi_recipient_encrypt_impl(
|
||||
destinations,
|
||||
destination_sessions,
|
||||
excluded_recipients,
|
||||
usmc,
|
||||
identity_store,
|
||||
rng,
|
||||
false,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@ -1319,7 +1275,6 @@ async fn sealed_sender_multi_recipient_encrypt_impl<
|
||||
usmc: &UnidentifiedSenderMessageContent,
|
||||
identity_store: &dyn IdentityKeyStore,
|
||||
rng: &mut R,
|
||||
should_use_legacy_ephemeral_key_derivation: bool,
|
||||
) -> Result<Vec<u8>>
|
||||
where
|
||||
X::IntoIter: ExactSizeIterator,
|
||||
@ -1335,11 +1290,7 @@ where
|
||||
|
||||
let m: [u8; sealed_sender_v2::MESSAGE_KEY_LEN] = rng.gen();
|
||||
let keys = sealed_sender_v2::DerivedKeys::new(&m);
|
||||
let e = if should_use_legacy_ephemeral_key_derivation {
|
||||
keys.derive_e_legacy()
|
||||
} else {
|
||||
keys.derive_e()
|
||||
};
|
||||
let e = keys.derive_e();
|
||||
let e_pub = &e.public_key;
|
||||
|
||||
// Encrypt the shared ciphertext using AES-GCM-SIV.
|
||||
@ -1885,18 +1836,7 @@ pub async fn sealed_sender_decrypt_to_usmc(
|
||||
)?;
|
||||
|
||||
let keys = sealed_sender_v2::DerivedKeys::new(&m);
|
||||
// It is okay that this is not constant time; the only information revealed is whether
|
||||
// the sender is using the new or old derivation for the ephemeral key, combined with
|
||||
// which key the receiver tried first.
|
||||
let mut derive_first_key: fn(_) -> _ = sealed_sender_v2::DerivedKeys::derive_e;
|
||||
let mut derive_second_key: fn(_) -> _ = sealed_sender_v2::DerivedKeys::derive_e_legacy;
|
||||
if sealed_sender_v2::USE_LEGACY_EPHEMERAL_KEY_DERIVATION_FOR_ENCRYPT {
|
||||
std::mem::swap(&mut derive_first_key, &mut derive_second_key);
|
||||
}
|
||||
|
||||
if !bool::from(derive_first_key(&keys).public_key.ct_eq(&ephemeral_public))
|
||||
&& !bool::from(derive_second_key(&keys).public_key.ct_eq(&ephemeral_public))
|
||||
{
|
||||
if !bool::from(keys.derive_e().public_key.ct_eq(&ephemeral_public)) {
|
||||
return Err(SignalProtocolError::InvalidSealedSenderMessage(
|
||||
"derived ephemeral key did not match key provided in message".to_string(),
|
||||
));
|
||||
|
@ -661,119 +661,6 @@ fn test_sealed_sender_multi_recipient() -> Result<(), SignalProtocolError> {
|
||||
.expect("sync")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sealed_sender_multi_recipient_legacy_derivation() -> Result<(), SignalProtocolError> {
|
||||
async {
|
||||
let mut rng = OsRng;
|
||||
|
||||
let alice_device_id: DeviceId = 23.into();
|
||||
let bob_device_id: DeviceId = 42.into();
|
||||
|
||||
let alice_e164 = "+14151111111".to_owned();
|
||||
let bob_e164 = "+14151114444".to_owned();
|
||||
|
||||
let alice_uuid = "9d0652a3-dcc3-4d11-975f-74d61598733f".to_string();
|
||||
let bob_uuid = "796abedb-ca4e-4f18-8803-1fde5b921f9f".to_string();
|
||||
|
||||
let bob_uuid_address = ProtocolAddress::new(bob_uuid.clone(), bob_device_id);
|
||||
|
||||
let mut alice_store = support::test_in_memory_protocol_store()?;
|
||||
let mut bob_store = support::test_in_memory_protocol_store()?;
|
||||
|
||||
let alice_pubkey = *alice_store.get_identity_key_pair().await?.public_key();
|
||||
|
||||
let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut rng).await?;
|
||||
|
||||
process_prekey_bundle(
|
||||
&bob_uuid_address,
|
||||
&mut alice_store.session_store,
|
||||
&mut alice_store.identity_store,
|
||||
&bob_pre_key_bundle,
|
||||
SystemTime::now(),
|
||||
&mut rng,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let trust_root = KeyPair::generate(&mut rng);
|
||||
let server_key = KeyPair::generate(&mut rng);
|
||||
|
||||
let server_cert =
|
||||
ServerCertificate::new(1, server_key.public_key, &trust_root.private_key, &mut rng)?;
|
||||
|
||||
let expires = Timestamp::from_epoch_millis(1605722925);
|
||||
|
||||
let sender_cert = SenderCertificate::new(
|
||||
alice_uuid.clone(),
|
||||
Some(alice_e164.clone()),
|
||||
alice_pubkey,
|
||||
alice_device_id,
|
||||
expires,
|
||||
server_cert,
|
||||
&server_key.private_key,
|
||||
&mut rng,
|
||||
)?;
|
||||
|
||||
let alice_ptext = vec![1, 2, 3, 23, 99];
|
||||
let alice_message = message_encrypt(
|
||||
&alice_ptext,
|
||||
&bob_uuid_address,
|
||||
&mut alice_store.session_store,
|
||||
&mut alice_store.identity_store,
|
||||
SystemTime::now(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let alice_usmc = UnidentifiedSenderMessageContent::new(
|
||||
alice_message.message_type(),
|
||||
sender_cert.clone(),
|
||||
alice_message.serialize().to_vec(),
|
||||
ContentHint::Default,
|
||||
None,
|
||||
)?;
|
||||
|
||||
let recipients = [&bob_uuid_address];
|
||||
let alice_ctext =
|
||||
sealed_sender_multi_recipient_encrypt_using_legacy_ephemeral_key_derivation(
|
||||
&recipients,
|
||||
&alice_store
|
||||
.session_store
|
||||
.load_existing_sessions(&recipients)?,
|
||||
[],
|
||||
&alice_usmc,
|
||||
&alice_store.identity_store,
|
||||
&mut rng,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let (recipient_addr, bob_ctext) = extract_single_ssv2_received_message(&alice_ctext);
|
||||
assert_eq!(recipient_addr.service_id_string(), bob_uuid);
|
||||
|
||||
let bob_ptext = sealed_sender_decrypt(
|
||||
&bob_ctext,
|
||||
&trust_root.public_key,
|
||||
expires.sub_millis(1),
|
||||
Some(bob_e164.clone()),
|
||||
bob_uuid.clone(),
|
||||
bob_device_id,
|
||||
&mut bob_store.identity_store,
|
||||
&mut bob_store.session_store,
|
||||
&mut bob_store.pre_key_store,
|
||||
&bob_store.signed_pre_key_store,
|
||||
&mut bob_store.kyber_pre_key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_eq!(bob_ptext.message, alice_ptext);
|
||||
assert_eq!(bob_ptext.sender_uuid, alice_uuid);
|
||||
assert_eq!(bob_ptext.sender_e164, Some(alice_e164));
|
||||
assert_eq!(bob_ptext.device_id, alice_device_id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
.now_or_never()
|
||||
.expect("sync")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sealed_sender_multi_recipient_encrypt_with_archived_session(
|
||||
) -> Result<(), SignalProtocolError> {
|
||||
|
Loading…
Reference in New Issue
Block a user