Skip to content

Commit

Permalink
Device Attestation Verifier: Certification Declaration (#10545)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
Marty Leisner authored and pull[bot] committed Aug 27, 2022
1 parent 53cc80e commit 1741721
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 25 deletions.
1 change: 0 additions & 1 deletion src/controller/CHIPDeviceController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions src/credentials/DeviceAttestationVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
31 changes: 24 additions & 7 deletions src/credentials/DeviceAttestationVerifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down Expand Up @@ -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:
Expand Down
27 changes: 25 additions & 2 deletions src/credentials/examples/DeviceAttestationCredsExample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
77 changes: 77 additions & 0 deletions src/credentials/examples/DeviceAttestationVerifierExample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
#include "DeviceAttestationVerifierExample.h"

#include <credentials/CHIPCert.h>
#include <credentials/CertificationDeclaration.h>
#include <credentials/DeviceAttestationConstructor.h>
#include <crypto/CHIPCryptoPAL.h>

#include <lib/core/CHIPError.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ScopedBuffer.h>
#include <lib/support/Span.h>

Expand Down Expand Up @@ -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:
Expand All @@ -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,
Expand Down Expand Up @@ -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;
}

Expand Down
Loading

0 comments on commit 1741721

Please sign in to comment.