Certificate.cpp 26 KB

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