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")]
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} // namespace livekit
171
172impl_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
178// Re-export the EncryptedPacket for convenience
179pub 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
203/// High-level Rust wrapper for data packet cryptor functionality
204pub struct DataPacketCryptor {
205    inner: cxx::SharedPtr<ffi::DataPacketCryptor>,
206}
207
208impl DataPacketCryptor {
209    /// Create a new data packet cryptor with the specified algorithm and key provider
210    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    /// Encrypt data for a specific participant
215    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    /// Decrypt an encrypted packet for a specific participant
229    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}