Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added an interface for revocation checks to DeviceAttestationVerifier #31222

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/controller/AutoCommissioner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,8 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStageInternal(Commissio
case CommissioningStage::kSendAttestationRequest:
return CommissioningStage::kAttestationVerification;
case CommissioningStage::kAttestationVerification:
return CommissioningStage::kAttestationRevocationCheck;
case CommissioningStage::kAttestationRevocationCheck:
return CommissioningStage::kSendOpCertSigningRequest;
case CommissioningStage::kSendOpCertSigningRequest:
return CommissioningStage::kValidateCSR;
Expand Down
98 changes: 96 additions & 2 deletions src/controller/CHIPDeviceController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ DeviceCommissioner::DeviceCommissioner() :
mOnDeviceConnectionRetryCallback(OnDeviceConnectionRetryFn, this),
#endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
mDeviceAttestationInformationVerificationCallback(OnDeviceAttestationInformationVerification, this),
mDACChainRevocationStatusVerificationCallback(OnDACChainRevocationStatusVerification, this),
mDeviceNOCChainCallback(OnDeviceNOCChainGeneration, this), mSetUpCodePairer(this)
{}

Expand Down Expand Up @@ -877,7 +878,8 @@ DeviceCommissioner::ContinueCommissioningAfterDeviceAttestation(DeviceProxy * de
return CHIP_ERROR_INCORRECT_STATE;
}

if (mCommissioningStage != CommissioningStage::kAttestationVerification)
if (mCommissioningStage != CommissioningStage::kAttestationVerification &&
mCommissioningStage != CommissioningStage::kAttestationRevocationCheck)
{
ChipLogError(Controller, "Commissioning is not attestation verification phase");
return CHIP_ERROR_INCORRECT_STATE;
Expand Down Expand Up @@ -1146,14 +1148,69 @@ void DeviceCommissioner::OnDeviceAttestationInformationVerification(
}
}
else
{
{
ChipLogProgress(Controller, "Successfully validated 'Attestation Information' command received from the device.");
commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
}
}
}

void DeviceCommissioner::OnDACChainRevocationStatusVerification(
void * context, const Credentials::DeviceAttestationVerifier::AttestationInfo & info, AttestationVerificationResult result)
{
MATTER_TRACE_SCOPE("OnDACChainRevocationStatusVerification", "DeviceCommissioner");
DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);

if (!commissioner->mDeviceBeingCommissioned)
{
ChipLogError(Controller, "Device attestation verification result received when we're not commissioning a device");
return;
}

auto & params = commissioner->mDefaultCommissioner->GetCommissioningParameters();
Credentials::DeviceAttestationDelegate * deviceAttestationDelegate = params.GetDeviceAttestationDelegate();

if (result != AttestationVerificationResult::kSuccess)
{
CommissioningDelegate::CommissioningReport report;
report.Set<AttestationErrorInfo>(result);
if (result == AttestationVerificationResult::kNotImplemented)
{
ChipLogError(Controller,
"Failed in verifying 'DAC Chain Revocation Status' command received from the device due to default "
"DeviceAttestationVerifier Class not being overridden by a real implementation.");
commissioner->CommissioningStageComplete(CHIP_ERROR_NOT_IMPLEMENTED, report);
return;
}

ChipLogError(Controller,
"Failed in verifying 'DAC Chain Revocation Status' command received from the device: err %hu. Look at "
"AttestationVerificationResult enum to understand the errors",
static_cast<uint16_t>(result));
// Go look at AttestationVerificationResult enum in src/credentials/attestation_verifier/DeviceAttestationVerifier.h to
// understand the errors.

// If a device attestation status delegate is installed, delegate handling of failure to the client and let them decide on
// whether to proceed further or not.
if (deviceAttestationDelegate)
{
commissioner->ExtendArmFailSafeForDeviceAttestation(info, result);
}
else
{
commissioner->CommissioningStageComplete(CHIP_ERROR_INTERNAL, report);
}
}
else
{
if (deviceAttestationDelegate && deviceAttestationDelegate->ShouldWaitAfterDeviceAttestation())
{
commissioner->ExtendArmFailSafeForDeviceAttestation(info, result);
}
else
{
ChipLogProgress(Controller, "Successfully validated 'Attestation Information' command received from the device.");
ChipLogProgress(Controller, "Successfully validated 'DAC Chain Revocation Status' command received from the device.");
commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
}
}
Expand Down Expand Up @@ -1305,6 +1362,18 @@ CHIP_ERROR DeviceCommissioner::ValidateAttestationInfo(const Credentials::Device
return CHIP_NO_ERROR;
}

CHIP_ERROR
DeviceCommissioner::ValidateDACChainRevocationStatus(const Credentials::DeviceAttestationVerifier::AttestationInfo & info)
{
MATTER_TRACE_SCOPE("ValidateDACChainRevocationStatus", "DeviceCommissioner");
VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mDeviceAttestationVerifier != nullptr, CHIP_ERROR_INCORRECT_STATE);

mDeviceAttestationVerifier->ValidateDACChainRevocationStatus(info, &mDACChainRevocationStatusVerificationCallback);

return CHIP_NO_ERROR;
}

CHIP_ERROR DeviceCommissioner::ValidateCSR(DeviceProxy * proxy, const ByteSpan & NOCSRElements,
const ByteSpan & AttestationSignature, const ByteSpan & dac, const ByteSpan & csrNonce)
{
Expand Down Expand Up @@ -2925,6 +2994,31 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio
}
}
break;
case CommissioningStage::kAttestationRevocationCheck: {
ChipLogProgress(Controller, "Verifying device's DAC chain revocation status");
if (!params.GetAttestationElements().HasValue() || !params.GetAttestationSignature().HasValue() ||
!params.GetAttestationNonce().HasValue() || !params.GetDAC().HasValue() || !params.GetPAI().HasValue() ||
!params.GetRemoteVendorId().HasValue() || !params.GetRemoteProductId().HasValue())
{
ChipLogError(Controller, "Missing attestation certificates");
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 (ValidateDACChainRevocationStatus(info) != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Error validating device's DAC chain revocation status");
CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
return;
}
}
break;
case CommissioningStage::kSendOpCertSigningRequest: {
if (!params.GetCSRNonce().HasValue())
{
Expand Down
13 changes: 13 additions & 0 deletions src/controller/CHIPDeviceController.h
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,14 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController,
*/
CHIP_ERROR ValidateAttestationInfo(const Credentials::DeviceAttestationVerifier::AttestationInfo & info);

/**
* @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 ValidateDACChainRevocationStatus(const Credentials::DeviceAttestationVerifier::AttestationInfo & info);

/**
* @brief
* Sends CommissioningStepComplete report to the commissioning delegate. Function will fill in current step.
Expand Down Expand Up @@ -884,6 +892,9 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController,
static void OnDeviceAttestationInformationVerification(void * context,
const Credentials::DeviceAttestationVerifier::AttestationInfo & info,
Credentials::AttestationVerificationResult result);
static void OnDACChainRevocationStatusVerification(void * context,
const Credentials::DeviceAttestationVerifier::AttestationInfo & info,
Credentials::AttestationVerificationResult result);

static void OnDeviceNOCChainGeneration(void * context, CHIP_ERROR status, const ByteSpan & noc, const ByteSpan & icac,
const ByteSpan & rcac, Optional<IdentityProtectionKeySpan> ipk,
Expand Down Expand Up @@ -1017,6 +1028,8 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController,

chip::Callback::Callback<Credentials::DeviceAttestationVerifier::OnAttestationInformationVerification>
mDeviceAttestationInformationVerificationCallback;
chip::Callback::Callback<Credentials::DeviceAttestationVerifier::OnAttestationInformationVerification>
mDACChainRevocationStatusVerificationCallback;

chip::Callback::Callback<OnNOCChainGeneration> mDeviceNOCChainCallback;
SetUpCodePairer mSetUpCodePairer;
Expand Down
1 change: 1 addition & 0 deletions src/controller/CommissioningDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ enum CommissioningStage : uint8_t
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,16 @@ CHIP_ERROR DefaultDACVerifier::VerifyNodeOperationalCSRInformation(const ByteSpa
return CHIP_NO_ERROR;
}

void DefaultDACVerifier::ValidateDACChainRevocationStatus(const AttestationInfo & info,
Callback::Callback<OnAttestationInformationVerification> * onCompletion)
{
AttestationVerificationResult attestationError = AttestationVerificationResult::kSuccess;

// TODO

onCompletion->mCall(onCompletion->mContext, info, attestationError);
}

bool CsaCdKeysTrustStore::IsCdTestKey(const ByteSpan & kid) const
{
return kid.data_equal(ByteSpan{ gTestCdPubkeyKid });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ class DefaultDACVerifier : public DeviceAttestationVerifier
const ByteSpan & attestationSignatureBuffer,
const Crypto::P256PublicKey & dacPublicKey, const ByteSpan & csrNonce) override;

void ValidateDACChainRevocationStatus(const AttestationInfo & info,
Callback::Callback<OnAttestationInformationVerification> * onCompletion) override;

CsaCdKeysTrustStore * GetCertificationDeclarationTrustStore() override { return &mCdKeysTrustStore; }

protected:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ class UnimplementedDACVerifier : public DeviceAttestationVerifier
(void) csrNonce;
return CHIP_ERROR_NOT_IMPLEMENTED;
}

void ValidateDACChainRevocationStatus(const AttestationInfo & info,
Callback::Callback<OnAttestationInformationVerification> * onCompletion) override
{
(void) info;
(void) onCompletion;
}
};

// Default to avoid nullptr on getter and cleanly handle new products/clients before
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,9 @@ class DeviceAttestationVerifier
const Crypto::P256PublicKey & dacPublicKey,
const ByteSpan & csrNonce) = 0;

virtual void ValidateDACChainRevocationStatus(const AttestationInfo & info,
Callback::Callback<OnAttestationInformationVerification> * onCompletion) = 0;

/**
* @brief Get the trust store used for the attestation verifier.
*
Expand Down
Loading