Revocation.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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_REVOCATION_HPP
  14. #define ZT_REVOCATION_HPP
  15. #include "../include/ZeroTierOne.h"
  16. #include "Address.hpp"
  17. #include "Buffer.hpp"
  18. #include "C25519.hpp"
  19. #include "Constants.hpp"
  20. #include "Credential.hpp"
  21. #include "Identity.hpp"
  22. #include "Utils.hpp"
  23. #include <stdint.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. /**
  28. * Flag: fast propagation via rumor mill algorithm
  29. */
  30. #define ZT_REVOCATION_FLAG_FAST_PROPAGATE 0x1ULL
  31. namespace ZeroTier {
  32. class RuntimeEnvironment;
  33. /**
  34. * Revocation certificate to instantaneously revoke a COM, capability, or tag
  35. */
  36. class Revocation : public Credential {
  37. public:
  38. static inline Credential::Type credentialType()
  39. {
  40. return Credential::CREDENTIAL_TYPE_REVOCATION;
  41. }
  42. Revocation() : _id(0), _credentialId(0), _networkId(0), _threshold(0), _flags(0), _target(), _signedBy(), _type(Credential::CREDENTIAL_TYPE_NULL)
  43. {
  44. memset(_signature.data, 0, sizeof(_signature.data));
  45. }
  46. /**
  47. * @param i ID (arbitrary for revocations, currently random)
  48. * @param nwid Network ID
  49. * @param cid Credential ID being revoked (0 for all or for COMs, which lack IDs)
  50. * @param thr Revocation time threshold before which credentials will be revoked
  51. * @param fl Flags
  52. * @param tgt Target node whose credential(s) are being revoked
  53. * @param ct Credential type being revoked
  54. */
  55. Revocation(const uint32_t i, const uint64_t nwid, const uint32_t cid, const int64_t thr, const uint64_t fl, const Address& tgt, const Credential::Type ct)
  56. : _id(i)
  57. , _credentialId(cid)
  58. , _networkId(nwid)
  59. , _threshold(thr)
  60. , _flags(fl)
  61. , _target(tgt)
  62. , _signedBy()
  63. , _type(ct)
  64. {
  65. memset(_signature.data, 0, sizeof(_signature.data));
  66. }
  67. inline uint32_t id() const
  68. {
  69. return _id;
  70. }
  71. inline uint32_t credentialId() const
  72. {
  73. return _credentialId;
  74. }
  75. inline uint64_t networkId() const
  76. {
  77. return _networkId;
  78. }
  79. inline int64_t threshold() const
  80. {
  81. return _threshold;
  82. }
  83. inline const Address& target() const
  84. {
  85. return _target;
  86. }
  87. inline const Address& signer() const
  88. {
  89. return _signedBy;
  90. }
  91. inline Credential::Type type() const
  92. {
  93. return _type;
  94. }
  95. inline bool fastPropagate() const
  96. {
  97. return ((_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0);
  98. }
  99. /**
  100. * @param signer Signing identity, must have private key
  101. * @return True if signature was successful
  102. */
  103. inline bool sign(const Identity& signer)
  104. {
  105. if (signer.hasPrivate()) {
  106. Buffer<sizeof(Revocation) + 64> tmp;
  107. _signedBy = signer.address();
  108. this->serialize(tmp, true);
  109. _signature = signer.sign(tmp.data(), tmp.size());
  110. return true;
  111. }
  112. return false;
  113. }
  114. /**
  115. * Verify this revocation's signature
  116. *
  117. * @param RR Runtime environment to provide for peer lookup, etc.
  118. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  119. * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or chain
  120. */
  121. int verify(const RuntimeEnvironment* RR, void* tPtr) const;
  122. template <unsigned int C> inline void serialize(Buffer<C>& b, const bool forSign = false) const
  123. {
  124. if (forSign) {
  125. b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
  126. }
  127. b.append((uint32_t)0); // 4 unused bytes, currently set to 0
  128. b.append(_id);
  129. b.append(_networkId);
  130. b.append((uint32_t)0); // 4 unused bytes, currently set to 0
  131. b.append(_credentialId);
  132. b.append(_threshold);
  133. b.append(_flags);
  134. _target.appendTo(b);
  135. _signedBy.appendTo(b);
  136. b.append((uint8_t)_type);
  137. if (! forSign) {
  138. b.append((uint8_t)1); // 1 == Ed25519 signature
  139. b.append((uint16_t)ZT_C25519_SIGNATURE_LEN);
  140. b.append(_signature.data, ZT_C25519_SIGNATURE_LEN);
  141. }
  142. // This is the size of any additional fields, currently 0.
  143. b.append((uint16_t)0);
  144. if (forSign) {
  145. b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
  146. }
  147. }
  148. template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
  149. {
  150. *this = Revocation();
  151. unsigned int p = startAt;
  152. p += 4; // 4 bytes, currently unused
  153. _id = b.template at<uint32_t>(p);
  154. p += 4;
  155. _networkId = b.template at<uint64_t>(p);
  156. p += 8;
  157. p += 4; // 4 bytes, currently unused
  158. _credentialId = b.template at<uint32_t>(p);
  159. p += 4;
  160. _threshold = (int64_t)b.template at<uint64_t>(p);
  161. p += 8;
  162. _flags = b.template at<uint64_t>(p);
  163. p += 8;
  164. _target.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
  165. p += ZT_ADDRESS_LENGTH;
  166. _signedBy.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
  167. p += ZT_ADDRESS_LENGTH;
  168. _type = (Credential::Type)b[p++];
  169. if (b[p++] == 1) {
  170. if (b.template at<uint16_t>(p) == ZT_C25519_SIGNATURE_LEN) {
  171. p += 2;
  172. memcpy(_signature.data, b.field(p, ZT_C25519_SIGNATURE_LEN), ZT_C25519_SIGNATURE_LEN);
  173. p += ZT_C25519_SIGNATURE_LEN;
  174. }
  175. else {
  176. throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
  177. }
  178. }
  179. else {
  180. p += 2 + b.template at<uint16_t>(p);
  181. }
  182. p += 2 + b.template at<uint16_t>(p);
  183. if (p > b.size()) {
  184. throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
  185. }
  186. return (p - startAt);
  187. }
  188. private:
  189. uint32_t _id;
  190. uint32_t _credentialId;
  191. uint64_t _networkId;
  192. int64_t _threshold;
  193. uint64_t _flags;
  194. Address _target;
  195. Address _signedBy;
  196. Credential::Type _type;
  197. C25519::Signature _signature;
  198. };
  199. } // namespace ZeroTier
  200. #endif