2
0

SymmetricKey.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*
  2. * Copyright (c)2013-2020 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2025-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. #ifndef ZT_SYMMETRICKEY_HPP
  14. #define ZT_SYMMETRICKEY_HPP
  15. #include "Constants.hpp"
  16. #include "Utils.hpp"
  17. #include "InetAddress.hpp"
  18. #include "AES.hpp"
  19. #include "SharedPtr.hpp"
  20. #include "Address.hpp"
  21. namespace ZeroTier {
  22. /**
  23. * Container for symmetric keys and ciphers initialized with them.
  24. */
  25. class SymmetricKey
  26. {
  27. friend class SharedPtr< SymmetricKey >;
  28. public:
  29. /**
  30. * Secret key
  31. */
  32. const uint8_t secret[ZT_SYMMETRIC_KEY_SIZE];
  33. /**
  34. * Symmetric cipher keyed with this key
  35. */
  36. const AES cipher;
  37. /**
  38. * Construct a new symmetric key
  39. *
  40. * SECURITY: we use a best effort method to construct the nonce's starting point so as
  41. * to avoid nonce duplication across invocations. The most significant bits are the
  42. * number of seconds since epoch but with the most significant bit masked to zero.
  43. * The least significant bits are random. Key life time is limited to 2^31 messages
  44. * per key as per the AES-GMAC-SIV spec, and this is a SIV mode anyway so nonce repetition
  45. * is non-catastrophic.
  46. *
  47. * The masking of the most significant bit is because we bisect the nonce space by
  48. * which direction the message is going. If the sender's ZeroTier address is
  49. * numerically greater than the receiver, this bit is flipped. This means that
  50. * two sides of a conversation that have created their key instances at the same
  51. * time are much less likely to duplicate nonces when sending pacekts from either
  52. * end.
  53. *
  54. * @param ts Current time
  55. * @param key 48-bit / 384-byte key
  56. */
  57. explicit ZT_INLINE SymmetricKey(const int64_t ts, const void *const key) noexcept:
  58. secret(),
  59. cipher(key), // AES-256 uses first 256 bits of 384-bit key
  60. m_initialNonce(((((uint64_t)ts / 1000ULL) << 32U) & 0x7fffffff00000000ULL) | (Utils::random() & 0x00000000ffffffffULL)),
  61. m_nonce(m_initialNonce),
  62. __refCount(0)
  63. {
  64. Utils::memoryLock(this, sizeof(SymmetricKey));
  65. Utils::copy< ZT_SYMMETRIC_KEY_SIZE >(const_cast<uint8_t *>(secret), key);
  66. }
  67. ZT_INLINE ~SymmetricKey() noexcept
  68. {
  69. Utils::burn(const_cast<uint8_t *>(secret), ZT_SYMMETRIC_KEY_SIZE);
  70. Utils::memoryUnlock(this, sizeof(SymmetricKey));
  71. }
  72. /**
  73. * Advance usage counter by one and return the next IV / packet ID.
  74. *
  75. * @param sender Sending ZeroTier address
  76. * @param receiver Receiving ZeroTier address
  77. * @return Next unique IV for next message
  78. */
  79. ZT_INLINE uint64_t nextMessage(const Address sender, const Address receiver) noexcept
  80. { return m_nonce.fetch_add(1) ^ (((uint64_t)(sender > receiver)) << 63U); }
  81. /**
  82. * @return Number of times nextMessage() has been called since object creation
  83. */
  84. ZT_INLINE uint64_t odometer() const noexcept
  85. { return m_nonce.load() - m_initialNonce; }
  86. private:
  87. const uint64_t m_initialNonce;
  88. std::atomic< uint64_t > m_nonce;
  89. std::atomic< int > __refCount;
  90. };
  91. } // namespace ZeroTier
  92. #endif