Page MenuHomePhabricator

D12669.id43130.diff
No OneTemporary

D12669.id43130.diff

diff --git a/lib/keyserver-conn/keyserver-auth.js b/lib/keyserver-conn/keyserver-auth.js
--- a/lib/keyserver-conn/keyserver-auth.js
+++ b/lib/keyserver-conn/keyserver-auth.js
@@ -100,7 +100,7 @@
const [notifsSession, contentSession, { userID, deviceID }] =
await Promise.all([
- olmAPI.notificationsSessionCreator(
+ olmAPI.keyserverNotificationsSessionCreator(
cookie,
keyserverKeys.identityKeysBlob.notificationIdentityPublicKeys,
keyserverKeys.notifInitializationInfo,
diff --git a/lib/shared/crypto-utils.js b/lib/shared/crypto-utils.js
--- a/lib/shared/crypto-utils.js
+++ b/lib/shared/crypto-utils.js
@@ -67,7 +67,7 @@
signedIdentityKeysBlob.payload,
);
- return await olmAPI.notificationsSessionCreator(
+ return await olmAPI.keyserverNotificationsSessionCreator(
cookie,
notificationIdentityPublicKeys,
notifInitializationInfo,
diff --git a/lib/types/crypto-types.js b/lib/types/crypto-types.js
--- a/lib/types/crypto-types.js
+++ b/lib/types/crypto-types.js
@@ -167,12 +167,17 @@
contentIdentityKeys: OLMIdentityKeys,
contentInitializationInfo: OlmSessionInitializationInfo,
) => Promise<OutboundSessionCreationResult>,
- +notificationsSessionCreator: (
+ +keyserverNotificationsSessionCreator: (
cookie: ?string,
notificationsIdentityKeys: OLMIdentityKeys,
notificationsInitializationInfo: OlmSessionInitializationInfo,
keyserverID: string,
) => Promise<string>,
+ +notificationsOutboundSessionCreator: (
+ deviceID: string,
+ notificationsIdentityKeys: OLMIdentityKeys,
+ notificationsInitializationInfo: OlmSessionInitializationInfo,
+ ) => Promise<EncryptedData>,
+reassignNotificationsSession?: (
prevCookie: ?string,
newCookie: ?string,
diff --git a/lib/utils/__mocks__/config.js b/lib/utils/__mocks__/config.js
--- a/lib/utils/__mocks__/config.js
+++ b/lib/utils/__mocks__/config.js
@@ -21,7 +21,8 @@
decryptAndPersist: jest.fn(),
contentInboundSessionCreator: jest.fn(),
contentOutboundSessionCreator: jest.fn(),
- notificationsSessionCreator: jest.fn(),
+ keyserverNotificationsSessionCreator: jest.fn(),
+ notificationsOutboundSessionCreator: jest.fn(),
getOneTimeKeys: jest.fn(),
validateAndUploadPrekeys: jest.fn(),
signMessage: jest.fn(),
diff --git a/native/crypto/olm-api.js b/native/crypto/olm-api.js
--- a/native/crypto/olm-api.js
+++ b/native/crypto/olm-api.js
@@ -59,7 +59,7 @@
contentIdentityKeys.ed25519,
);
},
- notificationsSessionCreator(
+ keyserverNotificationsSessionCreator(
cookie: ?string,
notificationsIdentityKeys: OLMIdentityKeys,
notificationsInitializationInfo: OlmSessionInitializationInfo,
@@ -75,6 +75,25 @@
keyserverID,
);
},
+ async notificationsOutboundSessionCreator(
+ deviceID: string,
+ notificationsIdentityKeys: OLMIdentityKeys,
+ notificationsInitializationInfo: OlmSessionInitializationInfo,
+ ): Promise<EncryptedData> {
+ const { prekey, prekeySignature, oneTimeKey } =
+ notificationsInitializationInfo;
+ const identityKeys = JSON.stringify({
+ curve25519: notificationsIdentityKeys.curve25519,
+ ed25519: notificationsIdentityKeys.ed25519,
+ });
+ return commCoreModule.initializeNotificationsOutboundSession(
+ identityKeys,
+ prekey,
+ prekeySignature,
+ oneTimeKey,
+ deviceID,
+ );
+ },
async getOneTimeKeys(numberOfKeys: number): Promise<OneTimeKeysResultValues> {
const { contentOneTimeKeys, notificationsOneTimeKeys } =
await commCoreModule.getOneTimeKeys(numberOfKeys);
diff --git a/web/crypto/olm-api.js b/web/crypto/olm-api.js
--- a/web/crypto/olm-api.js
+++ b/web/crypto/olm-api.js
@@ -50,7 +50,12 @@
decryptAndPersist: proxyToWorker('decryptAndPersist'),
contentInboundSessionCreator: proxyToWorker('contentInboundSessionCreator'),
contentOutboundSessionCreator: proxyToWorker('contentOutboundSessionCreator'),
- notificationsSessionCreator: proxyToWorker('notificationsSessionCreator'),
+ keyserverNotificationsSessionCreator: proxyToWorker(
+ 'keyserverNotificationsSessionCreator',
+ ),
+ notificationsOutboundSessionCreator: proxyToWorker(
+ 'notificationsOutboundSessionCreator',
+ ),
reassignNotificationsSession: proxyToWorker('reassignNotificationsSession'),
getOneTimeKeys: proxyToWorker('getOneTimeKeys'),
validateAndUploadPrekeys: proxyToWorker('validateAndUploadPrekeys'),
diff --git a/web/push-notif/notif-crypto-utils.js b/web/push-notif/notif-crypto-utils.js
--- a/web/push-notif/notif-crypto-utils.js
+++ b/web/push-notif/notif-crypto-utils.js
@@ -49,6 +49,7 @@
const SESSION_UPDATE_MAX_PENDING_TIME = 10 * 1000;
const INDEXED_DB_KEYSERVER_PREFIX = 'keyserver';
const INDEXED_DB_KEY_SEPARATOR = ':';
+const INDEXED_DB_DEVICE_PREFIX = 'device';
// This constant is only used to migrate the existing notifications
// session with production keyserver to new IndexedDB key format. This
@@ -407,6 +408,14 @@
return [olmDataContentKeyBase, cookieID].join(INDEXED_DB_KEY_SEPARATOR);
}
+function getOlmDataContentKeyForDeviceID(deviceID: string): string {
+ return [
+ INDEXED_DB_DEVICE_PREFIX,
+ deviceID,
+ NOTIFICATIONS_OLM_DATA_CONTENT,
+ ].join(INDEXED_DB_KEY_SEPARATOR);
+}
+
function getOlmEncryptionKeyDBLabelForCookie(
cookie: ?string,
keyserverID?: string,
@@ -429,6 +438,14 @@
return [olmEncryptionKeyDBLabelBase, cookieID].join(INDEXED_DB_KEY_SEPARATOR);
}
+function getOlmEncryptionKeyDBLabelForDeviceID(deviceID: string): string {
+ return [
+ INDEXED_DB_DEVICE_PREFIX,
+ deviceID,
+ NOTIFICATIONS_OLM_DATA_ENCRYPTION_KEY,
+ ].join(INDEXED_DB_KEY_SEPARATOR);
+}
+
function getCookieIDFromOlmDBKey(olmDBKey: string): string | '0' {
// Olm DB keys comply to one of the following formats:
// KEYSERVER:<id>:(OLM_CONTENT | OLM_ENCRYPTION_KEY):<cookie id>
@@ -542,6 +559,8 @@
decryptDesktopNotification,
getOlmDataContentKeyForCookie,
getOlmEncryptionKeyDBLabelForCookie,
+ getOlmDataContentKeyForDeviceID,
+ getOlmEncryptionKeyDBLabelForDeviceID,
migrateLegacyOlmNotificationsSessions,
updateNotifsUnreadCountStorage,
queryNotifsUnreadCountStorage,
diff --git a/web/shared-worker/worker/worker-crypto.js b/web/shared-worker/worker/worker-crypto.js
--- a/web/shared-worker/worker/worker-crypto.js
+++ b/web/shared-worker/worker/worker-crypto.js
@@ -52,6 +52,8 @@
import {
getOlmDataContentKeyForCookie,
getOlmEncryptionKeyDBLabelForCookie,
+ getOlmDataContentKeyForDeviceID,
+ getOlmEncryptionKeyDBLabelForDeviceID,
} from '../../push-notif/notif-crypto-utils.js';
import {
type WorkerRequestMessage,
@@ -147,6 +149,81 @@
}
}
+async function createAndPersistNotificationsOutboundSession(
+ notificationsIdentityKeys: OLMIdentityKeys,
+ notificationsInitializationInfo: OlmSessionInitializationInfo,
+ dataPersistenceKey: string,
+ dataEncryptionKeyDBLabel: string,
+): Promise<EncryptedData> {
+ if (!cryptoStore) {
+ throw new Error('Crypto account not initialized');
+ }
+
+ const { notificationAccountPickleKey, notificationAccount } = cryptoStore;
+ const encryptionKey = await generateCryptoKey({
+ extractable: isDesktopSafari,
+ });
+
+ const notificationsPrekey = notificationsInitializationInfo.prekey;
+ const session = new olm.Session();
+ if (notificationsInitializationInfo.oneTimeKey) {
+ session.create_outbound(
+ notificationAccount,
+ notificationsIdentityKeys.curve25519,
+ notificationsIdentityKeys.ed25519,
+ notificationsPrekey,
+ notificationsInitializationInfo.prekeySignature,
+ notificationsInitializationInfo.oneTimeKey,
+ );
+ } else {
+ session.create_outbound_without_otk(
+ notificationAccount,
+ notificationsIdentityKeys.curve25519,
+ notificationsIdentityKeys.ed25519,
+ notificationsPrekey,
+ notificationsInitializationInfo.prekeySignature,
+ );
+ }
+ const { body: message, type: messageType } = session.encrypt(
+ JSON.stringify(initialEncryptedMessageContent),
+ );
+
+ const mainSession = session.pickle(notificationAccountPickleKey);
+ const notificationsOlmData: NotificationsOlmDataType = {
+ mainSession,
+ pendingSessionUpdate: mainSession,
+ updateCreationTimestamp: Date.now(),
+ picklingKey: notificationAccountPickleKey,
+ };
+ const encryptedOlmData = await encryptData(
+ new TextEncoder().encode(JSON.stringify(notificationsOlmData)),
+ encryptionKey,
+ );
+
+ const persistEncryptionKeyPromise = (async () => {
+ let cryptoKeyPersistentForm;
+ if (isDesktopSafari) {
+ // Safari doesn't support structured clone algorithm in service
+ // worker context so we have to store CryptoKey as JSON
+ cryptoKeyPersistentForm = await exportKeyToJWK(encryptionKey);
+ } else {
+ cryptoKeyPersistentForm = encryptionKey;
+ }
+
+ await localforage.setItem(
+ dataEncryptionKeyDBLabel,
+ cryptoKeyPersistentForm,
+ );
+ })();
+
+ await Promise.all([
+ localforage.setItem(dataPersistenceKey, encryptedOlmData),
+ persistEncryptionKeyPromise,
+ ]);
+
+ return { message, messageType };
+}
+
function getOrCreateOlmAccount(accountIDInDB: number): {
+picklingKey: string,
+account: olm.Account,
@@ -646,7 +723,22 @@
return { encryptedData, sessionVersion: newSessionVersion };
},
- async notificationsSessionCreator(
+ async notificationsOutboundSessionCreator(
+ deviceID: string,
+ notificationsIdentityKeys: OLMIdentityKeys,
+ notificationsInitializationInfo: OlmSessionInitializationInfo,
+ ): Promise<EncryptedData> {
+ const dataPersistenceKey = getOlmDataContentKeyForDeviceID(deviceID);
+ const dataEncryptionKeyDBLabel =
+ getOlmEncryptionKeyDBLabelForDeviceID(deviceID);
+ return createAndPersistNotificationsOutboundSession(
+ notificationsIdentityKeys,
+ notificationsInitializationInfo,
+ dataPersistenceKey,
+ dataEncryptionKeyDBLabel,
+ );
+ },
+ async keyserverNotificationsSessionCreator(
cookie: ?string,
notificationsIdentityKeys: OLMIdentityKeys,
notificationsInitializationInfo: OlmSessionInitializationInfo,
@@ -657,76 +749,17 @@
throw new Error('Worker not initialized');
}
- if (!cryptoStore) {
- throw new Error('Crypto account not initialized');
- }
-
- const { notificationAccountPickleKey, notificationAccount } = cryptoStore;
- const encryptionKey = await generateCryptoKey({
- extractable: isDesktopSafari,
- });
-
- const notificationsPrekey = notificationsInitializationInfo.prekey;
- const session = new olm.Session();
- if (notificationsInitializationInfo.oneTimeKey) {
- session.create_outbound(
- notificationAccount,
- notificationsIdentityKeys.curve25519,
- notificationsIdentityKeys.ed25519,
- notificationsPrekey,
- notificationsInitializationInfo.prekeySignature,
- notificationsInitializationInfo.oneTimeKey,
- );
- } else {
- session.create_outbound_without_otk(
- notificationAccount,
- notificationsIdentityKeys.curve25519,
- notificationsIdentityKeys.ed25519,
- notificationsPrekey,
- notificationsInitializationInfo.prekeySignature,
- );
- }
- const { body: initialNotificationsEncryptedMessage } = session.encrypt(
- JSON.stringify(initialEncryptedMessageContent),
- );
-
- const mainSession = session.pickle(notificationAccountPickleKey);
- const notificationsOlmData: NotificationsOlmDataType = {
- mainSession,
- pendingSessionUpdate: mainSession,
- updateCreationTimestamp: Date.now(),
- picklingKey: notificationAccountPickleKey,
- };
- const encryptedOlmData = await encryptData(
- new TextEncoder().encode(JSON.stringify(notificationsOlmData)),
- encryptionKey,
- );
-
const { notifsOlmDataContentKey, notifsOlmDataEncryptionKeyDBLabel } =
getNotifsPersistenceKeys(cookie, keyserverID, platformDetails);
- const persistEncryptionKeyPromise = (async () => {
- let cryptoKeyPersistentForm;
- if (isDesktopSafari) {
- // Safari doesn't support structured clone algorithm in service
- // worker context so we have to store CryptoKey as JSON
- cryptoKeyPersistentForm = await exportKeyToJWK(encryptionKey);
- } else {
- cryptoKeyPersistentForm = encryptionKey;
- }
-
- await localforage.setItem(
- notifsOlmDataEncryptionKeyDBLabel,
- cryptoKeyPersistentForm,
- );
- })();
-
- await Promise.all([
- localforage.setItem(notifsOlmDataContentKey, encryptedOlmData),
- persistEncryptionKeyPromise,
- ]);
+ const { message } = await createAndPersistNotificationsOutboundSession(
+ notificationsIdentityKeys,
+ notificationsInitializationInfo,
+ notifsOlmDataContentKey,
+ notifsOlmDataEncryptionKeyDBLabel,
+ );
- return initialNotificationsEncryptedMessage;
+ return message;
},
async reassignNotificationsSession(
prevCookie: ?string,

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 23, 1:02 AM (12 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2561309
Default Alt Text
D12669.id43130.diff (12 KB)

Event Timeline