Skip to main content

livekit_datatrack/
e2ee.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 bytes::Bytes;
16use core::fmt::Debug;
17use thiserror::Error;
18
19// TODO: If a core module for end-to-end encryption is created in the future
20// (livekit-e2ee), these traits should be moved to there.
21
22/// Twelve byte AES initialization vector (IV).
23pub type InitializationVector = [u8; 12];
24
25/// Encrypted payload and metadata required for decryption.
26#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
27pub struct EncryptedPayload {
28    pub payload: Bytes,
29    pub iv: InitializationVector,
30    pub key_index: u8,
31}
32
33/// An error indicating a payload could not be encrypted.
34#[derive(Debug, Error)]
35#[cfg_attr(feature = "uniffi", derive(uniffi::Error))]
36#[cfg_attr(feature = "uniffi", uniffi(flat_error))]
37pub enum EncryptionError {
38    #[error("Encryption failed")]
39    Failed,
40}
41
42/// An error indicating a payload could not be decrypted.
43#[derive(Debug, Error)]
44#[cfg_attr(feature = "uniffi", derive(uniffi::Error))]
45#[cfg_attr(feature = "uniffi", uniffi(flat_error))]
46pub enum DecryptionError {
47    #[error("Decryption failed")]
48    Failed,
49}
50
51/// Provider for encrypting payloads for E2EE.
52#[cfg_attr(feature = "uniffi", uniffi::export(with_foreign))]
53pub trait EncryptionProvider: Send + Sync + Debug {
54    /// Encrypts the given payload being sent by the local participant.
55    fn encrypt(&self, payload: Bytes) -> Result<EncryptedPayload, EncryptionError>;
56}
57
58/// Provider for decrypting payloads for E2EE.
59#[cfg_attr(feature = "uniffi", uniffi::export(with_foreign))]
60pub trait DecryptionProvider: Send + Sync + Debug {
61    /// Decrypts the given payload received from a remote participant.
62    ///
63    /// Sender identity is required in order for the proper key to be used
64    /// for decryption.
65    ///
66    fn decrypt(
67        &self,
68        payload: EncryptedPayload,
69        sender_identity: String,
70    ) -> Result<Bytes, DecryptionError>;
71
72    // TODO: the above method previously took &str for sender_identity but has
73    // been modified to accept String so it can be exported for UniFFI. However,
74    // this results in an unnecessary heap allocation when used in a Rust-only context.
75    // Find a better solution for this.
76}
77
78#[cfg(feature = "uniffi")]
79uniffi::custom_type!(Bytes, Vec<u8>, { remote });
80
81#[cfg(feature = "uniffi")]
82uniffi::custom_type!(InitializationVector, Vec<u8>, {
83    remote,
84    lower: |iv| iv.to_vec(),
85    try_lift: |v| v.try_into()
86        .map_err(|_| uniffi::deps::anyhow::anyhow!("IV must be exactly 12 bytes"))
87});