CertificateOfMembership.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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: 2024-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. #include "CertificateOfMembership.hpp"
  14. namespace ZeroTier {
  15. CertificateOfMembership::CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo)
  16. {
  17. _qualifiers[0].id = COM_RESERVED_ID_TIMESTAMP;
  18. _qualifiers[0].value = timestamp;
  19. _qualifiers[0].maxDelta = timestampMaxDelta;
  20. _qualifiers[1].id = COM_RESERVED_ID_NETWORK_ID;
  21. _qualifiers[1].value = nwid;
  22. _qualifiers[1].maxDelta = 0;
  23. _qualifiers[2].id = COM_RESERVED_ID_ISSUED_TO;
  24. _qualifiers[2].value = issuedTo.toInt();
  25. _qualifiers[2].maxDelta = 0xffffffffffffffffULL;
  26. _qualifierCount = 3;
  27. _signatureLength = 0;
  28. }
  29. void CertificateOfMembership::setQualifier(uint64_t id,uint64_t value,uint64_t maxDelta)
  30. {
  31. _signedBy.zero();
  32. for(unsigned int i=0;i<_qualifierCount;++i) {
  33. if (_qualifiers[i].id == id) {
  34. _qualifiers[i].value = value;
  35. _qualifiers[i].maxDelta = maxDelta;
  36. return;
  37. }
  38. }
  39. if (_qualifierCount < ZT_NETWORK_COM_MAX_QUALIFIERS) {
  40. _qualifiers[_qualifierCount].id = id;
  41. _qualifiers[_qualifierCount].value = value;
  42. _qualifiers[_qualifierCount].maxDelta = maxDelta;
  43. ++_qualifierCount;
  44. std::sort(&(_qualifiers[0]),&(_qualifiers[_qualifierCount]));
  45. }
  46. }
  47. bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) const
  48. {
  49. unsigned int myidx = 0;
  50. unsigned int otheridx = 0;
  51. if ((_qualifierCount == 0)||(other._qualifierCount == 0))
  52. return false;
  53. while (myidx < _qualifierCount) {
  54. // Fail if we're at the end of other, since this means the field is
  55. // missing.
  56. if (otheridx >= other._qualifierCount)
  57. return false;
  58. // Seek to corresponding tuple in other, ignoring tuples that
  59. // we may not have. If we run off the end of other, the tuple is
  60. // missing. This works because tuples are sorted by ID.
  61. while (other._qualifiers[otheridx].id != _qualifiers[myidx].id) {
  62. ++otheridx;
  63. if (otheridx >= other._qualifierCount)
  64. return false;
  65. }
  66. // Compare to determine if the absolute value of the difference
  67. // between these two parameters is within our maxDelta.
  68. const uint64_t a = _qualifiers[myidx].value;
  69. const uint64_t b = other._qualifiers[myidx].value;
  70. if (((a >= b) ? (a - b) : (b - a)) > _qualifiers[myidx].maxDelta)
  71. return false;
  72. ++myidx;
  73. }
  74. return true;
  75. }
  76. bool CertificateOfMembership::sign(const Identity &with)
  77. {
  78. uint64_t buf[ZT_NETWORK_COM_MAX_QUALIFIERS * 3];
  79. unsigned int ptr = 0;
  80. for(unsigned int i=0;i<_qualifierCount;++i) {
  81. buf[ptr++] = Utils::hton(_qualifiers[i].id);
  82. buf[ptr++] = Utils::hton(_qualifiers[i].value);
  83. buf[ptr++] = Utils::hton(_qualifiers[i].maxDelta);
  84. }
  85. try {
  86. _signatureLength = with.sign(buf,ptr * sizeof(uint64_t),_signature,sizeof(_signature));
  87. _signedBy = with.address();
  88. return true;
  89. } catch ( ... ) {
  90. _signedBy.zero();
  91. return false;
  92. }
  93. }
  94. int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX]) const noexcept
  95. {
  96. data[0] = 1;
  97. Utils::storeBigEndian<uint16_t>(data + 1,(uint16_t)_qualifierCount);
  98. int p = 3;
  99. for(unsigned int i=0;i<_qualifierCount;++i) {
  100. Utils::storeBigEndian<uint64_t>(data + p,_qualifiers[i].id); p += 8;
  101. Utils::storeBigEndian<uint64_t>(data + p,_qualifiers[i].value); p += 8;
  102. Utils::storeBigEndian<uint64_t>(data + p,_qualifiers[i].maxDelta); p += 8;
  103. }
  104. _signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH;
  105. if ((_signedBy)&&(_signatureLength == 96)) {
  106. // UGLY: Ed25519 signatures in ZT are 96 bytes (64 + 32 bytes of hash).
  107. // P-384 signatures are also 96 bytes, praise the horned one. That means
  108. // we don't need to include a length. If we ever do we will need a new
  109. // serialized object version, but only for those with length != 96.
  110. memcpy(data + p,_signature,96); p += 96;
  111. }
  112. return p;
  113. }
  114. int CertificateOfMembership::unmarshal(const uint8_t *data,int len) noexcept
  115. {
  116. if ((len < 3)||(data[0] != 1))
  117. return -1;
  118. unsigned int numq = Utils::loadBigEndian<uint16_t>(data + 1);
  119. if (numq > ZT_NETWORK_COM_MAX_QUALIFIERS)
  120. return -1;
  121. _qualifierCount = numq;
  122. int p = 3;
  123. for(unsigned int i=0;i<numq;++i) {
  124. if ((p + 24) > len)
  125. return -1;
  126. _qualifiers[i].id = Utils::loadBigEndian<uint64_t>(data + p); p += 8;
  127. _qualifiers[i].value = Utils::loadBigEndian<uint64_t>(data + p); p += 8;
  128. _qualifiers[i].maxDelta = Utils::loadBigEndian<uint64_t>(data + p); p += 8;
  129. }
  130. if ((p + ZT_ADDRESS_LENGTH) > len)
  131. return -1;
  132. _signedBy.setTo(data + p); p += ZT_ADDRESS_LENGTH;
  133. if (_signedBy) {
  134. if ((p + 96) > len)
  135. return -1;
  136. _signatureLength = 96;
  137. memcpy(_signature,data + p,96);
  138. p += 96;
  139. }
  140. return p;
  141. }
  142. bool CertificateOfMembership::operator==(const CertificateOfMembership &c) const
  143. {
  144. if (_signedBy != c._signedBy)
  145. return false;
  146. if (_qualifierCount != c._qualifierCount)
  147. return false;
  148. if (_signatureLength != c._signatureLength)
  149. return false;
  150. for(unsigned int i=0;i<_qualifierCount;++i) {
  151. const _Qualifier &a = _qualifiers[i];
  152. const _Qualifier &b = c._qualifiers[i];
  153. if ((a.id != b.id)||(a.value != b.value)||(a.maxDelta != b.maxDelta))
  154. return false;
  155. }
  156. return (memcmp(_signature,c._signature,_signatureLength) == 0);
  157. }
  158. } // namespace ZeroTier