From 2519204d63af542f127e848762581c72f72f737f Mon Sep 17 00:00:00 2001
From: Tennessee Carmel-Veilleux <tennessee.carmelveilleux@gmail.com>
Date: Sat, 27 Nov 2021 12:08:31 -0500
Subject: [PATCH] Make PAA trust store configurable (#12277)

* Make PAA store configurable

PAA store used by DefaultDeviceAttestationVerifier could not be
replaced, forcing a few fixed test roots to always be used and
nothing else, unless completely forking the
DefaultDeviceAttestationVerifier.

- This PR introduces the `PaaRootStore` interface, which the
  default `DeviceAttestationVerifier` expects to get configured
  at in constructor.
- Examples were modified to use the default test PAA root store
- Unit tests updated to use the testing root store
- Refactored simple array-based Root store to self-extract
  the SKID

Testing done: added new units tests which pass, ran cert tests,
validated attestation succeeds the same as before with test keys.

Fixed #11913

* Restyled by clang-format

* Address review comments

- Rename PaaRootStore to AttestationTrustStore
- Add comments about ArrayAttestationtTrustStore lifecycle
- Remove debug print

* Fix python build

* Fix tv-app scoping issue

* Attempt to debug Darwin error

* Restyled by clang-format

* Remove debug logging used to diagnose CI

Co-authored-by: Restyled.io <commits@restyled.io>
---
 .../chip-tool/commands/common/CHIPCommand.cpp |   5 +-
 examples/platform/linux/AppMain.cpp           |   4 +-
 examples/tv-casting-app/linux/main.cpp        |   8 +-
 .../java/AndroidDeviceControllerWrapper.cpp   |   4 +-
 .../ChipDeviceController-ScriptBinding.cpp    |   4 +-
 .../python/chip/internal/CommissionerImpl.cpp |   8 +-
 src/credentials/CHIPCert.h                    |   2 +-
 src/credentials/DeviceAttestationVerifier.h   |  81 +++++++
 .../DefaultDeviceAttestationVerifier.cpp      | 208 +++++++++---------
 .../DefaultDeviceAttestationVerifier.h        |  22 +-
 .../tests/TestCertificationDeclaration.cpp    |   4 +-
 .../TestDeviceAttestationCredentials.cpp      |  80 ++++++-
 src/crypto/CHIPCryptoPAL.h                    |   2 +
 src/crypto/tests/CHIPCryptoPALTest.cpp        |   4 +-
 .../Framework/CHIP/CHIPDeviceController.mm    |   4 +-
 src/protocols/secure_channel/CASESession.h    |   2 +-
 16 files changed, 314 insertions(+), 128 deletions(-)

diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp
index 44921d77b457f9..7f39cab591b99b 100644
--- a/examples/chip-tool/commands/common/CHIPCommand.cpp
+++ b/examples/chip-tool/commands/common/CHIPCommand.cpp
@@ -45,7 +45,10 @@ CHIP_ERROR CHIPCommand::Run()
     chip::Platform::ScopedMemoryBuffer<uint8_t> rcac;
 
     chip::Credentials::SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider());
-    chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier());
+
+    // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available
+    const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore();
+    chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier(testingRootStore));
 
     VerifyOrReturnError(noc.Alloc(chip::Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
     VerifyOrReturnError(icac.Alloc(chip::Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp
index 5b79f089d13674..44f9917c92e70d 100644
--- a/examples/platform/linux/AppMain.cpp
+++ b/examples/platform/linux/AppMain.cpp
@@ -234,7 +234,9 @@ CHIP_ERROR InitCommissioner()
     ReturnErrorOnFailure(gCommissioner.SetUdcListenPort(LinuxDeviceOptions::GetInstance().unsecuredCommissionerPort));
 
     // Initialize device attestation verifier
-    SetDeviceAttestationVerifier(GetDefaultDACVerifier());
+    // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available
+    const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore();
+    SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore));
 
     chip::Platform::ScopedMemoryBuffer<uint8_t> noc;
     VerifyOrReturnError(noc.Alloc(chip::Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
diff --git a/examples/tv-casting-app/linux/main.cpp b/examples/tv-casting-app/linux/main.cpp
index e2b356db9ae093..7cd5934347e967 100644
--- a/examples/tv-casting-app/linux/main.cpp
+++ b/examples/tv-casting-app/linux/main.cpp
@@ -195,8 +195,12 @@ int main(int argc, char * argv[])
     // Initialize device attestation config
     SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
 
-    // Initialize device attestation verifier
-    SetDeviceAttestationVerifier(GetDefaultDACVerifier());
+    // Initialize device attestation verifier from a constant version
+    {
+        // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available
+        const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore();
+        SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore));
+    }
 
     if (!chip::ArgParser::ParseArgs(argv[0], argc, argv, allOptions))
     {
diff --git a/src/controller/java/AndroidDeviceControllerWrapper.cpp b/src/controller/java/AndroidDeviceControllerWrapper.cpp
index bb18387a38a488..4f961e0a0dec97 100644
--- a/src/controller/java/AndroidDeviceControllerWrapper.cpp
+++ b/src/controller/java/AndroidDeviceControllerWrapper.cpp
@@ -204,7 +204,9 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(Jav
     wrapper->SetJavaObjectRef(vm, deviceControllerObj);
 
     // Initialize device attestation verifier
-    SetDeviceAttestationVerifier(GetDefaultDACVerifier());
+    // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available
+    const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore();
+    SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore));
 
     chip::Controller::FactoryInitParams initParams;
     chip::Controller::SetupParams setupParams;
diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp
index 9c1b09388d0f7f..c7fc136760d8fc 100644
--- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp
+++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp
@@ -182,7 +182,9 @@ ChipError::StorageType pychip_DeviceController_NewDeviceController(chip::Control
     }
 
     // Initialize device attestation verifier
-    SetDeviceAttestationVerifier(GetDefaultDACVerifier());
+    // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available
+    const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore();
+    SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore));
 
     CHIP_ERROR err = sOperationalCredentialsIssuer.Initialize(sStorageDelegate);
     VerifyOrReturnError(err == CHIP_NO_ERROR, err.AsInteger());
diff --git a/src/controller/python/chip/internal/CommissionerImpl.cpp b/src/controller/python/chip/internal/CommissionerImpl.cpp
index 4386fc16ab549b..8d5b129d7d1159 100644
--- a/src/controller/python/chip/internal/CommissionerImpl.cpp
+++ b/src/controller/python/chip/internal/CommissionerImpl.cpp
@@ -108,6 +108,11 @@ extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_N
         chip::Platform::ScopedMemoryBuffer<uint8_t> rcac;
         chip::Crypto::P256Keypair ephemeralKey;
 
+        // Initialize device attestation verifier
+        // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available
+        const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore();
+        chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier(testingRootStore));
+
         err = gFabricStorage.Initialize(&gServerStorage);
         SuccessOrExit(err);
 
@@ -116,9 +121,6 @@ extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_N
         commissionerParams.pairingDelegate = &gPairingDelegate;
         commissionerParams.storageDelegate = &gServerStorage;
 
-        // Initialize device attestation verifier
-        chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier());
-
         err = ephemeralKey.Initialize();
         SuccessOrExit(err);
 
diff --git a/src/credentials/CHIPCert.h b/src/credentials/CHIPCert.h
index 762e0f25f209f6..b957e60283b638 100644
--- a/src/credentials/CHIPCert.h
+++ b/src/credentials/CHIPCert.h
@@ -42,7 +42,7 @@
 namespace chip {
 namespace Credentials {
 
-static constexpr uint32_t kKeyIdentifierLength                 = 20;
+static constexpr uint32_t kKeyIdentifierLength                 = static_cast<uint32_t>(Crypto::kSubjectKeyIdentifierLength);
 static constexpr uint32_t kChip32bitAttrUTF8Length             = 8;
 static constexpr uint32_t kChip64bitAttrUTF8Length             = 16;
 static constexpr uint16_t kX509NoWellDefinedExpirationDateYear = 9999;
diff --git a/src/credentials/DeviceAttestationVerifier.h b/src/credentials/DeviceAttestationVerifier.h
index 09d843153943d5..75ee5a0eb50d0e 100644
--- a/src/credentials/DeviceAttestationVerifier.h
+++ b/src/credentials/DeviceAttestationVerifier.h
@@ -99,6 +99,87 @@ struct DeviceInfoForAttestation
     uint16_t paaVendorId = VendorId::NotSpecified;
 };
 
+/**
+ * @brief Helper utility to model a basic trust store usable for device attestation verifiers.
+ *
+ * API is synchronous. Real commissioner implementations may entirely
+ * hide Product Attestation Authority cert lookup behind the DeviceAttestationVerifier and
+ * never use this interface at all. It is provided as a utility to help build DeviceAttestationVerifier
+ * implementations suitable for testing or examples.
+ */
+class AttestationTrustStore
+{
+public:
+    AttestationTrustStore()          = default;
+    virtual ~AttestationTrustStore() = default;
+
+    // Not copyable
+    AttestationTrustStore(const AttestationTrustStore &) = delete;
+    AttestationTrustStore & operator=(const AttestationTrustStore &) = delete;
+
+    /**
+     * @brief Look-up a PAA cert by SKID
+     *
+     * The implementations of this interface must have access to a set of PAAs to trust.
+     *
+     * Interface is synchronous, and therefore this should not be used unless to expose a PAA
+     * store that is both fully local and quick to access.
+     *
+     * @param[in] skid Buffer containing the subject key identifier (SKID) of the PAA to look-up
+     * @param[inout] outPaaDerBuffer Buffer to receive the contents of the PAA root cert, if found.
+     *                                  Size will be updated to match actual size.
+     *
+     * @returns CHIP_NO_ERROR on success, CHIP_INVALID_ARGUMENT if `skid` or `outPaaDerBuffer` arguments
+     *          are not usable, CHIP_BUFFER_TOO_SMALL if certificate doesn't fit in `outPaaDerBuffer`
+     *          span, CHIP_ERROR_CA_CERT_NOT_FOUND if no PAA found that matches `skid.
+     *
+     */
+    virtual CHIP_ERROR GetProductAttestationAuthorityCert(const ByteSpan & skid, MutableByteSpan & outPaaDerBuffer) const = 0;
+};
+
+/**
+ * @brief Basic AttestationTrustStore that holds all data within caller-owned memory.
+ *
+ * This is useful to wrap a fixed constant array of certificates into a trust store
+ * implementation.
+ */
+
+class ArrayAttestationTrustStore : public AttestationTrustStore
+{
+public:
+    ArrayAttestationTrustStore(const ByteSpan * derCerts, size_t numCerts) : mDerCerts(derCerts), mNumCerts(numCerts) {}
+
+    CHIP_ERROR GetProductAttestationAuthorityCert(const ByteSpan & skid, MutableByteSpan & outPaaDerBuffer) const override
+    {
+        VerifyOrReturnError(!skid.empty() && (skid.data() != nullptr), CHIP_ERROR_INVALID_ARGUMENT);
+        VerifyOrReturnError(skid.size() == Crypto::kSubjectKeyIdentifierLength, CHIP_ERROR_INVALID_ARGUMENT);
+
+        size_t paaIdx;
+        ByteSpan candidate;
+
+        for (paaIdx = 0; paaIdx < mNumCerts; ++paaIdx)
+        {
+            uint8_t skidBuf[Crypto::kSubjectKeyIdentifierLength] = { 0 };
+            candidate                                            = mDerCerts[paaIdx];
+            MutableByteSpan candidateSkidSpan{ skidBuf };
+            VerifyOrReturnError(CHIP_NO_ERROR == Crypto::ExtractSKIDFromX509Cert(candidate, candidateSkidSpan),
+                                CHIP_ERROR_INTERNAL);
+
+            if (skid.data_equal(candidateSkidSpan))
+            {
+                // Found a match
+                return CopySpanToMutableSpan(candidate, outPaaDerBuffer);
+            }
+        }
+
+        return CHIP_ERROR_CA_CERT_NOT_FOUND;
+    }
+
+protected:
+    const ByteSpan * mDerCerts;
+    const size_t mNumCerts;
+};
+
 class DeviceAttestationVerifier
 {
 public:
diff --git a/src/credentials/examples/DefaultDeviceAttestationVerifier.cpp b/src/credentials/examples/DefaultDeviceAttestationVerifier.cpp
index b6cf795092fd47..23acd0179f59f7 100644
--- a/src/credentials/examples/DefaultDeviceAttestationVerifier.cpp
+++ b/src/credentials/examples/DefaultDeviceAttestationVerifier.cpp
@@ -34,114 +34,98 @@ namespace Credentials {
 
 namespace {
 
-CHIP_ERROR GetProductAttestationAuthorityCert(const ByteSpan & skid, MutableByteSpan & outDacBuffer)
-{
-    struct PAALookupTable
-    {
-        const uint8_t mPAACertificate[kMax_x509_Certificate_Length];
-        const uint8_t mSKID[kKeyIdentifierLength];
-    };
-
-    static PAALookupTable
-        sPAALookupTable[] = {
-            { /*
-              credentials/test/attestation/Chip-Test-PAA-FFF1-Cert.pem
-              -----BEGIN CERTIFICATE-----
-              MIIBmTCCAT+gAwIBAgIIaDhPq7kZ/N8wCgYIKoZIzj0EAwIwHzEdMBsGA1UEAwwU
-              TWF0dGVyIFRlc3QgUEFBIEZGRjEwIBcNMjEwNjI4MTQyMzQzWhgPOTk5OTEyMzEy
-              MzU5NTlaMB8xHTAbBgNVBAMMFE1hdHRlciBUZXN0IFBBQSBGRkYxMFkwEwYHKoZI
-              zj0CAQYIKoZIzj0DAQcDQgAEG5isW7wR3GoXVaBbCsXha6AsRu5vwrvnb/fPbKeq
-              Tp/R15jcvvtP6uIl03c8kTSMwm1JMTHjCWMtXp7zHRLek6NjMGEwDwYDVR0TAQH/
-              BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFO8Y4OzUZgQ03w28kR7U
-              UhaZZoOfMB8GA1UdIwQYMBaAFO8Y4OzUZgQ03w28kR7UUhaZZoOfMAoGCCqGSM49
-              BAMCA0gAMEUCIQCn+l+nZv/3tf0VjNNPYl1IkSAOBYUO8SX23udWVPmXNgIgI7Ub
-              bkJTKCjbCZIDNwUNcPC2tyzNPLeB5nGsIl31Rys=
-              -----END CERTIFICATE-----
-              */
-              { 0x30, 0x82, 0x01, 0x99, 0x30, 0x82, 0x01, 0x3F, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x68, 0x38, 0x4F, 0xAB,
-                0xB9, 0x19, 0xFC, 0xDF, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1F, 0x31,
-                0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65,
-                0x73, 0x74, 0x20, 0x50, 0x41, 0x41, 0x20, 0x46, 0x46, 0x46, 0x31, 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, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
-                0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x50, 0x41, 0x41, 0x20, 0x46, 0x46,
-                0x46, 0x31, 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, 0x1B, 0x98, 0xAC, 0x5B, 0xBC, 0x11, 0xDC, 0x6A, 0x17,
-                0x55, 0xA0, 0x5B, 0x0A, 0xC5, 0xE1, 0x6B, 0xA0, 0x2C, 0x46, 0xEE, 0x6F, 0xC2, 0xBB, 0xE7, 0x6F, 0xF7, 0xCF, 0x6C,
-                0xA7, 0xAA, 0x4E, 0x9F, 0xD1, 0xD7, 0x98, 0xDC, 0xBE, 0xFB, 0x4F, 0xEA, 0xE2, 0x25, 0xD3, 0x77, 0x3C, 0x91, 0x34,
-                0x8C, 0xC2, 0x6D, 0x49, 0x31, 0x31, 0xE3, 0x09, 0x63, 0x2D, 0x5E, 0x9E, 0xF3, 0x1D, 0x12, 0xDE, 0x93, 0xA3, 0x63,
-                0x30, 0x61, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF,
-                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, 0xEF, 0x18, 0xE0, 0xEC, 0xD4, 0x66, 0x04, 0x34, 0xDF, 0x0D, 0xBC,
-                0x91, 0x1E, 0xD4, 0x52, 0x16, 0x99, 0x66, 0x83, 0x9F, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30,
-                0x16, 0x80, 0x14, 0xEF, 0x18, 0xE0, 0xEC, 0xD4, 0x66, 0x04, 0x34, 0xDF, 0x0D, 0xBC, 0x91, 0x1E, 0xD4, 0x52, 0x16,
-                0x99, 0x66, 0x83, 0x9F, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00,
-                0x30, 0x45, 0x02, 0x21, 0x00, 0xA7, 0xFA, 0x5F, 0xA7, 0x66, 0xFF, 0xF7, 0xB5, 0xFD, 0x15, 0x8C, 0xD3, 0x4F, 0x62,
-                0x5D, 0x48, 0x91, 0x20, 0x0E, 0x05, 0x85, 0x0E, 0xF1, 0x25, 0xF6, 0xDE, 0xE7, 0x56, 0x54, 0xF9, 0x97, 0x36, 0x02,
-                0x20, 0x23, 0xB5, 0x1B, 0x6E, 0x42, 0x53, 0x28, 0x28, 0xDB, 0x09, 0x92, 0x03, 0x37, 0x05, 0x0D, 0x70, 0xF0, 0xB6,
-                0xB7, 0x2C, 0xCD, 0x3C, 0xB7, 0x81, 0xE6, 0x71, 0xAC, 0x22, 0x5D, 0xF5, 0x47, 0x2B },
-              { 0xEF, 0x18, 0xE0, 0xEC, 0xD4, 0x66, 0x04, 0x34, 0xDF, 0x0D,
-                0xBC, 0x91, 0x1E, 0xD4, 0x52, 0x16, 0x99, 0x66, 0x83, 0x9F } },
-            { /*
-              credentials/test/attestation/Chip-Test-PAA-FFF2-Cert.pem
-              -----BEGIN CERTIFICATE-----
-              MIIBnTCCAUKgAwIBAgIIA5KnZVo+bHcwCgYIKoZIzj0EAwIwHzEdMBsGA1UEAwwU
-              TWF0dGVyIFRlc3QgUEFBIEZGRjIwIBcNMjEwNjI4MTQyMzQzWhgPOTk5OTEyMzEy
-              MzU5NTlaMB8xHTAbBgNVBAMMFE1hdHRlciBUZXN0IFBBQSBGRkYyMFkwEwYHKoZI
-              zj0CAQYIKoZIzj0DAQcDQgAEdW4YkvnpULAOlQqilfM1sEhLh20i4m+WZZLKweUQ
-              1f6Zsx1cmIgWeorWUDd+dRD7dYI8fluYuMAG7F8Gz66FSqNmMGQwEgYDVR0TAQH/
-              BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFOfv6sMzXF/Qw+Y0
-              Up8WcEbEvKVcMB8GA1UdIwQYMBaAFOfv6sMzXF/Qw+Y0Up8WcEbEvKVcMAoGCCqG
-              SM49BAMCA0kAMEYCIQCSUQ0dYCFfARvaLqeV/ssklO+QppeHrQr8IGxhjAnMUgIh
-              AKA2sK+D40VcCTi5S/9HdRlyuNy+cZyfYbVW7LTqF8xX
-              -----END CERTIFICATE-----
-              */
-              { 0x30, 0x82, 0x01, 0x9D, 0x30, 0x82, 0x01, 0x42, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x03, 0x92, 0xA7, 0x65,
-                0x5A, 0x3E, 0x6C, 0x77, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1F, 0x31,
-                0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65,
-                0x73, 0x74, 0x20, 0x50, 0x41, 0x41, 0x20, 0x46, 0x46, 0x46, 0x32, 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, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
-                0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x50, 0x41, 0x41, 0x20, 0x46, 0x46,
-                0x46, 0x32, 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, 0x75, 0x6E, 0x18, 0x92, 0xF9, 0xE9, 0x50, 0xB0, 0x0E,
-                0x95, 0x0A, 0xA2, 0x95, 0xF3, 0x35, 0xB0, 0x48, 0x4B, 0x87, 0x6D, 0x22, 0xE2, 0x6F, 0x96, 0x65, 0x92, 0xCA, 0xC1,
-                0xE5, 0x10, 0xD5, 0xFE, 0x99, 0xB3, 0x1D, 0x5C, 0x98, 0x88, 0x16, 0x7A, 0x8A, 0xD6, 0x50, 0x37, 0x7E, 0x75, 0x10,
-                0xFB, 0x75, 0x82, 0x3C, 0x7E, 0x5B, 0x98, 0xB8, 0xC0, 0x06, 0xEC, 0x5F, 0x06, 0xCF, 0xAE, 0x85, 0x4A, 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, 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0x5F, 0xD0,
-                0xC3, 0xE6, 0x34, 0x52, 0x9F, 0x16, 0x70, 0x46, 0xC4, 0xBC, 0xA5, 0x5C, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23,
-                0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0x5F, 0xD0, 0xC3, 0xE6, 0x34, 0x52, 0x9F,
-                0x16, 0x70, 0x46, 0xC4, 0xBC, 0xA5, 0x5C, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02,
-                0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x92, 0x51, 0x0D, 0x1D, 0x60, 0x21, 0x5F, 0x01, 0x1B, 0xDA, 0x2E,
-                0xA7, 0x95, 0xFE, 0xCB, 0x24, 0x94, 0xEF, 0x90, 0xA6, 0x97, 0x87, 0xAD, 0x0A, 0xFC, 0x20, 0x6C, 0x61, 0x8C, 0x09,
-                0xCC, 0x52, 0x02, 0x21, 0x00, 0xA0, 0x36, 0xB0, 0xAF, 0x83, 0xE3, 0x45, 0x5C, 0x09, 0x38, 0xB9, 0x4B, 0xFF, 0x47,
-                0x75, 0x19, 0x72, 0xB8, 0xDC, 0xBE, 0x71, 0x9C, 0x9F, 0x61, 0xB5, 0x56, 0xEC, 0xB4, 0xEA, 0x17, 0xCC, 0x57 },
-              { 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0x5F, 0xD0, 0xC3, 0xE6,
-                0x34, 0x52, 0x9F, 0x16, 0x70, 0x46, 0xC4, 0xBC, 0xA5, 0x5C } },
-        };
+/*
+credentials/test/attestation/Chip-Test-PAA-FFF1-Cert.pem
+-----BEGIN CERTIFICATE-----
+MIIBmTCCAT+gAwIBAgIIaDhPq7kZ/N8wCgYIKoZIzj0EAwIwHzEdMBsGA1UEAwwU
+TWF0dGVyIFRlc3QgUEFBIEZGRjEwIBcNMjEwNjI4MTQyMzQzWhgPOTk5OTEyMzEy
+MzU5NTlaMB8xHTAbBgNVBAMMFE1hdHRlciBUZXN0IFBBQSBGRkYxMFkwEwYHKoZI
+zj0CAQYIKoZIzj0DAQcDQgAEG5isW7wR3GoXVaBbCsXha6AsRu5vwrvnb/fPbKeq
+Tp/R15jcvvtP6uIl03c8kTSMwm1JMTHjCWMtXp7zHRLek6NjMGEwDwYDVR0TAQH/
+BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFO8Y4OzUZgQ03w28kR7U
+UhaZZoOfMB8GA1UdIwQYMBaAFO8Y4OzUZgQ03w28kR7UUhaZZoOfMAoGCCqGSM49
+BAMCA0gAMEUCIQCn+l+nZv/3tf0VjNNPYl1IkSAOBYUO8SX23udWVPmXNgIgI7Ub
+bkJTKCjbCZIDNwUNcPC2tyzNPLeB5nGsIl31Rys=
+-----END CERTIFICATE-----
+*/
+const uint8_t kChipTestPaaFff1[] = {
+    0x30, 0x82, 0x01, 0x99, 0x30, 0x82, 0x01, 0x3F, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x68, 0x38, 0x4F, 0xAB, 0xB9, 0x19,
+    0xFC, 0xDF, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06,
+    0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x50, 0x41, 0x41,
+    0x20, 0x46, 0x46, 0x46, 0x31, 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, 0x1F, 0x31,
+    0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74,
+    0x20, 0x50, 0x41, 0x41, 0x20, 0x46, 0x46, 0x46, 0x31, 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, 0x1B, 0x98, 0xAC, 0x5B, 0xBC, 0x11,
+    0xDC, 0x6A, 0x17, 0x55, 0xA0, 0x5B, 0x0A, 0xC5, 0xE1, 0x6B, 0xA0, 0x2C, 0x46, 0xEE, 0x6F, 0xC2, 0xBB, 0xE7, 0x6F, 0xF7, 0xCF,
+    0x6C, 0xA7, 0xAA, 0x4E, 0x9F, 0xD1, 0xD7, 0x98, 0xDC, 0xBE, 0xFB, 0x4F, 0xEA, 0xE2, 0x25, 0xD3, 0x77, 0x3C, 0x91, 0x34, 0x8C,
+    0xC2, 0x6D, 0x49, 0x31, 0x31, 0xE3, 0x09, 0x63, 0x2D, 0x5E, 0x9E, 0xF3, 0x1D, 0x12, 0xDE, 0x93, 0xA3, 0x63, 0x30, 0x61, 0x30,
+    0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 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, 0xEF, 0x18, 0xE0, 0xEC, 0xD4, 0x66, 0x04, 0x34, 0xDF, 0x0D, 0xBC, 0x91, 0x1E, 0xD4, 0x52, 0x16, 0x99, 0x66, 0x83, 0x9F,
+    0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xEF, 0x18, 0xE0, 0xEC, 0xD4, 0x66, 0x04, 0x34,
+    0xDF, 0x0D, 0xBC, 0x91, 0x1E, 0xD4, 0x52, 0x16, 0x99, 0x66, 0x83, 0x9F, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+    0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xA7, 0xFA, 0x5F, 0xA7, 0x66, 0xFF, 0xF7, 0xB5, 0xFD, 0x15,
+    0x8C, 0xD3, 0x4F, 0x62, 0x5D, 0x48, 0x91, 0x20, 0x0E, 0x05, 0x85, 0x0E, 0xF1, 0x25, 0xF6, 0xDE, 0xE7, 0x56, 0x54, 0xF9, 0x97,
+    0x36, 0x02, 0x20, 0x23, 0xB5, 0x1B, 0x6E, 0x42, 0x53, 0x28, 0x28, 0xDB, 0x09, 0x92, 0x03, 0x37, 0x05, 0x0D, 0x70, 0xF0, 0xB6,
+    0xB7, 0x2C, 0xCD, 0x3C, 0xB7, 0x81, 0xE6, 0x71, 0xAC, 0x22, 0x5D, 0xF5, 0x47, 0x2B
+};
 
-    size_t paaLookupTableIdx;
-    for (paaLookupTableIdx = 0; paaLookupTableIdx < ArraySize(sPAALookupTable); ++paaLookupTableIdx)
-    {
-        if (skid.data_equal(ByteSpan(sPAALookupTable[paaLookupTableIdx].mSKID)))
-        {
-            break;
-        }
-    }
+/*
+credentials/test/attestation/Chip-Test-PAA-FFF2-Cert.pem
+-----BEGIN CERTIFICATE-----
+MIIBnTCCAUKgAwIBAgIIA5KnZVo+bHcwCgYIKoZIzj0EAwIwHzEdMBsGA1UEAwwU
+TWF0dGVyIFRlc3QgUEFBIEZGRjIwIBcNMjEwNjI4MTQyMzQzWhgPOTk5OTEyMzEy
+MzU5NTlaMB8xHTAbBgNVBAMMFE1hdHRlciBUZXN0IFBBQSBGRkYyMFkwEwYHKoZI
+zj0CAQYIKoZIzj0DAQcDQgAEdW4YkvnpULAOlQqilfM1sEhLh20i4m+WZZLKweUQ
+1f6Zsx1cmIgWeorWUDd+dRD7dYI8fluYuMAG7F8Gz66FSqNmMGQwEgYDVR0TAQH/
+BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFOfv6sMzXF/Qw+Y0
+Up8WcEbEvKVcMB8GA1UdIwQYMBaAFOfv6sMzXF/Qw+Y0Up8WcEbEvKVcMAoGCCqG
+SM49BAMCA0kAMEYCIQCSUQ0dYCFfARvaLqeV/ssklO+QppeHrQr8IGxhjAnMUgIh
+AKA2sK+D40VcCTi5S/9HdRlyuNy+cZyfYbVW7LTqF8xX
+-----END CERTIFICATE-----
+*/
+const uint8_t kChipTestPaaFff2[] = {
+    0x30, 0x82, 0x01, 0x9D, 0x30, 0x82, 0x01, 0x42, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x03, 0x92, 0xA7, 0x65, 0x5A, 0x3E,
+    0x6C, 0x77, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06,
+    0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x50, 0x41, 0x41,
+    0x20, 0x46, 0x46, 0x46, 0x32, 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, 0x1F, 0x31,
+    0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x4D, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74,
+    0x20, 0x50, 0x41, 0x41, 0x20, 0x46, 0x46, 0x46, 0x32, 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, 0x75, 0x6E, 0x18, 0x92, 0xF9, 0xE9,
+    0x50, 0xB0, 0x0E, 0x95, 0x0A, 0xA2, 0x95, 0xF3, 0x35, 0xB0, 0x48, 0x4B, 0x87, 0x6D, 0x22, 0xE2, 0x6F, 0x96, 0x65, 0x92, 0xCA,
+    0xC1, 0xE5, 0x10, 0xD5, 0xFE, 0x99, 0xB3, 0x1D, 0x5C, 0x98, 0x88, 0x16, 0x7A, 0x8A, 0xD6, 0x50, 0x37, 0x7E, 0x75, 0x10, 0xFB,
+    0x75, 0x82, 0x3C, 0x7E, 0x5B, 0x98, 0xB8, 0xC0, 0x06, 0xEC, 0x5F, 0x06, 0xCF, 0xAE, 0x85, 0x4A, 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, 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0x5F, 0xD0, 0xC3, 0xE6, 0x34, 0x52, 0x9F, 0x16, 0x70, 0x46, 0xC4,
+    0xBC, 0xA5, 0x5C, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xE7, 0xEF, 0xEA, 0xC3, 0x33,
+    0x5C, 0x5F, 0xD0, 0xC3, 0xE6, 0x34, 0x52, 0x9F, 0x16, 0x70, 0x46, 0xC4, 0xBC, 0xA5, 0x5C, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86,
+    0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x92, 0x51, 0x0D, 0x1D, 0x60, 0x21, 0x5F,
+    0x01, 0x1B, 0xDA, 0x2E, 0xA7, 0x95, 0xFE, 0xCB, 0x24, 0x94, 0xEF, 0x90, 0xA6, 0x97, 0x87, 0xAD, 0x0A, 0xFC, 0x20, 0x6C, 0x61,
+    0x8C, 0x09, 0xCC, 0x52, 0x02, 0x21, 0x00, 0xA0, 0x36, 0xB0, 0xAF, 0x83, 0xE3, 0x45, 0x5C, 0x09, 0x38, 0xB9, 0x4B, 0xFF, 0x47,
+    0x75, 0x19, 0x72, 0xB8, 0xDC, 0xBE, 0x71, 0x9C, 0x9F, 0x61, 0xB5, 0x56, 0xEC, 0xB4, 0xEA, 0x17, 0xCC, 0x57
+};
 
-    VerifyOrReturnError(paaLookupTableIdx < ArraySize(sPAALookupTable), CHIP_ERROR_INVALID_ARGUMENT);
+const ByteSpan kTestPaaRoots[] = {
+    ByteSpan{ kChipTestPaaFff1 },
+    ByteSpan{ kChipTestPaaFff2 },
+};
 
-    return CopySpanToMutableSpan(ByteSpan{ sPAALookupTable[paaLookupTableIdx].mPAACertificate }, outDacBuffer);
-}
+const ArrayAttestationTrustStore kTestAttestationTrustStore{ &kTestPaaRoots[0], ArraySize(kTestPaaRoots) };
 
+/**
+ * @brief Look-up of well-known keys used for CD signing by CSA.
+ *
+ * Current version uses only test key/cert provided in spec.
+ */
 CHIP_ERROR GetCertificationDeclarationCertificate(const ByteSpan & skid, MutableByteSpan & outCertificate)
 {
     struct CertChainLookupTable
     {
         const uint8_t mCertificate[kMax_x509_Certificate_Length];
-        const uint8_t mSKID[kKeyIdentifierLength];
+        const uint8_t mSKID[Crypto::kSubjectKeyIdentifierLength];
     };
 
     static CertChainLookupTable
@@ -191,6 +175,8 @@ CHIP_ERROR GetCertificationDeclarationCertificate(const ByteSpan & skid, Mutable
 class DefaultDACVerifier : public DeviceAttestationVerifier
 {
 public:
+    DefaultDACVerifier(const AttestationTrustStore * paaRootStore) : mAttestationTrustStore(paaRootStore) {}
+
     AttestationVerificationResult VerifyAttestationInformation(const ByteSpan & attestationInfoBuffer,
                                                                const ByteSpan & attestationChallengeBuffer,
                                                                const ByteSpan & attestationSignatureBuffer,
@@ -203,6 +189,11 @@ class DefaultDACVerifier : public DeviceAttestationVerifier
     AttestationVerificationResult ValidateCertificateDeclarationPayload(const ByteSpan & certDeclBuffer,
                                                                         const ByteSpan & firmwareInfo,
                                                                         const DeviceInfoForAttestation & deviceInfo) override;
+
+protected:
+    DefaultDACVerifier() {}
+
+    const AttestationTrustStore * mAttestationTrustStore;
 };
 
 AttestationVerificationResult DefaultDACVerifier::VerifyAttestationInformation(const ByteSpan & attestationInfoBuffer,
@@ -246,7 +237,7 @@ AttestationVerificationResult DefaultDACVerifier::VerifyAttestationInformation(c
                                                      deviceSignature) == CHIP_NO_ERROR,
                         AttestationVerificationResult::kAttestationSignatureInvalid);
 
-    uint8_t akidBuf[Credentials::kKeyIdentifierLength];
+    uint8_t akidBuf[Crypto::kAuthorityKeyIdentifierLength];
     MutableByteSpan akid(akidBuf);
     ExtractAKIDFromX509Cert(paiCertDerBuffer, akid);
 
@@ -254,7 +245,7 @@ AttestationVerificationResult DefaultDACVerifier::VerifyAttestationInformation(c
     chip::Platform::ScopedMemoryBuffer<uint8_t> paaCert;
     VerifyOrReturnError(paaCert.Alloc(paaCertAllocatedLen), AttestationVerificationResult::kNoMemory);
     MutableByteSpan paa(paaCert.Get(), paaCertAllocatedLen);
-    VerifyOrReturnError(GetProductAttestationAuthorityCert(akid, paa) == CHIP_NO_ERROR,
+    VerifyOrReturnError(mAttestationTrustStore->GetProductAttestationAuthorityCert(akid, paa) == CHIP_NO_ERROR,
                         AttestationVerificationResult::kPaaNotFound);
 
     VerifyOrReturnError(ValidateCertificateChain(paa.data(), paa.size(), paiCertDerBuffer.data(), paiCertDerBuffer.size(),
@@ -279,9 +270,9 @@ AttestationVerificationResult DefaultDACVerifier::VerifyAttestationInformation(c
     ByteSpan firmwareInfoSpan;
     DeviceAttestationVendorReservedDeconstructor vendorReserved;
 
-    VerifyOrReturnError(DeconstructAttestationElements(attestationInfoBuffer, certificationDeclarationSpan, attestationNonceSpan,
-                                                       timestampDeconstructed, firmwareInfoSpan, vendorReserved) == CHIP_NO_ERROR,
-                        AttestationVerificationResult::kAttestationElementsMalformed);
+    CHIP_ERROR status = DeconstructAttestationElements(attestationInfoBuffer, certificationDeclarationSpan, attestationNonceSpan,
+                                                       timestampDeconstructed, firmwareInfoSpan, vendorReserved);
+    VerifyOrReturnError(status == CHIP_NO_ERROR, AttestationVerificationResult::kAttestationElementsMalformed);
 
     // Verify that Nonce matches with what we sent
     VerifyOrReturnError(attestationNonceSpan.data_equal(attestationNonce),
@@ -397,9 +388,14 @@ AttestationVerificationResult DefaultDACVerifier::ValidateCertificateDeclaration
 
 } // namespace
 
-DeviceAttestationVerifier * GetDefaultDACVerifier()
+const AttestationTrustStore * GetTestAttestationTrustStore()
+{
+    return &kTestAttestationTrustStore;
+}
+
+DeviceAttestationVerifier * GetDefaultDACVerifier(const AttestationTrustStore * paaRootStore)
 {
-    static DefaultDACVerifier defaultDACVerifier;
+    static DefaultDACVerifier defaultDACVerifier{ paaRootStore };
 
     return &defaultDACVerifier;
 }
diff --git a/src/credentials/examples/DefaultDeviceAttestationVerifier.h b/src/credentials/examples/DefaultDeviceAttestationVerifier.h
index aad200fdd3e434..4198e1c147348b 100644
--- a/src/credentials/examples/DefaultDeviceAttestationVerifier.h
+++ b/src/credentials/examples/DefaultDeviceAttestationVerifier.h
@@ -21,14 +21,30 @@
 namespace chip {
 namespace Credentials {
 
+/**
+ * @brief Get implementation of a PAA root store containing a basic set of static PAA roots
+ *        sufficient for *testing* only.
+ *
+ * WARNING: The PAA list known to this PAA root store is a reduced subset that will likely
+ *          cause users of it to fail attestation procedure in some cases. This is provided
+ *          to support tests and examples, not to be used by real commissioners, as it
+ *          contains several test roots which are not trustworthy for certified product usage.
+ *
+ * @returns a singleton AttestationTrustStore that contains some well-known PAA test root certs.
+ */
+const AttestationTrustStore * GetTestAttestationTrustStore();
+
 /**
  * @brief Get implementation of a sample DAC verifier to validate device
  *        attestation procedure.
  *
- * @returns a singleton DeviceAttestationVerifier that relies on no
- *          storage abstractions.
+ * @param[in] paaRootStore Pointer to the AttestationTrustStore instance to be used by implementation
+ *                         of default DeviceAttestationVerifier. Caller must ensure storage is
+ *                         always available while the DeviceAttestationVerifier could be used.
+ *
+ * @returns a singleton DeviceAttestationVerifier that satisfies basic device attestation procedure requirements.
  */
-DeviceAttestationVerifier * GetDefaultDACVerifier();
+DeviceAttestationVerifier * GetDefaultDACVerifier(const AttestationTrustStore * paaRootStore);
 
 } // namespace Credentials
 } // namespace chip
diff --git a/src/credentials/tests/TestCertificationDeclaration.cpp b/src/credentials/tests/TestCertificationDeclaration.cpp
index 12e49518de3e8f..3d15f39f2ea02e 100644
--- a/src/credentials/tests/TestCertificationDeclaration.cpp
+++ b/src/credentials/tests/TestCertificationDeclaration.cpp
@@ -247,7 +247,7 @@ static void TestCD_CMSSignAndVerify(nlTestSuite * inSuite, void * inContext)
 {
     ByteSpan cdContentIn(sTestCMS_CDContent01);
     ByteSpan cdContentOut;
-    uint8_t signerKeyIdBuf[kKeyIdentifierLength];
+    uint8_t signerKeyIdBuf[Crypto::kSubjectKeyIdentifierLength];
     MutableByteSpan signerKeyId(signerKeyIdBuf);
     uint8_t signedMessageBuf[kMaxCMSSignedCDMessage];
     MutableByteSpan signedMessage(signedMessageBuf);
@@ -297,7 +297,7 @@ static void TestCD_CMSVerifyAndExtract(nlTestSuite * inSuite, void * inContext)
         NL_TEST_ASSERT(inSuite, testCase.cdContent.data_equal(cdContentOut));
 
         // Test CMS_ExtractKeyId()
-        uint8_t signerKeyIdBuf[kKeyIdentifierLength];
+        uint8_t signerKeyIdBuf[Crypto::kSubjectKeyIdentifierLength];
         MutableByteSpan signerKeyId(signerKeyIdBuf);
         NL_TEST_ASSERT(inSuite, ExtractSKIDFromX509Cert(testCase.signerCert, signerKeyId) == CHIP_NO_ERROR);
 
diff --git a/src/credentials/tests/TestDeviceAttestationCredentials.cpp b/src/credentials/tests/TestDeviceAttestationCredentials.cpp
index f706582ddc087e..ea2de206212702 100644
--- a/src/credentials/tests/TestDeviceAttestationCredentials.cpp
+++ b/src/credentials/tests/TestDeviceAttestationCredentials.cpp
@@ -195,8 +195,7 @@ static void TestDACVerifierExample_AttestationInfoVerification(nlTestSuite * inS
         default_verifier->VerifyAttestationInformation(ByteSpan(), ByteSpan(), ByteSpan(), ByteSpan(), ByteSpan(), ByteSpan());
     NL_TEST_ASSERT(inSuite, attestation_result == AttestationVerificationResult::kNotImplemented);
 
-    // Replace default verifier with example verifier
-    DeviceAttestationVerifier * example_dac_verifier = GetDefaultDACVerifier();
+    DeviceAttestationVerifier * example_dac_verifier = GetDefaultDACVerifier(GetTestAttestationTrustStore());
     NL_TEST_ASSERT(inSuite, example_dac_verifier != nullptr);
     NL_TEST_ASSERT(inSuite, default_verifier != example_dac_verifier);
 
@@ -252,7 +251,7 @@ static void TestDACVerifierExample_CertDeclarationVerification(nlTestSuite * inS
     CHIP_ERROR err = CHIP_NO_ERROR;
 
     // Replace default verifier with example verifier
-    DeviceAttestationVerifier * example_dac_verifier = GetDefaultDACVerifier();
+    DeviceAttestationVerifier * example_dac_verifier = GetDefaultDACVerifier(GetTestAttestationTrustStore());
     NL_TEST_ASSERT(inSuite, example_dac_verifier != nullptr);
 
     SetDeviceAttestationVerifier(example_dac_verifier);
@@ -295,6 +294,80 @@ static void TestDACVerifierExample_CertDeclarationVerification(nlTestSuite * inS
     NL_TEST_ASSERT(inSuite, attestation_result == AttestationVerificationResult::kSuccess);
 }
 
+static void TestAttestationTrustStore(nlTestSuite * inSuite, void * inContext)
+{
+    uint8_t kPaaFff1Start[] = { 0x30, 0x82, 0x01, 0x99, 0x30, 0x82, 0x01, 0x3F, 0xA0, 0x03, 0x02, 0x01, 0x02,
+                                0x02, 0x08, 0x68, 0x38, 0x4F, 0xAB, 0xB9, 0x19, 0xFC, 0xDF, 0x30, 0x0A, 0x06,
+                                0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1F, 0x31 };
+    uint8_t kPaaFff1Skid[]  = { 0xEF, 0x18, 0xE0, 0xEC, 0xD4, 0x66, 0x04, 0x34, 0xDF, 0x0D,
+                               0xBC, 0x91, 0x1E, 0xD4, 0x52, 0x16, 0x99, 0x66, 0x83, 0x9F };
+
+    uint8_t kPaaFff2Start[] = { 0x30, 0x82, 0x01, 0x9D, 0x30, 0x82, 0x01, 0x42, 0xA0, 0x03, 0x02, 0x01, 0x02,
+                                0x02, 0x08, 0x03, 0x92, 0xA7, 0x65, 0x5A, 0x3E, 0x6C, 0x77, 0x30, 0x0A, 0x06,
+                                0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1F, 0x31 };
+    uint8_t kPaaFff2Skid[]  = { 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0x5F, 0xD0, 0xC3, 0xE6,
+                               0x34, 0x52, 0x9F, 0x16, 0x70, 0x46, 0xC4, 0xBC, 0xA5, 0x5C };
+
+    // SKID to trigger CHIP_ERROR_INVALID_ARGUMENT
+    uint8_t kPaaBadSkid1[] = { 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0xD0, 0xC3, 0xE6, 0x34,
+                               0x52, 0x9F, 0x16, 0x70, 0x46, 0xC4, 0xBC, 0xA5, 0x5C };
+    ByteSpan kPaaBadSkidSpan1{ kPaaBadSkid1 };
+
+    // SKID to trigger CHIP_ERROR_INVALID_ARGUMENT
+    ByteSpan kPaaBadSkidSpan2{ nullptr, sizeof(kPaaFff2Skid) };
+
+    // SKID to trigger CHIP_ERROR_CA_CERT_NOT_FOUND
+    uint8_t kPaaGoodSkidNotPresent[] = { 0xE7, 0xEF, 0xEA, 0xC3, 0x33, 0x5C, 0x5F, 0xD0, 0xC3, 0xE6,
+                                         0x34, 0x52, 0x9F, 0x16, 0x70, 0xFF, 0xFF, 0xBC, 0xA5, 0x5C };
+
+    struct TestCase
+    {
+        ByteSpan skidSpan;
+        ByteSpan startSpan;
+        CHIP_ERROR expectedResult;
+    };
+
+    const TestCase kTestCases[] = {
+        { .skidSpan = ByteSpan{ kPaaFff1Skid }, .startSpan = ByteSpan{ kPaaFff1Start }, .expectedResult = CHIP_NO_ERROR },
+        { .skidSpan = ByteSpan{ kPaaFff2Skid }, .startSpan = ByteSpan{ kPaaFff2Start }, .expectedResult = CHIP_NO_ERROR },
+        { .skidSpan       = ByteSpan{ kPaaFff2Skid },
+          .startSpan      = ByteSpan{ kPaaFff2Start },
+          .expectedResult = CHIP_ERROR_BUFFER_TOO_SMALL },
+        { .skidSpan = kPaaBadSkidSpan1, .startSpan = ByteSpan{}, .expectedResult = CHIP_ERROR_INVALID_ARGUMENT },
+        { .skidSpan = kPaaBadSkidSpan2, .startSpan = ByteSpan{}, .expectedResult = CHIP_ERROR_INVALID_ARGUMENT },
+        { .skidSpan = ByteSpan{ kPaaGoodSkidNotPresent }, .startSpan = ByteSpan{}, .expectedResult = CHIP_ERROR_CA_CERT_NOT_FOUND },
+    };
+
+    const AttestationTrustStore * testAttestationTrustStore = GetTestAttestationTrustStore();
+    NL_TEST_ASSERT(inSuite, testAttestationTrustStore != nullptr);
+
+    size_t testCaseIdx = 0;
+    for (const auto & testCase : kTestCases)
+    {
+        uint8_t buf[kMaxDERCertLength];
+        MutableByteSpan paaCertSpan{ buf };
+        if (testCase.expectedResult == CHIP_ERROR_BUFFER_TOO_SMALL)
+        {
+            // Make the output much too small if checking for size handling
+            paaCertSpan = paaCertSpan.SubSpan(0, 16);
+        }
+
+        // Try to obtain cert
+        CHIP_ERROR result = testAttestationTrustStore->GetProductAttestationAuthorityCert(testCase.skidSpan, paaCertSpan);
+        NL_TEST_ASSERT(inSuite, result == testCase.expectedResult);
+
+        // In success cases, make sure the start of the cert matches expectation. Not using full certs
+        // to avoid repeating the known constants here.
+        if (testCase.expectedResult == CHIP_NO_ERROR)
+        {
+            NL_TEST_ASSERT(inSuite, paaCertSpan.size() > testCase.startSpan.size());
+            paaCertSpan = paaCertSpan.SubSpan(0, testCase.startSpan.size());
+            NL_TEST_ASSERT(inSuite, paaCertSpan.data_equal(testCase.startSpan) == true);
+        }
+        ++testCaseIdx;
+    }
+}
+
 /**
  *  Set up the test suite.
  */
@@ -326,6 +399,7 @@ int TestDeviceAttestation_Teardown(void * inContext)
 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 the 'for testing' Paa Root Store", TestAttestationTrustStore),
     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()
diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h
index 1d55e72a060cbd..78a58be47eb604 100644
--- a/src/crypto/CHIPCryptoPAL.h
+++ b/src/crypto/CHIPCryptoPAL.h
@@ -46,6 +46,8 @@ constexpr size_t kP256_ECDSA_Signature_Length_Raw = (2 * kP256_FE_Length);
 constexpr size_t kP256_Point_Length               = (2 * kP256_FE_Length + 1);
 constexpr size_t kSHA256_Hash_Length              = 32;
 constexpr size_t kSHA1_Hash_Length                = 20;
+constexpr size_t kSubjectKeyIdentifierLength      = kSHA1_Hash_Length;
+constexpr size_t kAuthorityKeyIdentifierLength    = kSHA1_Hash_Length;
 
 constexpr size_t CHIP_CRYPTO_GROUP_SIZE_BYTES      = kP256_FE_Length;
 constexpr size_t CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES = kP256_Point_Length;
diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp
index df2a737913afd6..dc3989bec15880 100644
--- a/src/crypto/tests/CHIPCryptoPALTest.cpp
+++ b/src/crypto/tests/CHIPCryptoPALTest.cpp
@@ -1874,7 +1874,7 @@ static void TestSKID_x509Extraction(nlTestSuite * inSuite, void * inContext)
 
     HeapChecker heapChecker(inSuite);
     CHIP_ERROR err = CHIP_NO_ERROR;
-    uint8_t skidBuf[Credentials::kKeyIdentifierLength];
+    uint8_t skidBuf[kSubjectKeyIdentifierLength];
     MutableByteSpan skidOut(skidBuf);
 
     ByteSpan cert;
@@ -1901,7 +1901,7 @@ static void TestAKID_x509Extraction(nlTestSuite * inSuite, void * inContext)
 
     HeapChecker heapChecker(inSuite);
     CHIP_ERROR err = CHIP_NO_ERROR;
-    uint8_t akidBuf[Credentials::kKeyIdentifierLength];
+    uint8_t akidBuf[kAuthorityKeyIdentifierLength];
     MutableByteSpan akidOut(akidBuf);
 
     ByteSpan cert;
diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.mm b/src/darwin/Framework/CHIP/CHIPDeviceController.mm
index 794d6ed7ccd24f..1986c664cdbcda 100644
--- a/src/darwin/Framework/CHIP/CHIPDeviceController.mm
+++ b/src/darwin/Framework/CHIP/CHIPDeviceController.mm
@@ -190,7 +190,9 @@ - (BOOL)startup:(_Nullable id<CHIPPersistentStorageDelegate>)storageDelegate
         }
 
         // Initialize device attestation verifier
-        chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier());
+        // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available
+        const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore();
+        chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier(testingRootStore));
 
         params.fabricStorage = _fabricStorage;
         commissionerParams.storageDelegate = _persistentStorageDelegateBridge;
diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h
index a8bbadd3cf1b75..71cda76e5eabd7 100644
--- a/src/protocols/secure_channel/CASESession.h
+++ b/src/protocols/secure_channel/CASESession.h
@@ -47,7 +47,7 @@
 namespace chip {
 
 constexpr uint16_t kSigmaParamRandomNumberSize = 32;
-constexpr uint16_t kTrustedRootIdSize          = Credentials::kKeyIdentifierLength;
+constexpr uint16_t kTrustedRootIdSize          = Crypto::kSubjectKeyIdentifierLength;
 constexpr uint16_t kMaxTrustedRootIds          = 5;
 
 constexpr uint16_t kIPKSize = 16;