1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-23 17:02:25 +03:00

Explicitly free some Rust-side objects (#3911)

* Explicitly `free` stuff returned by `OlmMachine.getIdentity()`

* Explicitly `free` stuff returned by `OlmMachine.getDevice()`

* one more
This commit is contained in:
Richard van der Hoff
2023-11-28 13:14:53 +00:00
committed by GitHub
parent 8ef2ca681c
commit a7496627fc
3 changed files with 120 additions and 69 deletions

View File

@@ -645,6 +645,7 @@ describe("RustCrypto", () => {
it("should call getDevice", async () => { it("should call getDevice", async () => {
olmMachine.getDevice.mockResolvedValue({ olmMachine.getDevice.mockResolvedValue({
free: jest.fn(),
isCrossSigningTrusted: jest.fn().mockReturnValue(false), isCrossSigningTrusted: jest.fn().mockReturnValue(false),
isLocallyTrusted: jest.fn().mockReturnValue(false), isLocallyTrusted: jest.fn().mockReturnValue(false),
isCrossSignedByOwner: jest.fn().mockReturnValue(false), isCrossSignedByOwner: jest.fn().mockReturnValue(false),
@@ -871,7 +872,7 @@ describe("RustCrypto", () => {
}); });
it("returns a verified UserVerificationStatus when the UserIdentity is verified", async () => { it("returns a verified UserVerificationStatus when the UserIdentity is verified", async () => {
olmMachine.getIdentity.mockResolvedValue({ isVerified: jest.fn().mockReturnValue(true) }); olmMachine.getIdentity.mockResolvedValue({ free: jest.fn(), isVerified: jest.fn().mockReturnValue(true) });
const userVerificationStatus = await rustCrypto.getUserVerificationStatus(testData.TEST_USER_ID); const userVerificationStatus = await rustCrypto.getUserVerificationStatus(testData.TEST_USER_ID);
expect(userVerificationStatus.isVerified()).toBeTruthy(); expect(userVerificationStatus.isVerified()).toBeTruthy();

View File

@@ -91,10 +91,13 @@ export class CrossSigningIdentity {
this.olmMachine.userId, this.olmMachine.userId,
this.olmMachine.deviceId, this.olmMachine.deviceId,
); );
try {
// Sign the device with our cross-signing key and upload the signature // Sign the device with our cross-signing key and upload the signature
const request: RustSdkCryptoJs.SignatureUploadRequest = await device.verify(); const request: RustSdkCryptoJs.SignatureUploadRequest = await device.verify();
await this.outgoingRequestProcessor.makeOutgoingRequest(request); await this.outgoingRequestProcessor.makeOutgoingRequest(request);
} finally {
device.free();
}
} else { } else {
logger.log( logger.log(
"bootStrapCrossSigning: Cross-signing private keys not found locally or in secret storage, creating new keys", "bootStrapCrossSigning: Cross-signing private keys not found locally or in secret storage, creating new keys",

View File

@@ -425,6 +425,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
await this.outgoingRequestProcessor.makeOutgoingRequest(request); await this.outgoingRequestProcessor.makeOutgoingRequest(request);
} }
const userIdentity = await this.olmMachine.getIdentity(rustTrackedUser); const userIdentity = await this.olmMachine.getIdentity(rustTrackedUser);
userIdentity?.free();
return userIdentity !== undefined; return userIdentity !== undefined;
} else if (downloadUncached) { } else if (downloadUncached) {
// Download the cross signing keys and check if the master key is available // Download the cross signing keys and check if the master key is available
@@ -562,7 +563,13 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
if (!device) { if (!device) {
throw new Error(`Unknown device ${userId}|${deviceId}`); throw new Error(`Unknown device ${userId}|${deviceId}`);
} }
await device.setLocalTrust(verified ? RustSdkCryptoJs.LocalTrust.Verified : RustSdkCryptoJs.LocalTrust.Unset); try {
await device.setLocalTrust(
verified ? RustSdkCryptoJs.LocalTrust.Verified : RustSdkCryptoJs.LocalTrust.Unset,
);
} finally {
device.free();
}
} }
/** /**
@@ -578,13 +585,16 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
); );
if (!device) return null; if (!device) return null;
try {
return new DeviceVerificationStatus({ return new DeviceVerificationStatus({
signedByOwner: device.isCrossSignedByOwner(), signedByOwner: device.isCrossSignedByOwner(),
crossSigningVerified: device.isCrossSigningTrusted(), crossSigningVerified: device.isCrossSigningTrusted(),
localVerified: device.isLocallyTrusted(), localVerified: device.isLocallyTrusted(),
trustCrossSignedDevices: this._trustCrossSignedDevices, trustCrossSignedDevices: this._trustCrossSignedDevices,
}); });
} finally {
device.free();
}
} }
/** /**
@@ -596,7 +606,9 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
if (userIdentity === undefined) { if (userIdentity === undefined) {
return new UserVerificationStatus(false, false, false); return new UserVerificationStatus(false, false, false);
} }
return new UserVerificationStatus(userIdentity.isVerified(), false, false); const verified = userIdentity.isVerified();
userIdentity.free();
return new UserVerificationStatus(verified, false, false);
} }
/** /**
@@ -621,42 +633,51 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
const userIdentity: RustSdkCryptoJs.OwnUserIdentity | undefined = await this.olmMachine.getIdentity( const userIdentity: RustSdkCryptoJs.OwnUserIdentity | undefined = await this.olmMachine.getIdentity(
new RustSdkCryptoJs.UserId(this.userId), new RustSdkCryptoJs.UserId(this.userId),
); );
if (!userIdentity) {
const crossSigningStatus: RustSdkCryptoJs.CrossSigningStatus = await this.olmMachine.crossSigningStatus(); // The public keys are not available on this device
const privateKeysOnDevice =
crossSigningStatus.hasMaster && crossSigningStatus.hasUserSigning && crossSigningStatus.hasSelfSigning;
if (!userIdentity || !privateKeysOnDevice) {
// The public or private keys are not available on this device
return null; return null;
} }
if (!userIdentity.isVerified()) { try {
// We have both public and private keys, but they don't match! const crossSigningStatus: RustSdkCryptoJs.CrossSigningStatus = await this.olmMachine.crossSigningStatus();
return null;
}
let key: string; const privateKeysOnDevice =
switch (type) { crossSigningStatus.hasMaster && crossSigningStatus.hasUserSigning && crossSigningStatus.hasSelfSigning;
case CrossSigningKey.Master:
key = userIdentity.masterKey; if (!privateKeysOnDevice) {
break; // The private keys are not available on this device
case CrossSigningKey.SelfSigning:
key = userIdentity.selfSigningKey;
break;
case CrossSigningKey.UserSigning:
key = userIdentity.userSigningKey;
break;
default:
// Unknown type
return null; return null;
} }
const parsedKey: CrossSigningKeyInfo = JSON.parse(key); if (!userIdentity.isVerified()) {
// `keys` is an object with { [`ed25519:${pubKey}`]: pubKey } // We have both public and private keys, but they don't match!
// We assume only a single key, and we want the bare form without type return null;
// prefix, so we select the values. }
return Object.values(parsedKey.keys)[0];
let key: string;
switch (type) {
case CrossSigningKey.Master:
key = userIdentity.masterKey;
break;
case CrossSigningKey.SelfSigning:
key = userIdentity.selfSigningKey;
break;
case CrossSigningKey.UserSigning:
key = userIdentity.userSigningKey;
break;
default:
// Unknown type
return null;
}
const parsedKey: CrossSigningKeyInfo = JSON.parse(key);
// `keys` is an object with { [`ed25519:${pubKey}`]: pubKey }
// We assume only a single key, and we want the bare form without type
// prefix, so we select the values.
return Object.values(parsedKey.keys)[0];
} finally {
userIdentity.free();
}
} }
/** /**
@@ -800,6 +821,8 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
Boolean(userIdentity?.masterKey) && Boolean(userIdentity?.masterKey) &&
Boolean(userIdentity?.selfSigningKey) && Boolean(userIdentity?.selfSigningKey) &&
Boolean(userIdentity?.userSigningKey); Boolean(userIdentity?.userSigningKey);
userIdentity?.free();
const privateKeysInSecretStorage = await secretStorageContainsCrossSigningKeys(this.secretStorage); const privateKeysInSecretStorage = await secretStorageContainsCrossSigningKeys(this.secretStorage);
const crossSigningStatus: RustSdkCryptoJs.CrossSigningStatus | null = const crossSigningStatus: RustSdkCryptoJs.CrossSigningStatus | null =
await this.getOlmMachineOrThrow().crossSigningStatus(); await this.getOlmMachineOrThrow().crossSigningStatus();
@@ -917,23 +940,31 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
if (!userIdentity) throw new Error(`unknown userId ${userId}`); if (!userIdentity) throw new Error(`unknown userId ${userId}`);
// Transform the verification methods into rust objects try {
const methods = this._supportedVerificationMethods.map((method) => // Transform the verification methods into rust objects
verificationMethodIdentifierToMethod(method), const methods = this._supportedVerificationMethods.map((method) =>
); verificationMethodIdentifierToMethod(method),
// Get the request content to send to the DM room );
const verificationEventContent: string = await userIdentity.verificationRequestContent(methods); // Get the request content to send to the DM room
const verificationEventContent: string = await userIdentity.verificationRequestContent(methods);
// Send the request content to send to the DM room // Send the request content to send to the DM room
const eventId = await this.sendVerificationRequestContent(roomId, verificationEventContent); const eventId = await this.sendVerificationRequestContent(roomId, verificationEventContent);
// Get a verification request // Get a verification request
const request: RustSdkCryptoJs.VerificationRequest = await userIdentity.requestVerification( const request: RustSdkCryptoJs.VerificationRequest = await userIdentity.requestVerification(
new RustSdkCryptoJs.RoomId(roomId), new RustSdkCryptoJs.RoomId(roomId),
new RustSdkCryptoJs.EventId(eventId), new RustSdkCryptoJs.EventId(eventId),
methods, methods,
); );
return new RustVerificationRequest(request, this.outgoingRequestProcessor, this._supportedVerificationMethods); return new RustVerificationRequest(
request,
this.outgoingRequestProcessor,
this._supportedVerificationMethods,
);
} finally {
userIdentity.free();
}
} }
/** /**
@@ -995,12 +1026,20 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
throw new Error("cannot request verification for this device when there is no existing cross-signing key"); throw new Error("cannot request verification for this device when there is no existing cross-signing key");
} }
const [request, outgoingRequest]: [RustSdkCryptoJs.VerificationRequest, RustSdkCryptoJs.ToDeviceRequest] = try {
await userIdentity.requestVerification( const [request, outgoingRequest]: [RustSdkCryptoJs.VerificationRequest, RustSdkCryptoJs.ToDeviceRequest] =
this._supportedVerificationMethods.map(verificationMethodIdentifierToMethod), await userIdentity.requestVerification(
this._supportedVerificationMethods.map(verificationMethodIdentifierToMethod),
);
await this.outgoingRequestProcessor.makeOutgoingRequest(outgoingRequest);
return new RustVerificationRequest(
request,
this.outgoingRequestProcessor,
this._supportedVerificationMethods,
); );
await this.outgoingRequestProcessor.makeOutgoingRequest(outgoingRequest); } finally {
return new RustVerificationRequest(request, this.outgoingRequestProcessor, this._supportedVerificationMethods); userIdentity.free();
}
} }
/** /**
@@ -1025,12 +1064,20 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
throw new Error("Not a known device"); throw new Error("Not a known device");
} }
const [request, outgoingRequest]: [RustSdkCryptoJs.VerificationRequest, RustSdkCryptoJs.ToDeviceRequest] = try {
await device.requestVerification( const [request, outgoingRequest]: [RustSdkCryptoJs.VerificationRequest, RustSdkCryptoJs.ToDeviceRequest] =
this._supportedVerificationMethods.map(verificationMethodIdentifierToMethod), await device.requestVerification(
this._supportedVerificationMethods.map(verificationMethodIdentifierToMethod),
);
await this.outgoingRequestProcessor.makeOutgoingRequest(outgoingRequest);
return new RustVerificationRequest(
request,
this.outgoingRequestProcessor,
this._supportedVerificationMethods,
); );
await this.outgoingRequestProcessor.makeOutgoingRequest(outgoingRequest); } finally {
return new RustVerificationRequest(request, this.outgoingRequestProcessor, this._supportedVerificationMethods); device.free();
}
} }
/** /**