summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--protocols/WhatsAppWeb/WhatsAppWeb.vcxproj3
-rw-r--r--protocols/WhatsAppWeb/src/proto.h2
-rw-r--r--protocols/WhatsAppWeb/src/stdafx.h2
-rw-r--r--protocols/WhatsAppWeb/src/utils.cpp49
4 files changed, 55 insertions, 1 deletions
diff --git a/protocols/WhatsAppWeb/WhatsAppWeb.vcxproj b/protocols/WhatsAppWeb/WhatsAppWeb.vcxproj
index c2ea6b1c8c..8445a4a7a2 100644
--- a/protocols/WhatsAppWeb/WhatsAppWeb.vcxproj
+++ b/protocols/WhatsAppWeb/WhatsAppWeb.vcxproj
@@ -25,6 +25,9 @@
<ProjectReference Include="..\..\libs\libsignal\libsignal.vcxproj">
<Project>{620e0be7-3763-4f35-9dbd-4770104e269c}</Project>
</ProjectReference>
+ <ProjectReference Include="..\..\libs\libsodium\libsodium.vcxproj">
+ <Project>{a185b162-6cb6-4502-b03f-b56f7699a8d9}</Project>
+ </ProjectReference>
</ItemGroup>
<ItemGroup>
<Image Include="res\whatsapp.ico" />
diff --git a/protocols/WhatsAppWeb/src/proto.h b/protocols/WhatsAppWeb/src/proto.h
index 0feec70bae..9406c414e9 100644
--- a/protocols/WhatsAppWeb/src/proto.h
+++ b/protocols/WhatsAppWeb/src/proto.h
@@ -67,6 +67,8 @@ class WANoise
MBinBuffer pubKey, privKey, salt, encKey, decKey;
uint8_t hash[32];
+ void decrypt(const void *pData, size_t cbLen, MBinBuffer &dest);
+ void encrypt(const void *pData, size_t cbLen, MBinBuffer &dest);
void deriveKey(const void *pData, size_t cbLen, MBinBuffer &write, MBinBuffer &read);
void mixIntoKey(const void *pData, size_t cbLen);
void updateHash(const void *pData, size_t cbLen);
diff --git a/protocols/WhatsAppWeb/src/stdafx.h b/protocols/WhatsAppWeb/src/stdafx.h
index 6ae2826c3a..15b6a40f9c 100644
--- a/protocols/WhatsAppWeb/src/stdafx.h
+++ b/protocols/WhatsAppWeb/src/stdafx.h
@@ -56,6 +56,8 @@ Copyright © 2019-22 George Hazan
#include "../../libs/libsignal/src/hkdf.h"
#include "../../libs/libsignal/src/signal_protocol.h"
+#include "../../libs/libsodium/src/include/sodium.h"
+
/////////////////////////////////////////////////////////////////////////////////////////
// to obtain protobuf library do the following
// - install vcpkg (https://github.com/microsoft/vcpkg);
diff --git a/protocols/WhatsAppWeb/src/utils.cpp b/protocols/WhatsAppWeb/src/utils.cpp
index d956471e48..fba42e8b8d 100644
--- a/protocols/WhatsAppWeb/src/utils.cpp
+++ b/protocols/WhatsAppWeb/src/utils.cpp
@@ -7,6 +7,8 @@ Copyright © 2019 George Hazan
#include "stdafx.h"
+#define sharedKey(A, B, C) crypto_scalarmult((unsigned char*)A, (const unsigned char*)B, (const unsigned char*)C)
+
WAUser* WhatsAppProto::FindUser(const char *szId)
{
mir_cslock lck(m_csUsers);
@@ -234,6 +236,31 @@ void WANoise::mixIntoKey(const void *pData, size_t cbLen)
readCounter = writeCounter = 0;
}
+void WANoise::decrypt(const void *pData, size_t cbLen, MBinBuffer &dest)
+{
+ uint8_t iv[12];
+ memset(iv, 0, 8);
+ memcpy(iv + 8, (bInitFinished) ? &readCounter : &writeCounter, sizeof(int));
+
+ uint8_t outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
+
+ int dec_len = 0, final_len = 0;
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, (BYTE *)decKey.data(), iv);
+ for (size_t len = 0; len < cbLen; len += 1024) {
+ size_t portionSize = cbLen - len;
+ EVP_DecryptUpdate(ctx, outbuf, &dec_len, (BYTE*)pData + len, min(portionSize, 1024));
+ if (len == 0)
+ dest.assign(outbuf, dec_len);
+ else
+ dest.append(outbuf, dec_len);
+ }
+ EVP_DecryptFinal_ex(ctx, outbuf, &final_len);
+ if (final_len)
+ dest.append(outbuf, final_len);
+ EVP_CIPHER_CTX_free(ctx);
+}
+
bool WANoise::decodeFrame(const void *pData, size_t cbLen)
{
if (!bInitFinished) {
@@ -243,10 +270,25 @@ bool WANoise::decodeFrame(const void *pData, size_t cbLen)
auto &static_ = msg.serverhello().static_();
auto &payload = msg.serverhello().payload();
+ uint8_t tmp[32];
+
updateHash(ephemeral.c_str(), ephemeral.size());
- mixIntoKey(ephemeral.c_str(), ephemeral.size());
+ sharedKey(tmp, privKey.data(), ephemeral.c_str());
+ mixIntoKey(tmp, sizeof(tmp));
+
+ MBinBuffer decryptedStatic, decryptedCert;
+ decrypt(static_.c_str(), static_.size(), decryptedStatic);
+
+ sharedKey(tmp, privKey.data(), decryptedStatic.data());
+ mixIntoKey(tmp, sizeof(tmp));
+ decrypt(payload.c_str(), payload.size(), decryptedCert);
+
+ proto::CertChain cert; cert.ParseFromArray(decryptedCert.data(), (int)decryptedCert.length());
+ proto::CertChain::NoiseCertificate::Details details; details.ParseFromString(cert.intermediate().details());
+ if (details.issuerserial() != 0)
+ return false;
}
return true;
}
@@ -271,6 +313,11 @@ void WANoise::encodeFrame(const void *pData, size_t cbLen, MBinBuffer &res)
res.append(pData, cbLen);
}
+void WANoise::encrypt(const void *pData, size_t cbLen, MBinBuffer &dest)
+{
+
+}
+
void WANoise::updateHash(const void *pData, size_t cbLen)
{
if (bInitFinished)