1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-12-08 19:08:34 +03:00

various cross-signing fixes and improvements

This commit is contained in:
Hubert Chathi
2019-06-12 11:47:12 -04:00
parent 98815ffdf6
commit 4c6fa89053
7 changed files with 239 additions and 91 deletions

View File

@@ -50,11 +50,16 @@ describe("Cross Signing", function() {
const alice = await makeTestClient( const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"}, {userId: "@alice:example.com", deviceId: "Osborne2"},
); );
alice.uploadDeviceSigningKeys = async function(e) {return;};
alice.uploadKeySignatures = async function(e) {return;};
// set Alice's cross-signing key // set Alice's cross-signing key
let privateKeys; let privateKeys;
alice.on("cross-signing:savePrivateKeys", function(e) { alice.on("cross-signing:savePrivateKeys", function(e) {
privateKeys = e; privateKeys = e;
}); });
alice.on("cross-signing:getKey", function(e) {
e.done(privateKeys[e.type]);
});
await alice.resetCrossSigningKeys(); await alice.resetCrossSigningKeys();
// Alice downloads Bob's device key // Alice downloads Bob's device key
alice._crypto._deviceList.storeCrossSigningForUser("@bob:example.com", { alice._crypto._deviceList.storeCrossSigningForUser("@bob:example.com", {
@@ -69,10 +74,6 @@ describe("Cross Signing", function() {
}, },
}); });
// Alice verifies Bob's key // Alice verifies Bob's key
alice.on("cross-signing:getKey", function(e) {
expect(e.type).toBe("user_signing");
e.done(privateKeys.user_signing);
});
const promise = new Promise((resolve, reject) => { const promise = new Promise((resolve, reject) => {
alice.uploadKeySignatures = (...args) => { alice.uploadKeySignatures = (...args) => {
resolve(...args); resolve(...args);
@@ -110,6 +111,10 @@ describe("Cross Signing", function() {
alice.once("cross-signing:newKey", (e) => { alice.once("cross-signing:newKey", (e) => {
e.done(masterKey); e.done(masterKey);
}); });
alice.on("cross-signing:getKey", (e) => {
// will be called to sign our own device
e.done(selfSigningKey);
});
const deviceInfo = alice._crypto._deviceList._devices["@alice:example.com"] const deviceInfo = alice._crypto._deviceList._devices["@alice:example.com"]
.Osborne2; .Osborne2;
@@ -198,8 +203,13 @@ describe("Cross Signing", function() {
}, },
}, },
}, },
{
method: "POST",
path: "/keys/signatures/upload",
data: {},
},
]; ];
setHttpResponses(alice, responses); setHttpResponses(alice, responses, true, true);
await alice.startClient(); await alice.startClient();
@@ -213,11 +223,16 @@ describe("Cross Signing", function() {
const alice = await makeTestClient( const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"}, {userId: "@alice:example.com", deviceId: "Osborne2"},
); );
alice.uploadDeviceSigningKeys = async function(e) {return;};
alice.uploadKeySignatures = async function(e) {return;};
// set Alice's cross-signing key // set Alice's cross-signing key
let privateKeys; let privateKeys;
alice.on("cross-signing:savePrivateKeys", function(e) { alice.on("cross-signing:savePrivateKeys", function(e) {
privateKeys = e; privateKeys = e;
}); });
alice.on("cross-signing:getKey", function(e) {
e.done(privateKeys[e.type]);
});
await alice.resetCrossSigningKeys(); await alice.resetCrossSigningKeys();
// Alice downloads Bob's ssk and device key // Alice downloads Bob's ssk and device key
const bobMasterSigning = new global.Olm.PkSigning(); const bobMasterSigning = new global.Olm.PkSigning();
@@ -275,10 +290,6 @@ describe("Cross Signing", function() {
expect(alice.checkUserTrust("@bob:example.com")).toBe(2); expect(alice.checkUserTrust("@bob:example.com")).toBe(2);
expect(alice.checkDeviceTrust("@bob:example.com", "Dynabook")).toBe(2); expect(alice.checkDeviceTrust("@bob:example.com", "Dynabook")).toBe(2);
// Alice verifies Bob's SSK // Alice verifies Bob's SSK
alice.on("cross-signing:getKey", function(e) {
expect(e.type).toBe("user_signing");
e.done(privateKeys.user_signing);
});
alice.uploadKeySignatures = () => {}; alice.uploadKeySignatures = () => {};
await alice.setDeviceVerified("@bob:example.com", bobMasterPubkey, true); await alice.setDeviceVerified("@bob:example.com", bobMasterPubkey, true);
// Bob's device key should be trusted // Bob's device key should be trusted
@@ -292,17 +303,18 @@ describe("Cross Signing", function() {
); );
alice._crypto._deviceList.startTrackingDeviceList("@bob:example.com"); alice._crypto._deviceList.startTrackingDeviceList("@bob:example.com");
alice._crypto._deviceList.stopTrackingAllDeviceLists = () => {}; alice._crypto._deviceList.stopTrackingAllDeviceLists = () => {};
alice.uploadDeviceSigningKeys = async function(e) {return;};
alice.uploadKeySignatures = async function(e) {return;};
// set Alice's cross-signing key // set Alice's cross-signing key
let privateKeys; let privateKeys;
alice.on("cross-signing:savePrivateKeys", function(e) { alice.on("cross-signing:savePrivateKeys", function(e) {
privateKeys = e; privateKeys = e;
}); });
await alice.resetCrossSigningKeys(); alice.on("cross-signing:getKey", (e) => {
alice.once("cross-signing:getKey", (e) => {
e.done(privateKeys[e.type]); e.done(privateKeys[e.type]);
}); });
await alice.resetCrossSigningKeys();
const selfSigningKey = new Uint8Array([ const selfSigningKey = new Uint8Array([
0x1e, 0xf4, 0x01, 0x6d, 0x4f, 0xa1, 0x73, 0x66, 0x1e, 0xf4, 0x01, 0x6d, 0x4f, 0xa1, 0x73, 0x66,
@@ -450,11 +462,16 @@ describe("Cross Signing", function() {
const alice = await makeTestClient( const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"}, {userId: "@alice:example.com", deviceId: "Osborne2"},
); );
alice.uploadDeviceSigningKeys = async function(e) {return;};
alice.uploadKeySignatures = async function(e) {return;};
// set Alice's cross-signing key // set Alice's cross-signing key
let privateKeys; let privateKeys;
alice.on("cross-signing:savePrivateKeys", function(e) { alice.on("cross-signing:savePrivateKeys", function(e) {
privateKeys = e; privateKeys = e;
}); });
alice.on("cross-signing:getKey", (e) => {
e.done(privateKeys[e.type]);
});
await alice.resetCrossSigningKeys(); await alice.resetCrossSigningKeys();
// Alice downloads Bob's ssk and device key // Alice downloads Bob's ssk and device key
// (NOTE: device key is not signed by ssk) // (NOTE: device key is not signed by ssk)
@@ -506,12 +523,9 @@ describe("Cross Signing", function() {
// Bob's device key should be untrusted // Bob's device key should be untrusted
expect(alice.checkDeviceTrust("@bob:example.com", "Dynabook")).toBe(0); expect(alice.checkDeviceTrust("@bob:example.com", "Dynabook")).toBe(0);
// Alice verifies Bob's SSK // Alice verifies Bob's SSK
alice.on("cross-signing:getKey", function(e) { console.log("verifying bob's device");
expect(e.type).toBe("user_signing");
e.done(privateKeys.user_signing);
});
alice.uploadKeySignatures = () => {};
await alice.setDeviceVerified("@bob:example.com", bobMasterPubkey, true); await alice.setDeviceVerified("@bob:example.com", bobMasterPubkey, true);
console.log("done");
// Bob's device key should be untrusted // Bob's device key should be untrusted
expect(alice.checkDeviceTrust("@bob:example.com", "Dynabook")).toBe(0); expect(alice.checkDeviceTrust("@bob:example.com", "Dynabook")).toBe(0);
}); });
@@ -520,10 +534,15 @@ describe("Cross Signing", function() {
const alice = await makeTestClient( const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"}, {userId: "@alice:example.com", deviceId: "Osborne2"},
); );
alice.uploadDeviceSigningKeys = async function(e) {return;};
alice.uploadKeySignatures = async function(e) {return;};
let privateKeys; let privateKeys;
alice.on("cross-signing:savePrivateKeys", function(e) { alice.on("cross-signing:savePrivateKeys", function(e) {
privateKeys = e; privateKeys = e;
}); });
alice.on("cross-signing:getKey", function(e) {
e.done(privateKeys[e.type]);
});
await alice.resetCrossSigningKeys(); await alice.resetCrossSigningKeys();
// Alice downloads Bob's keys // Alice downloads Bob's keys
const bobMasterSigning = new global.Olm.PkSigning(); const bobMasterSigning = new global.Olm.PkSigning();
@@ -577,10 +596,6 @@ describe("Cross Signing", function() {
Dynabook: bobDevice, Dynabook: bobDevice,
}); });
// Alice verifies Bob's SSK // Alice verifies Bob's SSK
alice.on("cross-signing:getKey", function(e) {
expect(e.type).toBe("user_signing");
e.done(privateKeys.user_signing);
});
alice.uploadKeySignatures = () => {}; alice.uploadKeySignatures = () => {};
await alice.setDeviceVerified("@bob:example.com", bobMasterPubkey, true); await alice.setDeviceVerified("@bob:example.com", bobMasterPubkey, true);
// Bob's device key should be trusted // Bob's device key should be trusted
@@ -624,8 +639,7 @@ describe("Cross Signing", function() {
expect(alice.checkDeviceTrust("@bob:example.com", "Dynabook")).toBe(0); expect(alice.checkDeviceTrust("@bob:example.com", "Dynabook")).toBe(0);
// Alice verifies Bob's SSK // Alice verifies Bob's SSK
alice.on("cross-signing:getKey", function(e) { alice.on("cross-signing:getKey", function(e) {
expect(e.type).toBe("user_signing"); e.done(privateKeys[e.type]);
e.done(privateKeys.user_signing);
}); });
alice.uploadKeySignatures = () => {}; alice.uploadKeySignatures = () => {};
await alice.setDeviceVerified("@bob:example.com", bobMasterPubkey2, true); await alice.setDeviceVerified("@bob:example.com", bobMasterPubkey2, true);

View File

@@ -1676,9 +1676,10 @@ MatrixBaseApis.prototype.getKeyChanges = function(oldToken, newToken) {
); );
}; };
MatrixBaseApis.prototype.uploadDeviceSigningKeys = function(keys) { MatrixBaseApis.prototype.uploadDeviceSigningKeys = function(auth, keys) {
const data = Object.assign({}, keys, {auth});
return this._http.authedRequestWithPrefix( return this._http.authedRequestWithPrefix(
undefined, "POST", "/keys/device_signing/upload", undefined, keys, undefined, "POST", "/keys/device_signing/upload", undefined, data,
httpApi.PREFIX_UNSTABLE, httpApi.PREFIX_UNSTABLE,
); );
}; };

View File

@@ -559,6 +559,9 @@ MatrixClient.prototype.initCrypto = async function() {
"crypto.roomKeyRequest", "crypto.roomKeyRequest",
"crypto.roomKeyRequestCancellation", "crypto.roomKeyRequestCancellation",
"crypto.warning", "crypto.warning",
"crypto.devicesUpdated",
"cross-signing:savePrivateKeys",
"cross-signing:getKey",
]); ]);
logger.log("Crypto: initialising crypto object..."); logger.log("Crypto: initialising crypto object...");
@@ -795,27 +798,34 @@ MatrixClient.prototype.getGlobalBlacklistUnverifiedDevices = function() {
}; };
/** /**
* returns a function that just calls the corresponding function from this._crypto. * add methods that call the corresponding method in this._crypto
* *
* @param {string} name the function to call * @param {class} MatrixClient the class to add the method to
* * @param {string} names the names of the methods to call
* @return {Function} a wrapper function
*/ */
function wrapCryptoFunc(name) { function wrapCryptoFuncs(MatrixClient, names) {
return function(...args) { for (const name of names) {
if (!this._crypto) { // eslint-disable-line no-invalid-this MatrixClient.prototype[name] = function(...args) {
throw new Error("End-to-end encryption disabled"); if (!this._crypto) { // eslint-disable-line no-invalid-this
} throw new Error("End-to-end encryption disabled");
}
return this._crypto[name](...args); // eslint-disable-line no-invalid-this return this._crypto[name](...args); // eslint-disable-line no-invalid-this
}; };
}
} }
MatrixClient.prototype.checkUserTrust wrapCryptoFuncs(MatrixClient, [
= wrapCryptoFunc("checkUserTrust"); "checkUserTrust",
"checkDeviceTrust",
]);
MatrixClient.prototype.checkDeviceTrust wrapCryptoFuncs(MatrixClient, [
= wrapCryptoFunc("checkDeviceTrust"); "storeSecret",
"getSecret",
"isSecretStored",
"requestSecret",
]);
/** /**
* Get e2e information on the device that sent an event * Get e2e information on the device that sent an event
@@ -848,14 +858,11 @@ MatrixClient.prototype.isEventSenderVerified = async function(event) {
return device.isVerified(); return device.isVerified();
}; };
MatrixClient.prototype.resetCrossSigningKeys wrapCryptoFuncs(MatrixClient, [
= wrapCryptoFunc("resetCrossSigningKeys"); "resetCrossSigningKeys",
"getCrossSigningId",
MatrixClient.prototype.setCrossSigningKeys "getStoredCrossSigningForUser",
= wrapCryptoFunc("setCrossSigningKeys"); ]);
MatrixClient.prototype.getCrossSigningId
= wrapCryptoFunc("getCrossSigningId");
/** /**
* Cancel a room key request for this event if one is ongoing and resend the * Cancel a room key request for this event if one is ongoing and resend the

View File

@@ -195,8 +195,13 @@ export class CrossSigningInfo extends EventEmitter {
logger.error(error); logger.error(error);
throw new Error(error); throw new Error(error);
} }
// First-Use is true if and only if we had no previous key for the user if (!this.keys.master) {
this.fu = !(this.keys.self_signing); // this is the first key we've seen, so first-use is true
this.fu = true;
} else if (getPublicKey(keys.master)[1] !== this.getId()) {
// this is a different key, so first-use is false
this.fu = false;
} // otherwise, same key, so no change
signingKeys.master = keys.master; signingKeys.master = keys.master;
} else if (this.keys.master) { } else if (this.keys.master) {
signingKeys.master = this.keys.master; signingKeys.master = this.keys.master;
@@ -254,7 +259,11 @@ export class CrossSigningInfo extends EventEmitter {
} }
async signUser(key) { async signUser(key) {
if (!this.keys.user_signing) {
return;
}
const [pubkey, usk] = await getPrivateKey(this, "user_signing", (key) => { const [pubkey, usk] = await getPrivateKey(this, "user_signing", (key) => {
// FIXME:
return; return;
}); });
try { try {
@@ -268,9 +277,15 @@ export class CrossSigningInfo extends EventEmitter {
async signDevice(userId, device) { async signDevice(userId, device) {
if (userId !== this.userId) { if (userId !== this.userId) {
throw new Error("Urgh!"); throw new Error(
`Trying to sign ${userId}'s device; can only sign our own device`,
);
}
if (!this.keys.self_signing) {
return;
} }
const [pubkey, ssk] = await getPrivateKey(this, "self_signing", (key) => { const [pubkey, ssk] = await getPrivateKey(this, "self_signing", (key) => {
// FIXME:
return; return;
}); });
try { try {
@@ -288,6 +303,8 @@ export class CrossSigningInfo extends EventEmitter {
} }
checkUserTrust(userCrossSigning) { checkUserTrust(userCrossSigning) {
// if we're checking our own key, then it's trusted if the master key
// and self-signing key match
if (this.userId === userCrossSigning.userId if (this.userId === userCrossSigning.userId
&& this.getId() && this.getId() === userCrossSigning.getId() && this.getId() && this.getId() === userCrossSigning.getId()
&& this.getId("self_signing") && this.getId("self_signing")
@@ -298,7 +315,8 @@ export class CrossSigningInfo extends EventEmitter {
} }
if (!this.keys.user_signing) { if (!this.keys.user_signing) {
return 0; return (userCrossSigning.fu ? CrossSigningVerification.TOFU
: CrossSigningVerification.UNVERIFIED);
} }
let userTrusted; let userTrusted;

View File

@@ -655,6 +655,7 @@ export default class DeviceList extends EventEmitter {
} }
}); });
this.saveIfDirty(); this.saveIfDirty();
this.emit("crypto.devicesUpdated", users);
}; };
return prom; return prom;

View File

@@ -17,6 +17,9 @@ limitations under the License.
import {EventEmitter} from 'events'; import {EventEmitter} from 'events';
import logger from '../logger'; import logger from '../logger';
import olmlib from './olmlib'; import olmlib from './olmlib';
import { randomString } from '../randomstring';
import { keyForNewBackup } from './backup_password';
import { encodeRecoveryKey, decodeRecoveryKey } from './recoverykey';
/** Implements MSC-1946 /** Implements MSC-1946
*/ */
@@ -28,6 +31,56 @@ export default class SecretStorage extends EventEmitter {
this._incomingRequests = {}; this._incomingRequests = {};
} }
async addKey(type, opts) {
const keyData = {
algorithm: opts.algorithm,
};
switch (opts.algorithm) {
case "m.secret_storage.v1.curve25519-aes-sha2":
{
const decryption = new global.Olm.PkDecryption();
try {
if (opts.passphrase) {
const key = await keyForNewBackup(opts.passphrase);
keyData.passphrase = {
algorithm: "m.pbkdf2",
iterations: key.iterations,
salt: key.salt,
};
opts.encodedkey = encodeRecoveryKey(key.key);
keyData.pubkey = decryption.init_with_private_key(key.key);
} else if (opts.privkey) {
keyData.pubkey = decryption.init_with_private_key(opts.privkey);
opts.encodedkey = encodeRecoveryKey(opts.privkey);
} else {
keyData.pubkey = decryption.generate_key();
opts.encodedkey = encodeRecoveryKey(decryption.get_private_key());
}
} finally {
decryption.free();
}
break;
}
default:
throw new Error(`Unknown key algorithm ${opts.algorithm}`);
}
let keyName;
do {
keyName = randomString(32);
} while (!this._baseApis.getAccountData(`m.secret_storage.key.${keyName}`));
// FIXME: sign keyData?
await this._baseApis.setAccountData(
`m.secret_storage.key.${keyName}`, keyData,
);
return keyName;
}
/** store an encrypted secret on the server /** store an encrypted secret on the server
* *
* @param {string} name The name of the secret * @param {string} name The name of the secret
@@ -285,7 +338,11 @@ export default class SecretStorage extends EventEmitter {
}); });
} }
} else if (content.action === "request") { } else if (content.action === "request") {
// if from us and device is trusted (or else check trust) if (deviceId === this._baseApis.deviceId) {
// no point in trying to send ourself the secret
return;
}
// check if we have the secret // check if we have the secret
logger.info("received request for secret (" + sender logger.info("received request for secret (" + sender
+ ", " + deviceId + ", " + content.request_id + ")"); + ", " + deviceId + ", " + content.request_id + ")");
@@ -308,6 +365,15 @@ export default class SecretStorage extends EventEmitter {
sender_key: this._baseApis._crypto._olmDevice.deviceCurve25519Key, sender_key: this._baseApis._crypto._olmDevice.deviceCurve25519Key,
ciphertext: {}, ciphertext: {},
}; };
await olmlib.ensureOlmSessionsForDevices(
this._baseApis._crypto._olmDevice,
this._baseApis,
{
[sender]: [
await this._baseApis.getStoredDevice(sender, deviceId),
],
},
);
await olmlib.encryptMessageForDevice( await olmlib.encryptMessageForDevice(
encryptedContent.ciphertext, encryptedContent.ciphertext,
this._baseApis.getUserId(), this._baseApis.getUserId(),

View File

@@ -25,6 +25,7 @@ limitations under the License.
const anotherjson = require('another-json'); const anotherjson = require('another-json');
import Promise from 'bluebird'; import Promise from 'bluebird';
import {EventEmitter} from 'events'; import {EventEmitter} from 'events';
import ReEmitter from '../ReEmitter';
import logger from '../logger'; import logger from '../logger';
const utils = require("../utils"); const utils = require("../utils");
@@ -107,6 +108,7 @@ export default function Crypto(baseApis, sessionStore, userId, deviceId,
clientStore, cryptoStore, roomList, verificationMethods) { clientStore, cryptoStore, roomList, verificationMethods) {
this._onDeviceListUserCrossSigningUpdated = this._onDeviceListUserCrossSigningUpdated.bind(this); this._onDeviceListUserCrossSigningUpdated = this._onDeviceListUserCrossSigningUpdated.bind(this);
this._reEmitter = new ReEmitter(this);
this._baseApis = baseApis; this._baseApis = baseApis;
this._sessionStore = sessionStore; this._sessionStore = sessionStore;
this._userId = userId; this._userId = userId;
@@ -148,6 +150,7 @@ export default function Crypto(baseApis, sessionStore, userId, deviceId,
// XXX: This isn't removed at any point, but then none of the event listeners // XXX: This isn't removed at any point, but then none of the event listeners
// this class sets seem to be removed at any point... :/ // this class sets seem to be removed at any point... :/
this._deviceList.on('userCrossSigningUpdated', this._onDeviceListUserCrossSigningUpdated); this._deviceList.on('userCrossSigningUpdated', this._onDeviceListUserCrossSigningUpdated);
this._reEmitter.reEmit(this._deviceList, ["crypto.devicesUpdated"]);
// the last time we did a check for the number of one-time-keys on the // the last time we did a check for the number of one-time-keys on the
// server. // server.
@@ -200,18 +203,35 @@ export default function Crypto(baseApis, sessionStore, userId, deviceId,
this._verificationTransactions = new Map(); this._verificationTransactions = new Map();
this._crossSigningInfo = new CrossSigningInfo(userId); this._crossSigningInfo = new CrossSigningInfo(userId);
this._crossSigningInfo.on("cross-signing:savePrivateKeys", (...args) => { this._reEmitter.reEmit(this._crossSigningInfo, [
this._baseApis.emit("cross-signing:savePrivateKeys", ...args); "cross-signing:savePrivateKeys",
}); "cross-signing:getKey",
this._crossSigningInfo.on("cross-signing:getKey", (...args) => { ]);
this._baseApis.emit("cross-signing:getKey", ...args);
});
this._secretStorage = new SecretStorage(baseApis); this._secretStorage = new SecretStorage(baseApis);
// TODO: expose SecretStorage methods // TODO: expose SecretStorage methods
} }
utils.inherits(Crypto, EventEmitter); utils.inherits(Crypto, EventEmitter);
Crypto.prototype.storeSecret = function(name, secret, keys) {
return this._secretStorage.store(name, secret, keys);
};
Crypto.prototype.getSecret = function(name) {
return this._secretStorage.get(name);
};
Crypto.prototype.isSecretStored = function(name, checkKey) {
return this._secretStorage.isStored(name, checkKey);
};
Crypto.prototype.requestSecret = function(name, devices) {
if (!devices) {
devices = Object.keys(this._deviceList.getRawStoredDevicesForUser(this._userId));
}
return this._secretStorage.request(name, devices);
};
/** /**
* Initialise the crypto module so that it is ready for use * Initialise the crypto module so that it is ready for use
* *
@@ -271,19 +291,22 @@ Crypto.prototype.init = async function() {
* keys will be created for the given level and below. Defaults to * keys will be created for the given level and below. Defaults to
* regenerating all keys. * regenerating all keys.
*/ */
Crypto.prototype.resetCrossSigningKeys = async function(level) { Crypto.prototype.resetCrossSigningKeys = async function(authDict, level) {
await this._crossSigningInfo.resetKeys(level); await this._crossSigningInfo.resetKeys(level);
const keys = {};
for (const [name, key] of Object.entries(this._crossSigningInfo.keys)) {
keys[name + "_key"] = key;
}
await this._baseApis.uploadDeviceSigningKeys(authDict || {}, keys);
this._baseApis.emit("cross-signing:keysChanged", {}); this._baseApis.emit("cross-signing:keysChanged", {});
};
/** const device = this._deviceList.getStoredDevice(this._userId, this._deviceId);
* Set the user's cross-signing keys to use. const signedDevice = await this._crossSigningInfo.signDevice(this._userId, device);
* await this._baseApis.uploadKeySignatures({
* @param {object} keys A mapping of key type to key data. [this._userId]: {
*/ [this._deviceId]: signedDevice,
Crypto.prototype.setCrossSigningKeys = function(keys) { },
this._crossSigningInfo.setKeys(keys); });
this._baseApis.emit("cross-signing:keysChanged", {});
}; };
/** /**
@@ -298,6 +321,10 @@ Crypto.prototype.getCrossSigningId = function(type) {
return this._crossSigningInfo.getId(type); return this._crossSigningInfo.getId(type);
}; };
Crypto.prototype.getStoredCrossSigningForUser = function(userId) {
return this._deviceList.getStoredCrossSigningForUser(userId);
};
/** /**
* Check whether a given user is trusted. * Check whether a given user is trusted.
* *
@@ -419,19 +446,29 @@ Crypto.prototype.checkOwnCrossSigningTrust = async function() {
logger.info("Got private key"); logger.info("Got private key");
} }
// FIXME: fetch the private key? const oldSelfSigningId = this._crossSigningInfo.getId("self_signing");
if (this._crossSigningInfo.getId("self_signing") const oldUserSigningId = this._crossSigningInfo.getId("user_signing")
!== newCrossSigning.getId("self_signing")) {
logger.info("Got new self-signing key", newCrossSigning.getId("self_signing"));
}
if (this._crossSigningInfo.getId("user_signing")
!== newCrossSigning.getId("user_signing")) {
logger.info("Got new user-signing key", newCrossSigning.getId("user_signing"));
}
this._crossSigningInfo.setKeys(newCrossSigning.keys); this._crossSigningInfo.setKeys(newCrossSigning.keys);
// FIXME: save it ... somewhere? // FIXME: save it ... somewhere?
if (oldSelfSigningId !== newCrossSigning.getId("self_signing")) {
logger.info("Got new self-signing key", newCrossSigning.getId("self_signing"));
const device = this._deviceList.getStoredDevice(this._userId, this._deviceId);
const signedDevice = await this._crossSigningInfo.signDevice(
this._userId, device,
);
await this._baseApis.uploadKeySignatures({
[this._userId]: {
[this._deviceId]: signedDevice,
},
});
}
if (oldUserSigningId !== newCrossSigning.getId("user_signing")) {
logger.info("Got new user-signing key", newCrossSigning.getId("user_signing"));
}
if (changed) { if (changed) {
this._baseApis.emit("cross-signing:keysChanged", {}); this._baseApis.emit("cross-signing:keysChanged", {});
} }
@@ -1062,12 +1099,13 @@ Crypto.prototype.setDeviceVerification = async function(
if (xsk && xsk.getId() === deviceId) { if (xsk && xsk.getId() === deviceId) {
if (verified) { if (verified) {
const device = await this._crossSigningInfo.signUser(xsk); const device = await this._crossSigningInfo.signUser(xsk);
// FIXME: mark xsk as dirty in device list if (device) {
this._baseApis.uploadKeySignatures({ this._baseApis.uploadKeySignatures({
[userId]: { [userId]: {
[deviceId]: device, [deviceId]: device,
}, },
}); });
}
return device; return device;
} else { } else {
// FIXME: ??? // FIXME: ???
@@ -1109,13 +1147,16 @@ Crypto.prototype.setDeviceVerification = async function(
// do cross-signing // do cross-signing
if (verified && userId === this._userId) { if (verified && userId === this._userId) {
const device = await this._crossSigningInfo.signDevice(userId, dev); const device = await this._crossSigningInfo.signDevice(
// FIXME: mark device as dirty in device list userId, DeviceInfo.fromStorage(dev, deviceId),
this._baseApis.uploadKeySignatures({ );
[userId]: { if (device) {
[deviceId]: device, this._baseApis.uploadKeySignatures({
}, [userId]: {
}); [deviceId]: device,
},
});
}
} }
return DeviceInfo.fromStorage(dev, deviceId); return DeviceInfo.fromStorage(dev, deviceId);