Remove unused CryptoCallbacks implementations (#12919)

* Remove unused `onSecretRequested` callback

This thing is unused with the rust crypto stack (which is lucky, because it
uses methods that only work with the legacy stack).

* Remove unused `getDehydrationKey` method

This callback is no longer used, so there is no need for an implementation.

* Remove unused `dehydrationCache`

This is no longer written to, so is redundant.

* Remove another write to `CryptoCallbacks.getDehydrationKey`

As before: this hook is no longer used by the js-sdk, so writing to it is
pointless.
This commit is contained in:
Richard van der Hoff 2024-08-23 15:00:18 +01:00 committed by GitHub
parent 69da1754cb
commit 5a9d7ba2d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 1 additions and 188 deletions

View file

@ -41,7 +41,6 @@ import MatrixClientBackedSettingsHandler from "./settings/handlers/MatrixClientB
import * as StorageManager from "./utils/StorageManager"; import * as StorageManager from "./utils/StorageManager";
import IdentityAuthClient from "./IdentityAuthClient"; import IdentityAuthClient from "./IdentityAuthClient";
import { crossSigningCallbacks } from "./SecurityManager"; import { crossSigningCallbacks } from "./SecurityManager";
import { ModuleRunner } from "./modules/ModuleRunner";
import { SlidingSyncManager } from "./SlidingSyncManager"; import { SlidingSyncManager } from "./SlidingSyncManager";
import { _t, UserFriendlyError } from "./languageHandler"; import { _t, UserFriendlyError } from "./languageHandler";
import { SettingLevel } from "./settings/SettingLevel"; import { SettingLevel } from "./settings/SettingLevel";
@ -452,11 +451,6 @@ class MatrixClientPegClass implements IMatrixClientPeg {
}, },
}; };
const dehydrationKeyCallback = ModuleRunner.instance.extensions.cryptoSetup.getDehydrationKeyCallback();
if (dehydrationKeyCallback) {
opts.cryptoCallbacks!.getDehydrationKey = dehydrationKeyCallback;
}
this.matrixClient = createMatrixClient(opts); this.matrixClient = createMatrixClient(opts);
this.matrixClient.setGuest(Boolean(creds.guest)); this.matrixClient.setGuest(Boolean(creds.guest));

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { Crypto, ICryptoCallbacks, encodeBase64, SecretStorage } from "matrix-js-sdk/src/matrix"; import { ICryptoCallbacks, SecretStorage } from "matrix-js-sdk/src/matrix";
import { deriveKey } from "matrix-js-sdk/src/crypto/key_passphrase"; import { deriveKey } from "matrix-js-sdk/src/crypto/key_passphrase";
import { decodeRecoveryKey } from "matrix-js-sdk/src/crypto/recoverykey"; import { decodeRecoveryKey } from "matrix-js-sdk/src/crypto/recoverykey";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
@ -39,11 +39,6 @@ let secretStorageKeys: Record<string, Uint8Array> = {};
let secretStorageKeyInfo: Record<string, SecretStorage.SecretStorageKeyDescription> = {}; let secretStorageKeyInfo: Record<string, SecretStorage.SecretStorageKeyDescription> = {};
let secretStorageBeingAccessed = false; let secretStorageBeingAccessed = false;
let dehydrationCache: {
key?: Uint8Array;
keyInfo?: SecretStorage.SecretStorageKeyDescription;
} = {};
/** /**
* This can be used by other components to check if secret storage access is in * This can be used by other components to check if secret storage access is in
* progress, so that we can e.g. avoid intermittently showing toasts during * progress, so that we can e.g. avoid intermittently showing toasts during
@ -119,14 +114,6 @@ async function getSecretStorageKey({
return [keyId, secretStorageKeys[keyId]]; return [keyId, secretStorageKeys[keyId]];
} }
if (dehydrationCache.key) {
if (await MatrixClientPeg.safeGet().checkSecretStorageKey(dehydrationCache.key, keyInfo)) {
logger.debug("getSecretStorageKey: returning key from dehydration cache");
cacheSecretStorageKey(keyId, keyInfo, dehydrationCache.key);
return [keyId, dehydrationCache.key];
}
}
const keyFromCustomisations = ModuleRunner.instance.extensions.cryptoSetup.getSecretStorageKey(); const keyFromCustomisations = ModuleRunner.instance.extensions.cryptoSetup.getSecretStorageKey();
if (keyFromCustomisations) { if (keyFromCustomisations) {
logger.log("getSecretStorageKey: Using secret storage key from CryptoSetupExtension"); logger.log("getSecretStorageKey: Using secret storage key from CryptoSetupExtension");
@ -171,56 +158,6 @@ async function getSecretStorageKey({
return [keyId, key]; return [keyId, key];
} }
export async function getDehydrationKey(
keyInfo: SecretStorage.SecretStorageKeyDescription,
checkFunc: (data: Uint8Array) => void,
): Promise<Uint8Array> {
const keyFromCustomisations = ModuleRunner.instance.extensions.cryptoSetup.getSecretStorageKey();
if (keyFromCustomisations) {
logger.log("CryptoSetupExtension: Using key from extension (dehydration)");
return keyFromCustomisations;
}
const inputToKey = makeInputToKey(keyInfo);
const { finished } = Modal.createDialog(
AccessSecretStorageDialog,
/* props= */
{
keyInfo,
checkPrivateKey: async (input: KeyParams): Promise<boolean> => {
const key = await inputToKey(input);
try {
checkFunc(key);
return true;
} catch (e) {
return false;
}
},
},
/* className= */ undefined,
/* isPriorityModal= */ false,
/* isStaticModal= */ false,
/* options= */ {
onBeforeClose: async (reason): Promise<boolean> => {
if (reason === "backgroundClick") {
return confirmToDismiss();
}
return true;
},
},
);
const [input] = await finished;
if (!input) {
throw new AccessCancelledError();
}
const key = await inputToKey(input);
// need to copy the key because rehydration (unpickling) will clobber it
dehydrationCache = { key: new Uint8Array(key), keyInfo };
return key;
}
function cacheSecretStorageKey( function cacheSecretStorageKey(
keyId: string, keyId: string,
keyInfo: SecretStorage.SecretStorageKeyDescription, keyInfo: SecretStorage.SecretStorageKeyDescription,
@ -232,50 +169,9 @@ function cacheSecretStorageKey(
} }
} }
async function onSecretRequested(
userId: string,
deviceId: string,
requestId: string,
name: string,
deviceTrust: Crypto.DeviceVerificationStatus,
): Promise<string | undefined> {
logger.log("onSecretRequested", userId, deviceId, requestId, name, deviceTrust);
const client = MatrixClientPeg.safeGet();
if (userId !== client.getUserId()) {
return;
}
if (!deviceTrust?.isVerified()) {
logger.log(`Ignoring secret request from untrusted device ${deviceId}`);
return;
}
if (
name === "m.cross_signing.master" ||
name === "m.cross_signing.self_signing" ||
name === "m.cross_signing.user_signing"
) {
const callbacks = client.getCrossSigningCacheCallbacks();
if (!callbacks?.getCrossSigningKeyCache) return;
const keyId = name.replace("m.cross_signing.", "");
const key = await callbacks.getCrossSigningKeyCache(keyId);
if (!key) {
logger.log(`${keyId} requested by ${deviceId}, but not found in cache`);
}
return key ? encodeBase64(key) : undefined;
} else if (name === "m.megolm_backup.v1") {
const key = await client.crypto?.getSessionBackupPrivateKey();
if (!key) {
logger.log(`session backup key requested by ${deviceId}, but not found in cache`);
}
return key ? encodeBase64(key) : undefined;
}
logger.warn("onSecretRequested didn't recognise the secret named ", name);
}
export const crossSigningCallbacks: ICryptoCallbacks = { export const crossSigningCallbacks: ICryptoCallbacks = {
getSecretStorageKey, getSecretStorageKey,
cacheSecretStorageKey, cacheSecretStorageKey,
onSecretRequested,
getDehydrationKey,
}; };
/** /**

View file

@ -16,16 +16,11 @@ limitations under the License.
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import fetchMockJest from "fetch-mock-jest"; import fetchMockJest from "fetch-mock-jest";
import {
ProvideCryptoSetupExtensions,
SecretStorageKeyDescription,
} from "@matrix-org/react-sdk-module-api/lib/lifecycles/CryptoSetupExtensions";
import { advanceDateAndTime, stubClient } from "./test-utils"; import { advanceDateAndTime, stubClient } from "./test-utils";
import { IMatrixClientPeg, MatrixClientPeg as peg } from "../src/MatrixClientPeg"; import { IMatrixClientPeg, MatrixClientPeg as peg } from "../src/MatrixClientPeg";
import SettingsStore from "../src/settings/SettingsStore"; import SettingsStore from "../src/settings/SettingsStore";
import { SettingLevel } from "../src/settings/SettingLevel"; import { SettingLevel } from "../src/settings/SettingLevel";
import { ModuleRunner } from "../src/modules/ModuleRunner";
jest.useFakeTimers(); jest.useFakeTimers();
@ -78,78 +73,6 @@ describe("MatrixClientPeg", () => {
expect(peg.userRegisteredWithinLastHours(24)).toBe(false); expect(peg.userRegisteredWithinLastHours(24)).toBe(false);
}); });
describe(".start extensions", () => {
let testPeg: IMatrixClientPeg;
beforeEach(() => {
// instantiate a MatrixClientPegClass instance, with a new MatrixClient
testPeg = new PegClass();
fetchMockJest.get("http://example.com/_matrix/client/versions", {});
});
describe("cryptoSetup extension", () => {
it("should call default cryptoSetup.getDehydrationKeyCallback", async () => {
const mockCryptoSetup = {
SHOW_ENCRYPTION_SETUP_UI: true,
examineLoginResponse: jest.fn(),
persistCredentials: jest.fn(),
getSecretStorageKey: jest.fn(),
createSecretStorageKey: jest.fn(),
catchAccessSecretStorageError: jest.fn(),
setupEncryptionNeeded: jest.fn(),
getDehydrationKeyCallback: jest.fn().mockReturnValue(null),
} as ProvideCryptoSetupExtensions;
// Ensure we have an instance before we set up spies
const instance = ModuleRunner.instance;
jest.spyOn(instance.extensions, "cryptoSetup", "get").mockReturnValue(mockCryptoSetup);
testPeg.replaceUsingCreds({
accessToken: "SEKRET",
homeserverUrl: "http://example.com",
userId: "@user:example.com",
deviceId: "TEST_DEVICE_ID",
});
expect(mockCryptoSetup.getDehydrationKeyCallback).toHaveBeenCalledTimes(1);
});
it("should call overridden cryptoSetup.getDehydrationKeyCallback", async () => {
const mockDehydrationKeyCallback = () => Uint8Array.from([0x11, 0x22, 0x33]);
const mockCryptoSetup = {
SHOW_ENCRYPTION_SETUP_UI: true,
examineLoginResponse: jest.fn(),
persistCredentials: jest.fn(),
getSecretStorageKey: jest.fn(),
createSecretStorageKey: jest.fn(),
catchAccessSecretStorageError: jest.fn(),
setupEncryptionNeeded: jest.fn(),
getDehydrationKeyCallback: jest.fn().mockReturnValue(mockDehydrationKeyCallback),
} as ProvideCryptoSetupExtensions;
// Ensure we have an instance before we set up spies
const instance = ModuleRunner.instance;
jest.spyOn(instance.extensions, "cryptoSetup", "get").mockReturnValue(mockCryptoSetup);
testPeg.replaceUsingCreds({
accessToken: "SEKRET",
homeserverUrl: "http://example.com",
userId: "@user:example.com",
deviceId: "TEST_DEVICE_ID",
});
expect(mockCryptoSetup.getDehydrationKeyCallback).toHaveBeenCalledTimes(1);
const client = testPeg.get();
const dehydrationKey = await client?.cryptoCallbacks.getDehydrationKey!(
{} as SecretStorageKeyDescription,
(key: Uint8Array) => true,
);
expect(dehydrationKey).toEqual(Uint8Array.from([0x11, 0x22, 0x33]));
});
});
});
describe(".start", () => { describe(".start", () => {
let testPeg: IMatrixClientPeg; let testPeg: IMatrixClientPeg;