Skip to content

Commit

Permalink
[Darwin][AttestationVerifier] Expose a mechanism to customise cd sign…
Browse files Browse the repository at this point in the history
…ing keys and use it in darwin (#22338)

* Add AttestationTrustStore::GetCertificationDeclarationCert virtual method to allow controllers passing in some CD certs

* Add cdCerts member to MTRControllerFactoryparams and override AttestationTrustStore::GetCertificationDeclarationCert

* Implement ArrayTrustStore::GetCertificationDeclarationSigningKey and initialize the test ArrayTrustStore store with the test CD cert

* Update the FileAttestationTrustStore to read a directory with der certs for certification declaration verification

* Add credentials/development/cd-certs/ and update chip-tool to use it if desired

* Update API to match conversation
- Remove CD stuff from FileAttestationTrustStore
- Refactor FileAttestationTrustStore to allow loading
  of any X.509 cert directory
- Add a command line to chip-tool to disallow test keys
  (`only-allow-trusted-cd-keys`)
- Add plumbing to enable CD keys lookup properly without mixing-up
  with PAA semantics
- Add official CD verifying key and official SDK CD test key
  in the default CD trust store as-is

* Update src/darwin to take into account the proposed changes

* Add unit test for `CsaCdKeysTrustStore`

Co-authored-by: Tennessee Carmel-Veilleux <[email protected]>
  • Loading branch information
2 people authored and pull[bot] committed Jun 23, 2023
1 parent ba00917 commit 6551f4a
Show file tree
Hide file tree
Showing 15 changed files with 569 additions and 130 deletions.
Binary file not shown.
88 changes: 56 additions & 32 deletions examples/chip-tool/commands/common/CHIPCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,47 @@ std::set<CHIPCommand *> CHIPCommand::sDeferredCleanups;

using DeviceControllerFactory = chip::Controller::DeviceControllerFactory;

constexpr chip::FabricId kIdentityNullFabricId = chip::kUndefinedFabricId;
constexpr chip::FabricId kIdentityAlphaFabricId = 1;
constexpr chip::FabricId kIdentityBetaFabricId = 2;
constexpr chip::FabricId kIdentityGammaFabricId = 3;
constexpr chip::FabricId kIdentityOtherFabricId = 4;
constexpr const char * kTrustStorePathVariable = "CHIPTOOL_PAA_TRUST_STORE_PATH";

const chip::Credentials::AttestationTrustStore * CHIPCommand::sPaaTrustStore = nullptr;
constexpr chip::FabricId kIdentityNullFabricId = chip::kUndefinedFabricId;
constexpr chip::FabricId kIdentityAlphaFabricId = 1;
constexpr chip::FabricId kIdentityBetaFabricId = 2;
constexpr chip::FabricId kIdentityGammaFabricId = 3;
constexpr chip::FabricId kIdentityOtherFabricId = 4;
constexpr const char * kPAATrustStorePathVariable = "CHIPTOOL_PAA_TRUST_STORE_PATH";
constexpr const char * kCDTrustStorePathVariable = "CHIPTOOL_CD_TRUST_STORE_PATH";

const chip::Credentials::AttestationTrustStore * CHIPCommand::sTrustStore = nullptr;
chip::Credentials::GroupDataProviderImpl CHIPCommand::sGroupDataProvider{ kMaxGroupsPerFabric, kMaxGroupKeysPerFabric };

namespace {
const chip::Credentials::AttestationTrustStore * GetTestFileAttestationTrustStore(const char * paaTrustStorePath)
const CHIP_ERROR GetAttestationTrustStore(const char * paaTrustStorePath,
const chip::Credentials::AttestationTrustStore ** trustStore)
{
if (paaTrustStorePath == nullptr)
{
paaTrustStorePath = getenv(kPAATrustStorePathVariable);
}

if (paaTrustStorePath == nullptr)
{
*trustStore = chip::Credentials::GetTestAttestationTrustStore();
return CHIP_NO_ERROR;
}

static chip::Credentials::FileAttestationTrustStore attestationTrustStore{ paaTrustStorePath };

if (attestationTrustStore.IsInitialized())
if (paaTrustStorePath != nullptr && attestationTrustStore.paaCount() == 0)
{
return &attestationTrustStore;
ChipLogError(chipTool, "No PAAs found in path: %s", paaTrustStorePath);
ChipLogError(chipTool,
"Please specify a valid path containing trusted PAA certificates using "
"the argument [--paa-trust-store-path paa/file/path] "
"or environment variable [%s=paa/file/path]",
kPAATrustStorePathVariable);
return CHIP_ERROR_INVALID_ARGUMENT;
}

return nullptr;
*trustStore = &attestationTrustStore;
return CHIP_NO_ERROR;
}
} // namespace

Expand Down Expand Up @@ -103,29 +123,33 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack()
factoryInitParams.listenPort = port;
ReturnLogErrorOnFailure(DeviceControllerFactory::GetInstance().Init(factoryInitParams));

if (!mPaaTrustStorePath.HasValue())
ReturnErrorOnFailure(GetAttestationTrustStore(mPaaTrustStorePath.ValueOr(nullptr), &sTrustStore));

ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityNull, kIdentityNullFabricId));

// After initializing first commissioner, add the additional CD certs once
{
char * const trust_store_path = getenv(kTrustStorePathVariable);
if (trust_store_path != nullptr)
const char * cdTrustStorePath = mCDTrustStorePath.ValueOr(nullptr);
if (cdTrustStorePath == nullptr)
{
mPaaTrustStorePath.SetValue(trust_store_path);
cdTrustStorePath = getenv(kCDTrustStorePathVariable);
}
}
sPaaTrustStore = mPaaTrustStorePath.HasValue() ? GetTestFileAttestationTrustStore(mPaaTrustStorePath.Value())
: chip::Credentials::GetTestAttestationTrustStore();
;
if (mPaaTrustStorePath.HasValue() && sPaaTrustStore == nullptr)
{
ChipLogError(chipTool, "No PAAs found in path: %s", mPaaTrustStorePath.Value());
ChipLogError(chipTool,
"Please specify a valid path containing trusted PAA certificates using"
"the argument [--paa-trust-store-path paa/file/path]"
"or environment variable [%s=paa/file/path]",
kTrustStorePathVariable);
return CHIP_ERROR_INVALID_ARGUMENT;
}

ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityNull, kIdentityNullFabricId));
auto additionalCdCerts = chip::Credentials::LoadAllX509DerCerts(cdTrustStorePath);
if (cdTrustStorePath != nullptr && additionalCdCerts.size() == 0)
{
ChipLogError(chipTool, "Warning: no CD signing certs found in path: %s, only defaults will be used", cdTrustStorePath);
ChipLogError(chipTool,
"Please specify a path containing trusted CD verifying key certificates using "
"the argument [--cd-trust-store-path cd/file/path] "
"or environment variable [%s=cd/file/path]",
kCDTrustStorePathVariable);
}
ReturnErrorOnFailure(mCredIssuerCmds->AddAdditionalCDVerifyingCerts(additionalCdCerts));
}
bool allowTestCdSigningKey = !mOnlyAllowTrustedCdKeys.ValueOr(false);
mCredIssuerCmds->SetCredentialIssuerOption(CredentialIssuerCommands::CredentialIssuerOptions::kAllowTestCdSigningKey,
allowTestCdSigningKey);

return CHIP_NO_ERROR;
}
Expand Down Expand Up @@ -343,7 +367,7 @@ CHIP_ERROR CHIPCommand::InitializeCommissioner(std::string key, chip::FabricId f
std::unique_ptr<ChipDeviceCommissioner> commissioner = std::make_unique<ChipDeviceCommissioner>();
chip::Controller::SetupParams commissionerParams;

ReturnLogErrorOnFailure(mCredIssuerCmds->SetupDeviceAttestation(commissionerParams, sPaaTrustStore));
ReturnLogErrorOnFailure(mCredIssuerCmds->SetupDeviceAttestation(commissionerParams, sTrustStore));

VerifyOrReturnError(noc.Alloc(chip::Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
VerifyOrReturnError(icac.Alloc(chip::Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
Expand Down
10 changes: 9 additions & 1 deletion examples/chip-tool/commands/common/CHIPCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class CHIPCommand : public Command
AddArgument("paa-trust-store-path", &mPaaTrustStorePath,
"Path to directory holding PAA certificate information. Can be absolute or relative to the current working "
"directory.");
AddArgument("cd-trust-store-path", &mCDTrustStorePath,
"Path to directory holding CD certificate information. Can be absolute or relative to the current working "
"directory.");
AddArgument("commissioner-name", &mCommissionerName,
"Name of fabric to use. Valid values are \"alpha\", \"beta\", \"gamma\", and integers greater than or equal to "
"4. The default if not specified is \"alpha\".");
Expand All @@ -73,6 +76,9 @@ class CHIPCommand : public Command
AddArgument("use-max-sized-certs", 0, 1, &mUseMaxSizedCerts,
"Maximize the size of operational certificates. If not provided or 0 (\"false\"), normally sized operational "
"certificates are generated.");
AddArgument("only-allow-trusted-cd-keys", 0, 1, &mOnlyAllowTrustedCdKeys,
"Only allow trusted CD verifying keys (disallow test keys). If not provided or 0 (\"false\"), untrusted CD "
"verifying keys are allowed. If 1 (\"true\"), test keys are disallowed.");
#if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
AddArgument("trace_file", &mTraceFile);
AddArgument("trace_log", 0, 1, &mTraceLog);
Expand Down Expand Up @@ -156,11 +162,13 @@ class CHIPCommand : public Command
chip::Optional<chip::NodeId> mCommissionerNodeId;
chip::Optional<uint16_t> mBleAdapterId;
chip::Optional<char *> mPaaTrustStorePath;
chip::Optional<char *> mCDTrustStorePath;
chip::Optional<bool> mUseMaxSizedCerts;
chip::Optional<bool> mOnlyAllowTrustedCdKeys;

// Cached trust store so commands other than the original startup command
// can spin up commissioners as needed.
static const chip::Credentials::AttestationTrustStore * sPaaTrustStore;
static const chip::Credentials::AttestationTrustStore * sTrustStore;

static void RunQueuedCommand(intptr_t commandArg);

Expand Down
12 changes: 12 additions & 0 deletions examples/chip-tool/commands/common/CredentialIssuerCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPPersistentStorageDelegate.h>
#include <vector>

class CredentialIssuerCommands
{
Expand Down Expand Up @@ -54,6 +55,16 @@ class CredentialIssuerCommands
virtual CHIP_ERROR SetupDeviceAttestation(chip::Controller::SetupParams & setupParams,
const chip::Credentials::AttestationTrustStore * trustStore) = 0;

/**
* @brief Add a list of additional non-default CD verifying keys (by certificate)
*
* Must be called AFTER SetupDeviceAttestation.
*
* @param additionalCdCerts - vector of X.509 DER verifying cert bodies
* @return CHIP_NO_ERROR on succes, another CHIP_ERROR on internal failures.
*/
virtual CHIP_ERROR AddAdditionalCDVerifyingCerts(const std::vector<std::vector<uint8_t>> & additionalCdCerts) = 0;

virtual chip::Controller::OperationalCredentialsDelegate * GetCredentialIssuer() = 0;

/**
Expand All @@ -79,6 +90,7 @@ class CredentialIssuerCommands
enum CredentialIssuerOptions : uint8_t
{
kMaximizeCertificateSizes = 0, // If set, certificate chains will be maximized for testing via padding
kAllowTestCdSigningKey = 1, // If set, allow development/test SDK CD verifying key to be used
};

virtual void SetCredentialIssuerOption(CredentialIssuerOptions option, bool isEnabled)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ class ExampleCredentialIssuerCommands : public CredentialIssuerCommands
{
chip::Credentials::SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider());

setupParams.deviceAttestationVerifier = chip::Credentials::GetDefaultDACVerifier(trustStore);
mDacVerifier = chip::Credentials::GetDefaultDACVerifier(trustStore);
setupParams.deviceAttestationVerifier = mDacVerifier;
mDacVerifier->EnableCdTestKeySupport(mAllowTestCdSigningKey);

return CHIP_NO_ERROR;
}
Expand All @@ -49,6 +51,20 @@ class ExampleCredentialIssuerCommands : public CredentialIssuerCommands
return mOpCredsIssuer.GenerateNOCChainAfterValidation(nodeId, fabricId, cats, keypair.Pubkey(), rcac, icac, noc);
}

CHIP_ERROR AddAdditionalCDVerifyingCerts(const std::vector<std::vector<uint8_t>> & additionalCdCerts) override
{
VerifyOrReturnError(mDacVerifier != nullptr, CHIP_ERROR_INCORRECT_STATE);

for (const auto & cert : additionalCdCerts)
{
auto cdTrustStore = mDacVerifier->GetCertificationDeclarationTrustStore();
VerifyOrReturnError(cdTrustStore != nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorOnFailure(cdTrustStore->AddTrustedKey(chip::ByteSpan(cert.data(), cert.size())));
}

return CHIP_NO_ERROR;
}

void SetCredentialIssuerOption(CredentialIssuerOptions option, bool isEnabled) override
{
switch (option)
Expand All @@ -57,6 +73,13 @@ class ExampleCredentialIssuerCommands : public CredentialIssuerCommands
mUsesMaxSizedCerts = isEnabled;
mOpCredsIssuer.SetMaximallyLargeCertsUsed(mUsesMaxSizedCerts);
break;
case CredentialIssuerOptions::kAllowTestCdSigningKey:
mAllowTestCdSigningKey = isEnabled;
if (mDacVerifier != nullptr)
{
mDacVerifier->EnableCdTestKeySupport(isEnabled);
}

default:
break;
}
Expand All @@ -68,14 +91,19 @@ class ExampleCredentialIssuerCommands : public CredentialIssuerCommands
{
case CredentialIssuerOptions::kMaximizeCertificateSizes:
return mUsesMaxSizedCerts;
case CredentialIssuerOptions::kAllowTestCdSigningKey:
return mAllowTestCdSigningKey;
default:
return false;
}
}

protected:
bool mUsesMaxSizedCerts = false;
// Starts true for legacy purposes
bool mAllowTestCdSigningKey = true;

private:
chip::Controller::ExampleOperationalCredentialsIssuer mOpCredsIssuer;
chip::Credentials::DeviceAttestationVerifier * mDacVerifier;
};
Loading

0 comments on commit 6551f4a

Please sign in to comment.