summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2020-12-18 03:04:18 +0100
committerNicolas Werner <nicolas.werner@hotmail.de>2020-12-18 03:04:18 +0100
commit994c28ea95cff649213e782a8bed85d5c5f50bd7 (patch)
tree97de85bb81dc013972a6287ec3935a2e4d21da1f /src
parent9d2177afe24401821aae6df925b8ca09fa0765d8 (diff)
Add download keys from secret storage
Diffstat (limited to 'src')
-rw-r--r--src/ChatPage.cpp53
-rw-r--r--src/ChatPage.h8
-rw-r--r--src/Olm.cpp67
-rw-r--r--src/UserSettingsPage.cpp4
4 files changed, 131 insertions, 1 deletions
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 2d223584..e3325c05 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -17,6 +17,7 @@
#include <QApplication>
#include <QImageReader>
+#include <QInputDialog>
#include <QMessageBox>
#include <QSettings>
#include <QShortcut>
@@ -64,6 +65,8 @@ constexpr size_t MAX_ONETIME_KEYS = 50;
Q_DECLARE_METATYPE(std::optional<mtx::crypto::EncryptedFile>)
Q_DECLARE_METATYPE(std::optional<RelatedInfo>)
Q_DECLARE_METATYPE(mtx::presence::PresenceState)
+Q_DECLARE_METATYPE(mtx::secret_storage::AesHmacSha2KeyDescription)
+Q_DECLARE_METATYPE(SecretsToDecrypt)
ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
: QWidget(parent)
@@ -79,6 +82,8 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
qRegisterMetaType<std::optional<mtx::crypto::EncryptedFile>>();
qRegisterMetaType<std::optional<RelatedInfo>>();
qRegisterMetaType<mtx::presence::PresenceState>();
+ qRegisterMetaType<mtx::secret_storage::AesHmacSha2KeyDescription>();
+ qRegisterMetaType<SecretsToDecrypt>();
topLayout_ = new QHBoxLayout(this);
topLayout_->setSpacing(0);
@@ -136,6 +141,12 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
splitter->addWidget(content_);
splitter->restoreSizes(parent->width());
+ connect(this,
+ &ChatPage::downloadedSecrets,
+ this,
+ &ChatPage::decryptDownloadedSecrets,
+ Qt::QueuedConnection);
+
connect(this, &ChatPage::connectionLost, this, [this]() {
nhlog::net()->info("connectivity lost");
isConnected_ = false;
@@ -1208,3 +1219,45 @@ ChatPage::connectCallMessage()
view_manager_,
qOverload<const QString &, const T &>(&TimelineViewManager::queueCallMessage));
}
+
+void
+ChatPage::decryptDownloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
+ const SecretsToDecrypt &secrets)
+{
+ QString text = QInputDialog::getText(
+ ChatPage::instance(),
+ QCoreApplication::translate("CrossSigningSecrets", "Decrypt secrets"),
+ keyDesc.name.empty()
+ ? QCoreApplication::translate(
+ "CrossSigningSecrets",
+ "Enter your recovery key or passphrase to decrypt your secrets:")
+ : QCoreApplication::translate(
+ "CrossSigningSecrets",
+ "Enter your recovery key or passphrase called %1 to decrypt your secrets:")
+ .arg(QString::fromStdString(keyDesc.name)),
+ QLineEdit::Password);
+
+ if (text.isEmpty())
+ return;
+
+ auto decryptionKey = mtx::crypto::key_from_recoverykey(text.toStdString(), keyDesc);
+
+ if (!decryptionKey)
+ decryptionKey = mtx::crypto::key_from_passphrase(text.toStdString(), keyDesc);
+
+ if (!decryptionKey) {
+ QMessageBox::information(
+ ChatPage::instance(),
+ QCoreApplication::translate("CrossSigningSecrets", "Decrytion failed"),
+ QCoreApplication::translate("CrossSigningSecrets",
+ "Failed to decrypt secrets with the "
+ "provided recovery key or passphrase"));
+ return;
+ }
+
+ for (const auto &[secretName, encryptedSecret] : secrets) {
+ auto decrypted = mtx::crypto::decrypt(encryptedSecret, *decryptionKey, secretName);
+ if (!decrypted.empty())
+ cache::storeSecret(secretName, decrypted);
+ }
+}
diff --git a/src/ChatPage.h b/src/ChatPage.h
index 5b336cbb..45a4ff63 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -27,6 +27,7 @@
#include <mtx/events/encrypted.hpp>
#include <mtx/events/member.hpp>
#include <mtx/events/presence.hpp>
+#include <mtx/secret_storage.hpp>
#include <QFrame>
#include <QHBoxLayout>
@@ -72,6 +73,8 @@ namespace popups {
class UserMentions;
}
+using SecretsToDecrypt = std::map<std::string, mtx::secret_storage::AesHmacSha2EncryptedData>;
+
class ChatPage : public QWidget
{
Q_OBJECT
@@ -117,6 +120,8 @@ public slots:
void unbanUser(QString userid, QString reason);
void receivedSessionKey(const std::string &room_id, const std::string &session_id);
+ void decryptDownloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
+ const SecretsToDecrypt &secrets);
signals:
void connectionLost();
@@ -185,6 +190,9 @@ signals:
void receivedDeviceVerificationReady(const mtx::events::msg::KeyVerificationReady &message);
void receivedDeviceVerificationDone(const mtx::events::msg::KeyVerificationDone &message);
+ void downloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
+ const SecretsToDecrypt &secrets);
+
private slots:
void logout();
void removeRoom(const QString &room_id);
diff --git a/src/Olm.cpp b/src/Olm.cpp
index 82a61fba..0dbd5124 100644
--- a/src/Olm.cpp
+++ b/src/Olm.cpp
@@ -1243,8 +1243,73 @@ request_cross_signing_keys()
request(mtx::secret_storage::secrets::cross_signing_user_signing);
request(mtx::secret_storage::secrets::megolm_backup_v1);
}
+
+namespace {
+void
+unlock_secrets(const std::string &key,
+ const std::map<std::string, mtx::secret_storage::AesHmacSha2EncryptedData> &secrets)
+{
+ http::client()->secret_storage_key(
+ key,
+ [secrets](mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
+ mtx::http::RequestErr err) {
+ if (err) {
+ nhlog::net()->error("Failed to download secret storage key");
+ return;
+ }
+
+ emit ChatPage::instance()->downloadedSecrets(keyDesc, secrets);
+ });
+}
+}
+
void
download_cross_signing_keys()
-{}
+{
+ using namespace mtx::secret_storage;
+ http::client()->secret_storage_secret(
+ secrets::megolm_backup_v1, [](Secret secret, mtx::http::RequestErr err) {
+ std::optional<Secret> backup_key;
+ if (!err)
+ backup_key = secret;
+
+ http::client()->secret_storage_secret(
+ secrets::cross_signing_self_signing,
+ [backup_key](Secret secret, mtx::http::RequestErr err) {
+ std::optional<Secret> self_signing_key;
+ if (!err)
+ self_signing_key = secret;
+
+ http::client()->secret_storage_secret(
+ secrets::cross_signing_user_signing,
+ [backup_key, self_signing_key](Secret secret,
+ mtx::http::RequestErr err) {
+ std::optional<Secret> user_signing_key;
+ if (!err)
+ user_signing_key = secret;
+
+ std::map<std::string,
+ std::map<std::string, AesHmacSha2EncryptedData>>
+ secrets;
+
+ if (backup_key && !backup_key->encrypted.empty())
+ secrets[backup_key->encrypted.begin()->first]
+ [secrets::megolm_backup_v1] =
+ backup_key->encrypted.begin()->second;
+ if (self_signing_key && !self_signing_key->encrypted.empty())
+ secrets[self_signing_key->encrypted.begin()->first]
+ [secrets::cross_signing_self_signing] =
+ self_signing_key->encrypted.begin()->second;
+ if (user_signing_key && !user_signing_key->encrypted.empty())
+ secrets[user_signing_key->encrypted.begin()->first]
+ [secrets::cross_signing_user_signing] =
+ user_signing_key->encrypted.begin()->second;
+
+ for (const auto &[key, secrets] : secrets)
+ unlock_secrets(key, secrets);
+ });
+ });
+ });
+}
} // namespace olm
diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp
index fe0145fe..9fd76bda 100644
--- a/src/UserSettingsPage.cpp
+++ b/src/UserSettingsPage.cpp
@@ -1029,6 +1029,10 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
olm::request_cross_signing_keys();
});
+ connect(crossSigningDownloadBtn, &QPushButton::clicked, this, []() {
+ olm::download_cross_signing_keys();
+ });
+
connect(backBtn_, &QPushButton::clicked, this, [this]() {
settings_->save();
emit moveBack();