Moved cryptography layer down from Device to DeviceLink

DeviceLinks will need to know what they are sending and receiving to handle
payloads, so encryption can not happen above them.
This commit is contained in:
Albert Vaca 2013-09-13 23:27:16 +02:00
parent d1f38a16b2
commit 42e0b4a066
6 changed files with 87 additions and 42 deletions

View file

@ -22,6 +22,7 @@
#define DEVICELINK_H
#include <QObject>
#include <QtCrypto>
#include "../networkpackage.h"
@ -39,15 +40,21 @@ public:
const QString& deviceId() { return mDeviceId; }
LinkProvider* provider() { return mLinkProvider; }
virtual bool sendPackage(const NetworkPackage& np) = 0;
virtual bool sendPackage(NetworkPackage& np) = 0;
virtual bool sendPackageEncrypted(QCA::PublicKey& publicKey, NetworkPackage& np) = 0;
void setPrivateKey(const QCA::PrivateKey& privateKey) { mPrivateKey = privateKey; }
Q_SIGNALS:
void receivedPackage(const NetworkPackage& np);
protected:
QCA::PrivateKey mPrivateKey;
private:
QString mDeviceId;
LinkProvider* mLinkProvider;
};
#endif // DEVICELINK_H
#endif

View file

@ -51,10 +51,17 @@ LanDeviceLink::LanDeviceLink(const QString& d, LinkProvider* a, QTcpSocket* sock
this, SLOT(dataReceived()));
}
bool LanDeviceLink::sendPackage(const NetworkPackage& np)
bool LanDeviceLink::sendPackageEncrypted(QCA::PublicKey& key, NetworkPackage& np)
{
np.encrypt(key);
int written = mSocket->write(np.serialize());
return (written != -1);
}
bool LanDeviceLink::sendPackage(NetworkPackage& np)
{
int written = mSocket->write(np.serialize());
return written != -1;
return (written != -1);
}
void LanDeviceLink::dataReceived()
@ -67,10 +74,24 @@ void LanDeviceLink::dataReceived()
if (package.length() < 3) continue;
NetworkPackage np("");
NetworkPackage np(QString::null);
NetworkPackage::unserialize(package, &np);
if (np.type() == PACKAGE_TYPE_ENCRYPTED) {
if (mPrivateKey.isNull()) {
//TODO: Emit the problem?
return;
}
NetworkPackage decrypted(QString::null);
np.decrypt(mPrivateKey, &decrypted);
Q_EMIT receivedPackage(decrypted);
} else {
Q_EMIT receivedPackage(np);
}
}
}

View file

@ -37,7 +37,8 @@ class LanDeviceLink
public:
LanDeviceLink(const QString& d, LinkProvider* a, QTcpSocket* socket);
bool sendPackage(const NetworkPackage& np);
bool sendPackage(NetworkPackage& np);
bool sendPackageEncrypted(QCA::PublicKey& key, NetworkPackage& np);
private Q_SLOTS:
void dataReceived();

View file

@ -28,7 +28,34 @@ LoopbackDeviceLink::LoopbackDeviceLink(const QString& deviceId, LoopbackLinkProv
}
bool LoopbackDeviceLink::sendPackage(const NetworkPackage& input)
bool LoopbackDeviceLink::sendPackageEncrypted(QCA::PublicKey& key, NetworkPackage& input)
{
if (mPrivateKey.isNull() || key.isNull()) {
return false;
}
input.encrypt(key);
QByteArray serialized = input.serialize();
NetworkPackage unserialized(QString::null);
NetworkPackage::unserialize(serialized, &unserialized);
NetworkPackage output(QString::null);
unserialized.decrypt(mPrivateKey, &output);
//LoopbackDeviceLink does not need deviceTransferInfo
if (input.hasPayload()) {
QIODevice* device = input.payload();
output.setPayload(device);
}
Q_EMIT receivedPackage(output);
return true;
}
bool LoopbackDeviceLink::sendPackage(NetworkPackage& input)
{
NetworkPackage output(QString::null);
NetworkPackage::unserialize(input.serialize(), &output);
@ -43,3 +70,4 @@ bool LoopbackDeviceLink::sendPackage(const NetworkPackage& input)
return true;
}

View file

@ -32,7 +32,8 @@ class LoopbackDeviceLink
public:
LoopbackDeviceLink(const QString& d, LoopbackLinkProvider* a);
bool sendPackage(const NetworkPackage& np);
virtual bool sendPackage(NetworkPackage& np);
virtual bool sendPackageEncrypted(QCA::PublicKey& publicKey, NetworkPackage& np);
};

View file

@ -202,6 +202,12 @@ void Device::addLink(DeviceLink* link)
m_deviceLinks.append(link);
//TODO: Do not read the key every time
KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc");
const QString& key = config->group("myself").readEntry<QString>("privateKey",QString());
QCA::PrivateKey privateKey = QCA::PrivateKey::fromPEM(key);
link->setPrivateKey(privateKey);
//Theoretically we will never add two links from the same provider (the provider should destroy
//the old one before this is called), so we do not have to worry about destroying old links.
//Actually, we should not destroy them or the provider will store an invalid ref!
@ -241,17 +247,22 @@ void Device::removeLink(DeviceLink* link)
bool Device::sendPackage(NetworkPackage& np)
{
if (np.type() != PACKAGE_TYPE_PAIR && isPaired()) {
np.encrypt(m_publicKey);
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
//TODO: Actually detect if a package is received or not, now we keep TCP
//"ESTABLISHED" connections that look legit (return true when we use them),
//but that are actually broken
if (dl->sendPackageEncrypted(m_publicKey, np)) return true;
}
} else {
//Maybe we could block here any package that is not an identity or a pairing package to prevent sending non encrypted data
}
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
//TODO: Actually detect if a package is received or not, now we keep TCP
//"ESTABLISHED" connections that look legit (return true when we use them),
//but that are actually broken
if (dl->sendPackage(np)) return true;
}
}
return false;
}
@ -346,35 +357,11 @@ void Device::privateReceivedPackage(const NetworkPackage& np)
} else {
if (np.type() == PACKAGE_TYPE_ENCRYPTED) {
//TODO: Do not read the key every time
KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc");
const QString& key = config->group("myself").readEntry<QString>("privateKey",QString());
QCA::PrivateKey privateKey = QCA::PrivateKey::fromPEM(key);
//Emit decrypted package
NetworkPackage decryptedNp("");
bool success = np.decrypt(privateKey, &decryptedNp);
if (!success) {
qDebug() << "Failed to decrypt package";
} else {
Q_EMIT receivedPackage(decryptedNp);
}
} else {
//TODO: The other side doesn't know that we are already paired, do something
qDebug() << "WARNING: Received unencrypted package from paired device!";
//Forward package
Q_EMIT receivedPackage(np);
}
}
}
void Device::acceptPairing()