diff --git a/src/matrix/Session.js b/src/matrix/Session.js index 30335d23..afe96afc 100644 --- a/src/matrix/Session.js +++ b/src/matrix/Session.js @@ -536,12 +536,12 @@ export class Session { } } if (this._olm && this._e2eeAccount) { - // try set up session backup and cross-signing if we stored the ssss key - const ssssKey = await ssssReadKey(txn); - if (ssssKey) { - // this will close the txn above, so we do it last - await this._tryLoadSecretStorage(ssssKey, log); - } + this._secretStorage = new SecretStorage({ + platform: this._platform, + storage: this._storage, + olm: this._olm + }); + await this._secretStorage.load(txn); } } diff --git a/src/matrix/ssss/SecretStorage.ts b/src/matrix/ssss/SecretStorage.ts index cd4edf4e..34bea0c9 100644 --- a/src/matrix/ssss/SecretStorage.ts +++ b/src/matrix/ssss/SecretStorage.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ import {BaseObservableValue, RetainedObservableValue} from "../../observable/value"; -import {KeyType} from "./index"; +import {KeyType, SSSS_KEY} from "./index"; import {keyFromPassphrase} from "./passphrase"; import {keyFromRecoveryKey} from "./recoveryKey"; import {Key, KeyDescription, KeyDescriptionData} from "./common"; @@ -48,11 +48,17 @@ class DecryptionError extends Error { } } -type KeyCredentials = { - type: KeyType, +type StringKeyCredential = { + type: KeyType.Passphrase | KeyType.RecoveryKey, credential: string } +type BitsKeyCredential = { + type: KeyType.KeyBits, + credential: Uint8Array +} +type KeyCredentials = StringKeyCredential | BitsKeyCredential; + export class SecretStorage { // we know the id but don't have the description yet private keyId?: string; @@ -73,11 +79,32 @@ export class SecretStorage { this.observedSecrets = new Map(); } - load() { - // read key + async load(txn: Transaction) { + // first try to read the key bits from previously enabling 4S + const keyData = await txn.session.get(SSSS_KEY); + if (keyData) { + const keyAccountData = await txn.accountData.get(`m.secret_storage.key.${keyData.id}`); + if (keyAccountData) { + this.keyId = keyData.id; + this.keyDescription = new KeyDescription(keyData.id, keyAccountData.content as KeyDescriptionData); + this.keyCredentials = {type: KeyType.KeyBits, credential: keyData.binaryKey}; + } + } else { + // then prepare to track the default key + const defaultKey = await txn.accountData.get("m.secret_storage.default_key"); + const keyId = defaultKey?.content?.key; + if (keyId) { + this.keyId = keyId; + const keyData = await txn.accountData.get(`m.secret_storage.key.${keyId}`); + if (keyData) { + this.keyDescription = new KeyDescription(keyId, keyData.content as KeyDescriptionData); + } + } + } + this.updateKey(this.keyDescription, this.keyCredentials); } - async setKey(type: KeyType, credential: string) { + async setKey(type: KeyType.Passphrase | KeyType.RecoveryKey, credential: string) { const credentials: KeyCredentials = {type, credential}; this.keyCredentials = credentials; this.updateKey(this.keyDescription, this.keyCredentials); @@ -104,6 +131,8 @@ export class SecretStorage { } else if (credentials.type === KeyType.RecoveryKey) { this.key = await keyFromRecoveryKey(keyDescription, credentials.credential, this.olm, this.platform); return true; + } else if (credentials.type === KeyType.KeyBits) { + this.key = new Key(keyDescription, credentials.credential); } } return false; diff --git a/src/matrix/ssss/index.ts b/src/matrix/ssss/index.ts index 3b939a92..12ddb998 100644 --- a/src/matrix/ssss/index.ts +++ b/src/matrix/ssss/index.ts @@ -26,12 +26,13 @@ import type * as OlmNamespace from "@matrix-org/olm" type Olm = typeof OlmNamespace; -const SSSS_KEY = `${SESSION_E2EE_KEY_PREFIX}ssssKey`; +export const SSSS_KEY = `${SESSION_E2EE_KEY_PREFIX}ssssKey`; const BACKUPVERSION_KEY = `${SESSION_E2EE_KEY_PREFIX}keyBackupVersion`; export enum KeyType { RecoveryKey, - Passphrase + Passphrase, + KeyBits // decoded bits from either recovery key or passphrase, as stored on disk } async function readDefaultKeyDescription(storage: Storage): Promise { diff --git a/src/matrix/ssss/passphrase.ts b/src/matrix/ssss/passphrase.ts index 32d2cb0c..00e4801e 100644 --- a/src/matrix/ssss/passphrase.ts +++ b/src/matrix/ssss/passphrase.ts @@ -27,7 +27,7 @@ const DEFAULT_BITSIZE = 256; * @param {Platform} platform * @return {Key} */ -export async function keyFromPassphrase(passphrase: string, platform: Platform): Promise { +export async function keyFromPassphrase(keyDescription: KeyDescription, passphrase: string, platform: Platform): Promise { const {passphraseParams} = keyDescription; if (!passphraseParams) { throw new Error("not a passphrase key");