swift
cryptodtochannel.cpp
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 #include <algorithm>
7 
8 #include "sodium/crypto_aead_chacha20poly1305.h"
9 
10 #include "misc/verify.h"
11 
12 using namespace swift::misc;
13 
14 namespace swift::core::afv::crypto
15 {
16  CCryptoDtoChannel::CCryptoDtoChannel(const CryptoDtoChannelConfigDto &channelConfig, int receiveSequenceHistorySize)
17  : m_aeadTransmitKey(channelConfig.aeadTransmitKey), m_aeadReceiveKey(channelConfig.aeadReceiveKey),
18  m_receiveSequenceSizeMaxSize(receiveSequenceHistorySize), m_hmacKey(channelConfig.hmacKey),
19  m_channelTag(channelConfig.channelTag)
20  {
21  if (m_aeadTransmitKey.size() != crypto_aead_chacha20poly1305_IETF_KEYBYTES)
22  {
23  SWIFT_AUDIT_X(false, Q_FUNC_INFO, "wrong transmit key size");
24  throw std::invalid_argument("wrong transmit key size");
25  }
26 
27  if (m_aeadReceiveKey.size() != crypto_aead_chacha20poly1305_IETF_KEYBYTES)
28  {
29  SWIFT_AUDIT_X(false, Q_FUNC_INFO, "wrong receive key size");
30  throw std::invalid_argument("wrong receive key size");
31  }
32 
33  m_receiveSequenceSizeMaxSize = std::max(m_receiveSequenceSizeMaxSize, 1);
34  m_receiveSequenceHistory.fill(0, m_receiveSequenceSizeMaxSize);
35  m_receiveSequenceHistoryDepth = 0;
36  }
37 
39  {
40  switch (mode)
41  {
42  case CryptoDtoMode::AEAD_ChaCha20Poly1305: return m_aeadTransmitKey;
43  case CryptoDtoMode::Undefined:
44  case CryptoDtoMode::None:
45  SWIFT_VERIFY_X(false, Q_FUNC_INFO, "GetTransmitKey called with wrong argument.");
46  break;
47  }
48 
49  return {};
50  }
51 
52  QByteArray CCryptoDtoChannel::getTransmitKey(CryptoDtoMode mode, uint &sequenceToSend)
53  {
54  sequenceToSend = m_transmitSequence;
55  m_transmitSequence++;
56  m_LastTransmitUtc = QDateTime::currentDateTimeUtc();
57 
58  switch (mode)
59  {
60  case CryptoDtoMode::AEAD_ChaCha20Poly1305: return m_aeadTransmitKey;
61  case CryptoDtoMode::Undefined:
62  case CryptoDtoMode::None:
63  SWIFT_VERIFY_X(false, Q_FUNC_INFO, "GetTransmitKey called with wrong argument.");
64  break;
65  }
66 
67  return {};
68  }
69 
70  QString CCryptoDtoChannel::getChannelTag() const { return m_channelTag; }
71 
73  {
74  switch (mode)
75  {
76  case CryptoDtoMode::AEAD_ChaCha20Poly1305: return m_aeadReceiveKey;
77  case CryptoDtoMode::Undefined:
78  case CryptoDtoMode::None:
79  SWIFT_VERIFY_X(false, Q_FUNC_INFO, "GetReceiveKey called with wrong argument.");
80  break;
81  }
82 
83  return {};
84  }
85 
86  bool CCryptoDtoChannel::checkReceivedSequence(uint sequenceReceived)
87  {
88  if (contains(sequenceReceived))
89  {
90  // Duplication or replay attack
91  return false;
92  }
93 
94  if (m_receiveSequenceHistoryDepth < m_receiveSequenceSizeMaxSize) // If the buffer has been filled...
95  {
96  m_receiveSequenceHistory[m_receiveSequenceHistoryDepth++] = sequenceReceived;
97  }
98  else
99  {
100  int minIndex {};
101  uint minValue = getMin(minIndex);
102  if (sequenceReceived < minValue) { return false; } // Possible replay attack
103  m_receiveSequenceHistory[minIndex] = sequenceReceived;
104  }
105 
106  m_lastReceiveUtc = QDateTime::currentDateTimeUtc();
107  return true;
108  }
109 
110  bool CCryptoDtoChannel::contains(uint sequence) const
111  {
112  for (int i = 0; i < m_receiveSequenceHistoryDepth; i++)
113  {
114  if (m_receiveSequenceHistory[i] == sequence) { return true; }
115  }
116  return false;
117  }
118 
119  uint CCryptoDtoChannel::getMin(int &minIndex) const
120  {
121  uint minValue = std::numeric_limits<uint>::max();
122  minIndex = -1;
123  int index = -1;
124 
125  for (int i = 0; i < m_receiveSequenceHistoryDepth; i++)
126  {
127  index++;
128  if (m_receiveSequenceHistory[i] <= minValue)
129  {
130  minValue = m_receiveSequenceHistory[i];
131  minIndex = index;
132  }
133  }
134  return minValue;
135  }
136 } // namespace swift::core::afv::crypto
QByteArray getReceiveKey(CryptoDtoMode mode)
Receiver key.
bool checkReceivedSequence(uint sequenceReceived)
check the received sequence
QByteArray getTransmitKey(CryptoDtoMode mode)
Transmit key.
Free functions in swift::misc.
#define SWIFT_AUDIT_X(COND, WHERE, WHAT)
A weaker kind of verify.
Definition: verify.h:38
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.
Definition: verify.h:26