diff options
Diffstat (limited to 'includes/external/matrix/node_modules/matrix-js-sdk/lib/rust-crypto/rust-crypto.js')
-rw-r--r-- | includes/external/matrix/node_modules/matrix-js-sdk/lib/rust-crypto/rust-crypto.js | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/lib/rust-crypto/rust-crypto.js b/includes/external/matrix/node_modules/matrix-js-sdk/lib/rust-crypto/rust-crypto.js new file mode 100644 index 0000000..4faf66b --- /dev/null +++ b/includes/external/matrix/node_modules/matrix-js-sdk/lib/rust-crypto/rust-crypto.js @@ -0,0 +1,301 @@ +"use strict"; + +var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.RustCrypto = void 0; +var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); +var RustSdkCryptoJs = _interopRequireWildcard(require("@matrix-org/matrix-sdk-crypto-js")); +var _logger = require("../logger"); +var _CrossSigning = require("../crypto/CrossSigning"); +var _RoomEncryptor = require("./RoomEncryptor"); +var _OutgoingRequestProcessor = require("./OutgoingRequestProcessor"); +var _KeyClaimManager = require("./KeyClaimManager"); +function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } +function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/** + * An implementation of {@link CryptoBackend} using the Rust matrix-sdk-crypto. + */ +class RustCrypto { + /** whether {@link stop} has been called */ + + /** whether {@link outgoingRequestLoop} is currently running */ + + /** mapping of roomId → encryptor class */ + + constructor(olmMachine, http, _userId, _deviceId) { + this.olmMachine = olmMachine; + (0, _defineProperty2.default)(this, "globalErrorOnUnknownDevices", false); + (0, _defineProperty2.default)(this, "stopped", false); + (0, _defineProperty2.default)(this, "outgoingRequestLoopRunning", false); + (0, _defineProperty2.default)(this, "roomEncryptors", {}); + (0, _defineProperty2.default)(this, "keyClaimManager", void 0); + (0, _defineProperty2.default)(this, "outgoingRequestProcessor", void 0); + (0, _defineProperty2.default)(this, "globalBlacklistUnverifiedDevices", false); + this.outgoingRequestProcessor = new _OutgoingRequestProcessor.OutgoingRequestProcessor(olmMachine, http); + this.keyClaimManager = new _KeyClaimManager.KeyClaimManager(olmMachine, this.outgoingRequestProcessor); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // CryptoBackend implementation + // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + stop() { + // stop() may be called multiple times, but attempting to close() the OlmMachine twice + // will cause an error. + if (this.stopped) { + return; + } + this.stopped = true; + this.keyClaimManager.stop(); + + // make sure we close() the OlmMachine; doing so means that all the Rust objects will be + // cleaned up; in particular, the indexeddb connections will be closed, which means they + // can then be deleted. + this.olmMachine.close(); + } + async encryptEvent(event, _room) { + const roomId = event.getRoomId(); + const encryptor = this.roomEncryptors[roomId]; + if (!encryptor) { + throw new Error(`Cannot encrypt event in unconfigured room ${roomId}`); + } + await encryptor.encryptEvent(event); + } + async decryptEvent(event) { + const roomId = event.getRoomId(); + if (!roomId) { + // presumably, a to-device message. These are normally decrypted in preprocessToDeviceMessages + // so the fact it has come back here suggests that decryption failed. + // + // once we drop support for the libolm crypto implementation, we can stop passing to-device messages + // through decryptEvent and hence get rid of this case. + throw new Error("to-device event was not decrypted in preprocessToDeviceMessages"); + } + const res = await this.olmMachine.decryptRoomEvent(JSON.stringify({ + event_id: event.getId(), + type: event.getWireType(), + sender: event.getSender(), + state_key: event.getStateKey(), + content: event.getWireContent(), + origin_server_ts: event.getTs() + }), new RustSdkCryptoJs.RoomId(event.getRoomId())); + return { + clearEvent: JSON.parse(res.event), + claimedEd25519Key: res.senderClaimedEd25519Key, + senderCurve25519Key: res.senderCurve25519Key, + forwardingCurve25519KeyChain: res.forwardingCurve25519KeyChain + }; + } + getEventEncryptionInfo(event) { + var _event$getSenderKey; + // TODO: make this work properly. Or better, replace it. + + const ret = {}; + ret.senderKey = (_event$getSenderKey = event.getSenderKey()) !== null && _event$getSenderKey !== void 0 ? _event$getSenderKey : undefined; + ret.algorithm = event.getWireContent().algorithm; + if (!ret.senderKey || !ret.algorithm) { + ret.encrypted = false; + return ret; + } + ret.encrypted = true; + ret.authenticated = true; + ret.mismatchedSender = true; + return ret; + } + checkUserTrust(userId) { + // TODO + return new _CrossSigning.UserTrustLevel(false, false, false); + } + checkDeviceTrust(userId, deviceId) { + // TODO + return new _CrossSigning.DeviceTrustLevel(false, false, false, false); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // CryptoApi implementation + // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + async userHasCrossSigningKeys() { + // TODO + return false; + } + prepareToEncrypt(room) { + const encryptor = this.roomEncryptors[room.roomId]; + if (encryptor) { + encryptor.ensureEncryptionSession(); + } + } + forceDiscardSession(roomId) { + var _this$roomEncryptors$; + return (_this$roomEncryptors$ = this.roomEncryptors[roomId]) === null || _this$roomEncryptors$ === void 0 ? void 0 : _this$roomEncryptors$.forceDiscardSession(); + } + async exportRoomKeys() { + // TODO + return []; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // SyncCryptoCallbacks implementation + // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Apply sync changes to the olm machine + * @param events - the received to-device messages + * @param oneTimeKeysCounts - the received one time key counts + * @param unusedFallbackKeys - the received unused fallback keys + * @returns A list of preprocessed to-device messages. + */ + async receiveSyncChanges({ + events, + oneTimeKeysCounts = new Map(), + unusedFallbackKeys = new Set() + }) { + const result = await this.olmMachine.receiveSyncChanges(events ? JSON.stringify(events) : "[]", new RustSdkCryptoJs.DeviceLists(), oneTimeKeysCounts, unusedFallbackKeys); + + // receiveSyncChanges returns a JSON-encoded list of decrypted to-device messages. + return JSON.parse(result); + } + + /** called by the sync loop to preprocess incoming to-device messages + * + * @param events - the received to-device messages + * @returns A list of preprocessed to-device messages. + */ + preprocessToDeviceMessages(events) { + // send the received to-device messages into receiveSyncChanges. We have no info on device-list changes, + // one-time-keys, or fallback keys, so just pass empty data. + return this.receiveSyncChanges({ + events + }); + } + + /** called by the sync loop to preprocess one time key counts + * + * @param oneTimeKeysCounts - the received one time key counts + * @returns A list of preprocessed to-device messages. + */ + async preprocessOneTimeKeyCounts(oneTimeKeysCounts) { + await this.receiveSyncChanges({ + oneTimeKeysCounts + }); + } + + /** called by the sync loop to preprocess unused fallback keys + * + * @param unusedFallbackKeys - the received unused fallback keys + * @returns A list of preprocessed to-device messages. + */ + async preprocessUnusedFallbackKeys(unusedFallbackKeys) { + await this.receiveSyncChanges({ + unusedFallbackKeys + }); + } + + /** called by the sync loop on m.room.encrypted events + * + * @param room - in which the event was received + * @param event - encryption event to be processed + */ + async onCryptoEvent(room, event) { + const config = event.getContent(); + const existingEncryptor = this.roomEncryptors[room.roomId]; + if (existingEncryptor) { + existingEncryptor.onCryptoEvent(config); + } else { + this.roomEncryptors[room.roomId] = new _RoomEncryptor.RoomEncryptor(this.olmMachine, this.keyClaimManager, this.outgoingRequestProcessor, room, config); + } + + // start tracking devices for any users already known to be in this room. + const members = await room.getEncryptionTargetMembers(); + _logger.logger.debug(`[${room.roomId} encryption] starting to track devices for: `, members.map(u => `${u.userId} (${u.membership})`)); + await this.olmMachine.updateTrackedUsers(members.map(u => new RustSdkCryptoJs.UserId(u.userId))); + } + + /** called by the sync loop after processing each sync. + * + * TODO: figure out something equivalent for sliding sync. + * + * @param syncState - information on the completed sync. + */ + onSyncCompleted(syncState) { + // Processing the /sync may have produced new outgoing requests which need sending, so kick off the outgoing + // request loop, if it's not already running. + this.outgoingRequestLoop(); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Other public functions + // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** called by the MatrixClient on a room membership event + * + * @param event - The matrix event which caused this event to fire. + * @param member - The member whose RoomMember.membership changed. + * @param oldMembership - The previous membership state. Null if it's a new member. + */ + onRoomMembership(event, member, oldMembership) { + const enc = this.roomEncryptors[event.getRoomId()]; + if (!enc) { + // not encrypting in this room + return; + } + enc.onRoomMembership(member); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Outgoing requests + // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + async outgoingRequestLoop() { + if (this.outgoingRequestLoopRunning) { + return; + } + this.outgoingRequestLoopRunning = true; + try { + while (!this.stopped) { + const outgoingRequests = await this.olmMachine.outgoingRequests(); + if (outgoingRequests.length == 0 || this.stopped) { + // no more messages to send (or we have been told to stop): exit the loop + return; + } + for (const msg of outgoingRequests) { + await this.outgoingRequestProcessor.makeOutgoingRequest(msg); + } + } + } catch (e) { + _logger.logger.error("Error processing outgoing-message requests from rust crypto-sdk", e); + } finally { + this.outgoingRequestLoopRunning = false; + } + } +} +exports.RustCrypto = RustCrypto; +//# sourceMappingURL=rust-crypto.js.map
\ No newline at end of file |