Skip to content

Commit

Permalink
add failure tolerance for framecryptor. (#91)
Browse files Browse the repository at this point in the history
 * add failure tolerance for framecryptor.

 * add failureTolerance for android/objc.

 * fix: make H264's unencrypted_bytes consistent with js-sdk.

 * add SetSifTrailer.
  • Loading branch information
cloudwebrtc committed Sep 14, 2023
1 parent 98fe34e commit 87977ca
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 16 deletions.
12 changes: 6 additions & 6 deletions api/crypto/frame_crypto_transformer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ uint8_t get_unencrypted_bytes(webrtc::TransformableFrameInterface* frame,
<< "NonParameterSetNalu::payload_size: " << index.payload_size
<< ", nalu_type " << nalu_type << ", NaluIndex [" << idx++
<< "] offset: " << index.payload_start_offset;
break;
return unencrypted_bytes;
default:
break;
}
Expand Down Expand Up @@ -219,7 +219,7 @@ int AesGcmEncryptDecrypt(EncryptOrDecrypt mode,
}

if (!ok) {
RTC_LOG(LS_ERROR) << "Failed to perform AES-GCM operation.";
RTC_LOG(LS_WARNING) << "Failed to perform AES-GCM operation.";
return OperationError;
}

Expand Down Expand Up @@ -510,7 +510,7 @@ void FrameCryptorTransformer::decryptFrame(
uint8_t key_index = frame_trailer[1];

if (ivLength != getIvSize()) {
RTC_LOG(LS_ERROR) << "FrameCryptorTransformer::decryptFrame() ivLength["
RTC_LOG(LS_WARNING) << "FrameCryptorTransformer::decryptFrame() ivLength["
<< static_cast<int>(ivLength) << "] != getIvSize()["
<< static_cast<int>(getIvSize()) << "]";
if (last_dec_error_ != FrameCryptionState::kDecryptionFailed) {
Expand Down Expand Up @@ -569,7 +569,7 @@ void FrameCryptorTransformer::decryptFrame(
encrypted_payload, &buffer) == Success) {
decryption_success = true;
} else {
RTC_LOG(LS_ERROR) << "FrameCryptorTransformer::decryptFrame() failed";
RTC_LOG(LS_WARNING) << "FrameCryptorTransformer::decryptFrame() failed";
std::shared_ptr<ParticipantKeyHandler::KeySet> ratcheted_key_set;
auto currentKeyMaterial = key_set->material;
if (key_provider_->options().ratchet_window_size > 0) {
Expand All @@ -593,7 +593,7 @@ void FrameCryptorTransformer::decryptFrame(
decryption_success = true;
// success, so we set the new key
key_handler->SetKeyFromMaterial(new_material, key_index);
key_handler->SetHasValidKey(true);
key_handler->SetHasValidKey();
if (last_dec_error_ != FrameCryptionState::kKeyRatcheted) {
last_dec_error_ = FrameCryptionState::kKeyRatcheted;
if (observer_)
Expand Down Expand Up @@ -622,7 +622,7 @@ void FrameCryptorTransformer::decryptFrame(
if (!decryption_success) {
if (last_dec_error_ != FrameCryptionState::kDecryptionFailed) {
last_dec_error_ = FrameCryptionState::kDecryptionFailed;
key_handler->SetHasValidKey(false);
key_handler->DecryptionFailure();
if (observer_)
observer_->OnFrameCryptionStateChanged(participant_id_,
last_dec_error_);
Expand Down
35 changes: 29 additions & 6 deletions api/crypto/frame_crypto_transformer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ struct KeyProviderOptions {
std::vector<uint8_t> ratchet_salt;
std::vector<uint8_t> uncrypted_magic_bytes;
int ratchet_window_size;
KeyProviderOptions() : shared_key(false), ratchet_window_size(0) {}
int failure_tolerance;
KeyProviderOptions() : shared_key(false), ratchet_window_size(0), failure_tolerance(-1) {}
KeyProviderOptions(KeyProviderOptions& copy)
: shared_key(copy.shared_key),
ratchet_salt(copy.ratchet_salt),
uncrypted_magic_bytes(copy.uncrypted_magic_bytes),
ratchet_window_size(copy.ratchet_window_size) {}
ratchet_window_size(copy.ratchet_window_size),
failure_tolerance(copy.failure_tolerance) {}
};

class KeyProvider : public rtc::RefCountInterface {
Expand Down Expand Up @@ -74,6 +76,8 @@ class KeyProvider : public rtc::RefCountInterface {
virtual const std::vector<uint8_t> ExportKey(const std::string participant_id,
int key_index) const = 0;

virtual void SetSifTrailer(const std::vector<uint8_t> trailer) = 0;

virtual KeyProviderOptions& options() = 0;

protected:
Expand Down Expand Up @@ -116,7 +120,7 @@ class ParticipantKeyHandler {
}
SetKeyFromMaterial(new_material,
key_index != -1 ? key_index : current_key_index_);
SetHasValidKey(true);
SetHasValidKey();
return new_material;
}

Expand All @@ -127,7 +131,7 @@ class ParticipantKeyHandler {

virtual void SetKey(std::vector<uint8_t> password, int key_index) {
SetKeyFromMaterial(password, key_index);
SetHasValidKey(true);
SetHasValidKey();
}

std::vector<uint8_t> RatchetKeyMaterial(
Expand Down Expand Up @@ -156,9 +160,10 @@ class ParticipantKeyHandler {
return has_valid_key_;
}

void SetHasValidKey(bool has_valid_key) {
void SetHasValidKey() {
webrtc::MutexLock lock(&mutex_);
has_valid_key_ = has_valid_key;
decryption_failure_count_ = 0;
has_valid_key_ = true;
}

void SetKeyFromMaterial(std::vector<uint8_t> password, int key_index) {
Expand All @@ -170,8 +175,21 @@ class ParticipantKeyHandler {
DeriveKeys(password, key_provider_->options().ratchet_salt, 128);
}

void DecryptionFailure() {
webrtc::MutexLock lock(&mutex_);
if (key_provider_->options().failure_tolerance < 0) {
return;
}
decryption_failure_count_ += 1;

if (decryption_failure_count_ > key_provider_->options().failure_tolerance) {
has_valid_key_ = false;
}
}

private:
bool has_valid_key_ = false;
int decryption_failure_count_ = 0;
mutable webrtc::Mutex mutex_;
int current_key_index_ = 0;
KeyProvider* key_provider_;
Expand Down Expand Up @@ -296,6 +314,11 @@ class DefaultKeyProviderImpl : public KeyProvider {
return std::vector<uint8_t>();
}

void SetSifTrailer(const std::vector<uint8_t> trailer) override {
webrtc::MutexLock lock(&mutex_);
options_.uncrypted_magic_bytes = trailer;
}

KeyProviderOptions& options() override { return options_; }

private:
Expand Down
6 changes: 3 additions & 3 deletions sdk/android/api/org/webrtc/FrameCryptorFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

public class FrameCryptorFactory {
public static FrameCryptorKeyProvider createFrameCryptorKeyProvider(
boolean sharedKey, byte[] ratchetSalt, int ratchetWindowSize, byte[] uncryptedMagicBytes) {
return nativeCreateFrameCryptorKeyProvider(sharedKey, ratchetSalt, ratchetWindowSize, uncryptedMagicBytes);
boolean sharedKey, byte[] ratchetSalt, int ratchetWindowSize, byte[] uncryptedMagicBytes, int failureTolerance) {
return nativeCreateFrameCryptorKeyProvider(sharedKey, ratchetSalt, ratchetWindowSize, uncryptedMagicBytes, failureTolerance);
}

public static FrameCryptor createFrameCryptorForRtpSender(RtpSender rtpSender,
Expand All @@ -40,5 +40,5 @@ private static native FrameCryptor nativeCreateFrameCryptorForRtpReceiver(
long rtpReceiver, String participantId, int algorithm, long nativeFrameCryptorKeyProvider);

private static native FrameCryptorKeyProvider nativeCreateFrameCryptorKeyProvider(
boolean sharedKey, byte[] ratchetSalt, int ratchetWindowSize, byte[] uncryptedMagicBytes);
boolean sharedKey, byte[] ratchetSalt, int ratchetWindowSize, byte[] uncryptedMagicBytes, int failureTolerance);
}
7 changes: 7 additions & 0 deletions sdk/android/api/org/webrtc/FrameCryptorKeyProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ public byte[] exportKey(String participantId, int index) {
return nativeExportKey(nativeKeyProvider, participantId, index);
}

public void setSifTrailer(byte[] sifTrailer) {
checkKeyProviderExists();
nativeSetSifTrailer(nativeKeyProvider, sifTrailer);
}

public void dispose() {
checkKeyProviderExists();
JniCommon.nativeReleaseRef(nativeKeyProvider);
Expand All @@ -83,4 +88,6 @@ private static native byte[] nativeRatchetKey(
long keyProviderPointer, String participantId, int index);
private static native byte[] nativeExportKey(
long keyProviderPointer, String participantId, int index);
private static native void nativeSetSifTrailer(
long keyProviderPointer, byte[] sifTrailer);
}
4 changes: 3 additions & 1 deletion sdk/android/src/jni/pc/frame_cryptor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ JNI_FrameCryptorFactory_CreateFrameCryptorKeyProvider(
jboolean j_shared,
const base::android::JavaParamRef<jbyteArray>& j_ratchetSalt,
jint j_ratchetWindowSize,
const base::android::JavaParamRef<jbyteArray>& j_uncryptedMagicBytes) {
const base::android::JavaParamRef<jbyteArray>& j_uncryptedMagicBytes,
jint j_failureTolerance) {
auto ratchetSalt = JavaToNativeByteArray(env, j_ratchetSalt);
KeyProviderOptions options;
options.ratchet_salt =
Expand All @@ -182,6 +183,7 @@ JNI_FrameCryptorFactory_CreateFrameCryptorKeyProvider(
options.uncrypted_magic_bytes =
std::vector<uint8_t>(uncryptedMagicBytes.begin(), uncryptedMagicBytes.end());
options.shared_key = j_shared;
options.failure_tolerance = j_failureTolerance;
return NativeToJavaFrameCryptorKeyProvider(
env, rtc::make_ref_counted<webrtc::DefaultKeyProviderImpl>(options));
}
Expand Down
9 changes: 9 additions & 0 deletions sdk/android/src/jni/pc/frame_cryptor_key_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,14 @@ JNI_FrameCryptorKeyProvider_ExportKey(
return NativeToJavaByteArray(env, rtc::ArrayView<int8_t>(int8tKey));
}

static void JNI_FrameCryptorKeyProvider_SetSifTrailer(
JNIEnv* jni,
jlong j_key_provider,
const base::android::JavaParamRef<jbyteArray>& j_trailer) {
auto trailer = JavaToNativeByteArray(jni, j_trailer);
reinterpret_cast<webrtc::DefaultKeyProviderImpl*>(j_key_provider)
->SetSifTrailer(std::vector<uint8_t>(trailer.begin(), trailer.end()));
}

} // namespace jni
} // namespace webrtc
8 changes: 8 additions & 0 deletions sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,19 @@ RTC_OBJC_EXPORT

- (NSData *)exportKey:(NSString *)participantId withIndex:(int)index;

- (void)setSifTrailer:(NSData *)trailer;

- (instancetype)initWithRatchetSalt:(NSData *)salt
ratchetWindowSize:(int)windowSize
sharedKeyMode:(BOOL)sharedKey
uncryptedMagicBytes:(nullable NSData *)uncryptedMagicBytes;

- (instancetype)initWithRatchetSalt:(NSData *)salt
ratchetWindowSize:(int)windowSize
sharedKeyMode:(BOOL)sharedKey
uncryptedMagicBytes:(nullable NSData *)uncryptedMagicBytes
failureTolerance:(int)failureTolerance;

@end

NS_ASSUME_NONNULL_END
19 changes: 19 additions & 0 deletions sdk/objc/api/peerconnection/RTCFrameCryptorKeyProvider.mm
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,25 @@ - (instancetype)initWithRatchetSalt:(NSData *)salt
ratchetWindowSize:(int)windowSize
sharedKeyMode:(BOOL)sharedKey
uncryptedMagicBytes:(NSData *)uncryptedMagicBytes {
return [self initWithRatchetSalt:salt
ratchetWindowSize:windowSize
sharedKeyMode:sharedKey
uncryptedMagicBytes:uncryptedMagicBytes
failureTolerance:-1];
}

- (instancetype)initWithRatchetSalt:(NSData *)salt
ratchetWindowSize:(int)windowSize
sharedKeyMode:(BOOL)sharedKey
uncryptedMagicBytes:(nullable NSData *)uncryptedMagicBytes
failureTolerance:(int)failureTolerance {
if (self = [super init]) {
webrtc::KeyProviderOptions options;
options.ratchet_salt = std::vector<uint8_t>((const uint8_t *)salt.bytes,
((const uint8_t *)salt.bytes) + salt.length);
options.ratchet_window_size = windowSize;
options.shared_key = sharedKey;
options.failure_tolerance = failureTolerance;
if(uncryptedMagicBytes != nil) {
options.uncrypted_magic_bytes = std::vector<uint8_t>((const uint8_t *)uncryptedMagicBytes.bytes,
((const uint8_t *)uncryptedMagicBytes.bytes) + uncryptedMagicBytes.length);
Expand Down Expand Up @@ -82,4 +95,10 @@ - (NSData *)exportKey:(NSString *)participantId withIndex:(int)index {
return [NSData dataWithBytes:nativeKey.data() length:nativeKey.size()];
}

- (void)setSifTrailer:(NSData *)trailer {
_nativeKeyProvider->SetSifTrailer(
std::vector<uint8_t>((const uint8_t *)trailer.bytes,
((const uint8_t *)trailer.bytes) + trailer.length));
}

@end

0 comments on commit 87977ca

Please sign in to comment.