Added an interface for revocation checks to DeviceAttestationVerifier (#31222)

* Added an interface for revocation checks to DeviceAttestationVerifier

* Addressed review comments

* Removed the changes to add revocation set support to chip-tool and it will be submitted as a followup PR

* Implemented PR #31222 review comments

* Fixed issues in revocation check and code cleanup
diff --git a/docs/ERROR_CODES.md b/docs/ERROR_CODES.md
index ecfda40..5799c7a 100644
--- a/docs/ERROR_CODES.md
+++ b/docs/ERROR_CODES.md
@@ -47,6 +47,7 @@
 | 29        | 0x1D  | `CHIP_ERROR_INVALID_IPK`                           |
 | 30        | 0x1E  | `CHIP_ERROR_INVALID_STRING_LENGTH`                 |
 | 31        | 0x1F  | `CHIP_ERROR_INVALID_LIST_LENGTH`                   |
+| 32        | 0x20  | `CHIP_ERROR_FAILED_DEVICE_ATTESTATION`             |
 | 33        | 0x21  | `CHIP_ERROR_END_OF_TLV`                            |
 | 34        | 0x22  | `CHIP_ERROR_TLV_UNDERRUN`                          |
 | 35        | 0x23  | `CHIP_ERROR_INVALID_TLV_ELEMENT`                   |
diff --git a/src/controller/AutoCommissioner.cpp b/src/controller/AutoCommissioner.cpp
index a59ff82..5b37988 100644
--- a/src/controller/AutoCommissioner.cpp
+++ b/src/controller/AutoCommissioner.cpp
@@ -389,6 +389,8 @@
     case CommissioningStage::kSendAttestationRequest:
         return CommissioningStage::kAttestationVerification;
     case CommissioningStage::kAttestationVerification:
+        return CommissioningStage::kAttestationRevocationCheck;
+    case CommissioningStage::kAttestationRevocationCheck:
         return CommissioningStage::kSendOpCertSigningRequest;
     case CommissioningStage::kSendOpCertSigningRequest:
         return CommissioningStage::kValidateCSR;
@@ -693,6 +695,13 @@
                              "Failed device attestation. Device vendor and/or product ID do not match the IDs expected. "
                              "Verify DAC certificate chain and certification declaration to ensure spec rules followed.");
             }
+
+            if (report.stageCompleted == CommissioningStage::kAttestationVerification)
+            {
+                ChipLogError(Controller, "Failed verifying attestation information. Now checking DAC chain revoked status.");
+                // don't error out until we check for DAC chain revocation status
+                err = CHIP_NO_ERROR;
+            }
         }
         else if (report.Is<CommissioningErrorInfo>())
         {
diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp
index bb11432..910c0b2 100644
--- a/src/controller/CHIPDeviceController.cpp
+++ b/src/controller/CHIPDeviceController.cpp
@@ -947,7 +947,7 @@
         return CHIP_ERROR_INCORRECT_STATE;
     }
 
-    if (mCommissioningStage != CommissioningStage::kAttestationVerification)
+    if (mCommissioningStage != CommissioningStage::kAttestationRevocationCheck)
     {
         ChipLogError(Controller, "Commissioning is not attestation verification phase");
         return CHIP_ERROR_INCORRECT_STATE;
@@ -1175,6 +1175,17 @@
     MATTER_TRACE_SCOPE("OnDeviceAttestationInformationVerification", "DeviceCommissioner");
     DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
 
+    if (commissioner->mCommissioningStage == CommissioningStage::kAttestationVerification)
+    {
+        // Check for revoked DAC Chain before calling delegate. Enter next stage.
+
+        CommissioningDelegate::CommissioningReport report;
+        report.Set<AttestationErrorInfo>(result);
+
+        return commissioner->CommissioningStageComplete(
+            result == AttestationVerificationResult::kSuccess ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL, report);
+    }
+
     if (!commissioner->mDeviceBeingCommissioned)
     {
         ChipLogError(Controller, "Device attestation verification result received when we're not commissioning a device");
@@ -1184,6 +1195,15 @@
     auto & params = commissioner->mDefaultCommissioner->GetCommissioningParameters();
     Credentials::DeviceAttestationDelegate * deviceAttestationDelegate = params.GetDeviceAttestationDelegate();
 
+    if (params.GetCompletionStatus().attestationResult.HasValue())
+    {
+        auto previousResult = params.GetCompletionStatus().attestationResult.Value();
+        if (previousResult != AttestationVerificationResult::kSuccess)
+        {
+            result = previousResult;
+        }
+    }
+
     if (result != AttestationVerificationResult::kSuccess)
     {
         CommissioningDelegate::CommissioningReport report;
@@ -1398,6 +1418,18 @@
     return CHIP_NO_ERROR;
 }
 
+CHIP_ERROR
+DeviceCommissioner::CheckForRevokedDACChain(const Credentials::DeviceAttestationVerifier::AttestationInfo & info)
+{
+    MATTER_TRACE_SCOPE("CheckForRevokedDACChain", "DeviceCommissioner");
+    VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
+    VerifyOrReturnError(mDeviceAttestationVerifier != nullptr, CHIP_ERROR_INCORRECT_STATE);
+
+    mDeviceAttestationVerifier->CheckForRevokedDACChain(info, &mDeviceAttestationInformationVerificationCallback);
+
+    return CHIP_NO_ERROR;
+}
+
 CHIP_ERROR DeviceCommissioner::ValidateCSR(DeviceProxy * proxy, const ByteSpan & NOCSRElements,
                                            const ByteSpan & AttestationSignature, const ByteSpan & dac, const ByteSpan & csrNonce)
 {
@@ -3037,9 +3069,7 @@
     }
     case CommissioningStage::kAttestationVerification: {
         ChipLogProgress(Controller, "Verifying attestation");
-        if (!params.GetAttestationElements().HasValue() || !params.GetAttestationSignature().HasValue() ||
-            !params.GetAttestationNonce().HasValue() || !params.GetDAC().HasValue() || !params.GetPAI().HasValue() ||
-            !params.GetRemoteVendorId().HasValue() || !params.GetRemoteProductId().HasValue())
+        if (IsAttestationInformationMissing(params))
         {
             ChipLogError(Controller, "Missing attestation information");
             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
@@ -3055,9 +3085,32 @@
         if (ValidateAttestationInfo(info) != CHIP_NO_ERROR)
         {
             ChipLogError(Controller, "Error validating attestation information");
+            CommissioningStageComplete(CHIP_ERROR_FAILED_DEVICE_ATTESTATION);
+            return;
+        }
+    }
+    break;
+    case CommissioningStage::kAttestationRevocationCheck: {
+        ChipLogProgress(Controller, "Verifying device's DAC chain revocation status");
+        if (IsAttestationInformationMissing(params))
+        {
+            ChipLogError(Controller, "Missing attestation information");
             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
             return;
         }
+
+        DeviceAttestationVerifier::AttestationInfo info(
+            params.GetAttestationElements().Value(),
+            proxy->GetSecureSession().Value()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge(),
+            params.GetAttestationSignature().Value(), params.GetPAI().Value(), params.GetDAC().Value(),
+            params.GetAttestationNonce().Value(), params.GetRemoteVendorId().Value(), params.GetRemoteProductId().Value());
+
+        if (CheckForRevokedDACChain(info) != CHIP_NO_ERROR)
+        {
+            ChipLogError(Controller, "Error validating device's DAC chain revocation status");
+            CommissioningStageComplete(CHIP_ERROR_FAILED_DEVICE_ATTESTATION);
+            return;
+        }
     }
     break;
     case CommissioningStage::kSendOpCertSigningRequest: {
@@ -3424,6 +3477,18 @@
     }
 }
 
+bool DeviceCommissioner::IsAttestationInformationMissing(const CommissioningParameters & params)
+{
+    if (!params.GetAttestationElements().HasValue() || !params.GetAttestationSignature().HasValue() ||
+        !params.GetAttestationNonce().HasValue() || !params.GetDAC().HasValue() || !params.GetPAI().HasValue() ||
+        !params.GetRemoteVendorId().HasValue() || !params.GetRemoteProductId().HasValue())
+    {
+        return true;
+    }
+
+    return false;
+}
+
 CHIP_ERROR DeviceController::GetCompressedFabricIdBytes(MutableByteSpan & outBytes) const
 {
     const auto * fabricInfo = GetFabricInfo();
diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h
index 42b8a7e..8bef525 100644
--- a/src/controller/CHIPDeviceController.h
+++ b/src/controller/CHIPDeviceController.h
@@ -1000,6 +1000,14 @@
      */
     CHIP_ERROR ProcessCertificateChain(const ByteSpan & certificate);
 
+    /**
+     * @brief
+     *   This function validates the revocation status of the DAC Chain sent by the device.
+     *
+     * @param[in] info Structure contatining all the required information for validating the device attestation.
+     */
+    CHIP_ERROR CheckForRevokedDACChain(const Credentials::DeviceAttestationVerifier::AttestationInfo & info);
+
     void HandleAttestationResult(CHIP_ERROR err);
 
     CommissioneeDeviceProxy * FindCommissioneeDevice(NodeId id);
@@ -1053,6 +1061,8 @@
     // extend it).
     void ExtendFailsafeBeforeNetworkEnable(DeviceProxy * device, CommissioningParameters & params, CommissioningStage step);
 
+    bool IsAttestationInformationMissing(const CommissioningParameters & params);
+
     chip::Callback::Callback<OnDeviceConnected> mOnDeviceConnectedCallback;
     chip::Callback::Callback<OnDeviceConnectionFailure> mOnDeviceConnectionFailureCallback;
 #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
diff --git a/src/controller/CommissioningDelegate.cpp b/src/controller/CommissioningDelegate.cpp
index bbe82de..b3e3b6c 100644
--- a/src/controller/CommissioningDelegate.cpp
+++ b/src/controller/CommissioningDelegate.cpp
@@ -70,6 +70,9 @@
     case kAttestationVerification:
         return "AttestationVerification";
 
+    case kAttestationRevocationCheck:
+        return "AttestationRevocationCheck";
+
     case kSendOpCertSigningRequest:
         return "SendOpCertSigningRequest";
 
diff --git a/src/controller/CommissioningDelegate.h b/src/controller/CommissioningDelegate.h
index fae510b..e79ad1d 100644
--- a/src/controller/CommissioningDelegate.h
+++ b/src/controller/CommissioningDelegate.h
@@ -47,6 +47,7 @@
     kSendDACCertificateRequest,  ///< Send DAC CertificateChainRequest (0x3E:2) command to the device
     kSendAttestationRequest,     ///< Send AttestationRequest (0x3E:0) command to the device
     kAttestationVerification,    ///< Verify AttestationResponse (0x3E:1) validity
+    kAttestationRevocationCheck, ///< Verify Revocation Status of device's DAC chain
     kSendOpCertSigningRequest,   ///< Send CSRRequest (0x3E:4) command to the device
     kValidateCSR,                ///< Verify CSRResponse (0x3E:5) validity
     kGenerateNOCChain,           ///< TLV encode Node Operational Credentials (NOC) chain certs
@@ -782,6 +783,7 @@
      * kSendDACCertificateRequest: RequestedCertificate
      * kSendAttestationRequest: AttestationResponse
      * kAttestationVerification: AttestationErrorInfo if there is an error
+     * kAttestationRevocationCheck: AttestationErrorInfo if there is an error
      * kSendOpCertSigningRequest: CSRResponse
      * kGenerateNOCChain: NocChain
      * kSendTrustedRootCert: None
diff --git a/src/controller/python/OpCredsBinding.cpp b/src/controller/python/OpCredsBinding.cpp
index 66a6c84..5fd4205 100644
--- a/src/controller/python/OpCredsBinding.cpp
+++ b/src/controller/python/OpCredsBinding.cpp
@@ -331,6 +331,8 @@
             return mNeedsDST && mParams.GetDSTOffsets().HasValue();
         case chip::Controller::CommissioningStage::kError:
         case chip::Controller::CommissioningStage::kSecurePairing:
+        // "not valid" because attestation verification always fails after entering revocation check step
+        case chip::Controller::CommissioningStage::kAttestationVerification:
             return false;
         default:
             return true;
diff --git a/src/controller/python/test/test_scripts/commissioning_failure_test.py b/src/controller/python/test/test_scripts/commissioning_failure_test.py
index 4681dd1..eca1706 100755
--- a/src/controller/python/test/test_scripts/commissioning_failure_test.py
+++ b/src/controller/python/test/test_scripts/commissioning_failure_test.py
@@ -96,7 +96,7 @@
 
     # TODO: Start at stage 2 once handling for arming failsafe on pase is done.
     if options.report:
-        for testFailureStage in range(3, 20):
+        for testFailureStage in range(3, 21):
             FailIfNot(test.TestPaseOnly(ip=options.deviceAddress1,
                                         setuppin=20202021,
                                         nodeid=1),
@@ -105,7 +105,7 @@
                       "Commissioning failure tests failed for simulated report failure on stage {}".format(testFailureStage))
 
     else:
-        for testFailureStage in range(3, 20):
+        for testFailureStage in range(3, 21):
             FailIfNot(test.TestPaseOnly(ip=options.deviceAddress1,
                                         setuppin=20202021,
                                         nodeid=1),
diff --git a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp
index 0d7f67f..f3444b0 100644
--- a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp
+++ b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp
@@ -607,6 +607,16 @@
     return CHIP_NO_ERROR;
 }
 
+void DefaultDACVerifier::CheckForRevokedDACChain(const AttestationInfo & info,
+                                                 Callback::Callback<OnAttestationInformationVerification> * onCompletion)
+{
+    AttestationVerificationResult attestationError = AttestationVerificationResult::kSuccess;
+
+    // TODO(#33124): Implement default version of CheckForRevokedDACChain
+
+    onCompletion->mCall(onCompletion->mContext, info, attestationError);
+}
+
 bool CsaCdKeysTrustStore::IsCdTestKey(const ByteSpan & kid) const
 {
     return kid.data_equal(ByteSpan{ gTestCdPubkeyKid });
diff --git a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h
index bdf7f70..346d098 100644
--- a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h
+++ b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h
@@ -74,6 +74,9 @@
                                                    const ByteSpan & attestationSignatureBuffer,
                                                    const Crypto::P256PublicKey & dacPublicKey, const ByteSpan & csrNonce) override;
 
+    void CheckForRevokedDACChain(const AttestationInfo & info,
+                                 Callback::Callback<OnAttestationInformationVerification> * onCompletion) override;
+
     CsaCdKeysTrustStore * GetCertificationDeclarationTrustStore() override { return &mCdKeysTrustStore; }
 
 protected:
diff --git a/src/credentials/attestation_verifier/DeviceAttestationVerifier.cpp b/src/credentials/attestation_verifier/DeviceAttestationVerifier.cpp
index cc5d9d3..5bdbb9a 100644
--- a/src/credentials/attestation_verifier/DeviceAttestationVerifier.cpp
+++ b/src/credentials/attestation_verifier/DeviceAttestationVerifier.cpp
@@ -69,6 +69,14 @@
         (void) csrNonce;
         return CHIP_ERROR_NOT_IMPLEMENTED;
     }
+
+    void CheckForRevokedDACChain(const AttestationInfo & info,
+                                 Callback::Callback<OnAttestationInformationVerification> * onCompletion) override
+    {
+        (void) info;
+        (void) onCompletion;
+        VerifyOrDie(false);
+    }
 };
 
 // Default to avoid nullptr on getter and cleanly handle new products/clients before
diff --git a/src/credentials/attestation_verifier/DeviceAttestationVerifier.h b/src/credentials/attestation_verifier/DeviceAttestationVerifier.h
index 9465d93..f45ceae 100644
--- a/src/credentials/attestation_verifier/DeviceAttestationVerifier.h
+++ b/src/credentials/attestation_verifier/DeviceAttestationVerifier.h
@@ -387,6 +387,16 @@
                                                            const ByteSpan & csrNonce) = 0;
 
     /**
+     * @brief Verify whether or not the given DAC chain is revoked.
+     *
+     * @param[in] info All of the information required to check for revoked DAC chain.
+     * @param[in] onCompletion Callback handler to provide Attestation Information Verification result to the caller of
+     *                         CheckForRevokedDACChain()
+     */
+    virtual void CheckForRevokedDACChain(const AttestationInfo & info,
+                                         Callback::Callback<OnAttestationInformationVerification> * onCompletion) = 0;
+
+    /**
      * @brief Get the trust store used for the attestation verifier.
      *
      * Returns nullptr if not supported. Be careful not to hold-on to the trust store
diff --git a/src/lib/core/CHIPError.cpp b/src/lib/core/CHIPError.cpp
index 68a44d8..2b2461c 100644
--- a/src/lib/core/CHIPError.cpp
+++ b/src/lib/core/CHIPError.cpp
@@ -146,6 +146,9 @@
     case CHIP_ERROR_INVALID_LIST_LENGTH.AsInteger():
         desc = "Invalid list length";
         break;
+    case CHIP_ERROR_FAILED_DEVICE_ATTESTATION.AsInteger():
+        desc = "Failed Device Attestation";
+        break;
     case CHIP_END_OF_TLV.AsInteger():
         desc = "End of TLV";
         break;
diff --git a/src/lib/core/CHIPError.h b/src/lib/core/CHIPError.h
index 37001c8..370a7d3 100644
--- a/src/lib/core/CHIPError.h
+++ b/src/lib/core/CHIPError.h
@@ -743,7 +743,14 @@
  */
 #define CHIP_ERROR_INVALID_LIST_LENGTH                         CHIP_CORE_ERROR(0x1f)
 
-// AVAILABLE: 0x20
+/**
+ *  @def CHIP_ERROR_FAILED_DEVICE_ATTESTATION
+ *
+ *  @brief
+ *    Device Attestation failed.
+ *
+ */
+#define CHIP_ERROR_FAILED_DEVICE_ATTESTATION                   CHIP_CORE_ERROR(0x20)
 
 /**
  *  @def CHIP_END_OF_TLV
diff --git a/src/lib/core/tests/TestCHIPErrorStr.cpp b/src/lib/core/tests/TestCHIPErrorStr.cpp
index 730a484..54e187c 100644
--- a/src/lib/core/tests/TestCHIPErrorStr.cpp
+++ b/src/lib/core/tests/TestCHIPErrorStr.cpp
@@ -69,6 +69,7 @@
     CHIP_ERROR_UNINITIALIZED,
     CHIP_ERROR_INVALID_STRING_LENGTH,
     CHIP_ERROR_INVALID_LIST_LENGTH,
+    CHIP_ERROR_FAILED_DEVICE_ATTESTATION,
     CHIP_END_OF_TLV,
     CHIP_ERROR_TLV_UNDERRUN,
     CHIP_ERROR_INVALID_TLV_ELEMENT,
diff --git a/src/python_testing/TC_CGEN_2_4.py b/src/python_testing/TC_CGEN_2_4.py
index 23ab28e..7bb2e6d 100644
--- a/src/python_testing/TC_CGEN_2_4.py
+++ b/src/python_testing/TC_CGEN_2_4.py
@@ -34,9 +34,9 @@
 kSendPAICertificateRequest = 10
 kSendDACCertificateRequest = 11
 kSendAttestationRequest = 12
-kSendOpCertSigningRequest = 14
-kSendTrustedRootCert = 17
-kSendNOC = 18
+kSendOpCertSigningRequest = 15
+kSendTrustedRootCert = 18
+kSendNOC = 19
 
 
 class TC_CGEN_2_4(MatterBaseTest):