summaryrefslogtreecommitdiff
path: root/protocols/WhatsAppWeb
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2022-10-06 15:04:47 +0300
committerGeorge Hazan <ghazan@miranda.im>2022-10-06 15:04:47 +0300
commit824b202d681be059056b0bf7d9db2799c79d7ae4 (patch)
treec5b9f407b7f10513ad880d50fad40a2ba9ee9b4d /protocols/WhatsAppWeb
parent43134f01d3bcf7d5abe6c84c297faf1372e38bda (diff)
WhatsApp:
- global context moved inside MSignalStore; - signed prekey is stored now as one binary record; - libsignal errors are now logged to network log; - code cleaning
Diffstat (limited to 'protocols/WhatsAppWeb')
-rw-r--r--protocols/WhatsAppWeb/src/db.h7
-rw-r--r--protocols/WhatsAppWeb/src/iq.cpp5
-rw-r--r--protocols/WhatsAppWeb/src/main.cpp50
-rw-r--r--protocols/WhatsAppWeb/src/noise.cpp4
-rw-r--r--protocols/WhatsAppWeb/src/proto.h7
-rw-r--r--protocols/WhatsAppWeb/src/server.cpp49
-rw-r--r--protocols/WhatsAppWeb/src/signal.cpp241
-rw-r--r--protocols/WhatsAppWeb/src/stdafx.h1
-rw-r--r--protocols/WhatsAppWeb/src/utils.cpp2
9 files changed, 179 insertions, 187 deletions
diff --git a/protocols/WhatsAppWeb/src/db.h b/protocols/WhatsAppWeb/src/db.h
index adab0945e7..0686693330 100644
--- a/protocols/WhatsAppWeb/src/db.h
+++ b/protocols/WhatsAppWeb/src/db.h
@@ -13,12 +13,11 @@ Copyright © 2019-22 George Hazan
#define DBKEY_NOISE_PUB "NoisePublicKey"
#define DBKEY_NOISE_PRIV "NoisePrivateKey"
+
#define DBKEY_SIGNED_IDENTITY_PUB "SignedIdentityPublicKey"
#define DBKEY_SIGNED_IDENTITY_PRIV "SignedIdentityPrivateKey"
-#define DBKEY_PREKEY_PUB "PrekeyPublicKey"
-#define DBKEY_PREKEY_PRIV "PrekeyPrivateKey"
-#define DBKEY_PREKEY_SIGN "PrekeySignature"
-#define DBKEY_PREKEY_KEYID "PrekeyKeyId"
+
+#define DBKEY_PREKEY "SignedPreKey0"
#define DBKEY_PREKEY_NEXT_ID "PrekeyNextId"
#define DBKEY_PREKEY_UPLOAD_ID "PrekeyUploadId"
diff --git a/protocols/WhatsAppWeb/src/iq.cpp b/protocols/WhatsAppWeb/src/iq.cpp
index 07134c0cb8..66545e26ab 100644
--- a/protocols/WhatsAppWeb/src/iq.cpp
+++ b/protocols/WhatsAppWeb/src/iq.cpp
@@ -148,10 +148,11 @@ void WhatsAppProto::OnReceiveMessage(const WANode &node)
bFromMe = m_szJid == participant;
auto *pKey = new proto::MessageKey();
- pKey->set_participant(participant);
pKey->set_remotejid(szChatId);
pKey->set_id(msgId);
pKey->set_fromme(bFromMe);
+ if (participant)
+ pKey->set_participant(participant);
proto::WebMessageInfo msg;
msg.set_allocated_key(pKey);
@@ -353,7 +354,7 @@ void WhatsAppProto::OnIqPairSuccess(const WANode &node)
signal_buffer *result;
ec_private_key key = {};
memcpy(key.data, m_signalStore.signedIdentity.priv.data(), m_signalStore.signedIdentity.priv.length());
- if (curve_calculate_signature(g_plugin.pCtx, &result, &key, (BYTE *)buf.data(), buf.length()) != 0)
+ if (curve_calculate_signature(m_signalStore.CTX(), &result, &key, (BYTE *)buf.data(), buf.length()) != 0)
throw "OnIqPairSuccess: cannot calculate account signature, exiting";
account.set_devicesignature(result->data, result->len);
diff --git a/protocols/WhatsAppWeb/src/main.cpp b/protocols/WhatsAppWeb/src/main.cpp
index 445f22edb3..dc6ac65afe 100644
--- a/protocols/WhatsAppWeb/src/main.cpp
+++ b/protocols/WhatsAppWeb/src/main.cpp
@@ -45,41 +45,6 @@ CMPlugin::CMPlugin() :
/////////////////////////////////////////////////////////////////////////////////////////
// Load
-static int hmac_sha256_init(void **hmac_context, const uint8_t *key, size_t key_len, void *)
-{
- HMAC_CTX *ctx = HMAC_CTX_new();
- *hmac_context = ctx;
- HMAC_Init(ctx, key, (int)key_len, EVP_sha256());
- return 0;
-}
-
-int hmac_sha256_update(void *hmac_context, const uint8_t *data, size_t data_len, void *)
-{
- return HMAC_Update((HMAC_CTX *)hmac_context, data, data_len);
-}
-
-int hmac_sha256_final(void *hmac_context, signal_buffer **output, void *)
-{
- BYTE data[200];
- unsigned len = 0;
- if (!HMAC_Final((HMAC_CTX *)hmac_context, data, &len))
- return 1;
-
- *output = signal_buffer_create(data, len);
- return 0;
-}
-
-void hmac_sha256_cleanup(void *hmac_context, void *)
-{
- HMAC_CTX_free((HMAC_CTX *)hmac_context);
-}
-
-static int random_func(uint8_t *pData, size_t size, void *)
-{
- Utils_GetRandom(pData, size);
- return 0;
-}
-
int CMPlugin::Load()
{
// InitIcons();
@@ -90,19 +55,6 @@ int CMPlugin::Load()
nlu.szSettingsModule = "WhatsApp";
nlu.szDescriptiveName.w = TranslateT("WhatsApp (HTTP)");
hAvatarUser = Netlib_RegisterUser(&nlu);
-
- //////////////////////////////////////////////////////////////////////////////////////
- signal_context_create(&pCtx, nullptr);
-
- signal_crypto_provider prov;
- memset(&prov, 0xFF, sizeof(prov));
- prov.hmac_sha256_init_func = hmac_sha256_init;
- prov.hmac_sha256_final_func = hmac_sha256_final;
- prov.hmac_sha256_update_func = hmac_sha256_update;
- prov.hmac_sha256_cleanup_func = hmac_sha256_cleanup;
- prov.random_func = random_func;
- signal_context_set_crypto_provider(pCtx, &prov);
-
return 0;
}
@@ -113,7 +65,5 @@ int CMPlugin::Unload()
{
Netlib_CloseHandle(hAvatarConn);
Netlib_CloseHandle(hAvatarUser);
-
- signal_context_destroy(pCtx);
return 0;
}
diff --git a/protocols/WhatsAppWeb/src/noise.cpp b/protocols/WhatsAppWeb/src/noise.cpp
index 4d9dc23956..6a57c8f40e 100644
--- a/protocols/WhatsAppWeb/src/noise.cpp
+++ b/protocols/WhatsAppWeb/src/noise.cpp
@@ -21,7 +21,7 @@ WANoise::WANoise(WhatsAppProto *_ppro) :
// generate ephemeral keys: public & private
ec_key_pair *pKeys;
- curve_generate_key_pair(g_plugin.pCtx, &pKeys);
+ curve_generate_key_pair(ppro->m_signalStore.CTX(), &pKeys);
auto *pPubKey = ec_key_pair_get_public(pKeys);
ephemeral.pub.assign(pPubKey->data, sizeof(pPubKey->data));
@@ -55,7 +55,7 @@ void WANoise::init()
// generate noise keys (private & public)
ec_key_pair *pKeys;
- curve_generate_key_pair(g_plugin.pCtx, &pKeys);
+ curve_generate_key_pair(ppro->m_signalStore.CTX(), &pKeys);
auto *pPubKey = ec_key_pair_get_public(pKeys);
db_set_blob(0, ppro->m_szModuleName, DBKEY_NOISE_PUB, pPubKey->data, sizeof(pPubKey->data));
diff --git a/protocols/WhatsAppWeb/src/proto.h b/protocols/WhatsAppWeb/src/proto.h
index cbd766ea1c..b7792ec635 100644
--- a/protocols/WhatsAppWeb/src/proto.h
+++ b/protocols/WhatsAppWeb/src/proto.h
@@ -154,7 +154,8 @@ class MSignalStore
{
void init();
- signal_protocol_store_context *m_pContext;
+ signal_context *m_pContext;
+ signal_protocol_store_context *m_pStore;
public:
PROTO_INTERFACE *pProto;
@@ -177,6 +178,8 @@ public:
MSignalStore(PROTO_INTERFACE *_1, const char *_2);
~MSignalStore();
+ __forceinline signal_context *CTX() const { return m_pContext; }
+
MSignalSession *createSession(const CMStringA &szName, int deviceId);
MBinBuffer decryptSignalProto(const CMStringA &from, const char *pszType, const MBinBuffer &encrypted);
@@ -362,8 +365,6 @@ public:
struct CMPlugin : public ACCPROTOPLUGIN<WhatsAppProto>
{
- signal_context *pCtx = nullptr;
-
HNETLIBUSER hAvatarUser = nullptr;
HNETLIBCONN hAvatarConn = nullptr;
bool SaveFile(const char *pszUrl, PROTO_AVATAR_INFORMATION &ai);
diff --git a/protocols/WhatsAppWeb/src/server.cpp b/protocols/WhatsAppWeb/src/server.cpp
index f6ca1ef948..57dc3eae50 100644
--- a/protocols/WhatsAppWeb/src/server.cpp
+++ b/protocols/WhatsAppWeb/src/server.cpp
@@ -90,40 +90,31 @@ void WhatsAppProto::ServerThreadWorker()
while (true) {
MBinBuffer currPacket;
currPacket.assign(netbuf.data() + hdr.headerSize, hdr.payloadSize);
- currPacket.append("", 1); // add 0 to use strchr safely
- const char *start = currPacket.data();
-
switch (hdr.opCode) {
case 1: // json packet
- case 2: // binary packet
- // process a packet here
- {
- const char *pos = strchr(start, ',');
- if (pos != nullptr)
- pos++;
- else
- pos = start;
- size_t dataSize = hdr.payloadSize - size_t(pos - start);
-
- // try to decode
- if (hdr.opCode == 2 && hdr.payloadSize > 32)
- ProcessBinaryPacket(pos, dataSize);
- else {
- CMStringA szJson(pos, (int)dataSize);
-
- JSONNode root = JSONNode::parse(szJson);
- if (root) {
- debugLogA("JSON received:\n%s", start);
-
- CMStringA szPrefix(start, int(pos - start - 1));
- auto *pReq = m_arPacketQueue.find((WARequest *)&szPrefix);
- if (pReq != nullptr) {
- root << CHAR_PARAM("$id$", szPrefix);
- }
+ debugLogA("Text packet, skipping");
+ /*
+ currPacket.append("", 1); // add 0 to use strchr safely
+ CMStringA szJson(pos, (int)dataSize);
+
+ JSONNode root = JSONNode::parse(szJson);
+ if (root) {
+ debugLogA("JSON received:\n%s", start);
+
+ CMStringA szPrefix(start, int(pos - start - 1));
+ auto *pReq = m_arPacketQueue.find((WARequest *)&szPrefix);
+ if (pReq != nullptr) {
+ root << CHAR_PARAM("$id$", szPrefix);
}
}
}
+ */
+ break;
+
+ case 2: // binary packet
+ if (hdr.payloadSize > 32)
+ ProcessBinaryPacket(currPacket.data(), hdr.payloadSize);
break;
case 8: // close
@@ -132,7 +123,7 @@ void WhatsAppProto::ServerThreadWorker()
break;
default:
- Netlib_Dump(m_hServerConn, start, hdr.payloadSize, false, 0);
+ Netlib_Dump(m_hServerConn, currPacket.data(), hdr.payloadSize, false, 0);
}
netbuf.remove(hdr.headerSize + hdr.payloadSize);
diff --git a/protocols/WhatsAppWeb/src/signal.cpp b/protocols/WhatsAppWeb/src/signal.cpp
index b0547f69a8..467572737a 100644
--- a/protocols/WhatsAppWeb/src/signal.cpp
+++ b/protocols/WhatsAppWeb/src/signal.cpp
@@ -23,81 +23,57 @@ MSignalStore::MSignalStore(PROTO_INTERFACE *_1, const char *_2) :
prefix(_2),
arSessions(1, &CompareSessions)
{
- if (pProto->getDword(DBKEY_PREKEY_KEYID, 0xFFFF) == 0xFFFF) {
- // generate pre keys
- const unsigned int signed_pre_key_id = 1;
- pProto->setDword(DBKEY_PREKEY_KEYID, 1);
- pProto->setDword(DBKEY_PREKEY_NEXT_ID, 1);
- pProto->setDword(DBKEY_PREKEY_UPLOAD_ID, 1);
-
- // generate signed identity keys (private & public)
- ratchet_identity_key_pair *keyPair;
- signal_protocol_key_helper_generate_identity_key_pair(&keyPair, g_plugin.pCtx);
-
- auto *pPubKey = ratchet_identity_key_pair_get_public(keyPair);
- db_set_blob(0, pProto->m_szModuleName, DBKEY_SIGNED_IDENTITY_PUB, pPubKey->data, sizeof(pPubKey->data));
-
- auto *pPrivKey = ratchet_identity_key_pair_get_private(keyPair);
- db_set_blob(0, pProto->m_szModuleName, DBKEY_SIGNED_IDENTITY_PRIV, pPrivKey->data, sizeof(pPrivKey->data));
-
- session_signed_pre_key *signed_pre_key;
- signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, keyPair, signed_pre_key_id, time(0), g_plugin.pCtx);
- SIGNAL_UNREF(keyPair);
-
- signal_buffer *serialized_signed_pre_key;
- session_signed_pre_key_serialize(&serialized_signed_pre_key, signed_pre_key);
-
- ec_key_pair *pKeys = session_signed_pre_key_get_key_pair(signed_pre_key);
- pPubKey = ec_key_pair_get_public(pKeys);
- db_set_blob(0, pProto->m_szModuleName, DBKEY_PREKEY_PUB, pPubKey->data, sizeof(pPubKey->data));
+ init();
+}
- pPrivKey = ec_key_pair_get_private(pKeys);
- db_set_blob(0, pProto->m_szModuleName, DBKEY_PREKEY_PRIV, pPrivKey->data, sizeof(pPrivKey->data));
+MSignalStore::~MSignalStore()
+{
+ signal_protocol_store_context_destroy(m_pStore);
+ signal_context_destroy(m_pContext);
+}
- db_set_blob(0, pProto->m_szModuleName, DBKEY_PREKEY_SIGN, (void *)session_signed_pre_key_get_signature(signed_pre_key), (int)session_signed_pre_key_get_signature_len(signed_pre_key));
+/////////////////////////////////////////////////////////////////////////////////////////
- // generate and save pre keys set
- CMStringA szSetting;
- signal_protocol_key_helper_pre_key_list_node *keys_root;
- signal_protocol_key_helper_generate_pre_keys(&keys_root, 1, 20, g_plugin.pCtx);
- for (auto *it = keys_root; it; it = signal_protocol_key_helper_key_list_next(it)) {
- session_pre_key *pre_key = signal_protocol_key_helper_key_list_element(it);
- uint32_t pre_key_id = session_pre_key_get_id(pre_key);
- {
- signal_buffer *serialized_pre_key;
- session_pre_key_serialize(&serialized_pre_key, pre_key);
- szSetting.Format("PreKey%d", pre_key_id);
- db_set_blob(0, pProto->m_szModuleName, szSetting, signal_buffer_data(serialized_pre_key), (unsigned int)signal_buffer_len(serialized_pre_key));
- SIGNAL_UNREF(serialized_pre_key);
- }
+static void log_func(int level, const char *pmsg, size_t /*msgLen*/, void *pUserData)
+{
+ auto *pStore = (MSignalStore *)pUserData;
+ pStore->pProto->debugLogA("libsignal {%d}: %s", level, pmsg);
+}
- ec_key_pair *pre_key_pair = session_pre_key_get_key_pair(pre_key);
- pPubKey = ec_key_pair_get_public(pre_key_pair);
- szSetting.Format("PreKey%dPublic", pre_key_id);
- db_set_blob(0, pProto->m_szModuleName, szSetting, pPubKey->data, sizeof(pPubKey->data));
- }
- signal_protocol_key_helper_key_list_free(keys_root);
- }
+static int hmac_sha256_init(void **hmac_context, const uint8_t *key, size_t key_len, void *)
+{
+ HMAC_CTX *ctx = HMAC_CTX_new();
+ *hmac_context = ctx;
+ HMAC_Init(ctx, key, (int)key_len, EVP_sha256());
+ return 0;
+}
- // read resident data from database
- signedIdentity.pub = pProto->getBlob(DBKEY_SIGNED_IDENTITY_PUB);
- signedIdentity.priv = pProto->getBlob(DBKEY_SIGNED_IDENTITY_PRIV);
+static int hmac_sha256_update(void *hmac_context, const uint8_t *data, size_t data_len, void *)
+{
+ return HMAC_Update((HMAC_CTX *)hmac_context, data, data_len);
+}
- preKey.pub = pProto->getBlob(DBKEY_PREKEY_PUB);
- preKey.priv = pProto->getBlob(DBKEY_PREKEY_PRIV);
- preKey.keyid = pProto->getDword(DBKEY_PREKEY_KEYID);
- preKey.signature = pProto->getBlob(DBKEY_PREKEY_SIGN);
+static int hmac_sha256_final(void *hmac_context, signal_buffer **output, void *)
+{
+ BYTE data[200];
+ unsigned len = 0;
+ if (!HMAC_Final((HMAC_CTX *)hmac_context, data, &len))
+ return 1;
- // context cretion
- init();
+ *output = signal_buffer_create(data, len);
+ return 0;
}
-MSignalStore::~MSignalStore()
+static void hmac_sha256_cleanup(void *hmac_context, void *)
{
- signal_protocol_store_context_destroy(m_pContext);
+ HMAC_CTX_free((HMAC_CTX *)hmac_context);
}
-/////////////////////////////////////////////////////////////////////////////////////////
+static int random_func(uint8_t *pData, size_t size, void *)
+{
+ Utils_GetRandom(pData, size);
+ return 0;
+}
static int contains_session_func(const signal_protocol_address *address, void *user_data)
{
@@ -228,7 +204,7 @@ static int store_pre_key(uint32_t pre_key_id, uint8_t *record, size_t record_len
db_set_blob(0, pStore->pProto->m_szModuleName, szSetting, record, (unsigned int)record_len);
session_pre_key *prekey = nullptr;
- session_pre_key_deserialize(&prekey, record, record_len, g_plugin.pCtx); //TODO: handle error
+ session_pre_key_deserialize(&prekey, record, record_len, pStore->CTX()); //TODO: handle error
if (prekey) {
ec_key_pair *pre_key_pair = session_pre_key_get_key_pair(prekey);
signal_buffer *key_buf = nullptr;
@@ -248,37 +224,29 @@ static int contains_signed_pre_key(uint32_t signed_pre_key_id, void *user_data)
{
auto *pStore = (MSignalStore *)user_data;
- CMStringA szSetting(FORMAT, "%s_%d", "SignalSignedPreKey", signed_pre_key_id);
- DBVARIANT dbv = {};
- dbv.type = DBVT_BLOB;
- if (db_get(0, pStore->pProto->m_szModuleName, szSetting, &dbv))
- return 0;
-
- db_free(&dbv);
- return 1;
+ CMStringA szSetting(FORMAT, "%s%d", "SignedPreKey", signed_pre_key_id);
+ MBinBuffer blob(pStore->pProto->getBlob(szSetting));
+ return blob.data() != 0;
}
static int load_signed_pre_key(signal_buffer **record, uint32_t signed_pre_key_id, void *user_data)
{
auto *pStore = (MSignalStore *)user_data;
- CMStringA szSetting(FORMAT, "%s_%d", "SignalSignedPreKey", signed_pre_key_id);
- DBVARIANT dbv = {};
- dbv.type = DBVT_BLOB;
- if (db_get(0, pStore->pProto->m_szModuleName, szSetting, &dbv))
+ CMStringA szSetting(FORMAT, "%s%d", "SignedPreKey", signed_pre_key_id);
+ MBinBuffer blob(pStore->pProto->getBlob(szSetting));
+ if (blob.data() == 0)
return SG_ERR_INVALID_KEY_ID;
- *record = signal_buffer_create(dbv.pbVal, dbv.cpbVal);
- db_free(&dbv);
+ *record = signal_buffer_create(blob.data(), blob.length());
return SG_SUCCESS; //key exist and succesfully loaded
-
}
static int store_signed_pre_key(uint32_t signed_pre_key_id, uint8_t *record, size_t record_len, void *user_data)
{
auto *pStore = (MSignalStore *)user_data;
- CMStringA szSetting(FORMAT, "%s_%d", "SignalSignedPreKey", signed_pre_key_id);
+ CMStringA szSetting(FORMAT, "%s%d", "SignedPreKey", signed_pre_key_id);
db_set_blob(0, pStore->pProto->m_szModuleName, szSetting, record, (unsigned int)record_len);
return 0;
}
@@ -287,33 +255,36 @@ static int remove_signed_pre_key(uint32_t signed_pre_key_id, void *user_data)
{
auto *pStore = (MSignalStore *)user_data;
- CMStringA szSetting(FORMAT, "%s_%d", "SignalSignedPreKey", signed_pre_key_id);
+ CMStringA szSetting(FORMAT, "%s%d", "SignedPreKey", signed_pre_key_id);
pStore->pProto->delSetting(szSetting);
return 0;
}
-int get_identity_key_pair(signal_buffer **public_data, signal_buffer **private_data, void *user_data)
+static int get_identity_key_pair(signal_buffer **public_data, signal_buffer **private_data, void *user_data)
{
auto *pStore = (MSignalStore *)user_data;
- *public_data = signal_buffer_create((uint8_t *)pStore->preKey.pub.data(), (int)pStore->preKey.pub.length());
+ MBinBuffer buf;
+ buf.append(KEY_BUNDLE_TYPE, 1);
+ buf.append(pStore->preKey.pub);
+ *public_data = signal_buffer_create(buf.data(), (int)buf.length());
+
*private_data = signal_buffer_create((uint8_t *)pStore->preKey.priv.data(), (int)pStore->preKey.priv.length());
return 0;
}
-int get_local_registration_id(void *user_data, uint32_t *registration_id)
+static int get_local_registration_id(void *user_data, uint32_t *registration_id)
{
auto *pStore = (MSignalStore *)user_data;
*registration_id = pStore->pProto->getDword(DBKEY_REG_ID);
return 0;
}
-int save_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data)
+static int save_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data)
{
auto *pStore = (MSignalStore *)user_data;
CMStringA szSetting(FORMAT, "%s_%s_%d", "SignalIdentity", CMStringA(address->name, (int)address->name_len).c_str(), address->device_id);
-
if (key_data != nullptr)
db_set_blob(0, pStore->pProto->m_szModuleName, szSetting, key_data, (unsigned int)key_len); //TODO: check return value
else
@@ -321,14 +292,94 @@ int save_identity(const signal_protocol_address *address, uint8_t *key_data, siz
return 0;
}
-int is_trusted_identity(const signal_protocol_address * /*address*/, uint8_t * /*key_data*/, size_t /*key_len*/, void * /*user_data*/)
+static int is_trusted_identity(const signal_protocol_address * /*address*/, uint8_t * /*key_data*/, size_t /*key_len*/, void * /*user_data*/)
{
return 1;
}
void MSignalStore::init()
{
- signal_protocol_store_context_create(&m_pContext, g_plugin.pCtx);
+ signal_context_create(&m_pContext, this);
+ signal_context_set_log_function(m_pContext, log_func);
+
+ signal_crypto_provider prov;
+ memset(&prov, 0xFF, sizeof(prov));
+ prov.hmac_sha256_init_func = hmac_sha256_init;
+ prov.hmac_sha256_final_func = hmac_sha256_final;
+ prov.hmac_sha256_update_func = hmac_sha256_update;
+ prov.hmac_sha256_cleanup_func = hmac_sha256_cleanup;
+ prov.random_func = random_func;
+ signal_context_set_crypto_provider(m_pContext, &prov);
+
+ // default values calculation
+ if (pProto->getDword(DBKEY_PREKEY_NEXT_ID, 0xFFFF) == 0xFFFF) {
+ pProto->setDword(DBKEY_PREKEY_NEXT_ID, 1);
+ pProto->setDword(DBKEY_PREKEY_UPLOAD_ID, 1);
+
+ // generate signed identity keys (private & public)
+ ratchet_identity_key_pair *keyPair;
+ signal_protocol_key_helper_generate_identity_key_pair(&keyPair, m_pContext);
+
+ auto *pPubKey = ratchet_identity_key_pair_get_public(keyPair);
+ db_set_blob(0, pProto->m_szModuleName, DBKEY_SIGNED_IDENTITY_PUB, pPubKey->data, sizeof(pPubKey->data));
+
+ auto *pPrivKey = ratchet_identity_key_pair_get_private(keyPair);
+ db_set_blob(0, pProto->m_szModuleName, DBKEY_SIGNED_IDENTITY_PRIV, pPrivKey->data, sizeof(pPrivKey->data));
+
+ session_signed_pre_key *signed_pre_key;
+ signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, keyPair, 1, time(0), m_pContext);
+ SIGNAL_UNREF(keyPair);
+
+ signal_buffer *my_prekey;
+ session_signed_pre_key_serialize(&my_prekey, signed_pre_key);
+ db_set_blob(0, pProto->m_szModuleName, DBKEY_PREKEY, my_prekey->data, (int)my_prekey->len);
+ SIGNAL_UNREF(my_prekey);
+
+ // generate and save pre keys set
+ CMStringA szSetting;
+ signal_protocol_key_helper_pre_key_list_node *keys_root;
+ signal_protocol_key_helper_generate_pre_keys(&keys_root, 1, 20, m_pContext);
+ for (auto *it = keys_root; it; it = signal_protocol_key_helper_key_list_next(it)) {
+ session_pre_key *pre_key = signal_protocol_key_helper_key_list_element(it);
+ uint32_t pre_key_id = session_pre_key_get_id(pre_key);
+ {
+ signal_buffer *serialized_pre_key;
+ session_pre_key_serialize(&serialized_pre_key, pre_key);
+ szSetting.Format("PreKey%d", pre_key_id);
+ db_set_blob(0, pProto->m_szModuleName, szSetting, signal_buffer_data(serialized_pre_key), (unsigned int)signal_buffer_len(serialized_pre_key));
+ SIGNAL_UNREF(serialized_pre_key);
+ }
+
+ ec_key_pair *pre_key_pair = session_pre_key_get_key_pair(pre_key);
+ pPubKey = ec_key_pair_get_public(pre_key_pair);
+ szSetting.Format("PreKey%dPublic", pre_key_id);
+ db_set_blob(0, pProto->m_szModuleName, szSetting, pPubKey->data, sizeof(pPubKey->data));
+ }
+ signal_protocol_key_helper_key_list_free(keys_root);
+ SIGNAL_UNREF(signed_pre_key);
+ }
+
+ // read resident data from database
+ signedIdentity.pub = pProto->getBlob(DBKEY_SIGNED_IDENTITY_PUB);
+ signedIdentity.priv = pProto->getBlob(DBKEY_SIGNED_IDENTITY_PRIV);
+
+ MBinBuffer blob(pProto->getBlob(DBKEY_PREKEY));
+ session_signed_pre_key *signed_pre_key;
+ session_signed_pre_key_deserialize(&signed_pre_key, blob.data(), blob.length(), m_pContext);
+
+ ec_key_pair *pKeys = session_signed_pre_key_get_key_pair(signed_pre_key);
+ auto *pPubKey = ec_key_pair_get_public(pKeys);
+ preKey.pub.assign(pPubKey->data, sizeof(pPubKey->data));
+
+ auto *pPrivKey = ec_key_pair_get_private(pKeys);
+ preKey.priv.assign(pPrivKey->data, sizeof(pPrivKey->data));
+
+ preKey.signature.assign(session_signed_pre_key_get_signature(signed_pre_key), session_signed_pre_key_get_signature_len(signed_pre_key));
+ preKey.keyid = session_signed_pre_key_get_id(signed_pre_key);
+ SIGNAL_UNREF(signed_pre_key);
+
+ // create store with callbacks
+ signal_protocol_store_context_create(&m_pStore, m_pContext);
signal_protocol_session_store ss;
ss.contains_session_func = &contains_session_func;
@@ -339,7 +390,7 @@ void MSignalStore::init()
ss.load_session_func = &load_session_func;
ss.store_session_func = &store_session_func;
ss.user_data = this;
- signal_protocol_store_context_set_session_store(m_pContext, &ss);
+ signal_protocol_store_context_set_session_store(m_pStore, &ss);
signal_protocol_pre_key_store sp;
sp.contains_pre_key = &contains_pre_key;
@@ -348,7 +399,7 @@ void MSignalStore::init()
sp.remove_pre_key = &remove_pre_key;
sp.store_pre_key = &store_pre_key;
sp.user_data = this;
- signal_protocol_store_context_set_pre_key_store(m_pContext, &sp);
+ signal_protocol_store_context_set_pre_key_store(m_pStore, &sp);
signal_protocol_signed_pre_key_store ssp;
ssp.contains_signed_pre_key = &contains_signed_pre_key;
@@ -357,7 +408,7 @@ void MSignalStore::init()
ssp.remove_signed_pre_key = &remove_signed_pre_key;
ssp.store_signed_pre_key = &store_signed_pre_key;
ssp.user_data = this;
- signal_protocol_store_context_set_signed_pre_key_store(m_pContext, &ssp);
+ signal_protocol_store_context_set_signed_pre_key_store(m_pStore, &ssp);
signal_protocol_identity_key_store sip;
sip.destroy_func = &destroy_func;
@@ -366,7 +417,7 @@ void MSignalStore::init()
sip.is_trusted_identity = &is_trusted_identity;
sip.save_identity = &save_identity;
sip.user_data = this;
- signal_protocol_store_context_set_identity_key_store(m_pContext, &sip);
+ signal_protocol_store_context_set_identity_key_store(m_pStore, &sip);
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -403,7 +454,7 @@ MSignalSession *MSignalStore::createSession(const CMStringA &szName, int deviceI
}
if (pSession->cipher == nullptr)
- if (session_cipher_create(&pSession->cipher, m_pContext, &pSession->address, g_plugin.pCtx) < 0)
+ if (session_cipher_create(&pSession->cipher, m_pStore, &pSession->address, m_pContext) < 0)
throw "session_cipher_create failure";
return pSession;
@@ -423,7 +474,7 @@ MBinBuffer MSignalStore::decryptSignalProto(const CMStringA &from, const char *p
memcpy(&pIdentityKey.data, signedIdentity.pub.data(), 32);
pre_key_signal_message *pMsg;
- if (pre_key_signal_message_deserialize(&pMsg, (BYTE *)encrypted.data(), encrypted.length(), g_plugin.pCtx) < 0)
+ if (pre_key_signal_message_deserialize(&pMsg, (BYTE *)encrypted.data(), encrypted.length(), m_pContext) < 0)
throw "unable to deserialize prekey message";
if (session_cipher_decrypt_pre_key_signal_message(pSession->getCipher(), pMsg, 0, &result) < 0)
@@ -433,7 +484,7 @@ MBinBuffer MSignalStore::decryptSignalProto(const CMStringA &from, const char *p
}
else {
signal_message *pMsg;
- if (signal_message_deserialize(&pMsg, (BYTE *)encrypted.data(), encrypted.length(), g_plugin.pCtx) < 0)
+ if (signal_message_deserialize(&pMsg, (BYTE *)encrypted.data(), encrypted.length(), m_pContext) < 0)
throw "unable to deserialize signal message";
if (session_cipher_decrypt_signal_message(pSession->getCipher(), pMsg, 0, &result) < 0)
diff --git a/protocols/WhatsAppWeb/src/stdafx.h b/protocols/WhatsAppWeb/src/stdafx.h
index 29a708c101..bbcda15825 100644
--- a/protocols/WhatsAppWeb/src/stdafx.h
+++ b/protocols/WhatsAppWeb/src/stdafx.h
@@ -105,6 +105,5 @@ struct ec_private_key : public signal_type_base
#include "utils.h"
#include "proto.h"
#include "resource.h"
-#include "pmsg.pb.h"
#pragma comment(lib, "libcrypto.lib")
diff --git a/protocols/WhatsAppWeb/src/utils.cpp b/protocols/WhatsAppWeb/src/utils.cpp
index fdf2721c17..c2b62ca5a1 100644
--- a/protocols/WhatsAppWeb/src/utils.cpp
+++ b/protocols/WhatsAppWeb/src/utils.cpp
@@ -42,7 +42,7 @@ WAJid::WAJid(const char *pszJid)
}
bool WAJid::isUser() const
-{ return server == S_WHATSAPP_NET;
+{ return server == "s.whatsapp.net";
}
bool WAJid::isGroup() const