diff --git a/native/android/app/src/cpp/NotificationsCryptoModuleJNIHelper.cpp b/native/android/app/src/cpp/NotificationsCryptoModuleJNIHelper.cpp --- a/native/android/app/src/cpp/NotificationsCryptoModuleJNIHelper.cpp +++ b/native/android/app/src/cpp/NotificationsCryptoModuleJNIHelper.cpp @@ -9,11 +9,11 @@ std::string NotificationsCryptoModuleJNIHelper::decrypt( facebook::jni::alias_ref jThis, + std::string keyserverID, std::string data, - int messageType, - std::string callingProcessName) { + int messageType) { std::string decryptedData = - NotificationsCryptoModule::decrypt(data, messageType, callingProcessName); + NotificationsCryptoModule::decrypt(keyserverID, data, messageType); return decryptedData; } diff --git a/native/android/app/src/main/java/app/comm/android/fbjni/NotificationsCryptoModule.java b/native/android/app/src/main/java/app/comm/android/fbjni/NotificationsCryptoModule.java --- a/native/android/app/src/main/java/app/comm/android/fbjni/NotificationsCryptoModule.java +++ b/native/android/app/src/main/java/app/comm/android/fbjni/NotificationsCryptoModule.java @@ -3,5 +3,5 @@ public class NotificationsCryptoModule { public static native int olmEncryptedTypeMessage(); public static native String - decrypt(String data, int messageType, String callingProcessName); + decrypt(String keyserverID, String data, int messageType); } diff --git a/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java b/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java --- a/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java +++ b/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java @@ -89,9 +89,14 @@ @Override public void onMessageReceived(RemoteMessage message) { + String senderKeyserverID = message.getData().get(KEYSERVER_ID_KEY); + if (senderKeyserverID == null) { + senderKeyserverID = ASHOAT_KEYSERVER_ID; + } + if (message.getData().get(ENCRYPTED_PAYLOAD_KEY) != null) { try { - message = this.decryptRemoteMessage(message); + message = this.decryptRemoteMessage(message, senderKeyserverID); } catch (JSONException e) { Log.w("COMM", "Malformed notification JSON payload.", e); return; @@ -375,14 +380,15 @@ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); } - private RemoteMessage decryptRemoteMessage(RemoteMessage message) + private RemoteMessage + decryptRemoteMessage(RemoteMessage message, String senderKeyserverID) throws JSONException, IllegalStateException { String encryptedSerializedPayload = message.getData().get(ENCRYPTED_PAYLOAD_KEY); String decryptedSerializedPayload = NotificationsCryptoModule.decrypt( + senderKeyserverID, encryptedSerializedPayload, - NotificationsCryptoModule.olmEncryptedTypeMessage(), - "CommNotificationsHandler"); + NotificationsCryptoModule.olmEncryptedTypeMessage()); JSONObject decryptedPayload = new JSONObject(decryptedSerializedPayload); diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp --- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp @@ -11,6 +11,8 @@ #include #ifndef EMSCRIPTEN +#include "../CryptoTools/CryptoModule.h" +#include "../Notifications/BackgroundDataStorage/NotificationsCryptoModule.h" #include "CommSecureStore.h" #include "PlatformSpecificTools.h" #include "StaffUtils.h" @@ -513,6 +515,41 @@ return create_table(db, query, "communities"); } +bool migrate_notifs_crypto_account(sqlite3 *db) { +#ifndef EMSCRIPTEN + std::string legacyCryptoAccountDataKey = "cryptoAccountDataKey"; + folly::Optional secretKey = + CommSecureStore::get(legacyCryptoAccountDataKey); + + if (!secretKey.hasValue()) { + return false; + } + + std::unique_ptr legacyNotifsAccount = + NotificationsCryptoModule::migrateLegacyNotificationsCryptoModule(); + + if (!legacyNotifsAccount) { + return true; + } + + std::string insert_notifs_account_query = + "REPLACE INTO olm_persist_account (id, account_data) " + "VALUES (?, ?);"; + + crypto::Persist legacyNotifsPersist = + legacyNotifsAccount->storeAsB64(secretKey.value()); + std::string notifsAccountData = std::string( + legacyNotifsPersist.account.begin(), legacyNotifsPersist.account.end()); + + replaceEntity( + db, insert_notifs_account_query, {NOTIFS_ACCOUNT_ID, notifsAccountData}); + + return true; +#else + return true; +#endif +} + bool create_schema(sqlite3 *db) { char *error; sqlite3_exec( @@ -846,7 +883,8 @@ {32, {create_users_table, true}}, {33, {create_keyservers_table, true}}, {34, {enable_rollback_journal_mode, false}}, - {35, {create_communities_table, true}}}}; + {35, {create_communities_table, true}}, + {36, {migrate_notifs_crypto_account, true}}}}; enum class MigrationResult { SUCCESS, FAILURE, NOT_APPLIED }; diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp @@ -841,21 +841,35 @@ auto prekeyCpp{prekey.utf8(rt)}; auto prekeySignatureCpp{prekeySignature.utf8(rt)}; auto oneTimeKeyCpp{oneTimeKey.utf8(rt)}; + auto keyserverIDCpp{keyserverID.utf8(rt)}; return createPromiseAsJSIValue( rt, [=](jsi::Runtime &innerRt, std::shared_ptr promise) { taskType job = [=, &innerRt]() { std::string error; crypto::EncryptedData result; try { - // Introduced temporarily to make this diff non-breaking change - NotificationsCryptoModule::initializeNotificationsCryptoAccount( - "Comm"); - result = NotificationsCryptoModule::initializeNotificationsSession( - identityKeysCpp, - prekeyCpp, - prekeySignatureCpp, - oneTimeKeyCpp, - "Comm"); + this->notifsCryptoModule->initializeOutboundForSendingSession( + keyserverIDCpp, + std::vector( + identityKeysCpp.begin(), identityKeysCpp.end()), + std::vector(prekeyCpp.begin(), prekeyCpp.end()), + std::vector( + prekeySignatureCpp.begin(), prekeySignatureCpp.end()), + std::vector( + oneTimeKeyCpp.begin(), oneTimeKeyCpp.end())); + + result = this->notifsCryptoModule->encrypt( + keyserverIDCpp, + NotificationsCryptoModule::initialEncryptedMessageContent); + + std::shared_ptr keyserverNotificationsSession = + this->notifsCryptoModule->getSessionByDeviceId(keyserverIDCpp); + + NotificationsCryptoModule::persistNotificationsSession( + keyserverIDCpp, keyserverNotificationsSession); + + this->notifsCryptoModule->removeSessionByDeviceId(keyserverIDCpp); + this->persistCryptoModules(false, true); } catch (const std::exception &e) { error = e.what(); } diff --git a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h --- a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h +++ b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h @@ -6,59 +6,58 @@ namespace comm { class NotificationsCryptoModule { - const static std::string secureStoreNotificationsAccountDataKey; const static std::string notificationsCryptoAccountID; - const static std::string keyserverHostedNotificationsID; - const static std::string initialEncryptedMessageContent; - static std::string getPicklingKey(); - static void serializeAndFlushCryptoModule( - std::unique_ptr cryptoModule, - const std::string &path, - const std::string &picklingKey, - const std::string &callingProcessName); + static std::string getPicklingKey(bool generateIfNotExists); static std::unique_ptr deserializeCryptoModule( const std::string &path, const std::string &picklingKey); - static void callCryptoModule( - std::function &cryptoModule)> caller, - const std::string &callingProcessName); + static std::string + getKeyserverNotificationsSessionKey(const std::string &keyserverID); + static void persistNotificationsSessionInternal( + const std::string &keyserverID, + const std::string &picklingKey, + std::shared_ptr session); + static std::unique_ptr fetchNotificationsSession( + const std::string &keyserverID, + const std::string &picklingKey); public: + const static std::string initialEncryptedMessageContent; const static int olmEncryptedTypeMessage; - static void - initializeNotificationsCryptoAccount(const std::string &callingProcessName); + + static std::unique_ptr + migrateLegacyNotificationsCryptoModule(); static void clearSensitiveData(); - static crypto::EncryptedData initializeNotificationsSession( - const std::string &identityKeys, - const std::string &prekey, - const std::string &prekeySignature, - const std::string &oneTimeKeys, - const std::string &callingProcessName); - static bool - isNotificationsSessionInitialized(const std::string &callingProcessName); + static void persistNotificationsSession( + const std::string &keyserverID, + std::shared_ptr keyserverNotificationsSession); + static bool isNotificationsSessionInitialized(const std::string &keyserverID); static std::string decrypt( + const std::string &keyserverID, const std::string &data, - const size_t messageType, - const std::string &callingProcessName); + const size_t messageType); class StatefulDecryptResult { StatefulDecryptResult( - std::unique_ptr cryptoModule, + std::unique_ptr session, + std::string keyserverID, std::string decryptedData); - std::unique_ptr cryptoModuleState; + std::unique_ptr sessionState; + std::string keyserverID; std::string decryptedData; friend NotificationsCryptoModule; public: std::string getDecryptedData(); + std::string getKeyserverID(); }; - static std::unique_ptr - statefulDecrypt(const std::string &data, const size_t messageType); - static void flushState( - std::unique_ptr statefulDecryptResult, - const std::string &callingProcessName); + static std::unique_ptr statefulDecrypt( + const std::string &keyserverID, + const std::string &data, + const size_t messageType); + static void + flushState(std::unique_ptr statefulDecryptResult); }; } // namespace comm diff --git a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp --- a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp +++ b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp @@ -1,6 +1,7 @@ #include "NotificationsCryptoModule.h" #include "../../CryptoTools/Persist.h" #include "../../CryptoTools/Tools.h" +#include "../../Tools/CommMMKV.h" #include "../../Tools/CommSecureStore.h" #include "../../Tools/PlatformSpecificTools.h" @@ -15,17 +16,14 @@ namespace comm { -const std::string - NotificationsCryptoModule::secureStoreNotificationsAccountDataKey = - "notificationsCryptoAccountDataKey"; const std::string NotificationsCryptoModule::notificationsCryptoAccountID = "notificationsCryptoAccountDataID"; -const std::string NotificationsCryptoModule::keyserverHostedNotificationsID = - "keyserverHostedNotificationsID"; const std::string NotificationsCryptoModule::initialEncryptedMessageContent = "{\"type\": \"init\"}"; const int NotificationsCryptoModule::olmEncryptedTypeMessage = 1; -const int temporaryFilePathRandomSuffixLength = 32; + +// Introduced temporarily +const std::string ashoatKeyserverID = "256"; std::unique_ptr NotificationsCryptoModule::deserializeCryptoModule( @@ -74,156 +72,92 @@ crypto::Persist({account, sessions})); } -void NotificationsCryptoModule::serializeAndFlushCryptoModule( - std::unique_ptr cryptoModule, - const std::string &path, - const std::string &picklingKey, - const std::string &callingProcessName) { - crypto::Persist persist = cryptoModule->storeAsB64(picklingKey); +std::string +NotificationsCryptoModule::getPicklingKey(bool generateIfNotExists) { + static std::string notifsPicklingKeyID = "NOTIFS.PICKLING_KEY"; + std::optional picklingKey = + CommMMKV::getString(notifsPicklingKeyID); - folly::dynamic sessions = folly::dynamic::object; - for (auto &sessionKeyValuePair : persist.sessions) { - std::string targetUserID = sessionKeyValuePair.first; - crypto::OlmBuffer sessionData = sessionKeyValuePair.second; - sessions[targetUserID] = - std::string(sessionData.begin(), sessionData.end()); + if (picklingKey.has_value()) { + return picklingKey.value(); } - std::string account = - std::string(persist.account.begin(), persist.account.end()); - folly::dynamic persistJSON = - folly::dynamic::object("account", account)("sessions", sessions); - std::string pickledPersist = folly::toJson(persistJSON); - - std::string temporaryFilePathRandomSuffix = - crypto::Tools::generateRandomHexString( - temporaryFilePathRandomSuffixLength); - std::string temporaryPath = - path + callingProcessName + temporaryFilePathRandomSuffix; - - mode_t readWritePermissionsMode = 0666; - int temporaryFD = - open(temporaryPath.c_str(), O_CREAT | O_WRONLY, readWritePermissionsMode); - if (temporaryFD == -1) { - throw std::runtime_error( - "Failed to create temporary file. Unable to atomically update " - "notifications crypto account. Details: " + - std::string(strerror(errno))); - } - ssize_t bytesWritten = - write(temporaryFD, pickledPersist.c_str(), pickledPersist.length()); - if (bytesWritten == -1 || bytesWritten != pickledPersist.length()) { - remove(temporaryPath.c_str()); - throw std::runtime_error( - "Failed to write all data to temporary file. Unable to atomically " - "update notifications crypto account. Details: " + - std::string(strerror(errno))); - } - if (fsync(temporaryFD) == -1) { - remove(temporaryPath.c_str()); + if (!generateIfNotExists) { throw std::runtime_error( - "Failed to synchronize temporary file data with hardware storage. " - "Unable to atomically update notifications crypto account. Details: " + - std::string(strerror(errno))); - }; - close(temporaryFD); - if (rename(temporaryPath.c_str(), path.c_str()) == -1) { - remove(temporaryPath.c_str()); - throw std::runtime_error( - "Failed to replace temporary file content with notifications crypto " - "account. Unable to atomically update notifications crypto account. " - "Details: " + - std::string(strerror(errno))); + "Attempt to retrieve notifications sessions before it was " + "correctly initialized."); } - remove(temporaryPath.c_str()); -} -std::string NotificationsCryptoModule::getPicklingKey() { - folly::Optional picklingKey = CommSecureStore::get( - NotificationsCryptoModule::secureStoreNotificationsAccountDataKey); - if (!picklingKey.hasValue()) { - throw std::runtime_error( - "Attempt to retrieve notifications crypto account before it was " - "correctly initialized."); + std::string newPicklingKey = crypto::Tools::generateRandomString(64); + bool picklingKeySet = + CommMMKV::setString(notifsPicklingKeyID, newPicklingKey); + + if (!picklingKeySet) { + throw std::runtime_error("Failed to set notifications pickling key."); } - return picklingKey.value(); + + return newPicklingKey; } -void NotificationsCryptoModule::callCryptoModule( - std::function< - void(const std::unique_ptr &cryptoModule)> caller, - const std::string &callingProcessName) { - const std::string picklingKey = NotificationsCryptoModule::getPicklingKey(); - const std::string path = - PlatformSpecificTools::getNotificationsCryptoAccountPath(); - std::unique_ptr cryptoModule = - NotificationsCryptoModule::deserializeCryptoModule(path, picklingKey); - caller(cryptoModule); - NotificationsCryptoModule::serializeAndFlushCryptoModule( - std::move(cryptoModule), path, picklingKey, callingProcessName); +std::string NotificationsCryptoModule::getKeyserverNotificationsSessionKey( + const std::string &keyserverID) { + return "KEYSERVER." + keyserverID + ".NOTIFS_SESSION"; } -void NotificationsCryptoModule::initializeNotificationsCryptoAccount( - const std::string &callingProcessName) { +std::unique_ptr +NotificationsCryptoModule::migrateLegacyNotificationsCryptoModule() { const std::string notificationsCryptoAccountPath = PlatformSpecificTools::getNotificationsCryptoAccountPath(); std::ifstream notificationCryptoAccountCheck(notificationsCryptoAccountPath); - if (notificationCryptoAccountCheck.good()) { - // Implemented in CommmCoreModule semantics regarding public olm account - // initialization is idempotent. We should follow the same approach when it - // comes to notifications + + if (!notificationCryptoAccountCheck.good()) { notificationCryptoAccountCheck.close(); - return; + return nullptr; } - // There is no reason to check if the key is already present since if we are - // in this place in the code we are about to create new account - std::string picklingKey = crypto::Tools::generateRandomString(64); - CommSecureStore::set( - NotificationsCryptoModule::secureStoreNotificationsAccountDataKey, - picklingKey); - - std::unique_ptr cryptoModule = - std::make_unique( - NotificationsCryptoModule::notificationsCryptoAccountID); - NotificationsCryptoModule::serializeAndFlushCryptoModule( - std::move(cryptoModule), - notificationsCryptoAccountPath, - picklingKey, - callingProcessName); -} + notificationCryptoAccountCheck.close(); -crypto::EncryptedData NotificationsCryptoModule::initializeNotificationsSession( - const std::string &identityKeys, - const std::string &prekey, - const std::string &prekeySignature, - const std::string &oneTimeKey, - const std::string &callingProcessName) { - crypto::EncryptedData initialEncryptedMessage; - auto caller = [&](const std::unique_ptr &cryptoModule) { - cryptoModule->initializeOutboundForSendingSession( - NotificationsCryptoModule::keyserverHostedNotificationsID, - std::vector(identityKeys.begin(), identityKeys.end()), - std::vector(prekey.begin(), prekey.end()), - std::vector(prekeySignature.begin(), prekeySignature.end()), - std::vector(oneTimeKey.begin(), oneTimeKey.end())); - initialEncryptedMessage = cryptoModule->encrypt( - NotificationsCryptoModule::keyserverHostedNotificationsID, - NotificationsCryptoModule::initialEncryptedMessageContent); - }; - NotificationsCryptoModule::callCryptoModule(caller, callingProcessName); - return initialEncryptedMessage; -} + std::string legacySecureStoreNotifsAccountKey = + "notificationsCryptoAccountDataKey"; + folly::Optional legacyPicklingKey = + CommSecureStore::get(legacySecureStoreNotifsAccountKey); + if (!legacyPicklingKey.hasValue()) { + throw std::runtime_error( + "Attempt to migrate legacy notifications account but pickling key " + "missing."); + } -bool NotificationsCryptoModule::isNotificationsSessionInitialized( - const std::string &callingProcessName) { - bool sessionInitialized; - auto caller = [&sessionInitialized]( - const std::unique_ptr &cryptoModule) { - sessionInitialized = cryptoModule->hasSessionFor( - NotificationsCryptoModule::keyserverHostedNotificationsID); - }; - NotificationsCryptoModule::callCryptoModule(caller, callingProcessName); - return sessionInitialized; + std::unique_ptr legacyCryptoModule = + NotificationsCryptoModule::deserializeCryptoModule( + notificationsCryptoAccountPath, legacyPicklingKey.value()); + + std::string newPicklingKey = NotificationsCryptoModule::getPicklingKey(true); + crypto::Persist persist = legacyCryptoModule->storeAsB64(newPicklingKey); + + std::string legacyNotificationsSessionID = "keyserverHostedNotificationsID"; + if (persist.sessions.find(legacyNotificationsSessionID) == + persist.sessions.end()) { + return legacyCryptoModule; + } + + crypto::OlmBuffer autoritativeKeyserverSession = + persist.sessions.at(legacyNotificationsSessionID); + + std::string autoritativeKeyserverSessionKey = + NotificationsCryptoModule::getKeyserverNotificationsSessionKey( + ashoatKeyserverID); + + bool storedSession = CommMMKV::setString( + autoritativeKeyserverSessionKey, + std::string( + autoritativeKeyserverSession.begin(), + autoritativeKeyserverSession.end())); + + if (!storedSession) { + throw std::runtime_error( + "Failed to migrate autoritative keyserver session to MMKV."); + } + + return legacyCryptoModule; } void NotificationsCryptoModule::clearSensitiveData() { @@ -236,26 +170,88 @@ } } +void NotificationsCryptoModule::persistNotificationsSessionInternal( + const std::string &keyserverID, + const std::string &picklingKey, + std::shared_ptr session) { + auto sessionBytes = session->storeAsB64(picklingKey); + std::string serializedSession = + std::string(sessionBytes.begin(), sessionBytes.end()); + + std::string keyserverNotificationsSessionKey = + NotificationsCryptoModule::getKeyserverNotificationsSessionKey( + keyserverID); + + bool sessionStored = + CommMMKV::setString(keyserverNotificationsSessionKey, serializedSession); + + if (!sessionStored) { + throw std::runtime_error( + "Failed to persist to MMKV notifications session for keyserver: " + + keyserverID); + } +} + +std::unique_ptr +NotificationsCryptoModule::fetchNotificationsSession( + const std::string &keyserverID, + const std::string &picklingKey) { + std::string keyserverNotificationsSessionKey = + NotificationsCryptoModule::getKeyserverNotificationsSessionKey( + keyserverID); + std::optional serializedSession = + CommMMKV::getString(keyserverNotificationsSessionKey); + + if (!serializedSession.has_value()) { + throw std::runtime_error( + "Missing notifications session for keyserver: " + keyserverID); + } + + crypto::OlmBuffer sessionBytes = crypto::OlmBuffer{ + serializedSession.value().begin(), serializedSession.value().end()}; + std::unique_ptr session = + crypto::Session::restoreFromB64(picklingKey, sessionBytes); + return session; +} + +void NotificationsCryptoModule::persistNotificationsSession( + const std::string &keyserverID, + std::shared_ptr keyserverNotificationsSession) { + std::string picklingKey = NotificationsCryptoModule::getPicklingKey(true); + NotificationsCryptoModule::persistNotificationsSessionInternal( + keyserverID, picklingKey, keyserverNotificationsSession); +} + +bool NotificationsCryptoModule::isNotificationsSessionInitialized( + const std::string &keyserverID) { + std::string keyserverNotificationsSessionKey = + "KEYSERVER." + keyserverID + ".NOTIFS_SESSION"; + return CommMMKV::getString(keyserverNotificationsSessionKey).has_value(); +} + std::string NotificationsCryptoModule::decrypt( + const std::string &keyserverID, const std::string &data, - const size_t messageType, - const std::string &callingProcessName) { - std::string decryptedData; - auto caller = [&](const std::unique_ptr &cryptoModule) { - crypto::EncryptedData encryptedData{ - std::vector(data.begin(), data.end()), messageType}; - decryptedData = cryptoModule->decrypt( - NotificationsCryptoModule::keyserverHostedNotificationsID, - encryptedData); - }; - NotificationsCryptoModule::callCryptoModule(caller, callingProcessName); + const size_t messageType) { + std::string picklingKey = NotificationsCryptoModule::getPicklingKey(false); + std::unique_ptr session = + NotificationsCryptoModule::fetchNotificationsSession( + keyserverID, picklingKey); + crypto::EncryptedData encryptedData{ + std::vector(data.begin(), data.end()), messageType}; + std::string decryptedData = session->decrypt(encryptedData); + NotificationsCryptoModule::persistNotificationsSessionInternal( + keyserverID, picklingKey, std::move(session)); return decryptedData; } NotificationsCryptoModule::StatefulDecryptResult::StatefulDecryptResult( - std::unique_ptr cryptoModule, + std::unique_ptr session, + std::string keyserverID, std::string decryptedData) - : cryptoModuleState(std::move(cryptoModule)), decryptedData(decryptedData) { + : sessionState(std::move(session)), + keyserverID(keyserverID), + decryptedData(decryptedData) { } std::string @@ -263,37 +259,37 @@ return this->decryptedData; } +std::string NotificationsCryptoModule::StatefulDecryptResult::getKeyserverID() { + return this->keyserverID; +} + std::unique_ptr NotificationsCryptoModule::statefulDecrypt( + const std::string &keyserverID, const std::string &data, const size_t messageType) { - std::string path = PlatformSpecificTools::getNotificationsCryptoAccountPath(); - std::string picklingKey = NotificationsCryptoModule::getPicklingKey(); + std::string picklingKey = NotificationsCryptoModule::getPicklingKey(false); + + std::unique_ptr session = + NotificationsCryptoModule::fetchNotificationsSession( + keyserverID, picklingKey); - std::unique_ptr cryptoModule = - NotificationsCryptoModule::deserializeCryptoModule(path, picklingKey); crypto::EncryptedData encryptedData{ std::vector(data.begin(), data.end()), messageType}; - std::string decryptedData = cryptoModule->decrypt( - NotificationsCryptoModule::keyserverHostedNotificationsID, encryptedData); - StatefulDecryptResult statefulDecryptResult( - std::move(cryptoModule), decryptedData); + std::string decryptedData = session->decrypt(encryptedData); + StatefulDecryptResult statefulDecryptResult( + std::move(session), keyserverID, decryptedData); return std::make_unique( std::move(statefulDecryptResult)); } void NotificationsCryptoModule::flushState( - std::unique_ptr statefulDecryptResult, - const std::string &callingProcessName) { - - std::string path = PlatformSpecificTools::getNotificationsCryptoAccountPath(); - std::string picklingKey = NotificationsCryptoModule::getPicklingKey(); - - NotificationsCryptoModule::serializeAndFlushCryptoModule( - std::move(statefulDecryptResult->cryptoModuleState), - path, + std::unique_ptr statefulDecryptResult) { + std::string picklingKey = NotificationsCryptoModule::getPicklingKey(false); + NotificationsCryptoModule::persistNotificationsSessionInternal( + statefulDecryptResult->getKeyserverID(), picklingKey, - callingProcessName); + std::move(statefulDecryptResult->sessionState)); } } // namespace comm diff --git a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModuleJNIHelper.h b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModuleJNIHelper.h --- a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModuleJNIHelper.h +++ b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModuleJNIHelper.h @@ -14,10 +14,10 @@ static std::string decrypt( facebook::jni::alias_ref jThis, + std::string keyserverID, std::string data, - int messageType, - std::string callingProcessName); + int messageType); static void registerNatives(); }; } // namespace comm \ No newline at end of file diff --git a/native/ios/NotificationService/NotificationService.mm b/native/ios/NotificationService/NotificationService.mm --- a/native/ios/NotificationService/NotificationService.mm +++ b/native/ios/NotificationService/NotificationService.mm @@ -261,7 +261,7 @@ if (decryptionExecuted) { comm::NotificationsCryptoModule::flushState( - std::move(statefulDecryptResultPtr), callingProcessName); + std::move(statefulDecryptResultPtr)); } } @@ -534,9 +534,15 @@ decryptContentInPlace:(UNMutableNotificationContent *)content { std::string encryptedData = std::string([content.userInfo[encryptedPayloadKey] UTF8String]); - + std::string senderKeyserverID = ashoatKeyserverID; + if (content.userInfo[keyserverIDKey]) { + senderKeyserverID = + std::string([content.userInfo[keyserverIDKey] UTF8String]); + } auto decryptResult = comm::NotificationsCryptoModule::statefulDecrypt( - encryptedData, comm::NotificationsCryptoModule::olmEncryptedTypeMessage); + senderKeyserverID, + encryptedData, + comm::NotificationsCryptoModule::olmEncryptedTypeMessage); NSString *decryptedSerializedPayload = [NSString stringWithUTF8String:decryptResult->getDecryptedData().c_str()];