IdentificationCertificate.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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 "IdentificationCertificate.hpp"
  14. #include "SHA512.hpp"
  15. namespace ZeroTier {
  16. void IdentificationCertificate::clear()
  17. {
  18. Utils::zero< sizeof(ZT_IdentificationCertificate) >((ZT_IdentificationCertificate *)this);
  19. m_identities.clear();
  20. m_locators.clear();
  21. m_strings.clear();
  22. m_nodes.clear();
  23. m_networks.clear();
  24. m_updateUrls.clear();
  25. }
  26. IdentificationCertificate &IdentificationCertificate::operator=(const ZT_IdentificationCertificate &apiCert)
  27. {
  28. clear();
  29. Utils::copy< sizeof(ZT_IdentificationCertificate) >((ZT_IdentificationCertificate *)this, &apiCert);
  30. return *this;
  31. }
  32. IdentificationCertificate &IdentificationCertificate::operator=(const IdentificationCertificate &cert)
  33. {
  34. *this = *((const ZT_IdentificationCertificate *)(&cert));
  35. this->subject.nodeCount = 0;
  36. this->subject.networkCount = 0;
  37. if (cert.issuer) {
  38. m_identities.push_back(*reinterpret_cast<const Identity *>(cert.issuer));
  39. this->issuer = reinterpret_cast<ZT_Identity *>(&(m_identities.back()));
  40. }
  41. for (unsigned int i = 0; i < cert.subject.nodeCount; ++i) {
  42. if (cert.subject.nodes[i].locator)
  43. addSubjectNode(*reinterpret_cast<const Identity *>(cert.subject.nodes[i].identity), *reinterpret_cast<const Locator *>(cert.subject.nodes[i].locator));
  44. else if (cert.subject.nodes[i].identity)
  45. addSubjectNode(*reinterpret_cast<const Identity *>(cert.subject.nodes[i].identity));
  46. }
  47. for (unsigned int i = 0; i < cert.subject.networkCount; ++i)
  48. addSubjectNetwork(cert.subject.networks[i].id, cert.subject.networks[i].controller);
  49. if (cert.updateUrls) {
  50. for (unsigned int i = 0; i < cert.updateUrlCount; ++i)
  51. addUpdateUrl(cert.updateUrls[i]);
  52. }
  53. return *this;
  54. }
  55. ZT_IdentificationCertificate_Node *IdentificationCertificate::addSubjectNode(const Identity &id)
  56. {
  57. m_nodes.resize(++this->subject.nodeCount);
  58. this->subject.nodes = m_nodes.data();
  59. m_identities.push_back(id);
  60. m_nodes.back().identity = reinterpret_cast<ZT_Identity *>(&(m_identities.back()));
  61. m_nodes.back().locator = nullptr;
  62. return &(m_nodes.back());
  63. }
  64. ZT_IdentificationCertificate_Node *IdentificationCertificate::addSubjectNode(const Identity &id, const Locator &loc)
  65. {
  66. ZT_IdentificationCertificate_Node *n = addSubjectNode(id);
  67. m_locators.push_back(loc);
  68. n->locator = reinterpret_cast<ZT_Locator *>(&(m_locators.back()));
  69. return n;
  70. }
  71. ZT_IdentificationCertificate_Network *IdentificationCertificate::addSubjectNetwork(const uint64_t id, const ZT_Fingerprint &controller)
  72. {
  73. m_networks.resize(++this->subject.networkCount);
  74. this->subject.networks = m_networks.data();
  75. m_networks.back().id = id;
  76. Utils::copy< sizeof(ZT_Fingerprint) >(&(m_networks.back().controller), &controller);
  77. return &(m_networks.back());
  78. }
  79. void IdentificationCertificate::addUpdateUrl(const char *url)
  80. {
  81. m_strings.push_back(url);
  82. m_updateUrls.push_back(m_strings.back().c_str());
  83. this->updateUrls = m_updateUrls.data();
  84. this->updateUrlCount = (unsigned int)m_updateUrls.size();
  85. }
  86. Vector< uint8_t > IdentificationCertificate::encode(const bool omitSignature) const
  87. {
  88. char tmp[256];
  89. Vector< uint8_t > enc;
  90. Dictionary d;
  91. d.add("v", (uint64_t)this->version);
  92. d.add("mP", (uint64_t)this->maxPathLength);
  93. d.add("f", this->flags);
  94. d.add("v0", this->validity[0]);
  95. d.add("v1", this->validity[1]);
  96. d.add("s.n[]", (uint64_t)this->subject.nodeCount);
  97. for (unsigned int i = 0; i < this->subject.nodeCount; ++i) {
  98. d.addO(Dictionary::arraySubscript(tmp, "s.n[].i", i), *reinterpret_cast<const Identity *>(this->subject.nodes[i].identity));
  99. if (this->subject.nodes[i].locator)
  100. d.addO(Dictionary::arraySubscript(tmp, "s.n[].l", i), *reinterpret_cast<const Locator *>(this->subject.nodes[i].locator));
  101. }
  102. d.add("s.nw[]", (uint64_t)this->subject.networkCount);
  103. for (unsigned int i = 0; i < this->subject.networkCount; ++i) {
  104. d.add(Dictionary::arraySubscript(tmp, "s.nw[].i", i), this->subject.networks[i].id);
  105. Fingerprint fp(this->subject.networks[i].controller);
  106. d.addO(Dictionary::arraySubscript(tmp, "s.nw[].c", i), fp);
  107. }
  108. d.add("s.n.c", this->subject.name.country);
  109. d.add("s.n.o", this->subject.name.organization);
  110. d.add("s.n.u", this->subject.name.unit);
  111. d.add("s.n.l", this->subject.name.locality);
  112. d.add("s.n.p", this->subject.name.province);
  113. d.add("s.n.sA", this->subject.name.streetAddress);
  114. d.add("s.n.pC", this->subject.name.postalCode);
  115. d.add("s.n.cN", this->subject.name.commonName);
  116. d.add("s.n.sN", this->subject.name.serialNo);
  117. d.add("s.n.e", this->subject.name.email);
  118. d.add("s.n.ur", this->subject.name.url);
  119. if (this->issuer)
  120. d.addO("i", *reinterpret_cast<const Identity *>(this->issuer));
  121. d.add("iN.c", this->issuerName.country);
  122. d.add("iN.o", this->issuerName.organization);
  123. d.add("iN.u", this->issuerName.unit);
  124. d.add("iN.l", this->issuerName.locality);
  125. d.add("iN.p", this->issuerName.province);
  126. d.add("iN.sA", this->issuerName.streetAddress);
  127. d.add("iN.pC", this->issuerName.postalCode);
  128. d.add("iN.cN", this->issuerName.commonName);
  129. d.add("iN.sN", this->issuerName.serialNo);
  130. d.add("iN.e", this->issuerName.email);
  131. d.add("iN.ur", this->issuerName.url);
  132. d.add("uU[]", (uint64_t)this->updateUrlCount);
  133. if (this->updateUrls) {
  134. for (unsigned int i = 0; i < this->updateUrlCount; ++i)
  135. d.add(Dictionary::arraySubscript(tmp, "uU[]", i), this->updateUrls[i]);
  136. }
  137. if ((!omitSignature) && (this->signatureSize > 0) && (this->signatureSize <= sizeof(this->signature)))
  138. d["si"].assign(this->signature, this->signature + this->signatureSize);
  139. d.encode(enc);
  140. return enc;
  141. }
  142. bool IdentificationCertificate::decode(const Vector< uint8_t > &data)
  143. {
  144. char tmp[256], tmp2[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1];
  145. clear();
  146. Dictionary d;
  147. if (!d.decode(data.data(), (unsigned int)data.size()))
  148. return false;
  149. this->version = (unsigned int)d.getUI("v");
  150. this->maxPathLength = (unsigned int)d.getUI("mP");
  151. this->flags = d.getUI("f");
  152. this->validity[0] = (int64_t)d.getUI("v0");
  153. this->validity[1] = (int64_t)d.getUI("v1");
  154. unsigned int cnt = (unsigned int)d.getUI("s.n[]");
  155. for (unsigned int i = 0; i < cnt; ++i) {
  156. const Vector< uint8_t > &identityData = d[Dictionary::arraySubscript(tmp, "s.n[].i", i)];
  157. if (identityData.empty())
  158. return false;
  159. Identity id;
  160. if (id.unmarshal(identityData.data(), (unsigned int)identityData.size()) <= 0)
  161. return false;
  162. const Vector< uint8_t > &locatorData = d[Dictionary::arraySubscript(tmp, "s.n[].l", i)];
  163. if (!locatorData.empty()) {
  164. Locator loc;
  165. if (loc.unmarshal(locatorData.data(), (unsigned int)locatorData.size()) <= 0)
  166. return false;
  167. this->addSubjectNode(id, loc);
  168. } else {
  169. this->addSubjectNode(id);
  170. }
  171. }
  172. cnt = (unsigned int)d.getUI("s.nw[]");
  173. for (unsigned int i = 0; i < cnt; ++i) {
  174. const uint64_t nwid = d.getUI(Dictionary::arraySubscript(tmp, "s.nw[].i", i));
  175. if (nwid == 0)
  176. return false;
  177. const Vector< uint8_t > &fingerprintData = d[Dictionary::arraySubscript(tmp, "s.nw[].c", i)];
  178. if (fingerprintData.empty())
  179. return false;
  180. Fingerprint fp;
  181. if (fp.unmarshal(fingerprintData.data(), (unsigned int)fingerprintData.size()) <= 0)
  182. return false;
  183. this->addSubjectNetwork(nwid, fp);
  184. }
  185. d.getS("s.n.c", this->subject.name.country, sizeof(this->subject.name.country));
  186. d.getS("s.n.o", this->subject.name.organization, sizeof(this->subject.name.organization));
  187. d.getS("s.n.u", this->subject.name.unit, sizeof(this->subject.name.unit));
  188. d.getS("s.n.l", this->subject.name.locality, sizeof(this->subject.name.locality));
  189. d.getS("s.n.p", this->subject.name.province, sizeof(this->subject.name.province));
  190. d.getS("s.n.sA", this->subject.name.streetAddress, sizeof(this->subject.name.streetAddress));
  191. d.getS("s.n.pC", this->subject.name.postalCode, sizeof(this->subject.name.postalCode));
  192. d.getS("s.n.cN", this->subject.name.commonName, sizeof(this->subject.name.commonName));
  193. d.getS("s.n.sN", this->subject.name.serialNo, sizeof(this->subject.name.serialNo));
  194. d.getS("s.n.e", this->subject.name.email, sizeof(this->subject.name.email));
  195. d.getS("s.n.ur", this->subject.name.url, sizeof(this->subject.name.url));
  196. const Vector< uint8_t > &issuerData = d["i"];
  197. if (!issuerData.empty()) {
  198. Identity id;
  199. if (id.unmarshal(issuerData.data(), (int)issuerData.size()) > 0) {
  200. m_identities.push_back(id);
  201. this->issuer = reinterpret_cast<const Identity *>(&(m_identities.back()));
  202. }
  203. }
  204. d.getS("iN.c", this->issuerName.country, sizeof(this->issuerName.country));
  205. d.getS("iN.o", this->issuerName.organization, sizeof(this->issuerName.organization));
  206. d.getS("iN.u", this->issuerName.unit, sizeof(this->issuerName.unit));
  207. d.getS("iN.l", this->issuerName.locality, sizeof(this->issuerName.locality));
  208. d.getS("iN.p", this->issuerName.province, sizeof(this->issuerName.province));
  209. d.getS("iN.sA", this->issuerName.streetAddress, sizeof(this->issuerName.streetAddress));
  210. d.getS("iN.pC", this->issuerName.postalCode, sizeof(this->issuerName.postalCode));
  211. d.getS("iN.cN", this->issuerName.commonName, sizeof(this->issuerName.commonName));
  212. d.getS("iN.sN", this->issuerName.serialNo, sizeof(this->issuerName.serialNo));
  213. d.getS("iN.e", this->issuerName.email, sizeof(this->issuerName.email));
  214. d.getS("iN.ur", this->issuerName.url, sizeof(this->issuerName.url));
  215. cnt = (unsigned int)d.getUI("uU[]");
  216. for (unsigned int i = 0; i < cnt; ++i) {
  217. const char *const url = d.getS(Dictionary::arraySubscript(tmp, "uU[]", i), tmp2, sizeof(tmp2));
  218. if (url)
  219. addUpdateUrl(tmp2);
  220. else return false;
  221. }
  222. const Vector< uint8_t > &sig = d["si"];
  223. if (sig.size() > sizeof(this->signature))
  224. return false;
  225. Utils::copy(this->signature, sig.data(), (unsigned int)sig.size());
  226. this->signatureSize = (unsigned int)sig.size();
  227. Vector< uint8_t > enc(encode(true));
  228. SHA384(this->serialNo, enc.data(), (unsigned int)enc.size());
  229. return true;
  230. }
  231. bool IdentificationCertificate::sign(const Identity &issuer)
  232. {
  233. Vector< uint8_t > enc(encode(true));
  234. SHA384(this->serialNo, enc.data(), (unsigned int)enc.size());
  235. return (this->signatureSize = issuer.sign(enc.data(), (unsigned int)enc.size(), this->signature, sizeof(this->signature))) > 0;
  236. }
  237. bool IdentificationCertificate::verify() const
  238. {
  239. if (this->issuer) {
  240. Vector< uint8_t > enc(encode(true));
  241. return reinterpret_cast<const Identity *>(this->issuer)->verify(enc.data(), (unsigned int)enc.size(), this->signature, this->signatureSize);
  242. }
  243. return false;
  244. }
  245. } // namespace ZeroTier