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 @@ -1,9 +1,10 @@ // @flow -import t, { type TInterface } from 'tcomb'; +import t, { type TInterface, type TEnums } from 'tcomb'; import type { OlmSessionInitializationInfo } from './olm-session-types.js'; import { type AuthMetadata } from '../shared/identity-client-context.js'; +import { values } from '../utils/objects.js'; import { tShape } from '../utils/validation-utils.js'; export type OLMIdentityKeys = { @@ -114,6 +115,10 @@ export type OlmEncryptedMessageTypes = $Values; +export const olmEncryptedMessageTypesValidator: TEnums = t.enums.of( + values(olmEncryptedMessageTypes), +); + export type EncryptedData = { +message: string, +messageType: OlmEncryptedMessageTypes, 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 @@ -10,7 +10,9 @@ olmEncryptedMessageTypes, type NotificationsOlmDataType, type PickledOLMAccount, + type OlmEncryptedMessageTypes, } from 'lib/types/crypto-types.js'; +import { olmEncryptedMessageTypesValidator } from 'lib/types/crypto-types.js'; import type { PlainTextWebNotification, EncryptedWebNotification, @@ -94,6 +96,15 @@ 'unreadThickThreadIDsEncryptionKey'; const INDEXED_DB_UNREAD_THICK_THREADS_SYNC_KEY = 'unreadThickThreadIDsSyncKey'; +function stringToOlmEncryptedMessageType( + messageType: string, +): OlmEncryptedMessageTypes { + const messageTypeAsNumber = Number(messageType); + return assertWithValidator( + messageTypeAsNumber, + olmEncryptedMessageTypesValidator, + ); +} async function deserializeEncryptedData( encryptedData: EncryptedData, encryptionKey: CryptoKey, @@ -346,11 +357,11 @@ const { id, encryptedPayload, - type: messageType, + type: rawMessageType, ...rest } = encryptedNotification; const senderDeviceDescriptor: SenderDeviceDescriptor = rest; - + const messageType = stringToOlmEncryptedMessageType(rawMessageType); const utilsData = await localforage.getItem( WEB_NOTIFS_SERVICE_UTILS_KEY, ); @@ -414,6 +425,7 @@ } = await commonDecrypt( notificationsOlmData, encryptedPayload, + messageType, ); decryptedNotification = resultDecryptedNotification; @@ -495,12 +507,12 @@ async function decryptDesktopNotification( encryptedPayload: string, - messageType: string, + rawMessageType: string, staffCanSee: boolean, senderDeviceDescriptor: SenderDeviceDescriptor, ): Promise<{ +[string]: mixed }> { const { keyserverID, senderDeviceID } = senderDeviceDescriptor; - + const messageType = stringToOlmEncryptedMessageType(rawMessageType); let notifsAccountWithOlmData; try { [notifsAccountWithOlmData] = await Promise.all([ @@ -544,7 +556,7 @@ const { decryptedNotification, updatedOlmData } = await commonDecrypt<{ +[string]: mixed, - }>(notificationsOlmData, encryptedPayload); + }>(notificationsOlmData, encryptedPayload, olmEncryptedMessageTypes.TEXT); const updatedOlmDataPersistencePromise = persistNotifsAccountWithOlmData({ olmDataKey, @@ -634,6 +646,7 @@ async function commonDecrypt( notificationsOlmData: NotificationsOlmDataType, encryptedPayload: string, + type: OlmEncryptedMessageTypes, ): Promise<{ +decryptedNotification: T, +updatedOlmData: NotificationsOlmDataType, @@ -655,6 +668,7 @@ pendingSessionUpdate, picklingKey, encryptedPayload, + type, ); if (decryptionWithPendingSessionResult.decryptedNotification) { @@ -675,7 +689,7 @@ const { newUpdateCreationTimestamp, decryptedNotification: notifDecryptedWithMainSession, - } = decryptWithSession(mainSession, picklingKey, encryptedPayload); + } = decryptWithSession(mainSession, picklingKey, encryptedPayload, type); decryptedNotification = notifDecryptedWithMainSession; updatedOlmData = { @@ -693,22 +707,13 @@ senderDeviceID: string, notificationsOlmData: ?NotificationsOlmDataType, notificationAccount: PickledOLMAccount, - messageType: string, + messageType: OlmEncryptedMessageTypes, encryptedPayload: string, ): Promise<{ +decryptedNotification: T, +updatedOlmData?: NotificationsOlmDataType, +updatedNotifsAccount?: PickledOLMAccount, }> { - if ( - messageType !== olmEncryptedMessageTypes.PREKEY.toString() && - messageType !== olmEncryptedMessageTypes.TEXT.toString() - ) { - throw new Error( - `Received message of invalid type from device: ${senderDeviceID}`, - ); - } - let isSenderChainEmpty = true; let hasReceivedMessage = false; const sessionExists = !!notificationsOlmData; @@ -726,17 +731,20 @@ // regular message const isRegularMessage = - !!notificationsOlmData && - messageType === olmEncryptedMessageTypes.TEXT.toString(); + !!notificationsOlmData && messageType === olmEncryptedMessageTypes.TEXT; const isRegularPrekeyMessage = !!notificationsOlmData && - messageType === olmEncryptedMessageTypes.PREKEY.toString() && + messageType === olmEncryptedMessageTypes.PREKEY && isSenderChainEmpty && hasReceivedMessage; if (!!notificationsOlmData && (isRegularMessage || isRegularPrekeyMessage)) { - return await commonDecrypt(notificationsOlmData, encryptedPayload); + return await commonDecrypt( + notificationsOlmData, + encryptedPayload, + messageType, + ); } // At this point we either face race condition or session reset attempt or @@ -772,7 +780,7 @@ ); const decryptedNotification: T = JSON.parse( - session.decrypt(Number(messageType), encryptedPayload), + session.decrypt(messageType, encryptedPayload), ); // session reset attempt or session initialization - handled the same @@ -820,12 +828,13 @@ pickledSession: string, picklingKey: string, encryptedPayload: string, + type: OlmEncryptedMessageTypes, ): DecryptionResult { const session = new olm.Session(); session.unpickle(picklingKey, pickledSession); const decryptedNotification: T = JSON.parse( - session.decrypt(olmEncryptedMessageTypes.TEXT, encryptedPayload), + session.decrypt(type, encryptedPayload), ); const newPendingSessionUpdate = session.pickle(picklingKey); @@ -842,6 +851,7 @@ pendingSessionUpdate: string, picklingKey: string, encryptedPayload: string, + type: OlmEncryptedMessageTypes, ): DecryptionResult | { +error: string } { try { const { @@ -852,6 +862,7 @@ pendingSessionUpdate, picklingKey, encryptedPayload, + type, ); return { newPendingSessionUpdate,