Skip to content

Commit 3cbd8b1

Browse files
committed
fix: validate account_data values instead of checking them in syncUpdates
1 parent e1d4af8 commit 3cbd8b1

File tree

4 files changed

+48
-45
lines changed

4 files changed

+48
-45
lines changed

lib/encryption/ssss.dart

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -248,15 +248,16 @@ class SSSS {
248248
}()
249249
.firstWhere((keyId) => getKey(keyId) == null);
250250

251-
final accountDataType = EventTypes.secretStorageKey(keyId);
251+
final accountDataTypeKeyId = EventTypes.secretStorageKey(keyId);
252252
// noooow we set the account data
253-
final waitForAccountData = client.onSync.stream.firstWhere((syncUpdate) =>
254-
syncUpdate.accountData != null &&
255-
syncUpdate.accountData!
256-
.any((accountData) => accountData.type == accountDataType));
253+
257254
await client.setAccountData(
258-
client.userID!, accountDataType, content.toJson());
259-
await waitForAccountData;
255+
client.userID!, accountDataTypeKeyId, content.toJson());
256+
257+
while (!client.accountData.containsKey(accountDataTypeKeyId)) {
258+
Logs().v('Waiting accountData to have $accountDataTypeKeyId');
259+
await client.oneShotSync();
260+
}
260261

261262
final key = open(keyId);
262263
await key.setPrivateKey(privateKey);
@@ -750,6 +751,16 @@ class OpenSSSS {
750751
throw Exception('SSSS not unlocked');
751752
}
752753
await ssss.store(type, secret, keyId, privateKey, add: add);
754+
755+
// ideally never happens unless new key?
756+
while (!ssss.client.accountData.containsKey(type)) {
757+
Logs().d('Wait for $type in accountdata');
758+
await ssss.client.oneShotSync();
759+
}
760+
while (await getStored(type) != secret) {
761+
Logs().d('Wait for secret of $type to match in accountdata');
762+
await ssss.client.oneShotSync();
763+
}
753764
}
754765

755766
Future<void> validateAndStripOtherKeys(String type, String secret) async {

lib/encryption/utils/bootstrap.dart

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ class Bootstrap {
9090

9191
// cache the secret analyzing so that we don't drop stuff a different client sets during bootstrapping
9292
Map<String, Set<String>>? _secretsCache;
93+
94+
/// returns ssss from accountdata, eg: m.megolm_backup.v1, or your m.cross_signing stuff
9395
Map<String, Set<String>> analyzeSecrets() {
9496
final secretsCache = _secretsCache;
9597
if (secretsCache != null) {
@@ -292,12 +294,12 @@ class Bootstrap {
292294
}
293295
// alright, we re-encrypted all the secrets. We delete the dead weight only *after* we set our key to the default key
294296
}
295-
final updatedAccountData = client.onSync.stream.firstWhere((syncUpdate) =>
296-
syncUpdate.accountData != null &&
297-
syncUpdate.accountData!.any((accountData) =>
298-
accountData.type == EventTypes.SecretStorageDefaultKey));
299297
await encryption.ssss.setDefaultKeyId(newSsssKey!.keyId);
300-
await updatedAccountData;
298+
while (encryption.ssss.defaultKeyId != newSsssKey!.keyId) {
299+
Logs().v(
300+
'Waiting accountData to have the correct m.secret_storage.default_key');
301+
await client.oneShotSync();
302+
}
301303
if (oldSsssKeys != null) {
302304
for (final entry in secretMap!.entries) {
303305
Logs().v('Validate and stripe other keys ${entry.key}...');
@@ -479,33 +481,25 @@ class Bootstrap {
479481
));
480482
Logs().v('Device signing keys have been uploaded.');
481483
// aaaand set the SSSS secrets
482-
final futures = <Future<void>>[];
483484
if (masterKey != null) {
484-
futures.add(
485-
client.onSync.stream
486-
.firstWhere((syncUpdate) =>
487-
masterKey?.publicKey != null &&
488-
client.userDeviceKeys[client.userID]?.masterKey?.ed25519Key ==
489-
masterKey?.publicKey)
490-
.then((_) => Logs().v('New Master Key was created')),
491-
);
485+
while (!(masterKey.publicKey != null &&
486+
client.userDeviceKeys[client.userID]?.masterKey?.ed25519Key ==
487+
masterKey.publicKey)) {
488+
Logs().v('Waiting for master to be created');
489+
await client.oneShotSync();
490+
}
492491
}
493-
for (final entry in secretsToStore.entries) {
494-
futures.add(
495-
client.onSync.stream
496-
.firstWhere((syncUpdate) =>
497-
syncUpdate.accountData != null &&
498-
syncUpdate.accountData!
499-
.any((accountData) => accountData.type == entry.key))
500-
.then((_) =>
501-
Logs().v('New Key with type ${entry.key} was created')),
502-
);
503-
Logs().v('Store new SSSS key ${entry.key}...');
504-
await newSsssKey?.store(entry.key, entry.value);
492+
if (newSsssKey != null) {
493+
final storeFutures = <Future<void>>[];
494+
for (final entry in secretsToStore.entries) {
495+
storeFutures.add(newSsssKey!.store(entry.key, entry.value));
496+
}
497+
Logs().v('Store new SSSS key entry...');
498+
await Future.wait(storeFutures);
505499
}
500+
506501
Logs().v(
507502
'Wait for MasterKey and ${secretsToStore.entries.length} keys to be created');
508-
await Future.wait<void>(futures);
509503
final keysToSign = <SignableKey>[];
510504
if (masterKey != null) {
511505
if (client.userDeviceKeys[client.userID]?.masterKey?.ed25519Key !=
@@ -581,14 +575,6 @@ class Bootstrap {
581575
);
582576
Logs().v('Store the secret...');
583577
await newSsssKey?.store(megolmKey, base64.encode(privKey));
584-
Logs().v('Wait for secret to come down sync');
585-
586-
if (!await encryption.keyManager.isCached()) {
587-
await client.onSync.stream.firstWhere((syncUpdate) =>
588-
syncUpdate.accountData != null &&
589-
syncUpdate.accountData!
590-
.any((accountData) => accountData.type == megolmKey));
591-
}
592578

593579
Logs().v(
594580
'And finally set all megolm keys as needing to be uploaded again...');

lib/src/client.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,8 +1652,8 @@ class Client extends MatrixApi {
16521652

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

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

test/encryption/ssss_test.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,15 @@ void main() {
107107
await handle.unlock(recoveryKey: ssssKey);
108108
expect(handle.isUnlocked, true);
109109
FakeMatrixApi.calledEndpoints.clear();
110-
await handle.store('best animal', 'foxies');
110+
111+
// OpenSSSS store waits for accountdata to be updated before returning
112+
// but we can't update that before the below endpoint is not hit.
113+
await handle.ssss
114+
.store('best animal', 'foxies', handle.keyId, handle.privateKey!);
111115
// alright, since we don't properly sync we will manually have to update
112116
// account_data for this test
117+
118+
// await handle.store('best animal', 'foxies');
113119
final content = FakeMatrixApi
114120
.calledEndpoints[
115121
'/client/v3/user/%40test%3AfakeServer.notExisting/account_data/best%20animal']!

0 commit comments

Comments
 (0)