summaryrefslogtreecommitdiff
path: root/protocols/WhatsAppWeb/src
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/WhatsAppWeb/src')
-rw-r--r--protocols/WhatsAppWeb/src/noise.cpp10
-rw-r--r--protocols/WhatsAppWeb/src/utils.cpp99
-rw-r--r--protocols/WhatsAppWeb/src/utils.h6
3 files changed, 106 insertions, 9 deletions
diff --git a/protocols/WhatsAppWeb/src/noise.cpp b/protocols/WhatsAppWeb/src/noise.cpp
index 207d53d56a..d5d891d878 100644
--- a/protocols/WhatsAppWeb/src/noise.cpp
+++ b/protocols/WhatsAppWeb/src/noise.cpp
@@ -145,17 +145,9 @@ void WANoise::finish()
void WANoise::deriveKey(const void *pData, size_t cbLen, MBinBuffer &write, MBinBuffer &read)
{
- auto *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
- EVP_PKEY_derive_init(pctx);
- EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256());
- EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt.data(), (int)salt.length());
- EVP_PKEY_CTX_set1_hkdf_key(pctx, pData, (int)cbLen);
-
size_t outlen = 64;
uint8_t out[64];
- EVP_PKEY_derive(pctx, out, &outlen);
-
- EVP_PKEY_CTX_free(pctx);
+ HKDF(EVP_sha256(), (BYTE *)salt.data(), (int)salt.length(), (BYTE *)pData, (int)cbLen, (BYTE *)"", 0, out, outlen);
write.assign(out, 32);
read.assign(out + 32, 32);
diff --git a/protocols/WhatsAppWeb/src/utils.cpp b/protocols/WhatsAppWeb/src/utils.cpp
index a584d2431c..99393d65fc 100644
--- a/protocols/WhatsAppWeb/src/utils.cpp
+++ b/protocols/WhatsAppWeb/src/utils.cpp
@@ -648,3 +648,102 @@ void generateIV(uint8_t *iv, int &pVar)
pVar++;
}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
+ const unsigned char *salt, size_t salt_len,
+ const unsigned char *key, size_t key_len,
+ unsigned char *prk, size_t *prk_len)
+{
+ unsigned int tmp_len;
+
+ if (!HMAC(evp_md, salt, salt_len, key, key_len, prk, &tmp_len))
+ return NULL;
+
+ *prk_len = tmp_len;
+ return prk;
+}
+
+static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
+ const unsigned char *prk, size_t prk_len,
+ const unsigned char *info, size_t info_len,
+ unsigned char *okm, size_t okm_len)
+{
+ HMAC_CTX *hmac;
+ unsigned char *ret = NULL;
+
+ unsigned int i;
+
+ unsigned char prev[EVP_MAX_MD_SIZE];
+
+ size_t done_len = 0, dig_len = EVP_MD_size(evp_md);
+
+ size_t n = okm_len / dig_len;
+ if (okm_len % dig_len)
+ n++;
+
+ if (n > 255 || okm == NULL)
+ return NULL;
+
+ if ((hmac = HMAC_CTX_new()) == NULL)
+ return NULL;
+
+ if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
+ goto err;
+
+ for (i = 1; i <= n; i++) {
+ size_t copy_len;
+ const unsigned char ctr = i;
+
+ if (i > 1) {
+ if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
+ goto err;
+
+ if (!HMAC_Update(hmac, prev, dig_len))
+ goto err;
+ }
+
+ if (!HMAC_Update(hmac, info, info_len))
+ goto err;
+
+ if (!HMAC_Update(hmac, &ctr, 1))
+ goto err;
+
+ if (!HMAC_Final(hmac, prev, NULL))
+ goto err;
+
+ copy_len = (done_len + dig_len > okm_len) ?
+ okm_len - done_len :
+ dig_len;
+
+ memcpy(okm + done_len, prev, copy_len);
+
+ done_len += copy_len;
+ }
+ ret = okm;
+
+err:
+ OPENSSL_cleanse(prev, sizeof(prev));
+ HMAC_CTX_free(hmac);
+ return ret;
+}
+
+unsigned char* HKDF(const EVP_MD *evp_md,
+ const unsigned char *salt, size_t salt_len,
+ const unsigned char *key, size_t key_len,
+ const unsigned char *info, size_t info_len,
+ unsigned char *okm, size_t okm_len)
+{
+ unsigned char prk[EVP_MAX_MD_SIZE];
+ unsigned char *ret;
+ size_t prk_len;
+
+ if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, &prk_len))
+ return NULL;
+
+ ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
+ OPENSSL_cleanse(prk, sizeof(prk));
+
+ return ret;
+}
diff --git a/protocols/WhatsAppWeb/src/utils.h b/protocols/WhatsAppWeb/src/utils.h
index c05dbd5410..151f3adffd 100644
--- a/protocols/WhatsAppWeb/src/utils.h
+++ b/protocols/WhatsAppWeb/src/utils.h
@@ -104,3 +104,9 @@ public:
std::string encodeBigEndian(uint32_t num, size_t len = sizeof(uint32_t));
void generateIV(uint8_t *iv, int &pVar);
+
+unsigned char* HKDF(const EVP_MD *evp_md,
+ const unsigned char *salt, size_t salt_len,
+ const unsigned char *key, size_t key_len,
+ const unsigned char *info, size_t info_len,
+ unsigned char *okm, size_t okm_len);