summaryrefslogtreecommitdiff
path: root/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp')
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp89
1 files changed, 89 insertions, 0 deletions
diff --git a/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp b/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp
new file mode 100644
index 0000000000..f4741729a7
--- /dev/null
+++ b/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp
@@ -0,0 +1,89 @@
+/*
+ * WALogin.cpp
+ *
+ * Created on: 26/06/2012
+ * Author: Antonio
+ */
+
+#include "../common.h" // #TODO Remove Miranda-dependency
+
+#include "WALogin.h"
+#include "ByteArray.h"
+#include "ProtocolTreeNode.h"
+#include "WAException.h"
+
+using namespace Utilities;
+
+KeyStream::KeyStream(unsigned char* _key, unsigned char* _keyMac) :
+ seq(0)
+{
+ memcpy(key, _key, 20);
+ memcpy(keyMac, _keyMac, 20);
+
+ RC4_set_key(&this->rc4, 20, this->key);
+
+ unsigned char drop[768];
+ RC4(&this->rc4, sizeof(drop), drop, drop);
+
+ HMAC_CTX_init(&hmac);
+}
+
+KeyStream::~KeyStream()
+{
+ HMAC_CTX_cleanup(&hmac);
+}
+
+void KeyStream::keyFromPasswordAndNonce(const std::string& pass, const std::vector<unsigned char>& nonce, unsigned char *out)
+{
+ size_t cbSize = nonce.size();
+
+ uint8_t *pNonce = (uint8_t*)_alloca(cbSize + 1);
+ memcpy(pNonce, nonce.data(), cbSize);
+
+ for (int i = 0; i < 4; i++) {
+ pNonce[cbSize] = i + 1;
+ PKCS5_PBKDF2_HMAC_SHA1(pass.data(), (int)pass.size(), pNonce, (int)cbSize+1, 2, 20, out + i*20);
+ }
+}
+
+void KeyStream::decodeMessage(unsigned char* buffer, int macOffset, int offset, const int length)
+{
+ unsigned char digest[20];
+ this->hmacsha1(buffer + offset, length, digest);
+
+ if (memcmp(&buffer[macOffset], digest, 4))
+ throw WAException("invalid MAC", WAException::CORRUPT_STREAM_EX, 0);
+
+ unsigned char* out = (unsigned char*)_alloca(length);
+ RC4(&this->rc4, length, buffer + offset, out);
+ memcpy(buffer + offset, out, length);
+}
+
+void KeyStream::encodeMessage(unsigned char* buffer, int macOffset, int offset, const int length)
+{
+ unsigned char* out = (unsigned char*)_alloca(length);
+ RC4(&this->rc4, length, buffer + offset, out);
+ memcpy(buffer + offset, out, length);
+
+ unsigned char digest[20];
+ this->hmacsha1(buffer + offset, length, digest);
+ memcpy(buffer + macOffset, digest, 4);
+}
+
+void KeyStream::hmacsha1(unsigned char* text, int textLength, unsigned char *out)
+{
+ HMAC_Init(&hmac, this->keyMac, 20, EVP_sha1());
+ HMAC_Update(&hmac, text, textLength);
+
+ unsigned char hmacInt[4];
+ hmacInt[0] = (this->seq >> 24);
+ hmacInt[1] = (this->seq >> 16);
+ hmacInt[2] = (this->seq >> 8);
+ hmacInt[3] = (this->seq);
+ HMAC_Update(&hmac, hmacInt, sizeof(hmacInt));
+
+ unsigned int mdLength;
+ HMAC_Final(&hmac, out, &mdLength);
+
+ this->seq++;
+}