From 2505bc6667ad09f46d46245f9de340fda5b3e1f9 Mon Sep 17 00:00:00 2001 From: johan pascal <johan.pascal@belledonne-communications.com> Date: Thu, 27 Feb 2025 13:06:48 +0100 Subject: [PATCH] Lime message deflate condition improved + better migration testing --- .../lime-x3dh-encryption-engine.cpp | 12 +- tester/group_chat_secure_multialgo_tester.cpp | 122 ++++++++++++++++++ 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/src/chat/encryption/lime-x3dh-encryption-engine.cpp b/src/chat/encryption/lime-x3dh-encryption-engine.cpp index f36025eafe..d53f3c9d8e 100644 --- a/src/chat/encryption/lime-x3dh-encryption-engine.cpp +++ b/src/chat/encryption/lime-x3dh-encryption-engine.cpp @@ -360,12 +360,20 @@ ChatMessageModifier::Result LimeX3dhEncryptionEngine::processOutgoingMessage(con // Compress plain text message - compression after encryption is much less efficient // To keep compatibility with version not supporting the encryption at this stage, do it (for now: may 2024) - // only when the only supported algorithm is c25519k512 + // only when all the supported algorithm are in c25519k512, c25519mlk512, c448mlk1024 bool compressedPlain = false; Content plainContent(message->getInternalContent()); const string localDeviceId = localDevice->asStringUriOnly(); if (usersAlgos.find(localDeviceId) != usersAlgos.end()) { - if (usersAlgos[localDeviceId].size() == 1 && usersAlgos[localDeviceId][0] == lime::CurveId::c25519k512) { + bool skipDeflate = false; + for (const auto &algo : usersAlgos[localDeviceId]) { + if (algo < + lime::CurveId::c25519k512) { // enum class is ordered, values under c2519k512 are the older base algo + skipDeflate = true; + break; + } + } + if (!skipDeflate) { compressedPlain = plainContent.deflateBody(); } } diff --git a/tester/group_chat_secure_multialgo_tester.cpp b/tester/group_chat_secure_multialgo_tester.cpp index 0aa48be404..f9f35e0017 100644 --- a/tester/group_chat_secure_multialgo_tester.cpp +++ b/tester/group_chat_secure_multialgo_tester.cpp @@ -609,6 +609,128 @@ static void group_chat_lime_x3dh_soft_migration(void) { // wait bit more to allow imdn exchanges Linphone::Tester::CoreManagerAssert(allCoreMgrs).waitUntil(std::chrono::seconds(3), [] { return false; }); + + // ReStart Marie, Laure and Chloe core with c25519mlk512,c25519k512 (drop c25519) + laure.set_limeAlgoList({lime::CurveId::c25519mlk512, lime::CurveId::c25519k512}); + coresList = bctbx_list_remove(coresList, laure.getLc()); + laure.reStart(); + coresList = bctbx_list_append(coresList, laure.getLc()); + laureStats = laure.getStats(); + BC_ASSERT_TRUE(laure.assertPtrValue(&(laureStats.number_of_X3dhUserCreationSuccess), 1)); + + chloe.set_limeAlgoList({lime::CurveId::c25519mlk512, lime::CurveId::c25519k512}); + coresList = bctbx_list_remove(coresList, chloe.getLc()); + chloe.reStart(); + coresList = bctbx_list_append(coresList, chloe.getLc()); + chloeStats = chloe.getStats(); + BC_ASSERT_TRUE(chloe.assertPtrValue(&(chloeStats.number_of_X3dhUserCreationSuccess), 1)); + + marie.set_limeAlgoList({lime::CurveId::c25519mlk512, lime::CurveId::c25519k512}); + coresList = bctbx_list_remove(coresList, marie.getLc()); + marie.reStart(); + coresList = bctbx_list_append(coresList, marie.getLc()); + marieStats = marie.getStats(); + BC_ASSERT_TRUE(marie.assertPtrValue(&(marieStats.number_of_X3dhUserCreationSuccess), 1)); + + // get back marieCr + marieDeviceAddr = linphone_address_clone(linphone_proxy_config_get_contact(marie.getDefaultProxyConfig())); + marieCr = marie.searchChatRoom(marieDeviceAddr, confAddr); + BC_ASSERT_PTR_NOT_NULL(marieCr); + linphone_address_unref(marieDeviceAddr); + + // Marie send a message to the group + msgText = std::string("To infinity and beyond"); + msg = Linphone::Tester::ConfCoreManager::sendTextMsg(marieCr, msgText); + + // Message is delivered + BC_ASSERT_TRUE(Linphone::Tester::CoreManagerAssert(allCoreMgrs).wait([msg] { + return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); + })); + + linphone_chat_message_unref(msg); + msg = nullptr; + + // everyone get it + for (Linphone::Tester::CoreManager &client : recipients) { + for (auto chatRoom : client.getCore().getChatRooms()) { + BC_ASSERT_TRUE(Linphone::Tester::CoreManagerAssert(allCoreMgrs).wait([chatRoom] { + return chatRoom->getUnreadChatMessageCount() == 1; + })); + LinphoneChatMessage *lastMsg = client.getStats().last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(lastMsg); + if (lastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(lastMsg), msgText.c_str()); + } + chatRoom->markAsRead(); + } + } + + // wait bit more to allow imdn exchanges + Linphone::Tester::CoreManagerAssert(allCoreMgrs).waitUntil(std::chrono::seconds(3), [] { return false; }); + + // ReStart Marie, Laure and Chloe core with c25519mlk512 only (drop c25519k512) -> pauline won't be able to get the + // message + laure.set_limeAlgoList({lime::CurveId::c25519mlk512}); + coresList = bctbx_list_remove(coresList, laure.getLc()); + laure.reStart(); + coresList = bctbx_list_append(coresList, laure.getLc()); + laureStats = laure.getStats(); + BC_ASSERT_TRUE(laure.assertPtrValue(&(laureStats.number_of_X3dhUserCreationSuccess), 1)); + + chloe.set_limeAlgoList({lime::CurveId::c25519mlk512}); + coresList = bctbx_list_remove(coresList, chloe.getLc()); + chloe.reStart(); + coresList = bctbx_list_append(coresList, chloe.getLc()); + chloeStats = chloe.getStats(); + BC_ASSERT_TRUE(chloe.assertPtrValue(&(chloeStats.number_of_X3dhUserCreationSuccess), 1)); + + marie.set_limeAlgoList({lime::CurveId::c25519mlk512}); + coresList = bctbx_list_remove(coresList, marie.getLc()); + marie.reStart(); + coresList = bctbx_list_append(coresList, marie.getLc()); + marieStats = marie.getStats(); + BC_ASSERT_TRUE(marie.assertPtrValue(&(marieStats.number_of_X3dhUserCreationSuccess), 1)); + + // get back marieCr + marieDeviceAddr = linphone_address_clone(linphone_proxy_config_get_contact(marie.getDefaultProxyConfig())); + marieCr = marie.searchChatRoom(marieDeviceAddr, confAddr); + BC_ASSERT_PTR_NOT_NULL(marieCr); + linphone_address_unref(marieDeviceAddr); + + // Marie send a message to the group + msgText = std::string("Bye Pauline"); + msg = Linphone::Tester::ConfCoreManager::sendTextMsg(marieCr, msgText); + + // Message is delivered + BC_ASSERT_TRUE(Linphone::Tester::CoreManagerAssert(allCoreMgrs).wait([msg] { + return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); + })); + + linphone_chat_message_unref(msg); + msg = nullptr; + + // Laure and Chloe get it + for (Linphone::Tester::CoreManager &client : + std::list<std::reference_wrapper<Linphone::Tester::CoreManager>>{laure, chloe}) { + for (auto chatRoom : client.getCore().getChatRooms()) { + BC_ASSERT_TRUE(Linphone::Tester::CoreManagerAssert(allCoreMgrs).wait([chatRoom] { + return chatRoom->getUnreadChatMessageCount() == 1; + })); + LinphoneChatMessage *lastMsg = client.getStats().last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(lastMsg); + if (lastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(lastMsg), msgText.c_str()); + } + chatRoom->markAsRead(); + } + } + + // wait bit more to allow imdn exchanges + Linphone::Tester::CoreManagerAssert(allCoreMgrs).waitUntil(std::chrono::seconds(3), [] { return false; }); + + // Pauline does not + BC_ASSERT_EQUAL(pauline.getCore().getChatRooms().front()->getUnreadChatMessageCount(), 0, int, "%d"); + linphone_address_unref(confAddr); bctbx_list_free(coresList); } -- GitLab