summaryrefslogtreecommitdiff
path: root/protocols/WhatsApp/src
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2022-10-25 18:35:41 +0300
committerGeorge Hazan <ghazan@miranda.im>2022-10-25 18:35:41 +0300
commit85da6e58410c6fc027068159d19258c518f4c210 (patch)
treed614f5c55f70c76c5833081e35cea97cb02bba2a /protocols/WhatsApp/src
parentee5abbbe44376f6b4ba0c373acbf1637ffab3891 (diff)
WhatsApp: fix for reading & decrypting messages
Diffstat (limited to 'protocols/WhatsApp/src')
-rw-r--r--protocols/WhatsApp/src/crypt.cpp6
-rw-r--r--protocols/WhatsApp/src/message.cpp10
-rw-r--r--protocols/WhatsApp/src/proto.h1
-rw-r--r--protocols/WhatsApp/src/protobuf-c/protobuf-c.h2
-rw-r--r--protocols/WhatsApp/src/signal.cpp44
-rw-r--r--protocols/WhatsApp/src/utils.cpp13
-rw-r--r--protocols/WhatsApp/src/utils.h1
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,