diff --git a/lib/components/peer-olm-session-creator-provider.react.js b/lib/components/peer-olm-session-creator-provider.react.js index 7e1c09e6ae..41e1186f5b 100644 --- a/lib/components/peer-olm-session-creator-provider.react.js +++ b/lib/components/peer-olm-session-creator-provider.react.js @@ -45,6 +45,7 @@ function PeerOlmSessionCreatorProvider(props: Props): React.Node { const deadDevices = useSelector(getPeersDeadDeviceIDs); const refetchDeviceList = useGetAndUpdateDeviceListsForUsers(); + const auxUserInfos = useSelector(state => state.auxUserStore.auxUserInfos); const createOlmSessionsWithUserCallback = React.useCallback( async ( @@ -56,11 +57,20 @@ function PeerOlmSessionCreatorProvider(props: Props): React.Node { runningPromises.current[userID] = {}; } - const filteredDevices = devices.filter( - request => - !runningPromises.current[userID][request.deviceID] && - !deadDevices.has(request.deviceID), - ); + const filteredDevices = devices + .filter( + request => + !runningPromises.current[userID][request.deviceID] && + !deadDevices.has(request.deviceID), + ) + .map(request => ({ + ...request, + // `devicesPlatformDetails` is defined because otherwise, this device + // is going to be included in dead devices and filtered out, see + // `getPeersDeadDeviceIDs`. + platformDetails: + auxUserInfos[userID]?.devicesPlatformDetails?.[request.deviceID], + })); const promise = (async () => { const authMetadata = await getAuthMetadata(); @@ -105,10 +115,11 @@ function PeerOlmSessionCreatorProvider(props: Props): React.Node { }, [ deadDevices, + auxUserInfos, getAuthMetadata, identityClient, - olmDebugLog, sendMessageToDevice, + olmDebugLog, refetchDeviceList, ], ); diff --git a/lib/keyserver-conn/keyserver-auth.js b/lib/keyserver-conn/keyserver-auth.js index f5f0db1a3d..82e6497cd5 100644 --- a/lib/keyserver-conn/keyserver-auth.js +++ b/lib/keyserver-conn/keyserver-auth.js @@ -103,10 +103,18 @@ function useRawKeyserverAuth(keyserverID: string): RawKeyserverAuthFunc { keyserverKeys.identityKeysBlob.notificationIdentityPublicKeys, keyserverKeys.notifInitializationInfo, keyserverID, + // Assuming the keyserver is always running on the newest + // version, Olm compatibility is not required unlike for other + // clients that might not be updated yet. + false, ), olmAPI.contentOutboundSessionCreator( keyserverKeys.identityKeysBlob.primaryIdentityPublicKeys, keyserverKeys.contentInitializationInfo, + // Assuming the keyserver is always running on the newest + // version, Olm compatibility is not required unlike for other + // clients that might not be updated yet. + false, ), getAuthMetadata(), ]); diff --git a/lib/shared/crypto-utils.js b/lib/shared/crypto-utils.js index ba20e721ba..ed33919cc6 100644 --- a/lib/shared/crypto-utils.js +++ b/lib/shared/crypto-utils.js @@ -72,6 +72,10 @@ function useInitialNotificationsEncryptedMessage( notificationIdentityPublicKeys, notifInitializationInfo, keyserverID, + // Assuming the keyserver is always running on the newest + // version, Olm compatibility is not required unlike for other + // clients that might not be updated yet. + false, ); }, [ diff --git a/lib/types/crypto-types.js b/lib/types/crypto-types.js index ed732f0d17..a3943f6fd9 100644 --- a/lib/types/crypto-types.js +++ b/lib/types/crypto-types.js @@ -173,6 +173,7 @@ export type OlmAPI = { +contentOutboundSessionCreator: ( contentIdentityKeys: OLMIdentityKeys, contentInitializationInfo: OlmSessionInitializationInfo, + olmCompatibilityMode: boolean, ) => Promise, +isContentSessionInitialized: (deviceID: string) => Promise, +keyserverNotificationsSessionCreator: ( @@ -180,11 +181,13 @@ export type OlmAPI = { notificationsIdentityKeys: OLMIdentityKeys, notificationsInitializationInfo: OlmSessionInitializationInfo, keyserverID: string, + olmCompatibilityMode: boolean, ) => Promise, +notificationsOutboundSessionCreator: ( deviceID: string, notificationsIdentityKeys: OLMIdentityKeys, notificationsInitializationInfo: OlmSessionInitializationInfo, + olmCompatibilityMode: boolean, ) => Promise, +isDeviceNotificationsSessionInitialized: ( deviceID: string, diff --git a/lib/utils/crypto-utils.js b/lib/utils/crypto-utils.js index 2ff7ce9661..0df284271d 100644 --- a/lib/utils/crypto-utils.js +++ b/lib/utils/crypto-utils.js @@ -5,6 +5,7 @@ import { type TInterface } from 'tcomb'; import { getConfig } from './config.js'; import { getMessageForException } from './errors.js'; +import { olmSupportRequired } from './olm-support-required.js'; import { primaryIdentityPublicKeyRegex } from './siwe-utils.js'; import { tRegex, tShape } from './validation-utils.js'; import type { OlmDebugLog } from '../components/debug-logs-context.js'; @@ -16,7 +17,10 @@ import type { OutboundSessionCreationResult, SignedIdentityKeysBlob, } from '../types/crypto-types.js'; -import type { IdentityServiceClient } from '../types/identity-service-types'; +import type { + IdentityPlatformDetails, + IdentityServiceClient, +} from '../types/identity-service-types'; import { type OutboundSessionCreation, peerToPeerMessageTypes, @@ -77,10 +81,13 @@ async function createOlmSessionsWithOwnDevices( const recipientDeviceID = primaryIdentityPublicKeys.ed25519; try { + // This function is used for testing purposes only, available to staff + // users, so Olm support is hardcoded to false. const { sessionVersion, encryptedData } = await olmAPI.contentOutboundSessionCreator( primaryIdentityPublicKeys, keys.contentInitializationInfo, + false, ); const sessionCreationMessage: OutboundSessionCreation = { @@ -117,6 +124,10 @@ export type DeviceSessionCreationRequest = { +deviceID: string, +sessionCreationOptions?: SessionCreationOptions, }; +type DeviceSessionCreationRequestWithPlatformDetails = { + ...DeviceSessionCreationRequest, + platformDetails: ?IdentityPlatformDetails, +}; export type SessionCreationResult = { +deviceKeysMissing: boolean, }; @@ -125,7 +136,7 @@ async function createOlmSessionsWithUser( identityClient: IdentityServiceClient, sendMessage: (message: TunnelbrokerClientMessageToDevice) => Promise, userID: string, - devices: $ReadOnlyArray, + devices: $ReadOnlyArray, source: 'session_reset' | 'session_not_exists', olmDebugLog: (olmLog: OlmDebugLog) => mixed, ): Promise { @@ -147,6 +158,7 @@ async function createOlmSessionsWithUser( +deviceID: string, +hasContentSession: boolean, +hasNotifsSession: boolean, + +olmSupport: boolean, }> = await Promise.all( devices.map(request => (async () => { @@ -170,6 +182,7 @@ async function createOlmSessionsWithUser( deviceID: request.deviceID, hasContentSession, hasNotifsSession, + olmSupport: olmSupportRequired(request.platformDetails), }; })(), ), @@ -193,7 +206,8 @@ async function createOlmSessionsWithUser( success = false, sessionVersionResult = -1; try { - const { deviceID, hasContentSession, hasNotifsSession } = sessionRequest; + const { deviceID, hasContentSession, hasNotifsSession, olmSupport } = + sessionRequest; const deviceKeysResponse = keysResponse.find( keys => keys.deviceID === deviceID, ); @@ -215,6 +229,7 @@ async function createOlmSessionsWithUser( recipientDeviceID, notificationIdentityPublicKeys, keys.notifInitializationInfo, + olmSupport, ); success = true; return; @@ -227,6 +242,7 @@ async function createOlmSessionsWithUser( await olmAPI.contentOutboundSessionCreator( primaryIdentityPublicKeys, keys.contentInitializationInfo, + olmSupport, ); } else { resultDescription = 'creating content and notif session'; @@ -234,11 +250,13 @@ async function createOlmSessionsWithUser( await olmAPI.contentOutboundSessionCreator( primaryIdentityPublicKeys, keys.contentInitializationInfo, + olmSupport, ), olmAPI.notificationsOutboundSessionCreator( recipientDeviceID, notificationIdentityPublicKeys, keys.notifInitializationInfo, + olmSupport, ), ]); } diff --git a/lib/utils/olm-support-required.js b/lib/utils/olm-support-required.js new file mode 100644 index 0000000000..49b967bda9 --- /dev/null +++ b/lib/utils/olm-support-required.js @@ -0,0 +1,38 @@ +// @flow + +import { + hasMinCodeVersion, + NEXT_CODE_VERSION, +} from '../shared/version-utils.js'; +import type { IdentityPlatformDetails } from '../types/identity-service-types.js'; +import { + identityDeviceTypes, + identityDeviceTypeToPlatform, +} from '../types/identity-service-types.js'; + +function olmSupportRequired( + platformDetails: ?IdentityPlatformDetails, +): boolean { + if (!platformDetails) { + return true; + } + // Assuming the keyserver is always running on the newest + // version, Olm compatibility is not required unlike for other + // clients that might not be updated yet. + if (platformDetails.deviceType === identityDeviceTypes.KEYSERVER) { + return false; + } + const { deviceType, ...rest } = platformDetails; + + return !hasMinCodeVersion( + { + ...rest, + platform: identityDeviceTypeToPlatform[deviceType], + }, + { + native: NEXT_CODE_VERSION, + web: NEXT_CODE_VERSION, + }, + ); +} +export { olmSupportRequired }; diff --git a/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp b/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp index d7c45fe4c3..f15b5d0ecd 100644 --- a/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp +++ b/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp @@ -238,7 +238,8 @@ int CryptoModule::initializeOutboundForSendingSession( const std::string &idKeys, const std::string &preKeys, const std::string &preKeySignature, - const std::optional &oneTimeKey) { + const std::optional &oneTimeKey, + bool olmCompatibilityMode) { int newSessionVersion = 1; if (this->hasSessionFor(targetDeviceId)) { std::shared_ptr existingSession = @@ -256,7 +257,7 @@ int CryptoModule::initializeOutboundForSendingSession( preKeys, preKeySignature, oneTimeKey, - true); // olmCompatibilityMode = true + olmCompatibilityMode); newSession->setVersion(newSessionVersion); this->sessions.insert(make_pair(targetDeviceId, std::move(newSession))); diff --git a/native/cpp/CommonCpp/CryptoTools/CryptoModule.h b/native/cpp/CommonCpp/CryptoTools/CryptoModule.h index 00b6225e07..5ef87c8195 100644 --- a/native/cpp/CommonCpp/CryptoTools/CryptoModule.h +++ b/native/cpp/CommonCpp/CryptoTools/CryptoModule.h @@ -64,7 +64,8 @@ class CryptoModule { const std::string &idKeys, const std::string &preKeys, const std::string &preKeySignature, - const std::optional &oneTimeKey); + const std::optional &oneTimeKey, + bool olmCompatibilityMode); bool hasSessionFor(const std::string &targetDeviceId); std::shared_ptr getSessionByDeviceId(const std::string &deviceId); void removeSessionByDeviceId(const std::string &deviceId); diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp index 32c3fa82e5..67d0b013d8 100644 --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp @@ -1152,7 +1152,8 @@ jsi::Value CommCoreModule::initializeNotificationsSession( jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, - jsi::String keyserverID) { + jsi::String keyserverID, + bool olmCompatibilityMode) { auto identityKeysCpp{identityKeys.utf8(rt)}; auto prekeyCpp{prekey.utf8(rt)}; auto prekeySignatureCpp{prekeySignature.utf8(rt)}; @@ -1181,7 +1182,8 @@ jsi::Value CommCoreModule::initializeNotificationsSession( identityKeysCpp, prekeyCpp, prekeySignatureCpp, - oneTimeKeyCpp); + oneTimeKeyCpp, + olmCompatibilityMode); result = notifsCryptoModuleWithPicklingKey.value().first->encrypt( keyserverIDCpp, @@ -1526,7 +1528,8 @@ jsi::Value CommCoreModule::initializeContentOutboundSession( jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, - jsi::String deviceID) { + jsi::String deviceID, + bool olmCompatibilityMode) { auto identityKeysCpp{identityKeys.utf8(rt)}; auto prekeyCpp{prekey.utf8(rt)}; auto prekeySignatureCpp{prekeySignature.utf8(rt)}; @@ -1550,7 +1553,8 @@ jsi::Value CommCoreModule::initializeContentOutboundSession( identityKeysCpp, prekeyCpp, prekeySignatureCpp, - oneTimeKeyCpp); + oneTimeKeyCpp, + olmCompatibilityMode); const std::string initMessage = "{\"type\": \"init\"}"; initialEncryptedData = @@ -1667,7 +1671,8 @@ jsi::Value CommCoreModule::initializeNotificationsOutboundSession( jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, - jsi::String deviceID) { + jsi::String deviceID, + bool olmCompatibilityMode) { auto identityKeysCpp{identityKeys.utf8(rt)}; auto prekeyCpp{prekey.utf8(rt)}; auto prekeySignatureCpp{prekeySignature.utf8(rt)}; @@ -1695,7 +1700,8 @@ jsi::Value CommCoreModule::initializeNotificationsOutboundSession( identityKeysCpp, prekeyCpp, prekeySignatureCpp, - oneTimeKeyCpp); + oneTimeKeyCpp, + olmCompatibilityMode); result = notifsCryptoModuleWithPicklingKey.value().first->encrypt( deviceIDCpp, diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h index 5a503ace56..ef34821d8c 100644 --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h @@ -107,7 +107,8 @@ class CommCoreModule : public facebook::react::CommCoreModuleSchemaCxxSpecJSI { jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, - jsi::String keyserverID) override; + jsi::String keyserverID, + bool olmCompatibilityMode) override; virtual jsi::Value isNotificationsSessionInitialized(jsi::Runtime &rt) override; virtual jsi::Value isDeviceNotificationsSessionInitialized( @@ -133,7 +134,8 @@ class CommCoreModule : public facebook::react::CommCoreModuleSchemaCxxSpecJSI { jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, - jsi::String deviceID) override; + jsi::String deviceID, + bool olmCompatibilityMode) override; virtual jsi::Value initializeContentInboundSession( jsi::Runtime &rt, jsi::String identityKeys, @@ -149,7 +151,8 @@ class CommCoreModule : public facebook::react::CommCoreModuleSchemaCxxSpecJSI { jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, - jsi::String deviceID) override; + jsi::String deviceID, + bool olmCompatibilityMode) override; virtual jsi::Value encrypt(jsi::Runtime &rt, jsi::String message, jsi::String deviceID) override; virtual jsi::Value encryptNotification( diff --git a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp index ac0f7f2f52..d38716e0f6 100644 --- a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp +++ b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp @@ -55,7 +55,7 @@ static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_validateAndUploa return static_cast(&turboModule)->validateAndUploadPrekeys(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt)); } static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsSession(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - return static_cast(&turboModule)->initializeNotificationsSession(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].isNull() || args[3].isUndefined() ? std::nullopt : std::make_optional(args[3].asString(rt)), args[4].asString(rt)); + return static_cast(&turboModule)->initializeNotificationsSession(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].isNull() || args[3].isUndefined() ? std::nullopt : std::make_optional(args[3].asString(rt)), args[4].asString(rt), args[5].asBool()); } static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isNotificationsSessionInitialized(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->isNotificationsSessionInitialized(rt); @@ -82,7 +82,7 @@ static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getUnreadThickTh return static_cast(&turboModule)->getUnreadThickThreadIDsFromNotifsStorage(rt); } static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeContentOutboundSession(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - return static_cast(&turboModule)->initializeContentOutboundSession(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].isNull() || args[3].isUndefined() ? std::nullopt : std::make_optional(args[3].asString(rt)), args[4].asString(rt)); + return static_cast(&turboModule)->initializeContentOutboundSession(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].isNull() || args[3].isUndefined() ? std::nullopt : std::make_optional(args[3].asString(rt)), args[4].asString(rt), args[5].asBool()); } static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeContentInboundSession(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->initializeContentInboundSession(rt, args[0].asString(rt), args[1].asObject(rt), args[2].asString(rt), args[3].asNumber(), args[4].asBool()); @@ -91,7 +91,7 @@ static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isContentSession return static_cast(&turboModule)->isContentSessionInitialized(rt, args[0].asString(rt)); } static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsOutboundSession(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - return static_cast(&turboModule)->initializeNotificationsOutboundSession(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].isNull() || args[3].isUndefined() ? std::nullopt : std::make_optional(args[3].asString(rt)), args[4].asString(rt)); + return static_cast(&turboModule)->initializeNotificationsOutboundSession(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].isNull() || args[3].isUndefined() ? std::nullopt : std::make_optional(args[3].asString(rt)), args[4].asString(rt), args[5].asBool()); } static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_encrypt(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->encrypt(rt, args[0].asString(rt), args[1].asString(rt)); @@ -266,7 +266,7 @@ CommCoreModuleSchemaCxxSpecJSI::CommCoreModuleSchemaCxxSpecJSI(std::shared_ptr oneTimeKey, jsi::String keyserverID) = 0; + virtual jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, jsi::String keyserverID, bool olmCompatibilityMode) = 0; virtual jsi::Value isNotificationsSessionInitialized(jsi::Runtime &rt) = 0; virtual jsi::Value isDeviceNotificationsSessionInitialized(jsi::Runtime &rt, jsi::String deviceID) = 0; virtual jsi::Value isNotificationsSessionInitializedWithDevices(jsi::Runtime &rt, jsi::Array deviceIDs) = 0; @@ -42,10 +42,10 @@ class JSI_EXPORT CommCoreModuleSchemaCxxSpecJSI : public TurboModule { virtual jsi::Value getDataFromNotifStorage(jsi::Runtime &rt, jsi::Array ids) = 0; virtual jsi::Value updateUnreadThickThreadsInNotifsStorage(jsi::Runtime &rt, jsi::Array unreadThickThreadIDs) = 0; virtual jsi::Value getUnreadThickThreadIDsFromNotifsStorage(jsi::Runtime &rt) = 0; - virtual jsi::Value initializeContentOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, jsi::String deviceID) = 0; + virtual jsi::Value initializeContentOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, jsi::String deviceID, bool olmCompatibilityMode) = 0; virtual jsi::Value initializeContentInboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::Object encryptedContent, jsi::String deviceID, double sessionVersion, bool overwrite) = 0; virtual jsi::Value isContentSessionInitialized(jsi::Runtime &rt, jsi::String deviceID) = 0; - virtual jsi::Value initializeNotificationsOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, jsi::String deviceID) = 0; + virtual jsi::Value initializeNotificationsOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, jsi::String deviceID, bool olmCompatibilityMode) = 0; virtual jsi::Value encrypt(jsi::Runtime &rt, jsi::String message, jsi::String deviceID) = 0; virtual jsi::Value encryptNotification(jsi::Runtime &rt, jsi::String payload, jsi::String deviceID) = 0; virtual jsi::Value encryptAndPersist(jsi::Runtime &rt, jsi::String message, jsi::String deviceID, jsi::String messageID) = 0; @@ -222,13 +222,13 @@ class JSI_EXPORT CommCoreModuleSchemaCxxSpec : public TurboModule { return bridging::callFromJs( rt, &T::validateAndUploadPrekeys, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken)); } - jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, jsi::String keyserverID) override { + jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, jsi::String keyserverID, bool olmCompatibilityMode) override { static_assert( - bridging::getParameterCount(&T::initializeNotificationsSession) == 6, - "Expected initializeNotificationsSession(...) to have 6 parameters"); + bridging::getParameterCount(&T::initializeNotificationsSession) == 7, + "Expected initializeNotificationsSession(...) to have 7 parameters"); return bridging::callFromJs( - rt, &T::initializeNotificationsSession, jsInvoker_, instance_, std::move(identityKeys), std::move(prekey), std::move(prekeySignature), std::move(oneTimeKey), std::move(keyserverID)); + rt, &T::initializeNotificationsSession, jsInvoker_, instance_, std::move(identityKeys), std::move(prekey), std::move(prekeySignature), std::move(oneTimeKey), std::move(keyserverID), std::move(olmCompatibilityMode)); } jsi::Value isNotificationsSessionInitialized(jsi::Runtime &rt) override { static_assert( @@ -294,13 +294,13 @@ class JSI_EXPORT CommCoreModuleSchemaCxxSpec : public TurboModule { return bridging::callFromJs( rt, &T::getUnreadThickThreadIDsFromNotifsStorage, jsInvoker_, instance_); } - jsi::Value initializeContentOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, jsi::String deviceID) override { + jsi::Value initializeContentOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, jsi::String deviceID, bool olmCompatibilityMode) override { static_assert( - bridging::getParameterCount(&T::initializeContentOutboundSession) == 6, - "Expected initializeContentOutboundSession(...) to have 6 parameters"); + bridging::getParameterCount(&T::initializeContentOutboundSession) == 7, + "Expected initializeContentOutboundSession(...) to have 7 parameters"); return bridging::callFromJs( - rt, &T::initializeContentOutboundSession, jsInvoker_, instance_, std::move(identityKeys), std::move(prekey), std::move(prekeySignature), std::move(oneTimeKey), std::move(deviceID)); + rt, &T::initializeContentOutboundSession, jsInvoker_, instance_, std::move(identityKeys), std::move(prekey), std::move(prekeySignature), std::move(oneTimeKey), std::move(deviceID), std::move(olmCompatibilityMode)); } jsi::Value initializeContentInboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::Object encryptedContent, jsi::String deviceID, double sessionVersion, bool overwrite) override { static_assert( @@ -318,13 +318,13 @@ class JSI_EXPORT CommCoreModuleSchemaCxxSpec : public TurboModule { return bridging::callFromJs( rt, &T::isContentSessionInitialized, jsInvoker_, instance_, std::move(deviceID)); } - jsi::Value initializeNotificationsOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, jsi::String deviceID) override { + jsi::Value initializeNotificationsOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, std::optional oneTimeKey, jsi::String deviceID, bool olmCompatibilityMode) override { static_assert( - bridging::getParameterCount(&T::initializeNotificationsOutboundSession) == 6, - "Expected initializeNotificationsOutboundSession(...) to have 6 parameters"); + bridging::getParameterCount(&T::initializeNotificationsOutboundSession) == 7, + "Expected initializeNotificationsOutboundSession(...) to have 7 parameters"); return bridging::callFromJs( - rt, &T::initializeNotificationsOutboundSession, jsInvoker_, instance_, std::move(identityKeys), std::move(prekey), std::move(prekeySignature), std::move(oneTimeKey), std::move(deviceID)); + rt, &T::initializeNotificationsOutboundSession, jsInvoker_, instance_, std::move(identityKeys), std::move(prekey), std::move(prekeySignature), std::move(oneTimeKey), std::move(deviceID), std::move(olmCompatibilityMode)); } jsi::Value encrypt(jsi::Runtime &rt, jsi::String message, jsi::String deviceID) override { static_assert( diff --git a/native/crypto/olm-api.js b/native/crypto/olm-api.js index 8ef141b406..6de6e2652c 100644 --- a/native/crypto/olm-api.js +++ b/native/crypto/olm-api.js @@ -58,6 +58,7 @@ const olmAPI: OlmAPI = { async contentOutboundSessionCreator( contentIdentityKeys: OLMIdentityKeys, contentInitializationInfo: OlmSessionInitializationInfo, + olmCompatibilityMode: boolean, ): Promise { const { prekey, prekeySignature, oneTimeKey } = contentInitializationInfo; const identityKeys = JSON.stringify({ @@ -71,6 +72,7 @@ const olmAPI: OlmAPI = { prekeySignature, oneTimeKey, contentIdentityKeys.ed25519, + olmCompatibilityMode, ); }, keyserverNotificationsSessionCreator( @@ -78,6 +80,7 @@ const olmAPI: OlmAPI = { notificationsIdentityKeys: OLMIdentityKeys, notificationsInitializationInfo: OlmSessionInitializationInfo, keyserverID: string, + olmCompatibilityMode: boolean, ): Promise { const { prekey, prekeySignature, oneTimeKey } = notificationsInitializationInfo; @@ -87,12 +90,14 @@ const olmAPI: OlmAPI = { prekeySignature, oneTimeKey, keyserverID, + olmCompatibilityMode, ); }, async notificationsOutboundSessionCreator( deviceID: string, notificationsIdentityKeys: OLMIdentityKeys, notificationsInitializationInfo: OlmSessionInitializationInfo, + olmCompatibilityMode: boolean, ): Promise { const { prekey, prekeySignature, oneTimeKey } = notificationsInitializationInfo; @@ -106,6 +111,7 @@ const olmAPI: OlmAPI = { prekeySignature, oneTimeKey, deviceID, + olmCompatibilityMode, ); }, isDeviceNotificationsSessionInitialized: diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js index 8769ab3845..6256194d81 100644 --- a/native/schema/CommCoreModuleSchema.js +++ b/native/schema/CommCoreModuleSchema.js @@ -73,6 +73,7 @@ interface Spec extends TurboModule { prekeySignature: string, oneTimeKey: ?string, keyserverID: string, + olmCompatibilityMode: boolean, ) => Promise; +isNotificationsSessionInitialized: () => Promise; +isDeviceNotificationsSessionInitialized: ( @@ -102,6 +103,7 @@ interface Spec extends TurboModule { prekeySignature: string, oneTimeKey: ?string, deviceID: string, + olmCompatibilityMode: boolean, ) => Promise; +initializeContentInboundSession: ( identityKeys: string, @@ -117,6 +119,7 @@ interface Spec extends TurboModule { prekeySignature: string, oneTimeKey: ?string, deviceID: string, + olmCompatibilityMode: boolean, ) => Promise; +encrypt: (message: string, deviceID: string) => Promise; +encryptNotification: ( diff --git a/web/shared-worker/worker/worker-crypto.js b/web/shared-worker/worker/worker-crypto.js index 0ef9f1ebeb..c72b031663 100644 --- a/web/shared-worker/worker/worker-crypto.js +++ b/web/shared-worker/worker/worker-crypto.js @@ -185,6 +185,7 @@ async function createAndPersistNotificationsOutboundSession( notificationsInitializationInfo: OlmSessionInitializationInfo, dataPersistenceKey: string, dataEncryptionKeyDBLabel: string, + olmCompatibilityMode: boolean, ): Promise { if (!cryptoStore) { throw new Error('Crypto account not initialized'); @@ -208,7 +209,7 @@ async function createAndPersistNotificationsOutboundSession( notificationsInitializationInfo.oneTimeKey || '', notificationsPrekey, notificationsInitializationInfo.prekeySignature, - true, // olmCompatibilityMode + olmCompatibilityMode, ); const encryptedMessage = session.encrypt( @@ -841,6 +842,7 @@ const olmAPI: OlmAPI = { async contentOutboundSessionCreator( contentIdentityKeys: OLMIdentityKeys, contentInitializationInfo: OlmSessionInitializationInfo, + olmCompatibilityMode: boolean, ): Promise { if (!cryptoStore) { throw new Error('Crypto account not initialized'); @@ -856,7 +858,7 @@ const olmAPI: OlmAPI = { contentInitializationInfo.oneTimeKey || '', contentInitializationInfo.prekey, contentInitializationInfo.prekeySignature, - true, // olmCompatibilityMode + olmCompatibilityMode, ); const olmMessage = session.encrypt( @@ -896,6 +898,7 @@ const olmAPI: OlmAPI = { deviceID: string, notificationsIdentityKeys: OLMIdentityKeys, notificationsInitializationInfo: OlmSessionInitializationInfo, + olmCompatibilityMode: boolean, ): Promise { const dataPersistenceKey = getOlmDataKeyForDeviceID(deviceID); const dataEncryptionKeyDBLabel = @@ -906,6 +909,7 @@ const olmAPI: OlmAPI = { notificationsInitializationInfo, dataPersistenceKey, dataEncryptionKeyDBLabel, + olmCompatibilityMode, ); }, async isDeviceNotificationsSessionInitialized(deviceID: string) { @@ -944,6 +948,7 @@ const olmAPI: OlmAPI = { notificationsIdentityKeys: OLMIdentityKeys, notificationsInitializationInfo: OlmSessionInitializationInfo, keyserverID: string, + olmCompatibilityMode: boolean, ): Promise { const platformDetails = getPlatformDetails(); if (!platformDetails) { @@ -958,6 +963,7 @@ const olmAPI: OlmAPI = { notificationsInitializationInfo, notifsOlmDataContentKey, notifsOlmDataEncryptionKeyDBLabel, + olmCompatibilityMode, ); return message;