aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlexey Rusakov <Kitsune-Ral@users.sf.net>2022-09-26 09:44:20 +0200
committerAlexey Rusakov <Kitsune-Ral@users.sf.net>2022-09-26 10:46:34 +0200
commit363a7e40e8aa12cb780b076cca8db4f47b70f4fa (patch)
treee5c8d796415114f46c84ba39f25a42c4ad400311 /lib
parenta923750c7a1efadaa66f24dc17010063776e6246 (diff)
downloadlibquotient-363a7e40e8aa12cb780b076cca8db4f47b70f4fa.tar.gz
libquotient-363a7e40e8aa12cb780b076cca8db4f47b70f4fa.zip
Replace QOlmError with OlmErrorCode
QOlmError represents a subset of OlmErrorCode, and the associated fromString() function uses undocumented strings produced inside Olm; meanwhile OlmErrorCode is documented in its own header file. Each QOlm* class now has lastErrorCode() next to lastError() (that, from now, returns a textual representation straight from Olm, not QOlmError enum). Also: including olm/error.h in e2ee/e2ee.h required some rearrangement of the code to make sure non-E2EE configuration still builds.
Diffstat (limited to 'lib')
-rw-r--r--lib/connection.cpp3
-rw-r--r--lib/e2ee/e2ee.h36
-rw-r--r--lib/e2ee/qolmaccount.cpp82
-rw-r--r--lib/e2ee/qolmaccount.h9
-rw-r--r--lib/e2ee/qolmerrors.cpp25
-rw-r--r--lib/e2ee/qolmerrors.h28
-rw-r--r--lib/e2ee/qolminboundsession.cpp84
-rw-r--r--lib/e2ee/qolminboundsession.h5
-rw-r--r--lib/e2ee/qolmoutboundsession.cpp81
-rw-r--r--lib/e2ee/qolmoutboundsession.h7
-rw-r--r--lib/e2ee/qolmsession.cpp98
-rw-r--r--lib/e2ee/qolmsession.h4
-rw-r--r--lib/e2ee/qolmutility.cpp22
-rw-r--r--lib/e2ee/qolmutility.h4
-rw-r--r--lib/events/encryptedevent.cpp1
-rw-r--r--lib/events/encryptedevent.h7
-rw-r--r--lib/room.cpp1
-rw-r--r--lib/util.h17
18 files changed, 257 insertions, 257 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp
index 8ca76ceb..865dff79 100644
--- a/lib/connection.cpp
+++ b/lib/connection.cpp
@@ -270,8 +270,7 @@ public:
return {};
}
auto newSession = std::move(*newSessionResult);
- auto error = olmAccount->removeOneTimeKeys(*newSession);
- if (error) {
+ if (olmAccount->removeOneTimeKeys(*newSession) != OLM_SUCCESS) {
qWarning(E2EE) << "Failed to remove one time key for session"
<< newSession->sessionId();
// Keep going though
diff --git a/lib/e2ee/e2ee.h b/lib/e2ee/e2ee.h
index 0772b70a..51ceff67 100644
--- a/lib/e2ee/e2ee.h
+++ b/lib/e2ee/e2ee.h
@@ -6,21 +6,20 @@
#pragma once
#include "converters.h"
-#include "expected.h"
-#include "qolmerrors.h"
#include <QtCore/QMetaType>
#include <QtCore/QStringBuilder>
#include <array>
-#include <variant>
-namespace Quotient {
+#ifdef Quotient_E2EE_ENABLED
+# include "expected.h"
+
+# include <olm/error.h>
+# include <variant>
+#endif
-constexpr auto CiphertextKeyL = "ciphertext"_ls;
-constexpr auto SenderKeyKeyL = "sender_key"_ls;
-constexpr auto DeviceIdKeyL = "device_id"_ls;
-constexpr auto SessionIdKeyL = "session_id"_ls;
+namespace Quotient {
constexpr auto AlgorithmKeyL = "algorithm"_ls;
constexpr auto RotationPeriodMsKeyL = "rotation_period_ms"_ls;
@@ -47,6 +46,7 @@ inline bool isSupportedAlgorithm(const QString& algorithm)
!= SupportedAlgorithms.cend();
}
+#ifdef Quotient_E2EE_ENABLED
struct Unencrypted {};
struct Encrypted {
QByteArray key;
@@ -64,7 +64,8 @@ class QOlmOutboundGroupSession;
using QOlmOutboundGroupSessionPtr = std::unique_ptr<QOlmOutboundGroupSession>;
template <typename T>
-using QOlmExpected = Expected<T, QOlmError>;
+using QOlmExpected = Expected<T, OlmErrorCode>;
+#endif
struct IdentityKeys
{
@@ -133,23 +134,6 @@ private:
using OneTimeKeys = QHash<QString, std::variant<QString, SignedOneTimeKey>>;
-template <typename T>
-class asKeyValueRange
-{
-public:
- asKeyValueRange(T& data)
- : m_data { data }
- {}
-
- auto begin() { return m_data.keyValueBegin(); }
- auto end() { return m_data.keyValueEnd(); }
-
-private:
- T &m_data;
-};
-template <typename T>
-asKeyValueRange(T&) -> asKeyValueRange<T>;
-
} // namespace Quotient
Q_DECLARE_METATYPE(Quotient::SignedOneTimeKey)
diff --git a/lib/e2ee/qolmaccount.cpp b/lib/e2ee/qolmaccount.cpp
index ccb191f4..d33db8e3 100644
--- a/lib/e2ee/qolmaccount.cpp
+++ b/lib/e2ee/qolmaccount.cpp
@@ -18,8 +18,13 @@
using namespace Quotient;
// Convert olm error to enum
-QOlmError lastError(OlmAccount *account) {
- return fromString(olm_account_last_error(account));
+OlmErrorCode QOlmAccount::lastErrorCode() const {
+ return olm_account_last_error_code(m_account);
+}
+
+const char* QOlmAccount::lastError() const
+{
+ return olm_account_last_error(m_account);
}
QOlmAccount::QOlmAccount(const QString& userId, const QString& deviceId,
@@ -40,24 +45,24 @@ void QOlmAccount::createNewAccount()
m_account = olm_account(new uint8_t[olm_account_size()]);
size_t randomSize = olm_create_account_random_length(m_account);
QByteArray randomData = getRandom(randomSize);
- const auto error = olm_create_account(m_account, randomData.data(), randomSize);
- if (error == olm_error()) {
- throw lastError(m_account);
+ if (olm_create_account(m_account, randomData.data(), randomSize)
+ == olm_error()) {
+ throw lastError();
}
emit needsSave();
}
-void QOlmAccount::unpickle(QByteArray &pickled, const PicklingMode &mode)
+OlmErrorCode QOlmAccount::unpickle(QByteArray &pickled, const PicklingMode &mode)
{
m_account = olm_account(new uint8_t[olm_account_size()]);
const QByteArray key = toKey(mode);
- const auto error = olm_unpickle_account(m_account, key.data(), key.length(), pickled.data(), pickled.size());
- if (error == olm_error()) {
- qCWarning(E2EE) << "Failed to unpickle olm account";
- //TODO: Do something that is not dying
+ if (olm_unpickle_account(m_account, key.data(), key.length(),
+ pickled.data(), pickled.size())
+ == olm_error()) {
// Probably log the user out since we have no way of getting to the keys
- //throw lastError(m_account);
+ return lastErrorCode();
}
+ return OLM_SUCCESS;
}
QOlmExpected<QByteArray> QOlmAccount::pickle(const PicklingMode &mode)
@@ -65,11 +70,10 @@ QOlmExpected<QByteArray> QOlmAccount::pickle(const PicklingMode &mode)
const QByteArray key = toKey(mode);
const size_t pickleLength = olm_pickle_account_length(m_account);
QByteArray pickleBuffer(pickleLength, '0');
- const auto error = olm_pickle_account(m_account, key.data(),
- key.length(), pickleBuffer.data(), pickleLength);
- if (error == olm_error()) {
- return lastError(m_account);
- }
+ if (olm_pickle_account(m_account, key.data(), key.length(),
+ pickleBuffer.data(), pickleLength)
+ == olm_error())
+ return lastErrorCode();
return pickleBuffer;
}
@@ -77,9 +81,9 @@ IdentityKeys QOlmAccount::identityKeys() const
{
const size_t keyLength = olm_account_identity_keys_length(m_account);
QByteArray keyBuffer(keyLength, '0');
- const auto error = olm_account_identity_keys(m_account, keyBuffer.data(), keyLength);
- if (error == olm_error()) {
- throw lastError(m_account);
+ if (olm_account_identity_keys(m_account, keyBuffer.data(), keyLength)
+ == olm_error()) {
+ throw lastError();
}
const QJsonObject key = QJsonDocument::fromJson(keyBuffer).object();
return IdentityKeys {
@@ -92,11 +96,10 @@ QByteArray QOlmAccount::sign(const QByteArray &message) const
{
QByteArray signatureBuffer(olm_account_signature_length(m_account), '0');
- const auto error = olm_account_sign(m_account, message.data(), message.length(),
- signatureBuffer.data(), signatureBuffer.length());
-
- if (error == olm_error()) {
- throw lastError(m_account);
+ if (olm_account_sign(m_account, message.data(), message.length(),
+ signatureBuffer.data(), signatureBuffer.length())
+ == olm_error()) {
+ throw lastError();
}
return signatureBuffer;
}
@@ -131,15 +134,15 @@ size_t QOlmAccount::generateOneTimeKeys(size_t numberOfKeys)
olm_account_generate_one_time_keys_random_length(m_account,
numberOfKeys);
QByteArray randomBuffer = getRandom(randomLength);
- const auto error =
+ const auto result =
olm_account_generate_one_time_keys(m_account, numberOfKeys,
randomBuffer.data(), randomLength);
- if (error == olm_error()) {
- throw lastError(m_account);
+ if (result == olm_error()) {
+ throw lastError();
}
emit needsSave();
- return error;
+ return result;
}
UnsignedOneTimeKeys QOlmAccount::oneTimeKeys() const
@@ -147,11 +150,10 @@ UnsignedOneTimeKeys QOlmAccount::oneTimeKeys() const
const size_t oneTimeKeyLength = olm_account_one_time_keys_length(m_account);
QByteArray oneTimeKeysBuffer(static_cast<int>(oneTimeKeyLength), '0');
- const auto error = olm_account_one_time_keys(m_account,
- oneTimeKeysBuffer.data(),
- oneTimeKeyLength);
- if (error == olm_error()) {
- throw lastError(m_account);
+ if (olm_account_one_time_keys(m_account, oneTimeKeysBuffer.data(),
+ oneTimeKeyLength)
+ == olm_error()) {
+ throw lastError();
}
const auto json = QJsonDocument::fromJson(oneTimeKeysBuffer).object();
UnsignedOneTimeKeys oneTimeKeys;
@@ -171,16 +173,16 @@ OneTimeKeys QOlmAccount::signOneTimeKeys(const UnsignedOneTimeKeys &keys) const
return signedOneTimeKeys;
}
-std::optional<QOlmError> QOlmAccount::removeOneTimeKeys(
- const QOlmSession& session)
+OlmErrorCode QOlmAccount::removeOneTimeKeys(const QOlmSession& session)
{
- const auto error = olm_remove_one_time_keys(m_account, session.raw());
-
- if (error == olm_error()) {
- return lastError(m_account);
+ if (olm_remove_one_time_keys(m_account, session.raw()) == olm_error()) {
+ qWarning(E2EE).nospace()
+ << "Failed to remove one-time keys for session "
+ << session.sessionId() << ": " << lastError();
+ return lastErrorCode();
}
emit needsSave();
- return std::nullopt;
+ return OLM_SUCCESS;
}
OlmAccount* QOlmAccount::data() { return m_account; }
diff --git a/lib/e2ee/qolmaccount.h b/lib/e2ee/qolmaccount.h
index f2a31314..5ad98e47 100644
--- a/lib/e2ee/qolmaccount.h
+++ b/lib/e2ee/qolmaccount.h
@@ -36,7 +36,8 @@ public:
//! Deserialises from encrypted Base64 that was previously obtained by pickling a `QOlmAccount`.
//! This needs to be called before any other action or use createNewAccount() instead.
- void unpickle(QByteArray &pickled, const PicklingMode &mode);
+ [[nodiscard]] OlmErrorCode unpickle(QByteArray& pickled,
+ const PicklingMode& mode);
//! Serialises an OlmAccount to encrypted Base64.
QOlmExpected<QByteArray> pickle(const PicklingMode &mode);
@@ -69,8 +70,7 @@ public:
DeviceKeys deviceKeys() const;
//! Remove the one time key used to create the supplied session.
- [[nodiscard]] std::optional<QOlmError> removeOneTimeKeys(
- const QOlmSession& session);
+ [[nodiscard]] OlmErrorCode removeOneTimeKeys(const QOlmSession& session);
//! Creates an inbound session for sending/receiving messages from a received 'prekey' message.
//!
@@ -92,6 +92,9 @@ public:
void markKeysAsPublished();
+ OlmErrorCode lastErrorCode() const;
+ const char *lastError() const;
+
// HACK do not use directly
QOlmAccount(OlmAccount *account);
OlmAccount *data();
diff --git a/lib/e2ee/qolmerrors.cpp b/lib/e2ee/qolmerrors.cpp
deleted file mode 100644
index 5a60b7e6..00000000
--- a/lib/e2ee/qolmerrors.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-
-
-#include "qolmerrors.h"
-#include "util.h"
-#include <QtCore/QLatin1String>
-
-Quotient::QOlmError Quotient::fromString(const char* error_raw) {
- const QLatin1String error { error_raw };
- if (error_raw == "BAD_ACCOUNT_KEY"_ls) {
- return QOlmError::BadAccountKey;
- } else if (error_raw == "BAD_MESSAGE_KEY_ID"_ls) {
- return QOlmError::BadMessageKeyId;
- } else if (error_raw == "INVALID_BASE64"_ls) {
- return QOlmError::InvalidBase64;
- } else if (error_raw == "NOT_ENOUGH_RANDOM"_ls) {
- return QOlmError::NotEnoughRandom;
- } else if (error_raw == "OUTPUT_BUFFER_TOO_SMALL"_ls) {
- return QOlmError::OutputBufferTooSmall;
- } else {
- return QOlmError::Unknown;
- }
-}
diff --git a/lib/e2ee/qolmerrors.h b/lib/e2ee/qolmerrors.h
deleted file mode 100644
index 20e61c12..00000000
--- a/lib/e2ee/qolmerrors.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-
-#pragma once
-
-#include "quotient_export.h"
-
-namespace Quotient {
-//! All errors that could be caused by an operation regarding Olm
-//! Errors are named exactly like the ones in libolm.
-enum QOlmError
-{
- BadAccountKey,
- BadMessageFormat,
- BadMessageKeyId,
- BadMessageMac,
- BadMessageVersion,
- InvalidBase64,
- NotEnoughRandom,
- OutputBufferTooSmall,
- UnknownMessageIndex,
- Unknown,
-};
-
-QUOTIENT_API QOlmError fromString(const char* error_raw);
-
-} //namespace Quotient
diff --git a/lib/e2ee/qolminboundsession.cpp b/lib/e2ee/qolminboundsession.cpp
index 17f06205..870070c2 100644
--- a/lib/e2ee/qolminboundsession.cpp
+++ b/lib/e2ee/qolminboundsession.cpp
@@ -3,20 +3,27 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "e2ee/qolminboundsession.h"
-#include <iostream>
+#include "logging.h"
+
#include <cstring>
+#include <iostream>
+#include <olm/olm.h>
using namespace Quotient;
-QOlmError lastError(OlmInboundGroupSession *session) {
- return fromString(olm_inbound_group_session_last_error(session));
+OlmErrorCode QOlmInboundGroupSession::lastErrorCode() const {
+ return olm_inbound_group_session_last_error_code(m_groupSession);
}
-QOlmInboundGroupSession::QOlmInboundGroupSession(OlmInboundGroupSession *session)
- : m_groupSession(session)
+const char* QOlmInboundGroupSession::lastError() const
{
+ return olm_inbound_group_session_last_error(m_groupSession);
}
+QOlmInboundGroupSession::QOlmInboundGroupSession(OlmInboundGroupSession *session)
+ : m_groupSession(session)
+{}
+
QOlmInboundGroupSession::~QOlmInboundGroupSession()
{
olm_clear_inbound_group_session(m_groupSession);
@@ -26,11 +33,12 @@ QOlmInboundGroupSession::~QOlmInboundGroupSession()
std::unique_ptr<QOlmInboundGroupSession> QOlmInboundGroupSession::create(const QByteArray &key)
{
const auto olmInboundGroupSession = olm_inbound_group_session(new uint8_t[olm_inbound_group_session_size()]);
- const auto error = olm_init_inbound_group_session(olmInboundGroupSession,
- reinterpret_cast<const uint8_t *>(key.constData()), key.size());
-
- if (error == olm_error()) {
- throw lastError(olmInboundGroupSession);
+ if (olm_init_inbound_group_session(
+ olmInboundGroupSession,
+ reinterpret_cast<const uint8_t*>(key.constData()), key.size())
+ == olm_error()) {
+ // FIXME: create QOlmInboundGroupSession earlier and use lastError()
+ throw olm_inbound_group_session_last_error_code(olmInboundGroupSession);
}
return std::make_unique<QOlmInboundGroupSession>(olmInboundGroupSession);
@@ -41,10 +49,12 @@ std::unique_ptr<QOlmInboundGroupSession> QOlmInboundGroupSession::import(const Q
const auto olmInboundGroupSession = olm_inbound_group_session(new uint8_t[olm_inbound_group_session_size()]);
QByteArray keyBuf = key;
- const auto error = olm_import_inbound_group_session(olmInboundGroupSession,
- reinterpret_cast<const uint8_t *>(keyBuf.data()), keyBuf.size());
- if (error == olm_error()) {
- throw lastError(olmInboundGroupSession);
+ if (olm_import_inbound_group_session(
+ olmInboundGroupSession,
+ reinterpret_cast<const uint8_t*>(keyBuf.data()), keyBuf.size())
+ == olm_error()) {
+ // FIXME: create QOlmInboundGroupSession earlier and use lastError()
+ throw olm_inbound_group_session_last_error_code(olmInboundGroupSession);
}
return std::make_unique<QOlmInboundGroupSession>(olmInboundGroupSession);
@@ -62,10 +72,11 @@ QByteArray QOlmInboundGroupSession::pickle(const PicklingMode &mode) const
{
QByteArray pickledBuf(olm_pickle_inbound_group_session_length(m_groupSession), '0');
const QByteArray key = toKey(mode);
- const auto error = olm_pickle_inbound_group_session(m_groupSession, key.data(), key.length(), pickledBuf.data(),
- pickledBuf.length());
- if (error == olm_error()) {
- throw lastError(m_groupSession);
+ if (olm_pickle_inbound_group_session(m_groupSession, key.data(),
+ key.length(), pickledBuf.data(),
+ pickledBuf.length())
+ == olm_error()) {
+ throw lastError();
}
return pickledBuf;
}
@@ -76,10 +87,12 @@ QOlmExpected<QOlmInboundGroupSessionPtr> QOlmInboundGroupSession::unpickle(
QByteArray pickledBuf = pickled;
const auto groupSession = olm_inbound_group_session(new uint8_t[olm_inbound_group_session_size()]);
QByteArray key = toKey(mode);
- const auto error = olm_unpickle_inbound_group_session(groupSession, key.data(), key.length(),
- pickledBuf.data(), pickledBuf.size());
- if (error == olm_error()) {
- return lastError(groupSession);
+ if (olm_unpickle_inbound_group_session(groupSession, key.data(),
+ key.length(), pickledBuf.data(),
+ pickledBuf.size())
+ == olm_error()) {
+ // FIXME: create QOlmInboundGroupSession earlier and use lastError()
+ return olm_inbound_group_session_last_error_code(groupSession);
}
key.clear();
@@ -105,12 +118,9 @@ QOlmExpected<std::pair<QByteArray, uint32_t>> QOlmInboundGroupSession::decrypt(
const auto plaintextLen = olm_group_decrypt(m_groupSession, reinterpret_cast<uint8_t *>(messageBuf.data()),
messageBuf.length(), reinterpret_cast<uint8_t *>(plaintextBuf.data()), plaintextBuf.length(), &messageIndex);
-
- // Error code or plaintext length is returned
- const auto decryptError = plaintextLen;
-
- if (decryptError == olm_error()) {
- return lastError(m_groupSession);
+ if (plaintextLen == olm_error()) {
+ qWarning(E2EE) << "Failed to decrypt the message:" << lastError();
+ return lastErrorCode();
}
QByteArray output(plaintextLen, '0');
@@ -123,10 +133,11 @@ QOlmExpected<QByteArray> QOlmInboundGroupSession::exportSession(uint32_t message
{
const auto keyLength = olm_export_inbound_group_session_length(m_groupSession);
QByteArray keyBuf(keyLength, '0');
- const auto error = olm_export_inbound_group_session(m_groupSession, reinterpret_cast<uint8_t *>(keyBuf.data()), keyLength, messageIndex);
-
- if (error == olm_error()) {
- return lastError(m_groupSession);
+ if (olm_export_inbound_group_session(
+ m_groupSession, reinterpret_cast<uint8_t*>(keyBuf.data()),
+ keyLength, messageIndex)
+ == olm_error()) {
+ return lastErrorCode();
}
return keyBuf;
}
@@ -139,10 +150,11 @@ uint32_t QOlmInboundGroupSession::firstKnownIndex() const
QByteArray QOlmInboundGroupSession::sessionId() const
{
QByteArray sessionIdBuf(olm_inbound_group_session_id_length(m_groupSession), '0');
- const auto error = olm_inbound_group_session_id(m_groupSession, reinterpret_cast<uint8_t *>(sessionIdBuf.data()),
- sessionIdBuf.length());
- if (error == olm_error()) {
- throw lastError(m_groupSession);
+ if (olm_inbound_group_session_id(
+ m_groupSession, reinterpret_cast<uint8_t*>(sessionIdBuf.data()),
+ sessionIdBuf.length())
+ == olm_error()) {
+ throw lastError();
}
return sessionIdBuf;
}
diff --git a/lib/e2ee/qolminboundsession.h b/lib/e2ee/qolminboundsession.h
index 1a9b4415..e8da6355 100644
--- a/lib/e2ee/qolminboundsession.h
+++ b/lib/e2ee/qolminboundsession.h
@@ -6,7 +6,7 @@
#include "e2ee/e2ee.h"
-#include <olm/olm.h>
+struct OlmInboundGroupSession;
namespace Quotient {
@@ -46,6 +46,9 @@ public:
QString senderId() const;
void setSenderId(const QString& senderId);
+ OlmErrorCode lastErrorCode() const;
+ const char* lastError() const;
+
QOlmInboundGroupSession(OlmInboundGroupSession* session);
private:
OlmInboundGroupSession* m_groupSession;
diff --git a/lib/e2ee/qolmoutboundsession.cpp b/lib/e2ee/qolmoutboundsession.cpp
index a2eff2c8..79c16e01 100644
--- a/lib/e2ee/qolmoutboundsession.cpp
+++ b/lib/e2ee/qolmoutboundsession.cpp
@@ -3,12 +3,20 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "e2ee/qolmoutboundsession.h"
+
#include "e2ee/qolmutils.h"
+#include <olm/olm.h>
+
using namespace Quotient;
-QOlmError lastError(OlmOutboundGroupSession *session) {
- return fromString(olm_outbound_group_session_last_error(session));
+OlmErrorCode QOlmOutboundGroupSession::lastErrorCode() const {
+ return olm_outbound_group_session_last_error_code(m_groupSession);
+}
+
+const char* QOlmOutboundGroupSession::lastError() const
+{
+ return olm_outbound_group_session_last_error(m_groupSession);
}
QOlmOutboundGroupSession::QOlmOutboundGroupSession(OlmOutboundGroupSession *session)
@@ -27,11 +35,12 @@ QOlmOutboundGroupSessionPtr QOlmOutboundGroupSession::create()
const auto randomLength = olm_init_outbound_group_session_random_length(olmOutboundGroupSession);
QByteArray randomBuf = getRandom(randomLength);
- const auto error = olm_init_outbound_group_session(olmOutboundGroupSession,
- reinterpret_cast<uint8_t *>(randomBuf.data()), randomBuf.length());
-
- if (error == olm_error()) {
- throw lastError(olmOutboundGroupSession);
+ if (olm_init_outbound_group_session(
+ olmOutboundGroupSession,
+ reinterpret_cast<uint8_t*>(randomBuf.data()), randomBuf.length())
+ == olm_error()) {
+ // FIXME: create the session object earlier and use lastError()
+ throw olm_outbound_group_session_last_error_code(olmOutboundGroupSession);
}
const auto keyMaxLength = olm_outbound_group_session_key_length(olmOutboundGroupSession);
@@ -48,12 +57,11 @@ QOlmExpected<QByteArray> QOlmOutboundGroupSession::pickle(const PicklingMode &mo
{
QByteArray pickledBuf(olm_pickle_outbound_group_session_length(m_groupSession), '0');
QByteArray key = toKey(mode);
- const auto error = olm_pickle_outbound_group_session(m_groupSession, key.data(), key.length(),
- pickledBuf.data(), pickledBuf.length());
-
- if (error == olm_error()) {
- return lastError(m_groupSession);
- }
+ if (olm_pickle_outbound_group_session(m_groupSession, key.data(),
+ key.length(), pickledBuf.data(),
+ pickledBuf.length())
+ == olm_error())
+ return lastErrorCode();
key.clear();
@@ -65,10 +73,13 @@ QOlmExpected<QOlmOutboundGroupSessionPtr> QOlmOutboundGroupSession::unpickle(con
QByteArray pickledBuf = pickled;
auto *olmOutboundGroupSession = olm_outbound_group_session(new uint8_t[olm_outbound_group_session_size()]);
QByteArray key = toKey(mode);
- const auto error = olm_unpickle_outbound_group_session(olmOutboundGroupSession, key.data(), key.length(),
- pickledBuf.data(), pickledBuf.length());
- if (error == olm_error()) {
- return lastError(olmOutboundGroupSession);
+ if (olm_unpickle_outbound_group_session(olmOutboundGroupSession, key.data(),
+ key.length(), pickledBuf.data(),
+ pickledBuf.length())
+ == olm_error()) {
+ // FIXME: create the session object earlier and use lastError()
+ return olm_outbound_group_session_last_error_code(
+ olmOutboundGroupSession);
}
const auto idMaxLength = olm_outbound_group_session_id_length(olmOutboundGroupSession);
QByteArray idBuffer(idMaxLength, '0');
@@ -84,12 +95,13 @@ QOlmExpected<QByteArray> QOlmOutboundGroupSession::encrypt(const QString &plaint
QByteArray plaintextBuf = plaintext.toUtf8();
const auto messageMaxLength = olm_group_encrypt_message_length(m_groupSession, plaintextBuf.length());
QByteArray messageBuf(messageMaxLength, '0');
- const auto error = olm_group_encrypt(m_groupSession, reinterpret_cast<uint8_t *>(plaintextBuf.data()),
- plaintextBuf.length(), reinterpret_cast<uint8_t *>(messageBuf.data()), messageBuf.length());
-
- if (error == olm_error()) {
- return lastError(m_groupSession);
- }
+ if (olm_group_encrypt(m_groupSession,
+ reinterpret_cast<uint8_t*>(plaintextBuf.data()),
+ plaintextBuf.length(),
+ reinterpret_cast<uint8_t*>(messageBuf.data()),
+ messageBuf.length())
+ == olm_error())
+ return lastErrorCode();
return messageBuf;
}
@@ -103,11 +115,12 @@ QByteArray QOlmOutboundGroupSession::sessionId() const
{
const auto idMaxLength = olm_outbound_group_session_id_length(m_groupSession);
QByteArray idBuffer(idMaxLength, '0');
- const auto error = olm_outbound_group_session_id(m_groupSession, reinterpret_cast<uint8_t *>(idBuffer.data()),
- idBuffer.length());
- if (error == olm_error()) {
- throw lastError(m_groupSession);
- }
+ if (olm_outbound_group_session_id(
+ m_groupSession, reinterpret_cast<uint8_t*>(idBuffer.data()),
+ idBuffer.length())
+ == olm_error())
+ throw lastError();
+
return idBuffer;
}
@@ -115,12 +128,12 @@ QOlmExpected<QByteArray> QOlmOutboundGroupSession::sessionKey() const
{
const auto keyMaxLength = olm_outbound_group_session_key_length(m_groupSession);
QByteArray keyBuffer(keyMaxLength, '0');
- const auto error = olm_outbound_group_session_key(
- m_groupSession, reinterpret_cast<uint8_t*>(keyBuffer.data()),
- keyMaxLength);
- if (error == olm_error()) {
- return lastError(m_groupSession);
- }
+ if (olm_outbound_group_session_key(
+ m_groupSession, reinterpret_cast<uint8_t*>(keyBuffer.data()),
+ keyMaxLength)
+ == olm_error())
+ return lastErrorCode();
+
return keyBuffer;
}
diff --git a/lib/e2ee/qolmoutboundsession.h b/lib/e2ee/qolmoutboundsession.h
index 9a82d22a..cd26fc67 100644
--- a/lib/e2ee/qolmoutboundsession.h
+++ b/lib/e2ee/qolmoutboundsession.h
@@ -6,8 +6,7 @@
#include "e2ee/e2ee.h"
-#include <memory>
-#include <olm/olm.h>
+struct OlmOutboundGroupSession;
namespace Quotient {
@@ -51,6 +50,10 @@ public:
QDateTime creationTime() const;
void setCreationTime(const QDateTime& creationTime);
+
+ OlmErrorCode lastErrorCode() const;
+ const char* lastError() const;
+
private:
OlmOutboundGroupSession *m_groupSession;
int m_messageCount = 0;
diff --git a/lib/e2ee/qolmsession.cpp b/lib/e2ee/qolmsession.cpp
index 2a98d5d8..771d310d 100644
--- a/lib/e2ee/qolmsession.cpp
+++ b/lib/e2ee/qolmsession.cpp
@@ -12,8 +12,13 @@
using namespace Quotient;
-QOlmError lastError(OlmSession* session) {
- return fromString(olm_session_last_error(session));
+OlmErrorCode QOlmSession::lastErrorCode() const {
+ return olm_session_last_error_code(m_session);
+}
+
+const char* QOlmSession::lastError() const
+{
+ return olm_session_last_error(m_session);
}
Quotient::QOlmSession::~QOlmSession()
@@ -32,7 +37,8 @@ QOlmExpected<QOlmSessionPtr> QOlmSession::createInbound(
const QString& theirIdentityKey)
{
if (preKeyMessage.type() != QOlmMessage::PreKey) {
- qCCritical(E2EE) << "The message is not a pre-key in when creating inbound session" << BadMessageFormat;
+ qCCritical(E2EE) << "The message is not a pre-key; will try to create "
+ "the inbound session anyway";
}
const auto olmSession = create();
@@ -47,7 +53,8 @@ QOlmExpected<QOlmSessionPtr> QOlmSession::createInbound(
}
if (error == olm_error()) {
- const auto lastErr = lastError(olmSession);
+ // FIXME: the QOlmSession object should be created earlier
+ const auto lastErr = olm_session_last_error_code(olmSession);
qCWarning(E2EE) << "Error when creating inbound session" << lastErr;
return lastErr;
}
@@ -78,15 +85,17 @@ QOlmExpected<QOlmSessionPtr> QOlmSession::createOutboundSession(
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) {
+ if (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())
+ == olm_error()) {
+ // FIXME: the QOlmSession object should be created earlier
+ const auto lastErr = olm_session_last_error_code(olmOutboundSession);
+ if (lastErr == OLM_NOT_ENOUGH_RANDOM) {
throw lastErr;
}
return lastErr;
@@ -100,16 +109,12 @@ QOlmExpected<QByteArray> QOlmSession::pickle(const PicklingMode &mode) const
{
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);
- }
+ if (olm_pickle_session(m_session, key.data(), key.length(),
+ pickledBuf.data(), pickledBuf.length())
+ == olm_error())
+ return lastErrorCode();
key.clear();
-
return pickledBuf;
}
@@ -119,10 +124,11 @@ QOlmExpected<QOlmSessionPtr> QOlmSession::unpickle(const QByteArray& pickled,
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);
+ if (olm_unpickle_session(olmSession, key.data(), key.length(),
+ pickledBuf.data(), pickledBuf.length())
+ == olm_error()) {
+ // FIXME: the QOlmSession object should be created earlier
+ return olm_session_last_error_code(olmSession);
}
key.clear();
@@ -137,13 +143,14 @@ QOlmMessage QOlmSession::encrypt(const QString &plaintext)
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);
+ if (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())
+ == olm_error()) {
+ throw lastError();
}
return QOlmMessage(messageBuf, messageType);
@@ -163,9 +170,8 @@ QOlmExpected<QByteArray> QOlmSession::decrypt(const QOlmMessage &message) const
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);
+ return lastError();
}
QByteArray plaintextBuf(plaintextMaxLen, '0');
@@ -175,10 +181,9 @@ QOlmExpected<QByteArray> QOlmSession::decrypt(const QOlmMessage &message) const
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) {
+ const auto lastErr = lastErrorCode();
+ if (lastErr == OLM_OUTPUT_BUFFER_TOO_SMALL) {
throw lastErr;
}
return lastErr;
@@ -193,7 +198,7 @@ QOlmMessage::Type QOlmSession::encryptMessageType()
{
const auto messageTypeResult = olm_encrypt_message_type(m_session);
if (messageTypeResult == olm_error()) {
- throw lastError(m_session);
+ throw lastError();
}
if (messageTypeResult == OLM_MESSAGE_TYPE_PRE_KEY) {
return QOlmMessage::PreKey;
@@ -205,10 +210,10 @@ 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);
+ if (olm_session_id(m_session, reinterpret_cast<uint8_t*>(idBuffer.data()),
+ idBuffer.length())
+ == olm_error()) {
+ throw lastError();
}
return idBuffer;
}
@@ -225,11 +230,10 @@ bool QOlmSession::matchesInboundSession(const QOlmMessage& preKeyMessage) const
const auto maybeMatches =
olm_matches_inbound_session(m_session, oneTimeKeyBuf.data(),
oneTimeKeyBuf.length());
-
- if (maybeMatches == olm_error()) {
- return lastError(m_session);
- }
- return maybeMatches == 1;
+ if (maybeMatches == olm_error())
+ qWarning(E2EE) << "Error matching an inbound session:"
+ << olm_session_last_error(m_session);
+ return maybeMatches == 1; // Any errors are treated as non-match
}
bool QOlmSession::matchesInboundSessionFrom(
diff --git a/lib/e2ee/qolmsession.h b/lib/e2ee/qolmsession.h
index 021092c7..cc988a03 100644
--- a/lib/e2ee/qolmsession.h
+++ b/lib/e2ee/qolmsession.h
@@ -6,7 +6,6 @@
#include "e2ee/e2ee.h"
#include "e2ee/qolmmessage.h"
-#include "e2ee/qolmerrors.h"
#include "e2ee/qolmaccount.h"
struct OlmSession;
@@ -71,6 +70,9 @@ public:
return *lhs < *rhs;
}
+ OlmErrorCode lastErrorCode() const;
+ const char* lastError() const;
+
OlmSession* raw() const { return m_session; }
QOlmSession(OlmSession* session);
diff --git a/lib/e2ee/qolmutility.cpp b/lib/e2ee/qolmutility.cpp
index 84559085..15c875c0 100644
--- a/lib/e2ee/qolmutility.cpp
+++ b/lib/e2ee/qolmutility.cpp
@@ -8,9 +8,13 @@
using namespace Quotient;
-// Convert olm error to enum
-QOlmError lastError(OlmUtility *utility) {
- return fromString(olm_utility_last_error(utility));
+OlmErrorCode QOlmUtility::lastErrorCode() const {
+ return olm_utility_last_error_code(m_utility);
+}
+
+const char* QOlmUtility::lastError() const
+{
+ return olm_utility_last_error(m_utility);
}
QOlmUtility::QOlmUtility()
@@ -48,15 +52,15 @@ QOlmExpected<bool> QOlmUtility::ed25519Verify(const QByteArray& key,
std::copy(signature.begin(), signature.end(), signatureBuf.begin());
const auto ret = olm_ed25519_verify(m_utility, key.data(), key.size(),
- message.data(), message.size(), (void *)signatureBuf.data(), signatureBuf.size());
-
+ message.data(), message.size(),
+ (void*)signatureBuf.data(),
+ signatureBuf.size());
if (ret == olm_error()) {
- auto error = lastError(m_utility);
- if (error == QOlmError::BadMessageMac) {
+ auto error = lastErrorCode();
+ if (error == OLM_BAD_MESSAGE_MAC)
return false;
- }
return error;
}
- return !ret; // ret == 0 means success
+ return ret == 0;
}
diff --git a/lib/e2ee/qolmutility.h b/lib/e2ee/qolmutility.h
index 5f6bcdc5..89277385 100644
--- a/lib/e2ee/qolmutility.h
+++ b/lib/e2ee/qolmutility.h
@@ -32,8 +32,10 @@ public:
QOlmExpected<bool> ed25519Verify(const QByteArray &key,
const QByteArray &message, const QByteArray &signature);
+ OlmErrorCode lastErrorCode() const;
+ const char* lastError() const;
+
private:
OlmUtility *m_utility;
-
};
}
diff --git a/lib/events/encryptedevent.cpp b/lib/events/encryptedevent.cpp
index 94b44901..114addb5 100644
--- a/lib/events/encryptedevent.cpp
+++ b/lib/events/encryptedevent.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "encryptedevent.h"
+#include "e2ee/e2ee.h"
#include "logging.h"
using namespace Quotient;
diff --git a/lib/events/encryptedevent.h b/lib/events/encryptedevent.h
index 02d4c7aa..e24e5745 100644
--- a/lib/events/encryptedevent.h
+++ b/lib/events/encryptedevent.h
@@ -3,10 +3,15 @@
#pragma once
-#include "e2ee/e2ee.h"
#include "roomevent.h"
namespace Quotient {
+
+constexpr auto CiphertextKeyL = "ciphertext"_ls;
+constexpr auto SenderKeyKeyL = "sender_key"_ls;
+constexpr auto DeviceIdKeyL = "device_id"_ls;
+constexpr auto SessionIdKeyL = "session_id"_ls;
+
/*
* While the specification states:
*
diff --git a/lib/room.cpp b/lib/room.cpp
index 95dd0ab7..382d0243 100644
--- a/lib/room.cpp
+++ b/lib/room.cpp
@@ -65,7 +65,6 @@
#ifdef Quotient_E2EE_ENABLED
#include "e2ee/e2ee.h"
#include "e2ee/qolmaccount.h"
-#include "e2ee/qolmerrors.h"
#include "e2ee/qolminboundsession.h"
#include "e2ee/qolmutility.h"
#include "database.h"
diff --git a/lib/util.h b/lib/util.h
index 9efda5d1..ab219488 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -111,6 +111,23 @@ private:
iterator to;
};
+template <typename T>
+class asKeyValueRange
+{
+public:
+ asKeyValueRange(T& data)
+ : m_data { data }
+ {}
+
+ auto begin() { return m_data.keyValueBegin(); }
+ auto end() { return m_data.keyValueEnd(); }
+
+private:
+ T &m_data;
+};
+template <typename T>
+asKeyValueRange(T&) -> asKeyValueRange<T>;
+
/** A replica of std::find_first_of that returns a pair of iterators
*
* Convenient for cases when you need to know which particular "first of"