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,6 +4,7 @@ #include #include +#include "folly/Optional.h" #include "olm/olm.h" #include "Persist.h" @@ -40,6 +41,14 @@ std::string getIdentityKeys(); std::string getOneTimeKeys(size_t oneTimeKeysAmount = 50); + // Prekey rotation methods for X3DH + std::uint8_t getNumPrekeys(); + std::string getPrekey(); + folly::Optional getUnpublishedPrekey(); + std::string generateAndGetPrekey(); + void markPrekeyAsPublished(); + void forgetOldPrekey(); + void initializeInboundForReceivingSession( const std::string &targetUserId, const OlmBuffer &encryptedMessage, 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 @@ -1,5 +1,6 @@ #include "CryptoModule.h" #include "PlatformSpecificTools.h" +#include "olm/account.hh" #include "olm/session.hh" #include @@ -115,6 +116,76 @@ this->keys.oneTimeKeys.begin(), this->keys.oneTimeKeys.end()}; } +std::uint8_t CryptoModule::getNumPrekeys() { + return reinterpret_cast(this->account)->num_prekeys; +} + +std::string CryptoModule::getPrekey() { + OlmBuffer prekey; + prekey.resize(::olm_account_prekey_length(this->account)); + + if (-1 == ::olm_account_prekey(this->account, prekey.data(), prekey.size())) { + throw std::runtime_error{ + "error getPrekey => " + + std::string{::olm_account_last_error(this->account)}}; + } + + return std::string{std::string{prekey.begin(), prekey.end()}}; +} + +folly::Optional CryptoModule::getUnpublishedPrekey() { + OlmBuffer prekey; + prekey.resize(::olm_account_prekey_length(this->account)); + + std::size_t retval = ::olm_account_unpublished_prekey( + this->account, prekey.data(), prekey.size()); + + if (0 == retval) { + return folly::none; + } else if (-1 == retval) { + throw std::runtime_error{ + "error getUnpublishedPrekey => " + + std::string{::olm_account_last_error(this->account)}}; + } + + return std::string{prekey.begin(), prekey.end()}; +} + +std::string CryptoModule::generateAndGetPrekey() { + size_t prekeySize = + ::olm_account_generate_prekey_random_length(this->account); + + OlmBuffer random; + PlatformSpecificTools::generateSecureRandomBytes(random, prekeySize); + + if (-1 == + ::olm_account_generate_prekey( + this->account, random.data(), random.size())) { + throw std::runtime_error{ + "error generateAndGetPrekey => " + + std::string{::olm_account_last_error(this->account)}}; + } + + OlmBuffer prekey; + prekey.resize(::olm_account_prekey_length(this->account)); + + if (-1 == ::olm_account_prekey(this->account, prekey.data(), prekey.size())) { + throw std::runtime_error{ + "error generateAndGetPrekey => " + + std::string{::olm_account_last_error(this->account)}}; + } + + return std::string{prekey.begin(), prekey.end()}; +} + +void CryptoModule::markPrekeyAsPublished() { + ::olm_account_mark_prekey_as_published(this->account); +} + +void CryptoModule::forgetOldPrekey() { + ::olm_account_forget_old_prekey(this->account); +} + void CryptoModule::initializeInboundForReceivingSession( const std::string &targetUserId, const OlmBuffer &encryptedMessage,