Skip to main content

webrtc_sys/
frame_cryptor.rs

1// Copyright 2025 LiveKit, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::sync::Arc;
16
17use crate::impl_thread_safety;
18
19#[cxx::bridge(namespace = "livekit_ffi")]
20pub mod ffi {
21
22    #[derive(Debug)]
23    pub struct KeyProviderOptions {
24        pub shared_key: bool,
25        pub ratchet_window_size: i32,
26        pub ratchet_salt: Vec<u8>,
27        pub failure_tolerance: i32,
28        pub key_ring_size: i32,
29        pub key_derivation_algorithm: KeyDerivationAlgorithm,
30    }
31
32    #[derive(Debug)]
33    #[repr(i32)]
34    pub enum KeyDerivationAlgorithm {
35        PBKDF2 = 0,
36        HKDF,
37    }
38
39    #[derive(Debug)]
40    #[repr(i32)]
41    pub enum Algorithm {
42        AesGcm = 0,
43        AesCbc,
44    }
45
46    #[derive(Debug)]
47    #[repr(i32)]
48    pub enum FrameCryptionState {
49        New = 0,
50        Ok,
51        EncryptionFailed,
52        DecryptionFailed,
53        MissingKey,
54        KeyRatcheted,
55        InternalError,
56    }
57
58    #[derive(Debug)]
59    pub struct EncryptedPacket {
60        pub data: Vec<u8>,
61        pub iv: Vec<u8>,
62        pub key_index: u32,
63    }
64
65    unsafe extern "C++" {
66        include!("livekit/frame_cryptor.h");
67
68        pub type KeyProvider;
69
70        pub fn new_key_provider(options: KeyProviderOptions) -> SharedPtr<KeyProvider>;
71
72        pub fn set_shared_key(self: &KeyProvider, key_index: i32, key: Vec<u8>) -> bool;
73
74        pub fn ratchet_shared_key(self: &KeyProvider, key_index: i32) -> Result<Vec<u8>>;
75
76        pub fn get_shared_key(self: &KeyProvider, key_index: i32) -> Result<Vec<u8>>;
77
78        pub fn set_sif_trailer(&self, trailer: Vec<u8>);
79
80        pub fn set_key(
81            self: &KeyProvider,
82            participant_id: String,
83            key_index: i32,
84            key: Vec<u8>,
85        ) -> bool;
86
87        pub fn ratchet_key(
88            self: &KeyProvider,
89            participant_id: String,
90            key_index: i32,
91        ) -> Result<Vec<u8>>;
92
93        pub fn get_key(
94            self: &KeyProvider,
95            participant_id: String,
96            key_index: i32,
97        ) -> Result<Vec<u8>>;
98    }
99
100    unsafe extern "C++" {
101        include!("livekit/frame_cryptor.h");
102        include!("livekit/rtp_sender.h");
103        include!("livekit/rtp_receiver.h");
104        include!("livekit/peer_connection_factory.h");
105
106        type RtpSender = crate::rtp_sender::ffi::RtpSender;
107        type RtpReceiver = crate::rtp_receiver::ffi::RtpReceiver;
108        type PeerConnectionFactory = crate::peer_connection_factory::ffi::PeerConnectionFactory;
109
110        pub type FrameCryptor;
111
112        pub fn new_frame_cryptor_for_rtp_sender(
113            peer_factory: SharedPtr<PeerConnectionFactory>,
114            participant_id: String,
115            algorithm: Algorithm,
116            key_provider: SharedPtr<KeyProvider>,
117            sender: SharedPtr<RtpSender>,
118        ) -> SharedPtr<FrameCryptor>;
119
120        pub fn new_frame_cryptor_for_rtp_receiver(
121            peer_factory: SharedPtr<PeerConnectionFactory>,
122            participant_id: String,
123            algorithm: Algorithm,
124            key_provider: SharedPtr<KeyProvider>,
125            receiver: SharedPtr<RtpReceiver>,
126        ) -> SharedPtr<FrameCryptor>;
127
128        pub fn set_enabled(self: &FrameCryptor, enabled: bool);
129
130        pub fn enabled(self: &FrameCryptor) -> bool;
131
132        pub fn set_key_index(self: &FrameCryptor, index: i32);
133
134        pub fn key_index(self: &FrameCryptor) -> i32;
135
136        pub fn participant_id(self: &FrameCryptor) -> String;
137
138        pub fn register_observer(
139            self: &FrameCryptor,
140            observer: Box<RtcFrameCryptorObserverWrapper>,
141        );
142
143        pub fn unregister_observer(self: &FrameCryptor);
144    }
145
146    unsafe extern "C++" {
147        include!("livekit/frame_cryptor.h");
148
149        pub type DataPacketCryptor;
150
151        pub fn new_data_packet_cryptor(
152            algorithm: Algorithm,
153            key_provider: SharedPtr<KeyProvider>,
154        ) -> SharedPtr<DataPacketCryptor>;
155
156        pub fn encrypt_data_packet(
157            self: &DataPacketCryptor,
158            participant_id: String,
159            key_index: u32,
160            data: Vec<u8>,
161        ) -> Result<EncryptedPacket>;
162
163        pub fn decrypt_data_packet(
164            self: &DataPacketCryptor,
165            participant_id: String,
166            encrypted_packet: &EncryptedPacket,
167        ) -> Result<Vec<u8>>;
168    }
169
170    extern "Rust" {
171        type RtcFrameCryptorObserverWrapper;
172
173        fn on_frame_cryption_state_change(
174            self: &RtcFrameCryptorObserverWrapper,
175            participant_id: String,
176            state: FrameCryptionState,
177        );
178    }
179} // namespace livekit_ffi
180
181impl_thread_safety!(ffi::FrameCryptor, Send + Sync);
182impl_thread_safety!(ffi::KeyProvider, Send + Sync);
183impl_thread_safety!(ffi::DataPacketCryptor, Send + Sync);
184
185use ffi::FrameCryptionState;
186
187// Re-export the EncryptedPacket for convenience
188pub use ffi::EncryptedPacket;
189
190pub trait RtcFrameCryptorObserver: Send + Sync {
191    fn on_frame_cryption_state_change(&self, participant_id: String, state: FrameCryptionState);
192}
193
194pub struct RtcFrameCryptorObserverWrapper {
195    observer: Arc<dyn RtcFrameCryptorObserver>,
196}
197
198impl RtcFrameCryptorObserverWrapper {
199    pub fn new(observer: Arc<dyn RtcFrameCryptorObserver>) -> Self {
200        Self { observer }
201    }
202
203    fn on_frame_cryption_state_change(
204        self: &RtcFrameCryptorObserverWrapper,
205        participant_id: String,
206        state: FrameCryptionState,
207    ) {
208        self.observer.on_frame_cryption_state_change(participant_id, state);
209    }
210}
211
212/// High-level Rust wrapper for data packet cryptor functionality
213pub struct DataPacketCryptor {
214    inner: cxx::SharedPtr<ffi::DataPacketCryptor>,
215}
216
217impl DataPacketCryptor {
218    /// Create a new data packet cryptor with the specified algorithm and key provider
219    pub fn new(algorithm: ffi::Algorithm, key_provider: cxx::SharedPtr<ffi::KeyProvider>) -> Self {
220        Self { inner: ffi::new_data_packet_cryptor(algorithm, key_provider) }
221    }
222
223    /// Encrypt data for a specific participant
224    pub fn encrypt(
225        &self,
226        participant_id: &str,
227        key_index: u32,
228        data: &[u8],
229    ) -> Result<ffi::EncryptedPacket, Box<dyn std::error::Error>> {
230        let data_vec: Vec<u8> = data.to_vec();
231        match self.inner.encrypt_data_packet(participant_id.to_string(), key_index, data_vec) {
232            Ok(packet) => Ok(packet),
233            Err(e) => Err(format!("Encryption failed: {}", e).into()),
234        }
235    }
236
237    /// Decrypt an encrypted packet for a specific participant
238    pub fn decrypt(
239        &self,
240        participant_id: &str,
241        encrypted_packet: &ffi::EncryptedPacket,
242    ) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
243        match self.inner.decrypt_data_packet(participant_id.to_string(), encrypted_packet) {
244            Ok(data) => Ok(data.into_iter().collect()),
245            Err(e) => Err(format!("Decryption failed: {}", e).into()),
246        }
247    }
248}
249
250#[cfg(test)]
251mod tests {
252    use super::*;
253
254    #[test]
255    fn test_data_packet_cryptor_creation() {
256        let options = ffi::KeyProviderOptions {
257            shared_key: true,
258            ratchet_window_size: 16,
259            ratchet_salt: vec![],
260            failure_tolerance: -1,
261            key_ring_size: 16,
262            key_derivation_algorithm: ffi::KeyDerivationAlgorithm::HKDF,
263        };
264
265        let key_provider = ffi::new_key_provider(options);
266        let _cryptor = DataPacketCryptor::new(ffi::Algorithm::AesGcm, key_provider);
267    }
268}