aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/connection.cpp6
-rw-r--r--lib/connection.h3
-rw-r--r--lib/jobs/downloadfilejob.cpp48
-rw-r--r--lib/jobs/downloadfilejob.h3
-rw-r--r--lib/mxcreply.cpp36
-rw-r--r--lib/networkaccessmanager.cpp6
-rw-r--r--lib/networkaccessmanager.h2
-rw-r--r--lib/room.cpp2
8 files changed, 59 insertions, 47 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp
index 4a1130ae..d8e98bb0 100644
--- a/lib/connection.cpp
+++ b/lib/connection.cpp
@@ -1019,15 +1019,13 @@ DownloadFileJob* Connection::downloadFile(const QUrl& url,
#ifdef Quotient_E2EE_ENABLED
DownloadFileJob* Connection::downloadFile(const QUrl& url,
- const QString& key,
- const QString& iv,
- const QString& sha256,
+ const EncryptedFile file,
const QString& localFilename)
{
auto mediaId = url.authority() + url.path();
auto idParts = splitMediaId(mediaId);
auto* job =
- callApi<DownloadFileJob>(idParts.front(), idParts.back(), key, iv, sha256, localFilename);
+ callApi<DownloadFileJob>(idParts.front(), idParts.back(), file, localFilename);
return job;
}
#endif
diff --git a/lib/connection.h b/lib/connection.h
index f9143d3e..d0945aa4 100644
--- a/lib/connection.h
+++ b/lib/connection.h
@@ -568,8 +568,7 @@ public Q_SLOTS:
const QString& localFilename = {});
#ifdef Quotient_E2EE_ENABLED
- DownloadFileJob* downloadFile(const QUrl& url, const QString &key,
- const QString& iv, const QString& sha256,
+ DownloadFileJob* downloadFile(const QUrl& url, const EncryptedFile file,
const QString& localFilename = {});
#endif
/**
diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp
index e82271eb..2fba1973 100644
--- a/lib/jobs/downloadfilejob.cpp
+++ b/lib/jobs/downloadfilejob.cpp
@@ -9,20 +9,8 @@
#ifdef Quotient_E2EE_ENABLED
# include <QCryptographicHash>
-# include <openssl/evp.h>
-
-QByteArray decrypt(const QByteArray &ciphertext, const QByteArray &key, const QByteArray &iv)
-{
- QByteArray plaintext(ciphertext.size(), 0);
- EVP_CIPHER_CTX *ctx;
- int length;
- ctx = EVP_CIPHER_CTX_new();
- EVP_DecryptInit_ex(ctx, EVP_aes_256_ctr(), NULL, (const unsigned char *)key.data(), (const unsigned char *)iv.data());
- EVP_DecryptUpdate(ctx, (unsigned char *)plaintext.data(), &length, (const unsigned char *)ciphertext.data(), ciphertext.size());
- EVP_DecryptFinal_ex(ctx, (unsigned char *)plaintext.data() + length, &length);
- EVP_CIPHER_CTX_free(ctx);
- return plaintext;
-}
+# include "encryptionmanager.h"
+# include "events/encryptedfile.h"
#endif
using namespace Quotient;
@@ -39,9 +27,7 @@ public:
QScopedPointer<QFile> tempFile;
#ifdef Quotient_E2EE_ENABLED
- QByteArray key;
- QByteArray iv;
- QByteArray sha256;
+ Omittable<EncryptedFile> encryptedFile;
#endif
};
@@ -63,18 +49,13 @@ DownloadFileJob::DownloadFileJob(const QString& serverName,
#ifdef Quotient_E2EE_ENABLED
DownloadFileJob::DownloadFileJob(const QString& serverName,
const QString& mediaId,
- const QString& key,
- const QString& iv,
- const QString& sha256,
+ const EncryptedFile file,
const QString& localFilename)
: GetContentJob(serverName, mediaId)
, d(localFilename.isEmpty() ? new Private : new Private(localFilename))
{
setObjectName(QStringLiteral("DownloadFileJob"));
- auto _key = key;
- d->key = QByteArray::fromBase64(_key.replace(QLatin1Char('_'), QLatin1Char('/')).replace(QLatin1Char('-'), QLatin1Char('+')).toLatin1());
- d->iv = QByteArray::fromBase64(iv.toLatin1());
- d->sha256 = QByteArray::fromBase64(sha256.toLatin1());
+ d->encryptedFile = file;
}
#endif
QString DownloadFileJob::targetFileName() const
@@ -140,14 +121,12 @@ BaseJob::Status DownloadFileJob::prepareResult()
{
if (d->targetFile) {
#ifdef Quotient_E2EE_ENABLED
- if(d->key.size() != 0) {
+ if (d->encryptedFile.has_value()) {
d->tempFile->seek(0);
QByteArray encrypted = d->tempFile->readAll();
- if(d->sha256 != QCryptographicHash::hash(encrypted, QCryptographicHash::Sha256)) {
- qCWarning(E2EE) << "Hash verification failed for file";
- return IncorrectResponse;
- }
- auto decrypted = decrypt(encrypted, d->key, d->iv);
+
+ EncryptedFile file = *d->encryptedFile;
+ auto decrypted = EncryptionManager::decryptFile(encrypted, &file);
d->targetFile->write(decrypted);
d->tempFile->remove();
} else {
@@ -167,15 +146,12 @@ BaseJob::Status DownloadFileJob::prepareResult()
#endif
} else {
#ifdef Quotient_E2EE_ENABLED
- if(d->key.size() != 0) {
+ if (d->encryptedFile.has_value()) {
d->tempFile->seek(0);
auto encrypted = d->tempFile->readAll();
- if(d->sha256 != QCryptographicHash::hash(encrypted, QCryptographicHash::Sha256)) {
- qCWarning(E2EE) << "Hash verification failed for file";
- return IncorrectResponse;
- }
- auto decrypted = decrypt(encrypted, d->key, d->iv);
+ EncryptedFile file = *d->encryptedFile;
+ auto decrypted = EncryptionManager::decryptFile(encrypted, &file);
d->tempFile->write(decrypted);
} else {
#endif
diff --git a/lib/jobs/downloadfilejob.h b/lib/jobs/downloadfilejob.h
index f000b991..67a3e95f 100644
--- a/lib/jobs/downloadfilejob.h
+++ b/lib/jobs/downloadfilejob.h
@@ -4,6 +4,7 @@
#pragma once
#include "csapi/content-repo.h"
+#include "events/encryptedfile.h"
namespace Quotient {
class DownloadFileJob : public GetContentJob {
@@ -15,7 +16,7 @@ public:
const QString& localFilename = {});
#ifdef Quotient_E2EE_ENABLED
- DownloadFileJob(const QString& serverName, const QString& mediaId, const QString& key, const QString& iv, const QString& sha256, const QString& localFilename = {});
+ DownloadFileJob(const QString& serverName, const QString& mediaId, const EncryptedFile file, const QString& localFilename = {});
#endif
QString targetFileName() const;
diff --git a/lib/mxcreply.cpp b/lib/mxcreply.cpp
index 0b6643fc..65078301 100644
--- a/lib/mxcreply.cpp
+++ b/lib/mxcreply.cpp
@@ -3,8 +3,17 @@
#include "mxcreply.h"
+#include <algorithm>
+#include <QBuffer>
+#include "accountregistry.h"
+#include "connection.h"
#include "room.h"
+#ifdef Quotient_E2EE_ENABLED
+#include "encryptionmanager.h"
+#include "events/encryptedfile.h"
+#endif
+
using namespace Quotient;
class MxcReply::Private
@@ -14,6 +23,8 @@ public:
: m_reply(r)
{}
QNetworkReply* m_reply;
+ Omittable<EncryptedFile> m_encryptedFile;
+ QIODevice* m_device = nullptr;
};
MxcReply::MxcReply(QNetworkReply* reply)
@@ -31,11 +42,32 @@ MxcReply::MxcReply(QNetworkReply* reply, Room* room, const QString &eventId)
: d(std::make_unique<Private>(reply))
{
reply->setParent(this);
- connect(d->m_reply, &QNetworkReply::finished, this, [this, room, eventId]() {
+ connect(d->m_reply, &QNetworkReply::finished, this, [this]() {
setError(d->m_reply->error(), d->m_reply->errorString());
+
+#ifdef Quotient_E2EE_ENABLED
+ if(!d->m_encryptedFile.has_value()) {
+ d->m_device = d->m_reply;
+ } else {
+ EncryptedFile file = *d->m_encryptedFile;
+ auto buffer = new QBuffer(this);
+ buffer->setData(EncryptionManager::decryptFile(d->m_reply->readAll(), &file));
+ d->m_device = buffer;
+ }
setOpenMode(ReadOnly);
emit finished();
+#else
+ d->m_device = d->m_reply;
+#endif
});
+
+#ifdef Quotient_E2EE_ENABLED
+ auto eventIt = room->findInTimeline(eventId);
+ if(eventIt != room->historyEdge()) {
+ auto event = eventIt->viewAs<RoomMessageEvent>();
+ d->m_encryptedFile = event->content()->fileInfo()->file;
+ }
+#endif
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
@@ -61,7 +93,7 @@ MxcReply::MxcReply()
qint64 MxcReply::readData(char *data, qint64 maxSize)
{
- return d->m_reply->read(data, maxSize);
+ return d->m_device->read(data, maxSize);
}
void MxcReply::abort()
diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp
index d0380cec..c660cff8 100644
--- a/lib/networkaccessmanager.cpp
+++ b/lib/networkaccessmanager.cpp
@@ -12,6 +12,12 @@
#include <QtCore/QThreadStorage>
#include <QtCore/QSettings>
#include <QtNetwork/QNetworkReply>
+#include "accountregistry.h"
+#include "mxcreply.h"
+#include "connection.h"
+#include "events/eventcontent.h"
+
+#include "room.h"
using namespace Quotient;
diff --git a/lib/networkaccessmanager.h b/lib/networkaccessmanager.h
index 7643302f..efa41994 100644
--- a/lib/networkaccessmanager.h
+++ b/lib/networkaccessmanager.h
@@ -9,7 +9,7 @@
namespace Quotient {
class Room;
-class Connection;
+
class NetworkAccessManager : public QNetworkAccessManager {
Q_OBJECT
public:
diff --git a/lib/room.cpp b/lib/room.cpp
index d7ebe021..688ba5d4 100644
--- a/lib/room.cpp
+++ b/lib/room.cpp
@@ -2409,7 +2409,7 @@ void Room::downloadFile(const QString& eventId, const QUrl& localFilename)
#ifdef Quotient_E2EE_ENABLED
if(fileInfo->file.has_value()) {
auto file = *fileInfo->file;
- job = connection()->downloadFile(fileUrl, file.key.k, file.iv, file.hashes["sha256"], filePath);
+ job = connection()->downloadFile(fileUrl, file, filePath);
} else {
#endif
job = connection()->downloadFile(fileUrl, filePath);