swift
cryptodtoserializer.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2019 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #ifndef SWIFT_CORE_AFV_CRYPTO_CRYPTODTO_SERIALIZER_H
7 #define SWIFT_CORE_AFV_CRYPTO_CRYPTODTO_SERIALIZER_H
8 
9 #include <QBuffer>
10 #include <QByteArray>
11 #include <QtDebug>
12 
13 #include "sodium.h"
14 
18 
19 #ifndef crypto_aead_chacha20poly1305_IETF_ABYTES
21 # define crypto_aead_chacha20poly1305_IETF_ABYTES 16U
22 #endif
23 
24 namespace swift::core::afv::crypto
25 {
27  extern QHash<QByteArray, QByteArray> gShortDtoNames;
28 
31  {
32  public:
33  CryptoDtoSerializer() = default;
34 
36  template <typename T>
37  static QByteArray serialize(const QString &channelTag, CryptoDtoMode mode, const QByteArray &transmitKey,
38  uint sequenceToBeSent, T dto)
39  {
40  Q_ASSERT_X(transmitKey.size() == crypto_aead_chacha20poly1305_IETF_KEYBYTES, Q_FUNC_INFO, "");
41  const CryptoDtoHeaderDto header = { channelTag.toStdString(), sequenceToBeSent, mode };
42 
43  QBuffer headerBuffer;
44  headerBuffer.open(QIODevice::WriteOnly);
45  msgpack::pack(headerBuffer, header);
46  headerBuffer.close();
47  const auto headerLength = static_cast<quint16>(headerBuffer.buffer().size());
48 
49  const QByteArray dtoShortName = T::getShortDtoName();
50  const auto dtoNameLength = static_cast<quint16>(dtoShortName.size());
51 
52  QBuffer dtoBuffer;
53  dtoBuffer.open(QIODevice::WriteOnly);
54  msgpack::pack(dtoBuffer, dto);
55  dtoBuffer.close();
56  const auto dtoLength = static_cast<quint16>(dtoBuffer.buffer().size());
57 
58  if (header.Mode == CryptoDtoMode::AEAD_ChaCha20Poly1305)
59  {
60  QBuffer aePayloadBuffer;
61  aePayloadBuffer.open(QIODevice::WriteOnly);
62  aePayloadBuffer.write(reinterpret_cast<const char *>(&dtoNameLength), sizeof(dtoNameLength));
63  aePayloadBuffer.write(dtoShortName);
64  aePayloadBuffer.write(reinterpret_cast<const char *>(&dtoLength), sizeof(dtoLength));
65  aePayloadBuffer.write(dtoBuffer.buffer());
66  aePayloadBuffer.close();
67 
68  QBuffer adPayloadBuffer;
69  adPayloadBuffer.open(QIODevice::WriteOnly);
70  adPayloadBuffer.write(reinterpret_cast<const char *>(&headerLength), sizeof(headerLength));
71  adPayloadBuffer.write(headerBuffer.buffer());
72  adPayloadBuffer.close();
73 
74  QByteArray nonce;
75  nonce.fill(0, crypto_aead_chacha20poly1305_IETF_NPUBBYTES);
76  QBuffer nonceBuffer(&nonce);
77  nonceBuffer.open(QIODevice::WriteOnly);
78  uint32_t id = 0;
79  nonceBuffer.write(reinterpret_cast<const char *>(&id), sizeof(id));
80  nonceBuffer.write(reinterpret_cast<const char *>(&header.Sequence), sizeof(header.Sequence));
81  nonceBuffer.close();
82 
83  unsigned long long clen {};
84  QByteArray aeadPayload;
85  aeadPayload.fill(0,
86  static_cast<int>(aePayloadBuffer.size() + crypto_aead_chacha20poly1305_IETF_ABYTES));
87  int result = crypto_aead_chacha20poly1305_ietf_encrypt(
88  reinterpret_cast<unsigned char *>(aeadPayload.data()), &clen,
89  reinterpret_cast<const unsigned char *>(aePayloadBuffer.buffer().constData()),
90  aePayloadBuffer.size(),
91  reinterpret_cast<const unsigned char *>(adPayloadBuffer.buffer().constData()),
92  adPayloadBuffer.size(), nullptr, reinterpret_cast<const unsigned char *>(nonce.constData()),
93  reinterpret_cast<const unsigned char *>(transmitKey.constData()));
94  if (result != 0) { return {}; }
95 
96  QBuffer packetBuffer;
97  packetBuffer.open(QIODevice::WriteOnly);
98  packetBuffer.write(reinterpret_cast<const char *>(&headerLength), sizeof(headerLength));
99  packetBuffer.write(headerBuffer.buffer());
100  packetBuffer.write(aeadPayload);
101  packetBuffer.close();
102 
103  return packetBuffer.buffer();
104  }
105 
106  return {};
107  }
108 
110  template <typename T>
111  static QByteArray serialize(CCryptoDtoChannel &channel, CryptoDtoMode mode, T dto)
112  {
113  uint sequenceToSend = 0;
114  QByteArray transmitKey = channel.getTransmitKey(mode, sequenceToSend);
115  return serialize(channel.getChannelTag(), mode, transmitKey, sequenceToSend++, dto);
116  }
117 
120  {
122  Deserializer(CCryptoDtoChannel &channel, const QByteArray &bytes, bool loopback);
123 
125  template <typename T>
126  T getDto()
127  {
128  if (!m_verified) return {};
129  if (m_dtoNameBuffer == T::getDtoName() || m_dtoNameBuffer == T::getShortDtoName())
130  {
131  msgpack::object_handle oh2 =
132  msgpack::unpack(m_dataBuffer.data(), static_cast<std::size_t>(m_dataBuffer.size()));
133  msgpack::object obj = oh2.get();
134  T dto = obj.as<T>();
135  return dto;
136  }
137  return {};
138  }
139 
142  quint16 m_headerLength;
145 
149  QByteArray m_dtoNameBuffer;
151 
154  quint16 m_dataLength;
155  QByteArray m_dataBuffer;
157 
158  bool m_verified = false;
159  };
160 
162  static Deserializer deserialize(CCryptoDtoChannel &channel, const QByteArray &bytes, bool loopback);
163  };
164 } // namespace swift::core::afv::crypto
165 
166 #endif // SWIFT_CORE_AFV_CRYPTO_CRYPTODTO_SERIALIZER_H
QByteArray getTransmitKey(CryptoDtoMode mode)
Transmit key.
static QByteArray serialize(const QString &channelTag, CryptoDtoMode mode, const QByteArray &transmitKey, uint sequenceToBeSent, T dto)
Serialize a DTO.
static Deserializer deserialize(CCryptoDtoChannel &channel, const QByteArray &bytes, bool loopback)
Deserialize.
static QByteArray serialize(CCryptoDtoChannel &channel, CryptoDtoMode mode, T dto)
Serialize a DTO.
#define crypto_aead_chacha20poly1305_IETF_ABYTES
Number of a bytes.
Deserializer(CCryptoDtoChannel &channel, const QByteArray &bytes, bool loopback)
Ctor.