1use 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} impl_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
187pub 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
212pub struct DataPacketCryptor {
214 inner: cxx::SharedPtr<ffi::DataPacketCryptor>,
215}
216
217impl DataPacketCryptor {
218 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 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 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}