diff options
Diffstat (limited to 'src/format/OpVaultReader.h')
-rw-r--r-- | src/format/OpVaultReader.h | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/format/OpVaultReader.h b/src/format/OpVaultReader.h new file mode 100644 index 000000000..585415854 --- /dev/null +++ b/src/format/OpVaultReader.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2019 KeePassXC Team <team@keepassxc.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef OPVAULT_READER_H_ +#define OPVAULT_READER_H_ + +#include <QDir> + +#include "core/Database.h" +#include "core/Metadata.h" + +/*! + * Imports a directory in the 1Password \c opvault format into a \c Database. + * \sa https://support.1password.com/opvault-overview/ + * \sa https://support.1password.com/opvault-design/ + * \sa https://cache.agilebits.com/security-kb/freddy-2013-12-04.tar.gz is the sample data used to test this class, + * and its password is \c freddy + */ +class OpVaultReader : public QObject +{ + Q_OBJECT + +public: + explicit OpVaultReader(QObject* parent = nullptr); + ~OpVaultReader() override; + + Database* readDatabase(QDir& opdataDir, const QString& password); + + bool hasError(); + QString errorString(); + +private: + struct DerivedKeyHMAC + { + QByteArray encrypt; + QByteArray hmac; + bool error; + QString errorStr; + }; + + QJsonObject readAndAssertJsonFile(QFile& file, const QString& stripLeading, const QString& stripTrailing); + + DerivedKeyHMAC* deriveKeysFromPassPhrase(QByteArray& salt, const QString& password, unsigned long iterations); + DerivedKeyHMAC* decodeB64CompositeKeys(const QString& b64, const QByteArray& encKey, const QByteArray& hmacKey); + DerivedKeyHMAC* decodeCompositeKeys(const QByteArray& keyKey); + + /*! + * \sa https://support.1password.com/opvault-design/#profile-js + * @param profileJson the contents of \c profile.js + * @return \c true if the profile data was decrypted successfully, \c false otherwise + */ + bool processProfileJson(QJsonObject& profileJson, const QString& password, Group* rootGroup); + + /*! + * \sa https://support.1password.com/opvault-design/#folders-js + * @param foldersJson the map from a folder UUID to its data (name and any smart query) + * @return \c true if the folder data was decrypted successfully, \c false otherwise + */ + bool processFolderJson(QJsonObject& foldersJson, Group* rootGroup); + + /*! + * Decrypts the provided band object into its interior structure, + * as well as the encryption key and HMAC key declared therein, + * which are used to decrypt the attachments, also. + * @returns \c nullptr if unable to do the decryption, otherwise the interior object and its keys + */ + bool decryptBandEntry(const QJsonObject& bandEntry, QJsonObject& data, QByteArray& key, QByteArray& hmacKey); + Entry* processBandEntry(const QJsonObject& bandEntry, const QDir& attachmentDir, Group* rootGroup); + + bool readAttachment(const QString& filePath, + const QByteArray& itemKey, + const QByteArray& itemHmacKey, + QJsonObject& metadata, + QByteArray& payload); + void fillAttachment(Entry* entry, + const QFileInfo& attachmentFileInfo, + const QByteArray& entryKey, + const QByteArray& entryHmacKey); + void fillAttachments(Entry* entry, + const QDir& attachmentDir, + const QByteArray& entryKey, + const QByteArray& entryHmacKey); + + bool fillAttributes(Entry* entry, const QJsonObject& bandEntry); + + void fillFromSection(Entry* entry, const QJsonObject& section); + void fillFromSectionField(Entry* entry, const QString& sectionName, QJsonObject& field); + QString resolveAttributeName(const QString& section, const QString& name, const QString& text); + + void populateCategoryGroups(Group* rootGroup); + /*! Used to blank the memory after the keys have been used. */ + void zeroKeys(); + + bool m_error; + QString m_errorStr; + QByteArray m_masterKey; + QByteArray m_masterHmacKey; + /*! Used to decrypt overview text, such as folder names. */ + QByteArray m_overviewKey; + QByteArray m_overviewHmacKey; + + friend class TestOpVaultReader; +}; + +#endif /* OPVAULT_READER_H_ */ |