From a1c7145c8702f05050e0971dad18e17293774e56 Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Thu, 31 Aug 2023 15:21:47 +0800 Subject: [PATCH 1/8] Improve e2ee, add setSharedKey to KeyProvider. --- api/crypto/frame_crypto_transformer.cc | 10 +- api/crypto/frame_crypto_transformer.h | 94 ++++++++++++------- .../org/webrtc/FrameCryptorKeyProvider.java | 8 +- .../src/jni/pc/frame_cryptor_key_provider.cc | 10 ++ .../RTCFrameCryptorKeyProvider.h | 2 + .../RTCFrameCryptorKeyProvider.mm | 6 ++ 6 files changed, 89 insertions(+), 41 deletions(-) diff --git a/api/crypto/frame_crypto_transformer.cc b/api/crypto/frame_crypto_transformer.cc index ed5a17c957..0453e14db4 100644 --- a/api/crypto/frame_crypto_transformer.cc +++ b/api/crypto/frame_crypto_transformer.cc @@ -565,15 +565,15 @@ void FrameCryptorTransformer::decryptFrame( RTC_LOG(LS_ERROR) << "FrameCryptorTransformer::decryptFrame() failed"; std::shared_ptr ratcheted_key_set; auto currentKeyMaterial = key_set->material; - if (key_handler->options().ratchet_window_size > 0) { - while (ratchet_count < key_handler->options().ratchet_window_size) { + if (key_provider_->options().ratchet_window_size > 0) { + while (ratchet_count < key_provider_->options().ratchet_window_size) { ratchet_count++; RTC_LOG(LS_INFO) << "ratcheting key attempt " << ratchet_count << " of " - << key_handler->options().ratchet_window_size; + << key_provider_->options().ratchet_window_size; auto new_material = key_handler->RatchetKeyMaterial(currentKeyMaterial); - ratcheted_key_set = key_handler->DeriveKeys(new_material, key_handler->options().ratchet_salt, 128); + ratcheted_key_set = key_handler->DeriveKeys(new_material, key_provider_->options().ratchet_salt, 128); if (AesEncryptDecrypt(EncryptOrDecrypt::kDecrypt, algorithm_, ratcheted_key_set->encryption_key, iv, frame_header, @@ -603,7 +603,7 @@ void FrameCryptorTransformer::decryptFrame( times, we come back to the initial key. */ if (!decryption_success || - ratchet_count >= key_handler->options().ratchet_window_size) { + ratchet_count >= key_provider_->options().ratchet_window_size) { key_handler->SetKeyFromMaterial(initialKeyMaterial, key_index); } } diff --git a/api/crypto/frame_crypto_transformer.h b/api/crypto/frame_crypto_transformer.h index 7f98deb11d..1f7fc3bc21 100644 --- a/api/crypto/frame_crypto_transformer.h +++ b/api/crypto/frame_crypto_transformer.h @@ -34,6 +34,8 @@ namespace webrtc { const size_t KEYRING_SIZE = 16; +class ParticipantKeyHandler; + struct KeyProviderOptions { bool shared_key; std::vector ratchet_salt; @@ -47,6 +49,33 @@ struct KeyProviderOptions { ratchet_window_size(copy.ratchet_window_size) {} }; +class KeyProvider : public rtc::RefCountInterface { + public: + enum { kRawKeySize = 32 }; + + public: + virtual const std::shared_ptr GetKey( + const std::string participant_id) const = 0; + + virtual bool SetSharedKey(int key_index, std::vector key) = 0; + + virtual bool SetKey(const std::string participant_id, + int key_index, + std::vector key) = 0; + + virtual const std::vector RatchetKey( + const std::string participant_id, + int key_index) = 0; + + virtual const std::vector ExportKey(const std::string participant_id, + int key_index) const = 0; + + virtual KeyProviderOptions& options() = 0; + + protected: + virtual ~KeyProvider() {} +}; + class ParticipantKeyHandler { friend class FrameCryptorTransformer; public: @@ -56,18 +85,18 @@ class ParticipantKeyHandler { KeySet(std::vector material, std::vector encryptionKey) : material(material), encryption_key(encryptionKey) {} }; - public: - ParticipantKeyHandler(KeyProviderOptions options) : options_(options) { + ParticipantKeyHandler(KeyProvider* key_provider) : key_provider_(key_provider) { crypto_key_ring_.resize(KEYRING_SIZE); } virtual ~ParticipantKeyHandler() = default; virtual std::vector RatchetKey(int key_index) { + webrtc::MutexLock lock(&mutex_); auto current_material = GetKeySet(key_index)->material; std::vector new_material; - if (DerivePBKDF2KeyFromRawKey(current_material, options_.ratchet_salt, 256, + if (DerivePBKDF2KeyFromRawKey(current_material, key_provider_->options().ratchet_salt, 256, &new_material) != 0) { return std::vector(); } @@ -77,24 +106,25 @@ class ParticipantKeyHandler { } virtual std::shared_ptr GetKeySet(int key_index) { + webrtc::MutexLock lock(&mutex_); return crypto_key_ring_[key_index != -1 ? key_index : current_key_index_]; } virtual void SetKey(std::vector password, int key_index) { + webrtc::MutexLock lock(&mutex_); SetKeyFromMaterial(password, key_index); have_valid_key = true; } - virtual void SetKeyFromMaterial(std::vector password, int key_index) { +private: + void SetKeyFromMaterial(std::vector password, int key_index) { if (key_index >= 0) { current_key_index_ = key_index % crypto_key_ring_.size(); } crypto_key_ring_[current_key_index_] = - DeriveKeys(password, options_.ratchet_salt, 128); + DeriveKeys(password, key_provider_->options().ratchet_salt, 128); } - virtual KeyProviderOptions& options() { return options_; } - std::shared_ptr DeriveKeys(std::vector password, std::vector ratchet_salt, unsigned int optional_length_bits) { @@ -108,8 +138,9 @@ class ParticipantKeyHandler { std::vector RatchetKeyMaterial( std::vector current_material) { + webrtc::MutexLock lock(&mutex_); std::vector new_material; - if (DerivePBKDF2KeyFromRawKey(current_material, options_.ratchet_salt, 256, + if (DerivePBKDF2KeyFromRawKey(current_material, key_provider_->options().ratchet_salt, 256, &new_material) != 0) { return std::vector(); } @@ -118,41 +149,29 @@ class ParticipantKeyHandler { protected: bool have_valid_key = false; private: + mutable webrtc::Mutex mutex_; int current_key_index_ = 0; - KeyProviderOptions options_; + KeyProvider* key_provider_; std::vector> crypto_key_ring_; }; -class KeyProvider : public rtc::RefCountInterface { - public: - enum { kRawKeySize = 32 }; - - public: - virtual const std::shared_ptr GetKey( - const std::string participant_id) const = 0; - - virtual bool SetKey(const std::string participant_id, - int index, - std::vector key) = 0; - - virtual const std::vector RatchetKey( - const std::string participant_id, - int key_index) = 0; - - virtual const std::vector ExportKey(const std::string participant_id, - int key_index) const = 0; - - virtual KeyProviderOptions& options() = 0; - - protected: - virtual ~KeyProvider() {} -}; - class DefaultKeyProviderImpl : public KeyProvider { public: DefaultKeyProviderImpl(KeyProviderOptions options) : options_(options) {} ~DefaultKeyProviderImpl() override = default; + /// Set the shared key. + bool SetSharedKey(int key_index, std::vector key) override { + webrtc::MutexLock lock(&mutex_); + if (keys_.find("shared") == keys_.end()) { + keys_["shared"] = std::make_shared(this); + } + + auto key_handler = keys_["shared"]; + key_handler->SetKey(key, key_index); + return true; + } + /// Set the key at the given index. bool SetKey(const std::string participant_id, int index, @@ -160,7 +179,7 @@ class DefaultKeyProviderImpl : public KeyProvider { webrtc::MutexLock lock(&mutex_); if (keys_.find(participant_id) == keys_.end()) { - keys_[participant_id] = std::make_shared(options_); + keys_[participant_id] = std::make_shared(this); } auto key_handler = keys_[participant_id]; @@ -171,6 +190,11 @@ class DefaultKeyProviderImpl : public KeyProvider { const std::shared_ptr GetKey( const std::string participant_id) const override { webrtc::MutexLock lock(&mutex_); + + if(options_.shared_key && keys_.find(participant_id) != keys_.end()) { + return keys_.find("shared")->second; + } + if (keys_.find(participant_id) == keys_.end()) { return nullptr; } diff --git a/sdk/android/api/org/webrtc/FrameCryptorKeyProvider.java b/sdk/android/api/org/webrtc/FrameCryptorKeyProvider.java index 1c89eac55b..6e4a73a2bf 100644 --- a/sdk/android/api/org/webrtc/FrameCryptorKeyProvider.java +++ b/sdk/android/api/org/webrtc/FrameCryptorKeyProvider.java @@ -30,6 +30,11 @@ public long getNativeKeyProvider() { return nativeKeyProvider; } + public boolean setSharedKey(int index, byte[] key) { + checkKeyProviderExists(); + return nativeSetSharedKey(nativeKeyProvider,index, key); + } + public boolean setKey(String participantId, int index, byte[] key) { checkKeyProviderExists(); return nativeSetKey(nativeKeyProvider, participantId, index, key); @@ -56,7 +61,8 @@ private void checkKeyProviderExists() { throw new IllegalStateException("FrameCryptorKeyProvider has been disposed."); } } - + private static native boolean nativeSetSharedKey( + long keyProviderPointer, int index, byte[] key); private static native boolean nativeSetKey( long keyProviderPointer, String participantId, int index, byte[] key); private static native byte[] nativeRatchetKey( diff --git a/sdk/android/src/jni/pc/frame_cryptor_key_provider.cc b/sdk/android/src/jni/pc/frame_cryptor_key_provider.cc index 2732693c0f..81ceb458d6 100644 --- a/sdk/android/src/jni/pc/frame_cryptor_key_provider.cc +++ b/sdk/android/src/jni/pc/frame_cryptor_key_provider.cc @@ -33,6 +33,16 @@ ScopedJavaLocalRef NativeToJavaFrameCryptorKeyProvider( env, jlongFromPointer(key_provider.release())); } +static jboolean JNI_FrameCryptorKeyProvider_SetSharedKey( + JNIEnv* jni, + jlong j_key_provider, + jint j_index, + const base::android::JavaParamRef& j_key) { + auto key = JavaToNativeByteArray(jni, j_key); + return reinterpret_cast(j_key_provider) + ->SetSharedKey(j_index,std::vector(key.begin(), key.end())); +} + static jboolean JNI_FrameCryptorKeyProvider_SetKey( JNIEnv* jni, jlong j_key_provider, diff --git a/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.h b/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.h index 276b2e730c..ab879b7b9e 100644 --- a/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.h +++ b/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.h @@ -25,6 +25,8 @@ RTC_OBJC_EXPORT - (void)setKey:(NSData *)key withIndex:(int)index forParticipant:(NSString *)participantId; +- (void)setSharedKey:(NSData *)key withIndex:(int)index; + - (NSData *)ratchetKey:(NSString *)participantId withIndex:(int)index; - (NSData *)exportKey:(NSString *)participantId withIndex:(int)index; diff --git a/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.mm b/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.mm index c27e18975b..c0683c6a32 100644 --- a/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.mm +++ b/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.mm @@ -56,6 +56,12 @@ - (void)setKey:(NSData *)key withIndex:(int)index forParticipant:(NSString *)par std::vector((const uint8_t *)key.bytes, ((const uint8_t *)key.bytes) + key.length)); } +- (void)setSharedKey:(NSData *)key withIndex:(int)index { + _nativeKeyProvider->SetSharedKey( + index, + std::vector((const uint8_t *)key.bytes, ((const uint8_t *)key.bytes) + key.length)); +} + - (NSData *)ratchetKey:(NSString *)participantId withIndex:(int)index { std::vector nativeKey = _nativeKeyProvider->RatchetKey([participantId stdString], index); return [NSData dataWithBytes:nativeKey.data() length:nativeKey.size()]; From 677bec53bb420ede909f7d9fbc5a79a789166655 Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Thu, 31 Aug 2023 15:24:36 +0800 Subject: [PATCH 2/8] update. --- api/crypto/frame_crypto_transformer.h | 29 +++++++++++++-------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/api/crypto/frame_crypto_transformer.h b/api/crypto/frame_crypto_transformer.h index 1f7fc3bc21..8f358f8d48 100644 --- a/api/crypto/frame_crypto_transformer.h +++ b/api/crypto/frame_crypto_transformer.h @@ -116,13 +116,14 @@ class ParticipantKeyHandler { have_valid_key = true; } -private: - void SetKeyFromMaterial(std::vector password, int key_index) { - if (key_index >= 0) { - current_key_index_ = key_index % crypto_key_ring_.size(); + std::vector RatchetKeyMaterial( + std::vector current_material) { + std::vector new_material; + if (DerivePBKDF2KeyFromRawKey(current_material, key_provider_->options().ratchet_salt, 256, + &new_material) != 0) { + return std::vector(); } - crypto_key_ring_[current_key_index_] = - DeriveKeys(password, key_provider_->options().ratchet_salt, 128); + return new_material; } std::shared_ptr DeriveKeys(std::vector password, @@ -136,15 +137,13 @@ class ParticipantKeyHandler { return nullptr; } - std::vector RatchetKeyMaterial( - std::vector current_material) { - webrtc::MutexLock lock(&mutex_); - std::vector new_material; - if (DerivePBKDF2KeyFromRawKey(current_material, key_provider_->options().ratchet_salt, 256, - &new_material) != 0) { - return std::vector(); +private: + void SetKeyFromMaterial(std::vector password, int key_index) { + if (key_index >= 0) { + current_key_index_ = key_index % crypto_key_ring_.size(); } - return new_material; + crypto_key_ring_[current_key_index_] = + DeriveKeys(password, key_provider_->options().ratchet_salt, 128); } protected: bool have_valid_key = false; @@ -191,7 +190,7 @@ class DefaultKeyProviderImpl : public KeyProvider { const std::string participant_id) const override { webrtc::MutexLock lock(&mutex_); - if(options_.shared_key && keys_.find(participant_id) != keys_.end()) { + if(options_.shared_key && keys_.find("shared") != keys_.end()) { return keys_.find("shared")->second; } From bb20946d75ae83464b8192b12e33f9af4428cc69 Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Thu, 31 Aug 2023 16:07:07 +0800 Subject: [PATCH 3/8] reset has_valid_key after RatchetKey. --- api/crypto/frame_crypto_transformer.cc | 5 +++-- api/crypto/frame_crypto_transformer.h | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/api/crypto/frame_crypto_transformer.cc b/api/crypto/frame_crypto_transformer.cc index 0453e14db4..4f92d42b64 100644 --- a/api/crypto/frame_crypto_transformer.cc +++ b/api/crypto/frame_crypto_transformer.cc @@ -534,7 +534,7 @@ void FrameCryptorTransformer::decryptFrame( return; } - if(last_dec_error_ == kDecryptionFailed && !key_handler->have_valid_key) { + if(last_dec_error_ == kDecryptionFailed && !key_handler->has_valid_key) { // if decryption failed and we have an invalid key, // please try to decrypt with the next new key return; @@ -584,6 +584,7 @@ void FrameCryptorTransformer::decryptFrame( decryption_success = true; // success, so we set the new key key_handler->SetKeyFromMaterial(new_material, key_index); + key_handler->has_valid_key = true; if (last_dec_error_ != FrameCryptionState::kKeyRatcheted) { last_dec_error_ = FrameCryptionState::kKeyRatcheted; if (observer_) @@ -612,7 +613,7 @@ void FrameCryptorTransformer::decryptFrame( if (!decryption_success) { if (last_dec_error_ != FrameCryptionState::kDecryptionFailed) { last_dec_error_ = FrameCryptionState::kDecryptionFailed; - key_handler->have_valid_key = false; + key_handler->has_valid_key = false; if (observer_) observer_->OnFrameCryptionStateChanged(participant_id_, last_dec_error_); diff --git a/api/crypto/frame_crypto_transformer.h b/api/crypto/frame_crypto_transformer.h index 8f358f8d48..06e11a35f8 100644 --- a/api/crypto/frame_crypto_transformer.h +++ b/api/crypto/frame_crypto_transformer.h @@ -102,6 +102,7 @@ class ParticipantKeyHandler { } SetKeyFromMaterial(new_material, key_index != -1 ? key_index : current_key_index_); + has_valid_key = true; return new_material; } @@ -113,7 +114,7 @@ class ParticipantKeyHandler { virtual void SetKey(std::vector password, int key_index) { webrtc::MutexLock lock(&mutex_); SetKeyFromMaterial(password, key_index); - have_valid_key = true; + has_valid_key = true; } std::vector RatchetKeyMaterial( @@ -145,8 +146,8 @@ class ParticipantKeyHandler { crypto_key_ring_[current_key_index_] = DeriveKeys(password, key_provider_->options().ratchet_salt, 128); } - protected: - bool have_valid_key = false; +protected: + bool has_valid_key = false; private: mutable webrtc::Mutex mutex_; int current_key_index_ = 0; From a4dba5c759f6fb956a05a83bed0c94e7331c76f3 Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Thu, 31 Aug 2023 22:05:30 +0800 Subject: [PATCH 4/8] update. --- api/crypto/frame_crypto_transformer.cc | 6 +-- api/crypto/frame_crypto_transformer.h | 58 ++++++++++++++------------ 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/api/crypto/frame_crypto_transformer.cc b/api/crypto/frame_crypto_transformer.cc index 4f92d42b64..554f3f5acf 100644 --- a/api/crypto/frame_crypto_transformer.cc +++ b/api/crypto/frame_crypto_transformer.cc @@ -534,7 +534,7 @@ void FrameCryptorTransformer::decryptFrame( return; } - if(last_dec_error_ == kDecryptionFailed && !key_handler->has_valid_key) { + if(last_dec_error_ == kDecryptionFailed && !key_handler->HasValidKey()) { // if decryption failed and we have an invalid key, // please try to decrypt with the next new key return; @@ -584,7 +584,7 @@ void FrameCryptorTransformer::decryptFrame( decryption_success = true; // success, so we set the new key key_handler->SetKeyFromMaterial(new_material, key_index); - key_handler->has_valid_key = true; + key_handler->SetHasValidKey(true); if (last_dec_error_ != FrameCryptionState::kKeyRatcheted) { last_dec_error_ = FrameCryptionState::kKeyRatcheted; if (observer_) @@ -613,7 +613,7 @@ void FrameCryptorTransformer::decryptFrame( if (!decryption_success) { if (last_dec_error_ != FrameCryptionState::kDecryptionFailed) { last_dec_error_ = FrameCryptionState::kDecryptionFailed; - key_handler->has_valid_key = false; + key_handler->SetHasValidKey(false); if (observer_) observer_->OnFrameCryptionStateChanged(participant_id_, last_dec_error_); diff --git a/api/crypto/frame_crypto_transformer.h b/api/crypto/frame_crypto_transformer.h index 06e11a35f8..b670a62473 100644 --- a/api/crypto/frame_crypto_transformer.h +++ b/api/crypto/frame_crypto_transformer.h @@ -77,7 +77,6 @@ class KeyProvider : public rtc::RefCountInterface { }; class ParticipantKeyHandler { - friend class FrameCryptorTransformer; public: struct KeySet { std::vector material; @@ -93,8 +92,11 @@ class ParticipantKeyHandler { virtual ~ParticipantKeyHandler() = default; virtual std::vector RatchetKey(int key_index) { - webrtc::MutexLock lock(&mutex_); - auto current_material = GetKeySet(key_index)->material; + auto key_set = GetKeySet(key_index); + if (!key_set) { + return std::vector(); + } + auto current_material = key_set->material; std::vector new_material; if (DerivePBKDF2KeyFromRawKey(current_material, key_provider_->options().ratchet_salt, 256, &new_material) != 0) { @@ -102,7 +104,7 @@ class ParticipantKeyHandler { } SetKeyFromMaterial(new_material, key_index != -1 ? key_index : current_key_index_); - has_valid_key = true; + SetHasValidKey(true); return new_material; } @@ -112,9 +114,8 @@ class ParticipantKeyHandler { } virtual void SetKey(std::vector password, int key_index) { - webrtc::MutexLock lock(&mutex_); SetKeyFromMaterial(password, key_index); - has_valid_key = true; + SetHasValidKey(true); } std::vector RatchetKeyMaterial( @@ -138,17 +139,27 @@ class ParticipantKeyHandler { return nullptr; } -private: - void SetKeyFromMaterial(std::vector password, int key_index) { + bool HasValidKey() { + webrtc::MutexLock lock(&mutex_); + return has_valid_key_; + } + + void SetHasValidKey(bool has_valid_key) { + webrtc::MutexLock lock(&mutex_); + has_valid_key_ = has_valid_key; + } + + void SetKeyFromMaterial(std::vector password, int key_index) { + webrtc::MutexLock lock(&mutex_); if (key_index >= 0) { current_key_index_ = key_index % crypto_key_ring_.size(); } crypto_key_ring_[current_key_index_] = DeriveKeys(password, key_provider_->options().ratchet_salt, 128); } -protected: - bool has_valid_key = false; + private: + bool has_valid_key_ = false; mutable webrtc::Mutex mutex_; int current_key_index_ = 0; KeyProvider* key_provider_; @@ -204,28 +215,23 @@ class DefaultKeyProviderImpl : public KeyProvider { const std::vector RatchetKey(const std::string participant_id, int key_index) override { - webrtc::MutexLock lock(&mutex_); - if (keys_.find(participant_id) == keys_.end()) { - return std::vector(); + auto key_handler = GetKey(participant_id); + if (key_handler) { + return key_handler->RatchetKey(key_index); } - - return keys_[participant_id]->RatchetKey(key_index); + return std::vector(); } const std::vector ExportKey(const std::string participant_id, int key_index) const override { - webrtc::MutexLock lock(&mutex_); - if (keys_.find(participant_id) == keys_.end()) { - return std::vector(); + auto key_handler = GetKey(participant_id); + if (key_handler) { + auto key_set = key_handler->GetKeySet(key_index); + if (key_set) { + return key_set->material; + } } - - auto key_set = GetKey(participant_id); - - if (!key_set) { - return std::vector(); - } - - return key_set->GetKeySet(key_index)->material; + return std::vector(); } KeyProviderOptions& options() override { return options_; } From c2d3c7dfcce827f1ca5b9e5d72a6edd0891c04de Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Thu, 31 Aug 2023 22:59:56 +0800 Subject: [PATCH 5/8] clone key_handler from share_key for each participant. --- api/crypto/frame_crypto_transformer.cc | 56 +++++++++++++++----------- api/crypto/frame_crypto_transformer.h | 42 ++++++++++++++++--- 2 files changed, 69 insertions(+), 29 deletions(-) diff --git a/api/crypto/frame_crypto_transformer.cc b/api/crypto/frame_crypto_transformer.cc index 554f3f5acf..9d8ee44c9e 100644 --- a/api/crypto/frame_crypto_transformer.cc +++ b/api/crypto/frame_crypto_transformer.cc @@ -354,7 +354,10 @@ void FrameCryptorTransformer::encryptFrame( return; } - auto key_handler = key_provider_->GetKey(participant_id_); + auto key_handler = key_provider_->options().shared_key + ? key_provider_->GetSharedKey(participant_id_) + : key_provider_->GetKey(participant_id_); + if (key_handler == nullptr || key_handler->GetKeySet(key_index_) == nullptr) { RTC_LOG(LS_INFO) << "FrameCryptorTransformer::encryptFrame() no keys, or " "key_index[" @@ -462,30 +465,31 @@ void FrameCryptorTransformer::decryptFrame( sink_callback->OnTransformedFrame(std::move(frame)); return; } - + auto uncrypted_magic_bytes = key_provider_->options().uncrypted_magic_bytes; if (uncrypted_magic_bytes.size() > 0 && date_in.size() >= uncrypted_magic_bytes.size() + 1) { - auto tmp = date_in.subview(date_in.size() - (uncrypted_magic_bytes.size() + 1), - uncrypted_magic_bytes.size()); + auto tmp = + date_in.subview(date_in.size() - (uncrypted_magic_bytes.size() + 1), + uncrypted_magic_bytes.size()); if (uncrypted_magic_bytes == std::vector(tmp.begin(), tmp.end())) { - RTC_CHECK_EQ(tmp.size(), uncrypted_magic_bytes.size()); auto frame_type = date_in.subview(date_in.size() - 1, 1); RTC_CHECK_EQ(frame_type.size(), 1); - RTC_LOG(LS_INFO) << "FrameCryptorTransformer::uncrypted_magic_bytes( type " - << frame_type[0] << ", tmp " - << to_hex(tmp.data(), tmp.size()) << ", magic bytes " - << to_hex(uncrypted_magic_bytes.data(), - uncrypted_magic_bytes.size()) - << ")"; + RTC_LOG(LS_INFO) + << "FrameCryptorTransformer::uncrypted_magic_bytes( type " + << frame_type[0] << ", tmp " << to_hex(tmp.data(), tmp.size()) + << ", magic bytes " + << to_hex(uncrypted_magic_bytes.data(), uncrypted_magic_bytes.size()) + << ")"; - // magic bytes detected, this is a non-encrypted frame, skip frame decryption. + // magic bytes detected, this is a non-encrypted frame, skip frame + // decryption. rtc::Buffer data_out; - data_out.AppendData( - date_in.subview(0, date_in.size() - uncrypted_magic_bytes.size() - 1)); + data_out.AppendData(date_in.subview( + 0, date_in.size() - uncrypted_magic_bytes.size() - 1)); frame->SetData(data_out); sink_callback->OnTransformedFrame(std::move(frame)); return; @@ -518,7 +522,10 @@ void FrameCryptorTransformer::decryptFrame( return; } - auto key_handler = key_provider_->GetKey(participant_id_); + auto key_handler = key_provider_->options().shared_key + ? key_provider_->GetSharedKey(participant_id_) + : key_provider_->GetKey(participant_id_); + if (key_index >= KEYRING_SIZE || key_handler == nullptr || key_handler->GetKeySet(key_index) == nullptr) { RTC_LOG(LS_INFO) << "FrameCryptorTransformer::decryptFrame() no keys, or " @@ -534,10 +541,10 @@ void FrameCryptorTransformer::decryptFrame( return; } - if(last_dec_error_ == kDecryptionFailed && !key_handler->HasValidKey()) { - // if decryption failed and we have an invalid key, - // please try to decrypt with the next new key - return; + if (last_dec_error_ == kDecryptionFailed && !key_handler->HasValidKey()) { + // if decryption failed and we have an invalid key, + // please try to decrypt with the next new key + return; } auto key_set = key_handler->GetKeySet(key_index); @@ -573,11 +580,13 @@ void FrameCryptorTransformer::decryptFrame( << key_provider_->options().ratchet_window_size; auto new_material = key_handler->RatchetKeyMaterial(currentKeyMaterial); - ratcheted_key_set = key_handler->DeriveKeys(new_material, key_provider_->options().ratchet_salt, 128); + ratcheted_key_set = key_handler->DeriveKeys( + new_material, key_provider_->options().ratchet_salt, 128); if (AesEncryptDecrypt(EncryptOrDecrypt::kDecrypt, algorithm_, - ratcheted_key_set->encryption_key, iv, frame_header, - encrypted_payload, &buffer) == Success) { + ratcheted_key_set->encryption_key, iv, + frame_header, encrypted_payload, + &buffer) == Success) { RTC_LOG(LS_INFO) << "FrameCryptorTransformer::decryptFrame() " "ratcheted to key_index=" << static_cast(key_index); @@ -630,7 +639,8 @@ void FrameCryptorTransformer::decryptFrame( RTC_LOG(LS_INFO) << "FrameCryptorTransformer::decryptFrame() ivLength=" << static_cast(ivLength) << " unencrypted_bytes=" << static_cast(unencrypted_bytes) - << " key_index=" << static_cast(key_index_) << " aesKey=" + << " key_index=" << static_cast(key_index_) + << " aesKey=" << to_hex(key_set->encryption_key.data(), key_set->encryption_key.size()) << " iv=" << to_hex(iv.data(), iv.size()); diff --git a/api/crypto/frame_crypto_transformer.h b/api/crypto/frame_crypto_transformer.h index b670a62473..02239e6e49 100644 --- a/api/crypto/frame_crypto_transformer.h +++ b/api/crypto/frame_crypto_transformer.h @@ -54,15 +54,18 @@ class KeyProvider : public rtc::RefCountInterface { enum { kRawKeySize = 32 }; public: - virtual const std::shared_ptr GetKey( - const std::string participant_id) const = 0; virtual bool SetSharedKey(int key_index, std::vector key) = 0; + virtual const std::shared_ptr GetSharedKey(const std::string participant_id) = 0; + virtual bool SetKey(const std::string participant_id, int key_index, std::vector key) = 0; + virtual const std::shared_ptr GetKey( + const std::string participant_id) const = 0; + virtual const std::vector RatchetKey( const std::string participant_id, int key_index) = 0; @@ -91,6 +94,14 @@ class ParticipantKeyHandler { virtual ~ParticipantKeyHandler() = default; + std::shared_ptr Clone() { + auto clone = std::make_shared(key_provider_); + clone->crypto_key_ring_ = crypto_key_ring_; + clone->current_key_index_ = current_key_index_; + clone->has_valid_key_ = has_valid_key_; + return clone; + } + virtual std::vector RatchetKey(int key_index) { auto key_set = GetKeySet(key_index); if (!key_set) { @@ -180,9 +191,32 @@ class DefaultKeyProviderImpl : public KeyProvider { auto key_handler = keys_["shared"]; key_handler->SetKey(key, key_index); + + if(options_.shared_key) { + for(auto& key_pair : keys_) { + if(key_pair.first != "shared") { + key_pair.second->SetKey(key, key_index); + } + } + } return true; } + const std::shared_ptr GetSharedKey(const std::string participant_id) override { + webrtc::MutexLock lock(&mutex_); + if(options_.shared_key && keys_.find("shared") != keys_.end()) { + auto shared_key_handler = keys_["shared"]; + if (keys_.find(participant_id) != keys_.end()) { + return keys_[participant_id]; + } else { + auto key_handler_clone = shared_key_handler->Clone(); + keys_[participant_id] = key_handler_clone; + return key_handler_clone; + } + } + return nullptr; + } + /// Set the key at the given index. bool SetKey(const std::string participant_id, int index, @@ -202,10 +236,6 @@ class DefaultKeyProviderImpl : public KeyProvider { const std::string participant_id) const override { webrtc::MutexLock lock(&mutex_); - if(options_.shared_key && keys_.find("shared") != keys_.end()) { - return keys_.find("shared")->second; - } - if (keys_.find(participant_id) == keys_.end()) { return nullptr; } From 5a549637ab37d0d0db956940caf673373b1b157f Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Fri, 1 Sep 2023 08:47:56 +0800 Subject: [PATCH 6/8] add RatchetSharedKey and ExportSharedKey. --- api/crypto/frame_crypto_transformer.h | 38 ++++++++++++++++++- .../org/webrtc/FrameCryptorKeyProvider.java | 14 +++++++ .../src/jni/pc/frame_cryptor_key_provider.cc | 25 ++++++++++++ .../RTCFrameCryptorKeyProvider.h | 8 +++- .../RTCFrameCryptorKeyProvider.mm | 10 +++++ 5 files changed, 92 insertions(+), 3 deletions(-) diff --git a/api/crypto/frame_crypto_transformer.h b/api/crypto/frame_crypto_transformer.h index 02239e6e49..f1ffcee62e 100644 --- a/api/crypto/frame_crypto_transformer.h +++ b/api/crypto/frame_crypto_transformer.h @@ -59,6 +59,10 @@ class KeyProvider : public rtc::RefCountInterface { virtual const std::shared_ptr GetSharedKey(const std::string participant_id) = 0; + virtual const std::vector RatchetSharedKey(int key_index) = 0; + + virtual const std::vector ExportSharedKey(int key_index) const = 0; + virtual bool SetKey(const std::string participant_id, int key_index, std::vector key) = 0; @@ -185,6 +189,7 @@ class DefaultKeyProviderImpl : public KeyProvider { /// Set the shared key. bool SetSharedKey(int key_index, std::vector key) override { webrtc::MutexLock lock(&mutex_); + if (keys_.find("shared") == keys_.end()) { keys_["shared"] = std::make_shared(this); } @@ -198,8 +203,39 @@ class DefaultKeyProviderImpl : public KeyProvider { key_pair.second->SetKey(key, key_index); } } + return true; } - return true; + return false; + } + + const std::vector RatchetSharedKey(int key_index) override { + webrtc::MutexLock lock(&mutex_); + auto it = keys_.find("shared"); + if(it == keys_.end()) { + return std::vector(); + } + auto new_key = it->second->RatchetKey(key_index); + if(options_.shared_key) { + for(auto& key_pair : keys_) { + if(key_pair.first != "shared") { + key_pair.second->SetKey(new_key, key_index); + } + } + } + return new_key; + } + + const std::vector ExportSharedKey(int key_index) const override { + webrtc::MutexLock lock(&mutex_); + auto it = keys_.find("shared"); + if(it == keys_.end()) { + return std::vector(); + } + auto key_set = it->second->GetKeySet(key_index); + if(key_set) { + return key_set->material; + } + return std::vector(); } const std::shared_ptr GetSharedKey(const std::string participant_id) override { diff --git a/sdk/android/api/org/webrtc/FrameCryptorKeyProvider.java b/sdk/android/api/org/webrtc/FrameCryptorKeyProvider.java index 6e4a73a2bf..af2e3ff651 100644 --- a/sdk/android/api/org/webrtc/FrameCryptorKeyProvider.java +++ b/sdk/android/api/org/webrtc/FrameCryptorKeyProvider.java @@ -35,6 +35,16 @@ public boolean setSharedKey(int index, byte[] key) { return nativeSetSharedKey(nativeKeyProvider,index, key); } + public byte[] ratchetSharedKey(int index) { + checkKeyProviderExists(); + return nativeRatchetSharedKey(nativeKeyProvider, index); + } + + public byte[] exportSharedKey(int index) { + checkKeyProviderExists(); + return nativeExportSharedKey(nativeKeyProvider, index); + } + public boolean setKey(String participantId, int index, byte[] key) { checkKeyProviderExists(); return nativeSetKey(nativeKeyProvider, participantId, index, key); @@ -63,6 +73,10 @@ private void checkKeyProviderExists() { } private static native boolean nativeSetSharedKey( long keyProviderPointer, int index, byte[] key); + private static native byte[] nativeRatchetSharedKey( + long keyProviderPointer, int index); + private static native byte[] nativeExportSharedKey( + long keyProviderPointer, int index); private static native boolean nativeSetKey( long keyProviderPointer, String participantId, int index, byte[] key); private static native byte[] nativeRatchetKey( diff --git a/sdk/android/src/jni/pc/frame_cryptor_key_provider.cc b/sdk/android/src/jni/pc/frame_cryptor_key_provider.cc index 81ceb458d6..2665bdc9ab 100644 --- a/sdk/android/src/jni/pc/frame_cryptor_key_provider.cc +++ b/sdk/android/src/jni/pc/frame_cryptor_key_provider.cc @@ -43,6 +43,31 @@ static jboolean JNI_FrameCryptorKeyProvider_SetSharedKey( ->SetSharedKey(j_index,std::vector(key.begin(), key.end())); } +static base::android::ScopedJavaLocalRef +JNI_FrameCryptorKeyProvider_RatchetSharedKey( + JNIEnv* env, + jlong keyProviderPointer, + jint j_index) { + auto key_provider = + reinterpret_cast(keyProviderPointer); + auto newKey = key_provider->RatchetSharedKey(j_index); + std::vector int8tKey = + std::vector(newKey.begin(), newKey.end()); + return NativeToJavaByteArray(env, rtc::ArrayView(int8tKey)); +} + +static base::android::ScopedJavaLocalRef +JNI_FrameCryptorKeyProvider_ExportSharedKey( + JNIEnv* env, + jlong keyProviderPointer, + jint j_index) { + auto key_provider = + reinterpret_cast(keyProviderPointer); + auto key = key_provider->ExportSharedKey(j_index); + std::vector int8tKey = std::vector(key.begin(), key.end()); + return NativeToJavaByteArray(env, rtc::ArrayView(int8tKey)); +} + static jboolean JNI_FrameCryptorKeyProvider_SetKey( JNIEnv* jni, jlong j_key_provider, diff --git a/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.h b/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.h index ab879b7b9e..0122a31444 100644 --- a/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.h +++ b/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.h @@ -23,10 +23,14 @@ NS_ASSUME_NONNULL_BEGIN RTC_OBJC_EXPORT @interface RTC_OBJC_TYPE (RTCFrameCryptorKeyProvider) : NSObject -- (void)setKey:(NSData *)key withIndex:(int)index forParticipant:(NSString *)participantId; - - (void)setSharedKey:(NSData *)key withIndex:(int)index; +- (NSData *)ratchetSharedKey:(int)index; + +- (NSData *)exportSharedKey:(int)index; + +- (void)setKey:(NSData *)key withIndex:(int)index forParticipant:(NSString *)participantId; + - (NSData *)ratchetKey:(NSString *)participantId withIndex:(int)index; - (NSData *)exportKey:(NSString *)participantId withIndex:(int)index; diff --git a/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.mm b/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.mm index c0683c6a32..218a3fafb0 100644 --- a/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.mm +++ b/sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.mm @@ -62,6 +62,16 @@ - (void)setSharedKey:(NSData *)key withIndex:(int)index { std::vector((const uint8_t *)key.bytes, ((const uint8_t *)key.bytes) + key.length)); } +- (NSData *)ratchetSharedKey:(int)index { + std::vector nativeKey = _nativeKeyProvider->RatchetSharedKey(index); + return [NSData dataWithBytes:nativeKey.data() length:nativeKey.size()]; +} + +- (NSData *)exportSharedKey:(int)index { + std::vector nativeKey = _nativeKeyProvider->ExportSharedKey(index); + return [NSData dataWithBytes:nativeKey.data() length:nativeKey.size()]; +} + - (NSData *)ratchetKey:(NSString *)participantId withIndex:(int)index { std::vector nativeKey = _nativeKeyProvider->RatchetKey([participantId stdString], index); return [NSData dataWithBytes:nativeKey.data() length:nativeKey.size()]; From 38894feb0d9d3ee4b0949a38ea13222154506ca6 Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Fri, 1 Sep 2023 08:57:19 +0800 Subject: [PATCH 7/8] make KeyProvider::SetSharedKey only valid when KeyProviderOptions::shared_key == true. --- api/crypto/frame_crypto_transformer.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/api/crypto/frame_crypto_transformer.h b/api/crypto/frame_crypto_transformer.h index f1ffcee62e..c919feefcb 100644 --- a/api/crypto/frame_crypto_transformer.h +++ b/api/crypto/frame_crypto_transformer.h @@ -189,15 +189,14 @@ class DefaultKeyProviderImpl : public KeyProvider { /// Set the shared key. bool SetSharedKey(int key_index, std::vector key) override { webrtc::MutexLock lock(&mutex_); - - if (keys_.find("shared") == keys_.end()) { - keys_["shared"] = std::make_shared(this); - } + if(options_.shared_key) { + if (keys_.find("shared") == keys_.end()) { + keys_["shared"] = std::make_shared(this); + } - auto key_handler = keys_["shared"]; - key_handler->SetKey(key, key_index); + auto key_handler = keys_["shared"]; + key_handler->SetKey(key, key_index); - if(options_.shared_key) { for(auto& key_pair : keys_) { if(key_pair.first != "shared") { key_pair.second->SetKey(key, key_index); From 2f8bbd8cb364ebae8b90d5592d5082da4883ea4b Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Fri, 1 Sep 2023 09:14:41 +0800 Subject: [PATCH 8/8] remove unused enum. --- api/crypto/frame_crypto_transformer.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/api/crypto/frame_crypto_transformer.h b/api/crypto/frame_crypto_transformer.h index c919feefcb..bd245729cf 100644 --- a/api/crypto/frame_crypto_transformer.h +++ b/api/crypto/frame_crypto_transformer.h @@ -50,9 +50,6 @@ struct KeyProviderOptions { }; class KeyProvider : public rtc::RefCountInterface { - public: - enum { kRawKeySize = 32 }; - public: virtual bool SetSharedKey(int key_index, std::vector key) = 0;