Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Qt olm binding #443

Closed
wants to merge 45 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
1d98639
Start implementing Qt olm binding
CarlSchwan Jan 22, 2021
d2c0b2c
Add tests
CarlSchwan Jan 22, 2021
e16ae79
Add destructor
CarlSchwan Jan 22, 2021
e2ff63d
Start inboundsession wrapper
CarlSchwan Jan 23, 2021
aa46589
Implement Inboundsession
CarlSchwan Jan 23, 2021
a729932
Implement outboundsession
CarlSchwan Jan 24, 2021
9a93fb1
ifdef everything
CarlSchwan Jan 24, 2021
8c0f71b
Fix documentation typos
CarlSchwan Jan 24, 2021
844a945
Make it work
CarlSchwan Jan 24, 2021
fb5939f
Update test
CarlSchwan Jan 24, 2021
3274a9e
Depends on OpenSSL for crypo rand
CarlSchwan Jan 24, 2021
492f03d
Add group session decrypt/encrypt test and fix bug found by it
CarlSchwan Jan 24, 2021
57162df
Improve API
CarlSchwan Jan 26, 2021
529c905
E2EE: Introduce session (WiP)
a-andreyev Jan 26, 2021
b143b6c
Add missing reinterpret_cast for session data
a-andreyev Jan 26, 2021
d65963f
Add hehlper functions
CarlSchwan Jan 26, 2021
5369d33
Start adding test for session stuff
CarlSchwan Jan 27, 2021
c151719
Add first session test and it fails :(
CarlSchwan Jan 27, 2021
83eabf6
Add more test and methods in session handling
CarlSchwan Jan 27, 2021
9293454
Add QOlmSession::decrypt
CarlSchwan Jan 27, 2021
e89476b
Implement session sorting
CarlSchwan Jan 27, 2021
591b6ba
Disable olm test when disabling encryption
CarlSchwan Jan 27, 2021
818a14e
Add device key test
CarlSchwan Jan 27, 2021
5981c16
Fix CI
CarlSchwan Jan 27, 2021
7de7600
Add encrypted file struct
CarlSchwan Jan 27, 2021
75d2b97
Move files
CarlSchwan Jan 28, 2021
559274e
Remove duplicated file
CarlSchwan Jan 28, 2021
1926d50
E2EE: initial port to internal olm wrapper
a-andreyev Jan 28, 2021
e59b722
Fix test
CarlSchwan Jan 28, 2021
4b54169
More porting to new API
CarlSchwan Jan 29, 2021
5c50c4f
More tests
CarlSchwan Jan 29, 2021
62d661e
Key verification
CarlSchwan Jan 29, 2021
a8dc175
Add more test and use macro to remove duplicated code
CarlSchwan Jan 30, 2021
ffb3867
More test but still failing in signing/signature verification
CarlSchwan Jan 31, 2021
ddbe6c3
remove old files
CarlSchwan Jan 31, 2021
74c7843
Fix signing keys
CarlSchwan Jan 31, 2021
ad0158c
Fix cmake code
CarlSchwan Feb 4, 2021
88da786
Apply suggestions from code review
CarlSchwan Feb 15, 2021
aeed90e
Apply a few more comments
CarlSchwan Feb 15, 2021
44bca97
fix typo
CarlSchwan Feb 15, 2021
9244613
Ifdef E2EE out at cmake level
TobiasFella Mar 22, 2021
f1acf80
Apply suggestions from code review
CarlSchwan Apr 19, 2021
fe7ff15
ssl
CarlSchwan Feb 22, 2021
9d64694
Fix error manager
CarlSchwan May 5, 2021
3e7dbfe
Fix everything
CarlSchwan May 5, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .ci/adjust-config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/bin/bash

CMD=""

$CMD perl -pi -w -e \
's/rc_messages_per_second.*/rc_messages_per_second: 1000/g;' data/homeserver.yaml
$CMD perl -pi -w -e \
's/rc_message_burst_count.*/rc_message_burst_count: 10000/g;' data/homeserver.yaml

(
cat <<HEREDOC
rc_message:
per_second: 10000
burst_count: 100000
rc_registration:
per_second: 10000
burst_count: 30000
rc_login:
address:
per_second: 10000
burst_count: 30000
account:
per_second: 10000
burst_count: 30000
failed_attempts:
per_second: 10000
burst_count: 30000
rc_admin_redaction:
per_second: 1000
burst_count: 5000
rc_joins:
local:
per_second: 10000
burst_count: 100000
remote:
per_second: 10000
burst_count: 100000
HEREDOC
) | $CMD tee -a data/homeserver.yaml

$CMD perl -pi -w -e \
's/#enable_registration: false/enable_registration: true/g;' data/homeserver.yaml
$CMD perl -pi -w -e \
's/tls: false/tls: true/g;' data/homeserver.yaml
$CMD perl -pi -w -e \
's/#tls_certificate_path:/tls_certificate_path:/g;' data/homeserver.yaml
$CMD perl -pi -w -e \
's/#tls_private_key_path:/tls_private_key_path:/g;' data/homeserver.yaml

$CMD openssl req -x509 -newkey rsa:4096 -keyout data/localhost.tls.key -out data/localhost.tls.crt -days 365 -subj '/CN=localhost' -nodes

$CMD chmod 0777 data/localhost.tls.crt
$CMD chmod 0777 data/localhost.tls.key
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ jobs:
-DCMAKE_INSTALL_PREFIX=~/.local -DCMAKE_PREFIX_PATH=~/.local" >>$GITHUB_ENV
cmake -E make_directory ${{ runner.workspace }}/build

- name: Install OpenSSL
if: contains(matrix.os, 'ubuntu') and matrix.e2ee
run: |
sudo apt-get install libssl-dev
echo "openssl version" >>$GITHUB_ENV

- name: Build and install olm
if: matrix.e2ee
run: |
Expand Down
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
[submodule "3rdparty/libQtOlm"]
path = 3rdparty/libQtOlm
url = https://gitlab.com/b0/libqtolm.git
1 change: 0 additions & 1 deletion 3rdparty/libQtOlm
Submodule libQtOlm deleted from f2d8e2
73 changes: 38 additions & 35 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,39 +77,26 @@ get_filename_component(Qt5_Prefix "${Qt5_DIR}/../../../.." ABSOLUTE)
message(STATUS "Using Qt ${Qt5_VERSION} at ${Qt5_Prefix}")

if (${PROJECT_NAME}_ENABLE_E2EE)
if ((NOT DEFINED USE_INTREE_LIBQOLM OR USE_INTREE_LIBQOLM)
AND EXISTS ${PROJECT_SOURCE_DIR}/3rdparty/libQtOlm/lib/utils.h)
add_subdirectory(3rdparty/libQtOlm)
include_directories(3rdparty/libQtOlm)
if (NOT DEFINED USE_INTREE_LIBQOLM)
set (USE_INTREE_LIBQOLM 1)
endif ()
endif ()
if (USE_INTREE_LIBQOLM)
message( STATUS "Using in-tree libQtOlm")
find_package(Git QUIET)
if (GIT_FOUND)
execute_process(COMMAND
"${GIT_EXECUTABLE}" rev-parse -q HEAD
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/3rdparty/libQtOlm
OUTPUT_VARIABLE QTOLM_GIT_SHA1
OUTPUT_STRIP_TRAILING_WHITESPACE)
message( STATUS " Library git SHA1: ${QTOLM_GIT_SHA1}")
endif (GIT_FOUND)
else ()
set(SAVED_CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR})
set(CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR})
find_package(QtOlm 3.0.1 REQUIRED)
set_package_properties(QtOlm PROPERTIES
DESCRIPTION "QtOlm is a Qt wrapper around libOlm"
PURPOSE "libQtOlm is required to support end-to-end encryption. See also BUILDING.md"
URL "https://gitlab.com/b0/libqtolm"
)
if (QtOlm_FOUND)
message(STATUS "Using libQtOlm ${QtOlm_VERSION} at ${QtOlm_DIR}")
endif()
endif ()
endif ()
find_package(Olm 3.2.1 REQUIRED)
set_package_properties(Olm PROPERTIES
DESCRIPTION "Implementation of the Olm and Megolm cryptographic ratchets"
URL "https://gitlab.matrix.org/matrix-org/olm"
TYPE REQUIRED
)
if (Olm_FOUND)
message(STATUS "Using libOlm ${Olm_VERSION} at ${Olm_DIR}")
endif()

find_package(OpenSSL 1.1.0 REQUIRED)
set_package_properties(OpenSSL PROPERTIES
DESCRIPTION "Open source SSL and TLS implementation and cryptographic library"
URL "https://www.openssl.org/"
TYPE REQUIRED
)
if (OpenSSL_FOUND)
message(STATUS "Using OpenSSL ${OpenSSL_VERSION} at ${OpenSSL_DIR}")
endif()
endif()

# Set up source files
set(lib_SRCS
Expand Down Expand Up @@ -157,6 +144,19 @@ set(lib_SRCS
lib/jobs/mediathumbnailjob.cpp
lib/jobs/downloadfilejob.cpp
)
if (${PROJECT_NAME}_ENABLE_E2EE)
list(APPEND lib_SRCS
lib/crypto/qolmaccount.cpp
lib/crypto/qolmsession.cpp
lib/crypto/qolminboundsession.cpp
lib/crypto/qolmoutboundsession.cpp
lib/crypto/qolmutils.cpp
lib/crypto/qolmutility.cpp
lib/crypto/qolmerrors.cpp
lib/crypto/qolmsession.cpp
lib/crypto/qolmmessage.cpp
)
endif()

# Configure API files generation

Expand Down Expand Up @@ -276,8 +276,11 @@ target_include_directories(${PROJECT_NAME} PUBLIC
$<INSTALL_INTERFACE:${${PROJECT_NAME}_INSTALL_INCLUDEDIR}>
)
if (${PROJECT_NAME}_ENABLE_E2EE)
target_link_libraries(${PROJECT_NAME} QtOlm)
set(FIND_DEPS "find_dependency(QtOlm)") # For QuotientConfig.cmake.in
target_link_libraries(${PROJECT_NAME} Olm::Olm
OpenSSL::Crypto
OpenSSL::SSL)
set(FIND_DEPS "find_dependency(Olm)
find_dependency(OpenSSL)") # For QuotientConfig.cmake.in
endif()
target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Network Qt5::Gui Qt5::Multimedia)

Expand Down
31 changes: 31 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
SYNAPSE_IMAGE="matrixdotorg/synapse:v1.24.0"

test: ## Run the tests
@cd build/ && GTEST_COLOR=1 ctest --verbose

synapse: ## Start a synapse instance on docker
@mkdir -p data
@chmod 0777 data
@docker run -v `pwd`/data:/data --rm \
-e SYNAPSE_SERVER_NAME=localhost -e SYNAPSE_REPORT_STATS=no ${SYNAPSE_IMAGE} generate
@./.ci/adjust-config.sh
@docker run -d \
--name synapse \
-p 443:8008 \
-p 8448:8008 \
-p 8008:8008 \
-v `pwd`/data:/data ${SYNAPSE_IMAGE}
@echo Waiting for synapse to start...
@until curl -s -f -k https://localhost:443/_matrix/client/versions; do echo "Checking ..."; sleep 2; done
@echo Register alice
@docker exec synapse /bin/sh -c 'register_new_matrix_user --admin -u alice -p secret -c /data/homeserver.yaml https://localhost:8008'
@echo Register bob
@docker exec synapse /bin/sh -c 'register_new_matrix_user --admin -u bob -p secret -c /data/homeserver.yaml https://localhost:8008'
@echo Register carl
@docker exec synapse /bin/sh -c 'register_new_matrix_user --admin -u carl -p secret -c /data/homeserver.yaml https://localhost:8008'

stop-synapse: ## Stop any running instance of synapse
@rm -rf ./data/*
@docker rm -f synapse 2>&1>/dev/null

restart: stop-synapse synapse
6 changes: 6 additions & 0 deletions autotests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@ function(QUOTIENT_ADD_TEST)
endfunction()

quotient_add_test(NAME callcandidateseventtest)
if(${PROJECT_NAME}_ENABLE_E2EE)
quotient_add_test(NAME testolmaccount)
quotient_add_test(NAME testgroupsession)
quotient_add_test(NAME testolmsession)
quotient_add_test(NAME testolmutility)
endif()
54 changes: 54 additions & 0 deletions autotests/testgroupsession.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: 2021 Carl Schwan <[email protected]>
//
// SPDX-License-Identifier: LGPL-2.1-or-later

#include "testgroupsession.h"
#include "crypto/qolminboundsession.h"
#include "crypto/qolmoutboundsession.h"
#include "crypto/qolmutils.h"

using namespace Quotient;

void TestOlmSession::groupSessionPicklingValid()
{
auto ogs = QOlmOutboundGroupSession::create();
const auto ogsId = ogs->sessionId();
QVERIFY(QByteArray::fromBase64Encoding(ogsId).decodingStatus == QByteArray::Base64DecodingStatus::Ok);
QCOMPARE(0, ogs->sessionMessageIndex());

auto ogsPickled = std::get<QByteArray>(ogs->pickle(Unencrypted {}));
auto ogs2 = std::get<QOlmOutboundGroupSessionPtr>(QOlmOutboundGroupSession::unpickle(ogsPickled, Unencrypted {}));
QCOMPARE(ogsId, ogs2->sessionId());

auto igs = QOlmInboundGroupSession::create(std::get<QByteArray>(ogs->sessionKey()));
const auto igsId = igs->sessionId();
// ID is valid base64?
QVERIFY(QByteArray::fromBase64Encoding(igsId).decodingStatus == QByteArray::Base64DecodingStatus::Ok);

//// no messages have been sent yet
QCOMPARE(0, igs->firstKnownIndex());

auto igsPickled = igs->pickle(Unencrypted {});
igs = std::get<QOlmInboundGroupSessionPtr>(QOlmInboundGroupSession::unpickle(igsPickled, Unencrypted {}));
QCOMPARE(igsId, igs->sessionId());
}

void TestOlmSession::groupSessionCryptoValid()
{
auto ogs = QOlmOutboundGroupSession::create();
auto igs = QOlmInboundGroupSession::create(std::get<QByteArray>(ogs->sessionKey()));
QCOMPARE(ogs->sessionId(), igs->sessionId());

const auto plainText = QStringLiteral("Hello world!");
const auto ciphertext = std::get<QByteArray>(ogs->encrypt(plainText));
// ciphertext valid base64?
QVERIFY(QByteArray::fromBase64Encoding(ciphertext).decodingStatus == QByteArray::Base64DecodingStatus::Ok);

const auto decryptionResult = std::get<std::pair<QString, uint32_t>>(igs->decrypt(ciphertext));

//// correct plaintext?
QCOMPARE(plainText, decryptionResult.first);

QCOMPARE(0, decryptionResult.second);
}
QTEST_MAIN(TestOlmSession)
14 changes: 14 additions & 0 deletions autotests/testgroupsession.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-FileCopyrightText: 2021 Carl Schwan <[email protected]>
//
// SPDX-License-Identifier: LGPL-2.1-or-later

#include <QTest>

class TestOlmSession : public QObject
{
Q_OBJECT

private Q_SLOTS:
void groupSessionPicklingValid();
void groupSessionCryptoValid();
};
Loading