Skip to main content

gosuto_livekit/room/e2ee/
key_provider.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 gosuto_libwebrtc::native::frame_cryptor as fc;
16use std::sync::{
17    atomic::{AtomicI32, Ordering},
18    Arc,
19};
20
21use crate::id::ParticipantIdentity;
22
23pub use fc::KeyDerivationAlgorithm;
24
25const DEFAULT_RATCHET_SALT: &str = "LKFrameEncryptionKey";
26const DEFAULT_RATCHET_WINDOW_SIZE: i32 = 16;
27const DEFAULT_FAILURE_TOLERANCE: i32 = -1; // no tolerance by default
28
29#[derive(Clone)]
30pub struct KeyProviderOptions {
31    pub ratchet_window_size: i32,
32    pub ratchet_salt: Vec<u8>,
33    pub failure_tolerance: i32,
34    pub key_derivation_algorithm: KeyDerivationAlgorithm,
35}
36
37impl Default for KeyProviderOptions {
38    fn default() -> Self {
39        Self {
40            ratchet_window_size: DEFAULT_RATCHET_WINDOW_SIZE,
41            ratchet_salt: DEFAULT_RATCHET_SALT.to_owned().into_bytes(),
42            failure_tolerance: DEFAULT_FAILURE_TOLERANCE,
43            key_derivation_algorithm: KeyDerivationAlgorithm::Hkdf,
44        }
45    }
46}
47
48#[derive(Clone)]
49pub struct KeyProvider {
50    pub(crate) handle: fc::KeyProvider,
51    latest_key_index: Arc<AtomicI32>,
52}
53
54impl KeyProvider {
55    /// By default, the key provider is not shared
56    pub fn new(options: KeyProviderOptions) -> Self {
57        Self {
58            handle: fc::KeyProvider::new(fc::KeyProviderOptions {
59                shared_key: false,
60                ratchet_window_size: options.ratchet_window_size,
61                ratchet_salt: options.ratchet_salt,
62                failure_tolerance: options.failure_tolerance,
63                key_derivation_algorithm: options.key_derivation_algorithm,
64            }),
65            latest_key_index: Arc::new(AtomicI32::new(0)),
66        }
67    }
68
69    pub fn with_shared_key(options: KeyProviderOptions, shared_key: Vec<u8>) -> Self {
70        let handle = fc::KeyProvider::new(fc::KeyProviderOptions {
71            shared_key: true,
72            ratchet_window_size: options.ratchet_window_size,
73            ratchet_salt: options.ratchet_salt,
74            failure_tolerance: options.failure_tolerance,
75            key_derivation_algorithm: options.key_derivation_algorithm,
76        });
77        handle.set_shared_key(0, shared_key);
78        Self { handle, latest_key_index: Arc::new(AtomicI32::new(0)) }
79    }
80
81    pub fn set_shared_key(&self, shared_key: Vec<u8>, key_index: i32) {
82        self.latest_key_index.store(key_index, Ordering::Relaxed);
83        self.handle.set_shared_key(key_index, shared_key);
84    }
85
86    pub fn ratchet_shared_key(&self, key_index: i32) -> Option<Vec<u8>> {
87        self.handle.ratchet_shared_key(key_index)
88    }
89
90    pub fn get_shared_key(&self, key_index: i32) -> Option<Vec<u8>> {
91        self.handle.get_shared_key(key_index)
92    }
93
94    pub fn set_key(&self, identity: &ParticipantIdentity, key_index: i32, key: Vec<u8>) -> bool {
95        self.latest_key_index.store(key_index, Ordering::Relaxed);
96        self.handle.set_key(identity.to_string(), key_index, key)
97    }
98
99    pub fn ratchet_key(&self, identity: &ParticipantIdentity, key_index: i32) -> Option<Vec<u8>> {
100        self.handle.ratchet_key(identity.to_string(), key_index)
101    }
102
103    pub fn get_key(&self, identity: &ParticipantIdentity, key_index: i32) -> Option<Vec<u8>> {
104        self.handle.get_key(identity.to_string(), key_index)
105    }
106
107    pub fn set_sif_trailer(&self, trailer: Vec<u8>) {
108        self.handle.set_sif_trailer(trailer);
109    }
110
111    pub fn get_latest_key_index(&self) -> i32 {
112        self.latest_key_index.load(Ordering::Relaxed)
113    }
114}