index : matrix-js-sdk

My fork of matrix-js-sdk

diff options
context:
space:
mode:
authorBruno Windels <[email protected]>2020-06-17 15:25:42 +0200
committerBruno Windels <[email protected]>2020-06-17 15:25:42 +0200
commitb82870adb2e79748401f7268d1f99ff639c84737 (patch)
tree55ea942ab50258542165533757d6b4d11ab2dc65
parent3c5b304b6b75f15aea2a0eabc23192b3cd515c6e (diff)
downloadmatrix-js-sdk-b82870adb2e79748401f7268d1f99ff639c84737.tar.gz
move key backup bootstrap/migration over to builder
-rw-r--r--src/crypto/EncryptionSetup.js50
-rw-r--r--src/crypto/index.js43
2 files changed, 76 insertions, 17 deletions
diff --git a/src/crypto/EncryptionSetup.js b/src/crypto/EncryptionSetup.js
index 9447fabd..549ec5e3 100644
--- a/src/crypto/EncryptionSetup.js
+++ b/src/crypto/EncryptionSetup.js
@@ -39,6 +39,29 @@ export class EncryptionSetupBuilder {
}
/**
+ * Adds the key backup info to be updated on the server
+ *
+ * Used either to create a new key backup, or add signatures
+ * from the new MSK.
+ *
+ * @param {Object} keyBackupInfo as received from/sent to the server
+ */
+ addSessionBackup(keyBackupInfo) {
+ this._keyBackupInfo = keyBackupInfo;
+ }
+
+ /**
+ * Adds the session backup private key to be updated in the local cache
+ *
+ * Used after fixing the format of the key
+ *
+ * @param {Uint8Array} privateKey
+ */
+ addSessionBackupPrivateKeyToCache(privateKey) {
+ this._sessionBackupPrivateKey = privateKey;
+ }
+
+ /**
* Add signatures from a given user and device/x-sign key
* Used to sign the new cross-signing key with the device key
*
@@ -107,6 +130,10 @@ export class EncryptionSetupBuilder {
},
);
}
+ // store session backup key in cache
+ if (this._sessionBackupPrivateKey) {
+ await crypto.storeSessionBackupPrivateKey(this._sessionBackupPrivateKey);
+ }
}
}
@@ -160,6 +187,29 @@ export class EncryptionSetupOperation {
if (this._keySignatures) {
await baseApis.uploadKeySignatures(this._keySignatures);
}
+ // need to create/update key backup info
+ if (this._keyBackupInfo) {
+ if (this._keyBackupInfo.version) {
+ // session backup signature
+ // The backup is trusted because the user provided the private key.
+ // Sign the backup with the cross signing key so the key backup can
+ // be trusted via cross-signing.
+ await baseApis._http.authedRequest(
+ undefined, "PUT", "/room_keys/version/" + this._keyBackupInfo.version,
+ undefined, {
+ algorithm: this._keyBackupInfo.algorithm,
+ auth_data: this._keyBackupInfo.auth_data,
+ },
+ {prefix: PREFIX_UNSTABLE},
+ );
+ } else {
+ // add new key backup
+ await baseApis._http.authedRequest(
+ undefined, "POST", "/room_keys/version",
+ undefined, this._keyBackupInfo,
+ {prefix: PREFIX_UNSTABLE},
+ );
+ }
}
}
}
diff --git a/src/crypto/index.js b/src/crypto/index.js
index 28865eb7..5e4e7e9f 100644
--- a/src/crypto/index.js
+++ b/src/crypto/index.js
@@ -34,7 +34,6 @@ import {DeviceInfo} from "./deviceinfo";
import * as algorithms from "./algorithms";
import {
CrossSigningInfo,
- CrossSigningLevel,
DeviceTrustLevel,
UserTrustLevel,
createCryptoStoreCacheCallbacks,
@@ -50,11 +49,10 @@ import {
} from './verification/QRCode';
import {SAS} from './verification/SAS';
import {keyFromPassphrase} from './key_passphrase';
-import {encodeRecoveryKey} from './recoverykey';
+import {encodeRecoveryKey, decodeRecoveryKey} from './recoverykey';
import {VerificationRequest} from "./verification/request/VerificationRequest";
import {InRoomChannel, InRoomRequests} from "./verification/request/InRoomChannel";
import {ToDeviceChannel, ToDeviceRequests} from "./verification/request/ToDeviceChannel";
-import * as httpApi from "../http-api";
import {IllegalMethod} from "./verification/IllegalMethod";
import {KeySignatureUploadError} from "../errors";
import {decryptAES, encryptAES} from './aes';
@@ -622,7 +620,7 @@ Crypto.prototype.bootstrapSecretStorage = async function({
newKeyId = await createSSSS(opts, backupKey);
// store the backup key in secret storage
- await this.storeSecret(
+ await secretStorage.store(
"m.megolm_backup.v1", olmlib.encodeBase64(backupKey), [newKeyId],
);
@@ -633,11 +631,7 @@ Crypto.prototype.bootstrapSecretStorage = async function({
await crossSigningInfo.signObject(
keyBackupInfo.auth_data, "master",
);
- await this._baseApis._http.authedRequest(
- undefined, "PUT", "/room_keys/version/" + keyBackupInfo.version,
- undefined, keyBackupInfo,
- {prefix: httpApi.PREFIX_UNSTABLE},
- );
+ builder.addSessionBackup(keyBackupInfo);
} else if (!this._crossSigningInfo.getId()) {
// we have SSSS, but we don't know if the server's cross-signing
// keys should be trusted
@@ -680,30 +674,45 @@ Crypto.prototype.bootstrapSecretStorage = async function({
if (setupNewKeyBackup && !keyBackupInfo) {
const info = await this._baseApis.prepareKeyBackupVersion(
null /* random key */,
- { secureSecretStorage: true },
+ // don't write to secret storage, as it will write to this._secretStorage.
+ // Here, we want to capture all the side-effects of bootstrapping,
+ // and want to write to the local secretStorage object
+ { secureSecretStorage: false },
);
- await this._baseApis.createKeyBackupVersion(info);
- }
+ // write the key ourselves to 4S
+ const privateKey = decodeRecoveryKey(info.recovery_key);
+ await secretStorage.store("m.megolm_backup.v1", olmlib.encodeBase64(privateKey));
+
+ // create keyBackupInfo object to add to builder
+ const data = {
+ algorithm: info.algorithm,
+ auth_data: info.auth_data,
+ };
+ // sign with cross-sign master key
+ await crossSigningInfo.signObject(data.auth_data, "master");
+ // sign with the device fingerprint
+ await this._signObject(data.auth_data);
+
- if (this._crossSigningInfo._cacheCallbacks) {
+ builder.addSessionBackup(data);
}
// and likewise for the session backup key
- const sessionBackupKey = await this.getSecret('m.megolm_backup.v1');
+ const sessionBackupKey = await secretStorage.get('m.megolm_backup.v1');
if (sessionBackupKey) {
logger.info("Got session backup key from secret storage: caching");
// fix up the backup key if it's in the wrong format, and replace
// in secret storage
const fixedBackupKey = fixBackupKey(sessionBackupKey);
if (fixedBackupKey) {
- await this.storeSecret(
- "m.megolm_backup.v1", fixedBackupKey, [newKeyId || oldKeyId],
+ await secretStorage.store("m.megolm_backup.v1",
+ fixedBackupKey, [newKeyId || oldKeyId],
);
}
const decodedBackupKey = new Uint8Array(olmlib.decodeBase64(
fixedBackupKey || sessionBackupKey,
));
- await this.storeSessionBackupPrivateKey(decodedBackupKey);
+ await builder.addSessionBackupPrivateKeyToCache(decodedBackupKey);
}
} finally {
// Restore the original callbacks. NB. we must do this by manipulating