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