Skip to content

Commit c863be7

Browse files
authored
E2EE: allow setting key_ring_size and key_derivation_algorithm (#921)
* Allow setting keyring-size from Rust * Implement using HKDF as the KDF. * Reexport KeyDerivationAlgorithm, use const for default KeyDerivationAlgorithm. * Update webrtc * Add changeset * Don't wrongly to m144 change, update webrtc to webrtc-24f6822-2
1 parent 56669ae commit c863be7

8 files changed

Lines changed: 118 additions & 13 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
soxr-sys: patch
3+
webrtc-sys: patch
4+
livekit-ffi: minor
5+
livekit-protocol: patch
6+
livekit: minor
7+
livekit-wakeword: patch
8+
livekit-api: patch
9+
imgproc: patch
10+
libwebrtc: minor
11+
webrtc-sys-build: patch
12+
yuv-sys: patch
13+
---
14+
15+
# E2EE: allow setting key_ring_size and key_derivation_algorithm, update webrtc to m144
16+
17+
#921 by @onestacked
18+
19+
This PR uses [this webrtc-sdk PR](https://github.com/webrtc-sdk/webrtc/pull/224) to configure the KDF.
20+
21+
I've tested this with https://codeberg.org/esoteric_programmer/matrix-jukebox and it is compatible with Element Call.
22+
23+
Fixed: https://github.com/livekit/rust-sdks/issues/796

libwebrtc/src/native/frame_cryptor.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,29 @@ use crate::{
2525

2626
pub type OnStateChange = Box<dyn FnMut(String, EncryptionState) + Send + Sync>;
2727

28+
#[derive(Copy, Clone, Debug)]
29+
#[non_exhaustive]
30+
pub enum KeyDerivationAlgorithm {
31+
PBKDF2,
32+
HKDF,
33+
}
34+
impl Into<sys_fc::ffi::KeyDerivationAlgorithm> for KeyDerivationAlgorithm {
35+
fn into(self) -> sys_fc::ffi::KeyDerivationAlgorithm {
36+
match self {
37+
KeyDerivationAlgorithm::PBKDF2 => sys_fc::ffi::KeyDerivationAlgorithm::PBKDF2,
38+
KeyDerivationAlgorithm::HKDF => sys_fc::ffi::KeyDerivationAlgorithm::HKDF,
39+
}
40+
}
41+
}
42+
2843
#[derive(Debug, Clone)]
2944
pub struct KeyProviderOptions {
3045
pub shared_key: bool,
3146
pub ratchet_window_size: i32,
3247
pub ratchet_salt: Vec<u8>,
3348
pub failure_tolerance: i32,
49+
pub key_ring_size: i32,
50+
pub key_derivation_algorithm: KeyDerivationAlgorithm,
3451
}
3552

3653
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -272,6 +289,8 @@ impl From<KeyProviderOptions> for sys_fc::ffi::KeyProviderOptions {
272289
ratchet_window_size: value.ratchet_window_size,
273290
ratchet_salt: value.ratchet_salt,
274291
failure_tolerance: value.failure_tolerance,
292+
key_ring_size: value.key_ring_size,
293+
key_derivation_algorithm: value.key_derivation_algorithm.into(),
275294
}
276295
}
277296
}

livekit-ffi/protocol/e2ee.proto

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ message KeyProviderOptions {
3838
required int32 ratchet_window_size = 2;
3939
required bytes ratchet_salt = 3;
4040
required int32 failure_tolerance = 4; // -1 = no tolerance
41+
required int32 key_ring_size = 5;
42+
required KeyDerivationFunction key_derivation_function = 6;
43+
}
44+
45+
enum KeyDerivationFunction {
46+
PBKDF2 = 0;
47+
HKDF = 1;
4148
}
4249

4350
message E2eeOptions {

livekit-ffi/src/conversion/room.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use livekit::{
2121
options::{AudioEncoding, TrackPublishOptions, VideoEncoding},
2222
prelude::*,
2323
webrtc::{
24-
native::frame_cryptor::EncryptionState,
24+
native::frame_cryptor::{EncryptionState, KeyDerivationAlgorithm},
2525
prelude::{ContinualGatheringPolicy, IceServer, IceTransportsType, RtcConfiguration},
2626
},
2727
RoomInfo,
@@ -133,10 +133,22 @@ impl From<proto::DisconnectReason> for DisconnectReason {
133133

134134
impl From<proto::KeyProviderOptions> for KeyProviderOptions {
135135
fn from(value: proto::KeyProviderOptions) -> Self {
136+
let key_derivation_algorithm = value.key_derivation_function().into();
136137
Self {
137138
ratchet_window_size: value.ratchet_window_size,
138139
ratchet_salt: value.ratchet_salt,
139140
failure_tolerance: value.failure_tolerance,
141+
key_ring_size: value.key_ring_size,
142+
key_derivation_algorithm,
143+
}
144+
}
145+
}
146+
147+
impl From<proto::KeyDerivationFunction> for KeyDerivationAlgorithm {
148+
fn from(value: proto::KeyDerivationFunction) -> Self {
149+
match value {
150+
proto::KeyDerivationFunction::Pbkdf2 => KeyDerivationAlgorithm::PBKDF2,
151+
proto::KeyDerivationFunction::Hkdf => KeyDerivationAlgorithm::HKDF,
140152
}
141153
}
142154
}

livekit/src/room/e2ee/key_provider.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,21 @@ use std::sync::{
2020

2121
use crate::id::ParticipantIdentity;
2222

23+
pub use libwebrtc::native::frame_cryptor::KeyDerivationAlgorithm;
24+
2325
const DEFAULT_RATCHET_SALT: &str = "LKFrameEncryptionKey";
2426
const DEFAULT_RATCHET_WINDOW_SIZE: i32 = 16;
2527
const DEFAULT_FAILURE_TOLERANCE: i32 = -1; // no tolerance by default
28+
const DEFAULT_KEY_RING_SIZE: i32 = 16;
29+
const DEFAULT_KEY_DERIVATION_ALGORITHM: KeyDerivationAlgorithm = KeyDerivationAlgorithm::PBKDF2;
2630

2731
#[derive(Clone)]
2832
pub struct KeyProviderOptions {
2933
pub ratchet_window_size: i32,
3034
pub ratchet_salt: Vec<u8>,
3135
pub failure_tolerance: i32,
36+
pub key_ring_size: i32,
37+
pub key_derivation_algorithm: KeyDerivationAlgorithm,
3238
}
3339

3440
impl Default for KeyProviderOptions {
@@ -37,6 +43,8 @@ impl Default for KeyProviderOptions {
3743
ratchet_window_size: DEFAULT_RATCHET_WINDOW_SIZE,
3844
ratchet_salt: DEFAULT_RATCHET_SALT.to_owned().into_bytes(),
3945
failure_tolerance: DEFAULT_FAILURE_TOLERANCE,
46+
key_ring_size: DEFAULT_KEY_RING_SIZE,
47+
key_derivation_algorithm: DEFAULT_KEY_DERIVATION_ALGORITHM,
4048
}
4149
}
4250
}
@@ -56,6 +64,8 @@ impl KeyProvider {
5664
ratchet_window_size: options.ratchet_window_size,
5765
ratchet_salt: options.ratchet_salt,
5866
failure_tolerance: options.failure_tolerance,
67+
key_ring_size: options.key_ring_size,
68+
key_derivation_algorithm: options.key_derivation_algorithm,
5969
}),
6070
latest_key_index: Arc::new(AtomicI32::new(0)),
6171
}
@@ -67,6 +77,8 @@ impl KeyProvider {
6777
ratchet_window_size: options.ratchet_window_size,
6878
ratchet_salt: options.ratchet_salt,
6979
failure_tolerance: options.failure_tolerance,
80+
key_ring_size: options.key_ring_size,
81+
key_derivation_algorithm: options.key_derivation_algorithm,
7082
});
7183
handle.set_shared_key(0, shared_key);
7284
Self { handle, latest_key_index: Arc::new(AtomicI32::new(0)) }

webrtc-sys/libwebrtc/.gclient

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
solutions = [
22
{
33
"name": 'src',
4-
"url": 'https://github.com/webrtc-sdk/webrtc.git@m137_release',
4+
"url": 'https://github.com/webrtc-sdk/webrtc.git@m137_release'',
55
"custom_deps": {},
66
"deps_file": "DEPS",
77
"managed": False,

webrtc-sys/src/frame_cryptor.cpp

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@ webrtc::FrameCryptorTransformer::Algorithm AlgorithmToFrameCryptorAlgorithm(
4040
}
4141
}
4242

43+
webrtc::KeyDerivationAlgorithm
44+
KeyDerivationAlgorithmToFrameCryptorKeyDerivationAlgorithm(
45+
KeyDerivationAlgorithm algorithm) {
46+
switch (algorithm) {
47+
case KeyDerivationAlgorithm::PBKDF2:
48+
return webrtc::KeyDerivationAlgorithm::kPBKDF2;
49+
case KeyDerivationAlgorithm::HKDF:
50+
return webrtc::KeyDerivationAlgorithm::kHKDF;
51+
default:
52+
return webrtc::KeyDerivationAlgorithm::kPBKDF2;
53+
}
54+
}
55+
4356
KeyProvider::KeyProvider(KeyProviderOptions options) {
4457
webrtc::KeyProviderOptions rtc_options;
4558
rtc_options.shared_key = options.shared_key;
@@ -51,7 +64,10 @@ KeyProvider::KeyProvider(KeyProviderOptions options) {
5164
rtc_options.ratchet_salt = ratchet_salt;
5265
rtc_options.ratchet_window_size = options.ratchet_window_size;
5366
rtc_options.failure_tolerance = options.failure_tolerance;
54-
67+
rtc_options.key_ring_size = options.key_ring_size;
68+
rtc_options.key_derivation_algorithm =
69+
KeyDerivationAlgorithmToFrameCryptorKeyDerivationAlgorithm(
70+
options.key_derivation_algorithm);
5571
impl_ =
5672
new rtc::RefCountedObject<webrtc::DefaultKeyProviderImpl>(rtc_options);
5773
}
@@ -154,10 +170,12 @@ int32_t FrameCryptor::key_index() const {
154170
return e2ee_transformer_->key_index();
155171
}
156172

157-
DataPacketCryptor::DataPacketCryptor(webrtc::FrameCryptorTransformer::Algorithm algorithm,
158-
webrtc::scoped_refptr<webrtc::KeyProvider> key_provider)
173+
DataPacketCryptor::DataPacketCryptor(
174+
webrtc::FrameCryptorTransformer::Algorithm algorithm,
175+
webrtc::scoped_refptr<webrtc::KeyProvider> key_provider)
159176
: data_packet_cryptor_(
160-
webrtc::make_ref_counted<webrtc::DataPacketCryptor>(algorithm, key_provider)) {}
177+
webrtc::make_ref_counted<webrtc::DataPacketCryptor>(algorithm,
178+
key_provider)) {}
161179

162180
EncryptedPacket DataPacketCryptor::encrypt_data_packet(
163181
const ::rust::String participant_id,
@@ -167,12 +185,12 @@ EncryptedPacket DataPacketCryptor::encrypt_data_packet(
167185
std::copy(data.begin(), data.end(), std::back_inserter(data_vec));
168186

169187
auto result = data_packet_cryptor_->Encrypt(
170-
std::string(participant_id.data(), participant_id.size()),
171-
key_index,
188+
std::string(participant_id.data(), participant_id.size()), key_index,
172189
data_vec);
173190

174191
if (!result.ok()) {
175-
throw std::runtime_error(std::string("Failed to encrypt data packet: ") + result.error().message());
192+
throw std::runtime_error(std::string("Failed to encrypt data packet: ") +
193+
result.error().message());
176194
}
177195

178196
auto& packet = result.value();
@@ -202,20 +220,23 @@ rust::Vec<::std::uint8_t> DataPacketCryptor::decrypt_data_packet(
202220
std::copy(encrypted_packet.iv.begin(), encrypted_packet.iv.end(),
203221
std::back_inserter(iv_vec));
204222

205-
auto native_encrypted_packet = webrtc::make_ref_counted<webrtc::EncryptedPacket>(
206-
std::move(data_vec), std::move(iv_vec), encrypted_packet.key_index);
223+
auto native_encrypted_packet =
224+
webrtc::make_ref_counted<webrtc::EncryptedPacket>(
225+
std::move(data_vec), std::move(iv_vec), encrypted_packet.key_index);
207226

208227
auto result = data_packet_cryptor_->Decrypt(
209228
std::string(participant_id.data(), participant_id.size()),
210229
native_encrypted_packet);
211230

212231
if (!result.ok()) {
213-
throw std::runtime_error(std::string("Failed to decrypt data packet: ") + result.error().message());
232+
throw std::runtime_error(std::string("Failed to decrypt data packet: ") +
233+
result.error().message());
214234
}
215235

216236
rust::Vec<uint8_t> decrypted_data;
217237
auto& decrypted = result.value();
218-
std::copy(decrypted.begin(), decrypted.end(), std::back_inserter(decrypted_data));
238+
std::copy(decrypted.begin(), decrypted.end(),
239+
std::back_inserter(decrypted_data));
219240
return decrypted_data;
220241
}
221242

webrtc-sys/src/frame_cryptor.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ pub mod ffi {
2525
pub ratchet_window_size: i32,
2626
pub ratchet_salt: Vec<u8>,
2727
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,
2837
}
2938

3039
#[derive(Debug)]
@@ -249,6 +258,8 @@ mod tests {
249258
ratchet_window_size: 16,
250259
ratchet_salt: vec![],
251260
failure_tolerance: -1,
261+
key_ring_size: 16,
262+
key_derivation_algorithm: ffi::KeyDerivationAlgorithm::HKDF,
252263
};
253264

254265
let key_provider = ffi::new_key_provider(options);

0 commit comments

Comments
 (0)