diff --git a/.cargo/config.toml b/.cargo/config.toml index 2dc4a5047..ecf3467b1 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -14,4 +14,8 @@ rustflags = ["-C", "link-args=-ObjC"] rustflags = ["-C", "link-args=-ObjC"] [target.aarch64-apple-ios-sim] -rustflags = ["-C", "link-args=-ObjC"] \ No newline at end of file +rustflags = ["-C", "link-args=-ObjC"] + +[env] +# DO not merge! WIP change to for custom webrtc-sys build +LK_CUSTOM_WEBRTC = { value = "webrtc-sys/libwebrtc/linux-x64-release", relative = true } diff --git a/libwebrtc/src/native/frame_cryptor.rs b/libwebrtc/src/native/frame_cryptor.rs index f6fdf33bf..0a076bf9a 100644 --- a/libwebrtc/src/native/frame_cryptor.rs +++ b/libwebrtc/src/native/frame_cryptor.rs @@ -25,12 +25,29 @@ use crate::{ pub type OnStateChange = Box; +#[derive(Copy, Clone, Debug)] +#[non_exhaustive] +pub enum KeyDerivationAlgorithm { + PBKDF2, + HKDF, +} +impl Into for KeyDerivationAlgorithm { + fn into(self) -> sys_fc::ffi::KeyDerivationAlgorithm { + match self { + KeyDerivationAlgorithm::PBKDF2 => sys_fc::ffi::KeyDerivationAlgorithm::PBKDF2, + KeyDerivationAlgorithm::HKDF => sys_fc::ffi::KeyDerivationAlgorithm::HKDF, + } + } +} + #[derive(Debug, Clone)] pub struct KeyProviderOptions { pub shared_key: bool, pub ratchet_window_size: i32, pub ratchet_salt: Vec, pub failure_tolerance: i32, + pub key_ring_size: i32, + pub key_derivation_algorithm: KeyDerivationAlgorithm, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -272,6 +289,8 @@ impl From for sys_fc::ffi::KeyProviderOptions { ratchet_window_size: value.ratchet_window_size, ratchet_salt: value.ratchet_salt, failure_tolerance: value.failure_tolerance, + key_ring_size: value.key_ring_size, + key_derivation_algorithm: value.key_derivation_algorithm.into(), } } } diff --git a/livekit-ffi/protocol/e2ee.proto b/livekit-ffi/protocol/e2ee.proto index bb693341d..3b2192a07 100644 --- a/livekit-ffi/protocol/e2ee.proto +++ b/livekit-ffi/protocol/e2ee.proto @@ -38,6 +38,13 @@ message KeyProviderOptions { required int32 ratchet_window_size = 2; required bytes ratchet_salt = 3; required int32 failure_tolerance = 4; // -1 = no tolerance + required int32 key_ring_size = 5; + required KeyDerivationFunction key_derivation_function = 6; +} + +enum KeyDerivationFunction { + PBKDF2 = 0; + HKDF = 1; } message E2eeOptions { diff --git a/livekit-ffi/src/conversion/room.rs b/livekit-ffi/src/conversion/room.rs index 87ee00a14..0bcf6392f 100644 --- a/livekit-ffi/src/conversion/room.rs +++ b/livekit-ffi/src/conversion/room.rs @@ -21,7 +21,7 @@ use livekit::{ options::{AudioEncoding, TrackPublishOptions, VideoEncoding}, prelude::*, webrtc::{ - native::frame_cryptor::EncryptionState, + native::frame_cryptor::{EncryptionState, KeyDerivationAlgorithm}, prelude::{ContinualGatheringPolicy, IceServer, IceTransportsType, RtcConfiguration}, }, RoomInfo, @@ -108,10 +108,22 @@ impl From for proto::DisconnectReason { impl From for KeyProviderOptions { fn from(value: proto::KeyProviderOptions) -> Self { + let key_derivation_algorithm = value.key_derivation_function().into(); Self { ratchet_window_size: value.ratchet_window_size, ratchet_salt: value.ratchet_salt, failure_tolerance: value.failure_tolerance, + key_ring_size: value.key_ring_size, + key_derivation_algorithm, + } + } +} + +impl From for KeyDerivationAlgorithm { + fn from(value: proto::KeyDerivationFunction) -> Self { + match value { + proto::KeyDerivationFunction::Pbkdf2 => KeyDerivationAlgorithm::PBKDF2, + proto::KeyDerivationFunction::Hkdf => KeyDerivationAlgorithm::HKDF, } } } diff --git a/livekit/src/room/e2ee/key_provider.rs b/livekit/src/room/e2ee/key_provider.rs index 5140a4168..7902c76f3 100644 --- a/livekit/src/room/e2ee/key_provider.rs +++ b/livekit/src/room/e2ee/key_provider.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use libwebrtc::native::frame_cryptor as fc; +use libwebrtc::native::frame_cryptor::{self as fc, KeyDerivationAlgorithm}; use std::sync::{ atomic::{AtomicI32, Ordering}, Arc, @@ -23,12 +23,15 @@ use crate::id::ParticipantIdentity; const DEFAULT_RATCHET_SALT: &str = "LKFrameEncryptionKey"; const DEFAULT_RATCHET_WINDOW_SIZE: i32 = 16; const DEFAULT_FAILURE_TOLERANCE: i32 = -1; // no tolerance by default +const DEFAULT_KEY_RING_SIZE: i32 = 16; #[derive(Clone)] pub struct KeyProviderOptions { pub ratchet_window_size: i32, pub ratchet_salt: Vec, pub failure_tolerance: i32, + pub key_ring_size: i32, + pub key_derivation_algorithm: KeyDerivationAlgorithm, } impl Default for KeyProviderOptions { @@ -37,6 +40,8 @@ impl Default for KeyProviderOptions { ratchet_window_size: DEFAULT_RATCHET_WINDOW_SIZE, ratchet_salt: DEFAULT_RATCHET_SALT.to_owned().into_bytes(), failure_tolerance: DEFAULT_FAILURE_TOLERANCE, + key_ring_size: DEFAULT_KEY_RING_SIZE, + key_derivation_algorithm: KeyDerivationAlgorithm::PBKDF2, } } } @@ -56,6 +61,8 @@ impl KeyProvider { ratchet_window_size: options.ratchet_window_size, ratchet_salt: options.ratchet_salt, failure_tolerance: options.failure_tolerance, + key_ring_size: options.key_ring_size, + key_derivation_algorithm: options.key_derivation_algorithm, }), latest_key_index: Arc::new(AtomicI32::new(0)), } @@ -67,6 +74,8 @@ impl KeyProvider { ratchet_window_size: options.ratchet_window_size, ratchet_salt: options.ratchet_salt, failure_tolerance: options.failure_tolerance, + key_ring_size: options.key_ring_size, + key_derivation_algorithm: options.key_derivation_algorithm, }); handle.set_shared_key(0, shared_key); Self { handle, latest_key_index: Arc::new(AtomicI32::new(0)) } diff --git a/webrtc-sys/libwebrtc/.gclient b/webrtc-sys/libwebrtc/.gclient index 2cdc191a5..15d8bfbeb 100644 --- a/webrtc-sys/libwebrtc/.gclient +++ b/webrtc-sys/libwebrtc/.gclient @@ -1,7 +1,7 @@ solutions = [ { "name": 'src', - "url": 'https://github.com/webrtc-sdk/webrtc.git@m137_release', + "url": 'https://github.com/webrtc-sdk/webrtc.git@duan/hkdf-sha256-key-derivation', "custom_deps": {}, "deps_file": "DEPS", "managed": False, diff --git a/webrtc-sys/src/frame_cryptor.cpp b/webrtc-sys/src/frame_cryptor.cpp index cbbd10d0e..9ed50f38d 100644 --- a/webrtc-sys/src/frame_cryptor.cpp +++ b/webrtc-sys/src/frame_cryptor.cpp @@ -40,6 +40,19 @@ webrtc::FrameCryptorTransformer::Algorithm AlgorithmToFrameCryptorAlgorithm( } } +webrtc::KeyDerivationAlgorithm +KeyDerivationAlgorithmToFrameCryptorKeyDerivationAlgorithm( + KeyDerivationAlgorithm algorithm) { + switch (algorithm) { + case KeyDerivationAlgorithm::PBKDF2: + return webrtc::KeyDerivationAlgorithm::kPBKDF2; + case KeyDerivationAlgorithm::HKDF: + return webrtc::KeyDerivationAlgorithm::kHKDF; + default: + return webrtc::KeyDerivationAlgorithm::kPBKDF2; + } +} + KeyProvider::KeyProvider(KeyProviderOptions options) { webrtc::KeyProviderOptions rtc_options; rtc_options.shared_key = options.shared_key; @@ -51,7 +64,10 @@ KeyProvider::KeyProvider(KeyProviderOptions options) { rtc_options.ratchet_salt = ratchet_salt; rtc_options.ratchet_window_size = options.ratchet_window_size; rtc_options.failure_tolerance = options.failure_tolerance; - + rtc_options.key_ring_size = options.key_ring_size; + rtc_options.key_derivation_algorithm = + KeyDerivationAlgorithmToFrameCryptorKeyDerivationAlgorithm( + options.key_derivation_algorithm); impl_ = new rtc::RefCountedObject(rtc_options); } @@ -154,10 +170,12 @@ int32_t FrameCryptor::key_index() const { return e2ee_transformer_->key_index(); } -DataPacketCryptor::DataPacketCryptor(webrtc::FrameCryptorTransformer::Algorithm algorithm, - webrtc::scoped_refptr key_provider) +DataPacketCryptor::DataPacketCryptor( + webrtc::FrameCryptorTransformer::Algorithm algorithm, + webrtc::scoped_refptr key_provider) : data_packet_cryptor_( - webrtc::make_ref_counted(algorithm, key_provider)) {} + webrtc::make_ref_counted(algorithm, + key_provider)) {} EncryptedPacket DataPacketCryptor::encrypt_data_packet( const ::rust::String participant_id, @@ -167,12 +185,12 @@ EncryptedPacket DataPacketCryptor::encrypt_data_packet( std::copy(data.begin(), data.end(), std::back_inserter(data_vec)); auto result = data_packet_cryptor_->Encrypt( - std::string(participant_id.data(), participant_id.size()), - key_index, + std::string(participant_id.data(), participant_id.size()), key_index, data_vec); if (!result.ok()) { - throw std::runtime_error(std::string("Failed to encrypt data packet: ") + result.error().message()); + throw std::runtime_error(std::string("Failed to encrypt data packet: ") + + result.error().message()); } auto& packet = result.value(); @@ -202,20 +220,23 @@ rust::Vec<::std::uint8_t> DataPacketCryptor::decrypt_data_packet( std::copy(encrypted_packet.iv.begin(), encrypted_packet.iv.end(), std::back_inserter(iv_vec)); - auto native_encrypted_packet = webrtc::make_ref_counted( - std::move(data_vec), std::move(iv_vec), encrypted_packet.key_index); + auto native_encrypted_packet = + webrtc::make_ref_counted( + std::move(data_vec), std::move(iv_vec), encrypted_packet.key_index); auto result = data_packet_cryptor_->Decrypt( std::string(participant_id.data(), participant_id.size()), native_encrypted_packet); if (!result.ok()) { - throw std::runtime_error(std::string("Failed to decrypt data packet: ") + result.error().message()); + throw std::runtime_error(std::string("Failed to decrypt data packet: ") + + result.error().message()); } rust::Vec decrypted_data; auto& decrypted = result.value(); - std::copy(decrypted.begin(), decrypted.end(), std::back_inserter(decrypted_data)); + std::copy(decrypted.begin(), decrypted.end(), + std::back_inserter(decrypted_data)); return decrypted_data; } diff --git a/webrtc-sys/src/frame_cryptor.rs b/webrtc-sys/src/frame_cryptor.rs index 84095bfff..55774a0d2 100644 --- a/webrtc-sys/src/frame_cryptor.rs +++ b/webrtc-sys/src/frame_cryptor.rs @@ -25,6 +25,15 @@ pub mod ffi { pub ratchet_window_size: i32, pub ratchet_salt: Vec, pub failure_tolerance: i32, + pub key_ring_size: i32, + pub key_derivation_algorithm: KeyDerivationAlgorithm, + } + + #[derive(Debug)] + #[repr(i32)] + pub enum KeyDerivationAlgorithm { + PBKDF2 = 0, + HKDF, } #[derive(Debug)] @@ -249,6 +258,8 @@ mod tests { ratchet_window_size: 16, ratchet_salt: vec![], failure_tolerance: -1, + key_ring_size: 16, + key_derivation_algorithm: ffi::KeyDerivationAlgorithm::HKDF, }; let key_provider = ffi::new_key_provider(options);