aboutsummaryrefslogtreecommitdiff
path: root/lib/e2ee
diff options
context:
space:
mode:
Diffstat (limited to 'lib/e2ee')
-rw-r--r--lib/e2ee/qolmaccount.cpp37
-rw-r--r--lib/e2ee/qolmaccount.h4
-rw-r--r--lib/e2ee/qolminboundsession.cpp28
-rw-r--r--lib/e2ee/qolminboundsession.h4
-rw-r--r--lib/e2ee/qolmoutboundsession.cpp24
-rw-r--r--lib/e2ee/qolmoutboundsession.h6
-rw-r--r--lib/e2ee/qolmsession.cpp46
-rw-r--r--lib/e2ee/qolmsession.h2
-rw-r--r--lib/e2ee/qolmutils.h18
9 files changed, 108 insertions, 61 deletions
diff --git a/lib/e2ee/qolmaccount.cpp b/lib/e2ee/qolmaccount.cpp
index b56272ef..d03bcb3b 100644
--- a/lib/e2ee/qolmaccount.cpp
+++ b/lib/e2ee/qolmaccount.cpp
@@ -45,9 +45,9 @@ void QOlmAccount::createNewAccount()
m_account = olm_account(new uint8_t[olm_account_size()]);
const auto randomLength = olm_create_account_random_length(m_account);
if (olm_create_account(m_account, RandomBuffer(randomLength), randomLength)
- == olm_error()) {
- throw lastError();
- }
+ == olm_error())
+ QOLM_INTERNAL_ERROR("Failed to create a new account");
+
emit needsSave();
}
@@ -64,7 +64,7 @@ OlmErrorCode QOlmAccount::unpickle(QByteArray&& pickled, const PicklingMode &mod
return OLM_SUCCESS;
}
-QOlmExpected<QByteArray> QOlmAccount::pickle(const PicklingMode &mode)
+QByteArray QOlmAccount::pickle(const PicklingMode &mode)
{
const QByteArray key = toKey(mode);
const size_t pickleLength = olm_pickle_account_length(m_account);
@@ -72,7 +72,9 @@ QOlmExpected<QByteArray> QOlmAccount::pickle(const PicklingMode &mode)
if (olm_pickle_account(m_account, key.data(), key.length(),
pickleBuffer.data(), pickleLength)
== olm_error())
- return lastErrorCode();
+ QOLM_INTERNAL_ERROR(qPrintable("Failed to pickle Olm account "
+ + accountId()));
+
return pickleBuffer;
}
@@ -82,7 +84,8 @@ IdentityKeys QOlmAccount::identityKeys() const
QByteArray keyBuffer(keyLength, '\0');
if (olm_account_identity_keys(m_account, keyBuffer.data(), keyLength)
== olm_error()) {
- throw lastError();
+ QOLM_INTERNAL_ERROR(
+ qPrintable("Failed to get " % accountId() % " identity keys"));
}
const auto key = QJsonDocument::fromJson(keyBuffer).object();
return IdentityKeys {
@@ -97,9 +100,9 @@ QByteArray QOlmAccount::sign(const QByteArray &message) const
if (olm_account_sign(m_account, message.data(), message.length(),
signatureBuffer.data(), signatureBuffer.length())
- == olm_error()) {
- throw lastError();
- }
+ == olm_error())
+ QOLM_INTERNAL_ERROR("Failed to sign a message");
+
return signatureBuffer;
}
@@ -135,9 +138,10 @@ size_t QOlmAccount::generateOneTimeKeys(size_t numberOfKeys)
const auto result = olm_account_generate_one_time_keys(
m_account, numberOfKeys, RandomBuffer(randomLength), randomLength);
- if (result == olm_error()) {
- throw lastError();
- }
+ if (result == olm_error())
+ QOLM_INTERNAL_ERROR(qPrintable(
+ "Failed to generate one-time keys for account " + accountId()));
+
emit needsSave();
return result;
}
@@ -149,9 +153,10 @@ UnsignedOneTimeKeys QOlmAccount::oneTimeKeys() const
if (olm_account_one_time_keys(m_account, oneTimeKeysBuffer.data(),
oneTimeKeyLength)
- == olm_error()) {
- throw lastError();
- }
+ == olm_error())
+ QOLM_INTERNAL_ERROR(qPrintable(
+ "Failed to obtain one-time keys for account" % accountId()));
+
const auto json = QJsonDocument::fromJson(oneTimeKeysBuffer).object();
UnsignedOneTimeKeys oneTimeKeys;
fromJson(json, oneTimeKeys.keys);
@@ -266,3 +271,5 @@ bool Quotient::ed25519VerifySignature(const QString& signingKey,
return utility.ed25519Verify(signingKeyBuf, canonicalJson, signatureBuf)
.value_or(false);
}
+
+QString QOlmAccount::accountId() const { return m_userId % '/' % m_deviceId; }
diff --git a/lib/e2ee/qolmaccount.h b/lib/e2ee/qolmaccount.h
index 0fb9803f..a5faa82a 100644
--- a/lib/e2ee/qolmaccount.h
+++ b/lib/e2ee/qolmaccount.h
@@ -41,7 +41,7 @@ public:
const PicklingMode& mode);
//! Serialises an OlmAccount to encrypted Base64.
- QOlmExpected<QByteArray> pickle(const PicklingMode &mode);
+ QByteArray pickle(const PicklingMode &mode);
//! Returns the account's public identity keys already formatted as JSON
IdentityKeys identityKeys() const;
@@ -107,6 +107,8 @@ private:
OlmAccount *m_account = nullptr; // owning
QString m_userId;
QString m_deviceId;
+
+ QString accountId() const;
};
QUOTIENT_API bool verifyIdentitySignature(const DeviceKeys& deviceKeys,
diff --git a/lib/e2ee/qolminboundsession.cpp b/lib/e2ee/qolminboundsession.cpp
index a05ddf62..1e3803f2 100644
--- a/lib/e2ee/qolminboundsession.cpp
+++ b/lib/e2ee/qolminboundsession.cpp
@@ -31,7 +31,8 @@ QOlmInboundGroupSession::~QOlmInboundGroupSession()
//delete[](reinterpret_cast<uint8_t *>(m_groupSession));
}
-std::unique_ptr<QOlmInboundGroupSession> QOlmInboundGroupSession::create(const QByteArray &key)
+QOlmExpected<QOlmInboundGroupSessionPtr> QOlmInboundGroupSession::create(
+ const QByteArray& key)
{
const auto olmInboundGroupSession = olm_inbound_group_session(new uint8_t[olm_inbound_group_session_size()]);
if (olm_init_inbound_group_session(
@@ -39,13 +40,17 @@ std::unique_ptr<QOlmInboundGroupSession> QOlmInboundGroupSession::create(const Q
reinterpret_cast<const uint8_t*>(key.constData()), key.size())
== olm_error()) {
// FIXME: create QOlmInboundGroupSession earlier and use lastErrorCode()
- throw olm_inbound_group_session_last_error_code(olmInboundGroupSession);
+ qWarning(E2EE) << "Failed to create an inbound group session:"
+ << olm_inbound_group_session_last_error(
+ olmInboundGroupSession);
+ return olm_inbound_group_session_last_error_code(olmInboundGroupSession);
}
return std::make_unique<QOlmInboundGroupSession>(olmInboundGroupSession);
}
-std::unique_ptr<QOlmInboundGroupSession> QOlmInboundGroupSession::import(const QByteArray &key)
+QOlmExpected<QOlmInboundGroupSessionPtr> QOlmInboundGroupSession::import(
+ const QByteArray& key)
{
const auto olmInboundGroupSession = olm_inbound_group_session(new uint8_t[olm_inbound_group_session_size()]);
@@ -54,7 +59,10 @@ std::unique_ptr<QOlmInboundGroupSession> QOlmInboundGroupSession::import(const Q
reinterpret_cast<const uint8_t*>(key.data()), key.size())
== olm_error()) {
// FIXME: create QOlmInboundGroupSession earlier and use lastError()
- throw olm_inbound_group_session_last_error_code(olmInboundGroupSession);
+ qWarning(E2EE) << "Failed to import an inbound group session:"
+ << olm_inbound_group_session_last_error(
+ olmInboundGroupSession);
+ return olm_inbound_group_session_last_error_code(olmInboundGroupSession);
}
return std::make_unique<QOlmInboundGroupSession>(olmInboundGroupSession);
@@ -69,7 +77,7 @@ QByteArray QOlmInboundGroupSession::pickle(const PicklingMode& mode) const
key.length(), pickledBuf.data(),
pickledBuf.length())
== olm_error()) {
- throw lastError();
+ QOLM_INTERNAL_ERROR("Failed to pickle the inbound group session");
}
return pickledBuf;
}
@@ -84,6 +92,8 @@ QOlmExpected<QOlmInboundGroupSessionPtr> QOlmInboundGroupSession::unpickle(
pickled.size())
== olm_error()) {
// FIXME: create QOlmInboundGroupSession earlier and use lastError()
+ qWarning(E2EE) << "Failed to unpickle an inbound group session:"
+ << olm_inbound_group_session_last_error(groupSession);
return olm_inbound_group_session_last_error_code(groupSession);
}
key.clear();
@@ -133,6 +143,8 @@ QOlmExpected<QByteArray> QOlmInboundGroupSession::exportSession(
m_groupSession, reinterpret_cast<uint8_t*>(keyBuf.data()),
keyLength, messageIndex)
== olm_error()) {
+ QOLM_FAIL_OR_LOG(OLM_OUTPUT_BUFFER_TOO_SMALL,
+ "Failed to export the inbound group session");
return lastErrorCode();
}
return keyBuf;
@@ -150,9 +162,9 @@ QByteArray QOlmInboundGroupSession::sessionId() const
if (olm_inbound_group_session_id(
m_groupSession, reinterpret_cast<uint8_t*>(sessionIdBuf.data()),
sessionIdBuf.length())
- == olm_error()) {
- throw lastError();
- }
+ == olm_error())
+ QOLM_INTERNAL_ERROR("Failed to obtain the group session id");
+
return sessionIdBuf;
}
diff --git a/lib/e2ee/qolminboundsession.h b/lib/e2ee/qolminboundsession.h
index 0b89349a..15979a05 100644
--- a/lib/e2ee/qolminboundsession.h
+++ b/lib/e2ee/qolminboundsession.h
@@ -17,9 +17,9 @@ class QUOTIENT_API QOlmInboundGroupSession
public:
~QOlmInboundGroupSession();
//! Creates a new instance of `OlmInboundGroupSession`.
- static std::unique_ptr<QOlmInboundGroupSession> create(const QByteArray& key);
+ static QOlmExpected<QOlmInboundGroupSessionPtr> create(const QByteArray& key);
//! Import an inbound group session, from a previous export.
- static std::unique_ptr<QOlmInboundGroupSession> import(const QByteArray& key);
+ static QOlmExpected<QOlmInboundGroupSessionPtr> import(const QByteArray& key);
//! Serialises an `OlmInboundGroupSession` to encrypted Base64.
QByteArray pickle(const PicklingMode& mode) const;
//! Deserialises from encrypted Base64 that was previously obtained by pickling
diff --git a/lib/e2ee/qolmoutboundsession.cpp b/lib/e2ee/qolmoutboundsession.cpp
index 3d176274..18af5569 100644
--- a/lib/e2ee/qolmoutboundsession.cpp
+++ b/lib/e2ee/qolmoutboundsession.cpp
@@ -39,8 +39,10 @@ QOlmOutboundGroupSessionPtr QOlmOutboundGroupSession::create()
RandomBuffer(randomLength).bytes(),
randomLength)
== olm_error()) {
- // FIXME: create the session object earlier and use lastError()
- throw olm_outbound_group_session_last_error_code(olmOutboundGroupSession);
+ // FIXME: create the session object earlier
+ QOLM_INTERNAL_ERROR_X("Failed to initialise an outbound group session",
+ olm_outbound_group_session_last_error(
+ olmOutboundGroupSession));
}
// FIXME: is it used anywhere?
@@ -52,7 +54,7 @@ QOlmOutboundGroupSessionPtr QOlmOutboundGroupSession::create()
return std::make_unique<QOlmOutboundGroupSession>(olmOutboundGroupSession);
}
-QOlmExpected<QByteArray> QOlmOutboundGroupSession::pickle(const PicklingMode &mode) const
+QByteArray QOlmOutboundGroupSession::pickle(const PicklingMode &mode) const
{
QByteArray pickledBuf(
olm_pickle_outbound_group_session_length(m_groupSession), '\0');
@@ -61,7 +63,7 @@ QOlmExpected<QByteArray> QOlmOutboundGroupSession::pickle(const PicklingMode &mo
key.length(), pickledBuf.data(),
pickledBuf.length())
== olm_error())
- return lastErrorCode();
+ QOLM_INTERNAL_ERROR("Failed to pickle the outbound group session");
key.clear();
return pickledBuf;
@@ -77,6 +79,9 @@ QOlmExpected<QOlmOutboundGroupSessionPtr> QOlmOutboundGroupSession::unpickle(
pickled.length())
== olm_error()) {
// FIXME: create the session object earlier and use lastError()
+ qWarning(E2EE) << "Failed to unpickle an outbound group session:"
+ << olm_outbound_group_session_last_error(
+ olmOutboundGroupSession);
return olm_outbound_group_session_last_error_code(
olmOutboundGroupSession);
}
@@ -90,8 +95,7 @@ QOlmExpected<QOlmOutboundGroupSessionPtr> QOlmOutboundGroupSession::unpickle(
return std::make_unique<QOlmOutboundGroupSession>(olmOutboundGroupSession);
}
-QOlmExpected<QByteArray> QOlmOutboundGroupSession::encrypt(
- const QByteArray& plaintext) const
+QByteArray QOlmOutboundGroupSession::encrypt(const QByteArray& plaintext) const
{
const auto messageMaxLength =
olm_group_encrypt_message_length(m_groupSession, plaintext.length());
@@ -102,7 +106,7 @@ QOlmExpected<QByteArray> QOlmOutboundGroupSession::encrypt(
reinterpret_cast<uint8_t*>(messageBuf.data()),
messageBuf.length())
== olm_error())
- return lastErrorCode();
+ QOLM_INTERNAL_ERROR("Failed to encrypt a message");
return messageBuf;
}
@@ -120,12 +124,12 @@ QByteArray QOlmOutboundGroupSession::sessionId() const
m_groupSession, reinterpret_cast<uint8_t*>(idBuffer.data()),
idBuffer.length())
== olm_error())
- throw lastError();
+ QOLM_INTERNAL_ERROR("Failed to obtain group session id");
return idBuffer;
}
-QOlmExpected<QByteArray> QOlmOutboundGroupSession::sessionKey() const
+QByteArray QOlmOutboundGroupSession::sessionKey() const
{
const auto keyMaxLength = olm_outbound_group_session_key_length(m_groupSession);
QByteArray keyBuffer(keyMaxLength, '\0');
@@ -133,7 +137,7 @@ QOlmExpected<QByteArray> QOlmOutboundGroupSession::sessionKey() const
m_groupSession, reinterpret_cast<uint8_t*>(keyBuffer.data()),
keyMaxLength)
== olm_error())
- return lastErrorCode();
+ QOLM_INTERNAL_ERROR("Failed to obtain group session key");
return keyBuffer;
}
diff --git a/lib/e2ee/qolmoutboundsession.h b/lib/e2ee/qolmoutboundsession.h
index e5e73ddf..d36fbf69 100644
--- a/lib/e2ee/qolmoutboundsession.h
+++ b/lib/e2ee/qolmoutboundsession.h
@@ -20,14 +20,14 @@ public:
//! Throw OlmError on errors
static QOlmOutboundGroupSessionPtr create();
//! Serialises a `QOlmOutboundGroupSession` to encrypted Base64.
- QOlmExpected<QByteArray> pickle(const PicklingMode &mode) const;
+ QByteArray pickle(const PicklingMode &mode) const;
//! Deserialises from encrypted Base64 that was previously obtained by
//! pickling a `QOlmOutboundGroupSession`.
static QOlmExpected<QOlmOutboundGroupSessionPtr> unpickle(
QByteArray&& pickled, const PicklingMode& mode);
//! Encrypts a plaintext message using the session.
- QOlmExpected<QByteArray> encrypt(const QByteArray& plaintext) const;
+ QByteArray encrypt(const QByteArray& plaintext) const;
//! 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.
- QOlmExpected<QByteArray> sessionKey() const;
+ QByteArray sessionKey() const;
QOlmOutboundGroupSession(OlmOutboundGroupSession *groupSession);
int messageCount() const;
diff --git a/lib/e2ee/qolmsession.cpp b/lib/e2ee/qolmsession.cpp
index 7c102a96..0d6edd21 100644
--- a/lib/e2ee/qolmsession.cpp
+++ b/lib/e2ee/qolmsession.cpp
@@ -90,23 +90,23 @@ QOlmExpected<QOlmSessionPtr> QOlmSession::createOutboundSession(
== 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;
- }
+ QOLM_FAIL_OR_LOG_X(lastErr == OLM_NOT_ENOUGH_RANDOM,
+ "Failed to create an outbound Olm session",
+ olm_session_last_error(olmOutboundSession));
return lastErr;
}
return std::make_unique<QOlmSession>(olmOutboundSession);
}
-QOlmExpected<QByteArray> QOlmSession::pickle(const PicklingMode &mode) const
+QByteArray QOlmSession::pickle(const PicklingMode &mode) const
{
QByteArray pickledBuf(olm_pickle_session_length(m_session), '\0');
QByteArray key = toKey(mode);
if (olm_pickle_session(m_session, key.data(), key.length(),
pickledBuf.data(), pickledBuf.length())
== olm_error())
- return lastErrorCode();
+ QOLM_INTERNAL_ERROR("Failed to pickle an Olm session");
key.clear();
return pickledBuf;
@@ -121,7 +121,11 @@ QOlmExpected<QOlmSessionPtr> QOlmSession::unpickle(QByteArray&& pickled,
pickled.data(), pickled.length())
== olm_error()) {
// FIXME: the QOlmSession object should be created earlier
- return olm_session_last_error_code(olmSession);
+ const auto errorCode = olm_session_last_error_code(olmSession);
+ QOLM_FAIL_OR_LOG_X(errorCode == OLM_OUTPUT_BUFFER_TOO_SMALL,
+ "Failed to unpickle an Olm session",
+ olm_session_last_error(olmSession));
+ return errorCode;
}
key.clear();
@@ -140,7 +144,7 @@ QOlmMessage QOlmSession::encrypt(const QByteArray& plaintext)
RandomBuffer(randomLength), randomLength, messageBuf.data(),
messageBuf.length())
== olm_error()) {
- throw lastError();
+ QOLM_INTERNAL_ERROR("Failed to encrypt the message");
}
return QOlmMessage(messageBuf, QOlmMessage::Type(messageType));
@@ -159,7 +163,9 @@ QOlmExpected<QByteArray> QOlmSession::decrypt(const QOlmMessage &message) const
const auto plaintextMaxLen = olm_decrypt_max_plaintext_length(
m_session, messageTypeValue, messageBuf.data(), messageBuf.length());
if (plaintextMaxLen == olm_error()) {
- return lastError();
+ qWarning(E2EE) << "Couldn't calculate decrypted message length:"
+ << lastError();
+ return lastErrorCode();
}
QByteArray plaintextBuf(plaintextMaxLen, '\0');
@@ -170,11 +176,9 @@ QOlmExpected<QByteArray> QOlmSession::decrypt(const QOlmMessage &message) const
olm_decrypt(m_session, messageTypeValue, messageBuf2.data(),
messageBuf2.length(), plaintextBuf.data(), plaintextMaxLen);
if (plaintextResultLen == olm_error()) {
- const auto lastErr = lastErrorCode();
- if (lastErr == OLM_OUTPUT_BUFFER_TOO_SMALL) {
- throw lastErr;
- }
- return lastErr;
+ QOLM_FAIL_OR_LOG(OLM_OUTPUT_BUFFER_TOO_SMALL,
+ "Failed to decrypt the message");
+ return lastErrorCode();
}
plaintextBuf.truncate(plaintextResultLen);
return plaintextBuf;
@@ -183,10 +187,10 @@ QOlmExpected<QByteArray> QOlmSession::decrypt(const QOlmMessage &message) const
QByteArray QOlmSession::sessionId() const
{
const auto idMaxLength = olm_session_id_length(m_session);
- QByteArray idBuffer(idMaxLength, '0');
- if (olm_session_id(m_session, idBuffer.data(), idMaxLength) == olm_error()) {
- throw lastError();
- }
+ QByteArray idBuffer(idMaxLength, '\0');
+ if (olm_session_id(m_session, idBuffer.data(), idMaxLength) == olm_error())
+ QOLM_INTERNAL_ERROR("Failed to obtain Olm session id");
+
return idBuffer;
}
@@ -203,8 +207,8 @@ bool QOlmSession::matchesInboundSession(const QOlmMessage& preKeyMessage) const
olm_matches_inbound_session(m_session, oneTimeKeyBuf.data(),
oneTimeKeyBuf.length());
if (maybeMatches == olm_error())
- qWarning(E2EE) << "Error matching an inbound session:"
- << olm_session_last_error(m_session);
+ qWarning(E2EE) << "Error matching an inbound session:" << lastError();
+
return maybeMatches == 1; // Any errors are treated as non-match
}
@@ -218,8 +222,8 @@ bool QOlmSession::matchesInboundSessionFrom(
oneTimeKeyMessageBuf.data(), oneTimeKeyMessageBuf.length());
if (maybeMatches == olm_error())
- qCWarning(E2EE) << "Error matching an inbound session:"
- << olm_session_last_error(m_session);
+ qCWarning(E2EE) << "Error matching an inbound session:" << lastError();
+
return maybeMatches == 1;
}
diff --git a/lib/e2ee/qolmsession.h b/lib/e2ee/qolmsession.h
index 174e98ef..400fb854 100644
--- a/lib/e2ee/qolmsession.h
+++ b/lib/e2ee/qolmsession.h
@@ -30,7 +30,7 @@ public:
const QByteArray& theirOneTimeKey);
//! Serialises an `QOlmSession` to encrypted Base64.
- QOlmExpected<QByteArray> pickle(const PicklingMode &mode) const;
+ QByteArray pickle(const PicklingMode &mode) const;
//! Deserialises from encrypted Base64 previously made with pickle()
static QOlmExpected<QOlmSessionPtr> unpickle(QByteArray&& pickled,
diff --git a/lib/e2ee/qolmutils.h b/lib/e2ee/qolmutils.h
index da9d2d18..17eee7a3 100644
--- a/lib/e2ee/qolmutils.h
+++ b/lib/e2ee/qolmutils.h
@@ -34,4 +34,22 @@ public:
return RandomBuffer(bufferSize);
}
+#define QOLM_INTERNAL_ERROR_X(Message_, LastError_) \
+ qFatal("%s, internal error: %s", Message_, LastError_)
+
+#define QOLM_INTERNAL_ERROR(Message_) \
+ QOLM_INTERNAL_ERROR_X(Message_, lastError())
+
+#define QOLM_FAIL_OR_LOG_X(InternalCondition_, Message_, LastErrorText_) \
+ do { \
+ const QString errorMsg{ (Message_) }; \
+ if (InternalCondition_) \
+ QOLM_INTERNAL_ERROR_X(qPrintable(errorMsg), (LastErrorText_)); \
+ qWarning(E2EE).nospace() << errorMsg << ": " << (LastErrorText_); \
+ } while (false) /* End of macro */
+
+#define QOLM_FAIL_OR_LOG(InternalFailureValue_, Message_) \
+ QOLM_FAIL_OR_LOG_X(lastErrorCode() == (InternalFailureValue_), (Message_), \
+ lastError())
+
} // namespace Quotient