From 1b14c127a4c969e86e1ffb8520d9772036651223 Mon Sep 17 00:00:00 2001 From: Matthieu Gallien Date: Tue, 28 Mar 2023 00:45:28 +0200 Subject: [PATCH] check checksum when getting e2ee metadata Signed-off-by: Matthieu Gallien --- src/libsync/clientsideencryption.cpp | 45 ++++++++++++++++++++-------- src/libsync/clientsideencryption.h | 4 +++ 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/libsync/clientsideencryption.cpp b/src/libsync/clientsideencryption.cpp index ef6d0982c..38c819076 100644 --- a/src/libsync/clientsideencryption.cpp +++ b/src/libsync/clientsideencryption.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -1555,10 +1556,10 @@ void FolderMetadata::setupExistingMetadata(const QByteArray& metadata) } } - if (_metadataKey.isEmpty()) { - qCDebug(lcCse()) << "Could not setup existing metadata with missing metadataKeys!"; - return; - } + const auto sharing = metadataObj["sharing"].toString().toLocal8Bit(); + const auto files = metaDataDoc.object()["files"].toObject(); + const auto metadataKey = metaDataDoc.object()["metadata"].toObject()["metadataKey"].toString().toUtf8(); + const auto metadataKeyChecksum = metaDataDoc.object()["metadata"].toObject()["checksum"].toString().toUtf8(); QByteArray sharing = metadataObj["sharing"].toString().toLocal8Bit(); QJsonObject files = metaDataDoc.object()["files"].toObject(); @@ -1609,17 +1610,15 @@ void FolderMetadata::setupExistingMetadata(const QByteArray& metadata) file.encryptionKey = QByteArray::fromBase64(decryptedFileObj["key"].toString().toLocal8Bit()); file.mimetype = decryptedFileObj["mimetype"].toString().toLocal8Bit(); - // In case we wrongly stored "inode/directory" we try to recover from it - if (file.mimetype == QByteArrayLiteral("inode/directory")) { - file.mimetype = QByteArrayLiteral("httpd/unix-directory"); + if (!checkMetadataKeyChecksum(metadataKey, metadataKeyChecksum)) { + _metadataKey.clear(); + _files.clear(); + return; } - _files.push_back(file); - } - - // decryption finished, create new metadata key to be used for encryption - _metadataKey = EncryptionHelper::generateRandom(metadataKeySize); - _isMetadataSetup = true; + // decryption finished, create new metadata key to be used for encryption + _metadataKey = EncryptionHelper::generateRandom(metadataKeySize); + _isMetadataSetup = true; } // RSA/ECB/OAEPWithSHA-256AndMGF1Padding using private / public key. @@ -1663,6 +1662,26 @@ QByteArray FolderMetadata::decryptJsonObject(const QByteArray& encryptedMetadata return EncryptionHelper::decryptStringSymmetric(pass, encryptedMetadata); } +bool FolderMetadata::checkMetadataKeyChecksum(const QByteArray &metadataKey, + const QByteArray &metadataKeyChecksum) const +{ + const auto referenceMetadataKeyValue = computeMetadataKeyChecksum(metadataKey); + return referenceMetadataKeyValue == metadataKeyChecksum; +} + +QByteArray FolderMetadata::computeMetadataKeyChecksum(const QByteArray &metadataKey) const +{ + auto checksumData = _account->e2e()->_mnemonic.remove(' '); + for (const auto &singleFile : _files) { + checksumData += singleFile.encryptedFilename; + } + checksumData += metadataKey; + + auto hashAlgorithm = QCryptographicHash{QCryptographicHash::Sha256}; + hashAlgorithm.addData(checksumData.toUtf8()); + return hashAlgorithm.result().toHex(); +} + bool FolderMetadata::isMetadataSetup() const { return _isMetadataSetup; diff --git a/src/libsync/clientsideencryption.h b/src/libsync/clientsideencryption.h index a9a37e0cd..a180ef78f 100644 --- a/src/libsync/clientsideencryption.h +++ b/src/libsync/clientsideencryption.h @@ -213,6 +213,10 @@ private: [[nodiscard]] QByteArray encryptJsonObject(const QByteArray& obj, const QByteArray pass) const; [[nodiscard]] QByteArray decryptJsonObject(const QByteArray& encryptedJsonBlob, const QByteArray& pass) const; + [[nodiscard]] bool checkMetadataKeyChecksum(const QByteArray &metadataKey, const QByteArray &metadataKeyChecksum) const; + + [[nodiscard]] QByteArray computeMetadataKeyChecksum(const QByteArray &metadataKey) const; + QByteArray _metadataKey; QVector _files;