Skip to content

feat: add frame encryptor/decryptor interface. #46

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 49 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
29e7fff
feat: add frame encryptor/decryptor interface.
cloudwebrtc Sep 19, 2022
c9fa341
chore: add crypto class.
cloudwebrtc Sep 27, 2022
5e861d2
update.
cloudwebrtc Nov 17, 2022
8a72f8c
chore: add aes-256-gcm.
cloudwebrtc Nov 18, 2022
ff610e2
chore: cleanup.
cloudwebrtc Nov 18, 2022
1f8c943
update.
cloudwebrtc Nov 21, 2022
a007e76
chore: fill iv correctly.
cloudwebrtc Nov 21, 2022
4a86c5b
chore: New aes algorithm, compatible with webcrypto.
cloudwebrtc Nov 25, 2022
7faa1f2
chore: Remove FrameCryptor interface export.
cloudwebrtc Nov 28, 2022
7a090de
update.
cloudwebrtc Nov 28, 2022
ee7add8
update.
cloudwebrtc Dec 5, 2022
ef3ca8d
update.
cloudwebrtc Dec 9, 2022
db97425
Merge branch 'master' into feat/frame-encryptor-interface
cloudwebrtc Dec 9, 2022
2a2f3bc
Merge branch 'master' into feat/frame-encryptor-interface
cloudwebrtc Dec 9, 2022
bac087d
add KeyManager.
cloudwebrtc Dec 9, 2022
d9a3693
update.
cloudwebrtc Dec 9, 2022
ced81e6
update.
cloudwebrtc Dec 9, 2022
08685eb
fix compile.
cloudwebrtc Dec 11, 2022
e498b4a
update.
cloudwebrtc Dec 13, 2022
c92f25c
fix typo.
cloudwebrtc Dec 13, 2022
1369cb4
update.
cloudwebrtc Dec 13, 2022
fc4bbc6
update.
cloudwebrtc Dec 13, 2022
25b9483
fix crash for copy rtp params.
cloudwebrtc Dec 13, 2022
ce9ed12
fix bug
cloudwebrtc Dec 13, 2022
65eef62
Add participant_id.
cloudwebrtc Dec 13, 2022
94f9853
update.
cloudwebrtc Dec 14, 2022
e1fd06b
update.
cloudwebrtc Dec 19, 2022
bf5f7f9
Merge branch 'master' into feat/frame-encryptor-interface
cloudwebrtc Feb 1, 2023
d179f85
fix compile error.
cloudwebrtc Feb 1, 2023
9517a06
framecryptor state callback.
cloudwebrtc Feb 4, 2023
2c445a4
fix crash.
cloudwebrtc Feb 5, 2023
5e7ac5a
update.
cloudwebrtc Feb 6, 2023
e624e8d
update.
cloudwebrtc Feb 8, 2023
2939559
Merge branch 'master' into feat/frame-encryptor-interface
cloudwebrtc Feb 17, 2023
4e26a1d
update.
cloudwebrtc Feb 20, 2023
1c7c283
Merge branch 'master' into feat/frame-encryptor-interface
cloudwebrtc Feb 23, 2023
285f886
Merge branch 'master' into feat/frame-encryptor-interface
cloudwebrtc Feb 24, 2023
4e2ead7
update.
cloudwebrtc Mar 27, 2023
1a0ee8c
Merge branch 'master' into feat/frame-encryptor-interface
Mar 27, 2023
01e69a5
chore: add kKeyRatcheted state.
cloudwebrtc Mar 28, 2023
673fd6c
Merge branch 'master' into feat/frame-encryptor-interface
cloudwebrtc Mar 28, 2023
683fe43
chore: revert changes.
cloudwebrtc Mar 29, 2023
164b39e
chore: clang-format.
cloudwebrtc Mar 29, 2023
1ed2029
update.
cloudwebrtc Apr 24, 2023
45eec5d
rename KeyManager to KeyProvider.
cloudwebrtc Apr 24, 2023
4e87e75
update.
cloudwebrtc Apr 24, 2023
61dae4f
export key.
cloudwebrtc Apr 24, 2023
f6b8a32
Merge branch 'master' into feat/frame-encryptor-interface
cloudwebrtc Apr 24, 2023
a601f7a
Merge branch 'feat/frame-encryptor-interface' of https://github.com/w…
cloudwebrtc Apr 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ rtc_shared_library("libwebrtc") {
"include/rtc_data_channel.h",
"include/rtc_dtls_transport.h",
"include/rtc_dtmf_sender.h",
"include/rtc_frame_cryptor.h",
"include/rtc_ice_candidate.h",
"include/rtc_media_stream.h",
"include/rtc_media_track.h",
Expand Down Expand Up @@ -101,6 +102,8 @@ rtc_shared_library("libwebrtc") {
"src/rtc_dtls_transport_impl.h",
"src/rtc_dtmf_sender_impl.cc",
"src/rtc_dtmf_sender_impl.h",
"src/rtc_frame_cryptor_impl.cc",
"src/rtc_frame_cryptor_impl.h",
"src/rtc_ice_candidate_impl.cc",
"src/rtc_ice_candidate_impl.h",
"src/rtc_media_stream_impl.cc",
Expand Down Expand Up @@ -199,6 +202,7 @@ rtc_shared_library("libwebrtc") {
"../api:libjingle_peerconnection_api",
"../api/audio_codecs:builtin_audio_decoder_factory",
"../api/audio_codecs:builtin_audio_encoder_factory",
"../api/crypto:frame_crypto_transformer",
"../api/video:video_frame",
"../api/video_codecs:builtin_video_decoder_factory",
"../api/video_codecs:builtin_video_encoder_factory",
Expand All @@ -214,6 +218,7 @@ rtc_shared_library("libwebrtc") {
"../rtc_base:rtc_base",
"../sdk:media_constraints",
"//third_party/abseil-cpp/absl/memory",
"//third_party/boringssl:boringssl",
"//third_party/libyuv",
]

Expand Down
116 changes: 116 additions & 0 deletions include/rtc_frame_cryptor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#ifndef LIB_RTC_FRAME_CYRPTOR_H_
#define LIB_RTC_FRAME_CYRPTOR_H_

#include "base/refcount.h"
#include "rtc_rtp_receiver.h"
#include "rtc_rtp_sender.h"
#include "rtc_types.h"

namespace libwebrtc {

enum class Algorithm {
kAesGcm = 0,
kAesCbc,
};

struct KeyProviderOptions {
bool shared_key;
vector<uint8_t> ratchet_salt;
vector<uint8_t> uncrypted_magic_bytes;
int ratchet_window_size;
KeyProviderOptions()
: shared_key(false),
ratchet_salt(vector<uint8_t>()),
ratchet_window_size(0) {}
KeyProviderOptions(KeyProviderOptions& copy)
: shared_key(copy.shared_key),
ratchet_salt(copy.ratchet_salt),
ratchet_window_size(copy.ratchet_window_size) {}
};

/// Shared secret key for frame encryption.
class KeyProvider : public RefCountInterface {
public:
LIB_WEBRTC_API static scoped_refptr<KeyProvider> Create(KeyProviderOptions*);

/// Set the key at the given index.
virtual bool SetKey(const string participant_id,
int index,
vector<uint8_t> key) = 0;

virtual vector<uint8_t> RatchetKey(const string participant_id,
int key_index) = 0;

virtual vector<uint8_t> ExportKey(const string participant_id,
int key_index) = 0;
protected:
virtual ~KeyProvider() {}
};

enum RTCFrameCryptionState {
kNew = 0,
kOk,
kEncryptionFailed,
kDecryptionFailed,
kMissingKey,
kKeyRatcheted,
kInternalError,
};

class RTCFrameCryptorObserver {
public:
virtual void OnFrameCryptionStateChanged(const string participant_id,
RTCFrameCryptionState state) = 0;

protected:
virtual ~RTCFrameCryptorObserver() {}
};

/// Frame encryption/decryption.
///
class RTCFrameCryptor : public RefCountInterface {
public:
/// Enable/Disable frame crypto for the sender or receiver.
virtual bool SetEnabled(bool enabled) = 0;

/// Get the enabled state for the sender or receiver.
virtual bool enabled() const = 0;

/// Set the key index for the sender or receiver.
/// If the key index is not set, the key index will be set to 0.
virtual bool SetKeyIndex(int index) = 0;

/// Get the key index for the sender or receiver.
virtual int key_index() const = 0;

virtual const string participant_id() const = 0;

virtual void RegisterRTCFrameCryptorObserver(
RTCFrameCryptorObserver* observer) = 0;

virtual void DeRegisterRTCFrameCryptorObserver() = 0;

protected:
virtual ~RTCFrameCryptor() {}
};

class FrameCryptorFactory {
public:
/// Create a frame cyrptor for [RTCRtpSender].
LIB_WEBRTC_API static scoped_refptr<RTCFrameCryptor>
frameCryptorFromRtpSender(const string participant_id,
scoped_refptr<RTCRtpSender> sender,
Algorithm algorithm,
scoped_refptr<KeyProvider> key_provider);

/// Create a frame cyrptor for [RTCRtpReceiver].
LIB_WEBRTC_API static scoped_refptr<RTCFrameCryptor>
frameCryptorFromRtpReceiver(const string participant_id,
scoped_refptr<RTCRtpReceiver> receiver,
Algorithm algorithm,
scoped_refptr<KeyProvider> key_provider);
};

} // namespace libwebrtc

#endif // LIB_RTC_FRAME_CYRPTOR_H_
165 changes: 165 additions & 0 deletions src/rtc_frame_cryptor_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#include "rtc_frame_cryptor_impl.h"

namespace libwebrtc {

scoped_refptr<RTCFrameCryptor> FrameCryptorFactory::frameCryptorFromRtpSender(
const string participant_id,
scoped_refptr<RTCRtpSender> sender,
Algorithm algorithm,
scoped_refptr<KeyProvider> key_provider) {
return new RefCountedObject<RTCFrameCryptorImpl>(participant_id, algorithm,
key_provider, sender);
}

/// Create a frame cyrptor from a [RTCRtpReceiver].
scoped_refptr<RTCFrameCryptor> FrameCryptorFactory::frameCryptorFromRtpReceiver(
const string participant_id,
scoped_refptr<RTCRtpReceiver> receiver,
Algorithm algorithm,
scoped_refptr<KeyProvider> key_provider) {
return new RefCountedObject<RTCFrameCryptorImpl>(participant_id, algorithm,
key_provider, receiver);
}

webrtc::FrameCryptorTransformer::Algorithm AlgorithmToFrameCryptorAlgorithm(
Algorithm algorithm) {
switch (algorithm) {
case Algorithm::kAesGcm:
return webrtc::FrameCryptorTransformer::Algorithm::kAesGcm;
case Algorithm::kAesCbc:
return webrtc::FrameCryptorTransformer::Algorithm::kAesCbc;
default:
return webrtc::FrameCryptorTransformer::Algorithm::kAesGcm;
}
}

RTCFrameCryptorImpl::RTCFrameCryptorImpl(const string participant_id,
Algorithm algorithm,
scoped_refptr<KeyProvider> key_provider,
scoped_refptr<RTCRtpSender> sender)
: participant_id_(participant_id),
enabled_(false),
key_index_(0),
key_provider_(key_provider),
sender_(sender) {
auto keyImpl = static_cast<DefaultKeyProviderImpl*>(key_provider.get());
RTCRtpSenderImpl* impl = static_cast<RTCRtpSenderImpl*>(sender.get());
auto mediaType =
impl->rtc_rtp_sender()->track()->kind() == "audio"
? webrtc::FrameCryptorTransformer::MediaType::kAudioFrame
: webrtc::FrameCryptorTransformer::MediaType::kVideoFrame;
e2ee_transformer_ = rtc::scoped_refptr<webrtc::FrameCryptorTransformer>(
new webrtc::FrameCryptorTransformer(
participant_id_.std_string(), mediaType,
AlgorithmToFrameCryptorAlgorithm(algorithm),
keyImpl->rtc_key_provider()));
e2ee_transformer_->SetFrameCryptorTransformerObserver(this);
impl->rtc_rtp_sender()->SetEncoderToPacketizerFrameTransformer(
e2ee_transformer_);
e2ee_transformer_->SetEnabled(false);
}

RTCFrameCryptorImpl::RTCFrameCryptorImpl(const string participant_id,
Algorithm algorithm,
scoped_refptr<KeyProvider> key_provider,
scoped_refptr<RTCRtpReceiver> receiver)
: participant_id_(participant_id),
enabled_(false),
key_index_(0),
key_provider_(key_provider),
receiver_(receiver) {
auto keyImpl = static_cast<DefaultKeyProviderImpl*>(key_provider.get());
RTCRtpReceiverImpl* impl = static_cast<RTCRtpReceiverImpl*>(receiver.get());
auto mediaType =
impl->rtp_receiver()->track()->kind() == "audio"
? webrtc::FrameCryptorTransformer::MediaType::kAudioFrame
: webrtc::FrameCryptorTransformer::MediaType::kVideoFrame;
e2ee_transformer_ = rtc::scoped_refptr<webrtc::FrameCryptorTransformer>(
new webrtc::FrameCryptorTransformer(
participant_id_.std_string(), mediaType,
AlgorithmToFrameCryptorAlgorithm(algorithm),
keyImpl->rtc_key_provider()));
e2ee_transformer_->SetFrameCryptorTransformerObserver(this);
impl->rtp_receiver()->SetDepacketizerToDecoderFrameTransformer(
e2ee_transformer_);
e2ee_transformer_->SetEnabled(false);
}

RTCFrameCryptorImpl::~RTCFrameCryptorImpl() {}

bool RTCFrameCryptorImpl::SetEnabled(bool enabled) {
webrtc::MutexLock lock(&mutex_);
enabled_ = enabled;
e2ee_transformer_->SetEnabled(enabled_);
return true;
}

void RTCFrameCryptorImpl::RegisterRTCFrameCryptorObserver(
RTCFrameCryptorObserver* observer) {
webrtc::MutexLock lock(&mutex_);
observer_ = observer;
}

void RTCFrameCryptorImpl::DeRegisterRTCFrameCryptorObserver() {
webrtc::MutexLock lock(&mutex_);
observer_ = nullptr;
e2ee_transformer_->SetFrameCryptorTransformerObserver(nullptr);
}

void RTCFrameCryptorImpl::OnFrameCryptionStateChanged(
const std::string participant_id,
webrtc::FrameCryptionState error) {
{
RTCFrameCryptionState state = RTCFrameCryptionState::kNew;
switch (error) {
case webrtc::FrameCryptionState::kNew:
state = RTCFrameCryptionState::kNew;
break;
case webrtc::FrameCryptionState::kOk:
state = RTCFrameCryptionState::kOk;
break;
case webrtc::FrameCryptionState::kDecryptionFailed:
state = RTCFrameCryptionState::kDecryptionFailed;
break;
case webrtc::FrameCryptionState::kEncryptionFailed:
state = RTCFrameCryptionState::kEncryptionFailed;
break;
case webrtc::FrameCryptionState::kMissingKey:
state = RTCFrameCryptionState::kMissingKey;
break;
case webrtc::FrameCryptionState::kKeyRatcheted:
state = RTCFrameCryptionState::kKeyRatcheted;
break;
case webrtc::FrameCryptionState::kInternalError:
state = RTCFrameCryptionState::kInternalError;
break;
}
webrtc::MutexLock lock(&mutex_);
if (observer_) {
observer_->OnFrameCryptionStateChanged(participant_id_, state);
}
}
}

bool RTCFrameCryptorImpl::enabled() const {
webrtc::MutexLock lock(&mutex_);
return enabled_;
}

bool RTCFrameCryptorImpl::SetKeyIndex(int index) {
webrtc::MutexLock lock(&mutex_);
key_index_ = index;
e2ee_transformer_->SetKeyIndex(key_index_);
return true;
}

int RTCFrameCryptorImpl::key_index() const {
webrtc::MutexLock lock(&mutex_);
return key_index_;
}

scoped_refptr<KeyProvider> KeyProvider::Create(KeyProviderOptions* options) {
return new RefCountedObject<DefaultKeyProviderImpl>(options);
}

} // namespace libwebrtc
Loading