mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 20:43:44 +02:00
Interim commit of some cert and cert testing work, also other cleanup in Utils.
This commit is contained in:
parent
5e1b7f2ba6
commit
73d0e2e7e0
11 changed files with 743 additions and 440 deletions
|
@ -80,6 +80,14 @@ Commands:
|
||||||
sign <identity> <file> Sign a file with an identity's key
|
sign <identity> <file> Sign a file with an identity's key
|
||||||
verify <identity> <file> <sig> Verify a signature
|
verify <identity> <file> <sig> Verify a signature
|
||||||
certificate <command> [args] - Certificate commands
|
certificate <command> [args] - Certificate commands
|
||||||
|
newid Create a new unique subject ID
|
||||||
|
newcsr <settings> Create a new CSR (signing request)
|
||||||
|
sign <crl path> <identity path> Sign a CRL and create a certificate
|
||||||
|
verify <certificate> Verify a certificate
|
||||||
|
show List certificate for current node
|
||||||
|
import <certificate> [<trust>] Import certificate into this node
|
||||||
|
export <serial> Export a certificate from this node
|
||||||
|
delete <serial> Delete certificate from this node
|
||||||
|
|
||||||
An <address> may be specified as a 10-digit short ZeroTier address, a
|
An <address> may be specified as a 10-digit short ZeroTier address, a
|
||||||
fingerprint containing both an address and a SHA384 hash, or an identity.
|
fingerprint containing both an address and a SHA384 hash, or an identity.
|
||||||
|
|
|
@ -30,6 +30,7 @@ void Certificate::clear()
|
||||||
m_subjectNetworks.clear();
|
m_subjectNetworks.clear();
|
||||||
m_updateUrls.clear();
|
m_updateUrls.clear();
|
||||||
m_subjectCertificates.clear();
|
m_subjectCertificates.clear();
|
||||||
|
m_extendedAttributes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Certificate &Certificate::operator=(const ZT_Certificate &apiCert)
|
Certificate &Certificate::operator=(const ZT_Certificate &apiCert)
|
||||||
|
@ -45,16 +46,23 @@ Certificate &Certificate::operator=(const Certificate &cert)
|
||||||
|
|
||||||
// Zero these since we must explicitly attach all the objects from
|
// Zero these since we must explicitly attach all the objects from
|
||||||
// the other certificate to copy them into our containers.
|
// the other certificate to copy them into our containers.
|
||||||
|
this->subject.identities = nullptr;
|
||||||
this->subject.identityCount = 0;
|
this->subject.identityCount = 0;
|
||||||
|
this->subject.networks = nullptr;
|
||||||
this->subject.networkCount = 0;
|
this->subject.networkCount = 0;
|
||||||
|
this->subject.certificates = nullptr;
|
||||||
this->subject.certificateCount = 0;
|
this->subject.certificateCount = 0;
|
||||||
|
this->subject.updateUrls = nullptr;
|
||||||
this->subject.updateUrlCount = 0;
|
this->subject.updateUrlCount = 0;
|
||||||
|
this->extendedAttributes = nullptr;
|
||||||
|
this->extendedAttributesSize = 0;
|
||||||
|
this->issuer = nullptr;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < cert.subject.identityCount; ++i) {
|
for (unsigned int i = 0; i < cert.subject.identityCount; ++i) {
|
||||||
if (cert.subject.identities[i].identity) {
|
if (cert.subject.identities[i].identity) {
|
||||||
if (cert.subject.identities[i].locator)
|
if (cert.subject.identities[i].locator)
|
||||||
addSubjectNode(*reinterpret_cast<const Identity *>(cert.subject.identities[i].identity), *reinterpret_cast<const Locator *>(cert.subject.identities[i].locator));
|
addSubjectIdentity(*reinterpret_cast<const Identity *>(cert.subject.identities[i].identity), *reinterpret_cast<const Locator *>(cert.subject.identities[i].locator));
|
||||||
else addSubjectNode(*reinterpret_cast<const Identity *>(cert.subject.identities[i].identity));
|
else addSubjectIdentity(*reinterpret_cast<const Identity *>(cert.subject.identities[i].identity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,10 +79,16 @@ Certificate &Certificate::operator=(const Certificate &cert)
|
||||||
if (cert.subject.updateUrls) {
|
if (cert.subject.updateUrls) {
|
||||||
for (unsigned int i = 0; i < cert.subject.updateUrlCount; ++i) {
|
for (unsigned int i = 0; i < cert.subject.updateUrlCount; ++i) {
|
||||||
if (cert.subject.updateUrls[i])
|
if (cert.subject.updateUrls[i])
|
||||||
addUpdateUrl(cert.subject.updateUrls[i]);
|
addSubjectUpdateUrl(cert.subject.updateUrls[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((cert.extendedAttributes) && (cert.extendedAttributesSize > 0)) {
|
||||||
|
m_extendedAttributes.assign(cert.extendedAttributes, cert.extendedAttributes + cert.extendedAttributesSize);
|
||||||
|
this->extendedAttributes = m_extendedAttributes.data();
|
||||||
|
this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size();
|
||||||
|
}
|
||||||
|
|
||||||
if (cert.issuer) {
|
if (cert.issuer) {
|
||||||
m_identities.push_back(*reinterpret_cast<const Identity *>(cert.issuer));
|
m_identities.push_back(*reinterpret_cast<const Identity *>(cert.issuer));
|
||||||
this->issuer = &(m_identities.back());
|
this->issuer = &(m_identities.back());
|
||||||
|
@ -83,7 +97,7 @@ Certificate &Certificate::operator=(const Certificate &cert)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_Certificate_Identity *Certificate::addSubjectNode(const Identity &id)
|
ZT_Certificate_Identity *Certificate::addSubjectIdentity(const Identity &id)
|
||||||
{
|
{
|
||||||
// Enlarge array of ZT_Certificate_Identity structs and set pointer to potentially reallocated array.
|
// Enlarge array of ZT_Certificate_Identity structs and set pointer to potentially reallocated array.
|
||||||
m_subjectIdentities.resize(++this->subject.identityCount);
|
m_subjectIdentities.resize(++this->subject.identityCount);
|
||||||
|
@ -99,10 +113,10 @@ ZT_Certificate_Identity *Certificate::addSubjectNode(const Identity &id)
|
||||||
return &(m_subjectIdentities.back());
|
return &(m_subjectIdentities.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_Certificate_Identity *Certificate::addSubjectNode(const Identity &id, const Locator &loc)
|
ZT_Certificate_Identity *Certificate::addSubjectIdentity(const Identity &id, const Locator &loc)
|
||||||
{
|
{
|
||||||
// Add identity as above.
|
// Add identity as above.
|
||||||
ZT_Certificate_Identity *const n = addSubjectNode(id);
|
ZT_Certificate_Identity *const n = addSubjectIdentity(id);
|
||||||
|
|
||||||
// Store local copy of locator.
|
// Store local copy of locator.
|
||||||
m_locators.push_back(loc);
|
m_locators.push_back(loc);
|
||||||
|
@ -138,7 +152,7 @@ void Certificate::addSubjectCertificate(const uint8_t serialNo[ZT_SHA384_DIGEST_
|
||||||
this->subject.certificates = m_subjectCertificates.data();
|
this->subject.certificates = m_subjectCertificates.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Certificate::addUpdateUrl(const char *url)
|
void Certificate::addSubjectUpdateUrl(const char *url)
|
||||||
{
|
{
|
||||||
// Store local copy of URL.
|
// Store local copy of URL.
|
||||||
m_strings.push_back(url);
|
m_strings.push_back(url);
|
||||||
|
@ -159,28 +173,44 @@ Vector< uint8_t > Certificate::encode(const bool omitSignature) const
|
||||||
// format. Custom packed formats are used for credentials as these are smaller
|
// format. Custom packed formats are used for credentials as these are smaller
|
||||||
// and faster to marshal/unmarshal.
|
// and faster to marshal/unmarshal.
|
||||||
|
|
||||||
d.add("f", this->flags);
|
if (this->flags != 0)
|
||||||
|
d.add("f", this->flags);
|
||||||
d.add("t", (uint64_t)this->timestamp);
|
d.add("t", (uint64_t)this->timestamp);
|
||||||
d.add("v0", (uint64_t)this->validity[0]);
|
d.add("v0", (uint64_t)this->validity[0]);
|
||||||
d.add("v1", (uint64_t)this->validity[1]);
|
d.add("v1", (uint64_t)this->validity[1]);
|
||||||
|
if ((this->extendedAttributes) && (this->extendedAttributesSize > 0))
|
||||||
|
d["x"].assign(this->extendedAttributes, this->extendedAttributes + this->extendedAttributesSize);
|
||||||
d.add("mP", (uint64_t)this->maxPathLength);
|
d.add("mP", (uint64_t)this->maxPathLength);
|
||||||
|
|
||||||
m_encodeSubject(d, false);
|
m_encodeSubject(this->subject, d, false);
|
||||||
|
|
||||||
if (this->issuer)
|
if (this->issuer)
|
||||||
d.addO("i", *reinterpret_cast<const Identity *>(this->issuer));
|
d.addO("i", *reinterpret_cast<const Identity *>(this->issuer));
|
||||||
|
|
||||||
d.add("iN.c", this->issuerName.country);
|
if (this->issuerName.country[0])
|
||||||
d.add("iN.o", this->issuerName.organization);
|
d.add("iN.c", this->issuerName.country);
|
||||||
d.add("iN.u", this->issuerName.unit);
|
if (this->issuerName.organization[0])
|
||||||
d.add("iN.l", this->issuerName.locality);
|
d.add("iN.o", this->issuerName.organization);
|
||||||
d.add("iN.p", this->issuerName.province);
|
if (this->issuerName.unit[0])
|
||||||
d.add("iN.sA", this->issuerName.streetAddress);
|
d.add("iN.u", this->issuerName.unit);
|
||||||
d.add("iN.pC", this->issuerName.postalCode);
|
if (this->issuerName.locality[0])
|
||||||
d.add("iN.cN", this->issuerName.commonName);
|
d.add("iN.l", this->issuerName.locality);
|
||||||
d.add("iN.sN", this->issuerName.serialNo);
|
if (this->issuerName.province[0])
|
||||||
d.add("iN.e", this->issuerName.email);
|
d.add("iN.p", this->issuerName.province);
|
||||||
d.add("iN.ur", this->issuerName.url);
|
if (this->issuerName.streetAddress[0])
|
||||||
|
d.add("iN.sA", this->issuerName.streetAddress);
|
||||||
|
if (this->issuerName.postalCode[0])
|
||||||
|
d.add("iN.pC", this->issuerName.postalCode);
|
||||||
|
if (this->issuerName.commonName[0])
|
||||||
|
d.add("iN.cN", this->issuerName.commonName);
|
||||||
|
if (this->issuerName.serialNo[0])
|
||||||
|
d.add("iN.sN", this->issuerName.serialNo);
|
||||||
|
if (this->issuerName.email[0])
|
||||||
|
d.add("iN.e", this->issuerName.email);
|
||||||
|
if (this->issuerName.url[0])
|
||||||
|
d.add("iN.ur", this->issuerName.url);
|
||||||
|
if (this->issuerName.host[0])
|
||||||
|
d.add("iN.h", this->issuerName.host);
|
||||||
|
|
||||||
if ((!omitSignature) && (this->signatureSize > 0) && (this->signatureSize <= sizeof(this->signature)))
|
if ((!omitSignature) && (this->signatureSize > 0) && (this->signatureSize <= sizeof(this->signature)))
|
||||||
d["si"].assign(this->signature, this->signature + this->signatureSize);
|
d["si"].assign(this->signature, this->signature + this->signatureSize);
|
||||||
|
@ -204,7 +234,11 @@ bool Certificate::decode(const Vector< uint8_t > &data)
|
||||||
this->validity[0] = (int64_t)d.getUI("v0");
|
this->validity[0] = (int64_t)d.getUI("v0");
|
||||||
this->validity[1] = (int64_t)d.getUI("v1");
|
this->validity[1] = (int64_t)d.getUI("v1");
|
||||||
this->maxPathLength = (unsigned int)d.getUI("mP");
|
this->maxPathLength = (unsigned int)d.getUI("mP");
|
||||||
|
m_extendedAttributes = d["x"];
|
||||||
|
if (!m_extendedAttributes.empty()) {
|
||||||
|
this->extendedAttributes = m_extendedAttributes.data();
|
||||||
|
this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size();
|
||||||
|
}
|
||||||
this->subject.timestamp = (int64_t)d.getUI("s.t");
|
this->subject.timestamp = (int64_t)d.getUI("s.t");
|
||||||
|
|
||||||
unsigned int cnt = (unsigned int)d.getUI("s.i$");
|
unsigned int cnt = (unsigned int)d.getUI("s.i$");
|
||||||
|
@ -220,9 +254,9 @@ bool Certificate::decode(const Vector< uint8_t > &data)
|
||||||
Locator loc;
|
Locator loc;
|
||||||
if (loc.unmarshal(locatorData.data(), (unsigned int)locatorData.size()) <= 0)
|
if (loc.unmarshal(locatorData.data(), (unsigned int)locatorData.size()) <= 0)
|
||||||
return false;
|
return false;
|
||||||
this->addSubjectNode(id, loc);
|
this->addSubjectIdentity(id, loc);
|
||||||
} else {
|
} else {
|
||||||
this->addSubjectNode(id);
|
this->addSubjectIdentity(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,6 +291,7 @@ bool Certificate::decode(const Vector< uint8_t > &data)
|
||||||
d.getS("s.n.pC", this->subject.name.postalCode, sizeof(this->subject.name.postalCode));
|
d.getS("s.n.pC", this->subject.name.postalCode, sizeof(this->subject.name.postalCode));
|
||||||
d.getS("s.n.e", this->subject.name.email, sizeof(this->subject.name.email));
|
d.getS("s.n.e", this->subject.name.email, sizeof(this->subject.name.email));
|
||||||
d.getS("s.n.ur", this->subject.name.url, sizeof(this->subject.name.url));
|
d.getS("s.n.ur", this->subject.name.url, sizeof(this->subject.name.url));
|
||||||
|
d.getS("s.n.h", this->subject.name.host, sizeof(this->subject.name.host));
|
||||||
|
|
||||||
const Vector< uint8_t > &issuerData = d["i"];
|
const Vector< uint8_t > &issuerData = d["i"];
|
||||||
if (!issuerData.empty()) {
|
if (!issuerData.empty()) {
|
||||||
|
@ -278,12 +313,13 @@ bool Certificate::decode(const Vector< uint8_t > &data)
|
||||||
d.getS("iN.pC", this->issuerName.postalCode, sizeof(this->issuerName.postalCode));
|
d.getS("iN.pC", this->issuerName.postalCode, sizeof(this->issuerName.postalCode));
|
||||||
d.getS("iN.e", this->issuerName.email, sizeof(this->issuerName.email));
|
d.getS("iN.e", this->issuerName.email, sizeof(this->issuerName.email));
|
||||||
d.getS("iN.ur", this->issuerName.url, sizeof(this->issuerName.url));
|
d.getS("iN.ur", this->issuerName.url, sizeof(this->issuerName.url));
|
||||||
|
d.getS("iN.h", this->issuerName.host, sizeof(this->issuerName.host));
|
||||||
|
|
||||||
cnt = (unsigned int)d.getUI("u$");
|
cnt = (unsigned int)d.getUI("u$");
|
||||||
for (unsigned int i = 0; i < cnt; ++i) {
|
for (unsigned int i = 0; i < cnt; ++i) {
|
||||||
const char *const url = d.getS(Dictionary::arraySubscript(tmp, "u$", i), tmp2, sizeof(tmp2));
|
const char *const url = d.getS(Dictionary::arraySubscript(tmp, "u$", i), tmp2, sizeof(tmp2));
|
||||||
if (url)
|
if (url)
|
||||||
addUpdateUrl(tmp2);
|
addSubjectUpdateUrl(tmp2);
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +362,7 @@ ZT_CertificateError Certificate::verify() const
|
||||||
(this->subject.uniqueId[0] != ZT_CERTIFICATE_UNIQUE_ID_PUBLIC_KEY_TYPE_NIST_P_384))
|
(this->subject.uniqueId[0] != ZT_CERTIFICATE_UNIQUE_ID_PUBLIC_KEY_TYPE_NIST_P_384))
|
||||||
return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
|
return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
|
||||||
Dictionary tmp;
|
Dictionary tmp;
|
||||||
m_encodeSubject(tmp, true);
|
m_encodeSubject(this->subject, tmp, true);
|
||||||
Vector< uint8_t > enc;
|
Vector< uint8_t > enc;
|
||||||
tmp.encode(enc);
|
tmp.encode(enc);
|
||||||
uint8_t h[ZT_SHA384_DIGEST_SIZE];
|
uint8_t h[ZT_SHA384_DIGEST_SIZE];
|
||||||
|
@ -368,55 +404,86 @@ ZT_CertificateError Certificate::verify() const
|
||||||
return ZT_CERTIFICATE_ERROR_NONE;
|
return ZT_CERTIFICATE_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Certificate::m_encodeSubject(Dictionary &d, bool omitUniqueIdProofSignature) const
|
bool Certificate::setSubjectUniqueId(ZT_Certificate_Subject &s, const uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384], const uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_PRIVATE_KEY_SIZE_TYPE_NIST_P_384])
|
||||||
|
{
|
||||||
|
Utils::copy<ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384>(s.uniqueId, uniqueId);
|
||||||
|
s.uniqueIdSize = ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384;
|
||||||
|
|
||||||
|
Dictionary d;
|
||||||
|
m_encodeSubject(s, d, true);
|
||||||
|
Vector< uint8_t > enc;
|
||||||
|
d.encode(enc);
|
||||||
|
uint8_t h[ZT_ECC384_SIGNATURE_HASH_SIZE];
|
||||||
|
SHA384(h, enc.data(), (unsigned int)enc.size());
|
||||||
|
|
||||||
|
ECC384ECDSASign(uniqueIdPrivate, h, s.uniqueIdProofSignature);
|
||||||
|
s.uniqueIdProofSignatureSize = ZT_ECC384_SIGNATURE_SIZE;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Certificate::m_encodeSubject(const ZT_Certificate_Subject &s, Dictionary &d, bool omitUniqueIdProofSignature)
|
||||||
{
|
{
|
||||||
char tmp[256];
|
char tmp[256];
|
||||||
|
|
||||||
d.add("s.t", (uint64_t)this->subject.timestamp);
|
d.add("s.t", (uint64_t)s.timestamp);
|
||||||
|
|
||||||
d.add("s.i$", (uint64_t)this->subject.identityCount);
|
d.add("s.i$", (uint64_t)s.identityCount);
|
||||||
for (unsigned int i = 0; i < this->subject.identityCount; ++i) {
|
for (unsigned int i = 0; i < s.identityCount; ++i) {
|
||||||
if (this->subject.identities[i].identity)
|
if (s.identities[i].identity)
|
||||||
d.addO(Dictionary::arraySubscript(tmp, "s.i$.i", i), *reinterpret_cast<const Identity *>(this->subject.identities[i].identity));
|
d.addO(Dictionary::arraySubscript(tmp, "s.i$.i", i), *reinterpret_cast<const Identity *>(s.identities[i].identity));
|
||||||
if (this->subject.identities[i].locator)
|
if (s.identities[i].locator)
|
||||||
d.addO(Dictionary::arraySubscript(tmp, "s.i$.l", i), *reinterpret_cast<const Locator *>(this->subject.identities[i].locator));
|
d.addO(Dictionary::arraySubscript(tmp, "s.i$.l", i), *reinterpret_cast<const Locator *>(s.identities[i].locator));
|
||||||
}
|
}
|
||||||
|
|
||||||
d.add("s.n$", (uint64_t)this->subject.networkCount);
|
d.add("s.n$", (uint64_t)s.networkCount);
|
||||||
for (unsigned int i = 0; i < this->subject.networkCount; ++i) {
|
for (unsigned int i = 0; i < s.networkCount; ++i) {
|
||||||
d.add(Dictionary::arraySubscript(tmp, "s.n$.i", i), this->subject.networks[i].id);
|
d.add(Dictionary::arraySubscript(tmp, "s.n$.i", i), s.networks[i].id);
|
||||||
Fingerprint fp(this->subject.networks[i].controller);
|
Fingerprint fp(s.networks[i].controller);
|
||||||
d.addO(Dictionary::arraySubscript(tmp, "s.n$.c", i), fp);
|
d.addO(Dictionary::arraySubscript(tmp, "s.n$.c", i), fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
d.add("s.c$", (uint64_t)this->subject.certificateCount);
|
d.add("s.c$", (uint64_t)s.certificateCount);
|
||||||
for (unsigned int i = 0; i < this->subject.certificateCount; ++i) {
|
for (unsigned int i = 0; i < s.certificateCount; ++i) {
|
||||||
if (this->subject.certificates[i])
|
if (s.certificates[i])
|
||||||
d[Dictionary::arraySubscript(tmp, "s.c$", i)].assign(this->subject.certificates[i], this->subject.certificates[i] + ZT_SHA384_DIGEST_SIZE);
|
d[Dictionary::arraySubscript(tmp, "s.c$", i)].assign(s.certificates[i], s.certificates[i] + ZT_SHA384_DIGEST_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
d.add("s.u$", (uint64_t)this->subject.updateUrlCount);
|
d.add("s.u$", (uint64_t)s.updateUrlCount);
|
||||||
if (this->subject.updateUrls) {
|
if (s.updateUrls) {
|
||||||
for (unsigned int i = 0; i < this->subject.updateUrlCount; ++i)
|
for (unsigned int i = 0; i < s.updateUrlCount; ++i)
|
||||||
d.add(Dictionary::arraySubscript(tmp, "s.u$", i), this->subject.updateUrls[i]);
|
d.add(Dictionary::arraySubscript(tmp, "s.u$", i), s.updateUrls[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
d.add("s.n.c", this->subject.name.country);
|
if (s.name.country[0])
|
||||||
d.add("s.n.o", this->subject.name.organization);
|
d.add("s.n.c", s.name.country);
|
||||||
d.add("s.n.u", this->subject.name.unit);
|
if (s.name.organization[0])
|
||||||
d.add("s.n.l", this->subject.name.locality);
|
d.add("s.n.o", s.name.organization);
|
||||||
d.add("s.n.p", this->subject.name.province);
|
if (s.name.unit[0])
|
||||||
d.add("s.n.sA", this->subject.name.streetAddress);
|
d.add("s.n.u", s.name.unit);
|
||||||
d.add("s.n.pC", this->subject.name.postalCode);
|
if (s.name.locality[0])
|
||||||
d.add("s.n.cN", this->subject.name.commonName);
|
d.add("s.n.l", s.name.locality);
|
||||||
d.add("s.n.sN", this->subject.name.serialNo);
|
if (s.name.province[0])
|
||||||
d.add("s.n.e", this->subject.name.email);
|
d.add("s.n.p", s.name.province);
|
||||||
d.add("s.n.ur", this->subject.name.url);
|
if (s.name.streetAddress[0])
|
||||||
|
d.add("s.n.sA", s.name.streetAddress);
|
||||||
|
if (s.name.postalCode[0])
|
||||||
|
d.add("s.n.pC", s.name.postalCode);
|
||||||
|
if (s.name.commonName[0])
|
||||||
|
d.add("s.n.cN", s.name.commonName);
|
||||||
|
if (s.name.serialNo[0])
|
||||||
|
d.add("s.n.sN", s.name.serialNo);
|
||||||
|
if (s.name.email[0])
|
||||||
|
d.add("s.n.e", s.name.email);
|
||||||
|
if (s.name.url[0])
|
||||||
|
d.add("s.n.ur", s.name.url);
|
||||||
|
if (s.name.host[0])
|
||||||
|
d.add("s.n.h", s.name.host);
|
||||||
|
|
||||||
if ((this->subject.uniqueIdSize > 0) && (this->subject.uniqueIdSize <= ZT_CERTIFICATE_MAX_UNIQUE_ID_SIZE))
|
if ((s.uniqueIdSize > 0) && (s.uniqueIdSize <= ZT_CERTIFICATE_MAX_UNIQUE_ID_SIZE))
|
||||||
d["s.uI"].assign(this->subject.uniqueId, this->subject.uniqueId + this->subject.uniqueIdSize);
|
d["s.uI"].assign(s.uniqueId, s.uniqueId + s.uniqueIdSize);
|
||||||
if ((!omitUniqueIdProofSignature) && (this->subject.uniqueIdProofSignatureSize > 0) && (this->subject.uniqueIdProofSignatureSize <= ZT_CERTIFICATE_MAX_SIGNATURE_SIZE))
|
if ((!omitUniqueIdProofSignature) && (s.uniqueIdProofSignatureSize > 0) && (s.uniqueIdProofSignatureSize <= ZT_CERTIFICATE_MAX_SIGNATURE_SIZE))
|
||||||
d["s.uS"].assign(this->subject.uniqueIdProofSignature, this->subject.uniqueIdProofSignature + this->subject.uniqueIdProofSignatureSize);
|
d["s.uS"].assign(s.uniqueIdProofSignature, s.uniqueIdProofSignature + s.uniqueIdProofSignatureSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -74,7 +74,7 @@ public:
|
||||||
* @param id Identity
|
* @param id Identity
|
||||||
* @return Pointer to C struct
|
* @return Pointer to C struct
|
||||||
*/
|
*/
|
||||||
ZT_Certificate_Identity *addSubjectNode(const Identity &id);
|
ZT_Certificate_Identity *addSubjectIdentity(const Identity &id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a subject node/identity with a locator
|
* Add a subject node/identity with a locator
|
||||||
|
@ -83,7 +83,7 @@ public:
|
||||||
* @param loc Locator signed by identity (signature is NOT checked here)
|
* @param loc Locator signed by identity (signature is NOT checked here)
|
||||||
* @return Pointer to C struct
|
* @return Pointer to C struct
|
||||||
*/
|
*/
|
||||||
ZT_Certificate_Identity *addSubjectNode(const Identity &id, const Locator &loc);
|
ZT_Certificate_Identity *addSubjectIdentity(const Identity &id, const Locator &loc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a subject network
|
* Add a subject network
|
||||||
|
@ -106,7 +106,20 @@ public:
|
||||||
*
|
*
|
||||||
* @param url Update URL
|
* @param url Update URL
|
||||||
*/
|
*/
|
||||||
void addUpdateUrl(const char *url);
|
void addSubjectUpdateUrl(const char *url);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the extended attributes of this certificate
|
||||||
|
*
|
||||||
|
* @param x Extended attributes (set by issuer)
|
||||||
|
*/
|
||||||
|
ZT_INLINE void setExtendedAttributes(const Dictionary &x)
|
||||||
|
{
|
||||||
|
m_extendedAttributes.clear();
|
||||||
|
x.encode(m_extendedAttributes);
|
||||||
|
this->extendedAttributes = m_extendedAttributes.data();
|
||||||
|
this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marshal this certificate in binary form
|
* Marshal this certificate in binary form
|
||||||
|
@ -145,6 +158,28 @@ public:
|
||||||
*/
|
*/
|
||||||
ZT_CertificateError verify() const;
|
ZT_CertificateError verify() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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_SIZE_TYPE_NIST_P_384], uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_PRIVATE_KEY_SIZE_TYPE_NIST_P_384])
|
||||||
|
{
|
||||||
|
uniqueId[0] = ZT_CERTIFICATE_UNIQUE_ID_PUBLIC_KEY_TYPE_NIST_P_384;
|
||||||
|
ECC384GenerateKey(uniqueId + 1, uniqueIdPrivate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the unique ID and unique ID proof signature fields in a subject.
|
||||||
|
*
|
||||||
|
* @param s Subject to set
|
||||||
|
* @param uniqueId Unique ID (public)
|
||||||
|
* @param uniqueIdPrivate Unique ID private key
|
||||||
|
* @return True on success
|
||||||
|
*/
|
||||||
|
static bool setSubjectUniqueId(ZT_Certificate_Subject &s, const uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384], const uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_PRIVATE_KEY_SIZE_TYPE_NIST_P_384]);
|
||||||
|
|
||||||
ZT_INLINE unsigned long hashCode() const noexcept
|
ZT_INLINE unsigned long hashCode() const noexcept
|
||||||
{ return (unsigned long)Utils::loadAsIsEndian< uint32_t >(this->serialNo); }
|
{ return (unsigned long)Utils::loadAsIsEndian< uint32_t >(this->serialNo); }
|
||||||
|
|
||||||
|
@ -162,7 +197,7 @@ public:
|
||||||
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) >= 0; }
|
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) >= 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void m_encodeSubject(Dictionary &d, bool omitUniqueIdProofSignature) const;
|
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
|
// 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
|
// be deleted with this certificate. Lists are used so the pointers never
|
||||||
|
@ -177,6 +212,7 @@ private:
|
||||||
Vector< ZT_Certificate_Network > m_subjectNetworks;
|
Vector< ZT_Certificate_Network > m_subjectNetworks;
|
||||||
Vector< const uint8_t * > m_subjectCertificates;
|
Vector< const uint8_t * > m_subjectCertificates;
|
||||||
Vector< const char * > m_updateUrls;
|
Vector< const char * > m_updateUrls;
|
||||||
|
Vector< uint8_t > m_extendedAttributes;
|
||||||
|
|
||||||
std::atomic<int> __refCount;
|
std::atomic<int> __refCount;
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,8 +36,8 @@
|
||||||
#if ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX > ZT_BUF_MEM_SIZE
|
#if ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX > ZT_BUF_MEM_SIZE
|
||||||
#error ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX exceeds maximum buffer size
|
#error ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX exceeds maximum buffer size
|
||||||
#endif
|
#endif
|
||||||
#if ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX > ZT_BUF_MEM_SIZE
|
#if ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX > ZT_BUF_MEM_SIZE
|
||||||
#error ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX exceeds maximum buffer size
|
#error ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX exceeds maximum buffer size
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
@ -83,7 +83,7 @@ Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,
|
||||||
return Credential::VERIFY_NEED_IDENTITY;
|
return Credential::VERIFY_NEED_IDENTITY;
|
||||||
|
|
||||||
// Now verify the controller's signature.
|
// Now verify the controller's signature.
|
||||||
uint64_t buf[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX / 8];
|
uint64_t buf[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX / 8];
|
||||||
const unsigned int bufSize = credential.m_fillSigningBuf(buf);
|
const unsigned int bufSize = credential.m_fillSigningBuf(buf);
|
||||||
return peer->identity().verify(buf, bufSize, credential.m_signature, credential.m_signatureLength) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE;
|
return peer->identity().verify(buf, bufSize, credential.m_signature, credential.m_signatureLength) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,15 +115,22 @@ char *Dictionary::getS(const char *k, char *v, const unsigned int cap) const
|
||||||
if (cap == 0) // sanity check
|
if (cap == 0) // sanity check
|
||||||
return v;
|
return v;
|
||||||
const Vector< uint8_t > &e = (*this)[k];
|
const Vector< uint8_t > &e = (*this)[k];
|
||||||
|
if (e.empty()) {
|
||||||
|
v[0] = 0;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
const unsigned int last = cap - 1;
|
const unsigned int last = cap - 1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((i == last) || (i >= (unsigned int)e.size()))
|
if ((i >= last) || (i >= (unsigned int)e.size())) {
|
||||||
|
v[i] = 0;
|
||||||
break;
|
break;
|
||||||
v[i] = (char)e[i];
|
}
|
||||||
|
if ((v[i] = (char)e[i]) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
v[i] = 0;
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,17 @@ public:
|
||||||
int marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], bool excludeSignature = false) const noexcept;
|
int marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], bool excludeSignature = false) const noexcept;
|
||||||
int unmarshal(const uint8_t *data, int len) noexcept;
|
int unmarshal(const uint8_t *data, int len) noexcept;
|
||||||
|
|
||||||
|
ZT_INLINE bool operator==(const Locator &l) const noexcept
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
(m_ts == l.m_ts) &&
|
||||||
|
(m_signer == l.m_signer) &&
|
||||||
|
(m_endpoints == l.m_endpoints) &&
|
||||||
|
(m_signature == l.m_signature));
|
||||||
|
}
|
||||||
|
ZT_INLINE bool operator!=(const Locator &l) const noexcept
|
||||||
|
{ return !(*this == l); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int64_t m_ts;
|
int64_t m_ts;
|
||||||
Fingerprint m_signer;
|
Fingerprint m_signer;
|
||||||
|
|
|
@ -37,10 +37,10 @@ bool MembershipCredential::agreesWith(const MembershipCredential &other) const n
|
||||||
}
|
}
|
||||||
|
|
||||||
// us <> them
|
// us <> them
|
||||||
for (FCV<p_Qualifier, ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(m_additionalQualifiers.begin());i != m_additionalQualifiers.end();++i) {
|
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(m_additionalQualifiers.begin()); i != m_additionalQualifiers.end(); ++i) {
|
||||||
if (i->delta != 0xffffffffffffffffULL) {
|
if (i->delta != 0xffffffffffffffffULL) {
|
||||||
const uint64_t *v2 = nullptr;
|
const uint64_t *v2 = nullptr;
|
||||||
for (FCV<p_Qualifier, ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(other.m_additionalQualifiers.begin());j != other.m_additionalQualifiers.end();++i) {
|
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(other.m_additionalQualifiers.begin()); j != other.m_additionalQualifiers.end(); ++i) {
|
||||||
if (j->id == i->id) {
|
if (j->id == i->id) {
|
||||||
v2 = &(j->value);
|
v2 = &(j->value);
|
||||||
break;
|
break;
|
||||||
|
@ -59,10 +59,10 @@ bool MembershipCredential::agreesWith(const MembershipCredential &other) const n
|
||||||
}
|
}
|
||||||
|
|
||||||
// them <> us (we need a second pass in case they have qualifiers we don't or vice versa)
|
// them <> us (we need a second pass in case they have qualifiers we don't or vice versa)
|
||||||
for (FCV<p_Qualifier, ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(other.m_additionalQualifiers.begin());i != other.m_additionalQualifiers.end();++i) {
|
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(other.m_additionalQualifiers.begin()); i != other.m_additionalQualifiers.end(); ++i) {
|
||||||
if (i->delta != 0xffffffffffffffffULL) {
|
if (i->delta != 0xffffffffffffffffULL) {
|
||||||
const uint64_t *v2 = nullptr;
|
const uint64_t *v2 = nullptr;
|
||||||
for (FCV<p_Qualifier, ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(m_additionalQualifiers.begin());j != m_additionalQualifiers.end();++i) {
|
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(m_additionalQualifiers.begin()); j != m_additionalQualifiers.end(); ++i) {
|
||||||
if (j->id == i->id) {
|
if (j->id == i->id) {
|
||||||
v2 = &(j->value);
|
v2 = &(j->value);
|
||||||
break;
|
break;
|
||||||
|
@ -88,13 +88,13 @@ bool MembershipCredential::agreesWith(const MembershipCredential &other) const n
|
||||||
bool MembershipCredential::sign(const Identity &with) noexcept
|
bool MembershipCredential::sign(const Identity &with) noexcept
|
||||||
{
|
{
|
||||||
m_signedBy = with.address();
|
m_signedBy = with.address();
|
||||||
uint64_t buf[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX / 8];
|
uint64_t buf[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX / 8];
|
||||||
const unsigned int bufSize = m_fillSigningBuf(buf);
|
const unsigned int bufSize = m_fillSigningBuf(buf);
|
||||||
m_signatureLength = with.sign(buf, bufSize, m_signature, sizeof(m_signature));
|
m_signatureLength = with.sign(buf, bufSize, m_signature, sizeof(m_signature));
|
||||||
return m_signatureLength > 0;
|
return m_signatureLength > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MembershipCredential::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX], const bool v2) const noexcept
|
int MembershipCredential::marshal(uint8_t data[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX], const bool v2) const noexcept
|
||||||
{
|
{
|
||||||
data[0] = v2 ? 2 : 1;
|
data[0] = v2 ? 2 : 1;
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ int MembershipCredential::unmarshal(const uint8_t *data, int len) noexcept
|
||||||
TriviallyCopyable::memoryZero(this);
|
TriviallyCopyable::memoryZero(this);
|
||||||
|
|
||||||
const unsigned int numq = Utils::loadBigEndian<uint16_t>(data + 1);
|
const unsigned int numq = Utils::loadBigEndian<uint16_t>(data + 1);
|
||||||
if ((numq < 3) || (numq > (ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS + 3)))
|
if ((numq < 3) || (numq > (ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS + 3)))
|
||||||
return -1;
|
return -1;
|
||||||
int p = 3;
|
int p = 3;
|
||||||
for (unsigned int q = 0;q < numq;++q) {
|
for (unsigned int q = 0;q < numq;++q) {
|
||||||
|
@ -209,7 +209,7 @@ int MembershipCredential::unmarshal(const uint8_t *data, int len) noexcept
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (m_additionalQualifiers.size() >= ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS)
|
if (m_additionalQualifiers.size() >= ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS)
|
||||||
return -1;
|
return -1;
|
||||||
m_additionalQualifiers.push_back(p_Qualifier(id, value, delta));
|
m_additionalQualifiers.push_back(p_Qualifier(id, value, delta));
|
||||||
break;
|
break;
|
||||||
|
@ -287,7 +287,7 @@ unsigned int MembershipCredential::m_fillSigningBuf(uint64_t *buf) const noexcep
|
||||||
buf[p++] = informational;
|
buf[p++] = informational;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FCV<p_Qualifier, ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(m_additionalQualifiers.begin());i != m_additionalQualifiers.end();++i) { // NOLINT(modernize-loop-convert)
|
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(m_additionalQualifiers.begin()); i != m_additionalQualifiers.end(); ++i) { // NOLINT(modernize-loop-convert)
|
||||||
buf[p++] = Utils::hton(i->id);
|
buf[p++] = Utils::hton(i->id);
|
||||||
buf[p++] = Utils::hton(i->value);
|
buf[p++] = Utils::hton(i->value);
|
||||||
buf[p++] = Utils::hton(i->delta);
|
buf[p++] = Utils::hton(i->delta);
|
||||||
|
|
|
@ -32,10 +32,10 @@
|
||||||
#include "FCV.hpp"
|
#include "FCV.hpp"
|
||||||
|
|
||||||
// Maximum number of additional tuples beyond the standard always-present three.
|
// Maximum number of additional tuples beyond the standard always-present three.
|
||||||
#define ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS 8
|
#define ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS 8
|
||||||
|
|
||||||
// version + qualifier count + three required qualifiers + additional qualifiers +
|
// version + qualifier count + three required qualifiers + additional qualifiers +
|
||||||
#define ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX (1 + 2 + (3 * 3 * 8) + (ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS * 3 * 8) + 144 + 5 + 2 + 96)
|
#define ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX (1 + 2 + (3 * 3 * 8) + (ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS * 3 * 8) + 144 + 5 + 2 + 96)
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
@ -186,8 +186,8 @@ public:
|
||||||
|
|
||||||
// NOTE: right now we use v1 serialization format which works with both ZeroTier 1.x and 2.x. V2 format
|
// NOTE: right now we use v1 serialization format which works with both ZeroTier 1.x and 2.x. V2 format
|
||||||
// will be switched on once 1.x is pretty much dead and out of support.
|
// will be switched on once 1.x is pretty much dead and out of support.
|
||||||
static constexpr int marshalSizeMax() noexcept { return ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX; }
|
static constexpr int marshalSizeMax() noexcept { return ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX; }
|
||||||
int marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX],bool v2 = false) const noexcept;
|
int marshal(uint8_t data[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX], bool v2 = false) const noexcept;
|
||||||
int unmarshal(const uint8_t *data,int len) noexcept;
|
int unmarshal(const uint8_t *data,int len) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -203,7 +203,7 @@ private:
|
||||||
ZT_INLINE bool operator<(const p_Qualifier &q) const noexcept { return (id < q.id); } // sort order
|
ZT_INLINE bool operator<(const p_Qualifier &q) const noexcept { return (id < q.id); } // sort order
|
||||||
};
|
};
|
||||||
|
|
||||||
FCV<p_Qualifier,ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS> m_additionalQualifiers;
|
FCV<p_Qualifier,ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS> m_additionalQualifiers;
|
||||||
int64_t m_timestamp;
|
int64_t m_timestamp;
|
||||||
int64_t m_timestampMaxDelta;
|
int64_t m_timestampMaxDelta;
|
||||||
uint64_t m_networkId;
|
uint64_t m_networkId;
|
||||||
|
|
747
core/Tests.cpp
747
core/Tests.cpp
File diff suppressed because it is too large
Load diff
|
@ -702,58 +702,21 @@ static ZT_INLINE void storeLittleEndian(void *const p, const I i) noexcept
|
||||||
* @param dest Destination memory
|
* @param dest Destination memory
|
||||||
* @param src Source memory
|
* @param src Source memory
|
||||||
*/
|
*/
|
||||||
template< unsigned int L >
|
template< unsigned long L >
|
||||||
static ZT_INLINE void copy(void *const dest, const void *const src) noexcept
|
static ZT_INLINE void copy(void *dest, const void *src) noexcept
|
||||||
{
|
{
|
||||||
#ifdef ZT_ARCH_X64
|
#if defined(ZT_ARCH_X64) && defined(__GNUC__)
|
||||||
uint8_t *volatile d = reinterpret_cast<uint8_t *>(dest);
|
unsigned long l = L;
|
||||||
const uint8_t *s = reinterpret_cast<const uint8_t *>(src);
|
asm volatile ("rep movsb"
|
||||||
for (unsigned int i = 0; i < (L >> 6U); ++i) {
|
: "=D" (dest),
|
||||||
__m128i x0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s));
|
"=S" (src),
|
||||||
__m128i x1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s + 16));
|
"=c" (l)
|
||||||
__m128i x2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s + 32));
|
: "0" (dest),
|
||||||
__m128i x3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s + 48));
|
"1" (src),
|
||||||
s += 64;
|
"2" (l)
|
||||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(d), x0);
|
: "memory");
|
||||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(d + 16), x1);
|
|
||||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(d + 32), x2);
|
|
||||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(d + 48), x3);
|
|
||||||
d += 64;
|
|
||||||
}
|
|
||||||
if ((L & 32U) != 0) {
|
|
||||||
__m128i x0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s));
|
|
||||||
__m128i x1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s + 16));
|
|
||||||
s += 32;
|
|
||||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(d), x0);
|
|
||||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(d + 16), x1);
|
|
||||||
d += 32;
|
|
||||||
}
|
|
||||||
if ((L & 16U) != 0) {
|
|
||||||
__m128i x0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s));
|
|
||||||
s += 16;
|
|
||||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(d), x0);
|
|
||||||
d += 16;
|
|
||||||
}
|
|
||||||
if ((L & 8U) != 0) {
|
|
||||||
*reinterpret_cast<volatile uint64_t *>(d) = *reinterpret_cast<const uint64_t *>(s);
|
|
||||||
s += 8;
|
|
||||||
d += 8;
|
|
||||||
}
|
|
||||||
if ((L & 4U) != 0) {
|
|
||||||
*reinterpret_cast<volatile uint32_t *>(d) = *reinterpret_cast<const uint32_t *>(s);
|
|
||||||
s += 4;
|
|
||||||
d += 4;
|
|
||||||
}
|
|
||||||
if ((L & 2U) != 0) {
|
|
||||||
*reinterpret_cast<volatile uint16_t *>(d) = *reinterpret_cast<const uint16_t *>(s);
|
|
||||||
s += 2;
|
|
||||||
d += 2;
|
|
||||||
}
|
|
||||||
if ((L & 1U) != 0) {
|
|
||||||
*d = *s;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
memcpy(dest,src,L);
|
memcpy(dest, src, L);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -764,8 +727,21 @@ static ZT_INLINE void copy(void *const dest, const void *const src) noexcept
|
||||||
* @param src Source memory
|
* @param src Source memory
|
||||||
* @param len Bytes to copy
|
* @param len Bytes to copy
|
||||||
*/
|
*/
|
||||||
static ZT_INLINE void copy(void *const dest, const void *const src, unsigned int len) noexcept
|
static ZT_INLINE void copy(void *dest, const void *src, unsigned long len) noexcept
|
||||||
{ memcpy(dest, src, len); }
|
{
|
||||||
|
#if defined(ZT_ARCH_X64) && defined(__GNUC__)
|
||||||
|
asm volatile ("rep movsb"
|
||||||
|
: "=D" (dest),
|
||||||
|
"=S" (src),
|
||||||
|
"=c" (len)
|
||||||
|
: "0" (dest),
|
||||||
|
"1" (src),
|
||||||
|
"2" (len)
|
||||||
|
: "memory");
|
||||||
|
#else
|
||||||
|
memcpy(dest, src, len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zero memory block whose size is known at compile time
|
* Zero memory block whose size is known at compile time
|
||||||
|
@ -773,7 +749,7 @@ static ZT_INLINE void copy(void *const dest, const void *const src, unsigned int
|
||||||
* @tparam L Size in bytes
|
* @tparam L Size in bytes
|
||||||
* @param dest Memory to zero
|
* @param dest Memory to zero
|
||||||
*/
|
*/
|
||||||
template< unsigned int L >
|
template< unsigned long L >
|
||||||
static ZT_INLINE void zero(void *const dest) noexcept
|
static ZT_INLINE void zero(void *const dest) noexcept
|
||||||
{ memset(dest, 0, L); }
|
{ memset(dest, 0, L); }
|
||||||
|
|
||||||
|
@ -783,7 +759,7 @@ static ZT_INLINE void zero(void *const dest) noexcept
|
||||||
* @param dest Memory to zero
|
* @param dest Memory to zero
|
||||||
* @param len Size in bytes
|
* @param len Size in bytes
|
||||||
*/
|
*/
|
||||||
static ZT_INLINE void zero(void *const dest, const unsigned int len) noexcept
|
static ZT_INLINE void zero(void *const dest, const unsigned long len) noexcept
|
||||||
{ memset(dest, 0, len); }
|
{ memset(dest, 0, len); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -323,6 +323,16 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
#define ZT_CERTIFICATE_UNIQUE_ID_PUBLIC_KEY_TYPE_NIST_P_384 1
|
#define ZT_CERTIFICATE_UNIQUE_ID_PUBLIC_KEY_TYPE_NIST_P_384 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of a unique ID of the given key type (with type prefix byte)
|
||||||
|
*/
|
||||||
|
#define ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384 50
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of the private key corresponding to a unique ID of the given type.
|
||||||
|
*/
|
||||||
|
#define ZT_CERTIFICATE_UNIQUE_ID_PRIVATE_KEY_SIZE_TYPE_NIST_P_384 48
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Errors returned by functions that verify or handle certificates.
|
* Errors returned by functions that verify or handle certificates.
|
||||||
*/
|
*/
|
||||||
|
@ -368,24 +378,22 @@ enum ZT_CertificateError
|
||||||
*/
|
*/
|
||||||
ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF = -6,
|
ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF = -6,
|
||||||
|
|
||||||
/**
|
|
||||||
* Certificate is not appropriate for this use
|
|
||||||
*/
|
|
||||||
ZT_CERTIFICATE_ERROR_INAPPROPRIATE_FOR_USE = -7,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Certificate is missing a required field
|
* Certificate is missing a required field
|
||||||
*/
|
*/
|
||||||
ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS = -8,
|
ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS = -7,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Certificate is expired or not yet in effect
|
* Certificate is expired or not yet in effect
|
||||||
*/
|
*/
|
||||||
ZT_CERTIFICATE_ERROR_OUT_OF_VALID_TIME_WINDOW = -9
|
ZT_CERTIFICATE_ERROR_OUT_OF_VALID_TIME_WINDOW = -8
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about a real world entity.
|
* Information about a real world entity.
|
||||||
|
*
|
||||||
|
* These fields are all optional and are all taken from the
|
||||||
|
* most common fields present in X509 certificates.
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -400,6 +408,7 @@ typedef struct
|
||||||
char postalCode[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
|
char postalCode[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
|
||||||
char email[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
|
char email[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
|
||||||
char url[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
|
char url[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
|
||||||
|
char host[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
|
||||||
} ZT_Certificate_Name;
|
} ZT_Certificate_Name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -490,12 +499,28 @@ typedef struct
|
||||||
ZT_Certificate_Name name;
|
ZT_Certificate_Name name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unique ID, which can be a public key prefixed by a key type.
|
* Globally unique ID for this subject
|
||||||
|
*
|
||||||
|
* Unique IDs are actually public keys. Their size makes them globally
|
||||||
|
* unique (if generated from good randomness) to within ridiculous
|
||||||
|
* probability bounds. If a subject has a unique ID it must also have
|
||||||
|
* a unique ID proof signature, which is the signature of the subject
|
||||||
|
* with the private key corresponding to its unique ID.
|
||||||
|
*
|
||||||
|
* This allows subjects to "own" themselves and exist independent of
|
||||||
|
* CAs or delegated signers. It also allows a certificate for a given
|
||||||
|
* subject to be updated.
|
||||||
|
*
|
||||||
|
* Subject unique IDs are optional. If no unique ID is specified these
|
||||||
|
* and their corresponding size fields must be empty/zero.
|
||||||
|
*
|
||||||
|
* A subject is valid if it has no unique ID or has one with a valid
|
||||||
|
* proof signature.
|
||||||
*/
|
*/
|
||||||
uint8_t uniqueId[ZT_CERTIFICATE_MAX_UNIQUE_ID_SIZE];
|
uint8_t uniqueId[ZT_CERTIFICATE_MAX_UNIQUE_ID_SIZE];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If unique ID is a public key, this can be a signature of the subject.
|
* Signature proving ownership of unique ID.
|
||||||
*/
|
*/
|
||||||
uint8_t uniqueIdProofSignature[ZT_CERTIFICATE_MAX_SIGNATURE_SIZE];
|
uint8_t uniqueIdProofSignature[ZT_CERTIFICATE_MAX_SIGNATURE_SIZE];
|
||||||
|
|
||||||
|
@ -557,6 +582,16 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
ZT_Certificate_Name issuerName;
|
ZT_Certificate_Name issuerName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extended attributes set by issuer (in Dictionary format, NULL if none)
|
||||||
|
*/
|
||||||
|
uint8_t *extendedAttributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of extended attributes field in bytes
|
||||||
|
*/
|
||||||
|
unsigned int extendedAttributesSize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum path length from this certificate toward further certificates.
|
* Maximum path length from this certificate toward further certificates.
|
||||||
*
|
*
|
||||||
|
@ -1627,7 +1662,7 @@ enum ZT_StateObjectType
|
||||||
ZT_STATE_OBJECT_NETWORK_CONFIG = 6,
|
ZT_STATE_OBJECT_NETWORK_CONFIG = 6,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of certificates and their local trust, and locally added roots
|
* List of certificates, their local trust, and locally added roots
|
||||||
*
|
*
|
||||||
* Object ID: (none)
|
* Object ID: (none)
|
||||||
* Canonical path: <HOME>/trust
|
* Canonical path: <HOME>/trust
|
||||||
|
|
Loading…
Add table
Reference in a new issue