From cb7c854ceac45577abcb66e691e3522fb29b59cf Mon Sep 17 00:00:00 2001 From: Marty Leisner Date: Tue, 2 Nov 2021 17:26:32 -0400 Subject: [PATCH] Device Attestation Verifier: Certification Declaration (#10545) * Added method to Validate Certification Declaration in DeviceAttestationVerifier Class. Implemented lookup table for Certification Declaration signer certificate Added unit test * Update certification declaration buffer on DAC Provider Example. Use Max CMS Signed CD Message constant to instantiate cd_data_buf. Check that CMS CD Payload content matches the test vector. add documentation for new ValidateCertificationDeclaration method. bzbarsky review * renamed ValidateCertificationDeclaration method to ValidateCertificationDeclarationSignature Added TODO to implement ValidateCertificationDeclarationPayload (new spec Updates) Updated Certification Declaration as per Spec updates. Updated respective signing certificate and test vectors used on unit tests. --- src/controller/CHIPDeviceController.cpp | 1 - src/credentials/DeviceAttestationVerifier.cpp | 8 ++ src/credentials/DeviceAttestationVerifier.h | 31 +++++-- .../DeviceAttestationCredsExample.cpp | 27 +++++- .../DeviceAttestationVerifierExample.cpp | 77 ++++++++++++++++ .../TestDeviceAttestationCredentials.cpp | 91 ++++++++++++++++--- 6 files changed, 210 insertions(+), 25 deletions(-) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 89d3baa5c66729..b468d485fde26f 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -1172,7 +1172,6 @@ CHIP_ERROR DeviceCommissioner::ValidateAttestationInfo(const ByteSpan & attestat ChipLogProgress(Controller, "Successfully validated 'Attestation Information' command received from the device."); - // TODO: Validate Certification Declaration // TODO: Validate Firmware Information return CHIP_NO_ERROR; diff --git a/src/credentials/DeviceAttestationVerifier.cpp b/src/credentials/DeviceAttestationVerifier.cpp index 7001a481392308..428b3d6823466c 100644 --- a/src/credentials/DeviceAttestationVerifier.cpp +++ b/src/credentials/DeviceAttestationVerifier.cpp @@ -44,6 +44,14 @@ class UnimplementedDACVerifier : public DeviceAttestationVerifier (void) attestationNonce; return AttestationVerificationResult::kNotImplemented; } + + AttestationVerificationResult ValidateCertificationDeclarationSignature(const ByteSpan & cmsEnvelopeBuffer, + ByteSpan & certDeclBuffer) override + { + (void) cmsEnvelopeBuffer; + (void) certDeclBuffer; + return AttestationVerificationResult::kNotImplemented; + } }; // Default to avoid nullptr on getter and cleanly handle new products/clients before diff --git a/src/credentials/DeviceAttestationVerifier.h b/src/credentials/DeviceAttestationVerifier.h index 8e0cabb00fff29..129d50310357e6 100644 --- a/src/credentials/DeviceAttestationVerifier.h +++ b/src/credentials/DeviceAttestationVerifier.h @@ -52,13 +52,16 @@ enum class AttestationVerificationResult : uint16_t kFirmwareInformationMismatch = 400, kFirmwareInformationMissing = 401, - kCertificationDeclarationMissing = 500, - kAttestationSignatureInvalid = 501, - kAttestationElementsMalformed = 502, - kAttestationNonceMismatch = 503, - kAttestationSignatureInvalidFormat = 504, + kAttestationSignatureInvalid = 500, + kAttestationElementsMalformed = 501, + kAttestationNonceMismatch = 502, + kAttestationSignatureInvalidFormat = 503, - kNoMemory = 600, + kCertificationDeclarationNoKeyId = 600, + kCertificationDeclarationNoCertificateFound = 601, + kCertificationDeclarationInvalidSignature = 602, + + kNoMemory = 700, kNotImplemented = 0xFFFFU, @@ -101,7 +104,21 @@ class DeviceAttestationVerifier const ByteSpan & attestationSignatureBuffer, const ByteSpan & paiCertDerBuffer, const ByteSpan & dacCertDerBuffer, const ByteSpan & attestationNonce) = 0; - // TODO: Validate Certification Declaration + /** + * @brief Verify a CMS Signed Data signature against the CSA certificate of Subject Key Identifier that matches + * the subjectKeyIdentifier field of cmsEnvelopeBuffer. + * + * @param[in] cmsEnvelopeBuffer A ByteSpan with a CMS signed message. + * @param[out] certDeclBuffer A ByteSpan to hold the CD content extracted from the CMS signed message. + * + * @returns AttestationVerificationResult::kSuccess on success or another specific + * value from AttestationVerificationResult enum on failure. + */ + virtual AttestationVerificationResult ValidateCertificationDeclarationSignature(const ByteSpan & cmsEnvelopeBuffer, + ByteSpan & certDeclBuffer) = 0; + + // TODO: Validate Certification Declaration Payload + // TODO: Validate Firmware Information protected: diff --git a/src/credentials/examples/DeviceAttestationCredsExample.cpp b/src/credentials/examples/DeviceAttestationCredsExample.cpp index 83bdac04b2aa49..8c2472307562e0 100644 --- a/src/credentials/examples/DeviceAttestationCredsExample.cpp +++ b/src/credentials/examples/DeviceAttestationCredsExample.cpp @@ -144,8 +144,31 @@ CHIP_ERROR ExampleDACProvider::GetProductAttestationIntermediateCert(MutableByte CHIP_ERROR ExampleDACProvider::GetCertificationDeclaration(MutableByteSpan & out_cd_buffer) { - // TODO: We need a real example CD to be populated. - constexpr uint8_t kCertificationDeclaration[128] = { 1 }; + // -> format_version = 1 + // -> vendor_id = 0xFFF1 + // -> product_id_array = [ 0x8000 ] + // -> device_type_id = 0x1234 + // -> certificate_id = "ZIG20141ZB330001-24" + // -> security_level = 0 + // -> security_information = 0 + // -> version_number = 0x2694 + // -> certification_type = 0 + // -> dac_origin_vendor_id is not present + // -> dac_origin_product_id is not present + constexpr uint8_t kCertificationDeclaration[] = { + 0x30, 0x81, 0xe8, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x81, 0xda, 0x30, 0x81, 0xd7, + 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x45, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x38, 0x04, 0x36, 0x15, 0x24, 0x00, 0x01, 0x25, + 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, 0x18, 0x25, 0x03, 0x34, 0x12, 0x2c, 0x04, 0x13, 0x5a, 0x49, 0x47, 0x32, + 0x30, 0x31, 0x34, 0x31, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x32, 0x34, 0x24, 0x05, 0x00, 0x24, 0x06, + 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7c, 0x30, 0x7a, 0x02, 0x01, 0x03, 0x80, 0x14, 0x62, 0xfa, + 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, 0xf3, 0x71, 0x60, 0x30, 0x0b, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x04, 0x03, 0x02, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, 0x43, 0xa6, 0x3f, 0x2b, 0x94, 0x3d, 0xf3, 0x3c, 0x38, 0xb3, 0xe0, + 0x2f, 0xca, 0xa7, 0x5f, 0xe3, 0x53, 0x2a, 0xeb, 0xbf, 0x5e, 0x63, 0xf5, 0xbb, 0xdb, 0xc0, 0xb1, 0xf0, 0x1d, 0x3c, 0x4f, + 0x60, 0x02, 0x20, 0x4c, 0x1a, 0xbf, 0x5f, 0x18, 0x07, 0xb8, 0x18, 0x94, 0xb1, 0x57, 0x6c, 0x47, 0xe4, 0x72, 0x4e, 0x4d, + 0x96, 0x6c, 0x61, 0x2e, 0xd3, 0xfa, 0x25, 0xc1, 0x18, 0xc3, 0xf2, 0xb3, 0xf9, 0x03, 0x69 + }; return CopySpanToMutableSpan(ByteSpan{ kCertificationDeclaration }, out_cd_buffer); } diff --git a/src/credentials/examples/DeviceAttestationVerifierExample.cpp b/src/credentials/examples/DeviceAttestationVerifierExample.cpp index 36f53d308a8af5..a2720012d628a6 100644 --- a/src/credentials/examples/DeviceAttestationVerifierExample.cpp +++ b/src/credentials/examples/DeviceAttestationVerifierExample.cpp @@ -17,10 +17,12 @@ #include "DeviceAttestationVerifierExample.h" #include +#include #include #include #include +#include #include #include @@ -134,6 +136,58 @@ CHIP_ERROR GetProductAttestationAuthorityCert(const ByteSpan & skid, MutableByte return CopySpanToMutableSpan(ByteSpan{ sPAALookupTable[paaLookupTableIdx].mPAACertificate }, outDacBuffer); } +CHIP_ERROR GetCertificationDeclarationCertificate(const ByteSpan & skid, MutableByteSpan & outCertificate) +{ + struct CertChainLookupTable + { + const uint8_t mCertificate[kMax_x509_Certificate_Length]; + const uint8_t mSKID[kKeyIdentifierLength]; + }; + + static CertChainLookupTable + sCertChainLookupTable[] = { + { { 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x5a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x45, 0xda, 0xf3, 0x9d, + 0xe4, 0x7a, 0xa0, 0x8f, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x2b, 0x31, + 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x20, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, + 0x73, 0x74, 0x20, 0x43, 0x44, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x36, 0x32, 0x38, 0x31, 0x34, 0x32, 0x33, 0x34, + 0x33, 0x5a, 0x18, 0x0f, 0x39, 0x39, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, + 0x30, 0x2b, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x20, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x44, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x3c, 0x39, 0x89, 0x22, + 0x45, 0x2b, 0x55, 0xca, 0xf3, 0x89, 0xc2, 0x5b, 0xd1, 0xbc, 0xa4, 0x65, 0x69, 0x52, 0xcc, 0xb9, 0x0e, 0x88, 0x69, + 0x24, 0x9a, 0xd8, 0x47, 0x46, 0x53, 0x01, 0x4c, 0xbf, 0x95, 0xd6, 0x87, 0x96, 0x5e, 0x03, 0x6b, 0x52, 0x1c, 0x51, + 0x03, 0x7e, 0x6b, 0x8c, 0xed, 0xef, 0xca, 0x1e, 0xb4, 0x40, 0x46, 0x69, 0x4f, 0xa0, 0x88, 0x82, 0xee, 0xd6, 0x51, + 0x9d, 0xec, 0xba, 0xa3, 0x66, 0x30, 0x64, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, + 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, + 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x62, 0xfa, 0x82, + 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, 0xf3, 0x71, 0x60, 0x30, 0x1f, + 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, + 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, 0xf3, 0x71, 0x60, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x2c, 0x54, 0x5c, 0xe4, 0xe4, 0x57, 0xd8, + 0xa6, 0xf0, 0xd9, 0xd9, 0xbb, 0xeb, 0xd6, 0xec, 0xe1, 0xdd, 0xfe, 0x7f, 0x8c, 0x6d, 0x9a, 0x6c, 0xf3, 0x75, 0x32, + 0x1f, 0xc6, 0xfa, 0xc7, 0x13, 0x84, 0x02, 0x20, 0x54, 0x07, 0x78, 0xe8, 0x74, 0x39, 0x72, 0x52, 0x7e, 0xed, 0xeb, + 0xaf, 0x58, 0x68, 0x62, 0x20, 0xb5, 0x40, 0x78, 0xf2, 0xcd, 0x4e, 0x62, 0xa7, 0x6a, 0xe7, 0xcb, 0xb9, 0x2f, 0xf5, + 0x4c, 0x8b }, + { 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, + 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, 0xf3, 0x71, 0x60 } } + }; + + size_t certChainLookupTableIdx; + for (certChainLookupTableIdx = 0; certChainLookupTableIdx < ArraySize(sCertChainLookupTable); ++certChainLookupTableIdx) + { + if (skid.data_equal(ByteSpan(sCertChainLookupTable[certChainLookupTableIdx].mSKID))) + { + break; + } + } + + VerifyOrReturnError(certChainLookupTableIdx < ArraySize(sCertChainLookupTable), CHIP_ERROR_INVALID_ARGUMENT); + + return CopySpanToMutableSpan(ByteSpan{ sCertChainLookupTable[certChainLookupTableIdx].mCertificate }, outCertificate); +} + class ExampleDACVerifier : public DeviceAttestationVerifier { public: @@ -142,6 +196,9 @@ class ExampleDACVerifier : public DeviceAttestationVerifier const ByteSpan & attestationSignatureBuffer, const ByteSpan & paiCertDerBuffer, const ByteSpan & dacCertDerBuffer, const ByteSpan & attestationNonce) override; + + AttestationVerificationResult ValidateCertificationDeclarationSignature(const ByteSpan & cmsEnvelopeBuffer, + ByteSpan & certDeclBuffer) override; }; AttestationVerificationResult ExampleDACVerifier::VerifyAttestationInformation(const ByteSpan & attestationInfoBuffer, @@ -218,6 +275,26 @@ AttestationVerificationResult ExampleDACVerifier::VerifyAttestationInformation(c VerifyOrReturnError(attestationNonceSpan.data_equal(attestationNonce), AttestationVerificationResult::kAttestationNonceMismatch); + ByteSpan certificationDeclarationPayload; + return ValidateCertificationDeclarationSignature(certificationDeclarationSpan, certificationDeclarationPayload); +} + +AttestationVerificationResult ExampleDACVerifier::ValidateCertificationDeclarationSignature(const ByteSpan & cmsEnvelopeBuffer, + ByteSpan & certDeclBuffer) +{ + uint8_t certificate[Credentials::kMaxDERCertLength]; + MutableByteSpan certificateSpan(certificate); + ByteSpan skid; + + VerifyOrReturnError(CMS_ExtractKeyId(cmsEnvelopeBuffer, skid) == CHIP_NO_ERROR, + AttestationVerificationResult::kCertificationDeclarationNoKeyId); + + VerifyOrReturnError(GetCertificationDeclarationCertificate(skid, certificateSpan) == CHIP_NO_ERROR, + AttestationVerificationResult::kCertificationDeclarationNoCertificateFound); + + VerifyOrReturnError(CMS_Verify(cmsEnvelopeBuffer, certificateSpan, certDeclBuffer) == CHIP_NO_ERROR, + AttestationVerificationResult::kCertificationDeclarationInvalidSignature); + return AttestationVerificationResult::kSuccess; } diff --git a/src/credentials/tests/TestDeviceAttestationCredentials.cpp b/src/credentials/tests/TestDeviceAttestationCredentials.cpp index 9ad44eddd6450b..f802ae2eee4c48 100644 --- a/src/credentials/tests/TestDeviceAttestationCredentials.cpp +++ b/src/credentials/tests/TestDeviceAttestationCredentials.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -156,26 +157,32 @@ static void TestDACVerifierExample_AttestationInfoVerification(nlTestSuite * inS CHIP_ERROR err = CHIP_NO_ERROR; uint8_t attestationElementsTestVector[] = { - 0x15, 0x30, 0x01, 0x70, 0xd2, 0x84, 0x4b, 0xa2, 0x01, 0x26, 0x04, 0x46, 0x63, 0x73, 0x61, 0x63, 0x64, 0x30, 0xa0, - 0x58, 0x1d, 0x15, 0x25, 0x01, 0x88, 0x99, 0x25, 0x02, 0xfe, 0xff, 0x25, 0x03, 0xd2, 0x04, 0x25, 0x04, 0x2e, 0x16, - 0x24, 0x05, 0xaa, 0x25, 0x06, 0xde, 0xc0, 0x25, 0x07, 0x94, 0x26, 0x18, 0x58, 0x40, 0x96, 0x57, 0x2d, 0xd6, 0x3c, - 0x03, 0x64, 0x0b, 0x28, 0x67, 0x02, 0xbd, 0x6b, 0xba, 0x48, 0xac, 0x7c, 0x83, 0x54, 0x9b, 0x68, 0x73, 0x29, 0x47, - 0x48, 0xb9, 0x51, 0xd5, 0xab, 0x66, 0x62, 0x2e, 0x9d, 0x26, 0x10, 0x41, 0xf8, 0x0e, 0x97, 0x49, 0xfe, 0xff, 0x78, - 0x10, 0x02, 0x49, 0x67, 0xae, 0xdf, 0x41, 0x38, 0x36, 0x5b, 0x0a, 0x22, 0x57, 0x14, 0x9c, 0x9a, 0x12, 0x3e, 0x0d, - 0x30, 0xaa, 0x30, 0x02, 0x20, 0xe0, 0x42, 0x1b, 0x91, 0xc6, 0xfd, 0xcd, 0xb4, 0x0e, 0x2a, 0x4d, 0x2c, 0xf3, 0x1d, - 0xb2, 0xb4, 0xe1, 0x8b, 0x41, 0x1b, 0x1d, 0x3a, 0xd4, 0xd1, 0x2a, 0x9d, 0x90, 0xaa, 0x8e, 0x52, 0xfa, 0xe2, 0x26, - 0x03, 0xfd, 0xc6, 0x5b, 0x28, 0xd0, 0xf1, 0xff, 0x3e, 0x00, 0x01, 0x00, 0x17, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, - 0x5f, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x31, 0xd0, 0xf1, - 0xff, 0x3e, 0x00, 0x03, 0x00, 0x18, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x64, 0x33, 0x5f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18 + 0x15, 0x30, 0x01, 0xeb, 0x30, 0x81, 0xe8, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x81, + 0xda, 0x30, 0x81, 0xd7, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x01, 0x30, 0x45, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x38, 0x04, 0x36, 0x15, + 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, 0x18, 0x25, 0x03, 0x34, 0x12, 0x2c, 0x04, 0x13, + 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x31, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x32, 0x34, 0x24, + 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7c, 0x30, 0x7a, 0x02, 0x01, 0x03, + 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, 0xf3, + 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, 0x43, 0xa6, 0x3f, 0x2b, 0x94, 0x3d, 0xf3, + 0x3c, 0x38, 0xb3, 0xe0, 0x2f, 0xca, 0xa7, 0x5f, 0xe3, 0x53, 0x2a, 0xeb, 0xbf, 0x5e, 0x63, 0xf5, 0xbb, 0xdb, 0xc0, 0xb1, + 0xf0, 0x1d, 0x3c, 0x4f, 0x60, 0x02, 0x20, 0x4c, 0x1a, 0xbf, 0x5f, 0x18, 0x07, 0xb8, 0x18, 0x94, 0xb1, 0x57, 0x6c, 0x47, + 0xe4, 0x72, 0x4e, 0x4d, 0x96, 0x6c, 0x61, 0x2e, 0xd3, 0xfa, 0x25, 0xc1, 0x18, 0xc3, 0xf2, 0xb3, 0xf9, 0x03, 0x69, 0x30, + 0x02, 0x20, 0xe0, 0x42, 0x1b, 0x91, 0xc6, 0xfd, 0xcd, 0xb4, 0x0e, 0x2a, 0x4d, 0x2c, 0xf3, 0x1d, 0xb2, 0xb4, 0xe1, 0x8b, + 0x41, 0x1b, 0x1d, 0x3a, 0xd4, 0xd1, 0x2a, 0x9d, 0x90, 0xaa, 0x8e, 0x52, 0xfa, 0xe2, 0x26, 0x03, 0xfd, 0xc6, 0x5b, 0x28, + 0xd0, 0xf1, 0xff, 0x3e, 0x00, 0x01, 0x00, 0x17, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x76, 0x65, 0x6e, 0x64, 0x6f, + 0x72, 0x5f, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x31, 0xd0, 0xf1, 0xff, 0x3e, 0x00, 0x03, 0x00, 0x18, 0x76, + 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x33, 0x5f, 0x65, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x18 }; uint8_t attestationChallengeTestVector[] = { 0x7a, 0x49, 0x53, 0x05, 0xd0, 0x77, 0x79, 0xa4, 0x94, 0xdd, 0x39, 0xa0, 0x85, 0x1b, 0x66, 0x0d }; uint8_t attestationSignatureTestVector[] = { 0x79, 0x82, 0x53, 0x5d, 0x24, 0xcf, 0xe1, 0x4a, 0x71, 0xab, 0x04, 0x24, 0xcf, 0x0b, 0xac, 0xf1, 0xe3, 0x45, 0x48, 0x7e, 0xd5, 0x0f, 0x1a, 0xc0, 0xbc, 0x25, - 0x9e, 0xcc, 0xfb, 0x39, 0x08, 0x1e, 0x23, 0x71, 0xd1, 0x82, 0xfe, 0x46, 0x03, - 0x9b, 0x7b, 0xf2, 0x0f, 0x78, 0x72, 0x2f, 0xdb, 0x8f, 0x6d, 0x29, 0xd9, 0x8c, - 0xca, 0x55, 0x55, 0xb4, 0x1b, 0x6c, 0x3e, 0x96, 0x0d, 0x97, 0x14, 0x41 }; + 0x9e, 0xcc, 0xfb, 0x39, 0x08, 0x1e, 0x61, 0xa9, 0x26, 0x7e, 0x74, 0xf8, 0x55, + 0xda, 0x53, 0x63, 0x83, 0x74, 0xa0, 0x16, 0x71, 0xcf, 0x3d, 0x7d, 0xb8, 0xcc, + 0x17, 0x0b, 0x38, 0x03, 0x45, 0xe6, 0x0b, 0xc8, 0x6f, 0xdf, 0x45, 0x9e }; uint8_t attestationNonceTestVector[] = { 0xe0, 0x42, 0x1b, 0x91, 0xc6, 0xfd, 0xcd, 0xb4, 0x0e, 0x2a, 0x4d, 0x2c, 0xf3, 0x1d, 0xb2, 0xb4, 0xe1, 0x8b, 0x41, 0x1b, 0x1d, 0x3a, 0xd4, 0xd1, 0x2a, 0x9d, 0x90, 0xaa, 0x8e, 0x52, 0xfa, 0xe2 }; @@ -220,6 +227,59 @@ static void TestDACVerifierExample_AttestationInfoVerification(nlTestSuite * inS NL_TEST_ASSERT(inSuite, attestation_result == AttestationVerificationResult::kSuccess); } +static void TestDACVerifierExample_CertDeclarationVerification(nlTestSuite * inSuite, void * inContext) +{ + // -> format_version = 1 + // -> vendor_id = 0xFFF1 + // -> product_id_array = [ 0x8000 ] + // -> device_type_id = 0x1234 + // -> certificate_id = "ZIG20141ZB330001-24" + // -> security_level = 0 + // -> security_information = 0 + // -> version_number = 0x2694 + // -> certification_type = 0 + // -> dac_origin_vendor_id is not present + // -> dac_origin_product_id is not present + static constexpr uint8_t sTestCMS_CDContent[] = { 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, + 0x00, 0x80, 0x18, 0x25, 0x03, 0x34, 0x12, 0x2c, 0x04, 0x13, 0x5a, + 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x31, 0x5a, 0x42, 0x33, 0x33, + 0x30, 0x30, 0x30, 0x31, 0x2d, 0x32, 0x34, 0x24, 0x05, 0x00, 0x24, + 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18 }; + + CHIP_ERROR err = CHIP_NO_ERROR; + + // Replace default verifier with example verifier + DeviceAttestationVerifier * example_dac_verifier = Examples::GetExampleDACVerifier(); + NL_TEST_ASSERT(inSuite, example_dac_verifier != nullptr); + + SetDeviceAttestationVerifier(example_dac_verifier); + DeviceAttestationVerifier * default_verifier = GetDeviceAttestationVerifier(); + NL_TEST_ASSERT(inSuite, default_verifier == example_dac_verifier); + + DeviceAttestationCredentialsProvider * example_dac_provider = Examples::GetExampleDACProvider(); + NL_TEST_ASSERT(inSuite, example_dac_provider != nullptr); + + SetDeviceAttestationCredentialsProvider(example_dac_provider); + DeviceAttestationCredentialsProvider * default_provider = GetDeviceAttestationCredentialsProvider(); + NL_TEST_ASSERT(inSuite, default_provider == example_dac_provider); + + // Check for CD presence + uint8_t cd_data_buf[kMaxCMSSignedCDMessage] = { 0 }; + MutableByteSpan cd_data_span(cd_data_buf); + + err = example_dac_provider->GetCertificationDeclaration(cd_data_span); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, cd_data_span.size() > 0); + NL_TEST_ASSERT(inSuite, cd_data_span.data()[0] != 0); + + ByteSpan cd_payload; + AttestationVerificationResult attestation_result = + default_verifier->ValidateCertificationDeclarationSignature(cd_data_span, cd_payload); + NL_TEST_ASSERT(inSuite, attestation_result == AttestationVerificationResult::kSuccess); + + NL_TEST_ASSERT(inSuite, cd_payload.data_equal(ByteSpan(sTestCMS_CDContent))); +} + /** * Set up the test suite. */ @@ -252,6 +312,7 @@ static const nlTest sTests[] = { NL_TEST_DEF("Test Example Device Attestation Credentials Providers", TestDACProvidersExample_Providers), NL_TEST_DEF("Test Example Device Attestation Signature", TestDACProvidersExample_Signature), NL_TEST_DEF("Test Example Device Attestation Information Verification", TestDACVerifierExample_AttestationInfoVerification), + NL_TEST_DEF("Test Example Device Attestation Certification Declaration Verification", TestDACVerifierExample_CertDeclarationVerification), NL_TEST_SENTINEL() }; // clang-format on