aboutsummaryrefslogtreecommitdiff
path: root/lib/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'lib/crypto')
-rw-r--r--lib/crypto/e2ee.h7
-rw-r--r--lib/crypto/qolmaccount.cpp23
-rw-r--r--lib/crypto/qolmaccount.h15
-rw-r--r--lib/crypto/qolmerrors.cpp (renamed from lib/crypto/errors.cpp)16
-rw-r--r--lib/crypto/qolmerrors.h (renamed from lib/crypto/errors.h)4
-rw-r--r--lib/crypto/qolminboundsession.cpp8
-rw-r--r--lib/crypto/qolminboundsession.h8
-rw-r--r--lib/crypto/qolmmessage.cpp (renamed from lib/crypto/message.cpp)14
-rw-r--r--lib/crypto/qolmmessage.h (renamed from lib/crypto/message.h)10
-rw-r--r--lib/crypto/qolmoutboundsession.cpp14
-rw-r--r--lib/crypto/qolmoutboundsession.h12
-rw-r--r--lib/crypto/qolmsession.cpp246
-rw-r--r--lib/crypto/qolmsession.cpp.back29
-rw-r--r--lib/crypto/qolmsession.h92
-rw-r--r--lib/crypto/qolmsession.h.back49
-rw-r--r--lib/crypto/qolmutils.cpp (renamed from lib/crypto/utils.cpp)2
-rw-r--r--lib/crypto/qolmutils.h (renamed from lib/crypto/utils.h)2
-rw-r--r--lib/crypto/session.cpp242
-rw-r--r--lib/crypto/session.h77
19 files changed, 440 insertions, 430 deletions
diff --git a/lib/crypto/e2ee.h b/lib/crypto/e2ee.h
index 74f876e4..73dd7f65 100644
--- a/lib/crypto/e2ee.h
+++ b/lib/crypto/e2ee.h
@@ -5,15 +5,17 @@
#pragma once
-#include "util.h"
#include <optional>
#include <string>
#include <variant>
-#include <QMap>
+#include <QMap>
#include <QStringList>
+#include "util.h"
+
namespace Quotient {
+
inline const auto CiphertextKeyL = "ciphertext"_ls;
inline const auto SenderKeyKeyL = "sender_key"_ls;
inline const auto DeviceIdKeyL = "device_id"_ls;
@@ -37,7 +39,6 @@ inline const auto MegolmV1AesSha2AlgoKey =
QStringLiteral("m.megolm.v1.aes-sha2");
inline const QStringList SupportedAlgorithms = { OlmV1Curve25519AesSha2AlgoKey,
MegolmV1AesSha2AlgoKey };
-
struct Unencrypted {};
struct Encrypted {
QByteArray key;
diff --git a/lib/crypto/qolmaccount.cpp b/lib/crypto/qolmaccount.cpp
index 8824e7ef..fc0fc1cf 100644
--- a/lib/crypto/qolmaccount.cpp
+++ b/lib/crypto/qolmaccount.cpp
@@ -3,8 +3,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#ifdef Quotient_E2EE_ENABLED
-#include "crypto/qolmaccount.h"
-#include "crypto/utils.h"
+#include "qolmaccount.h"
+#include "crypto/qolmutils.h"
#include <QJsonObject>
#include <QJsonDocument>
#include <QDebug>
@@ -31,7 +31,7 @@ bool operator==(const IdentityKeys& lhs, const IdentityKeys& rhs)
}
// Convert olm error to enum
-OlmError lastError(OlmAccount *account) {
+QOlmError lastError(OlmAccount *account) {
const std::string error_raw = olm_account_last_error(account);
return fromString(error_raw);
@@ -77,7 +77,7 @@ void QOlmAccount::unpickle(QByteArray &pickled, const PicklingMode &mode)
}
}
-std::variant<QByteArray, OlmError> QOlmAccount::pickle(const PicklingMode &mode)
+std::variant<QByteArray, QOlmError> QOlmAccount::pickle(const PicklingMode &mode)
{
const QByteArray key = toKey(mode);
const size_t pickleLength = olm_pickle_account_length(m_account);
@@ -118,6 +118,11 @@ QByteArray QOlmAccount::sign(const QByteArray &message) const
return signatureBuffer;
}
+QByteArray QOlmAccount::sign(const QJsonObject &message) const
+{
+ return sign(QJsonDocument(message).toJson(QJsonDocument::Compact));
+}
+
QByteArray QOlmAccount::signIdentityKeys() const
{
const auto keys = identityKeys();
@@ -197,19 +202,19 @@ OlmAccount *Quotient::QOlmAccount::data()
return m_account;
}
-std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmAccount::createInboundSession(const Message &preKeyMessage)
+std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmAccount::createInboundSession(const QOlmMessage &preKeyMessage)
{
- Q_ASSERT(preKeyMessage.type() == Message::PreKey);
+ Q_ASSERT(preKeyMessage.type() == QOlmMessage::PreKey);
return QOlmSession::createInboundSession(this, preKeyMessage);
}
-std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmAccount::createInboundSessionFrom(const QByteArray &theirIdentityKey, const Message &preKeyMessage)
+std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmAccount::createInboundSessionFrom(const QByteArray &theirIdentityKey, const QOlmMessage &preKeyMessage)
{
- Q_ASSERT(preKeyMessage.type() == Message::PreKey);
+ Q_ASSERT(preKeyMessage.type() == QOlmMessage::PreKey);
return QOlmSession::createInboundSessionFrom(this, theirIdentityKey, preKeyMessage);
}
-std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmAccount::createOutboundSession(const QByteArray &theirIdentityKey, const QByteArray &theirOneTimeKey)
+std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmAccount::createOutboundSession(const QByteArray &theirIdentityKey, const QByteArray &theirOneTimeKey)
{
return QOlmSession::createOutboundSession(this, theirIdentityKey, theirOneTimeKey);
}
diff --git a/lib/crypto/qolmaccount.h b/lib/crypto/qolmaccount.h
index f98d78ba..b33e3768 100644
--- a/lib/crypto/qolmaccount.h
+++ b/lib/crypto/qolmaccount.h
@@ -5,9 +5,9 @@
#ifdef Quotient_E2EE_ENABLED
#include "crypto/e2ee.h"
-#include "crypto/errors.h"
-#include "crypto/session.h"
-#include <olm/olm.h>
+#include "crypto/qolmerrors.h"
+#include "crypto/qolmmessage.h"
+#include "crypto/qolmsession.h"
#include <QObject>
struct OlmAccount;
@@ -38,13 +38,14 @@ public:
void unpickle(QByteArray &picked, const PicklingMode &mode);
//! Serialises an OlmAccount to encrypted Base64.
- std::variant<QByteArray, OlmError> pickle(const PicklingMode &mode);
+ std::variant<QByteArray, QOlmError> pickle(const PicklingMode &mode);
//! Returns the account's public identity keys already formatted as JSON
IdentityKeys identityKeys() const;
//! Returns the signature of the supplied message.
QByteArray sign(const QByteArray &message) const;
+ QByteArray sign(const QJsonObject& message) const;
//! Sign identity keys.
QByteArray signIdentityKeys() const;
@@ -70,17 +71,17 @@ public:
//! Creates an inbound session for sending/receiving messages from a received 'prekey' message.
//!
//! \param message An Olm pre-key message that was encrypted for this account.
- std::variant<std::unique_ptr<QOlmSession>, OlmError> createInboundSession(const Message &preKeyMessage);
+ std::variant<std::unique_ptr<QOlmSession>, QOlmError> createInboundSession(const QOlmMessage &preKeyMessage);
//! Creates an inbound session for sending/receiving messages from a received 'prekey' message.
//!
//! \param theirIdentityKey - The identity key of an Olm account that
//! encrypted this Olm message.
- std::variant<std::unique_ptr<QOlmSession>, OlmError> createInboundSessionFrom(const QByteArray &theirIdentityKey, const Message &preKeyMessage);
+ std::variant<std::unique_ptr<QOlmSession>, QOlmError> createInboundSessionFrom(const QByteArray &theirIdentityKey, const QOlmMessage &preKeyMessage);
//! Creates an outbound session for sending messages to a specific
/// identity and one time key.
- std::variant<std::unique_ptr<QOlmSession>, OlmError> createOutboundSession(const QByteArray &theirIdentityKey, const QByteArray &theirOneTimeKey);
+ std::variant<std::unique_ptr<QOlmSession>, QOlmError> createOutboundSession(const QByteArray &theirIdentityKey, const QByteArray &theirOneTimeKey);
// HACK do not use directly
QOlmAccount(OlmAccount *account);
diff --git a/lib/crypto/errors.cpp b/lib/crypto/qolmerrors.cpp
index 00ff962d..f407383e 100644
--- a/lib/crypto/errors.cpp
+++ b/lib/crypto/qolmerrors.cpp
@@ -1,21 +1,21 @@
// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
// SPDX-License-Identifier: LGPL-2.1-or-later
#ifdef Quotient_E2EE_ENABLED
-#include "crypto/errors.h"
+#include "qolmerrors.h"
-Quotient::OlmError Quotient::fromString(const std::string &error_raw) {
+Quotient::QOlmError Quotient::fromString(const std::string &error_raw) {
if (error_raw.compare("BAD_ACCOUNT_KEY")) {
- return OlmError::BadAccountKey;
+ return QOlmError::BadAccountKey;
} else if (error_raw.compare("BAD_MESSAGE_KEY_ID")) {
- return OlmError::BadMessageKeyId;
+ return QOlmError::BadMessageKeyId;
} else if (error_raw.compare("INVALID_BASE64")) {
- return OlmError::InvalidBase64;
+ return QOlmError::InvalidBase64;
} else if (error_raw.compare("NOT_ENOUGH_RANDOM")) {
- return OlmError::NotEnoughRandom;
+ return QOlmError::NotEnoughRandom;
} else if (error_raw.compare("OUTPUT_BUFFER_TOO_SMALL")) {
- return OlmError::OutputBufferTooSmall;
+ return QOlmError::OutputBufferTooSmall;
} else {
- return OlmError::Unknown;
+ return QOlmError::Unknown;
}
}
#endif
diff --git a/lib/crypto/errors.h b/lib/crypto/qolmerrors.h
index 09d2a989..400573c6 100644
--- a/lib/crypto/errors.h
+++ b/lib/crypto/qolmerrors.h
@@ -10,7 +10,7 @@
namespace Quotient {
//! All errors that could be caused by an operation regarding Olm
//! Errors are named exactly like the ones in libolm.
-enum OlmError
+enum QOlmError
{
BadAccountKey,
BadMessageFormat,
@@ -24,7 +24,7 @@ enum OlmError
Unknown,
};
-OlmError fromString(const std::string &error_raw);
+QOlmError fromString(const std::string &error_raw);
} //namespace Quotient
diff --git a/lib/crypto/qolminboundsession.cpp b/lib/crypto/qolminboundsession.cpp
index 539fdc51..8f5056d8 100644
--- a/lib/crypto/qolminboundsession.cpp
+++ b/lib/crypto/qolminboundsession.cpp
@@ -8,7 +8,7 @@
#include <cstring>
using namespace Quotient;
-OlmError lastError(OlmInboundGroupSession *session) {
+QOlmError lastError(OlmInboundGroupSession *session) {
const std::string error_raw = olm_inbound_group_session_last_error(session);
std::cout << error_raw;
@@ -75,7 +75,7 @@ QByteArray QOlmInboundGroupSession::pickle(const PicklingMode &mode) const
return pickledBuf;
}
-std::variant<std::unique_ptr<QOlmInboundGroupSession>, OlmError> QOlmInboundGroupSession::unpickle(QByteArray &pickled, const PicklingMode &mode)
+std::variant<std::unique_ptr<QOlmInboundGroupSession>, QOlmError> QOlmInboundGroupSession::unpickle(QByteArray &pickled, const PicklingMode &mode)
{
QByteArray pickledBuf = pickled;
const auto groupSession = olm_inbound_group_session(new uint8_t[olm_inbound_group_session_size()]);
@@ -90,7 +90,7 @@ std::variant<std::unique_ptr<QOlmInboundGroupSession>, OlmError> QOlmInboundGrou
return std::make_unique<QOlmInboundGroupSession>(groupSession);
}
-std::variant<std::pair<QString, uint32_t>, OlmError> QOlmInboundGroupSession::decrypt(const QByteArray &message)
+std::variant<std::pair<QString, uint32_t>, QOlmError> QOlmInboundGroupSession::decrypt(const QByteArray &message)
{
// This is for capturing the output of olm_group_decrypt
uint32_t messageIndex = 0;
@@ -122,7 +122,7 @@ std::variant<std::pair<QString, uint32_t>, OlmError> QOlmInboundGroupSession::de
return std::make_pair<QString, qint32>(QString(output), messageIndex);
}
-std::variant<QByteArray, OlmError> QOlmInboundGroupSession::exportSession(uint32_t messageIndex)
+std::variant<QByteArray, QOlmError> QOlmInboundGroupSession::exportSession(uint32_t messageIndex)
{
const auto keyLen = olm_export_inbound_group_session_length(m_groupSession);
QByteArray keyBuf(keyLen, '0');
diff --git a/lib/crypto/qolminboundsession.h b/lib/crypto/qolminboundsession.h
index a58fbbbc..6af71cbd 100644
--- a/lib/crypto/qolminboundsession.h
+++ b/lib/crypto/qolminboundsession.h
@@ -10,7 +10,7 @@
#include <variant>
#include <memory>
#include "olm/olm.h"
-#include "crypto/errors.h"
+#include "crypto/qolmerrors.h"
#include "crypto/e2ee.h"
namespace Quotient {
@@ -29,12 +29,12 @@ public:
QByteArray pickle(const PicklingMode &mode) const;
//! Deserialises from encrypted Base64 that was previously obtained by pickling
//! an `OlmInboundGroupSession`.
- static std::variant<std::unique_ptr<QOlmInboundGroupSession>, OlmError> unpickle(QByteArray &picked, const PicklingMode &mode);
+ static std::variant<std::unique_ptr<QOlmInboundGroupSession>, QOlmError> unpickle(QByteArray &picked, const PicklingMode &mode);
//! Decrypts ciphertext received for this group session.
- std::variant<std::pair<QString, uint32_t>, OlmError> decrypt(const QByteArray &message);
+ std::variant<std::pair<QString, uint32_t>, QOlmError> decrypt(const QByteArray &message);
//! Export the base64-encoded ratchet key for this session, at the given index,
//! in a format which can be used by import.
- std::variant<QByteArray, OlmError> exportSession(uint32_t messageIndex);
+ std::variant<QByteArray, QOlmError> exportSession(uint32_t messageIndex);
//! Get the first message index we know how to decrypt.
uint32_t firstKnownIndex() const;
//! Get a base64-encoded identifier for this session.
diff --git a/lib/crypto/message.cpp b/lib/crypto/qolmmessage.cpp
index 830633bf..ae98d52f 100644
--- a/lib/crypto/message.cpp
+++ b/lib/crypto/qolmmessage.cpp
@@ -3,36 +3,36 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#ifdef Quotient_E2EE_ENABLED
-#include "crypto/message.h"
+#include "qolmmessage.h"
using namespace Quotient;
-Message::Message(const QByteArray &ciphertext, Message::Type type)
+QOlmMessage::QOlmMessage(const QByteArray &ciphertext, QOlmMessage::Type type)
: QByteArray(std::move(ciphertext))
, m_messageType(type)
{
Q_ASSERT_X(!ciphertext.isEmpty(), "olm message", "Ciphertext is empty");
}
-Message::Message(const Message &message)
+QOlmMessage::QOlmMessage(const QOlmMessage &message)
: QByteArray(message)
, m_messageType(message.type())
{
}
-Message::Type Message::type() const
+QOlmMessage::Type QOlmMessage::type() const
{
return m_messageType;
}
-QByteArray Message::toCiphertext() const
+QByteArray QOlmMessage::toCiphertext() const
{
return QByteArray(*this);
}
-Message Message::fromCiphertext(const QByteArray &ciphertext)
+QOlmMessage QOlmMessage::fromCiphertext(const QByteArray &ciphertext)
{
- return Message(ciphertext, Message::General);
+ return QOlmMessage(ciphertext, QOlmMessage::General);
}
diff --git a/lib/crypto/message.h b/lib/crypto/qolmmessage.h
index 1ae19ba8..d203364d 100644
--- a/lib/crypto/message.h
+++ b/lib/crypto/qolmmessage.h
@@ -18,7 +18,7 @@ namespace Quotient {
*
* The class provides functions to get a type and the ciphertext.
*/
-class Message : public QByteArray {
+class QOlmMessage : public QByteArray {
Q_GADGET
public:
enum Type {
@@ -27,11 +27,11 @@ public:
};
Q_ENUM(Type)
- Message() = default;
- explicit Message(const QByteArray &ciphertext, Type type = General);
- explicit Message(const Message &message);
+ QOlmMessage() = default;
+ explicit QOlmMessage(const QByteArray &ciphertext, Type type = General);
+ explicit QOlmMessage(const QOlmMessage &message);
- static Message fromCiphertext(const QByteArray &ciphertext);
+ static QOlmMessage fromCiphertext(const QByteArray &ciphertext);
Q_INVOKABLE Type type() const;
Q_INVOKABLE QByteArray toCiphertext() const;
diff --git a/lib/crypto/qolmoutboundsession.cpp b/lib/crypto/qolmoutboundsession.cpp
index 3bfb0187..14b7368e 100644
--- a/lib/crypto/qolmoutboundsession.cpp
+++ b/lib/crypto/qolmoutboundsession.cpp
@@ -3,12 +3,12 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#ifdef Quotient_E2EE_ENABLED
-#include "crypto/qolmoutboundsession.h"
-#include "crypto/utils.h"
+#include "qolmoutboundsession.h"
+#include "crypto/qolmutils.h"
using namespace Quotient;
-OlmError lastError(OlmOutboundGroupSession *session) {
+QOlmError lastError(OlmOutboundGroupSession *session) {
const std::string error_raw = olm_outbound_group_session_last_error(session);
return fromString(error_raw);
@@ -48,7 +48,7 @@ std::unique_ptr<QOlmOutboundGroupSession> QOlmOutboundGroupSession::create()
return std::make_unique<QOlmOutboundGroupSession>(olmOutboundGroupSession);
}
-std::variant<QByteArray, OlmError> QOlmOutboundGroupSession::pickle(const PicklingMode &mode)
+std::variant<QByteArray, QOlmError> QOlmOutboundGroupSession::pickle(const PicklingMode &mode)
{
QByteArray pickledBuf(olm_pickle_outbound_group_session_length(m_groupSession), '0');
QByteArray key = toKey(mode);
@@ -65,7 +65,7 @@ std::variant<QByteArray, OlmError> QOlmOutboundGroupSession::pickle(const Pickli
}
-std::variant<std::unique_ptr<QOlmOutboundGroupSession>, OlmError> QOlmOutboundGroupSession::unpickle(QByteArray &pickled, const PicklingMode &mode)
+std::variant<std::unique_ptr<QOlmOutboundGroupSession>, QOlmError> QOlmOutboundGroupSession::unpickle(QByteArray &pickled, const PicklingMode &mode)
{
QByteArray pickledBuf = pickled;
auto *olmOutboundGroupSession = olm_outbound_group_session(new uint8_t[olm_outbound_group_session_size()]);
@@ -84,7 +84,7 @@ std::variant<std::unique_ptr<QOlmOutboundGroupSession>, OlmError> QOlmOutboundGr
return std::make_unique<QOlmOutboundGroupSession>(olmOutboundGroupSession);
}
-std::variant<QByteArray, OlmError> QOlmOutboundGroupSession::encrypt(const QString &plaintext)
+std::variant<QByteArray, QOlmError> QOlmOutboundGroupSession::encrypt(const QString &plaintext)
{
QByteArray plaintextBuf = plaintext.toUtf8();
const auto messageMaxLen = olm_group_encrypt_message_length(m_groupSession, plaintextBuf.length());
@@ -116,7 +116,7 @@ QByteArray QOlmOutboundGroupSession::sessionId() const
return idBuffer;
}
-std::variant<QByteArray, OlmError> QOlmOutboundGroupSession::sessionKey() const
+std::variant<QByteArray, QOlmError> QOlmOutboundGroupSession::sessionKey() const
{
const auto keyMaxLength = olm_outbound_group_session_key_length(m_groupSession);
QByteArray keyBuffer(keyMaxLength, '0');
diff --git a/lib/crypto/qolmoutboundsession.h b/lib/crypto/qolmoutboundsession.h
index 6c6c635c..6b4fd30b 100644
--- a/lib/crypto/qolmoutboundsession.h
+++ b/lib/crypto/qolmoutboundsession.h
@@ -4,8 +4,8 @@
#pragma once
#ifdef Quotient_E2EE_ENABLED
-#include "olm/olm.h" // from Olm
-#include "crypto/errors.h"
+#include "olm/olm.h"
+#include "crypto/qolmerrors.h"
#include "crypto/e2ee.h"
#include <memory>
@@ -22,12 +22,12 @@ public:
//! Throw OlmError on errors
static std::unique_ptr<QOlmOutboundGroupSession> create();
//! Serialises an `QOlmOutboundGroupSession` to encrypted Base64.
- std::variant<QByteArray, OlmError> pickle(const PicklingMode &mode);
+ std::variant<QByteArray, QOlmError> pickle(const PicklingMode &mode);
//! Deserialises from encrypted Base64 that was previously obtained by
//! pickling a `QOlmOutboundGroupSession`.
- static std::variant<std::unique_ptr<QOlmOutboundGroupSession>, OlmError> unpickle(QByteArray &pickled, const PicklingMode &mode);
+ static std::variant<std::unique_ptr<QOlmOutboundGroupSession>, QOlmError> unpickle(QByteArray &pickled, const PicklingMode &mode);
//! Encrypts a plaintext message using the session.
- std::variant<QByteArray, OlmError> encrypt(const QString &plaintext);
+ std::variant<QByteArray, QOlmError> encrypt(const QString &plaintext);
//! Get the current message index for this session.
//!
@@ -42,7 +42,7 @@ public:
//!
//! Each message is sent with a different ratchet key. This function returns the
//! ratchet key that will be used for the next message.
- std::variant<QByteArray, OlmError> sessionKey() const;
+ std::variant<QByteArray, QOlmError> sessionKey() const;
QOlmOutboundGroupSession(OlmOutboundGroupSession *groupSession);
private:
OlmOutboundGroupSession *m_groupSession;
diff --git a/lib/crypto/qolmsession.cpp b/lib/crypto/qolmsession.cpp
index afa42728..cfe21650 100644
--- a/lib/crypto/qolmsession.cpp
+++ b/lib/crypto/qolmsession.cpp
@@ -1,29 +1,243 @@
-// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
+// SPDX-FileCopyrightText: 2021 Alexey Andreyev <aa13q@ya.ru>
//
// SPDX-License-Identifier: LGPL-2.1-or-later
-#include "crypto/qolmsession.h"
+#ifdef Quotient_E2EE_ENABLED
+#include "qolmsession.h"
+#include "crypto/qolmutils.h"
+#include "logging.h"
+#include <cstring>
+#include <QDebug>
using namespace Quotient;
-std::optional<OlmMessage> fromTypeAndCipthertext(size_t messageType, const QByteArray &ciphertext)
+QOlmError lastError(OlmSession* session) {
+ const std::string error_raw = olm_session_last_error(session);
+
+ return fromString(error_raw);
+}
+
+Quotient::QOlmSession::~QOlmSession()
+{
+ olm_clear_session(m_session);
+ delete[](reinterpret_cast<uint8_t *>(m_session));
+}
+
+OlmSession* QOlmSession::create()
{
- if (messageType == OLM_MESSAGE_TYPE_PRE_KEY) {
- return PreKeyMessage { ciphertext };
- } else if (messageType == OLM_MESSAGE_TYPE_MESSAGE) {
- return Message { ciphertext };
+ return olm_session(new uint8_t[olm_session_size()]);
+}
+
+std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmSession::createInbound(QOlmAccount *account, const QOlmMessage &preKeyMessage, bool from, const QString &theirIdentityKey)
+{
+ if (preKeyMessage.type() != QOlmMessage::PreKey) {
+ qCDebug(E2EE) << "The message is not a pre-key";
+ throw BadMessageFormat;
}
- return std::nullopt;
+
+ const auto olmSession = create();
+
+ QByteArray oneTimeKeyMessageBuf = preKeyMessage.toCiphertext();
+ QByteArray theirIdentityKeyBuf = theirIdentityKey.toUtf8();
+ size_t error = 0;
+ if (from) {
+ error = olm_create_inbound_session_from(olmSession, account->data(), theirIdentityKeyBuf.data(), theirIdentityKeyBuf.length(), oneTimeKeyMessageBuf.data(), oneTimeKeyMessageBuf.length());
+ } else {
+ error = olm_create_inbound_session(olmSession, account->data(), oneTimeKeyMessageBuf.data(), oneTimeKeyMessageBuf.length());
+ }
+
+ if (error == olm_error()) {
+ const auto lastErr = lastError(olmSession);
+ if (lastErr == QOlmError::NotEnoughRandom) {
+ throw lastErr;
+ }
+ return lastErr;
+ }
+
+ return std::make_unique<QOlmSession>(olmSession);
}
-std::pair<OlmMessageType, QByteArray> toPair(const OlmMessage &message)
+std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmSession::createInboundSession(QOlmAccount *account, const QOlmMessage &preKeyMessage)
{
- return std::visit([](auto &arg) {
- using T = std::decay_t<decltype(arg)>;
- if constexpr (std::is_same_v<T, Message>) {
- return std::make_pair<OlmMessageType, QByteArray>(MessageType, QByteArray(arg.message));
- } else if constexpr (std::is_same_v<T, PreKeyMessage>) {
- return std::make_pair<OlmMessageType, QByteArray>(PreKeyType, QByteArray(arg.message));
+ return createInbound(account, preKeyMessage);
+}
+
+std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmSession::createInboundSessionFrom(QOlmAccount *account, const QString &theirIdentityKey, const QOlmMessage &preKeyMessage)
+{
+ return createInbound(account, preKeyMessage, true, theirIdentityKey);
+}
+
+std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmSession::createOutboundSession(QOlmAccount *account, const QString &theirIdentityKey, const QString &theirOneTimeKey)
+{
+ auto *olmOutboundSession = create();
+ const auto randomLen = olm_create_outbound_session_random_length(olmOutboundSession);
+ QByteArray randomBuf = getRandom(randomLen);
+
+ QByteArray theirIdentityKeyBuf = theirIdentityKey.toUtf8();
+ QByteArray theirOneTimeKeyBuf = theirOneTimeKey.toUtf8();
+ const auto error = olm_create_outbound_session(olmOutboundSession,
+ account->data(),
+ reinterpret_cast<uint8_t *>(theirIdentityKeyBuf.data()), theirIdentityKeyBuf.length(),
+ reinterpret_cast<uint8_t *>(theirOneTimeKeyBuf.data()), theirOneTimeKeyBuf.length(),
+ reinterpret_cast<uint8_t *>(randomBuf.data()), randomBuf.length());
+
+ if (error == olm_error()) {
+ const auto lastErr = lastError(olmOutboundSession);
+ if (lastErr == QOlmError::NotEnoughRandom) {
+ throw lastErr;
}
- }, message);
+ return lastErr;
+ }
+
+ randomBuf.clear();
+ return std::make_unique<QOlmSession>(olmOutboundSession);
+}
+
+std::variant<QByteArray, QOlmError> QOlmSession::pickle(const PicklingMode &mode)
+{
+ QByteArray pickledBuf(olm_pickle_session_length(m_session), '0');
+ QByteArray key = toKey(mode);
+ const auto error = olm_pickle_session(m_session, key.data(), key.length(),
+ pickledBuf.data(), pickledBuf.length());
+
+ if (error == olm_error()) {
+ return lastError(m_session);
+ }
+
+ key.clear();
+
+ return pickledBuf;
+}
+
+std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmSession::unpickle(const QByteArray &pickled, const PicklingMode &mode)
+{
+ QByteArray pickledBuf = pickled;
+ auto *olmSession = create();
+ QByteArray key = toKey(mode);
+ const auto error = olm_unpickle_session(olmSession, key.data(), key.length(),
+ pickledBuf.data(), pickledBuf.length());
+ if (error == olm_error()) {
+ return lastError(olmSession);
+ }
+
+ key.clear();
+ return std::make_unique<QOlmSession>(olmSession);
}
+
+QOlmMessage QOlmSession::encrypt(const QString &plaintext)
+{
+ QByteArray plaintextBuf = plaintext.toUtf8();
+ const auto messageMaxLen = olm_encrypt_message_length(m_session, plaintextBuf.length());
+ QByteArray messageBuf(messageMaxLen, '0');
+ const auto messageType = encryptMessageType();
+ const auto randomLen = olm_encrypt_random_length(m_session);
+ QByteArray randomBuf = getRandom(randomLen);
+ const auto error = olm_encrypt(m_session,
+ reinterpret_cast<uint8_t *>(plaintextBuf.data()), plaintextBuf.length(),
+ reinterpret_cast<uint8_t *>(randomBuf.data()), randomBuf.length(),
+ reinterpret_cast<uint8_t *>(messageBuf.data()), messageBuf.length());
+
+ if (error == olm_error()) {
+ throw lastError(m_session);
+ }
+
+ return QOlmMessage(messageBuf, messageType);
+}
+
+std::variant<QString, QOlmError> QOlmSession::decrypt(const QOlmMessage &message) const
+{
+ const auto messageType = message.type();
+ const auto ciphertext = message.toCiphertext();
+ const auto messageTypeValue = messageType == QOlmMessage::Type::General
+ ? OLM_MESSAGE_TYPE_MESSAGE : OLM_MESSAGE_TYPE_PRE_KEY;
+
+ // We need to clone the message because
+ // olm_decrypt_max_plaintext_length destroys the input buffer
+ QByteArray messageBuf(ciphertext.length(), '0');
+ std::copy(message.begin(), message.end(), messageBuf.begin());
+
+ const auto plaintextMaxLen = olm_decrypt_max_plaintext_length(m_session, messageTypeValue,
+ reinterpret_cast<uint8_t *>(messageBuf.data()), messageBuf.length());
+
+ if (plaintextMaxLen == olm_error()) {
+ return lastError(m_session);
+ }
+
+ QByteArray plaintextBuf(plaintextMaxLen, '0');
+ QByteArray messageBuf2(ciphertext.length(), '0');
+ std::copy(message.begin(), message.end(), messageBuf2.begin());
+
+ const auto plaintextResultLen = olm_decrypt(m_session, messageTypeValue,
+ reinterpret_cast<uint8_t *>(messageBuf2.data()), messageBuf2.length(),
+ reinterpret_cast<uint8_t *>(plaintextBuf.data()), plaintextMaxLen);
+
+ if (plaintextResultLen == olm_error()) {
+ const auto lastErr = lastError(m_session);
+ if (lastErr == QOlmError::OutputBufferTooSmall) {
+ throw lastErr;
+ }
+ return lastErr;
+ }
+ QByteArray output(plaintextResultLen, '0');
+ std::memcpy(output.data(), plaintextBuf.data(), plaintextResultLen);
+ plaintextBuf.clear();
+ return output;
+}
+
+QOlmMessage::Type QOlmSession::encryptMessageType()
+{
+ const auto messageTypeResult = olm_encrypt_message_type(m_session);
+ if (messageTypeResult == olm_error()) {
+ throw lastError(m_session);
+ }
+ if (messageTypeResult == OLM_MESSAGE_TYPE_PRE_KEY) {
+ return QOlmMessage::PreKey;
+ }
+ return QOlmMessage::General;
+}
+
+QByteArray QOlmSession::sessionId() const
+{
+ const auto idMaxLength = olm_session_id_length(m_session);
+ QByteArray idBuffer(idMaxLength, '0');
+ const auto error = olm_session_id(m_session, reinterpret_cast<uint8_t *>(idBuffer.data()),
+ idBuffer.length());
+ if (error == olm_error()) {
+ throw lastError(m_session);
+ }
+ return idBuffer;
+}
+
+bool QOlmSession::hasReceivedMessage() const
+{
+ return olm_session_has_received_message(m_session);
+}
+
+std::variant<bool, QOlmError> QOlmSession::matchesInboundSession(QOlmMessage &preKeyMessage)
+{
+ Q_ASSERT(preKeyMessage.type() == QOlmMessage::Type::PreKey);
+ QByteArray oneTimeKeyBuf(preKeyMessage.data());
+ const auto matchesResult = olm_matches_inbound_session(m_session, oneTimeKeyBuf.data(), oneTimeKeyBuf.length());
+
+ if (matchesResult == olm_error()) {
+ return lastError(m_session);
+ }
+ switch (matchesResult) {
+ case 0:
+ return false;
+ case 1:
+ return true;
+ default:
+ return QOlmError::Unknown;
+ }
+}
+
+QOlmSession::QOlmSession(OlmSession *session)
+ : m_session(session)
+{
+}
+
+#endif // Quotient_E2EE_ENABLED
+
+
+
diff --git a/lib/crypto/qolmsession.cpp.back b/lib/crypto/qolmsession.cpp.back
new file mode 100644
index 00000000..ee8b2a7f
--- /dev/null
+++ b/lib/crypto/qolmsession.cpp.back
@@ -0,0 +1,29 @@
+// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
+//
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#include "olm/qolmsession.h"
+
+using namespace Quotient;
+
+std::optional<OlmMessage> fromTypeAndCipthertext(size_t messageType, const QByteArray &ciphertext)
+{
+ if (messageType == OLM_MESSAGE_TYPE_PRE_KEY) {
+ return PreKeyMessage { ciphertext };
+ } else if (messageType == OLM_MESSAGE_TYPE_MESSAGE) {
+ return QOlmMessage { ciphertext };
+ }
+ return std::nullopt;
+}
+
+std::pair<OlmMessageType, QByteArray> toPair(const OlmMessage &message)
+{
+ return std::visit([](auto &arg) {
+ using T = std::decay_t<decltype(arg)>;
+ if constexpr (std::is_same_v<T, QOlmMessage>) {
+ return std::make_pair<OlmMessageType, QByteArray>(MessageType, QByteArray(arg.message));
+ } else if constexpr (std::is_same_v<T, PreKeyMessage>) {
+ return std::make_pair<OlmMessageType, QByteArray>(PreKeyType, QByteArray(arg.message));
+ }
+ }, message);
+}
diff --git a/lib/crypto/qolmsession.h b/lib/crypto/qolmsession.h
index 3be3c7fc..6e13801e 100644
--- a/lib/crypto/qolmsession.h
+++ b/lib/crypto/qolmsession.h
@@ -1,49 +1,77 @@
-// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
+// SPDX-FileCopyrightText: 2021 Alexey Andreyev <aa13q@ya.ru>
//
// SPDX-License-Identifier: LGPL-2.1-or-later
#pragma once
-#include <variant>
-#include <olm/olm.h>
+#ifdef Quotient_E2EE_ENABLED
+
+#include <QDebug>
+#include <olm/olm.h> // FIXME: OlmSession
#include "crypto/e2ee.h"
-#include "crypto/errors.h"
+#include "crypto/qolmmessage.h"
+#include "crypto/qolmerrors.h"
+#include "crypto/qolmaccount.h"
namespace Quotient {
-//! An encrypted Olm message.
-struct Message {
- QByteArray message;
-};
+class QOlmAccount;
+class QOlmSession;
-//! A encrypted Olm pre-key message.
-//!
-//! This message, unlike a normal Message, can be used to create new Olm sessions.
-struct PreKeyMessage
-{
- QByteArray message;
-};
-enum OlmMessageType
+//! Either an outbound or inbound session for secure communication.
+class QOlmSession
{
- PreKeyType,
- MessageType,
-};
+public:
+ ~QOlmSession();
+ //! Creates an inbound session for sending/receiving messages from a received 'prekey' message.
+ static std::variant<std::unique_ptr<QOlmSession>, QOlmError> createInboundSession(QOlmAccount *account, const QOlmMessage &preKeyMessage);
+ static std::variant<std::unique_ptr<QOlmSession>, QOlmError> createInboundSessionFrom(QOlmAccount *account, const QString &theirIdentityKey, const QOlmMessage &preKeyMessage);
+ static std::variant<std::unique_ptr<QOlmSession>, QOlmError> createOutboundSession(QOlmAccount *account, const QString &theirIdentityKey, const QString &theirOneTimeKey);
+ //! Serialises an `QOlmSession` to encrypted Base64.
+ std::variant<QByteArray, QOlmError> pickle(const PicklingMode &mode);
+ //! Deserialises from encrypted Base64 that was previously obtained by pickling a `QOlmSession`.
+ static std::variant<std::unique_ptr<QOlmSession>, QOlmError> unpickle(const QByteArray &pickled, const PicklingMode &mode);
+ //! Encrypts a plaintext message using the session.
+ QOlmMessage encrypt(const QString &plaintext);
-using OlmMessage = std::variant<Message, PreKeyMessage>;
+ //! Decrypts a message using this session. Decoding is lossy, meaing if
+ //! the decrypted plaintext contains invalid UTF-8 symbols, they will
+ //! be returned as `U+FFFD` (�).
+ std::variant<QString, QOlmError> decrypt(const QOlmMessage &message) const;
-std::optional<OlmMessage> fromTypeAndCipthertext(size_t messageType, const QByteArray &ciphertext);
+ //! Get a base64-encoded identifier for this session.
+ QByteArray sessionId() const;
-std::pair<OlmMessageType, QByteArray> toPair(const OlmMessage &message);
+ //! The type of the next message that will be returned from encryption.
+ QOlmMessage::Type encryptMessageType();
-//class QOlmSession
-//{
-// /// Creates an inbound session for sending/receiving messages from a received 'prekey' message.
-// static std::variant<std::unique_ptr<QOlmSession>, OlmError> createInboundSession(const QOlmAccount &account,
-// PreKeyMessage &message);
-//
-////private:
-// //static std::variant<std::unique_ptr<QOlmSession>, OlmError> createSessionWith(std::function<std::variant<size_t(OlmSession *)>> func);
-//}
+ //! Checker for any received messages for this session.
+ bool hasReceivedMessage() const;
+
+ //! Checks if the 'prekey' message is for this in-bound session.
+ std::variant<bool, QOlmError> matchesInboundSession(QOlmMessage &preKeyMessage);
+
+ friend bool operator<(const QOlmSession& lhs, const QOlmSession& rhs)
+ {
+ return lhs.sessionId() < rhs.sessionId();
+ }
+
+ friend bool operator<(const std::unique_ptr<QOlmSession> &lhs, const std::unique_ptr<QOlmSession> &rhs) {
+ return *lhs < *rhs;
+ }
+
+ QOlmSession(OlmSession* session);
+private:
+ //! Helper function for creating new sessions and handling errors.
+ static OlmSession* create();
+ static std::variant<std::unique_ptr<QOlmSession>, QOlmError> createInbound(QOlmAccount *account, const QOlmMessage& preKeyMessage, bool from = false, const QString& theirIdentityKey = "");
+ OlmSession* m_session;
+};
+
+
+//using QOlmSessionPtr = std::unique_ptr<QOlmSession>;
+
+} //namespace Quotient
-}
+#endif // Quotient_E2EE_ENABLED
diff --git a/lib/crypto/qolmsession.h.back b/lib/crypto/qolmsession.h.back
new file mode 100644
index 00000000..cbba5cef
--- /dev/null
+++ b/lib/crypto/qolmsession.h.back
@@ -0,0 +1,49 @@
+// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
+//
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#pragma once
+
+#include "olm/e2ee.h"
+#include "olm/olm.h"
+#include "olm/errors.h"
+#include <variant>
+
+namespace Quotient {
+
+//! An encrypted Olm message.
+struct QOlmMessage {
+ QByteArray message;
+};
+
+//! A encrypted Olm pre-key message.
+//!
+//! This message, unlike a normal Message, can be used to create new Olm sessions.
+struct PreKeyMessage
+{
+ QByteArray message;
+};
+
+enum OlmMessageType
+{
+ PreKeyType,
+ MessageType,
+};
+
+using OlmMessage = std::variant<QOlmMessage, PreKeyMessage>;
+
+std::optional<OlmMessage> fromTypeAndCipthertext(size_t messageType, const QByteArray &ciphertext);
+
+std::pair<OlmMessageType, QByteArray> toPair(const OlmMessage &message);
+
+//class QOlmSession
+//{
+// /// Creates an inbound session for sending/receiving messages from a received 'prekey' message.
+// static std::variant<std::unique_ptr<QOlmSession>, OlmError> createInboundSession(const QOlmAccount &account,
+// PreKeyMessage &message);
+//
+////private:
+// //static std::variant<std::unique_ptr<QOlmSession>, OlmError> createSessionWith(std::function<std::variant<size_t(OlmSession *)>> func);
+//}
+
+}
diff --git a/lib/crypto/utils.cpp b/lib/crypto/qolmutils.cpp
index cb20abf8..a486ea0f 100644
--- a/lib/crypto/utils.cpp
+++ b/lib/crypto/qolmutils.cpp
@@ -3,7 +3,7 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#ifdef Quotient_E2EE_ENABLED
-#include "crypto/utils.h"
+#include "crypto/qolmutils.h"
#include <QDebug>
#include <openssl/rand.h>
diff --git a/lib/crypto/utils.h b/lib/crypto/qolmutils.h
index cea87144..11e9f3cc 100644
--- a/lib/crypto/utils.h
+++ b/lib/crypto/qolmutils.h
@@ -5,6 +5,8 @@
#pragma once
#ifdef Quotient_E2EE_ENABLED
+#include <QByteArray>
+
#include "crypto/e2ee.h"
namespace Quotient {
diff --git a/lib/crypto/session.cpp b/lib/crypto/session.cpp
deleted file mode 100644
index 8b2cb022..00000000
--- a/lib/crypto/session.cpp
+++ /dev/null
@@ -1,242 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Alexey Andreyev <aa13q@ya.ru>
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-
-#ifdef Quotient_E2EE_ENABLED
-#include "crypto/session.h"
-#include "crypto/utils.h"
-#include "logging.h"
-#include <cstring>
-
-using namespace Quotient;
-
-OlmError lastError(OlmSession* session) {
- const std::string error_raw = olm_session_last_error(session);
-
- return fromString(error_raw);
-}
-
-Quotient::QOlmSession::~QOlmSession()
-{
- olm_clear_session(m_session);
- delete[](reinterpret_cast<uint8_t *>(m_session));
-}
-
-OlmSession* QOlmSession::create()
-{
- return olm_session(new uint8_t[olm_session_size()]);
-}
-
-std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmSession::createInbound(QOlmAccount *account, const Message &preKeyMessage, bool from, const QString &theirIdentityKey)
-{
- if (preKeyMessage.type() != Message::PreKey) {
- qCDebug(E2EE) << "The message is not a pre-key";
- throw BadMessageFormat;
- }
-
- const auto olmSession = create();
-
- QByteArray oneTimeKeyMessageBuf = preKeyMessage.toCiphertext();
- QByteArray theirIdentityKeyBuf = theirIdentityKey.toUtf8();
- size_t error = 0;
- if (from) {
- error = olm_create_inbound_session_from(olmSession, account->data(), theirIdentityKeyBuf.data(), theirIdentityKeyBuf.length(), oneTimeKeyMessageBuf.data(), oneTimeKeyMessageBuf.length());
- } else {
- error = olm_create_inbound_session(olmSession, account->data(), oneTimeKeyMessageBuf.data(), oneTimeKeyMessageBuf.length());
- }
-
- if (error == olm_error()) {
- const auto lastErr = lastError(olmSession);
- if (lastErr == OlmError::NotEnoughRandom) {
- throw lastErr;
- }
- return lastErr;
- }
-
- return std::make_unique<QOlmSession>(olmSession);
-}
-
-std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmSession::createInboundSession(QOlmAccount *account, const Message &preKeyMessage)
-{
- return createInbound(account, preKeyMessage);
-}
-
-std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmSession::createInboundSessionFrom(QOlmAccount *account, const QString &theirIdentityKey, const Message &preKeyMessage)
-{
- return createInbound(account, preKeyMessage, true, theirIdentityKey);
-}
-
-std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmSession::createOutboundSession(QOlmAccount *account, const QString &theirIdentityKey, const QString &theirOneTimeKey)
-{
- auto *olmOutboundSession = create();
- const auto randomLen = olm_create_outbound_session_random_length(olmOutboundSession);
- QByteArray randomBuf = getRandom(randomLen);
-
- QByteArray theirIdentityKeyBuf = theirIdentityKey.toUtf8();
- QByteArray theirOneTimeKeyBuf = theirOneTimeKey.toUtf8();
- const auto error = olm_create_outbound_session(olmOutboundSession,
- account->data(),
- reinterpret_cast<uint8_t *>(theirIdentityKeyBuf.data()), theirIdentityKeyBuf.length(),
- reinterpret_cast<uint8_t *>(theirOneTimeKeyBuf.data()), theirOneTimeKeyBuf.length(),
- reinterpret_cast<uint8_t *>(randomBuf.data()), randomBuf.length());
-
- if (error == olm_error()) {
- const auto lastErr = lastError(olmOutboundSession);
- if (lastErr == OlmError::NotEnoughRandom) {
- throw lastErr;
- }
- return lastErr;
- }
-
- randomBuf.clear();
- return std::make_unique<QOlmSession>(olmOutboundSession);
-}
-
-std::variant<QByteArray, OlmError> QOlmSession::pickle(const PicklingMode &mode)
-{
- QByteArray pickledBuf(olm_pickle_session_length(m_session), '0');
- QByteArray key = toKey(mode);
- const auto error = olm_pickle_session(m_session, key.data(), key.length(),
- pickledBuf.data(), pickledBuf.length());
-
- if (error == olm_error()) {
- return lastError(m_session);
- }
-
- key.clear();
-
- return pickledBuf;
-}
-
-std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmSession::unpickle(const QByteArray &pickled, const PicklingMode &mode)
-{
- QByteArray pickledBuf = pickled;
- auto *olmSession = create();
- QByteArray key = toKey(mode);
- const auto error = olm_unpickle_session(olmSession, key.data(), key.length(),
- pickledBuf.data(), pickledBuf.length());
- if (error == olm_error()) {
- return lastError(olmSession);
- }
-
- key.clear();
- return std::make_unique<QOlmSession>(olmSession);
-}
-
-Message QOlmSession::encrypt(const QString &plaintext)
-{
- QByteArray plaintextBuf = plaintext.toUtf8();
- const auto messageMaxLen = olm_encrypt_message_length(m_session, plaintextBuf.length());
- QByteArray messageBuf(messageMaxLen, '0');
- const auto messageType = encryptMessageType();
- const auto randomLen = olm_encrypt_random_length(m_session);
- QByteArray randomBuf = getRandom(randomLen);
- const auto error = olm_encrypt(m_session,
- reinterpret_cast<uint8_t *>(plaintextBuf.data()), plaintextBuf.length(),
- reinterpret_cast<uint8_t *>(randomBuf.data()), randomBuf.length(),
- reinterpret_cast<uint8_t *>(messageBuf.data()), messageBuf.length());
-
- if (error == olm_error()) {
- throw lastError(m_session);
- }
-
- return Message(messageBuf, messageType);
-}
-
-std::variant<QString, OlmError> QOlmSession::decrypt(const Message &message) const
-{
- const auto messageType = message.type();
- const auto ciphertext = message.toCiphertext();
- const auto messageTypeValue = messageType == Message::Type::General
- ? OLM_MESSAGE_TYPE_MESSAGE : OLM_MESSAGE_TYPE_PRE_KEY;
-
- // We need to clone the message because
- // olm_decrypt_max_plaintext_length destroys the input buffer
- QByteArray messageBuf(ciphertext.length(), '0');
- std::copy(message.begin(), message.end(), messageBuf.begin());
-
- const auto plaintextMaxLen = olm_decrypt_max_plaintext_length(m_session, messageTypeValue,
- reinterpret_cast<uint8_t *>(messageBuf.data()), messageBuf.length());
-
- if (plaintextMaxLen == olm_error()) {
- return lastError(m_session);
- }
-
- QByteArray plaintextBuf(plaintextMaxLen, '0');
- QByteArray messageBuf2(ciphertext.length(), '0');
- std::copy(message.begin(), message.end(), messageBuf2.begin());
-
- const auto plaintextResultLen = olm_decrypt(m_session, messageTypeValue,
- reinterpret_cast<uint8_t *>(messageBuf2.data()), messageBuf2.length(),
- reinterpret_cast<uint8_t *>(plaintextBuf.data()), plaintextMaxLen);
-
- if (plaintextResultLen == olm_error()) {
- const auto lastErr = lastError(m_session);
- if (lastErr == OlmError::OutputBufferTooSmall) {
- throw lastErr;
- }
- return lastErr;
- }
- QByteArray output(plaintextResultLen, '0');
- std::memcpy(output.data(), plaintextBuf.data(), plaintextResultLen);
- plaintextBuf.clear();
- return output;
-}
-
-Message::Type QOlmSession::encryptMessageType()
-{
- const auto messageTypeResult = olm_encrypt_message_type(m_session);
- if (messageTypeResult == olm_error()) {
- throw lastError(m_session);
- }
- if (messageTypeResult == OLM_MESSAGE_TYPE_PRE_KEY) {
- return Message::PreKey;
- }
- return Message::General;
-}
-
-QByteArray QOlmSession::sessionId() const
-{
- const auto idMaxLength = olm_session_id_length(m_session);
- QByteArray idBuffer(idMaxLength, '0');
- const auto error = olm_session_id(m_session, reinterpret_cast<uint8_t *>(idBuffer.data()),
- idBuffer.length());
- if (error == olm_error()) {
- throw lastError(m_session);
- }
- return idBuffer;
-}
-
-bool QOlmSession::hasReceivedMessage() const
-{
- return olm_session_has_received_message(m_session);
-}
-
-std::variant<bool, OlmError> QOlmSession::matchesInboundSession(Message &preKeyMessage)
-{
- Q_ASSERT(preKeyMessage.type() == Message::Type::PreKey);
- QByteArray oneTimeKeyBuf(preKeyMessage.data());
- const auto matchesResult = olm_matches_inbound_session(m_session, oneTimeKeyBuf.data(), oneTimeKeyBuf.length());
-
- if (matchesResult == olm_error()) {
- return lastError(m_session);
- }
- switch (matchesResult) {
- case 0:
- return false;
- case 1:
- return true;
- default:
- return OlmError::Unknown;
- }
-}
-
-QOlmSession::QOlmSession(OlmSession *session)
- : m_session(session)
-{
-}
-
-#endif // Quotient_E2EE_ENABLED
-
-
-
diff --git a/lib/crypto/session.h b/lib/crypto/session.h
deleted file mode 100644
index 24702564..00000000
--- a/lib/crypto/session.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Alexey Andreyev <aa13q@ya.ru>
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-
-#pragma once
-
-#ifdef Quotient_E2EE_ENABLED
-
-#include <QDebug>
-#include <olm/olm.h>
-#include "crypto/e2ee.h"
-#include "crypto/message.h"
-#include "crypto/errors.h"
-#include "crypto/qolmaccount.h"
-
-namespace Quotient {
-
-class QOlmAccount;
-class QOlmSession;
-
-
-//! Either an outbound or inbound session for secure communication.
-class QOlmSession
-{
-public:
- ~QOlmSession();
- //! Creates an inbound session for sending/receiving messages from a received 'prekey' message.
- static std::variant<std::unique_ptr<QOlmSession>, OlmError> createInboundSession(QOlmAccount *account, const Message &preKeyMessage);
- static std::variant<std::unique_ptr<QOlmSession>, OlmError> createInboundSessionFrom(QOlmAccount *account, const QString &theirIdentityKey, const Message &preKeyMessage);
- static std::variant<std::unique_ptr<QOlmSession>, OlmError> createOutboundSession(QOlmAccount *account, const QString &theirIdentityKey, const QString &theirOneTimeKey);
- //! Serialises an `QOlmSession` to encrypted Base64.
- std::variant<QByteArray, OlmError> pickle(const PicklingMode &mode);
- //! Deserialises from encrypted Base64 that was previously obtained by pickling a `QOlmSession`.
- static std::variant<std::unique_ptr<QOlmSession>, OlmError> unpickle(const QByteArray &pickled, const PicklingMode &mode);
- //! Encrypts a plaintext message using the session.
- Message encrypt(const QString &plaintext);
-
- //! Decrypts a message using this session. Decoding is lossy, meaing if
- //! the decrypted plaintext contains invalid UTF-8 symbols, they will
- //! be returned as `U+FFFD` (�).
- std::variant<QString, OlmError> decrypt(const Message &message) const;
-
- //! Get a base64-encoded identifier for this session.
- QByteArray sessionId() const;
-
- //! The type of the next message that will be returned from encryption.
- Message::Type encryptMessageType();
-
- //! Checker for any received messages for this session.
- bool hasReceivedMessage() const;
-
- //! Checks if the 'prekey' message is for this in-bound session.
- std::variant<bool, OlmError> matchesInboundSession(Message &preKeyMessage);
-
- friend bool operator<(const QOlmSession& lhs, const QOlmSession& rhs)
- {
- return lhs.sessionId() < rhs.sessionId();
- }
-
- friend bool operator<(const std::unique_ptr<QOlmSession> &lhs, const std::unique_ptr<QOlmSession> &rhs) {
- return *lhs < *rhs;
- }
-
- QOlmSession(OlmSession* session);
-private:
- //! Helper function for creating new sessions and handling errors.
- static OlmSession* create();
- static std::variant<std::unique_ptr<QOlmSession>, OlmError> createInbound(QOlmAccount *account, const Message& preKeyMessage, bool from = false, const QString& theirIdentityKey = "");
- OlmSession* m_session;
-};
-
-
-//using QOlmSessionPtr = std::unique_ptr<QOlmSession>;
-
-} //namespace Quotient
-
-#endif // Quotient_E2EE_ENABLED