2010-09-13 23:24:36 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
|
2017-06-09 23:40:36 +02:00
|
|
|
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
2010-09-13 23:24:36 +02:00
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "CompositeKey.h"
|
2017-01-14 13:25:30 -05:00
|
|
|
#include <QFile>
|
|
|
|
#include <QtConcurrent>
|
2012-04-18 22:08:22 +02:00
|
|
|
|
2016-09-02 19:51:51 +02:00
|
|
|
#include "core/Global.h"
|
2010-09-13 23:24:36 +02:00
|
|
|
#include "crypto/CryptoHash.h"
|
|
|
|
|
2011-11-13 14:52:43 +01:00
|
|
|
CompositeKey::CompositeKey()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CompositeKey::CompositeKey(const CompositeKey& key)
|
|
|
|
{
|
|
|
|
*this = key;
|
|
|
|
}
|
|
|
|
|
2010-09-13 23:24:36 +02:00
|
|
|
CompositeKey::~CompositeKey()
|
|
|
|
{
|
2012-04-25 18:35:30 +02:00
|
|
|
clear();
|
2010-09-13 23:24:36 +02:00
|
|
|
}
|
|
|
|
|
2012-01-11 23:59:50 +01:00
|
|
|
void CompositeKey::clear()
|
|
|
|
{
|
|
|
|
qDeleteAll(m_keys);
|
|
|
|
m_keys.clear();
|
2015-01-27 17:38:26 +00:00
|
|
|
m_challengeResponseKeys.clear();
|
2012-01-11 23:59:50 +01:00
|
|
|
}
|
|
|
|
|
2012-10-12 12:10:13 +02:00
|
|
|
bool CompositeKey::isEmpty() const
|
|
|
|
{
|
2014-05-26 01:38:07 -07:00
|
|
|
return m_keys.isEmpty() && m_challengeResponseKeys.isEmpty();
|
2012-10-12 12:10:13 +02:00
|
|
|
}
|
|
|
|
|
2010-09-13 23:24:36 +02:00
|
|
|
CompositeKey* CompositeKey::clone() const
|
|
|
|
{
|
|
|
|
return new CompositeKey(*this);
|
|
|
|
}
|
|
|
|
|
2011-11-13 14:52:43 +01:00
|
|
|
CompositeKey& CompositeKey::operator=(const CompositeKey& key)
|
|
|
|
{
|
2012-07-17 10:47:56 +02:00
|
|
|
// handle self assignment as that would break when calling clear()
|
|
|
|
if (this == &key) {
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2012-04-21 18:09:14 +02:00
|
|
|
clear();
|
|
|
|
|
2016-09-02 19:51:51 +02:00
|
|
|
for (const Key* subKey : asConst(key.m_keys)) {
|
2012-04-25 18:35:30 +02:00
|
|
|
addKey(*subKey);
|
2011-11-13 14:52:43 +01:00
|
|
|
}
|
2017-02-23 23:52:36 +01:00
|
|
|
for (const auto subKey : asConst(key.m_challengeResponseKeys)) {
|
|
|
|
addChallengeResponseKey(subKey);
|
2014-05-26 01:38:07 -07:00
|
|
|
}
|
2011-11-13 14:52:43 +01:00
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
2010-09-13 23:24:36 +02:00
|
|
|
|
|
|
|
QByteArray CompositeKey::rawKey() const
|
|
|
|
{
|
|
|
|
CryptoHash cryptoHash(CryptoHash::Sha256);
|
|
|
|
|
2016-09-02 19:51:51 +02:00
|
|
|
for (const Key* key : m_keys) {
|
2010-09-13 23:24:36 +02:00
|
|
|
cryptoHash.addData(key->rawKey());
|
|
|
|
}
|
|
|
|
|
|
|
|
return cryptoHash.result();
|
|
|
|
}
|
|
|
|
|
2017-11-12 20:20:57 +08:00
|
|
|
bool CompositeKey::transform(const Kdf& kdf, QByteArray& result) const
|
2010-09-13 23:24:36 +02:00
|
|
|
{
|
2017-11-12 20:20:57 +08:00
|
|
|
return kdf.transform(rawKey(), result);
|
2010-09-13 23:24:36 +02:00
|
|
|
}
|
|
|
|
|
2014-09-06 17:49:39 -07:00
|
|
|
bool CompositeKey::challenge(const QByteArray& seed, QByteArray& result) const
|
2014-05-26 01:38:07 -07:00
|
|
|
{
|
2017-02-23 23:52:36 +01:00
|
|
|
// if no challenge response was requested, return nothing to
|
|
|
|
// maintain backwards compatibility with regular databases.
|
2014-05-26 01:38:07 -07:00
|
|
|
if (m_challengeResponseKeys.length() == 0) {
|
2015-01-27 17:38:26 +00:00
|
|
|
result.clear();
|
2014-09-06 17:49:39 -07:00
|
|
|
return true;
|
2014-05-26 01:38:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
CryptoHash cryptoHash(CryptoHash::Sha256);
|
|
|
|
|
2017-02-23 23:52:36 +01:00
|
|
|
for (const auto key : m_challengeResponseKeys) {
|
|
|
|
// if the device isn't present or fails, return an error
|
|
|
|
if (!key->challenge(seed)) {
|
2014-09-06 17:49:39 -07:00
|
|
|
return false;
|
|
|
|
}
|
2014-05-26 01:38:07 -07:00
|
|
|
cryptoHash.addData(key->rawKey());
|
|
|
|
}
|
|
|
|
|
2014-09-06 17:49:39 -07:00
|
|
|
result = cryptoHash.result();
|
|
|
|
return true;
|
2014-05-26 01:38:07 -07:00
|
|
|
}
|
|
|
|
|
2011-11-12 01:49:19 +01:00
|
|
|
void CompositeKey::addKey(const Key& key)
|
2010-09-13 23:24:36 +02:00
|
|
|
{
|
2011-11-12 01:49:19 +01:00
|
|
|
m_keys.append(key.clone());
|
2010-09-13 23:24:36 +02:00
|
|
|
}
|
2012-05-07 14:38:10 +02:00
|
|
|
|
2017-02-23 23:52:36 +01:00
|
|
|
void CompositeKey::addChallengeResponseKey(QSharedPointer<ChallengeResponseKey> key)
|
2014-05-26 01:38:07 -07:00
|
|
|
{
|
2017-02-23 23:52:36 +01:00
|
|
|
m_challengeResponseKeys.append(key);
|
2014-05-26 01:38:07 -07:00
|
|
|
}
|