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 @@ -30,6 +30,7 @@ size_t publishOneTimeKeys(); bool prekeyExistsAndOlderThan(uint64_t threshold); bool prekeyDoesntExist(); + bool isPrekeySignatureValid(); OlmBuffer pickleAccount(const std::string &secretKey); public: 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,7 @@ #include "CryptoModule.h" +#include "Base64.h" #include "Logger.h" +#include "OlmUtils.h" #include "PlatformSpecificTools.h" #include "olm/account.hh" #include "olm/session.hh" @@ -8,6 +10,7 @@ #include #include #include +#include namespace comm { namespace crypto { @@ -139,6 +142,29 @@ signature == emptySignature; } +bool CryptoModule::isPrekeySignatureValid() { + const std::string signingPublicKey = + getSigningPublicKey(this->getIdentityKeys()); + const std::string prekey = parseOLMPrekey(this->getPrekey()); + const std::string preKeySignature = this->getPrekeySignature(); + + const OlmBuffer prekeyBytes = Base64::decode(prekey); + try { + this->verifySignature(signingPublicKey, prekeyBytes, preKeySignature); + return true; + } catch (const std::exception &e) { + std::string rawMessage{e.what()}; + if (rawMessage.find("BAD_MESSAGE_MAC") != std::string::npos) { + return false; + } + + std::string errorMessage{ + "prekey signature verification failed with: " + rawMessage}; + Logger::log(errorMessage); + throw std::runtime_error(errorMessage); + } +} + Keys CryptoModule::keysFromStrings( const std::string &identityKeys, const std::string &oneTimeKeys) { @@ -474,7 +500,8 @@ std::optional maybeNewPrekey; bool prekeyDoesntExist = this->prekeyDoesntExist(); - if (prekeyDoesntExist) { + bool prekeySignatureValid = this->isPrekeySignatureValid(); + if (prekeyDoesntExist || !prekeySignatureValid) { return this->generateAndGetPrekey(); } diff --git a/native/ios/Comm.xcodeproj/project.pbxproj b/native/ios/Comm.xcodeproj/project.pbxproj --- a/native/ios/Comm.xcodeproj/project.pbxproj +++ b/native/ios/Comm.xcodeproj/project.pbxproj @@ -46,6 +46,7 @@ 7FBB2A7B29EEA2A4002C6493 /* Base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBB2A7A29EEA2A4002C6493 /* Base64.cpp */; }; 7FDFC0FE2DC0FEBD00B1D87F /* OlmUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FDFC0FD2DC0FEBD00B1D87F /* OlmUtils.cpp */; }; 7FDFC0FF2DC0FEBD00B1D87F /* OlmUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FDFC0FD2DC0FEBD00B1D87F /* OlmUtils.cpp */; }; + 7FDFC1002DC105E500B1D87F /* Base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBB2A7A29EEA2A4002C6493 /* Base64.cpp */; }; 7FE4D9F5291DFE9300667BF6 /* commJSI-generated.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FE4D9F4291DFE9300667BF6 /* commJSI-generated.cpp */; }; 816D2D5A2C480E60001C0B67 /* MessageSearchStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 816D2D582C480E60001C0B67 /* MessageSearchStore.cpp */; }; 8B38121629CE5742000C52E9 /* RustPromiseManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8B38121529CE5742000C52E9 /* RustPromiseManager.cpp */; }; @@ -1306,6 +1307,7 @@ CB1648AF27CFBE6A00394D9D /* CryptoModule.cpp in Sources */, CB4821AE27CFB187001AB7E1 /* Tools.cpp in Sources */, CB4821AC27CFB17C001AB7E1 /* Session.cpp in Sources */, + 7FDFC1002DC105E500B1D87F /* Base64.cpp in Sources */, CBB0DF612B768007008E22FF /* CommMMKV.mm in Sources */, CB4821A927CFB153001AB7E1 /* WorkerThread.cpp in Sources */, CB4821AA27CFB153001AB7E1 /* Tools.mm in Sources */,