diff --git a/core/Certificate.cpp b/core/Certificate.cpp index 6ef585b71..16fdd044b 100644 --- a/core/Certificate.cpp +++ b/core/Certificate.cpp @@ -433,6 +433,26 @@ ZT_CertificateError Certificate::verify() const return ZT_CERTIFICATE_ERROR_NONE; } +bool Certificate::setSubjectUniqueId(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]) +{ + m_subjectUniqueId.assign(uniqueId, uniqueId + ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384); + this->subject.uniqueId = m_subjectUniqueId.data(); + this->subject.uniqueIdSize = ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384; + + Dictionary d; + m_encodeSubject(this->subject, d, true); + Vector< uint8_t > enc; + d.encode(enc); + uint8_t h[ZT_SHA384_DIGEST_SIZE]; + SHA384(h, enc.data(), (unsigned int)enc.size()); + m_subjectUniqueIdProofSignature.resize(ZT_ECC384_SIGNATURE_SIZE); + ECC384ECDSASign(uniqueIdPrivate, h, m_subjectUniqueIdProofSignature.data()); + this->subject.uniqueIdProofSignature = m_subjectUniqueIdProofSignature.data(); + this->subject.uniqueIdProofSignatureSize = ZT_ECC384_SIGNATURE_SIZE; + + return true; +} + void Certificate::m_encodeSubject(const ZT_Certificate_Subject &s, Dictionary &d, bool omitUniqueIdProofSignature) { char tmp[256]; diff --git a/core/Certificate.hpp b/core/Certificate.hpp index 44c8ff695..277d90c44 100644 --- a/core/Certificate.hpp +++ b/core/Certificate.hpp @@ -158,6 +158,17 @@ public: */ ZT_CertificateError verify() const; + /** + * 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_SIZE_TYPE_NIST_P_384], const uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_PRIVATE_KEY_SIZE_TYPE_NIST_P_384]); + /** * Create a subject unique ID and corresponding private key required for use * diff --git a/core/Tests.cpp b/core/Tests.cpp index 35bbaf7b6..429c0a556 100644 --- a/core/Tests.cpp +++ b/core/Tests.cpp @@ -1120,12 +1120,19 @@ extern "C" const char *ZTT_crypto() cert.validity[0] = 0; cert.validity[1] = 9223372036854775807LL; Utils::copy(&cert.issuerName, &cert.subject.name); - //Certificate::setSubjectUniqueId(cert.subject, uniqueId, uniqueIdPrivate); + cert.setSubjectUniqueId(uniqueId, uniqueIdPrivate); cert.sign(testIssuerId); Vector< uint8_t > enc(cert.encode()); ZT_T_PRINTF("OK (%d bytes)" ZT_EOL_S, (int)enc.size()); - ZT_T_PRINTF(" Test certificate decode and verify... "); + ZT_T_PRINTF(" Testing certificate verify... "); + if (!cert.verify()) { + ZT_T_PRINTF("FAILED (verify original)" ZT_EOL_S); + return "Verify original certificate"; + } + ZT_T_PRINTF("OK" ZT_EOL_S); + + ZT_T_PRINTF(" Test certificate decode from marshaled format... "); Certificate cert2; if (!cert2.decode(enc)) { ZT_T_PRINTF("FAILED (decode)" ZT_EOL_S); @@ -1135,6 +1142,11 @@ extern "C" const char *ZTT_crypto() ZT_T_PRINTF("FAILED (compare decoded with original)" ZT_EOL_S); return "Certificate decode and compare"; } + if (!cert2.verify()) { + ZT_T_PRINTF("FAILED (verify decoded certificate)"); + return "Verify decoded certificate"; + } + ZT_T_PRINTF("OK" ZT_EOL_S); } } catch (std::exception &e) { ZT_T_PRINTF(ZT_EOL_S "[crypto] Unexpected exception: %s" ZT_EOL_S, e.what());