Revocation.hpp 5.4 KB

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