Revocation.hpp 5.6 KB

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