diff options
Diffstat (limited to 'lib/e2ee')
-rw-r--r-- | lib/e2ee/e2ee.h | 36 | ||||
-rw-r--r-- | lib/e2ee/qolmaccount.cpp | 82 | ||||
-rw-r--r-- | lib/e2ee/qolmaccount.h | 9 | ||||
-rw-r--r-- | lib/e2ee/qolmerrors.cpp | 25 | ||||
-rw-r--r-- | lib/e2ee/qolmerrors.h | 28 | ||||
-rw-r--r-- | lib/e2ee/qolminboundsession.cpp | 84 | ||||
-rw-r--r-- | lib/e2ee/qolminboundsession.h | 5 | ||||
-rw-r--r-- | lib/e2ee/qolmoutboundsession.cpp | 81 | ||||
-rw-r--r-- | lib/e2ee/qolmoutboundsession.h | 7 | ||||
-rw-r--r-- | lib/e2ee/qolmsession.cpp | 98 | ||||
-rw-r--r-- | lib/e2ee/qolmsession.h | 4 | ||||
-rw-r--r-- | lib/e2ee/qolmutility.cpp | 22 | ||||
-rw-r--r-- | lib/e2ee/qolmutility.h | 4 |
13 files changed, 232 insertions, 253 deletions
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; - }; } |