Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3153273
D10600.id35881.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
13 KB
Referenced Files
None
Subscribers
None
D10600.id35881.diff
View Options
diff --git a/native/cpp/CommonCpp/CryptoTools/CryptoModule.h b/native/cpp/CommonCpp/CryptoTools/CryptoModule.h
--- a/native/cpp/CommonCpp/CryptoTools/CryptoModule.h
+++ b/native/cpp/CommonCpp/CryptoTools/CryptoModule.h
@@ -4,7 +4,6 @@
#include <string>
#include <unordered_map>
-#include "folly/Optional.h"
#include "olm/olm.h"
#include "Persist.h"
@@ -28,6 +27,7 @@
void generateOneTimeKeys(size_t oneTimeKeysAmount);
// returns number of published keys
size_t publishOneTimeKeys();
+ bool prekeyExistsAndOlderThan(uint64_t threshold);
public:
const std::string id;
@@ -49,7 +49,7 @@
std::uint8_t getNumPrekeys();
std::string getPrekey();
std::string getPrekeySignature();
- folly::Optional<std::string> getUnpublishedPrekey();
+ std::optional<std::string> getUnpublishedPrekey();
std::string generateAndGetPrekey();
void markPrekeyAsPublished();
void forgetOldPrekey();
@@ -82,6 +82,7 @@
const std::string &publicKey,
const std::string &message,
const std::string &signature);
+ std::optional<std::string> validatePrekey();
};
} // namespace crypto
diff --git a/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp b/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp
--- a/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp
+++ b/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp
@@ -4,6 +4,7 @@
#include "olm/account.hh"
#include "olm/session.hh"
+#include <ctime>
#include <stdexcept>
namespace comm {
@@ -102,6 +103,22 @@
return ::olm_account_mark_keys_as_published(this->getOlmAccount());
}
+bool CryptoModule::prekeyExistsAndOlderThan(uint64_t threshold) {
+ // Our fork of Olm only remembers two prekeys at a time.
+ // If the new one hasn't been published, then the old one is still active.
+ // In that scenario, we need to avoid rotating the prekey because it will
+ // result in the old active prekey being discarded.
+ if (this->getUnpublishedPrekey().has_value()) {
+ return false;
+ }
+
+ uint64_t currentTime = std::time(nullptr);
+ uint64_t lastPrekeyPublishTime =
+ ::olm_account_get_last_prekey_publish_time(this->getOlmAccount());
+
+ return currentTime - lastPrekeyPublishTime >= threshold;
+}
+
Keys CryptoModule::keysFromStrings(
const std::string &identityKeys,
const std::string &oneTimeKeys) {
@@ -167,7 +184,7 @@
return std::string{signatureBuffer.begin(), signatureBuffer.end()};
}
-folly::Optional<std::string> CryptoModule::getUnpublishedPrekey() {
+std::optional<std::string> CryptoModule::getUnpublishedPrekey() {
OlmBuffer prekey;
prekey.resize(::olm_account_prekey_length(this->getOlmAccount()));
@@ -175,7 +192,7 @@
this->getOlmAccount(), prekey.data(), prekey.size());
if (0 == retval) {
- return folly::none;
+ return std::nullopt;
} else if (-1 == retval) {
throw std::runtime_error{
"error getUnpublishedPrekey => " +
@@ -447,5 +464,24 @@
}
}
+std::optional<std::string> CryptoModule::validatePrekey() {
+ static const uint64_t maxPrekeyPublishTime = 10 * 60;
+ static const uint64_t maxOldPrekeyAge = 2 * 60;
+ std::optional<std::string> maybeNewPrekey;
+
+ bool shouldRotatePrekey =
+ this->prekeyExistsAndOlderThan(maxPrekeyPublishTime);
+ if (shouldRotatePrekey) {
+ maybeNewPrekey = this->generateAndGetPrekey();
+ }
+
+ bool shouldForgetPrekey = this->prekeyExistsAndOlderThan(maxOldPrekeyAge);
+ if (shouldForgetPrekey) {
+ this->forgetOldPrekey();
+ }
+
+ return maybeNewPrekey;
+}
+
} // namespace crypto
} // namespace comm
diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
--- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
+++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
@@ -72,6 +72,7 @@
jsi::Runtime &rt,
double oneTimeKeysAmount) override;
virtual jsi::Value generateAndGetPrekeys(jsi::Runtime &rt) override;
+ virtual jsi::Value validateAndUploadPrekeys(jsi::Runtime &rt) override;
virtual jsi::Value initializeNotificationsSession(
jsi::Runtime &rt,
jsi::String identityKeys,
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
@@ -654,6 +654,78 @@
});
}
+jsi::Value CommCoreModule::validateAndUploadPrekeys(jsi::Runtime &rt) {
+ return createPromiseAsJSIValue(
+ rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
+ taskType job = [=, &innerRt]() {
+ std::string error;
+ std::optional<std::string> maybePrekeyToUpload;
+
+ try {
+ maybePrekeyToUpload = this->cryptoModule->validatePrekey();
+ if (maybePrekeyToUpload.has_value()) {
+ this->persistCryptoModule();
+ } else {
+ maybePrekeyToUpload = this->cryptoModule->getUnpublishedPrekey();
+ }
+ } catch (const std::exception &e) {
+ error = e.what();
+ }
+
+ if (error.size()) {
+ this->jsInvoker_->invokeAsync(
+ [=, &innerRt]() { promise->reject(error); });
+ return;
+ } else if (!maybePrekeyToUpload.has_value()) {
+ this->jsInvoker_->invokeAsync(
+ [=]() { promise->resolve(jsi::Value::undefined()); });
+ return;
+ }
+
+ std::string prekeyToUpload = maybePrekeyToUpload.value();
+ std::string prekeyUploadError;
+
+ try {
+ std::string prekeySignature =
+ this->cryptoModule->getPrekeySignature();
+ // TODO: Implement notifs prekey rotation.
+ // Notifications prekey is not rotated at this moment. It
+ // is fetched with signature to match identity service API.
+ std::string notificationsPrekey =
+ NotificationsCryptoModule::getNotificationsPrekey("Comm");
+ std::string notificationsPrekeySignature =
+ NotificationsCryptoModule::getNotificationsPrekeySignature(
+ "Comm");
+ try {
+ // TODO: upload prekey to identity service
+ } catch (const std::exception &e) {
+ prekeyUploadError = e.what();
+ }
+
+ if (!prekeyUploadError.size()) {
+ this->cryptoModule->markPrekeyAsPublished();
+ this->persistCryptoModule();
+ }
+ } catch (std::exception &e) {
+ error = e.what();
+ }
+
+ this->jsInvoker_->invokeAsync([=]() {
+ if (error.size()) {
+ promise->reject(error);
+ return;
+ }
+ if (prekeyUploadError.size()) {
+ promise->reject(prekeyUploadError);
+ return;
+ }
+ promise->resolve(jsi::Value::undefined());
+ });
+ };
+ this->cryptoThread->scheduleTask(job);
+ });
+}
+
jsi::Value CommCoreModule::initializeNotificationsSession(
jsi::Runtime &rt,
jsi::String identityKeys,
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
@@ -33,6 +33,8 @@
static std::string
getNotificationsIdentityKeys(const std::string &callingProcessName);
static std::string
+ getNotificationsPrekey(const std::string &callingProcessName);
+ static std::string
generateAndGetNotificationsPrekey(const std::string &callingProcessName);
static std::string
getNotificationsPrekeySignature(const std::string &callingProcessName);
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
@@ -203,6 +203,17 @@
return identityKeys;
}
+std::string NotificationsCryptoModule::getNotificationsPrekey(
+ const std::string &callingProcessName) {
+ std::string prekey;
+ auto caller =
+ [&prekey](const std::unique_ptr<crypto::CryptoModule> &cryptoModule) {
+ prekey = cryptoModule->getPrekey();
+ };
+ NotificationsCryptoModule::callCryptoModule(caller, callingProcessName);
+ return prekey;
+}
+
std::string NotificationsCryptoModule::generateAndGetNotificationsPrekey(
const std::string &callingProcessName) {
std::string prekey;
diff --git a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
--- a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
+++ b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
@@ -75,6 +75,9 @@
static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_generateAndGetPrekeys(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->generateAndGetPrekeys(rt);
}
+static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_validateAndUploadPrekeys(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
+ return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->validateAndUploadPrekeys(rt);
+}
static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsSession(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->initializeNotificationsSession(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt));
}
@@ -169,6 +172,7 @@
methodMap_["getPrimaryOneTimeKeys"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getPrimaryOneTimeKeys};
methodMap_["getNotificationsOneTimeKeys"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getNotificationsOneTimeKeys};
methodMap_["generateAndGetPrekeys"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_generateAndGetPrekeys};
+ methodMap_["validateAndUploadPrekeys"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_validateAndUploadPrekeys};
methodMap_["initializeNotificationsSession"] = MethodMetadata {4, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsSession};
methodMap_["isNotificationsSessionInitialized"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isNotificationsSessionInitialized};
methodMap_["initializeContentOutboundSession"] = MethodMetadata {5, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeContentOutboundSession};
diff --git a/native/cpp/CommonCpp/_generated/commJSI.h b/native/cpp/CommonCpp/_generated/commJSI.h
--- a/native/cpp/CommonCpp/_generated/commJSI.h
+++ b/native/cpp/CommonCpp/_generated/commJSI.h
@@ -40,6 +40,7 @@
virtual jsi::Value getPrimaryOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0;
virtual jsi::Value getNotificationsOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0;
virtual jsi::Value generateAndGetPrekeys(jsi::Runtime &rt) = 0;
+ virtual jsi::Value validateAndUploadPrekeys(jsi::Runtime &rt) = 0;
virtual jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKeys) = 0;
virtual jsi::Value isNotificationsSessionInitialized(jsi::Runtime &rt) = 0;
virtual jsi::Value initializeContentOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKeys, jsi::String deviceID) = 0;
@@ -244,6 +245,14 @@
return bridging::callFromJs<jsi::Value>(
rt, &T::generateAndGetPrekeys, jsInvoker_, instance_);
}
+ jsi::Value validateAndUploadPrekeys(jsi::Runtime &rt) override {
+ static_assert(
+ bridging::getParameterCount(&T::validateAndUploadPrekeys) == 1,
+ "Expected validateAndUploadPrekeys(...) to have 1 parameters");
+
+ return bridging::callFromJs<jsi::Value>(
+ rt, &T::validateAndUploadPrekeys, jsInvoker_, instance_);
+ }
jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKeys) override {
static_assert(
bridging::getParameterCount(&T::initializeNotificationsSession) == 5,
diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js
--- a/native/schema/CommCoreModuleSchema.js
+++ b/native/schema/CommCoreModuleSchema.js
@@ -82,6 +82,7 @@
oneTimeKeysAmount: number,
) => Promise<OLMOneTimeKeys>;
+generateAndGetPrekeys: () => Promise<SignedPrekeys>;
+ +validateAndUploadPrekeys: () => Promise<void>;
+initializeNotificationsSession: (
identityKeys: string,
prekey: string,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 6, 6:01 AM (21 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2428628
Default Alt Text
D10600.id35881.diff (13 KB)
Attached To
Mode
D10600: Implement prekey rotation on native
Attached
Detach File
Event Timeline
Log In to Comment