Certificate.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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: 2025-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. #ifndef ZT_CERTIFICATE_HPP
  14. #define ZT_CERTIFICATE_HPP
  15. #include "Constants.hpp"
  16. #include "SHA512.hpp"
  17. #include "C25519.hpp"
  18. #include "ECC384.hpp"
  19. #include "SharedPtr.hpp"
  20. #include "Identity.hpp"
  21. #include "Locator.hpp"
  22. #include "Dictionary.hpp"
  23. #include "Utils.hpp"
  24. #include "Blob.hpp"
  25. #include "Containers.hpp"
  26. namespace ZeroTier {
  27. /**
  28. * Certificate describing and grouping a set of objects.
  29. *
  30. * This is a wrapper around the straight C ZT_IdentificationCertificate and
  31. * handles allocating memory for objects added via addXXX() and disposing of
  32. * them on delete. If pointers in the underlying C struct are set manually,
  33. * their memory is not freed on delete. Use the addXXX() methods to fill
  34. * out this structure in C++ code.
  35. *
  36. * The serialNo field is filled in automatically by sign() and decode(), so
  37. * it can be left undefined when building certificates. It contains a SHA384
  38. * hash of the certificate marshalled without the signature field.
  39. *
  40. * The hashCode() method and comparison operators compare the serial number
  41. * field, so these will not work correctly before sign() or decode() is
  42. * called.
  43. */
  44. class Certificate : public ZT_Certificate
  45. {
  46. friend class SharedPtr< Certificate >;
  47. friend class SharedPtr< const Certificate >;
  48. public:
  49. Certificate() noexcept;
  50. Certificate(const ZT_Certificate &apiCert);
  51. Certificate(const Certificate &cert);
  52. ~Certificate();
  53. Certificate &operator=(const ZT_Certificate &cert);
  54. ZT_INLINE Certificate &operator=(const Certificate &cert) noexcept
  55. {
  56. if (likely(&cert != this)) {
  57. const ZT_Certificate *const sup = &cert;
  58. *this = *sup;
  59. }
  60. return *this;
  61. }
  62. /**
  63. * Add a subject node/identity without a locator
  64. *
  65. * @param id Identity
  66. * @return Pointer to C struct
  67. */
  68. ZT_Certificate_Identity *addSubjectIdentity(const Identity &id);
  69. /**
  70. * Add a subject node/identity with a locator
  71. *
  72. * @param id Identity
  73. * @param loc Locator signed by identity (signature is NOT checked here)
  74. * @return Pointer to C struct
  75. */
  76. ZT_Certificate_Identity *addSubjectIdentity(const Identity &id, const Locator &loc);
  77. /**
  78. * Add a subject network
  79. *
  80. * @param id Network ID
  81. * @param controller Network controller's full fingerprint
  82. * @return Pointer to C struct
  83. */
  84. ZT_Certificate_Network *addSubjectNetwork(const uint64_t id, const ZT_Fingerprint &controller);
  85. /**
  86. * Add a subject certificate (by its serial number)
  87. *
  88. * @param serialNo 384-bit serial number
  89. */
  90. void addSubjectCertificate(const uint8_t serialNo[ZT_SHA384_DIGEST_SIZE]);
  91. /**
  92. * Add an update URL to the updateUrls list
  93. *
  94. * @param url Update URL
  95. */
  96. void addSubjectUpdateUrl(const char *url);
  97. /**
  98. * Set the extended attributes of this certificate
  99. *
  100. * @param x Extended attributes (set by issuer)
  101. */
  102. void setExtendedAttributes(const Dictionary &x);
  103. /**
  104. * Set the unique ID of this certificate's subject
  105. *
  106. * This must be done after all other fields in the subject are set.
  107. *
  108. * @param uniqueId Unique ID
  109. * @param uniqueIdPrivate Private key associated with unique ID to prove ownership of it
  110. * @return True if successful
  111. */
  112. bool 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]);
  113. /**
  114. * Add a serial number to the CRL list
  115. *
  116. * @param serialNo Serial number of certificate to revoke
  117. */
  118. void addCRLCertificate(const uint8_t serialNo[ZT_SHA384_DIGEST_SIZE]);
  119. /**
  120. * Marshal this certificate in binary form
  121. *
  122. * The internal encoding used here is Dictionary to permit easy
  123. * extensibility.
  124. *
  125. * @param omitSignature If true omit the signature field (for signing and verification, default is false)
  126. * @return Marshaled certificate
  127. */
  128. Vector< uint8_t > encode(bool omitSignature = false) const;
  129. /**
  130. * Decode this certificate from marshaled bytes.
  131. *
  132. * @param data Marshalled certificate
  133. * @param len Length of marshalled certificate
  134. * @return True if input is valid and was unmarshalled (signature is NOT checked)
  135. */
  136. bool decode(const void *data, unsigned int len);
  137. /**
  138. * Sign this certificate (and also fill in serialNo).
  139. *
  140. * @param issuer Issuer identity (must have secret key)
  141. * @return True on success
  142. */
  143. bool sign(const Identity &issuer);
  144. /**
  145. * Verify self-contained signatures and validity of certificate structure
  146. *
  147. * This doesn't check the entire certificate chain, just the validity of
  148. * the certificate's internal signature and fields.
  149. *
  150. * @return OK (0) or error code indicating why certificate failed verification.
  151. */
  152. ZT_CertificateError verify() const;
  153. /**
  154. * Create a CSR that encodes the subject of this certificate
  155. *
  156. * @param s Subject to encode
  157. * @param uniqueId Unique ID to sign subject with or NULL if none
  158. * @param uniqueIdSize Size of unique ID or 0 if none
  159. * @param uniqueIdPrivate Unique ID private key for proof signature or NULL if none
  160. * @param uniqueIdPrivateSize Size of unique ID private key
  161. * @return Encoded subject (without any unique ID fields) or empty vector on error
  162. */
  163. static Vector< uint8_t > createCSR(const ZT_Certificate_Subject &s, const void *uniqueId, unsigned int uniqueIdSize, const void *uniqueIdPrivate, unsigned int uniqueIdPrivateSize);
  164. /**
  165. * Create a subject unique ID and corresponding private key required for use
  166. *
  167. * @param uniqueId Buffer to receive unique ID
  168. * @param uniqueIdPrivate Buffer to receive private key
  169. */
  170. static ZT_INLINE void createSubjectUniqueId(uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE], uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE])
  171. {
  172. uniqueId[0] = ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384;
  173. ECC384GenerateKey(uniqueId + 1, uniqueIdPrivate);
  174. }
  175. ZT_INLINE unsigned long hashCode() const noexcept
  176. { return (unsigned long)Utils::loadMachineEndian< uint32_t >(this->serialNo); }
  177. ZT_INLINE bool operator==(const ZT_Certificate &c) const noexcept
  178. { return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) == 0; }
  179. ZT_INLINE bool operator!=(const ZT_Certificate &c) const noexcept
  180. { return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) != 0; }
  181. ZT_INLINE bool operator<(const ZT_Certificate &c) const noexcept
  182. { return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) < 0; }
  183. ZT_INLINE bool operator<=(const ZT_Certificate &c) const noexcept
  184. { return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) <= 0; }
  185. ZT_INLINE bool operator>(const ZT_Certificate &c) const noexcept
  186. { return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) > 0; }
  187. ZT_INLINE bool operator>=(const ZT_Certificate &c) const noexcept
  188. { return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) >= 0; }
  189. private:
  190. void m_clear();
  191. static void m_encodeSubject(const ZT_Certificate_Subject &s, Dictionary &d, bool omitUniqueIdProofSignature);
  192. // These hold any identity or locator objects that are owned by and should
  193. // be deleted with this certificate. Lists are used so the pointers never
  194. // change.
  195. ForwardList< Identity > m_identities;
  196. ForwardList< Locator > m_locators;
  197. ForwardList< String > m_strings;
  198. ForwardList< SHA384Hash > m_serials;
  199. // These are stored in a vector because the memory needs to be contiguous.
  200. Vector< ZT_Certificate_Identity > m_subjectIdentities;
  201. Vector< ZT_Certificate_Network > m_subjectNetworks;
  202. Vector< const uint8_t * > m_subjectCertificates;
  203. Vector< const char * > m_updateUrls;
  204. Vector< uint8_t > m_extendedAttributes;
  205. Vector< uint8_t > m_subjectUniqueId;
  206. Vector< uint8_t > m_subjectUniqueIdProofSignature;
  207. Vector< const uint8_t * > m_crl;
  208. Vector< uint8_t > m_signature;
  209. std::atomic< int > __refCount;
  210. };
  211. } // namespace ZeroTier
  212. #endif