diff options
author | George Hazan <ghazan@miranda.im> | 2022-10-02 21:48:11 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2022-10-02 21:48:11 +0300 |
commit | 0a59ec1d5a3e02cd8bc04933ae06c038d05c6a34 (patch) | |
tree | dec44acb6fba8fb34d8ab7377c2ee226c0ed80ed /protocols/WhatsAppWeb/src | |
parent | 0f65b85e68f7ad9068b0e20f0cade4c4c41c454e (diff) |
WhatsApp: prekeys upload
Diffstat (limited to 'protocols/WhatsAppWeb/src')
-rw-r--r-- | protocols/WhatsAppWeb/src/iq.cpp | 47 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/noise.cpp | 25 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/proto.h | 1 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/server.cpp | 12 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/utils.h | 3 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/wanode.cpp | 17 |
6 files changed, 86 insertions, 19 deletions
diff --git a/protocols/WhatsAppWeb/src/iq.cpp b/protocols/WhatsAppWeb/src/iq.cpp index 287fbe54e5..287257594a 100644 --- a/protocols/WhatsAppWeb/src/iq.cpp +++ b/protocols/WhatsAppWeb/src/iq.cpp @@ -7,6 +7,53 @@ Copyright © 2019-22 George Hazan #include "stdafx.h" +static int sttEnumPrekeys(const char *szSetting, void *param) +{ + std::vector<int> *list = (std::vector<int> *)param; + if (!memcmp(szSetting, "PreKey", 6) && !strstr(szSetting, "Public")) + list->push_back(atoi(szSetting + 6)); + return 0; +} + +void WhatsAppProto::OnIqCountPrekeys(const WANode &node) +{ + std::vector<int> ids; + db_enum_settings(0, sttEnumPrekeys, m_szModuleName, &ids); + + int iCount = node.getChild("count")->getAttrInt("value"); + if (iCount >= ids.size()) { + debugLogA("Prekeys are already uploaded"); + return; + } + + WANode iq("iq"); + iq << CHAR_PARAM("xmlns", "encrypt") << CHAR_PARAM("type", "set") << CHAR_PARAM("to", S_WHATSAPP_NET) << CHAR_PARAM("id", generateMessageId()); + + auto regId = encodeBigEndian(getDword(DBKEY_REG_ID)); + iq.addChild("registration")->content.append(regId.c_str(), regId.size()); + + iq.addChild("type")->content.append(KEY_BUNDLE_TYPE, 1); + iq.addChild("identity")->content.append(m_noise->signedIdentity.pub); + + auto *n = iq.addChild("list"); + for (auto &keyId : ids) { + auto *nKey = n->addChild("key"); + + auto encId = encodeBigEndian(keyId, 3); + nKey->addChild("id")->content.append(encId.c_str(), encId.size()); + nKey->addChild("value")->content.append(getBlob(CMStringA(FORMAT, "PreKey%dPublic", keyId))); + } + + auto *skey = n->addChild("skey"); + + auto encId = encodeBigEndian(m_noise->preKey.keyid, 3); + skey->addChild("id")->content.append(encId.c_str(), encId.size()); + skey->addChild("value")->content.append(m_noise->preKey.pub); + skey->addChild("signature")->content.append(m_noise->preKey.signature); + + WSSendNode(iq); +} + ///////////////////////////////////////////////////////////////////////////////////////// void WhatsAppProto::OnStreamError(const WANode &node) diff --git a/protocols/WhatsAppWeb/src/noise.cpp b/protocols/WhatsAppWeb/src/noise.cpp index 30449aa09d..ecc7921b2d 100644 --- a/protocols/WhatsAppWeb/src/noise.cpp +++ b/protocols/WhatsAppWeb/src/noise.cpp @@ -43,9 +43,6 @@ void WANoise::init() { // no data? generate them if (ppro->getDword(DBKEY_REG_ID, 0xFFFF) == 0xFFFF) { - ppro->setDword(DBKEY_PREKEY_NEXT_ID, 1); - ppro->setDword(DBKEY_PREKEY_UPLOAD_ID, 1); - // generate registration id uint32_t regId; Utils_GetRandom(®Id, sizeof(regId)); @@ -66,21 +63,25 @@ void WANoise::init() auto *pPrivKey = ec_key_pair_get_private(pKeys); db_set_blob(0, ppro->m_szModuleName, DBKEY_NOISE_PRIV, pPrivKey->data, sizeof(pPrivKey->data)); ec_key_pair_destroy(pKeys); + } + + if (ppro->getDword(DBKEY_PREKEY_KEYID, 0xFFFF) == 0xFFFF) { + // generate pre keys + const unsigned int signed_pre_key_id = 1; + ppro->setDword(DBKEY_PREKEY_KEYID, 1); + ppro->setDword(DBKEY_PREKEY_NEXT_ID, 1); + ppro->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); - pPubKey = ratchet_identity_key_pair_get_public(keyPair); + auto *pPubKey = ratchet_identity_key_pair_get_public(keyPair); db_set_blob(0, ppro->m_szModuleName, DBKEY_SIGNED_IDENTITY_PUB, pPubKey->data, sizeof(pPubKey->data)); - pPrivKey = ratchet_identity_key_pair_get_private(keyPair); + auto *pPrivKey = ratchet_identity_key_pair_get_private(keyPair); db_set_blob(0, ppro->m_szModuleName, DBKEY_SIGNED_IDENTITY_PRIV, pPrivKey->data, sizeof(pPrivKey->data)); - // generate pre keys - const unsigned int signed_pre_key_id = 1; - ppro->setDword(DBKEY_PREKEY_KEYID, 1); - 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); @@ -88,7 +89,7 @@ void WANoise::init() signal_buffer *serialized_signed_pre_key; session_signed_pre_key_serialize(&serialized_signed_pre_key, signed_pre_key); - pKeys = session_signed_pre_key_get_key_pair(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, ppro->m_szModuleName, DBKEY_PREKEY_PUB, pPubKey->data, sizeof(pPubKey->data)); @@ -100,7 +101,7 @@ void WANoise::init() // 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, 0, 20, g_plugin.pCtx); + 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); @@ -115,7 +116,7 @@ void WANoise::init() 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, ppro->m_szModuleName, szSetting, pPrivKey->data, sizeof(pPrivKey->data)); + db_set_blob(0, ppro->m_szModuleName, szSetting, pPubKey->data, sizeof(pPubKey->data)); } signal_protocol_key_helper_key_list_free(keys_root); } diff --git a/protocols/WhatsAppWeb/src/proto.h b/protocols/WhatsAppWeb/src/proto.h index 72ac5bede9..ff1d4fe18e 100644 --- a/protocols/WhatsAppWeb/src/proto.h +++ b/protocols/WhatsAppWeb/src/proto.h @@ -205,6 +205,7 @@ class WhatsAppProto : public PROTO<WhatsAppProto> void OnProcessHandshake(const void *pData, int cbLen); void InitPersistentHandlers(); + void OnIqCountPrekeys(const WANode &node); void OnIqPairDevice(const WANode &node); void OnIqPairSuccess(const WANode &node); void OnIqResult(const WANode &node); diff --git a/protocols/WhatsAppWeb/src/server.cpp b/protocols/WhatsAppWeb/src/server.cpp index 7cbdba3a20..cf53d72896 100644 --- a/protocols/WhatsAppWeb/src/server.cpp +++ b/protocols/WhatsAppWeb/src/server.cpp @@ -80,9 +80,9 @@ void WhatsAppProto::ServerThreadWorker() if (!WSReadPacket(hdr, netbuf)) break; - // debugLogA("Got packet: buffer = %d, opcode = %d, headerSize = %d, payloadSize = %d, final = %d, masked = %d", - // netbuf.length(), hdr.opCode, hdr.headerSize, hdr.payloadSize, hdr.bIsFinal, hdr.bIsMasked); - // Netlib_Dump(m_hServerConn, netbuf.data(), netbuf.length(), false, 0); + debugLogA("Got packet: buffer = %d, opcode = %d, headerSize = %d, payloadSize = %d, final = %d, masked = %d", + netbuf.length(), hdr.opCode, hdr.headerSize, hdr.payloadSize, hdr.bIsFinal, hdr.bIsMasked); + Netlib_Dump(m_hServerConn, netbuf.data(), netbuf.length(), false, 0); m_lastRecvTime = time(0); @@ -235,6 +235,12 @@ void WhatsAppProto::OnLoggedIn() m_iStatus = m_iDesiredStatus; m_impl.m_keepAlive.Start(1000); + + // retrieve loaded prekeys + WANode iq("iq"); + iq << CHAR_PARAM("id", generateMessageId()) << CHAR_PARAM("xmlns", "encrypt") << CHAR_PARAM("type", "get") << CHAR_PARAM("to", S_WHATSAPP_NET); + iq.addChild("count"); + WSSendNode(iq, &WhatsAppProto::OnIqCountPrekeys); } void WhatsAppProto::OnLoggedOut(void) diff --git a/protocols/WhatsAppWeb/src/utils.h b/protocols/WhatsAppWeb/src/utils.h index e517301b86..292a8e7011 100644 --- a/protocols/WhatsAppWeb/src/utils.h +++ b/protocols/WhatsAppWeb/src/utils.h @@ -39,7 +39,8 @@ public: void addAttr(const char *pszName, const char *pszValue); void addAttr(const char *pszName, int iValue); - const char* getAttr(const char *pszName) const; + int getAttrInt(const char *pszName) const; + const char *getAttr(const char *pszName) const; CMStringA getBody() const; diff --git a/protocols/WhatsAppWeb/src/wanode.cpp b/protocols/WhatsAppWeb/src/wanode.cpp index f3d4053e7d..518c29d9dd 100644 --- a/protocols/WhatsAppWeb/src/wanode.cpp +++ b/protocols/WhatsAppWeb/src/wanode.cpp @@ -43,13 +43,24 @@ WANode::~WANode() const char *WANode::getAttr(const char *pszName) const { - for (auto &p : attrs) - if (p->name == pszName) - return p->value.c_str(); + if (this != nullptr) + for (auto &p : attrs) + if (p->name == pszName) + return p->value.c_str(); return nullptr; } +int WANode::getAttrInt(const char *pszName) const +{ + if (this != nullptr) + for (auto &p : attrs) + if (p->name == pszName) + return atoi(p->value.c_str()); + + return 0; +} + void WANode::addAttr(const char *pszName, const char *pszValue) { attrs.insert(new Attr(pszName, pszValue)); |