Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32285148
D11234.1765269981.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
30 KB
Referenced Files
None
Subscribers
None
D11234.1765269981.diff
View Options
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<NotificationsCryptoModuleJNIHelper> 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 <thread>
#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<std::string> secretKey =
+ CommSecureStore::get(legacyCryptoAccountDataKey);
+
+ if (!secretKey.hasValue()) {
+ return false;
+ }
+
+ std::unique_ptr<crypto::CryptoModule> 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<OlmPersistAccount>(
+ 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> 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<uint8_t>(
+ identityKeysCpp.begin(), identityKeysCpp.end()),
+ std::vector<uint8_t>(prekeyCpp.begin(), prekeyCpp.end()),
+ std::vector<uint8_t>(
+ prekeySignatureCpp.begin(), prekeySignatureCpp.end()),
+ std::vector<uint8_t>(
+ oneTimeKeyCpp.begin(), oneTimeKeyCpp.end()));
+
+ result = this->notifsCryptoModule->encrypt(
+ keyserverIDCpp,
+ NotificationsCryptoModule::initialEncryptedMessageContent);
+
+ std::shared_ptr<crypto::Session> 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<crypto::CryptoModule> cryptoModule,
- const std::string &path,
- const std::string &picklingKey,
- const std::string &callingProcessName);
+ static std::string getPicklingKey(bool generateIfNotExists);
static std::unique_ptr<crypto::CryptoModule> deserializeCryptoModule(
const std::string &path,
const std::string &picklingKey);
- static void callCryptoModule(
- std::function<void(
- const std::unique_ptr<crypto::CryptoModule> &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<crypto::Session> session);
+ static std::unique_ptr<crypto::Session> 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<crypto::CryptoModule>
+ 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<crypto::Session> 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<crypto::CryptoModule> cryptoModule,
+ std::unique_ptr<crypto::Session> session,
+ std::string keyserverID,
std::string decryptedData);
- std::unique_ptr<crypto::CryptoModule> cryptoModuleState;
+ std::unique_ptr<crypto::Session> sessionState;
+ std::string keyserverID;
std::string decryptedData;
friend NotificationsCryptoModule;
public:
std::string getDecryptedData();
+ std::string getKeyserverID();
};
- static std::unique_ptr<StatefulDecryptResult>
- statefulDecrypt(const std::string &data, const size_t messageType);
- static void flushState(
- std::unique_ptr<StatefulDecryptResult> statefulDecryptResult,
- const std::string &callingProcessName);
+ static std::unique_ptr<StatefulDecryptResult> statefulDecrypt(
+ const std::string &keyserverID,
+ const std::string &data,
+ const size_t messageType);
+ static void
+ flushState(std::unique_ptr<StatefulDecryptResult> 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<crypto::CryptoModule>
NotificationsCryptoModule::deserializeCryptoModule(
@@ -74,156 +72,92 @@
crypto::Persist({account, sessions}));
}
-void NotificationsCryptoModule::serializeAndFlushCryptoModule(
- std::unique_ptr<crypto::CryptoModule> 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<std::string> 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<std::string> 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<crypto::CryptoModule> &cryptoModule)> caller,
- const std::string &callingProcessName) {
- const std::string picklingKey = NotificationsCryptoModule::getPicklingKey();
- const std::string path =
- PlatformSpecificTools::getNotificationsCryptoAccountPath();
- std::unique_ptr<crypto::CryptoModule> 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<crypto::CryptoModule>
+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<crypto::CryptoModule> cryptoModule =
- std::make_unique<crypto::CryptoModule>(
- 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<crypto::CryptoModule> &cryptoModule) {
- cryptoModule->initializeOutboundForSendingSession(
- NotificationsCryptoModule::keyserverHostedNotificationsID,
- std::vector<uint8_t>(identityKeys.begin(), identityKeys.end()),
- std::vector<uint8_t>(prekey.begin(), prekey.end()),
- std::vector<uint8_t>(prekeySignature.begin(), prekeySignature.end()),
- std::vector<uint8_t>(oneTimeKey.begin(), oneTimeKey.end()));
- initialEncryptedMessage = cryptoModule->encrypt(
- NotificationsCryptoModule::keyserverHostedNotificationsID,
- NotificationsCryptoModule::initialEncryptedMessageContent);
- };
- NotificationsCryptoModule::callCryptoModule(caller, callingProcessName);
- return initialEncryptedMessage;
-}
+ std::string legacySecureStoreNotifsAccountKey =
+ "notificationsCryptoAccountDataKey";
+ folly::Optional<std::string> 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<crypto::CryptoModule> &cryptoModule) {
- sessionInitialized = cryptoModule->hasSessionFor(
- NotificationsCryptoModule::keyserverHostedNotificationsID);
- };
- NotificationsCryptoModule::callCryptoModule(caller, callingProcessName);
- return sessionInitialized;
+ std::unique_ptr<crypto::CryptoModule> 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<crypto::Session> 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<crypto::Session>
+NotificationsCryptoModule::fetchNotificationsSession(
+ const std::string &keyserverID,
+ const std::string &picklingKey) {
+ std::string keyserverNotificationsSessionKey =
+ NotificationsCryptoModule::getKeyserverNotificationsSessionKey(
+ keyserverID);
+ std::optional<std::string> 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<crypto::Session> session =
+ crypto::Session::restoreFromB64(picklingKey, sessionBytes);
+ return session;
+}
+
+void NotificationsCryptoModule::persistNotificationsSession(
+ const std::string &keyserverID,
+ std::shared_ptr<crypto::Session> 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<crypto::CryptoModule> &cryptoModule) {
- crypto::EncryptedData encryptedData{
- std::vector<uint8_t>(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<crypto::Session> session =
+ NotificationsCryptoModule::fetchNotificationsSession(
+ keyserverID, picklingKey);
+ crypto::EncryptedData encryptedData{
+ std::vector<uint8_t>(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<crypto::CryptoModule> cryptoModule,
+ std::unique_ptr<crypto::Session> 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::StatefulDecryptResult>
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<crypto::Session> session =
+ NotificationsCryptoModule::fetchNotificationsSession(
+ keyserverID, picklingKey);
- std::unique_ptr<crypto::CryptoModule> cryptoModule =
- NotificationsCryptoModule::deserializeCryptoModule(path, picklingKey);
crypto::EncryptedData encryptedData{
std::vector<uint8_t>(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<StatefulDecryptResult>(
std::move(statefulDecryptResult));
}
void NotificationsCryptoModule::flushState(
- std::unique_ptr<StatefulDecryptResult> 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> 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<NotificationsCryptoModuleJNIHelper> 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()];
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Dec 9, 8:46 AM (15 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5853579
Default Alt Text
D11234.1765269981.diff (30 KB)
Attached To
Mode
D11234: Implement notifications sessions storage on top of MMKV. Migrate existing notifs account to SQLite
Attached
Detach File
Event Timeline
Log In to Comment