From 2292ef20cf0378346f4fa857ca7cdc501c52794d Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sat, 15 Oct 2022 19:22:12 +0300 Subject: Jabber: OMEMO + file transfers --- protocols/JabberG/src/jabber_ft.cpp | 52 +++++++++++++++++++++++++++++++--- protocols/JabberG/src/jabber_omemo.cpp | 19 ++++++------- 2 files changed, 56 insertions(+), 15 deletions(-) (limited to 'protocols/JabberG/src') diff --git a/protocols/JabberG/src/jabber_ft.cpp b/protocols/JabberG/src/jabber_ft.cpp index 0437824f2d..60faeb53c4 100644 --- a/protocols/JabberG/src/jabber_ft.cpp +++ b/protocols/JabberG/src/jabber_ft.cpp @@ -139,7 +139,10 @@ void CJabberProto::FtInitiate(filetransfer *ft) pwszContentType = "application/octet-stream"; char szSize[100]; - _i64toa(st.st_size, szSize, 10); + int tsize = st.st_size; + if (m_bUseOMEMO && OmemoIsEnabled(ft->std.hContact) && !isChatRoom(ft->std.hContact)) + tsize += 16; + _i64toa(tsize, szSize, 10); XmlNodeIq iq(AddIQ(&CJabberProto::OnHttpSlotAllocated, JABBER_IQ_TYPE_GET, szUploadService, ft)); if (getByte("HttpUploadVer")) { @@ -692,9 +695,42 @@ LBL_Fail: goto LBL_Fail; } - nlhr.dataLength = _filelength(fileId); - nlhr.pData = new char[nlhr.dataLength]; - _read(fileId, nlhr.pData, nlhr.dataLength); + unsigned char key[32], iv[12], tag[16]; + bool enOmemo = m_bUseOMEMO && OmemoIsEnabled(ft->std.hContact) && !isChatRoom(ft->std.hContact); + if (enOmemo) { + Utils_GetRandom(key, _countof(key)); + Utils_GetRandom(iv, _countof(iv)); + + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, _countof(iv), nullptr); + EVP_EncryptInit(ctx, EVP_aes_256_gcm(), key, iv); + + int tmp_len = 0, outl; + //EVP_EncryptUpdate(ctx, nullptr, &outl, aad, _countof(aad)); + unsigned char *out = (unsigned char*)mir_alloc(_filelength(fileId) + _countof(key) - 1 + _countof(tag)); + unsigned char *in = (unsigned char*)mir_alloc(1024 * 1024); + for (;;) { + int inl = _read(fileId, in, 1024 * 1024); + if(inl == 0) + break; + EVP_EncryptUpdate(ctx, out + tmp_len, &outl, in, inl); + tmp_len += outl; + } + mir_free(in); + + EVP_EncryptFinal(ctx, out + tmp_len, &outl); + tmp_len += outl; + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, _countof(tag), tag); + EVP_CIPHER_CTX_free(ctx); + + memcpy(out + tmp_len, tag, _countof(tag)); + nlhr.dataLength = tmp_len + _countof(tag); + nlhr.pData = (char*)out; + } else { + nlhr.dataLength = _filelength(fileId); + nlhr.pData = new char[nlhr.dataLength]; + _read(fileId, nlhr.pData, nlhr.dataLength); + } _close(fileId); NETLIBHTTPREQUEST *res = Netlib_HttpTransaction(m_hNetlibUser, &nlhr); @@ -723,6 +759,14 @@ LBL_Fail: else szMessage = szUrl; + if (enOmemo) { + int i = szMessage.Find("://"); + char szIv[2*_countof(iv) + 1], szKey[2*_countof(key) + 1]; + bin2hex(iv, _countof(iv), szIv); + bin2hex(key, _countof(key), szKey); + szMessage.Format("aesgcm%s#%s%s", szMessage.Mid(i).c_str(), szIv, szKey); + } + if (m_bEmbraceUrls && ProtoGetAvatarFormat(_A2T(szMessage)) != PA_FORMAT_UNKNOWN) { szMessage.Insert(0, "[img]"); szMessage.Append("[/img]"); diff --git a/protocols/JabberG/src/jabber_omemo.cpp b/protocols/JabberG/src/jabber_omemo.cpp index ac80f8dd5b..43195cc1f5 100644 --- a/protocols/JabberG/src/jabber_omemo.cpp +++ b/protocols/JabberG/src/jabber_omemo.cpp @@ -1991,24 +1991,20 @@ int CJabberProto::OmemoEncryptMessage(XmlNode &msg, const char *msg_text, MCONTA unsigned char key[16], iv[12], tag[16] /*, aad[48]*/; Utils_GetRandom(key, _countof(key)); Utils_GetRandom(iv, _countof(iv)); - Utils_GetRandom(tag, _countof(tag)); + //Utils_GetRandom(aad, _countof(aad)); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, _countof(iv), nullptr); EVP_EncryptInit(ctx, cipher, key, iv); - char *out; + const size_t inl = strlen(msg_text); int tmp_len = 0, outl; //EVP_EncryptUpdate(ctx, nullptr, &outl, aad, _countof(aad)); - out = (char*)mir_alloc(inl + _countof(key) - 1); - for (;;) { - EVP_EncryptUpdate(ctx, (unsigned char*)(out + tmp_len), &outl, (unsigned char*)(msg_text + tmp_len), (int)(inl - tmp_len)); - tmp_len += outl; - if (tmp_len >= (int)inl - 16 + 1) //cast to int is required here - break; - } - - EVP_EncryptFinal(ctx, (unsigned char*)(msg_text + tmp_len), &outl); + unsigned char *out = (unsigned char*)mir_alloc(inl + _countof(key) - 1); + EVP_EncryptUpdate(ctx, out, &outl, (unsigned char*)msg_text, inl); + tmp_len += outl; + + EVP_EncryptFinal(ctx, (unsigned char*)(out + tmp_len), &outl); tmp_len += outl; EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, _countof(tag), tag); EVP_CIPHER_CTX_free(ctx); @@ -2016,6 +2012,7 @@ int CJabberProto::OmemoEncryptMessage(XmlNode &msg, const char *msg_text, MCONTA TiXmlElement *encrypted = msg << XCHILDNS("encrypted", JABBER_FEAT_OMEMO); TiXmlElement *payload = encrypted << XCHILD("payload"); payload->SetText(ptrA(mir_base64_encode(out, tmp_len)).get()); + mir_free(out); TiXmlElement *header = encrypted << XCHILD("header"); header << XATTRI64("sid", m_omemo.GetOwnDeviceId()); -- cgit v1.2.3