mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-26 08:57:26 +02:00
247 lines
8 KiB
C++
247 lines
8 KiB
C++
/*
|
|
* Copyright (c)2013-2020 ZeroTier, Inc.
|
|
*
|
|
* Use of this software is governed by the Business Source License included
|
|
* in the LICENSE.TXT file in the project's root directory.
|
|
*
|
|
* Change Date: 2025-01-01
|
|
*
|
|
* On the date above, in accordance with the Business Source License, use
|
|
* of this software will be governed by version 2.0 of the Apache License.
|
|
*/
|
|
/****/
|
|
|
|
#ifndef ZT_CERTIFICATE_HPP
|
|
#define ZT_CERTIFICATE_HPP
|
|
|
|
#include "Constants.hpp"
|
|
#include "SHA512.hpp"
|
|
#include "C25519.hpp"
|
|
#include "ECC384.hpp"
|
|
#include "SharedPtr.hpp"
|
|
#include "Identity.hpp"
|
|
#include "Locator.hpp"
|
|
#include "Dictionary.hpp"
|
|
#include "Utils.hpp"
|
|
#include "Blob.hpp"
|
|
#include "Containers.hpp"
|
|
|
|
namespace ZeroTier {
|
|
|
|
/**
|
|
* Certificate describing and grouping a set of objects.
|
|
*
|
|
* This is a wrapper around the straight C ZT_IdentificationCertificate and
|
|
* handles allocating memory for objects added via addXXX() and disposing of
|
|
* them on delete. If pointers in the underlying C struct are set manually,
|
|
* their memory is not freed on delete. Use the addXXX() methods to fill
|
|
* out this structure in C++ code.
|
|
*
|
|
* The serialNo field is filled in automatically by sign() and decode(), so
|
|
* it can be left undefined when building certificates. It contains a SHA384
|
|
* hash of the certificate marshalled without the signature field.
|
|
*
|
|
* The hashCode() method and comparison operators compare the serial number
|
|
* field, so these will not work correctly before sign() or decode() is
|
|
* called.
|
|
*/
|
|
class Certificate : public ZT_Certificate
|
|
{
|
|
friend class SharedPtr< Certificate >;
|
|
friend class SharedPtr< const Certificate >;
|
|
|
|
public:
|
|
Certificate() noexcept;
|
|
Certificate(const ZT_Certificate &apiCert);
|
|
Certificate(const Certificate &cert);
|
|
~Certificate();
|
|
|
|
Certificate &operator=(const ZT_Certificate &cert);
|
|
|
|
ZT_INLINE Certificate &operator=(const Certificate &cert)
|
|
{
|
|
if (likely(&cert != this)) {
|
|
const ZT_Certificate *const sup = &cert;
|
|
*this = *sup;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Add a subject node/identity without a locator
|
|
*
|
|
* @param id Identity
|
|
* @return Pointer to C struct
|
|
*/
|
|
ZT_Certificate_Identity *addSubjectIdentity(const Identity &id);
|
|
|
|
/**
|
|
* Add a subject node/identity with a locator
|
|
*
|
|
* @param id Identity
|
|
* @param loc Locator signed by identity (signature is NOT checked here)
|
|
* @return Pointer to C struct
|
|
*/
|
|
ZT_Certificate_Identity *addSubjectIdentity(const Identity &id, const Locator &loc);
|
|
|
|
/**
|
|
* Add a subject network
|
|
*
|
|
* @param id Network ID
|
|
* @param controller Network controller's full fingerprint
|
|
* @return Pointer to C struct
|
|
*/
|
|
ZT_Certificate_Network *addSubjectNetwork(const uint64_t id, const ZT_Fingerprint &controller);
|
|
|
|
/**
|
|
* Add a subject certificate (by its serial number)
|
|
*
|
|
* @param serialNo 384-bit serial number
|
|
*/
|
|
void addSubjectCertificate(const uint8_t serialNo[ZT_SHA384_DIGEST_SIZE]);
|
|
|
|
/**
|
|
* Add an update URL to the updateUrls list
|
|
*
|
|
* @param url Update URL
|
|
*/
|
|
void addSubjectUpdateUrl(const char *url);
|
|
|
|
/**
|
|
* Set the extended attributes of this certificate
|
|
*
|
|
* @param x Extended attributes (set by issuer)
|
|
*/
|
|
void setExtendedAttributes(const Dictionary &x);
|
|
|
|
/**
|
|
* Set the unique ID of this certificate's subject
|
|
*
|
|
* This must be done after all other fields in the subject are set.
|
|
*
|
|
* @param uniqueId Unique ID
|
|
* @param uniqueIdPrivate Private key associated with unique ID to prove ownership of it
|
|
* @return True if successful
|
|
*/
|
|
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]);
|
|
|
|
/**
|
|
* Add a serial number to the CRL list
|
|
*
|
|
* @param serialNo Serial number of certificate to revoke
|
|
*/
|
|
void addCRLCertificate(const uint8_t serialNo[ZT_SHA384_DIGEST_SIZE]);
|
|
|
|
/**
|
|
* Marshal this certificate in binary form
|
|
*
|
|
* The internal encoding used here is Dictionary to permit easy
|
|
* extensibility.
|
|
*
|
|
* @param omitSignature If true omit the signature field (for signing and verification, default is false)
|
|
* @return Marshaled certificate
|
|
*/
|
|
Vector< uint8_t > encode(bool omitSignature = false) const;
|
|
|
|
/**
|
|
* Decode this certificate from marshaled bytes.
|
|
*
|
|
* @param data Marshalled certificate
|
|
* @param len Length of marshalled certificate
|
|
* @return True if input is valid and was unmarshalled (signature is NOT checked)
|
|
*/
|
|
bool decode(const void *data, unsigned int len);
|
|
|
|
/**
|
|
* Sign this certificate (and also fill in serialNo).
|
|
*
|
|
* @param issuer Issuer identity (must have secret key)
|
|
* @return True on success
|
|
*/
|
|
bool sign(const Identity &issuer);
|
|
|
|
/**
|
|
* Verify self-contained signatures and validity of certificate structure
|
|
*
|
|
* This doesn't check the entire certificate chain, just the validity of
|
|
* the certificate's internal signature and fields.
|
|
*
|
|
* @return OK (0) or error code indicating why certificate failed verification.
|
|
*/
|
|
ZT_CertificateError verify() const;
|
|
|
|
/**
|
|
* Create a CSR that encodes the subject of this certificate
|
|
*
|
|
* @param s Subject to encode
|
|
* @param uniqueId Unique ID to sign subject with or NULL if none
|
|
* @param uniqueIdSize Size of unique ID or 0 if none
|
|
* @param uniqueIdPrivate Unique ID private key for proof signature or NULL if none
|
|
* @param uniqueIdPrivateSize Size of unique ID private key
|
|
* @return Encoded subject (without any unique ID fields) or empty vector on error
|
|
*/
|
|
static Vector< uint8_t > createCSR(const ZT_Certificate_Subject &s, const void *uniqueId, unsigned int uniqueIdSize, const void *uniqueIdPrivate, unsigned int uniqueIdPrivateSize);
|
|
|
|
/**
|
|
* Create a subject unique ID and corresponding private key required for use
|
|
*
|
|
* @param uniqueId Buffer to receive unique ID
|
|
* @param uniqueIdPrivate Buffer to receive private key
|
|
*/
|
|
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])
|
|
{
|
|
uniqueId[0] = ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384;
|
|
ECC384GenerateKey(uniqueId + 1, uniqueIdPrivate);
|
|
}
|
|
|
|
ZT_INLINE unsigned long hashCode() const noexcept
|
|
{ return (unsigned long)Utils::loadMachineEndian< uint32_t >(this->serialNo); }
|
|
|
|
ZT_INLINE bool operator==(const ZT_Certificate &c) const noexcept
|
|
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) == 0; }
|
|
|
|
ZT_INLINE bool operator!=(const ZT_Certificate &c) const noexcept
|
|
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) != 0; }
|
|
|
|
ZT_INLINE bool operator<(const ZT_Certificate &c) const noexcept
|
|
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) < 0; }
|
|
|
|
ZT_INLINE bool operator<=(const ZT_Certificate &c) const noexcept
|
|
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) <= 0; }
|
|
|
|
ZT_INLINE bool operator>(const ZT_Certificate &c) const noexcept
|
|
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) > 0; }
|
|
|
|
ZT_INLINE bool operator>=(const ZT_Certificate &c) const noexcept
|
|
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) >= 0; }
|
|
|
|
private:
|
|
void m_clear();
|
|
|
|
static void m_encodeSubject(const ZT_Certificate_Subject &s, Dictionary &d, bool omitUniqueIdProofSignature);
|
|
|
|
// These hold any identity or locator objects that are owned by and should
|
|
// be deleted with this certificate. Lists are used so the pointers never
|
|
// change.
|
|
ForwardList< Identity > m_identities;
|
|
ForwardList< Locator > m_locators;
|
|
ForwardList< String > m_strings;
|
|
ForwardList< SHA384Hash > m_serials;
|
|
|
|
// These are stored in a vector because the memory needs to be contiguous.
|
|
Vector< ZT_Certificate_Identity > m_subjectIdentities;
|
|
Vector< ZT_Certificate_Network > m_subjectNetworks;
|
|
Vector< const uint8_t * > m_subjectCertificates;
|
|
Vector< const char * > m_updateUrls;
|
|
Vector< uint8_t > m_extendedAttributes;
|
|
Vector< uint8_t > m_subjectUniqueId;
|
|
Vector< uint8_t > m_subjectUniqueIdProofSignature;
|
|
Vector< const uint8_t * > m_crl;
|
|
Vector< uint8_t > m_signature;
|
|
|
|
std::atomic< int > __refCount;
|
|
};
|
|
|
|
} // namespace ZeroTier
|
|
|
|
#endif
|