Certificate.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  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 "Certificate.hpp"
  14. #include "SHA512.hpp"
  15. #include "ECC384.hpp"
  16. namespace ZeroTier {
  17. Certificate::Certificate() noexcept
  18. {
  19. ZT_Certificate *const sup = this;
  20. Utils::zero< sizeof(ZT_Certificate) >(sup);
  21. }
  22. Certificate::Certificate(const ZT_Certificate &apiCert)
  23. {
  24. ZT_Certificate *const sup = this;
  25. Utils::copy< sizeof(ZT_Certificate) >(sup, &apiCert);
  26. }
  27. Certificate::Certificate(const Certificate &cert)
  28. { *this = cert; }
  29. Certificate::~Certificate()
  30. {}
  31. Certificate &Certificate::operator=(const ZT_Certificate &cert)
  32. {
  33. m_clear();
  34. ZT_Certificate *const sup = this;
  35. Utils::copy< sizeof(ZT_Certificate) >(sup, &cert);
  36. // Zero these since we must explicitly attach all the objects from
  37. // the other certificate to copy them into our containers.
  38. this->subject.identities = nullptr;
  39. this->subject.identityCount = 0;
  40. this->subject.networks = nullptr;
  41. this->subject.networkCount = 0;
  42. this->subject.certificates = nullptr;
  43. this->subject.certificateCount = 0;
  44. this->subject.updateURLs = nullptr;
  45. this->subject.updateURLCount = 0;
  46. this->subject.uniqueId = nullptr;
  47. this->subject.uniqueIdProofSignature = nullptr;
  48. this->subject.uniqueIdSize = 0;
  49. this->subject.uniqueIdProofSignatureSize = 0;
  50. this->extendedAttributes = nullptr;
  51. this->extendedAttributesSize = 0;
  52. this->issuer = nullptr;
  53. this->signature = nullptr;
  54. this->signatureSize = 0;
  55. for (unsigned int i = 0; i < cert.subject.identityCount; ++i) {
  56. if (cert.subject.identities[i].identity) {
  57. if (cert.subject.identities[i].locator)
  58. addSubjectIdentity(*reinterpret_cast<const Identity *>(cert.subject.identities[i].identity), *reinterpret_cast<const Locator *>(cert.subject.identities[i].locator));
  59. else addSubjectIdentity(*reinterpret_cast<const Identity *>(cert.subject.identities[i].identity));
  60. }
  61. }
  62. for (unsigned int i = 0; i < cert.subject.networkCount; ++i) {
  63. if (cert.subject.networks[i].id)
  64. addSubjectNetwork(cert.subject.networks[i].id, cert.subject.networks[i].controller);
  65. }
  66. for (unsigned int i = 0; i < cert.subject.certificateCount; ++i) {
  67. if (cert.subject.certificates[i])
  68. addSubjectCertificate(cert.subject.certificates[i]);
  69. }
  70. if (cert.subject.updateURLs) {
  71. for (unsigned int i = 0; i < cert.subject.updateURLCount; ++i) {
  72. if (cert.subject.updateURLs[i])
  73. addSubjectUpdateUrl(cert.subject.updateURLs[i]);
  74. }
  75. }
  76. if ((cert.subject.uniqueId) && (cert.subject.uniqueIdSize > 0)) {
  77. m_subjectUniqueId.assign(cert.subject.uniqueId, cert.subject.uniqueId + cert.subject.uniqueIdSize);
  78. this->subject.uniqueId = m_subjectUniqueId.data();
  79. this->subject.uniqueIdSize = (unsigned int)m_subjectUniqueId.size();
  80. }
  81. if ((cert.subject.uniqueIdProofSignature) && (cert.subject.uniqueIdProofSignatureSize > 0)) {
  82. m_subjectUniqueIdProofSignature.assign(cert.subject.uniqueIdProofSignature, cert.subject.uniqueIdProofSignature + cert.subject.uniqueIdProofSignatureSize);
  83. this->subject.uniqueIdProofSignature = m_subjectUniqueIdProofSignature.data();
  84. this->subject.uniqueIdProofSignatureSize = (unsigned int)m_subjectUniqueIdProofSignature.size();
  85. }
  86. if (cert.issuer) {
  87. m_identities.push_back(*reinterpret_cast<const Identity *>(cert.issuer));
  88. this->issuer = &(m_identities.back());
  89. }
  90. if ((cert.extendedAttributes) && (cert.extendedAttributesSize > 0)) {
  91. m_extendedAttributes.assign(cert.extendedAttributes, cert.extendedAttributes + cert.extendedAttributesSize);
  92. this->extendedAttributes = m_extendedAttributes.data();
  93. this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size();
  94. }
  95. if ((cert.signature) && (cert.signatureSize > 0)) {
  96. m_signature.assign(cert.signature, cert.signature + cert.signatureSize);
  97. this->signature = m_signature.data();
  98. this->signatureSize = (unsigned int)m_signature.size();
  99. }
  100. return *this;
  101. }
  102. ZT_Certificate_Identity *Certificate::addSubjectIdentity(const Identity &id)
  103. {
  104. // Enlarge array of ZT_Certificate_Identity structs and set pointer to potentially reallocated array.
  105. m_subjectIdentities.resize(++this->subject.identityCount);
  106. this->subject.identities = m_subjectIdentities.data();
  107. // Store a local copy of the actual identity.
  108. m_identities.push_back(id);
  109. // Set ZT_Certificate_Identity struct fields to point to local copy of identity.
  110. m_subjectIdentities.back().identity = &(m_identities.back());
  111. m_subjectIdentities.back().locator = nullptr;
  112. return &(m_subjectIdentities.back());
  113. }
  114. ZT_Certificate_Identity *Certificate::addSubjectIdentity(const Identity &id, const Locator &loc)
  115. {
  116. // Add identity as above.
  117. ZT_Certificate_Identity *const n = addSubjectIdentity(id);
  118. // Store local copy of locator.
  119. m_locators.push_back(loc);
  120. // Set pointer to stored local copy of locator.
  121. n->locator = &(m_locators.back());
  122. return n;
  123. }
  124. ZT_Certificate_Network *Certificate::addSubjectNetwork(const uint64_t id, const ZT_Fingerprint &controller)
  125. {
  126. // Enlarge array of ZT_Certificate_Network and set pointer to potentially reallocated array.
  127. m_subjectNetworks.resize(++this->subject.networkCount);
  128. this->subject.networks = m_subjectNetworks.data();
  129. // Set fields in new ZT_Certificate_Network structure.
  130. m_subjectNetworks.back().id = id;
  131. Utils::copy< sizeof(ZT_Fingerprint) >(&(m_subjectNetworks.back().controller), &controller);
  132. return &(m_subjectNetworks.back());
  133. }
  134. void Certificate::addSubjectCertificate(const uint8_t serialNo[ZT_SHA384_DIGEST_SIZE])
  135. {
  136. // Store local copy of serial in m_serials container.
  137. m_serials.push_back(SHA384Hash(serialNo));
  138. // Enlarge array of uint8_t pointers, set new pointer to local copy of serial, and set
  139. // certificates to point to potentially reallocated array.
  140. m_subjectCertificates.resize(++this->subject.certificateCount);
  141. m_subjectCertificates.back() = m_serials.back().bytes();
  142. this->subject.certificates = m_subjectCertificates.data();
  143. }
  144. void Certificate::addSubjectUpdateUrl(const char *url)
  145. {
  146. // Store local copy of URL.
  147. m_strings.push_back(url);
  148. // Add pointer to local copy to pointer array and update C structure to point to
  149. // potentially reallocated array.
  150. m_updateUrls.push_back(m_strings.back().c_str());
  151. this->subject.updateURLs = m_updateUrls.data();
  152. this->subject.updateURLCount = (unsigned int)m_updateUrls.size();
  153. }
  154. void Certificate::setExtendedAttributes(const Dictionary &x)
  155. {
  156. m_extendedAttributes.clear();
  157. x.encode(m_extendedAttributes);
  158. this->extendedAttributes = m_extendedAttributes.data();
  159. this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size();
  160. }
  161. Vector< uint8_t > Certificate::encode(const bool omitSignature) const
  162. {
  163. Vector< uint8_t > enc;
  164. Dictionary d;
  165. // A Dictionary is used to encode certificates as it's a common and extensible
  166. // format. Custom packed formats are used for credentials as these are smaller
  167. // and faster to marshal/unmarshal.
  168. if (this->flags != 0)
  169. d.add("f", this->flags);
  170. d.add("t", (uint64_t)this->timestamp);
  171. d.add("v#0", (uint64_t)this->validity[0]);
  172. d.add("v#1", (uint64_t)this->validity[1]);
  173. if ((this->extendedAttributes) && (this->extendedAttributesSize > 0))
  174. d["x"].assign(this->extendedAttributes, this->extendedAttributes + this->extendedAttributesSize);
  175. d.add("mP", (uint64_t)this->maxPathLength);
  176. m_encodeSubject(this->subject, d, false);
  177. if (this->issuer)
  178. d.addO("i", *reinterpret_cast<const Identity *>(this->issuer));
  179. if (this->issuerName.country[0])
  180. d.add("iN.c", this->issuerName.country);
  181. if (this->issuerName.organization[0])
  182. d.add("iN.o", this->issuerName.organization);
  183. if (this->issuerName.unit[0])
  184. d.add("iN.u", this->issuerName.unit);
  185. if (this->issuerName.locality[0])
  186. d.add("iN.l", this->issuerName.locality);
  187. if (this->issuerName.province[0])
  188. d.add("iN.p", this->issuerName.province);
  189. if (this->issuerName.streetAddress[0])
  190. d.add("iN.sA", this->issuerName.streetAddress);
  191. if (this->issuerName.postalCode[0])
  192. d.add("iN.pC", this->issuerName.postalCode);
  193. if (this->issuerName.commonName[0])
  194. d.add("iN.cN", this->issuerName.commonName);
  195. if (this->issuerName.serialNo[0])
  196. d.add("iN.sN", this->issuerName.serialNo);
  197. if (this->issuerName.email[0])
  198. d.add("iN.e", this->issuerName.email);
  199. if (this->issuerName.url[0])
  200. d.add("iN.ur", this->issuerName.url);
  201. if (this->issuerName.host[0])
  202. d.add("iN.h", this->issuerName.host);
  203. if ((this->extendedAttributes) && (this->extendedAttributesSize > 0))
  204. d["x"].assign(this->extendedAttributes, this->extendedAttributes + this->extendedAttributesSize);
  205. if ((!omitSignature) && (this->signatureSize > 0) && (this->signature))
  206. d["si"].assign(this->signature, this->signature + this->signatureSize);
  207. d.encode(enc);
  208. return enc;
  209. }
  210. bool Certificate::decode(const void *const data, const unsigned int len)
  211. {
  212. char tmp[256], tmp2[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
  213. Dictionary d;
  214. if (!d.decode(data, len))
  215. return false;
  216. m_clear();
  217. this->flags = d.getUI("f");
  218. this->timestamp = (int64_t)d.getUI("t");
  219. this->validity[0] = (int64_t)d.getUI("v#0");
  220. this->validity[1] = (int64_t)d.getUI("v#1");
  221. this->maxPathLength = (unsigned int)d.getUI("mP");
  222. this->subject.timestamp = (int64_t)d.getUI("s.t");
  223. unsigned int cnt = (unsigned int)d.getUI("s.i$");
  224. for (unsigned int i = 0; i < cnt; ++i) {
  225. const Vector< uint8_t > &identityData = d[Dictionary::arraySubscript(tmp, "s.i$.i", i)];
  226. if (identityData.empty())
  227. return false;
  228. Identity id;
  229. if (id.unmarshal(identityData.data(), (unsigned int)identityData.size()) <= 0)
  230. return false;
  231. const Vector< uint8_t > &locatorData = d[Dictionary::arraySubscript(tmp, "s.i$.l", i)];
  232. if (!locatorData.empty()) {
  233. Locator loc;
  234. if (loc.unmarshal(locatorData.data(), (unsigned int)locatorData.size()) <= 0)
  235. return false;
  236. this->addSubjectIdentity(id, loc);
  237. } else {
  238. this->addSubjectIdentity(id);
  239. }
  240. }
  241. cnt = (unsigned int)d.getUI("s.n$");
  242. for (unsigned int i = 0; i < cnt; ++i) {
  243. const uint64_t nwid = d.getUI(Dictionary::arraySubscript(tmp, "s.n$.i", i));
  244. const Vector< uint8_t > &fingerprintData = d[Dictionary::arraySubscript(tmp, "s.n$.c", i)];
  245. if ((nwid == 0) || (fingerprintData.empty()))
  246. return false;
  247. Fingerprint fp;
  248. if (fp.unmarshal(fingerprintData.data(), (unsigned int)fingerprintData.size()) <= 0)
  249. return false;
  250. this->addSubjectNetwork(nwid, fp);
  251. }
  252. cnt = (unsigned int)d.getUI("s.c$");
  253. for (unsigned int i = 0; i < cnt; ++i) {
  254. const Vector< uint8_t > &serial = d[Dictionary::arraySubscript(tmp, "s.c$", i)];
  255. if (serial.size() != ZT_SHA384_DIGEST_SIZE)
  256. return false;
  257. this->addSubjectCertificate(serial.data());
  258. }
  259. cnt = (unsigned int)d.getUI("s.u$");
  260. for (unsigned int i = 0; i < cnt; ++i)
  261. addSubjectUpdateUrl(d.getS(Dictionary::arraySubscript(tmp, "s.u$", i), tmp, sizeof(tmp)));
  262. d.getS("s.n.sN", this->subject.name.serialNo, sizeof(this->subject.name.serialNo));
  263. d.getS("s.n.cN", this->subject.name.commonName, sizeof(this->subject.name.commonName));
  264. d.getS("s.n.c", this->subject.name.country, sizeof(this->subject.name.country));
  265. d.getS("s.n.o", this->subject.name.organization, sizeof(this->subject.name.organization));
  266. d.getS("s.n.u", this->subject.name.unit, sizeof(this->subject.name.unit));
  267. d.getS("s.n.l", this->subject.name.locality, sizeof(this->subject.name.locality));
  268. d.getS("s.n.p", this->subject.name.province, sizeof(this->subject.name.province));
  269. d.getS("s.n.sA", this->subject.name.streetAddress, sizeof(this->subject.name.streetAddress));
  270. d.getS("s.n.pC", this->subject.name.postalCode, sizeof(this->subject.name.postalCode));
  271. d.getS("s.n.e", this->subject.name.email, sizeof(this->subject.name.email));
  272. d.getS("s.n.ur", this->subject.name.url, sizeof(this->subject.name.url));
  273. d.getS("s.n.h", this->subject.name.host, sizeof(this->subject.name.host));
  274. m_subjectUniqueId = d["s.uI"];
  275. if (!m_subjectUniqueId.empty()) {
  276. this->subject.uniqueId = m_subjectUniqueId.data();
  277. this->subject.uniqueIdSize = (unsigned int)m_subjectUniqueId.size();
  278. }
  279. m_subjectUniqueIdProofSignature = d["s.uS"];
  280. if (!m_subjectUniqueIdProofSignature.empty()) {
  281. this->subject.uniqueIdProofSignature = m_subjectUniqueIdProofSignature.data();
  282. this->subject.uniqueIdProofSignatureSize = (unsigned int)m_subjectUniqueIdProofSignature.size();
  283. }
  284. const Vector< uint8_t > &issuerData = d["i"];
  285. if (!issuerData.empty()) {
  286. Identity id;
  287. if (id.unmarshal(issuerData.data(), (int)issuerData.size()) > 0) {
  288. m_identities.push_back(id);
  289. this->issuer = reinterpret_cast<const Identity *>(&(m_identities.back()));
  290. }
  291. }
  292. d.getS("iN.sN", this->issuerName.serialNo, sizeof(this->issuerName.serialNo));
  293. d.getS("iN.cN", this->issuerName.commonName, sizeof(this->issuerName.commonName));
  294. d.getS("iN.c", this->issuerName.country, sizeof(this->issuerName.country));
  295. d.getS("iN.o", this->issuerName.organization, sizeof(this->issuerName.organization));
  296. d.getS("iN.u", this->issuerName.unit, sizeof(this->issuerName.unit));
  297. d.getS("iN.l", this->issuerName.locality, sizeof(this->issuerName.locality));
  298. d.getS("iN.p", this->issuerName.province, sizeof(this->issuerName.province));
  299. d.getS("iN.sA", this->issuerName.streetAddress, sizeof(this->issuerName.streetAddress));
  300. d.getS("iN.pC", this->issuerName.postalCode, sizeof(this->issuerName.postalCode));
  301. d.getS("iN.e", this->issuerName.email, sizeof(this->issuerName.email));
  302. d.getS("iN.ur", this->issuerName.url, sizeof(this->issuerName.url));
  303. d.getS("iN.h", this->issuerName.host, sizeof(this->issuerName.host));
  304. cnt = (unsigned int)d.getUI("u$");
  305. for (unsigned int i = 0; i < cnt; ++i) {
  306. const char *const url = d.getS(Dictionary::arraySubscript(tmp, "u$", i), tmp2, sizeof(tmp2));
  307. if (url)
  308. addSubjectUpdateUrl(tmp2);
  309. else return false;
  310. }
  311. m_extendedAttributes = d["x"];
  312. if (!m_extendedAttributes.empty()) {
  313. this->extendedAttributes = m_extendedAttributes.data();
  314. this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size();
  315. }
  316. m_signature = d["si"];
  317. if (!m_signature.empty()) {
  318. this->signature = m_signature.data();
  319. this->signatureSize = (unsigned int)m_signature.size();
  320. }
  321. const Vector< uint8_t > enc(encode(true));
  322. SHA384(this->serialNo, enc.data(), (unsigned int)enc.size());
  323. return true;
  324. }
  325. Vector< uint8_t > Certificate::encodeCSR()
  326. {
  327. Vector< uint8_t > enc;
  328. Dictionary d;
  329. m_encodeSubject(this->subject, d, false);
  330. d.encode(enc);
  331. return enc;
  332. }
  333. bool Certificate::sign(const Identity &issuer)
  334. {
  335. Vector< uint8_t > enc(encode(true));
  336. SHA384(this->serialNo, enc.data(), (unsigned int)enc.size());
  337. uint8_t sig[ZT_SIGNATURE_BUFFER_SIZE];
  338. const unsigned int sigSize = issuer.sign(enc.data(), (unsigned int)enc.size(), sig, sizeof(sig));
  339. if (sigSize > 0) {
  340. m_signature.assign(sig, sig + sigSize);
  341. this->signature = m_signature.data();
  342. this->signatureSize = sigSize;
  343. return true;
  344. }
  345. m_signature.clear();
  346. this->signature = nullptr;
  347. this->signatureSize = 0;
  348. return false;
  349. }
  350. ZT_CertificateError Certificate::verify() const
  351. {
  352. try {
  353. if (this->issuer) {
  354. const Vector< uint8_t > enc(encode(true));
  355. if (!reinterpret_cast<const Identity *>(this->issuer)->verify(enc.data(), (unsigned int)enc.size(), this->signature, this->signatureSize))
  356. return ZT_CERTIFICATE_ERROR_INVALID_PRIMARY_SIGNATURE;
  357. } else {
  358. return ZT_CERTIFICATE_ERROR_INVALID_PRIMARY_SIGNATURE;
  359. }
  360. if (this->subject.uniqueIdProofSignatureSize > 0) {
  361. if (
  362. (this->subject.uniqueIdProofSignatureSize != ZT_ECC384_SIGNATURE_SIZE) ||
  363. (this->subject.uniqueIdSize != (ZT_ECC384_PUBLIC_KEY_SIZE + 1)) ||
  364. (this->subject.uniqueId[0] != ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384))
  365. return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
  366. Dictionary tmp;
  367. m_encodeSubject(this->subject, tmp, true);
  368. Vector< uint8_t > enc;
  369. tmp.encode(enc);
  370. uint8_t h[ZT_SHA384_DIGEST_SIZE];
  371. SHA384(h, enc.data(), (unsigned int)enc.size());
  372. if (!ECC384ECDSAVerify(this->subject.uniqueId + 1, h, this->subject.uniqueIdProofSignature))
  373. return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
  374. } else if (this->subject.uniqueIdSize > 0) {
  375. return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
  376. }
  377. for (unsigned int i = 0; i < this->subject.identityCount; ++i) {
  378. if (!this->subject.identities[i].identity)
  379. return ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS;
  380. if (!reinterpret_cast<const Identity *>(this->subject.identities[i].identity)->locallyValidate())
  381. return ZT_CERTIFICATE_ERROR_INVALID_IDENTITY;
  382. if (this->subject.identities[i].locator) {
  383. if (!reinterpret_cast<const Locator *>(this->subject.identities[i].locator)->verify(*reinterpret_cast<const Identity *>(this->subject.identities[i].identity)))
  384. return ZT_CERTIFICATE_ERROR_INVALID_COMPONENT_SIGNATURE;
  385. }
  386. }
  387. for (unsigned int i = 0; i < this->subject.networkCount; ++i) {
  388. if (!this->subject.networks[i].id)
  389. return ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS;
  390. }
  391. if (this->subject.updateURLCount) {
  392. if (!this->subject.updateURLs)
  393. return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
  394. for (unsigned int i = 0; i < this->subject.updateURLCount; ++i) {
  395. if (!this->subject.updateURLs[i])
  396. return ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS;
  397. }
  398. } else if (this->subject.updateURLs) {
  399. return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
  400. }
  401. } catch (...) {}
  402. return ZT_CERTIFICATE_ERROR_NONE;
  403. }
  404. bool Certificate::setSubjectUniqueId(const uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE], const uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE])
  405. {
  406. m_subjectUniqueId.assign(uniqueId, uniqueId + ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE);
  407. this->subject.uniqueId = m_subjectUniqueId.data();
  408. this->subject.uniqueIdSize = ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE;
  409. Dictionary d;
  410. m_encodeSubject(this->subject, d, true);
  411. Vector< uint8_t > enc;
  412. d.encode(enc);
  413. uint8_t h[ZT_SHA384_DIGEST_SIZE];
  414. SHA384(h, enc.data(), (unsigned int)enc.size());
  415. m_subjectUniqueIdProofSignature.resize(ZT_ECC384_SIGNATURE_SIZE);
  416. ECC384ECDSASign(uniqueIdPrivate, h, m_subjectUniqueIdProofSignature.data());
  417. this->subject.uniqueIdProofSignature = m_subjectUniqueIdProofSignature.data();
  418. this->subject.uniqueIdProofSignatureSize = ZT_ECC384_SIGNATURE_SIZE;
  419. return true;
  420. }
  421. void Certificate::m_clear()
  422. {
  423. ZT_Certificate *const sup = this;
  424. Utils::zero< sizeof(ZT_Certificate) >(sup);
  425. m_identities.clear();
  426. m_locators.clear();
  427. m_strings.clear();
  428. m_serials.clear();
  429. m_subjectIdentities.clear();
  430. m_subjectNetworks.clear();
  431. m_updateUrls.clear();
  432. m_subjectCertificates.clear();
  433. m_extendedAttributes.clear();
  434. m_subjectUniqueId.clear();
  435. m_subjectUniqueIdProofSignature.clear();
  436. m_signature.clear();
  437. }
  438. void Certificate::m_encodeSubject(const ZT_Certificate_Subject &s, Dictionary &d, bool omitUniqueIdProofSignature)
  439. {
  440. char tmp[64];
  441. d.add("s.t", (uint64_t)s.timestamp);
  442. d.add("s.i$", (uint64_t)s.identityCount);
  443. for (unsigned int i = 0; i < s.identityCount; ++i) {
  444. if (s.identities[i].identity)
  445. d.addO(Dictionary::arraySubscript(tmp, "s.i$.i", i), *reinterpret_cast<const Identity *>(s.identities[i].identity));
  446. if (s.identities[i].locator)
  447. d.addO(Dictionary::arraySubscript(tmp, "s.i$.l", i), *reinterpret_cast<const Locator *>(s.identities[i].locator));
  448. }
  449. d.add("s.n$", (uint64_t)s.networkCount);
  450. for (unsigned int i = 0; i < s.networkCount; ++i) {
  451. d.add(Dictionary::arraySubscript(tmp, "s.n$.i", i), s.networks[i].id);
  452. Fingerprint fp(s.networks[i].controller);
  453. d.addO(Dictionary::arraySubscript(tmp, "s.n$.c", i), fp);
  454. }
  455. d.add("s.c$", (uint64_t)s.certificateCount);
  456. for (unsigned int i = 0; i < s.certificateCount; ++i) {
  457. if (s.certificates[i])
  458. d[Dictionary::arraySubscript(tmp, "s.c$", i)].assign(s.certificates[i], s.certificates[i] + ZT_SHA384_DIGEST_SIZE);
  459. }
  460. d.add("s.u$", (uint64_t)s.updateURLCount);
  461. if (s.updateURLs) {
  462. for (unsigned int i = 0; i < s.updateURLCount; ++i)
  463. d.add(Dictionary::arraySubscript(tmp, "s.u$", i), s.updateURLs[i]);
  464. }
  465. if (s.name.country[0])
  466. d.add("s.n.c", s.name.country);
  467. if (s.name.organization[0])
  468. d.add("s.n.o", s.name.organization);
  469. if (s.name.unit[0])
  470. d.add("s.n.u", s.name.unit);
  471. if (s.name.locality[0])
  472. d.add("s.n.l", s.name.locality);
  473. if (s.name.province[0])
  474. d.add("s.n.p", s.name.province);
  475. if (s.name.streetAddress[0])
  476. d.add("s.n.sA", s.name.streetAddress);
  477. if (s.name.postalCode[0])
  478. d.add("s.n.pC", s.name.postalCode);
  479. if (s.name.commonName[0])
  480. d.add("s.n.cN", s.name.commonName);
  481. if (s.name.serialNo[0])
  482. d.add("s.n.sN", s.name.serialNo);
  483. if (s.name.email[0])
  484. d.add("s.n.e", s.name.email);
  485. if (s.name.url[0])
  486. d.add("s.n.ur", s.name.url);
  487. if (s.name.host[0])
  488. d.add("s.n.h", s.name.host);
  489. if ((s.uniqueIdSize > 0) && (s.uniqueId != nullptr))
  490. d["s.uI"].assign(s.uniqueId, s.uniqueId + s.uniqueIdSize);
  491. if ((!omitUniqueIdProofSignature) && (s.uniqueIdProofSignatureSize > 0) && (s.uniqueIdProofSignature != nullptr))
  492. d["s.uS"].assign(s.uniqueIdProofSignature, s.uniqueIdProofSignature + s.uniqueIdProofSignatureSize);
  493. }
  494. } // namespace ZeroTier
  495. extern "C" {
  496. int ZT_Certificate_newSubjectUniqueId(
  497. enum ZT_CertificateUniqueIdType type,
  498. void *uniqueId,
  499. int *uniqueIdSize,
  500. void *uniqueIdPrivate,
  501. int *uniqueIdPrivateSize)
  502. {
  503. switch(type) {
  504. case ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384:
  505. if ((*uniqueIdSize < ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE) || (*uniqueIdPrivateSize < ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE))
  506. return ZT_RESULT_ERROR_BAD_PARAMETER;
  507. *uniqueIdSize = ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE;
  508. *uniqueIdPrivateSize = ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE;
  509. ZeroTier::Certificate::createSubjectUniqueId(reinterpret_cast<uint8_t *>(uniqueId), reinterpret_cast<uint8_t *>(uniqueIdPrivate));
  510. return ZT_RESULT_OK;
  511. }
  512. return ZT_RESULT_ERROR_BAD_PARAMETER;
  513. }
  514. int ZT_Certificate_newCSR(
  515. const ZT_Certificate_Subject *subject,
  516. const void *uniqueId,
  517. int uniqueIdSize,
  518. const void *uniqueIdPrivate,
  519. int uniqueIdPrivateSize,
  520. void *csr,
  521. int *csrSize)
  522. {
  523. ZeroTier::Certificate c;
  524. ZeroTier::Utils::copy< sizeof(ZT_Certificate_Subject) >(&(c.subject), subject);
  525. if ((uniqueId) && (uniqueIdSize > 0) && (uniqueIdPrivate) && (uniqueIdPrivateSize > 0)) {
  526. if ((reinterpret_cast<const uint8_t *>(uniqueId)[0] != ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384) || (uniqueIdSize != ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE) || (uniqueIdPrivateSize != ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE))
  527. return ZT_RESULT_ERROR_BAD_PARAMETER;
  528. if (!c.setSubjectUniqueId(reinterpret_cast<const uint8_t *>(uniqueId), reinterpret_cast<const uint8_t *>(uniqueIdPrivate)))
  529. return ZT_RESULT_ERROR_INVALID_CREDENTIAL;
  530. }
  531. ZeroTier::Vector< uint8_t > csrV(c.encodeCSR());
  532. if ((int)csrV.size() > *csrSize)
  533. return ZT_RESULT_ERROR_BAD_PARAMETER;
  534. ZeroTier::Utils::copy(csr, csrV.data(), (unsigned int)csrV.size());
  535. *csrSize = (int)csrV.size();
  536. return ZT_RESULT_OK;
  537. }
  538. int ZT_Certificate_sign(
  539. const ZT_Certificate *cert,
  540. const ZT_Identity *signer,
  541. void *signedCert,
  542. int *signedCertSize)
  543. {
  544. if (!cert)
  545. return ZT_RESULT_ERROR_BAD_PARAMETER;
  546. ZeroTier::Certificate c(*cert);
  547. if (!c.sign(*reinterpret_cast<const ZeroTier::Identity *>(signer)))
  548. return ZT_RESULT_ERROR_BAD_PARAMETER;
  549. ZeroTier::Vector< uint8_t > enc(c.encode());
  550. if ((int)enc.size() > *signedCertSize)
  551. return ZT_RESULT_ERROR_BAD_PARAMETER;
  552. ZeroTier::Utils::copy(signedCert, enc.data(), (unsigned int)enc.size());
  553. *signedCertSize = (int)enc.size();
  554. return ZT_RESULT_OK;
  555. }
  556. enum ZT_CertificateError ZT_Certificate_decode(
  557. const ZT_Certificate **decodedCert,
  558. const void *cert,
  559. int certSize,
  560. int verify)
  561. {
  562. try {
  563. if (!decodedCert)
  564. return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
  565. *decodedCert = nullptr;
  566. ZeroTier::Certificate *const c = new ZeroTier::Certificate();
  567. if (!c->decode(cert, certSize)) {
  568. delete c;
  569. return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
  570. }
  571. if (verify) {
  572. ZT_CertificateError err = c->verify();
  573. if (err != ZT_CERTIFICATE_ERROR_NONE) {
  574. delete c;
  575. return err;
  576. }
  577. }
  578. *decodedCert = c;
  579. return ZT_CERTIFICATE_ERROR_NONE;
  580. } catch ( ... ) {
  581. return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
  582. }
  583. }
  584. int ZT_Certificate_encode(
  585. const ZT_Certificate *cert,
  586. void *encoded,
  587. int *encodedSize)
  588. {
  589. if ((!cert) || (!encoded) || (!encodedSize))
  590. return ZT_RESULT_ERROR_BAD_PARAMETER;
  591. ZeroTier::Certificate c(*cert);
  592. ZeroTier::Vector< uint8_t > enc(c.encode());
  593. if ((int)enc.size() > *encodedSize)
  594. return ZT_RESULT_ERROR_BAD_PARAMETER;
  595. ZeroTier::Utils::copy(encoded, enc.data(), (unsigned int)enc.size());
  596. *encodedSize = (int)enc.size();
  597. return ZT_RESULT_OK;
  598. }
  599. enum ZT_CertificateError ZT_Certificate_verify(const ZT_Certificate *cert)
  600. {
  601. try {
  602. if (!cert)
  603. return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
  604. return ZeroTier::Certificate(*cert).verify();
  605. } catch ( ... ) {
  606. return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
  607. }
  608. }
  609. const ZT_Certificate *ZT_Certificate_clone(const ZT_Certificate *cert)
  610. {
  611. try {
  612. if (!cert)
  613. return nullptr;
  614. return (const ZT_Certificate *)(new ZeroTier::Certificate(*cert));
  615. } catch ( ... ) {
  616. return nullptr;
  617. }
  618. }
  619. void ZT_Certificate_delete(const ZT_Certificate *cert)
  620. {
  621. if (cert)
  622. delete (const ZeroTier::Certificate *)(cert);
  623. }
  624. }