From 689dee6a16c97b86eb487f25ffc3d1182c8744c5 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Fri, 11 Nov 2022 15:54:13 +0100 Subject: [PATCH] Properly handle sensitive data deletion in ClientSideEncryption Signed-off-by: Claudio Cambra --- src/libsync/clientsideencryption.cpp | 74 ++++++++++++++++++++++++---- src/libsync/clientsideencryption.h | 9 ++++ 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/src/libsync/clientsideencryption.cpp b/src/libsync/clientsideencryption.cpp index 762dd5b2a..49b528dc6 100644 --- a/src/libsync/clientsideencryption.cpp +++ b/src/libsync/clientsideencryption.cpp @@ -1064,22 +1064,78 @@ void ClientSideEncryption::writeMnemonic(const AccountPtr &account) void ClientSideEncryption::forgetSensitiveData(const AccountPtr &account) { - _privateKey = QByteArray(); - _certificate = QSslCertificate(); _publicKey = QSslKey(); - _mnemonic = QString(); - auto startDeleteJob = [account](QString user) { + const auto createDeleteJob = [account](QString user) { auto *job = new DeletePasswordJob(Theme::instance()->appName()); job->setInsecureFallback(false); job->setKey(AbstractCredentials::keychainKey(account->url().toString(), user, account->id())); - job->start(); + return job; }; - auto user = account->credentials()->user(); - startDeleteJob(user + e2e_private); - startDeleteJob(user + e2e_cert); - startDeleteJob(user + e2e_mnemonic); + const auto user = account->credentials()->user(); + const auto deletePrivateKeyJob = createDeleteJob(user + e2e_private); + const auto deleteCertJob = createDeleteJob(user + e2e_cert); + const auto deleteMnemonicJob = createDeleteJob(user + e2e_mnemonic); + + connect(deletePrivateKeyJob, &DeletePasswordJob::finished, this, &ClientSideEncryption::handlePrivateKeyDeleted); + connect(deleteCertJob, &DeletePasswordJob::finished, this, &ClientSideEncryption::handleCertificateDeleted); + connect(deleteMnemonicJob, &DeletePasswordJob::finished, this, &ClientSideEncryption::handleMnemonicDeleted); + deletePrivateKeyJob->start(); + deleteCertJob->start(); + deleteMnemonicJob->start(); +} + +void ClientSideEncryption::handlePrivateKeyDeleted(QKeychain::Job *incoming) +{ + if (incoming->error() != QKeychain::NoError) { + qCWarning(lcCse) << "Private key could not be deleted:" << incoming->errorString(); + return; + } + + qCDebug(lcCse) << "Private key successfully deleted from keychain. Clearing."; + _privateKey = QByteArray(); + Q_EMIT privateKeyDeleted(); + checkAllSensitiveDataDeleted(); +} + +void ClientSideEncryption::handleCertificateDeleted(QKeychain::Job *incoming) +{ + if (incoming->error() != QKeychain::NoError) { + qCWarning(lcCse) << "Certificate could not be deleted:" << incoming->errorString(); + return; + } + + qCDebug(lcCse) << "Certificate successfully deleted from keychain. Clearing."; + _certificate = QSslCertificate(); + Q_EMIT certificateDeleted(); + checkAllSensitiveDataDeleted(); +} + +void ClientSideEncryption::handleMnemonicDeleted(QKeychain::Job *incoming) +{ + if (incoming->error() != QKeychain::NoError) { + qCWarning(lcCse) << "Mnemonic could not be deleted:" << incoming->errorString(); + return; + } + + qCDebug(lcCse) << "Mnemonic successfully deleted from keychain. Clearing."; + _mnemonic = QString(); + Q_EMIT mnemonicDeleted(); + checkAllSensitiveDataDeleted(); +} + +void ClientSideEncryption::checkAllSensitiveDataDeleted() +{ + if (_privateKey.isEmpty() && _certificate.isNull() && _mnemonic.isEmpty()) { + qCDebug(lcCse) << "All sensitive encryption data has been deleted."; + Q_EMIT sensitiveDataForgotten(); + } + + qCDebug(lcCse) << "Some sensitive data emaining:" + << "Private key:" << _privateKey + << "Certificate is null:" << _certificate.isNull() + << "Mnemonic:" << _mnemonic; } void ClientSideEncryption::generateKeyPair(const AccountPtr &account) diff --git a/src/libsync/clientsideencryption.h b/src/libsync/clientsideencryption.h index 1783ebba5..037d231ea 100644 --- a/src/libsync/clientsideencryption.h +++ b/src/libsync/clientsideencryption.h @@ -128,6 +128,10 @@ public: signals: void initializationFinished(bool isNewMnemonicGenerated = false); + void sensitiveDataForgotten(); + void privateKeyDeleted(); + void certificateDeleted(); + void mnemonicDeleted(); public slots: void initialize(const AccountPtr &account); @@ -141,6 +145,11 @@ private slots: void privateKeyFetched(QKeychain::Job *incoming); void mnemonicKeyFetched(QKeychain::Job *incoming); + void handlePrivateKeyDeleted(QKeychain::Job *incoming); + void handleCertificateDeleted(QKeychain::Job *incoming); + void handleMnemonicDeleted(QKeychain::Job *incoming); + void checkAllSensitiveDataDeleted(); + void getPrivateKeyFromServer(const AccountPtr &account); void getPublicKeyFromServer(const AccountPtr &account); void fetchAndValidatePublicKeyFromServer(const AccountPtr &account); -- 2.30.2