From 64d578eaad10ff4fb7722985783bc16885957415 Mon Sep 17 00:00:00 2001 From: watcherhd Date: Wed, 26 Apr 2017 11:20:10 +0300 Subject: Revert "Revert "jabber: omemo: improoved 4.4, working on 4.5"" This reverts commit 3919b8b2d5270a41cbad66158165a4101b230e95. returning 26092086b62afd9bdef93f4756ae7558ec681e9a to the original state --- protocols/JabberG/src/jabber_omemo.cpp | 89 +++++++++++++++++++++++++--------- protocols/JabberG/src/jabber_proto.cpp | 2 +- protocols/JabberG/src/jabber_proto.h | 2 +- 3 files changed, 68 insertions(+), 25 deletions(-) (limited to 'protocols/JabberG') diff --git a/protocols/JabberG/src/jabber_omemo.cpp b/protocols/JabberG/src/jabber_omemo.cpp index 94fdb1f335..4fdd5e2ee2 100755 --- a/protocols/JabberG/src/jabber_omemo.cpp +++ b/protocols/JabberG/src/jabber_omemo.cpp @@ -33,6 +33,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include +#include //c++ #include @@ -574,6 +575,7 @@ namespace omemo { struct signal_store_backend_user_data { MCONTACT hContact; + unsigned int device_id; CJabberProto *proto; }; int load_session_func(signal_buffer **record, const signal_protocol_address *address, void *user_data) @@ -588,6 +590,11 @@ namespace omemo { * @param address the address of the remote client * @return 1 if the session was loaded, 0 if the session was not found, negative on failure */ + //some sanity checks + if (address->device_id <= 0) + return -1; + if (address->name_len > 1024) + return -1; signal_store_backend_user_data* data = (signal_store_backend_user_data*)user_data; @@ -845,7 +852,7 @@ namespace omemo { signal_store_backend_user_data* data = (signal_store_backend_user_data*)user_data; char *setting_name = (char*)mir_alloc(strlen("OmemoSignalPreKey_") + 32); - mir_snprintf(setting_name, strlen("OmemoSignalPreKey_") + 31, "%s%d", "OmemoSignalSession_", pre_key_id); + mir_snprintf(setting_name, strlen("OmemoSignalPreKey_") + 31, "%s%d%d", "OmemoSignalSession_", data->device_id, pre_key_id); DBVARIANT dbv = { 0 }; dbv.type = DBVT_BLOB; db_get(data->hContact, data->proto->m_szModuleName, setting_name, &dbv); @@ -874,7 +881,7 @@ namespace omemo { signal_store_backend_user_data* data = (signal_store_backend_user_data*)user_data; char *setting_name = (char*)mir_alloc(strlen("OmemoSignalPreKey_") + 32); - mir_snprintf(setting_name, strlen("OmemoSignalPreKey_") + 31, "%s%d", "OmemoSignalSession_", pre_key_id); + mir_snprintf(setting_name, strlen("OmemoSignalPreKey_") + 31, "%s%d%d", "OmemoSignalSession_", data->device_id, pre_key_id); db_set_blob(data->hContact, data->proto->m_szModuleName, setting_name, record, (unsigned int)record_len); //TODO: check return value mir_free(setting_name); @@ -894,7 +901,7 @@ namespace omemo { signal_store_backend_user_data* data = (signal_store_backend_user_data*)user_data; char *setting_name = (char*)mir_alloc(strlen("OmemoSignalPreKey_") + 32); - mir_snprintf(setting_name, strlen("OmemoSignalPreKey_") + 31, "%s%d", "OmemoSignalSession_", pre_key_id); + mir_snprintf(setting_name, strlen("OmemoSignalPreKey_") + 31, "%s%d%d", "OmemoSignalSession_", data->device_id, pre_key_id); DBVARIANT dbv = { 0 }; dbv.type = DBVT_BLOB; db_get(data->hContact, data->proto->m_szModuleName, setting_name, &dbv); @@ -921,7 +928,7 @@ namespace omemo { signal_store_backend_user_data* data = (signal_store_backend_user_data*)user_data; char *setting_name = (char*)mir_alloc(strlen("OmemoSignalPreKey_") + 32); - mir_snprintf(setting_name, strlen("OmemoSignalPreKey_") + 31, "%s%d", "OmemoSignalSession_", pre_key_id); + mir_snprintf(setting_name, strlen("OmemoSignalPreKey_") + 31, "%s%d%d", "OmemoSignalSession_", data->device_id, pre_key_id); db_unset(data->hContact, data->proto->m_szModuleName, setting_name); mir_free(setting_name); @@ -947,7 +954,7 @@ namespace omemo { signal_store_backend_user_data* data = (signal_store_backend_user_data*)user_data; char *setting_name = (char*)mir_alloc(strlen("OmemoSignalSignedPreKey_") + 32); - mir_snprintf(setting_name, strlen("OmemoSignalSignedPreKey_") + 31, "%s%d", "OmemoSignalSignedPreKey_", signed_pre_key_id); + mir_snprintf(setting_name, strlen("OmemoSignalSignedPreKey_") + 31, "%s%d%d", "OmemoSignalSignedPreKey_", data->device_id, signed_pre_key_id); DBVARIANT dbv = { 0 }; dbv.type = DBVT_BLOB; db_get(data->hContact, data->proto->m_szModuleName, setting_name, &dbv); @@ -977,7 +984,7 @@ namespace omemo { signal_store_backend_user_data* data = (signal_store_backend_user_data*)user_data; char *setting_name = (char*)mir_alloc(strlen("OmemoSignalSignedPreKey_") + 32); - mir_snprintf(setting_name, strlen("OmemoSignalSignedPreKey_") + 31, "%s%d", "OmemoSignalSignedPreKey_", signed_pre_key_id); + mir_snprintf(setting_name, strlen("OmemoSignalSignedPreKey_") + 31, "%s%d%d", "OmemoSignalSignedPreKey_", data->device_id, signed_pre_key_id); db_set_blob(data->hContact, data->proto->m_szModuleName, setting_name, record, (unsigned int)record_len); //TODO: check return value mir_free(setting_name); @@ -997,7 +1004,7 @@ namespace omemo { signal_store_backend_user_data* data = (signal_store_backend_user_data*)user_data; char *setting_name = (char*)mir_alloc(strlen("OmemoSignalSignedPreKey_") + 32); - mir_snprintf(setting_name, strlen("OmemoSignalSignedPreKey_") + 31, "%s%d", "OmemoSignalSignedPreKey_", signed_pre_key_id); + mir_snprintf(setting_name, strlen("OmemoSignalSignedPreKey_") + 31, "%s%d%d", "OmemoSignalSignedPreKey_", data->device_id, signed_pre_key_id); DBVARIANT dbv = { 0 }; dbv.type = DBVT_BLOB; db_get(data->hContact, data->proto->m_szModuleName, setting_name, &dbv); @@ -1024,7 +1031,7 @@ namespace omemo { signal_store_backend_user_data* data = (signal_store_backend_user_data*)user_data; char *setting_name = (char*)mir_alloc(strlen("OmemoSignalSignedPreKey_") + 32); - mir_snprintf(setting_name, strlen("OmemoSignalSignedPreKey_") + 31, "%s%d", "OmemoSignalSignedPreKey_", signed_pre_key_id); + mir_snprintf(setting_name, strlen("OmemoSignalSignedPreKey_") + 31, "%s%d%d", "OmemoSignalSignedPreKey_", data->device_id, signed_pre_key_id); db_unset(data->hContact, data->proto->m_szModuleName, setting_name); mir_free(setting_name); @@ -1077,9 +1084,10 @@ namespace omemo { * registration ID, if it was successfully retrieved. * @return 0 on success, negative on failure */ - + uint32_t *id = (uint32_t*)mir_alloc(sizeof(uint32_t)); signal_store_backend_user_data* data = (signal_store_backend_user_data*)user_data; - *registration_id = GetOwnDeviceId(data->proto); //TODO: check it, maybe memory allocation is necessary + *id = GetOwnDeviceId(data->proto); + registration_id = id; return 0; } @@ -1180,13 +1188,15 @@ namespace omemo { bool create_session_store(MCONTACT hContact, LPCTSTR device_id, CJabberProto *proto) { - sessions_internal[hContact].clear(); +// sessions_internal[hContact].clear(); signal_store_backend_user_data *data[4]; + unsigned int device_id_int = _wtoi(device_id); for (int i = 0; i < 4; i++) { data[i] = (signal_store_backend_user_data*)mir_alloc(sizeof(signal_store_backend_user_data)); data[i]->hContact = hContact; data[i]->proto = proto; + data[i]->device_id = device_id_int; } /* Create the data store context, and add all the callbacks to it */ //TODO: validation of functions return codes @@ -1238,24 +1248,20 @@ namespace omemo { /* Instantiate a session_builder for a recipient address. */ char *jid_str = mir_u2a(jid); int dev_id_int = _wtoi(dev_id); - signal_protocol_address address = + signal_protocol_address *address = (signal_protocol_address*)mir_alloc(sizeof(signal_protocol_address)); //libsignal does not copy structure, so we must allocate one manually, does it free it on exit ? + *address = { - jid_str, - mir_strlen(jid_str), + jid_str, //will libsignal free arrav for us on exit ? + mir_strlen(jid_str), dev_id_int }; session_builder *builder; - if (session_builder_create(&builder, sessions_internal[hContact][dev_id_int].store_context, &address, global_context) < 0) - { - mir_free(jid_str); + if (session_builder_create(&builder, sessions_internal[hContact][dev_id_int].store_context, address, global_context) < 0) return false; //failure - } sessions_internal[hContact][dev_id_int].builder = builder; - mir_free(jid_str); - int key_id_int = _wtoi(key_id); char *pre_key_a = mir_u2a(pre_key_public); @@ -1305,7 +1311,7 @@ namespace omemo { /* Create the session cipher and encrypt the message */ session_cipher *cipher; - if (session_cipher_create(&cipher, sessions_internal[hContact][dev_id_int].store_context, &address, global_context) < 0) + if (session_cipher_create(&cipher, sessions_internal[hContact][dev_id_int].store_context, address, global_context) < 0) return false; //failure sessions_internal[hContact][dev_id_int].cipher = cipher; @@ -1666,9 +1672,46 @@ void CJabberProto::OmemoOnIqResultGetBundle(HXML iqNode, CJabberIqInfo *pInfo) } -void CJabberProto::OmemoEncryptMessage(XmlNode &msg, const wchar_t *msg_text) +void CJabberProto::OmemoEncryptMessage(XmlNode &msg, const wchar_t *msg_text, MCONTACT hContact) { - //TODO: + const EVP_CIPHER *cipher = EVP_aes_128_gcm(); + unsigned char key[16], iv[128]; + Utils_GetRandom(key, 16); + Utils_GetRandom(iv, 128); + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + EVP_EncryptInit(ctx, cipher, key, iv); + char *tmp = mir_u2a(msg_text), *out; + const int inl = strlen(tmp); + int tmp_len = 0, outl; + out = (char*)mir_alloc(inl + 16 - 1); + for (;;) + { + EVP_EncryptUpdate(ctx, (unsigned char*)(out + tmp_len), &outl, (unsigned char*)(tmp + tmp_len), inl - tmp_len); + tmp_len += outl; + if (tmp_len >= inl - 16 + 1) + break; + } + EVP_EncryptFinal(ctx, (unsigned char*)(out + tmp_len), &outl); + EVP_CIPHER_CTX_free(ctx); + //TODO: check if encryption works properly + mir_free(tmp); + //TODO: construct "MessageElement" node + for (std::map::iterator i = omemo::sessions_internal[hContact].begin(), end = omemo::sessions_internal[hContact].end(); i != end; i++) //something wrong with map ... + { + unsigned int intdev_id = i->first; + ciphertext_message *encrypted_key; + if (session_cipher_encrypt(i->second.cipher, (uint8_t*)key, 16, &encrypted_key) != SG_SUCCESS) + { + //TODO: handle encryption error + continue; + } + else + { + signal_buffer *serialized_encrypted_key = ciphertext_message_get_serialized(encrypted_key); + SIGNAL_UNREF(encrypted_key); + } + } + //TODO: add "MessageElement" to msg node } bool CJabberProto::OmemoIsEnabled(MCONTACT hContact) { diff --git a/protocols/JabberG/src/jabber_proto.cpp b/protocols/JabberG/src/jabber_proto.cpp index d2ce816639..71e630bd4a 100755 --- a/protocols/JabberG/src/jabber_proto.cpp +++ b/protocols/JabberG/src/jabber_proto.cpp @@ -964,7 +964,7 @@ int __cdecl CJabberProto::SendMsg(MCONTACT hContact, int, const char* pszSrc) if(m_options.UseOMEMO && OmemoIsEnabled(hContact) && !mir_wstrcmp(msgType, L"chat")) //omemo enabled in options, omemo enabled for contact { - OmemoEncryptMessage(m, msg); + OmemoEncryptMessage(m, msg, hContact); } else { diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h index 04414012fc..79d4f7d93b 100755 --- a/protocols/JabberG/src/jabber_proto.h +++ b/protocols/JabberG/src/jabber_proto.h @@ -344,7 +344,7 @@ struct CJabberProto : public PROTO, public IJabberInterface void OmemoSendBundle(); void OmemoPublishNodes(); bool OmemoCheckSession(MCONTACT hContact); - void OmemoEncryptMessage(XmlNode &msg, const wchar_t *msg_text); + void OmemoEncryptMessage(XmlNode &msg, const wchar_t *msg_text, MCONTACT hContact); bool OmemoIsEnabled(MCONTACT hContact); void OmemoOnIqResultGetBundle(HXML iqNode, CJabberIqInfo *pInfo); -- cgit v1.2.3