Skip to content

Commit b1c9b55

Browse files
cloudwebrtcroot
andcommitted
feat: key ratchet/derive. (#66)
* feat: key derive. * update. * add ParticipantKeyHandler. * update. * update. * update. * update. * update. * fix key derive. * chore: add kKeyRatcheted state. * fixed key ratchet. * update api for darwin. * chore: for android. * fix crash. * fix bug for setkey * chore: add ExportKey for KeyManager. * chore: key export for android. * chore: clang-format. * chore: exportKey for darwin. * chore: When ratchet and material derivation fail, the current keyset will not be updated until the decryption is successful or the ratchet count window is exceeded. * chore: magic bytes. * update. * update for darwin. * rename KeyManager to KeyProvider. * fix compile for android. * fix key retchet. * Emit the KeyRatcheted state after a successful ratchet. --------- Co-authored-by: root <root@WIN-13900KF>
1 parent 5351ab6 commit b1c9b55

22 files changed

+757
-500
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,9 @@
7272
/xcodebuild
7373
/.vscode
7474
!webrtc/*
75+
/tmp.patch
76+
/out-release
77+
/out-debug
78+
/node_modules
79+
/libwebrtc
80+
/args.txt

api/crypto/frame_crypto_transformer.cc

Lines changed: 194 additions & 57 deletions
Large diffs are not rendered by default.

api/crypto/frame_crypto_transformer.h

Lines changed: 181 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,39 +17,209 @@
1717
#ifndef WEBRTC_FRAME_CRYPTOR_TRANSFORMER_H_
1818
#define WEBRTC_FRAME_CRYPTOR_TRANSFORMER_H_
1919

20+
#include <unordered_map>
21+
2022
#include "api/frame_transformer_interface.h"
2123
#include "rtc_base/buffer.h"
2224
#include "rtc_base/synchronization/mutex.h"
2325
#include "rtc_base/system/rtc_export.h"
2426
#include "rtc_base/thread.h"
2527

28+
int DerivePBKDF2KeyFromRawKey(const std::vector<uint8_t> raw_key,
29+
const std::vector<uint8_t>& salt,
30+
unsigned int optional_length_bits,
31+
std::vector<uint8_t>* derived_key);
32+
2633
namespace webrtc {
2734

28-
class KeyManager : public rtc::RefCountInterface {
35+
const size_t KEYRING_SIZE = 16;
36+
37+
struct KeyProviderOptions {
38+
bool shared_key;
39+
std::vector<uint8_t> ratchet_salt;
40+
std::vector<uint8_t> uncrypted_magic_bytes;
41+
int ratchet_window_size;
42+
KeyProviderOptions() : shared_key(false), ratchet_window_size(0) {}
43+
KeyProviderOptions(KeyProviderOptions& copy)
44+
: shared_key(copy.shared_key),
45+
ratchet_salt(copy.ratchet_salt),
46+
uncrypted_magic_bytes(copy.uncrypted_magic_bytes),
47+
ratchet_window_size(copy.ratchet_window_size) {}
48+
};
49+
50+
class ParticipantKeyHandler {
51+
public:
52+
struct KeySet {
53+
std::vector<uint8_t> material;
54+
std::vector<uint8_t> encryption_key;
55+
KeySet(std::vector<uint8_t> material, std::vector<uint8_t> encryptionKey)
56+
: material(material), encryption_key(encryptionKey) {}
57+
};
58+
59+
public:
60+
ParticipantKeyHandler(KeyProviderOptions options) : options_(options) {
61+
cryptoKeyRing_.resize(KEYRING_SIZE);
62+
}
63+
64+
virtual ~ParticipantKeyHandler() = default;
65+
66+
virtual std::vector<uint8_t> RatchetKey(int keyIndex) {
67+
auto currentMaterial = GetKeySet(keyIndex)->material;
68+
std::vector<uint8_t> newMaterial;
69+
if (DerivePBKDF2KeyFromRawKey(currentMaterial, options_.ratchet_salt, 256,
70+
&newMaterial) != 0) {
71+
return std::vector<uint8_t>();
72+
}
73+
SetKeyFromMaterial(newMaterial,
74+
keyIndex != -1 ? keyIndex : currentKeyIndex);
75+
return newMaterial;
76+
}
77+
78+
virtual std::shared_ptr<KeySet> GetKeySet(int keyIndex) {
79+
return cryptoKeyRing_[keyIndex != -1 ? keyIndex : currentKeyIndex];
80+
}
81+
82+
virtual void SetKeyFromMaterial(std::vector<uint8_t> password, int keyIndex) {
83+
if (keyIndex >= 0) {
84+
currentKeyIndex = keyIndex % cryptoKeyRing_.size();
85+
}
86+
cryptoKeyRing_[currentKeyIndex] =
87+
DeriveKeys(password, options_.ratchet_salt, 128);
88+
}
89+
90+
virtual KeyProviderOptions& options() { return options_; }
91+
92+
std::shared_ptr<KeySet> DeriveKeys(std::vector<uint8_t> password,
93+
std::vector<uint8_t> ratchet_salt,
94+
unsigned int optional_length_bits) {
95+
std::vector<uint8_t> derived_key;
96+
if (DerivePBKDF2KeyFromRawKey(password, ratchet_salt, optional_length_bits,
97+
&derived_key) == 0) {
98+
return std::make_shared<KeySet>(password, derived_key);
99+
}
100+
return nullptr;
101+
}
102+
103+
std::vector<uint8_t> RatchetKeyMaterial(
104+
std::vector<uint8_t> currentMaterial) {
105+
std::vector<uint8_t> newMaterial;
106+
if (DerivePBKDF2KeyFromRawKey(currentMaterial, options_.ratchet_salt, 256,
107+
&newMaterial) != 0) {
108+
return std::vector<uint8_t>();
109+
}
110+
return newMaterial;
111+
}
112+
113+
private:
114+
int currentKeyIndex = 0;
115+
KeyProviderOptions options_;
116+
std::vector<std::shared_ptr<KeySet>> cryptoKeyRing_;
117+
};
118+
119+
class KeyProvider : public rtc::RefCountInterface {
29120
public:
30121
enum { kRawKeySize = 32 };
31122

32123
public:
33-
virtual const std::vector<std::vector<uint8_t>> keys(
124+
virtual const std::shared_ptr<ParticipantKeyHandler> GetKey(
34125
const std::string participant_id) const = 0;
35126

127+
virtual bool SetKey(const std::string participant_id,
128+
int index,
129+
std::vector<uint8_t> key) = 0;
130+
131+
virtual const std::vector<uint8_t> RatchetKey(
132+
const std::string participant_id,
133+
int key_index) = 0;
134+
135+
virtual const std::vector<uint8_t> ExportKey(const std::string participant_id,
136+
int key_index) const = 0;
137+
138+
virtual KeyProviderOptions& options() = 0;
139+
36140
protected:
37-
virtual ~KeyManager() {}
141+
virtual ~KeyProvider() {}
38142
};
39143

40-
enum FrameCryptionError {
144+
class DefaultKeyProviderImpl : public KeyProvider {
145+
public:
146+
DefaultKeyProviderImpl(KeyProviderOptions options) : options_(options) {}
147+
~DefaultKeyProviderImpl() override = default;
148+
149+
/// Set the key at the given index.
150+
bool SetKey(const std::string participant_id,
151+
int index,
152+
std::vector<uint8_t> key) override {
153+
webrtc::MutexLock lock(&mutex_);
154+
155+
if (keys_.find(participant_id) == keys_.end()) {
156+
keys_[participant_id] = std::make_shared<ParticipantKeyHandler>(options_);
157+
}
158+
159+
auto keyHandler = keys_[participant_id];
160+
keyHandler->SetKeyFromMaterial(key, index);
161+
162+
return true;
163+
}
164+
165+
const std::shared_ptr<ParticipantKeyHandler> GetKey(
166+
const std::string participant_id) const override {
167+
webrtc::MutexLock lock(&mutex_);
168+
if (keys_.find(participant_id) == keys_.end()) {
169+
return nullptr;
170+
}
171+
172+
return keys_.find(participant_id)->second;
173+
}
174+
175+
const std::vector<uint8_t> RatchetKey(const std::string participant_id,
176+
int key_index) override {
177+
webrtc::MutexLock lock(&mutex_);
178+
if (keys_.find(participant_id) == keys_.end()) {
179+
return std::vector<uint8_t>();
180+
}
181+
182+
return keys_[participant_id]->RatchetKey(key_index);
183+
}
184+
185+
const std::vector<uint8_t> ExportKey(const std::string participant_id,
186+
int key_index) const override {
187+
webrtc::MutexLock lock(&mutex_);
188+
if (keys_.find(participant_id) == keys_.end()) {
189+
return std::vector<uint8_t>();
190+
}
191+
192+
auto keySet = GetKey(participant_id);
193+
194+
if (!keySet) {
195+
return std::vector<uint8_t>();
196+
}
197+
198+
return keySet->GetKeySet(key_index)->material;
199+
}
200+
201+
KeyProviderOptions& options() override { return options_; }
202+
203+
private:
204+
mutable webrtc::Mutex mutex_;
205+
KeyProviderOptions options_;
206+
std::unordered_map<std::string, std::shared_ptr<ParticipantKeyHandler>> keys_;
207+
};
208+
209+
enum FrameCryptionState {
41210
kNew = 0,
42211
kOk,
43212
kEncryptionFailed,
44213
kDecryptionFailed,
45214
kMissingKey,
215+
kKeyRatcheted,
46216
kInternalError,
47217
};
48218

49219
class FrameCryptorTransformerObserver {
50220
public:
51-
virtual void OnFrameCryptionError(const std::string participant_id,
52-
FrameCryptionError error) = 0;
221+
virtual void OnFrameCryptionStateChanged(const std::string participant_id,
222+
FrameCryptionState error) = 0;
53223

54224
protected:
55225
virtual ~FrameCryptorTransformerObserver() {}
@@ -71,7 +241,7 @@ class RTC_EXPORT FrameCryptorTransformer
71241
explicit FrameCryptorTransformer(const std::string participant_id,
72242
MediaType type,
73243
Algorithm algorithm,
74-
rtc::scoped_refptr<KeyManager> key_manager);
244+
rtc::scoped_refptr<KeyProvider> key_provider);
75245

76246
virtual void SetFrameCryptorTransformerObserver(
77247
FrameCryptorTransformerObserver* observer) {
@@ -85,6 +255,7 @@ class RTC_EXPORT FrameCryptorTransformer
85255
}
86256

87257
virtual int key_index() const { return key_index_; }
258+
88259
virtual void SetEnabled(bool enabled) {
89260
webrtc::MutexLock lock(&mutex_);
90261
enabled_cryption_ = enabled;
@@ -140,11 +311,11 @@ class RTC_EXPORT FrameCryptorTransformer
140311
sink_callbacks_;
141312
int key_index_ = 0;
142313
std::map<uint32_t, uint32_t> sendCounts_;
143-
rtc::scoped_refptr<KeyManager> key_manager_;
314+
rtc::scoped_refptr<KeyProvider> key_provider_;
144315
FrameCryptorTransformerObserver* observer_ = nullptr;
145316
std::unique_ptr<rtc::Thread> thread_;
146-
FrameCryptionError last_enc_error_ = FrameCryptionError::kNew;
147-
FrameCryptionError last_dec_error_ = FrameCryptionError::kNew;
317+
FrameCryptionState last_enc_error_ = FrameCryptionState::kNew;
318+
FrameCryptionState last_dec_error_ = FrameCryptionState::kNew;
148319
};
149320

150321
} // namespace webrtc

sdk/BUILD.gn

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,9 +1024,9 @@ if (is_ios || is_mac) {
10241024
"objc/api/peerconnection/RTCFrameCryptor+Private.h",
10251025
"objc/api/peerconnection/RTCFrameCryptor.h",
10261026
"objc/api/peerconnection/RTCFrameCryptor.mm",
1027-
"objc/api/peerconnection/RTCFrameCryptorKeyManager+Private.h",
1028-
"objc/api/peerconnection/RTCFrameCryptorKeyManager.h",
1029-
"objc/api/peerconnection/RTCFrameCryptorKeyManager.mm",
1027+
"objc/api/peerconnection/RTCFrameCryptorKeyProvider+Private.h",
1028+
"objc/api/peerconnection/RTCFrameCryptorKeyProvider.h",
1029+
"objc/api/peerconnection/RTCFrameCryptorKeyProvider.mm",
10301030
"objc/api/peerconnection/RTCIceCandidate+Private.h",
10311031
"objc/api/peerconnection/RTCIceCandidate.h",
10321032
"objc/api/peerconnection/RTCIceCandidate.mm",
@@ -1381,7 +1381,7 @@ if (is_ios || is_mac) {
13811381
"objc/api/peerconnection/RTCDataChannel.h",
13821382
"objc/api/peerconnection/RTCDataChannelConfiguration.h",
13831383
"objc/api/peerconnection/RTCFrameCryptor.h",
1384-
"objc/api/peerconnection/RTCFrameCryptorKeyManager.h",
1384+
"objc/api/peerconnection/RTCFrameCryptorKeyProvider.h",
13851385
"objc/api/peerconnection/RTCFieldTrials.h",
13861386
"objc/api/peerconnection/RTCIceCandidate.h",
13871387
"objc/api/peerconnection/RTCIceCandidateErrorEvent.h",
@@ -1505,7 +1505,7 @@ if (is_ios || is_mac) {
15051505
"objc/api/peerconnection/RTCDataChannelConfiguration.h",
15061506
"objc/api/peerconnection/RTCDtmfSender.h",
15071507
"objc/api/peerconnection/RTCFrameCryptor.h",
1508-
"objc/api/peerconnection/RTCFrameCryptorKeyManager.h",
1508+
"objc/api/peerconnection/RTCFrameCryptorKeyProvider.h",
15091509
"objc/api/peerconnection/RTCFieldTrials.h",
15101510
"objc/api/peerconnection/RTCIceCandidate.h",
15111511
"objc/api/peerconnection/RTCIceCandidateErrorEvent.h",

sdk/android/BUILD.gn

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ if (is_android) {
264264
"api/org/webrtc/FrameCryptor.java",
265265
"api/org/webrtc/FrameCryptorAlgorithm.java",
266266
"api/org/webrtc/FrameCryptorFactory.java",
267-
"api/org/webrtc/FrameCryptorKeyManager.java",
267+
"api/org/webrtc/FrameCryptorKeyProvider.java",
268268
"api/org/webrtc/FrameDecryptor.java",
269269
"api/org/webrtc/FrameEncryptor.java",
270270
"api/org/webrtc/IceCandidate.java",
@@ -291,6 +291,10 @@ if (is_android) {
291291
"api/org/webrtc/RTCStatsCollectorCallback.java",
292292
"api/org/webrtc/RTCStatsReport.java",
293293
"api/org/webrtc/RtcCertificatePem.java",
294+
"api/org/webrtc/FrameCryptor.java",
295+
"api/org/webrtc/FrameCryptorAlgorithm.java",
296+
"api/org/webrtc/FrameCryptorFactory.java",
297+
"api/org/webrtc/FrameCryptorKeyProvider.java",
294298
"api/org/webrtc/RtpCapabilities.java",
295299
"api/org/webrtc/RtpParameters.java",
296300
"api/org/webrtc/RtpReceiver.java",
@@ -724,8 +728,8 @@ if (current_os == "linux" || is_android) {
724728
"src/jni/pc/dtmf_sender.cc",
725729
"src/jni/pc/frame_cryptor.cc",
726730
"src/jni/pc/frame_cryptor.h",
727-
"src/jni/pc/frame_cryptor_key_manager.cc",
728-
"src/jni/pc/frame_cryptor_key_manager.h",
731+
"src/jni/pc/frame_cryptor_key_provider.cc",
732+
"src/jni/pc/frame_cryptor_key_provider.h",
729733
"src/jni/pc/ice_candidate.cc",
730734
"src/jni/pc/ice_candidate.h",
731735
"src/jni/pc/media_constraints.cc",
@@ -1411,7 +1415,7 @@ if (current_os == "linux" || is_android) {
14111415
"api/org/webrtc/DtmfSender.java",
14121416
"api/org/webrtc/FrameCryptor.java",
14131417
"api/org/webrtc/FrameCryptorFactory.java",
1414-
"api/org/webrtc/FrameCryptorKeyManager.java",
1418+
"api/org/webrtc/FrameCryptorKeyProvider.java",
14151419
"api/org/webrtc/IceCandidate.java",
14161420
"api/org/webrtc/IceCandidateErrorEvent.java",
14171421
"api/org/webrtc/MediaConstraints.java",

sdk/android/api/org/webrtc/FrameCryptor.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,24 @@
1919
import androidx.annotation.Nullable;
2020

2121
public class FrameCryptor {
22-
23-
public enum FrameCryptorErrorState {
22+
public enum FrameCryptionState {
2423
NEW,
2524
OK,
2625
ENCRYPTIONFAILED,
2726
DECRYPTIONFAILED,
2827
MISSINGKEY,
28+
KEYRATCHETED,
2929
INTERNALERROR;
3030

31-
@CalledByNative("FrameCryptorErrorState")
32-
static FrameCryptorErrorState fromNativeIndex(int nativeIndex) {
31+
@CalledByNative("FrameCryptionState")
32+
static FrameCryptionState fromNativeIndex(int nativeIndex) {
3333
return values()[nativeIndex];
3434
}
3535
}
3636

3737
public static interface Observer {
3838
@CalledByNative("Observer")
39-
void onFrameCryptorErrorState(String participantId, FrameCryptorErrorState newState);
39+
void onFrameCryptionStateChanged(String participantId, FrameCryptionState newState);
4040
}
4141

4242
private long nativeFrameCryptor;
@@ -74,23 +74,23 @@ public void setKeyIndex(int index) {
7474

7575
public void dispose() {
7676
checkFrameCryptorExists();
77+
nativeUnSetObserver(nativeFrameCryptor);
7778
JniCommon.nativeReleaseRef(nativeFrameCryptor);
7879
nativeFrameCryptor = 0;
79-
if(observerPtr != 0) {
80+
if (observerPtr != 0) {
8081
JniCommon.nativeReleaseRef(observerPtr);
8182
observerPtr = 0;
8283
}
83-
nativeUnSetObserver(nativeFrameCryptor);
8484
}
8585

8686
public void setObserver(@Nullable Observer observer) {
8787
checkFrameCryptorExists();
8888
long newPtr = nativeSetObserver(nativeFrameCryptor, observer);
89-
if(observerPtr != 0) {
89+
if (observerPtr != 0) {
9090
JniCommon.nativeReleaseRef(observerPtr);
9191
observerPtr = 0;
9292
}
93-
newPtr= observerPtr;
93+
newPtr = observerPtr;
9494
}
9595

9696
private void checkFrameCryptorExists() {

0 commit comments

Comments
 (0)