CertificateOfMembership.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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::sign(const Identity &with)
  48. {
  49. uint64_t buf[ZT_NETWORK_COM_MAX_QUALIFIERS * 3];
  50. unsigned int ptr = 0;
  51. for(unsigned int i=0;i<_qualifierCount;++i) {
  52. buf[ptr++] = Utils::hton(_qualifiers[i].id);
  53. buf[ptr++] = Utils::hton(_qualifiers[i].value);
  54. buf[ptr++] = Utils::hton(_qualifiers[i].maxDelta);
  55. }
  56. try {
  57. _signatureLength = with.sign(buf,ptr * sizeof(uint64_t),_signature,sizeof(_signature));
  58. _signedBy = with.address();
  59. return true;
  60. } catch ( ... ) {
  61. _signedBy.zero();
  62. return false;
  63. }
  64. }
  65. int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX]) const
  66. {
  67. data[0] = 1;
  68. Utils::storeBigEndian<uint16_t>(data + 1,(uint16_t)_qualifierCount);
  69. int p = 3;
  70. for(unsigned int i=0;i<_qualifierCount;++i) {
  71. Utils::storeBigEndian<uint64_t>(data + p,_qualifiers[i].id); p += 8;
  72. Utils::storeBigEndian<uint64_t>(data + p,_qualifiers[i].value); p += 8;
  73. Utils::storeBigEndian<uint64_t>(data + p,_qualifiers[i].maxDelta); p += 8;
  74. }
  75. _signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH;
  76. if ((_signedBy)&&(_signatureLength == 96)) {
  77. // UGLY: Ed25519 signatures in ZT are 96 bytes (64 + 32 bytes of hash).
  78. // P-384 signatures are also 96 bytes, praise the horned one. That means
  79. // we don't need to include a length. If we ever do we will need a new
  80. // serialized object version, but only for those with length != 96.
  81. memcpy(data + p,_signature,96); p += 96;
  82. }
  83. return p;
  84. }
  85. int CertificateOfMembership::unmarshal(const uint8_t *data,int len)
  86. {
  87. if ((len < 3)||(data[0] != 1))
  88. return -1;
  89. unsigned int numq = Utils::loadBigEndian<uint16_t>(data + 1);
  90. if (numq > ZT_NETWORK_COM_MAX_QUALIFIERS)
  91. return -1;
  92. _qualifierCount = numq;
  93. int p = 3;
  94. for(unsigned int i=0;i<numq;++i) {
  95. if ((p + 24) > len)
  96. return -1;
  97. _qualifiers[i].id = Utils::loadBigEndian<uint64_t>(data + p); p += 8;
  98. _qualifiers[i].value = Utils::loadBigEndian<uint64_t>(data + p); p += 8;
  99. _qualifiers[i].maxDelta = Utils::loadBigEndian<uint64_t>(data + p); p += 8;
  100. }
  101. if ((p + ZT_ADDRESS_LENGTH) > len)
  102. return -1;
  103. _signedBy.setTo(data + p); p += ZT_ADDRESS_LENGTH;
  104. if (_signedBy) {
  105. if ((p + 96) > len)
  106. return -1;
  107. _signatureLength = 96;
  108. memcpy(_signature,data + p,96);
  109. p += 96;
  110. }
  111. return p;
  112. }
  113. bool CertificateOfMembership::operator==(const CertificateOfMembership &c) const
  114. {
  115. if (_signedBy != c._signedBy)
  116. return false;
  117. if (_qualifierCount != c._qualifierCount)
  118. return false;
  119. if (_signatureLength != c._signatureLength)
  120. return false;
  121. for(unsigned int i=0;i<_qualifierCount;++i) {
  122. const _Qualifier &a = _qualifiers[i];
  123. const _Qualifier &b = c._qualifiers[i];
  124. if ((a.id != b.id)||(a.value != b.value)||(a.maxDelta != b.maxDelta))
  125. return false;
  126. }
  127. return (memcmp(_signature,c._signature,_signatureLength) == 0);
  128. }
  129. } // namespace ZeroTier