Merge pull request #1066 from vector-im/fix-sas-issues

Fix some SAS issues
This commit is contained in:
Bruno Windels 2023-03-30 12:52:47 +02:00 committed by GitHub
commit 51c3e3104f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 48 additions and 35 deletions

View File

@ -90,6 +90,13 @@ export class DeviceVerificationViewModel extends ErrorReportViewModel<SegmentTyp
this.emitChange("currentStageViewModel"); this.emitChange("currentStageViewModel");
} }
dispose(): void {
if (!this.sas.finished) {
this.sas.abort().catch(() => {/** ignore */});
}
super.dispose();
}
get currentStageViewModel() { get currentStageViewModel() {
return this._currentStageViewModel; return this._currentStageViewModel;
} }

View File

@ -142,7 +142,7 @@ export function tests() {
await olm.init(); await olm.init();
const olmUtil = new Olm.Utility(); const olmUtil = new Olm.Utility();
const e2eeAccount = { const e2eeAccount = {
getDeviceKeysToSignWithCrossSigning: () => { getUnsignedDeviceKey: () => {
return { return {
keys: { keys: {
[`ed25519:${ourDeviceId}`]: [`ed25519:${ourDeviceId}`]:

View File

@ -6,6 +6,7 @@ import {CancelReason, VerificationEventType} from "./types";
import {getKeyEd25519Key} from "../../CrossSigning"; import {getKeyEd25519Key} from "../../CrossSigning";
import {getDeviceEd25519Key} from "../../../e2ee/common"; import {getDeviceEd25519Key} from "../../../e2ee/common";
import anotherjson from "another-json"; import anotherjson from "another-json";
import {NullLogger} from "../../../../logging/NullLogger";
interface ITestChannel extends IChannel { interface ITestChannel extends IChannel {
setOlmSas(olmSas): void; setOlmSas(olmSas): void;
@ -82,31 +83,33 @@ export class MockChannel implements ITestChannel {
private async recalculateMAC() { private async recalculateMAC() {
// We need to replace the mac with calculated mac // We need to replace the mac with calculated mac
const baseInfo = await new NullLogger().run("log", async (log) => {
"MATRIX_KEY_VERIFICATION_MAC" + const baseInfo =
this.otherUserId + "MATRIX_KEY_VERIFICATION_MAC" +
this.otherUserDeviceId + this.otherUserId +
this.ourUserId + this.otherUserDeviceId +
this.ourUserDeviceId + this.ourUserId +
this.id; this.ourUserDeviceId +
const { content: macContent } = this.receivedMessages.get(VerificationEventType.Mac); this.id;
const macMethod = this.acceptMessage.content.message_authentication_code; const { content: macContent } = this.receivedMessages.get(VerificationEventType.Mac);
const calculateMac = createCalculateMAC(this.olmSas, macMethod); const macMethod = this.acceptMessage.content.message_authentication_code;
const input = Object.keys(macContent.mac).sort().join(","); const calculateMac = createCalculateMAC(this.olmSas, macMethod);
const properMac = calculateMac(input, baseInfo + "KEY_IDS"); const input = Object.keys(macContent.mac).sort().join(",");
macContent.keys = properMac; const properMac = calculateMac(input, baseInfo + "KEY_IDS", log);
for (const keyId of Object.keys(macContent.mac)) { macContent.keys = properMac;
const deviceId = keyId.split(":", 2)[1]; for (const keyId of Object.keys(macContent.mac)) {
const device = await this.deviceTracker.deviceForId(this.otherUserDeviceId, deviceId); const deviceId = keyId.split(":", 2)[1];
if (device) { const device = await this.deviceTracker.deviceForId(this.otherUserDeviceId, deviceId);
macContent.mac[keyId] = calculateMac(getDeviceEd25519Key(device), baseInfo + keyId); if (device) {
macContent.mac[keyId] = calculateMac(getDeviceEd25519Key(device), baseInfo + keyId, log);
}
else {
const key = await this.deviceTracker.getCrossSigningKeyForUser(this.otherUserId);
const masterKey = getKeyEd25519Key(key)!;
macContent.mac[keyId] = calculateMac(masterKey, baseInfo + keyId, log);
}
} }
else { });
const key = await this.deviceTracker.getCrossSigningKeyForUser(this.otherUserId);
const masterKey = getKeyEd25519Key(key)!;
macContent.mac[keyId] = calculateMac(masterKey, baseInfo + keyId);
}
}
} }
setStartMessage(event: any): void { setStartMessage(event: any): void {

View File

@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import type {ILogItem} from "../../../logging/types";
import type {MacMethod} from "./stages/constants"; import type {MacMethod} from "./stages/constants";
const macMethods: Record<MacMethod, string> = { const macMethods: Record<MacMethod, string> = {
@ -23,8 +24,10 @@ const macMethods: Record<MacMethod, string> = {
}; };
export function createCalculateMAC(olmSAS: Olm.SAS, method: MacMethod) { export function createCalculateMAC(olmSAS: Olm.SAS, method: MacMethod) {
return function (input: string, info: string): string { return function (input: string, info: string, log: ILogItem): string {
const mac = olmSAS[macMethods[method]](input, info); return log.wrap({ l: "calculate MAC", method}, () => {
return mac; const mac = olmSAS[macMethods[method]](input, info);
return mac;
});
}; };
} }

View File

@ -32,7 +32,7 @@ export class SendMacStage extends BaseSASVerificationStage {
}); });
} }
private async sendMAC(calculateMAC: (input: string, info: string) => string, log: ILogItem): Promise<void> { private async sendMAC(calculateMAC: (input: string, info: string, log: ILogItem) => string, log: ILogItem): Promise<void> {
const mac: Record<string, string> = {}; const mac: Record<string, string> = {};
const keyList: string[] = []; const keyList: string[] = [];
const baseInfo = const baseInfo =
@ -45,7 +45,7 @@ export class SendMacStage extends BaseSASVerificationStage {
const deviceKeyId = `ed25519:${this.ourUserDeviceId}`; const deviceKeyId = `ed25519:${this.ourUserDeviceId}`;
const deviceKeys = this.e2eeAccount.getUnsignedDeviceKey(); const deviceKeys = this.e2eeAccount.getUnsignedDeviceKey();
mac[deviceKeyId] = calculateMAC(deviceKeys.keys[deviceKeyId], baseInfo + deviceKeyId); mac[deviceKeyId] = calculateMAC(deviceKeys.keys[deviceKeyId], baseInfo + deviceKeyId, log);
keyList.push(deviceKeyId); keyList.push(deviceKeyId);
const key = await this.deviceTracker.getCrossSigningKeyForUser(this.ourUserId, KeyUsage.Master, this.hsApi, log); const key = await this.deviceTracker.getCrossSigningKeyForUser(this.ourUserId, KeyUsage.Master, this.hsApi, log);
@ -56,11 +56,11 @@ export class SendMacStage extends BaseSASVerificationStage {
const crossSigningKey = getKeyEd25519Key(key); const crossSigningKey = getKeyEd25519Key(key);
if (crossSigningKey) { if (crossSigningKey) {
const crossSigningKeyId = `ed25519:${crossSigningKey}`; const crossSigningKeyId = `ed25519:${crossSigningKey}`;
mac[crossSigningKeyId] = calculateMAC(crossSigningKey, baseInfo + crossSigningKeyId); mac[crossSigningKeyId] = calculateMAC(crossSigningKey, baseInfo + crossSigningKeyId, log);
keyList.push(crossSigningKeyId); keyList.push(crossSigningKeyId);
} }
const keys = calculateMAC(keyList.sort().join(","), baseInfo + "KEY_IDS"); const keys = calculateMAC(keyList.sort().join(","), baseInfo + "KEY_IDS", log);
await this.channel.send(VerificationEventType.Mac, { mac, keys }, log); await this.channel.send(VerificationEventType.Mac, { mac, keys }, log);
} }
} }

View File

@ -35,7 +35,7 @@ export class VerifyMacStage extends BaseSASVerificationStage {
}); });
} }
private async checkMAC(calculateMAC: (input: string, info: string) => string, log: ILogItem): Promise<void> { private async checkMAC(calculateMAC: (input: string, info: string, log: ILogItem) => string, log: ILogItem): Promise<void> {
const {content} = this.channel.getReceivedMessage(VerificationEventType.Mac); const {content} = this.channel.getReceivedMessage(VerificationEventType.Mac);
const baseInfo = const baseInfo =
"MATRIX_KEY_VERIFICATION_MAC" + "MATRIX_KEY_VERIFICATION_MAC" +
@ -45,7 +45,7 @@ export class VerifyMacStage extends BaseSASVerificationStage {
this.ourUserDeviceId + this.ourUserDeviceId +
this.channel.id; this.channel.id;
const calculatedMAC = calculateMAC(Object.keys(content.mac).sort().join(","), baseInfo + "KEY_IDS"); const calculatedMAC = calculateMAC(Object.keys(content.mac).sort().join(","), baseInfo + "KEY_IDS", log);
if (content.keys !== calculatedMAC) { if (content.keys !== calculatedMAC) {
log.log({ l: "MAC verification failed for keys field", keys: content.keys, calculated: calculatedMAC }); log.log({ l: "MAC verification failed for keys field", keys: content.keys, calculated: calculatedMAC });
this.channel.cancelVerification(CancelReason.KeyMismatch); this.channel.cancelVerification(CancelReason.KeyMismatch);
@ -53,7 +53,7 @@ export class VerifyMacStage extends BaseSASVerificationStage {
} }
await this.verifyKeys(content.mac, (keyId, key, keyInfo) => { await this.verifyKeys(content.mac, (keyId, key, keyInfo) => {
const calculatedMAC = calculateMAC(key, baseInfo + keyId); const calculatedMAC = calculateMAC(key, baseInfo + keyId, log);
if (keyInfo !== calculatedMAC) { if (keyInfo !== calculatedMAC) {
log.log({ l: "Mac verification failed for key", keyMac: keyInfo, calculatedMAC, keyId, key }); log.log({ l: "Mac verification failed for key", keyMac: keyInfo, calculatedMAC, keyId, key });
this.channel.cancelVerification(CancelReason.KeyMismatch); this.channel.cancelVerification(CancelReason.KeyMismatch);