Files
pilotclient/src/blackcore/afv/crypto/cryptodtoserializer.h
Klaus Basan 384aa3ce19 Ref T730, namespace for BlackCore::Afv
* added namespace
* removed some *.pri files and added files to blackcore.pro
* added copyright etc.
2019-10-11 18:59:02 +01:00

153 lines
6.7 KiB
C++

/* Copyright (C) 2019
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
//! \file
#ifndef BLACKCORE_AFV_CRYPTO_CRYPTODTO_SERIALIZER_H
#define BLACKCORE_AFV_CRYPTO_CRYPTODTO_SERIALIZER_H
#include "cryptodtochannel.h"
#include "cryptodtomode.h"
#include "cryptodtoheaderdto.h"
#include "sodium.h"
#include <QByteArray>
#include <QBuffer>
#include <QtDebug>
namespace BlackCore
{
namespace Afv
{
namespace Crypto
{
extern QHash<QByteArray, QByteArray> gShortDtoNames;
//! Crypto serializer
class CryptoDtoSerializer
{
public:
CryptoDtoSerializer();
template<typename T>
static QByteArray Serialize(const QString &channelTag, CryptoDtoMode mode, const QByteArray &transmitKey, uint sequenceToBeSent, T dto)
{
const CryptoDtoHeaderDto header = { channelTag.toStdString(), sequenceToBeSent, mode };
QBuffer headerBuffer;
headerBuffer.open(QIODevice::WriteOnly);
msgpack::pack(headerBuffer, header);
headerBuffer.close();
const quint16 headerLength = static_cast<quint16>(headerBuffer.buffer().size());
const QByteArray dtoNameBuffer = T::getDtoName();
const QByteArray dtoShortName = T::getShortDtoName();
const quint16 dtoNameLength = static_cast<quint16>(dtoShortName.size());
QBuffer dtoBuffer;
dtoBuffer.open(QIODevice::WriteOnly);
msgpack::pack(dtoBuffer, dto);
dtoBuffer.close();
const quint16 dtoLength = static_cast<quint16>(dtoBuffer.buffer().size());
if (header.Mode == CryptoDtoMode::AEAD_ChaCha20Poly1305)
{
QBuffer aePayloadBuffer;
aePayloadBuffer.open(QIODevice::WriteOnly);
aePayloadBuffer.write(reinterpret_cast<const char *>(&dtoNameLength), sizeof(dtoNameLength));
aePayloadBuffer.write(dtoShortName);
aePayloadBuffer.write(reinterpret_cast<const char *>(&dtoLength), sizeof(dtoLength));
aePayloadBuffer.write(dtoBuffer.buffer());
aePayloadBuffer.close();
QBuffer adPayloadBuffer;
adPayloadBuffer.open(QIODevice::WriteOnly);
adPayloadBuffer.write(reinterpret_cast<const char *>(&headerLength), sizeof(headerLength));
adPayloadBuffer.write(headerBuffer.buffer());
adPayloadBuffer.close();
QByteArray nonce;
nonce.fill(0, crypto_aead_chacha20poly1305_IETF_NPUBBYTES);
QBuffer nonceBuffer(&nonce);
nonceBuffer.open(QIODevice::WriteOnly);
uint32_t id = 0;
nonceBuffer.write(reinterpret_cast<const char *>(&id), sizeof(id));
nonceBuffer.write(reinterpret_cast<const char *>(&header.Sequence), sizeof(header.Sequence));
nonceBuffer.close();
unsigned long long clen;
QByteArray aeadPayload;
aeadPayload.fill(0, static_cast<int>(aePayloadBuffer.size() + crypto_aead_chacha20poly1305_IETF_ABYTES));
int result = crypto_aead_chacha20poly1305_ietf_encrypt(reinterpret_cast<unsigned char *>(aeadPayload.data()),
&clen,
reinterpret_cast<const unsigned char *>(aePayloadBuffer.buffer().constData()), aePayloadBuffer.size(),
reinterpret_cast<const unsigned char *>(adPayloadBuffer.buffer().constData()), adPayloadBuffer.size(),
nullptr,
reinterpret_cast<const unsigned char *>(nonce.constData()),
reinterpret_cast<const unsigned char *>(transmitKey.constData()));
if (result != 0) { return {}; }
QBuffer packetBuffer;
packetBuffer.open(QIODevice::WriteOnly);
packetBuffer.write(reinterpret_cast<const char *>(&headerLength), sizeof(headerLength));
packetBuffer.write(headerBuffer.buffer());
packetBuffer.write(aeadPayload);
packetBuffer.close();
return packetBuffer.buffer();
}
return {};
}
template<typename T>
static QByteArray Serialize(CryptoDtoChannel &channel, CryptoDtoMode mode, T dto)
{
uint sequenceToSend = 0;
QByteArray transmitKey = channel.getTransmitKey(mode, sequenceToSend);
return Serialize(channel.getChannelTag(), mode, transmitKey, sequenceToSend++, dto);
}
struct Deserializer
{
Deserializer(CryptoDtoChannel &channel, const QByteArray &bytes, bool loopback);
template<typename T>
T getDto()
{
if (! verified) return {};
if (dtoNameBuffer == T::getDtoName() || dtoNameBuffer == T::getShortDtoName())
{
msgpack::object_handle oh2 = msgpack::unpack(dataBuffer.data(), dataBuffer.size());
msgpack::object obj = oh2.get();
T dto = obj.as<T>();
return dto;
}
return {};
}
quint16 headerLength;
CryptoDtoHeaderDto header;
quint16 dtoNameLength;
QByteArray dtoNameBuffer;
quint16 dataLength;
QByteArray dataBuffer;
bool verified = false;
};
static Deserializer deserialize(CryptoDtoChannel &channel, const QByteArray &bytes, bool loopback);
};
} // ns
} // ns
} // ns
#endif // guard