From 4b1104e463cb00bc7ec55776b53385536d281a0e Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 25 Sep 2020 17:36:47 +0100 Subject: [PATCH] Only sign key backup with cross-signing keys when available This changes the key backup setup step to only sign with cross-signing keys when both the public and private keys are already available without prompting. In many cases down these paths, the cross-signing keys either may not exist or may not be accessible. We always sign the key backup with your device key as well, so there is always a route to trust the key backup even if this is skipped. Fixes https://github.com/vector-im/element-web/issues/15230 --- src/crypto/CrossSigning.js | 9 ++++++--- src/crypto/index.js | 34 ++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/crypto/CrossSigning.js b/src/crypto/CrossSigning.js index 74d776925..acee5b389 100644 --- a/src/crypto/CrossSigning.js +++ b/src/crypto/CrossSigning.js @@ -211,13 +211,16 @@ export class CrossSigningInfo extends EventEmitter { /** * Check whether the private keys exist in the local key cache. * + * @param {string} [type] The type of key to get. One of "master", + * "self_signing", or "user_signing". Optional, will check all by default. * @returns {boolean} True if all keys are stored in the local cache. */ - async isStoredInKeyCache() { + async isStoredInKeyCache(type) { const cacheCallbacks = this._cacheCallbacks; if (!cacheCallbacks) return false; - for (const type of ["master", "self_signing", "user_signing"]) { - if (!await cacheCallbacks.getCrossSigningKeyCache(type)) { + const types = [type] || ["master", "self_signing", "user_signing"]; + for (const t of types) { + if (!await cacheCallbacks.getCrossSigningKeyCache(t)) { return false; } } diff --git a/src/crypto/index.js b/src/crypto/index.js index 8283ab081..8926374af 100644 --- a/src/crypto/index.js +++ b/src/crypto/index.js @@ -758,10 +758,20 @@ Crypto.prototype.bootstrapSecretStorage = async function({ // 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. - logger.log("Adding cross signing signature to key backup"); - await this._crossSigningInfo.signObject( - keyBackupInfo.auth_data, "master", - ); + if ( + this._crossSigningInfo.getId() && + this._crossSigningInfo.isStoredInKeyCache("master") + ) { + logger.log("Adding cross-signing signature to key backup"); + await this._crossSigningInfo.signObject( + keyBackupInfo.auth_data, "master", + ); + } else { + logger.warn( + "Cross-signing keys not available, skipping signature on key backup", + ); + } + builder.addSessionBackup(keyBackupInfo); } else { // 4S is already set up @@ -810,8 +820,20 @@ Crypto.prototype.bootstrapSecretStorage = async function({ algorithm: info.algorithm, auth_data: info.auth_data, }; - // sign with cross-sign master key - await this._crossSigningInfo.signObject(data.auth_data, "master"); + + if ( + this._crossSigningInfo.getId() && + this._crossSigningInfo.isStoredInKeyCache("master") + ) { + // sign with cross-sign master key + logger.log("Adding cross-signing signature to key backup"); + await this._crossSigningInfo.signObject(data.auth_data, "master"); + } else { + logger.warn( + "Cross-signing keys not available, skipping signature on key backup", + ); + } + // sign with the device fingerprint await this._signObject(data.auth_data);