diff options
author | George Hazan <ghazan@miranda.im> | 2022-10-25 18:35:41 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2022-10-25 18:35:41 +0300 |
commit | 85da6e58410c6fc027068159d19258c518f4c210 (patch) | |
tree | d614f5c55f70c76c5833081e35cea97cb02bba2a /protocols/WhatsApp/src | |
parent | ee5abbbe44376f6b4ba0c373acbf1637ffab3891 (diff) |
WhatsApp: fix for reading & decrypting messages
Diffstat (limited to 'protocols/WhatsApp/src')
-rw-r--r-- | protocols/WhatsApp/src/crypt.cpp | 6 | ||||
-rw-r--r-- | protocols/WhatsApp/src/message.cpp | 10 | ||||
-rw-r--r-- | protocols/WhatsApp/src/proto.h | 1 | ||||
-rw-r--r-- | protocols/WhatsApp/src/protobuf-c/protobuf-c.h | 2 | ||||
-rw-r--r-- | protocols/WhatsApp/src/signal.cpp | 44 | ||||
-rw-r--r-- | protocols/WhatsApp/src/utils.cpp | 13 | ||||
-rw-r--r-- | protocols/WhatsApp/src/utils.h | 1 |
7 files changed, 64 insertions, 13 deletions
diff --git a/protocols/WhatsApp/src/crypt.cpp b/protocols/WhatsApp/src/crypt.cpp index 09a14f53b0..1efb93dde4 100644 --- a/protocols/WhatsApp/src/crypt.cpp +++ b/protocols/WhatsApp/src/crypt.cpp @@ -21,8 +21,10 @@ MBinBuffer aesDecrypt( if (additionalLen) EVP_DecryptUpdate(ctx, nullptr, &tag_len, (uint8_t *)additionalData, (int)additionalLen); - dataLen -= 16; - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (uint8_t *)data + dataLen); + if (cipher == EVP_aes_256_gcm()) { + dataLen -= 16; + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (uint8_t *)data + dataLen); + } MBinBuffer ret; uint8_t outbuf[2000]; diff --git a/protocols/WhatsApp/src/message.cpp b/protocols/WhatsApp/src/message.cpp index 2479ba0458..1397c7c17c 100644 --- a/protocols/WhatsApp/src/message.cpp +++ b/protocols/WhatsApp/src/message.cpp @@ -129,7 +129,14 @@ void WhatsAppProto::OnReceiveMessage(const WANode &node) iDecryptable++; + auto c = msgBody.data() + msgBody.len() - 1; + if (*c <= 0x10) + msgBody.reset(msgBody.len() - *c); + proto::Message encMsg(msgBody.data(), msgBody.len()); + if (!encMsg) + throw "Invalid decoded message"; + if (encMsg->devicesentmessage) msg.message = encMsg->devicesentmessage->message; else @@ -155,7 +162,8 @@ void WhatsAppProto::OnReceiveMessage(const WANode &node) SendReceipt(szChatId, pszReceiptTo, msgId, pszReceiptType); } - catch (const char *) { + catch (const char *pszError) { + debugLogA("Message decryption failed with error: %s", pszError); } if (!iDecryptable) { diff --git a/protocols/WhatsApp/src/proto.h b/protocols/WhatsApp/src/proto.h index 965fbb7ce6..5f315d3ace 100644 --- a/protocols/WhatsApp/src/proto.h +++ b/protocols/WhatsApp/src/proto.h @@ -169,6 +169,7 @@ public: __forceinline session_cipher* getCipher(void) const { return cipher; } __forceinline int getDeviceId() const { return address.device_id; } + CMStringA getSetting() const; }; class MSignalStore diff --git a/protocols/WhatsApp/src/protobuf-c/protobuf-c.h b/protocols/WhatsApp/src/protobuf-c/protobuf-c.h index 5fa52da626..c66fa000e3 100644 --- a/protocols/WhatsApp/src/protobuf-c/protobuf-c.h +++ b/protocols/WhatsApp/src/protobuf-c/protobuf-c.h @@ -209,6 +209,8 @@ size_t foo__bar__baz_bah__pack_to_buffer # define PROTOBUF_C__END_DECLS #endif +#define PROTOBUF_C_UNPACK_ERROR OutputDebugStringA + PROTOBUF_C__BEGIN_DECLS #if defined(_WIN32) && defined(PROTOBUF_C_USE_SHARED_LIB) diff --git a/protocols/WhatsApp/src/signal.cpp b/protocols/WhatsApp/src/signal.cpp index 8207a7462d..1a59fb443b 100644 --- a/protocols/WhatsApp/src/signal.cpp +++ b/protocols/WhatsApp/src/signal.cpp @@ -35,7 +35,7 @@ MSignalStore::~MSignalStore() void MSignalStore::logError(int err, const char *pszMessage) { if (err < 0) { - pProto->debugLogA("libsignal error %d: %s", err, pszMessage); + pProto->debugLogA("libsignal error %d", err); throw pszMessage; } } @@ -100,7 +100,8 @@ static int contains_session_func(const signal_protocol_address *address, void *u auto *pStore = (MSignalStore *)user_data; MSignalSession tmp(CMStringA(address->name, (int)address->name_len), address->device_id); - return pStore->arSessions.find(&tmp) == nullptr; + ptrA data(pStore->pProto->getStringA(tmp.getSetting())); + return data == nullptr; } static int delete_all_sessions_func(const char *name, size_t name_len, void *user_data) @@ -111,6 +112,7 @@ static int delete_all_sessions_func(const char *name, size_t name_len, void *use int count = 0; for (auto &it : pList.rev_iter()) { if (it->hasAddress(name, name_len)) { + pStore->pProto->delSetting(it->getSetting()); pList.remove(pList.indexOf(&it)); count++; } @@ -125,8 +127,10 @@ int delete_session_func(const signal_protocol_address *address, void *user_data) MSignalSession tmp(CMStringA(address->name, (int)address->name_len), address->device_id); int idx = pList.getIndex(&tmp); - if (idx != -1) + if (idx != -1) { + pStore->pProto->delSetting(tmp.getSetting()); pList.remove(idx); + } return 0; } @@ -156,13 +160,21 @@ int load_session_func(signal_buffer **record, signal_buffer **user_data_storage, auto *pStore = (MSignalStore *)user_data; MSignalSession tmp(CMStringA(address->name, (int)address->name_len), address->device_id); - if (auto *pSession = pStore->arSessions.find(&tmp)) { - *record = signal_buffer_create((uint8_t *)pSession->sessionData.data(), pSession->sessionData.length()); - *user_data_storage = signal_buffer_create((uint8_t *)pSession->userData.data(), pSession->userData.length()); - return 1; - } + auto *pSession = pStore->arSessions.find(&tmp); + if (pSession == nullptr) { + ptrA szSession(pStore->pProto->getStringA(tmp.getSetting())); + if (szSession == nullptr) + return 0; - return 0; + JSONNode root = JSONNode::parse(szSession); + pSession = new MSignalSession(tmp); + pSession->sessionData = decodeBufStr(root["data"].as_string()); + pSession->userData = decodeBufStr(root["user"].as_string()); + } + + *record = signal_buffer_create((uint8_t *)pSession->sessionData.data(), pSession->sessionData.length()); + *user_data_storage = signal_buffer_create((uint8_t *)pSession->userData.data(), pSession->userData.length()); + return 1; } static int store_session_func(const signal_protocol_address *address, uint8_t *record, size_t record_len, uint8_t *user_record, size_t user_record_len, void *user_data) @@ -178,6 +190,10 @@ static int store_session_func(const signal_protocol_address *address, uint8_t *r pSession->sessionData.assign(record, record_len); pSession->userData.assign(user_record, user_record_len); + + JSONNode root; + root << CHAR_PARAM("data", ptrA(mir_base64_encode(record, record_len))) << CHAR_PARAM("user", ptrA(mir_base64_encode(user_record, user_record_len))); + pStore->pProto->setString(pSession->getSetting(), root.write().c_str()); return 0; } @@ -256,6 +272,9 @@ static int load_signed_pre_key(signal_buffer **record, uint32_t signed_pre_key_i { auto *pStore = (MSignalStore *)user_data; + if (signed_pre_key_id == 0) + signed_pre_key_id = 1; + CMStringA szSetting(FORMAT, "%s%d", "SignedPreKey", signed_pre_key_id); MBinBuffer blob(pStore->pProto->getBlob(szSetting)); if (blob.data() == 0) { @@ -442,6 +461,11 @@ bool MSignalSession::hasAddress(const char *name, size_t name_len) const return memcmp(address.name, name, name_len) == 0; } +CMStringA MSignalSession::getSetting() const +{ + return CMStringA(FORMAT, "%s_%s_%d", "SignalSession", szName.c_str(), getDeviceId()); +} + ///////////////////////////////////////////////////////////////////////////////////////// MSignalSession* MSignalStore::createSession(const CMStringA &szName, int deviceId) @@ -575,6 +599,6 @@ void MSignalStore::generatePrekeys(int count) ///////////////////////////////////////////////////////////////////////////////////////// -void MSignalStore::processSenderKeyMessage(const Wa__Message__SenderKeyDistributionMessage *) +void MSignalStore::processSenderKeyMessage(const Wa__Message__SenderKeyDistributionMessage *msg) { } diff --git a/protocols/WhatsApp/src/utils.cpp b/protocols/WhatsApp/src/utils.cpp index 592d509253..983a98a3f7 100644 --- a/protocols/WhatsApp/src/utils.cpp +++ b/protocols/WhatsApp/src/utils.cpp @@ -224,6 +224,19 @@ std::string decodeBinStr(const std::string &buf) return res; } +MBinBuffer decodeBufStr(const std::string &buf) +{ + MBinBuffer res; + size_t cbLen; + void *pData = mir_base64_decode(buf.c_str(), &cbLen); + if (pData == nullptr) + return res; + + res.assign(pData, cbLen); + mir_free(pData); + return res; +} + uint32_t decodeBigEndian(const ProtobufCBinaryData &buf) { uint32_t ret = 0; diff --git a/protocols/WhatsApp/src/utils.h b/protocols/WhatsApp/src/utils.h index a3163ad88d..f102c47c2a 100644 --- a/protocols/WhatsApp/src/utils.h +++ b/protocols/WhatsApp/src/utils.h @@ -203,6 +203,7 @@ CMStringA file2string(const wchar_t *pwszFileName); CMStringA directPath2url(const char *pszDirectPath); std::string decodeBinStr(const std::string &buf); +MBinBuffer decodeBufStr(const std::string &buf); MBinBuffer aesDecrypt( const EVP_CIPHER *cipher, |