Skip to content

Commit

Permalink
fix: validate account_data values instead of checking them in syncUpd…
Browse files Browse the repository at this point in the history
…ates
  • Loading branch information
td-famedly committed Dec 18, 2023
1 parent 0bb1e3b commit 3a06b38
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 41 deletions.
20 changes: 13 additions & 7 deletions lib/encryption/ssss.dart
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,16 @@ class SSSS {
}()
.firstWhere((keyId) => getKey(keyId) == null);

final accountDataType = EventTypes.secretStorageKey(keyId);
final accountDataTypeKeyId = EventTypes.secretStorageKey(keyId);
// noooow we set the account data
final waitForAccountData = client.onSync.stream.firstWhere((syncUpdate) =>
syncUpdate.accountData != null &&
syncUpdate.accountData!
.any((accountData) => accountData.type == accountDataType));

await client.setAccountData(
client.userID!, accountDataType, content.toJson());
await waitForAccountData;
client.userID!, accountDataTypeKeyId, content.toJson());

while (!client.accountData.containsKey(accountDataTypeKeyId)) {
Logs().v('Waiting accountData to have $accountDataTypeKeyId');
await client.oneShotSync(timeout: Duration(seconds: 3));
}

final key = open(keyId);
await key.setPrivateKey(privateKey);
Expand Down Expand Up @@ -750,6 +751,11 @@ class OpenSSSS {
throw Exception('SSSS not unlocked');
}
await ssss.store(type, secret, keyId, privateKey, add: add);

while (await getStored(type) != secret) {
Logs().v('Wait for secret to come down sync');
await ssss.client.oneShotSync(timeout: Duration(seconds: 3));
}
}

Future<void> validateAndStripOtherKeys(String type, String secret) async {
Expand Down
45 changes: 13 additions & 32 deletions lib/encryption/utils/bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class Bootstrap {

// cache the secret analyzing so that we don't drop stuff a different client sets during bootstrapping
Map<String, Set<String>>? _secretsCache;

/// returns ssss from accountdata, eg: m.megolm_backup.v1, or your m.cross_signing stuff
Map<String, Set<String>> analyzeSecrets() {
final secretsCache = _secretsCache;
if (secretsCache != null) {
Expand Down Expand Up @@ -292,12 +294,12 @@ class Bootstrap {
}
// alright, we re-encrypted all the secrets. We delete the dead weight only *after* we set our key to the default key
}
final updatedAccountData = client.onSync.stream.firstWhere((syncUpdate) =>
syncUpdate.accountData != null &&
syncUpdate.accountData!.any((accountData) =>
accountData.type == EventTypes.SecretStorageDefaultKey));
await encryption.ssss.setDefaultKeyId(newSsssKey!.keyId);
await updatedAccountData;
while (encryption.ssss.defaultKeyId != newSsssKey!.keyId) {
Logs().v(
'Waiting accountData to have the correct m.secret_storage.default_key');
await client.oneShotSync(timeout: Duration(seconds: 3));
}
if (oldSsssKeys != null) {
for (final entry in secretMap!.entries) {
Logs().v('Validate and stripe other keys ${entry.key}...');
Expand Down Expand Up @@ -479,33 +481,20 @@ class Bootstrap {
));
Logs().v('Device signing keys have been uploaded.');
// aaaand set the SSSS secrets
final futures = <Future<void>>[];
if (masterKey != null) {
futures.add(
client.onSync.stream
.firstWhere((syncUpdate) =>
masterKey?.publicKey != null &&
client.userDeviceKeys[client.userID]?.masterKey?.ed25519Key ==
masterKey?.publicKey)
.then((_) => Logs().v('New Master Key was created')),
);
while (!(masterKey.publicKey != null &&
client.userDeviceKeys[client.userID]?.masterKey?.ed25519Key ==
masterKey.publicKey)) {
Logs().v('Waiting for master to be created');
await client.oneShotSync(timeout: Duration(seconds: 3));
}
}
for (final entry in secretsToStore.entries) {
futures.add(
client.onSync.stream
.firstWhere((syncUpdate) =>
syncUpdate.accountData != null &&
syncUpdate.accountData!
.any((accountData) => accountData.type == entry.key))
.then((_) =>
Logs().v('New Key with type ${entry.key} was created')),
);
Logs().v('Store new SSSS key ${entry.key}...');
await newSsssKey?.store(entry.key, entry.value);
}
Logs().v(
'Wait for MasterKey and ${secretsToStore.entries.length} keys to be created');
await Future.wait<void>(futures);
final keysToSign = <SignableKey>[];
if (masterKey != null) {
if (client.userDeviceKeys[client.userID]?.masterKey?.ed25519Key !=
Expand Down Expand Up @@ -581,14 +570,6 @@ class Bootstrap {
);
Logs().v('Store the secret...');
await newSsssKey?.store(megolmKey, base64.encode(privKey));
Logs().v('Wait for secret to come down sync');

if (!await encryption.keyManager.isCached()) {
await client.onSync.stream.firstWhere((syncUpdate) =>
syncUpdate.accountData != null &&
syncUpdate.accountData!
.any((accountData) => accountData.type == megolmKey));
}

Logs().v(
'And finally set all megolm keys as needing to be uploaded again...');
Expand Down
4 changes: 2 additions & 2 deletions lib/src/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1652,8 +1652,8 @@ class Client extends MatrixApi {

/// Immediately start a sync and wait for completion.
/// If there is an active sync already, wait for the active sync instead.
Future<void> oneShotSync() {
return _sync();
Future<void> oneShotSync({Duration? timeout}) {
return _sync(timeout: timeout);
}

/// Pass a timeout to set how long the server waits before sending an empty response.
Expand Down

0 comments on commit 3a06b38

Please sign in to comment.