diff options
author | George Hazan <ghazan@miranda.im> | 2022-11-17 18:38:47 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2022-11-17 18:38:47 +0300 |
commit | 6d4ab3925c39c234cefd6b6145eb98c169693681 (patch) | |
tree | 99d37f497b0f1867d9161e58b92201648db75a7c /protocols/WhatsApp | |
parent | ec6ddc5feabf87a067ea22bea943befb169a8684 (diff) |
WhatsApp: fix for reading own keys
Diffstat (limited to 'protocols/WhatsApp')
-rw-r--r-- | protocols/WhatsApp/src/appsync.cpp | 2 | ||||
-rw-r--r-- | protocols/WhatsApp/src/iq.cpp | 20 | ||||
-rw-r--r-- | protocols/WhatsApp/src/message.cpp | 3 | ||||
-rw-r--r-- | protocols/WhatsApp/src/proto.h | 4 | ||||
-rw-r--r-- | protocols/WhatsApp/src/signal.cpp | 53 | ||||
-rw-r--r-- | protocols/WhatsApp/src/utils.cpp | 6 | ||||
-rw-r--r-- | protocols/WhatsApp/src/utils.h | 10 | ||||
-rw-r--r-- | protocols/WhatsApp/src/wanode.cpp | 24 |
8 files changed, 106 insertions, 16 deletions
diff --git a/protocols/WhatsApp/src/appsync.cpp b/protocols/WhatsApp/src/appsync.cpp index 1a0d1b2191..4209160b79 100644 --- a/protocols/WhatsApp/src/appsync.cpp +++ b/protocols/WhatsApp/src/appsync.cpp @@ -308,8 +308,8 @@ void WhatsAppProto::ProcessHistorySync(const Wa__HistorySync *pSync) case WA__HISTORY_SYNC__HISTORY_SYNC_TYPE__INITIAL_STATUS_V3: for (int i = 0; i < pSync->n_statusv3messages; i++) { - auto *pStatus = pSync->statusv3messages[i]; // TODO + // auto *pStatus = pSync->statusv3messages[i]; } break; } diff --git a/protocols/WhatsApp/src/iq.cpp b/protocols/WhatsApp/src/iq.cpp index 3c0cd8c64f..2f8b7fb3d6 100644 --- a/protocols/WhatsApp/src/iq.cpp +++ b/protocols/WhatsApp/src/iq.cpp @@ -82,6 +82,16 @@ void WhatsAppProto::OnIqDoNothing(const WANode&) ///////////////////////////////////////////////////////////////////////////////////////// +void WhatsAppProto::OnIqGetKeys(const WANode &node) +{ + if (auto *pList = node.getChild("list")) + for (auto &it : pList->getChildren()) + if (it->title == "user") + m_signalStore.injectSession(it); +} + +///////////////////////////////////////////////////////////////////////////////////////// + void WhatsAppProto::OnIqGetUsync(const WANode &node) { m_arDevices.destroy(); @@ -92,6 +102,16 @@ void WhatsAppProto::OnIqGetUsync(const WANode &node) for (auto &it : pList->getChildren()) if (it->title == "device") m_arDevices.insert(new WAJid(pszJid, it->getAttrInt("id"))); + + WANodeIq iq(IQ::GET, "encrypt"); + auto *pKey = iq.addChild("key"); + for (auto &it : m_arDevices) { + auto blob = getBlob(MSignalSession(it->user, it->device).getSetting()); + if (blob.isEmpty()) + pKey->addChild("user")->addAttr("jid", it->toString()); + } + if (pKey->getChildren().getCount() > 0) + WSSendNode(iq, &WhatsAppProto::OnIqGetKeys); } } diff --git a/protocols/WhatsApp/src/message.cpp b/protocols/WhatsApp/src/message.cpp index 78567f355a..3a768961ee 100644 --- a/protocols/WhatsApp/src/message.cpp +++ b/protocols/WhatsApp/src/message.cpp @@ -341,6 +341,9 @@ void WhatsAppProto::OnReceiveAck(const WANode &node) bool WhatsAppProto::CreateMsgParticipant(WANode *pParticipants, const WAJid &jid, const MBinBuffer &orig) { + if (jid.device == (int)getDword(DBKEY_DEVICE_ID)) + return false; + int type = 0; try { diff --git a/protocols/WhatsApp/src/proto.h b/protocols/WhatsApp/src/proto.h index 4f52f0409e..36ecbfcbf9 100644 --- a/protocols/WhatsApp/src/proto.h +++ b/protocols/WhatsApp/src/proto.h @@ -169,6 +169,8 @@ class MSignalStore signal_context *m_pContext; signal_protocol_store_context *m_pStore; + void importPublicKey(ec_public_key **result, MBinBuffer &buf); + public: PROTO_INTERFACE *pProto; const char *prefix; @@ -195,6 +197,7 @@ public: MSignalSession* createSession(const CMStringA &szName, int deviceId); MSignalSession* getSession(const signal_protocol_address *address); + void injectSession(const WANode *pNode); MBinBuffer decryptSignalProto(const CMStringA &from, const char *pszType, const MBinBuffer &encrypted); MBinBuffer decryptGroupSignalProto(const CMStringA &from, const CMStringA &author, const MBinBuffer &encrypted); @@ -350,6 +353,7 @@ class WhatsAppProto : public PROTO<WhatsAppProto> void OnIqDoNothing(const WANode &node); void OnIqGcGetAllMetadata(const WANode &node); void OnIqGetAvatar(const WANode &node); + void OnIqGetKeys(const WANode &node); void OnIqGetUsync(const WANode &node); void OnIqPairDevice(const WANode &node); void OnIqPairSuccess(const WANode &node); diff --git a/protocols/WhatsApp/src/signal.cpp b/protocols/WhatsApp/src/signal.cpp index 5ad985db27..3da969a722 100644 --- a/protocols/WhatsApp/src/signal.cpp +++ b/protocols/WhatsApp/src/signal.cpp @@ -504,7 +504,7 @@ CMStringA MSignalSession::getSetting() const MSignalSession* MSignalStore::createSession(const CMStringA &szName, int deviceId) { - signal_protocol_address tmp = {szName.c_str(), szName.GetLength(), deviceId}; + signal_protocol_address tmp = {szName.c_str(), (unsigned)szName.GetLength(), deviceId}; auto *pSession = getSession(&tmp); if (pSession == nullptr) { pSession = new MSignalSession(szName, deviceId); @@ -536,6 +536,55 @@ MSignalSession* MSignalStore::getSession(const signal_protocol_address *address) return pSession; } +void MSignalStore::importPublicKey(ec_public_key **result, MBinBuffer &buf) +{ + buf.appendBefore("\x05", 1); + curve_decode_point(result, buf.data(), buf.length(), m_pContext); +} + +void MSignalStore::injectSession(const WANode *pNode) +{ + WAJid jid(pNode->getAttr("jid")); + auto *signedKey = pNode->getChild("skey"); + auto *key = pNode->getChild("key"); + auto *identity = pNode->getChild("identity"); + auto *registration = pNode->getChild("registration"); + if (!signedKey || !key || !identity || !registration) { + pProto->debugLogA("Bad key data for %s", jid.toString().c_str()); + return; + } + + signal_protocol_address address = {jid.user.c_str(), (unsigned)jid.user.GetLength(), jid.device}; + + session_builder *builder; + logError( + session_builder_create(&builder, m_pStore, &address, m_pContext), + "unable to create session cipher"); + + int regId = decodeBigEndian(registration->content); + int preKeyId = decodeBigEndian(key->getChild("id")->content); + int signedPreKeyId = decodeBigEndian(signedKey->getChild("id")->content); + + ec_public_key *preKeyPub, *signedPreKeyPub, *identityKey; + importPublicKey(&preKeyPub, key->getChild("value")->content); + importPublicKey(&identityKey, identity->content); + importPublicKey(&signedPreKeyPub, signedKey->getChild("value")->content); + + auto &sign = signedKey->getChild("signature")->content; + + session_pre_key_bundle *bundle; + logError( + session_pre_key_bundle_create(&bundle, regId, jid.device, preKeyId, preKeyPub, signedPreKeyId, signedPreKeyPub, sign.data(), sign.length(), identityKey), + "unable to create pre key bundle"); + + logError( + session_builder_process_pre_key_bundle(builder, bundle), + "unable to process pre key bundle"); + + session_pre_key_bundle_destroy((signal_type_base*)bundle); + session_builder_free(builder); +} + ///////////////////////////////////////////////////////////////////////////////////////// MBinBuffer MSignalStore::decryptSignalProto(const CMStringA &from, const char *pszType, const MBinBuffer &encrypted) @@ -696,7 +745,7 @@ MBinBuffer MSignalStore::encryptSignalProto(const WAJid &to, const MBinBuffer &b MBinBuffer res; auto *encBuf = ciphertext_message_get_serialized(pEncrypted); res.assign(encBuf->data, encBuf->len); - signal_message_destroy((signal_type_base *)pEncrypted); + SIGNAL_UNREF(pEncrypted); return res; } diff --git a/protocols/WhatsApp/src/utils.cpp b/protocols/WhatsApp/src/utils.cpp index 9f4d64a4d4..de72fd5b92 100644 --- a/protocols/WhatsApp/src/utils.cpp +++ b/protocols/WhatsApp/src/utils.cpp @@ -240,12 +240,12 @@ MBinBuffer decodeBufStr(const std::string &buf) return res; } -uint32_t decodeBigEndian(const ProtobufCBinaryData &buf) +uint32_t decodeBigEndian(const uint8_t *buf, size_t len) { uint32_t ret = 0; - for (int i = 0; i < buf.len; i++) { + for (int i = 0; i < len; i++) { ret <<= 8; - ret += buf.data[i]; + ret += buf[i]; } return ret; diff --git a/protocols/WhatsApp/src/utils.h b/protocols/WhatsApp/src/utils.h index 5eafb39628..37e48793b2 100644 --- a/protocols/WhatsApp/src/utils.h +++ b/protocols/WhatsApp/src/utils.h @@ -224,7 +224,15 @@ MBinBuffer aesEncrypt( const void *data, size_t dataLen, const void *additionalData = 0, size_t additionalLen = 0); -uint32_t decodeBigEndian(const ProtobufCBinaryData &buf); +uint32_t decodeBigEndian(const uint8_t *pData, size_t len); + +__forceinline uint32_t decodeBigEndian(const ProtobufCBinaryData &buf) { + return decodeBigEndian(buf.data, buf.len); +} +__forceinline uint32_t decodeBigEndian(const MBinBuffer &buf) { + return decodeBigEndian(buf.data(), buf.length()); +} + std::string encodeBigEndian(uint32_t num, size_t len = sizeof(uint32_t)); void generateIV(uint8_t *iv, uint32_t &pVar); diff --git a/protocols/WhatsApp/src/wanode.cpp b/protocols/WhatsApp/src/wanode.cpp index 8d5a2ef7f0..f48ceaebd9 100644 --- a/protocols/WhatsApp/src/wanode.cpp +++ b/protocols/WhatsApp/src/wanode.cpp @@ -576,17 +576,23 @@ void WAWriter::writeString(const char *str) auto *pszDelimiter = strchr(str, '@'); if (pszDelimiter) { - writeByte(JID_PAIR); + WAJid jid(str); + if (jid.device || jid.agent) { + writeByte(AD_JID); + writeByte(jid.agent); + writeByte(jid.device); + writeString(jid.user); + } + else { + writeByte(JID_PAIR); - if (pszDelimiter == str) // empty jid - writeByte(LIST_EMPTY); - else - writeString(CMStringA(str, int(pszDelimiter - str))); + if (jid.user.IsEmpty()) // empty user + writeByte(LIST_EMPTY); + else + writeString(jid.user); - if (pszDelimiter[1] == 0) // empty jid - writeByte(LIST_EMPTY); - else - writeString(pszDelimiter + 1); + writeString(jid.server); + } } else { CMStringA buf(str); |