CertificateOfOwnership.hpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /*
  2. * Copyright (c)2019 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: 2026-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_CERTIFICATEOFOWNERSHIP_HPP
  14. #define ZT_CERTIFICATEOFOWNERSHIP_HPP
  15. #include "Address.hpp"
  16. #include "Buffer.hpp"
  17. #include "Constants.hpp"
  18. #include "Credential.hpp"
  19. #include "ECC.hpp"
  20. #include "Identity.hpp"
  21. #include "InetAddress.hpp"
  22. #include "MAC.hpp"
  23. #include <stdint.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. // Max things per CertificateOfOwnership
  28. #define ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS 16
  29. // Maximum size of a thing's value field in bytes
  30. #define ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE 16
  31. namespace ZeroTier {
  32. class RuntimeEnvironment;
  33. /**
  34. * Certificate indicating ownership of a network identifier
  35. */
  36. class CertificateOfOwnership : public Credential {
  37. public:
  38. static inline Credential::Type credentialType()
  39. {
  40. return Credential::CREDENTIAL_TYPE_COO;
  41. }
  42. enum Thing { THING_NULL = 0, THING_MAC_ADDRESS = 1, THING_IPV4_ADDRESS = 2, THING_IPV6_ADDRESS = 3 };
  43. CertificateOfOwnership()
  44. {
  45. memset(reinterpret_cast<void*>(this), 0, sizeof(CertificateOfOwnership));
  46. }
  47. CertificateOfOwnership(const uint64_t nwid, const int64_t ts, const Address& issuedTo, const uint32_t id)
  48. {
  49. memset(reinterpret_cast<void*>(this), 0, sizeof(CertificateOfOwnership));
  50. _networkId = nwid;
  51. _ts = ts;
  52. _id = id;
  53. _issuedTo = issuedTo;
  54. }
  55. inline uint64_t networkId() const
  56. {
  57. return _networkId;
  58. }
  59. inline int64_t timestamp() const
  60. {
  61. return _ts;
  62. }
  63. inline uint32_t id() const
  64. {
  65. return _id;
  66. }
  67. inline unsigned int thingCount() const
  68. {
  69. return (unsigned int)_thingCount;
  70. }
  71. inline Thing thingType(const unsigned int i) const
  72. {
  73. return (Thing)_thingTypes[i];
  74. }
  75. inline const uint8_t* thingValue(const unsigned int i) const
  76. {
  77. return _thingValues[i];
  78. }
  79. inline const Address& issuedTo() const
  80. {
  81. return _issuedTo;
  82. }
  83. inline bool owns(const InetAddress& ip) const
  84. {
  85. if (ip.ss_family == AF_INET) {
  86. return this->_owns(THING_IPV4_ADDRESS, &(reinterpret_cast<const struct sockaddr_in*>(&ip)->sin_addr.s_addr), 4);
  87. }
  88. if (ip.ss_family == AF_INET6) {
  89. return this->_owns(THING_IPV6_ADDRESS, reinterpret_cast<const struct sockaddr_in6*>(&ip)->sin6_addr.s6_addr, 16);
  90. }
  91. return false;
  92. }
  93. inline bool owns(const MAC& mac) const
  94. {
  95. uint8_t tmp[6];
  96. mac.copyTo(tmp, 6);
  97. return this->_owns(THING_MAC_ADDRESS, tmp, 6);
  98. }
  99. inline void addThing(const InetAddress& ip)
  100. {
  101. if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) {
  102. return;
  103. }
  104. if (ip.ss_family == AF_INET) {
  105. _thingTypes[_thingCount] = THING_IPV4_ADDRESS;
  106. memcpy(_thingValues[_thingCount], &(reinterpret_cast<const struct sockaddr_in*>(&ip)->sin_addr.s_addr), 4);
  107. ++_thingCount;
  108. }
  109. else if (ip.ss_family == AF_INET6) {
  110. _thingTypes[_thingCount] = THING_IPV6_ADDRESS;
  111. memcpy(_thingValues[_thingCount], reinterpret_cast<const struct sockaddr_in6*>(&ip)->sin6_addr.s6_addr, 16);
  112. ++_thingCount;
  113. }
  114. }
  115. inline void addThing(const MAC& mac)
  116. {
  117. if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) {
  118. return;
  119. }
  120. _thingTypes[_thingCount] = THING_MAC_ADDRESS;
  121. mac.copyTo(_thingValues[_thingCount], 6);
  122. ++_thingCount;
  123. }
  124. /**
  125. * @param signer Signing identity, must have private key
  126. * @return True if signature was successful
  127. */
  128. inline bool sign(const Identity& signer)
  129. {
  130. if (signer.hasPrivate()) {
  131. Buffer<sizeof(CertificateOfOwnership) + 64> tmp;
  132. _signedBy = signer.address();
  133. this->serialize(tmp, true);
  134. _signature = signer.sign(tmp.data(), tmp.size());
  135. return true;
  136. }
  137. return false;
  138. }
  139. /**
  140. * @param RR Runtime environment to allow identity lookup for signedBy
  141. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  142. * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature
  143. */
  144. int verify(const RuntimeEnvironment* RR, void* tPtr) const;
  145. template <unsigned int C> inline void serialize(Buffer<C>& b, const bool forSign = false) const
  146. {
  147. if (forSign) {
  148. b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
  149. }
  150. b.append(_networkId);
  151. b.append(_ts);
  152. b.append(_flags);
  153. b.append(_id);
  154. b.append((uint16_t)_thingCount);
  155. for (unsigned int i = 0, j = _thingCount; i < j; ++i) {
  156. b.append((uint8_t)_thingTypes[i]);
  157. b.append(_thingValues[i], ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE);
  158. }
  159. _issuedTo.appendTo(b);
  160. _signedBy.appendTo(b);
  161. if (! forSign) {
  162. b.append((uint8_t)1); // 1 == Ed25519
  163. b.append((uint16_t)ZT_ECC_SIGNATURE_LEN); // length of signature
  164. b.append(_signature.data, ZT_ECC_SIGNATURE_LEN);
  165. }
  166. b.append((uint16_t)0); // length of additional fields, currently 0
  167. if (forSign) {
  168. b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
  169. }
  170. }
  171. template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
  172. {
  173. unsigned int p = startAt;
  174. *this = CertificateOfOwnership();
  175. _networkId = b.template at<uint64_t>(p);
  176. p += 8;
  177. _ts = b.template at<uint64_t>(p);
  178. p += 8;
  179. _flags = b.template at<uint64_t>(p);
  180. p += 8;
  181. _id = b.template at<uint32_t>(p);
  182. p += 4;
  183. _thingCount = b.template at<uint16_t>(p);
  184. p += 2;
  185. for (unsigned int i = 0, j = _thingCount; i < j; ++i) {
  186. if (i < ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) {
  187. _thingTypes[i] = (uint8_t)b[p++];
  188. memcpy(_thingValues[i], b.field(p, ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE), ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE);
  189. p += ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE;
  190. }
  191. }
  192. _issuedTo.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
  193. p += ZT_ADDRESS_LENGTH;
  194. _signedBy.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
  195. p += ZT_ADDRESS_LENGTH;
  196. if (b[p++] == 1) {
  197. if (b.template at<uint16_t>(p) != ZT_ECC_SIGNATURE_LEN) {
  198. throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
  199. }
  200. p += 2;
  201. memcpy(_signature.data, b.field(p, ZT_ECC_SIGNATURE_LEN), ZT_ECC_SIGNATURE_LEN);
  202. p += ZT_ECC_SIGNATURE_LEN;
  203. }
  204. else {
  205. p += 2 + b.template at<uint16_t>(p);
  206. }
  207. p += 2 + b.template at<uint16_t>(p);
  208. if (p > b.size()) {
  209. throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
  210. }
  211. return (p - startAt);
  212. }
  213. // Provides natural sort order by ID
  214. inline bool operator<(const CertificateOfOwnership& coo) const
  215. {
  216. return (_id < coo._id);
  217. }
  218. inline bool operator==(const CertificateOfOwnership& coo) const
  219. {
  220. return (memcmp(this, &coo, sizeof(CertificateOfOwnership)) == 0);
  221. }
  222. inline bool operator!=(const CertificateOfOwnership& coo) const
  223. {
  224. return (memcmp(this, &coo, sizeof(CertificateOfOwnership)) != 0);
  225. }
  226. private:
  227. bool _owns(const Thing& t, const void* v, unsigned int l) const;
  228. uint64_t _networkId;
  229. int64_t _ts;
  230. uint64_t _flags;
  231. uint32_t _id;
  232. uint16_t _thingCount;
  233. uint8_t _thingTypes[ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS];
  234. uint8_t _thingValues[ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS][ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE];
  235. Address _issuedTo;
  236. Address _signedBy;
  237. ECC::Signature _signature;
  238. };
  239. } // namespace ZeroTier
  240. #endif