aboutsummaryrefslogtreecommitdiff
path: root/lib/olm
diff options
context:
space:
mode:
authorCarl Schwan <carl@carlschwan.eu>2021-01-27 15:33:46 +0100
committerTobias Fella <fella@posteo.de>2021-12-01 21:34:52 +0100
commiteabea7af10b5734a507484478a64d2c9f716279f (patch)
tree04abf250636dadd8f639c9c34d0a6af571aa4730 /lib/olm
parent069602584e0f3ec10a26380af69b95f5da11a8b7 (diff)
downloadlibquotient-eabea7af10b5734a507484478a64d2c9f716279f.tar.gz
libquotient-eabea7af10b5734a507484478a64d2c9f716279f.zip
Add QOlmSession::decrypt
Diffstat (limited to 'lib/olm')
-rw-r--r--lib/olm/session.cpp41
-rw-r--r--lib/olm/session.h6
2 files changed, 46 insertions, 1 deletions
diff --git a/lib/olm/session.cpp b/lib/olm/session.cpp
index d0493fe8..a05e0786 100644
--- a/lib/olm/session.cpp
+++ b/lib/olm/session.cpp
@@ -6,6 +6,7 @@
#include "olm/session.h"
#include "olm/utils.h"
#include "logging.h"
+#include <cstring>
using namespace Quotient;
@@ -142,6 +143,46 @@ Message QOlmSession::encrypt(const QString &plaintext)
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);
diff --git a/lib/olm/session.h b/lib/olm/session.h
index c45b6898..3f1622c7 100644
--- a/lib/olm/session.h
+++ b/lib/olm/session.h
@@ -32,7 +32,11 @@ public:
static std::variant<std::unique_ptr<QOlmSession>, OlmError> unpickle(QByteArray &pickled, const PicklingMode &mode);
//! Encrypts a plaintext message using the session.
Message encrypt(const QString &plaintext);
- // TODO: WiP
+
+ //! 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;