1use std::sync::Arc;
16
17use crate::impl_thread_safety;
18
19#[cxx::bridge(namespace = "livekit")]
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 }
29
30 #[derive(Debug)]
31 #[repr(i32)]
32 pub enum Algorithm {
33 AesGcm = 0,
34 AesCbc,
35 }
36
37 #[derive(Debug)]
38 #[repr(i32)]
39 pub enum FrameCryptionState {
40 New = 0,
41 Ok,
42 EncryptionFailed,
43 DecryptionFailed,
44 MissingKey,
45 KeyRatcheted,
46 InternalError,
47 }
48
49 #[derive(Debug)]
50 pub struct EncryptedPacket {
51 pub data: Vec<u8>,
52 pub iv: Vec<u8>,
53 pub key_index: u32,
54 }
55
56 unsafe extern "C++" {
57 include!("livekit/frame_cryptor.h");
58
59 pub type KeyProvider;
60
61 pub fn new_key_provider(options: KeyProviderOptions) -> SharedPtr<KeyProvider>;
62
63 pub fn set_shared_key(self: &KeyProvider, key_index: i32, key: Vec<u8>) -> bool;
64
65 pub fn ratchet_shared_key(self: &KeyProvider, key_index: i32) -> Result<Vec<u8>>;
66
67 pub fn get_shared_key(self: &KeyProvider, key_index: i32) -> Result<Vec<u8>>;
68
69 pub fn set_sif_trailer(&self, trailer: Vec<u8>);
70
71 pub fn set_key(
72 self: &KeyProvider,
73 participant_id: String,
74 key_index: i32,
75 key: Vec<u8>,
76 ) -> bool;
77
78 pub fn ratchet_key(
79 self: &KeyProvider,
80 participant_id: String,
81 key_index: i32,
82 ) -> Result<Vec<u8>>;
83
84 pub fn get_key(
85 self: &KeyProvider,
86 participant_id: String,
87 key_index: i32,
88 ) -> Result<Vec<u8>>;
89 }
90
91 unsafe extern "C++" {
92 include!("livekit/frame_cryptor.h");
93 include!("livekit/rtp_sender.h");
94 include!("livekit/rtp_receiver.h");
95 include!("livekit/peer_connection_factory.h");
96
97 type RtpSender = crate::rtp_sender::ffi::RtpSender;
98 type RtpReceiver = crate::rtp_receiver::ffi::RtpReceiver;
99 type PeerConnectionFactory = crate::peer_connection_factory::ffi::PeerConnectionFactory;
100
101 pub type FrameCryptor;
102
103 pub fn new_frame_cryptor_for_rtp_sender(
104 peer_factory: SharedPtr<PeerConnectionFactory>,
105 participant_id: String,
106 algorithm: Algorithm,
107 key_provider: SharedPtr<KeyProvider>,
108 sender: SharedPtr<RtpSender>,
109 ) -> SharedPtr<FrameCryptor>;
110
111 pub fn new_frame_cryptor_for_rtp_receiver(
112 peer_factory: SharedPtr<PeerConnectionFactory>,
113 participant_id: String,
114 algorithm: Algorithm,
115 key_provider: SharedPtr<KeyProvider>,
116 receiver: SharedPtr<RtpReceiver>,
117 ) -> SharedPtr<FrameCryptor>;
118
119 pub fn set_enabled(self: &FrameCryptor, enabled: bool);
120
121 pub fn enabled(self: &FrameCryptor) -> bool;
122
123 pub fn set_key_index(self: &FrameCryptor, index: i32);
124
125 pub fn key_index(self: &FrameCryptor) -> i32;
126
127 pub fn participant_id(self: &FrameCryptor) -> String;
128
129 pub fn register_observer(
130 self: &FrameCryptor,
131 observer: Box<RtcFrameCryptorObserverWrapper>,
132 );
133
134 pub fn unregister_observer(self: &FrameCryptor);
135 }
136
137 unsafe extern "C++" {
138 include!("livekit/frame_cryptor.h");
139
140 pub type DataPacketCryptor;
141
142 pub fn new_data_packet_cryptor(
143 algorithm: Algorithm,
144 key_provider: SharedPtr<KeyProvider>,
145 ) -> SharedPtr<DataPacketCryptor>;
146
147 pub fn encrypt_data_packet(
148 self: &DataPacketCryptor,
149 participant_id: String,
150 key_index: u32,
151 data: Vec<u8>,
152 ) -> Result<EncryptedPacket>;
153
154 pub fn decrypt_data_packet(
155 self: &DataPacketCryptor,
156 participant_id: String,
157 encrypted_packet: &EncryptedPacket,
158 ) -> Result<Vec<u8>>;
159 }
160
161 extern "Rust" {
162 type RtcFrameCryptorObserverWrapper;
163
164 fn on_frame_cryption_state_change(
165 self: &RtcFrameCryptorObserverWrapper,
166 participant_id: String,
167 state: FrameCryptionState,
168 );
169 }
170} impl_thread_safety!(ffi::FrameCryptor, Send + Sync);
173impl_thread_safety!(ffi::KeyProvider, Send + Sync);
174impl_thread_safety!(ffi::DataPacketCryptor, Send + Sync);
175
176use ffi::FrameCryptionState;
177
178pub use ffi::EncryptedPacket;
180
181pub trait RtcFrameCryptorObserver: Send + Sync {
182 fn on_frame_cryption_state_change(&self, participant_id: String, state: FrameCryptionState);
183}
184
185pub struct RtcFrameCryptorObserverWrapper {
186 observer: Arc<dyn RtcFrameCryptorObserver>,
187}
188
189impl RtcFrameCryptorObserverWrapper {
190 pub fn new(observer: Arc<dyn RtcFrameCryptorObserver>) -> Self {
191 Self { observer }
192 }
193
194 fn on_frame_cryption_state_change(
195 self: &RtcFrameCryptorObserverWrapper,
196 participant_id: String,
197 state: FrameCryptionState,
198 ) {
199 self.observer.on_frame_cryption_state_change(participant_id, state);
200 }
201}
202
203pub struct DataPacketCryptor {
205 inner: cxx::SharedPtr<ffi::DataPacketCryptor>,
206}
207
208impl DataPacketCryptor {
209 pub fn new(algorithm: ffi::Algorithm, key_provider: cxx::SharedPtr<ffi::KeyProvider>) -> Self {
211 Self { inner: ffi::new_data_packet_cryptor(algorithm, key_provider) }
212 }
213
214 pub fn encrypt(
216 &self,
217 participant_id: &str,
218 key_index: u32,
219 data: &[u8],
220 ) -> Result<ffi::EncryptedPacket, Box<dyn std::error::Error>> {
221 let data_vec: Vec<u8> = data.to_vec();
222 match self.inner.encrypt_data_packet(participant_id.to_string(), key_index, data_vec) {
223 Ok(packet) => Ok(packet),
224 Err(e) => Err(format!("Encryption failed: {}", e).into()),
225 }
226 }
227
228 pub fn decrypt(
230 &self,
231 participant_id: &str,
232 encrypted_packet: &ffi::EncryptedPacket,
233 ) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
234 match self.inner.decrypt_data_packet(participant_id.to_string(), encrypted_packet) {
235 Ok(data) => Ok(data.into_iter().collect()),
236 Err(e) => Err(format!("Decryption failed: {}", e).into()),
237 }
238 }
239}
240
241#[cfg(test)]
242mod tests {
243 use super::*;
244
245 #[test]
246 fn test_data_packet_cryptor_creation() {
247 let options = ffi::KeyProviderOptions {
248 shared_key: true,
249 ratchet_window_size: 16,
250 ratchet_salt: vec![],
251 failure_tolerance: -1,
252 };
253
254 let key_provider = ffi::new_key_provider(options);
255 let _cryptor = DataPacketCryptor::new(ffi::Algorithm::AesGcm, key_provider);
256 }
257}