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

[Yaml] Add a test adding a new fabric from an existing fabric #25969

Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions examples/chip-tool/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ static_library("chip-tool-utils") {
"commands/pairing/OpenCommissioningWindowCommand.cpp",
"commands/pairing/OpenCommissioningWindowCommand.h",
"commands/pairing/PairingCommand.cpp",
"commands/pairing/ToTLVCert.cpp",
"commands/payload/AdditionalDataParseCommand.cpp",
"commands/payload/SetupPayloadGenerateCommand.cpp",
"commands/payload/SetupPayloadParseCommand.cpp",
Expand Down
37 changes: 25 additions & 12 deletions examples/chip-tool/commands/common/CHIPCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,22 @@ CHIP_ERROR CHIPCommand::GetIdentityNodeId(std::string identity, chip::NodeId * n
return CHIP_NO_ERROR;
}

CHIP_ERROR CHIPCommand::GetIdentityRootCertificate(std::string identity, chip::ByteSpan & span)
{
if (identity == kIdentityNull)
{
return CHIP_ERROR_NOT_FOUND;
}

chip::NodeId nodeId;
VerifyOrDie(GetIdentityNodeId(identity, &nodeId) == CHIP_NO_ERROR);
CommissionerIdentity lookupKey{ identity, nodeId };
auto item = mCommissioners.find(lookupKey);

span = chip::ByteSpan(item->first.mRCAC, item->first.mRCACLen);
return CHIP_NO_ERROR;
}

chip::FabricId CHIPCommand::CurrentCommissionerId()
{
chip::FabricId id;
Expand Down Expand Up @@ -388,21 +404,13 @@ void CHIPCommand::ShutdownCommissioner(const CommissionerIdentity & key)
mCommissioners[key].get()->Shutdown();
}

CHIP_ERROR CHIPCommand::InitializeCommissioner(const CommissionerIdentity & identity, chip::FabricId fabricId)
CHIP_ERROR CHIPCommand::InitializeCommissioner(CommissionerIdentity & identity, chip::FabricId fabricId)
{
chip::Platform::ScopedMemoryBuffer<uint8_t> noc;
chip::Platform::ScopedMemoryBuffer<uint8_t> icac;
chip::Platform::ScopedMemoryBuffer<uint8_t> rcac;

std::unique_ptr<ChipDeviceCommissioner> commissioner = std::make_unique<ChipDeviceCommissioner>();
chip::Controller::SetupParams commissionerParams;

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);
VerifyOrReturnError(rcac.Alloc(chip::Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);

chip::Crypto::P256Keypair ephemeralKey;

if (fabricId != chip::kUndefinedFabricId)
Expand All @@ -420,15 +428,20 @@ CHIP_ERROR CHIPCommand::InitializeCommissioner(const CommissionerIdentity & iden

ReturnLogErrorOnFailure(mCredIssuerCmds->InitializeCredentialsIssuer(mCommissionerStorage));

chip::MutableByteSpan nocSpan(noc.Get(), chip::Controller::kMaxCHIPDERCertLength);
chip::MutableByteSpan icacSpan(icac.Get(), chip::Controller::kMaxCHIPDERCertLength);
chip::MutableByteSpan rcacSpan(rcac.Get(), chip::Controller::kMaxCHIPDERCertLength);
chip::MutableByteSpan nocSpan(identity.mNOC);
chip::MutableByteSpan icacSpan(identity.mICAC);
chip::MutableByteSpan rcacSpan(identity.mRCAC);

ReturnLogErrorOnFailure(ephemeralKey.Initialize(chip::Crypto::ECPKeyTarget::ECDSA));

ReturnLogErrorOnFailure(mCredIssuerCmds->GenerateControllerNOCChain(identity.mLocalNodeId, fabricId,
mCommissionerStorage.GetCommissionerCATs(),
ephemeralKey, rcacSpan, icacSpan, nocSpan));

identity.mRCACLen = rcacSpan.size();
identity.mICACLen = icacSpan.size();
identity.mNOCLen = nocSpan.size();

commissionerParams.operationalKeypair = &ephemeralKey;
commissionerParams.controllerRCAC = rcacSpan;
commissionerParams.controllerICAC = icacSpan;
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 @@ -155,6 +155,7 @@ class CHIPCommand : public Command

std::string GetIdentity();
CHIP_ERROR GetIdentityNodeId(std::string identity, chip::NodeId * nodeId);
CHIP_ERROR GetIdentityRootCertificate(std::string identity, chip::ByteSpan & span);
void SetIdentity(const char * name);

// This method returns the commissioner instance to be used for running the command.
Expand All @@ -179,12 +180,19 @@ class CHIPCommand : public Command
}
std::string mName;
chip::NodeId mLocalNodeId;
uint8_t mRCAC[chip::Controller::kMaxCHIPDERCertLength] = {};
uint8_t mICAC[chip::Controller::kMaxCHIPDERCertLength] = {};
uint8_t mNOC[chip::Controller::kMaxCHIPDERCertLength] = {};

size_t mRCACLen;
size_t mICACLen;
size_t mNOCLen;
};

// InitializeCommissioner uses various members, so can't be static. This is
// obviously a little odd, since the commissioners are then shared across
// multiple commands in interactive mode...
CHIP_ERROR InitializeCommissioner(const CommissionerIdentity & identity, chip::FabricId fabricId);
CHIP_ERROR InitializeCommissioner(CommissionerIdentity & identity, chip::FabricId fabricId);
void ShutdownCommissioner(const CommissionerIdentity & key);
chip::FabricId CurrentCommissionerId();

Expand Down
32 changes: 32 additions & 0 deletions examples/chip-tool/commands/common/RemoteDataModelLogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ constexpr const char * kErrorIdKey = "error";
constexpr const char * kClusterErrorIdKey = "clusterError";
constexpr const char * kValueKey = "value";
constexpr const char * kNodeIdKey = "nodeId";
constexpr const char * kNOCKey = "NOC";
constexpr const char * kICACKey = "ICAC";
constexpr const char * kRCACKey = "RCAC";
constexpr const char * kIPKKey = "IPK";

namespace {
RemoteDataModelLoggerDelegate * gDelegate;
Expand All @@ -53,6 +57,7 @@ CHIP_ERROR LogError(Json::Value & value, const chip::app::StatusIB & status)
auto valueStr = chip::JsonToString(value);
return gDelegate->LogJSON(valueStr.c_str());
}

} // namespace

namespace RemoteDataModelLogger {
Expand Down Expand Up @@ -165,6 +170,33 @@ CHIP_ERROR LogGetCommissionerNodeId(chip::NodeId value)
return gDelegate->LogJSON(valueStr.c_str());
}

CHIP_ERROR LogGetCommissionerRootCertificate(const char * value)
{
VerifyOrReturnError(gDelegate != nullptr, CHIP_NO_ERROR);

Json::Value rootValue;
rootValue[kValueKey] = Json::Value();
rootValue[kValueKey][kRCACKey] = value;

auto valueStr = chip::JsonToString(rootValue);
return gDelegate->LogJSON(valueStr.c_str());
}

CHIP_ERROR LogIssueNOCChain(const char * noc, const char * icac, const char * rcac, const char * ipk)
{
VerifyOrReturnError(gDelegate != nullptr, CHIP_NO_ERROR);

Json::Value rootValue;
rootValue[kValueKey] = Json::Value();
rootValue[kValueKey][kNOCKey] = noc;
rootValue[kValueKey][kICACKey] = icac;
rootValue[kValueKey][kRCACKey] = rcac;
rootValue[kValueKey][kIPKKey] = ipk;

auto valueStr = chip::JsonToString(rootValue);
return gDelegate->LogJSON(valueStr.c_str());
}

CHIP_ERROR LogDiscoveredNodeData(const chip::Dnssd::DiscoveredNodeData & nodeData)
{
VerifyOrReturnError(gDelegate != nullptr, CHIP_NO_ERROR);
Expand Down
3 changes: 3 additions & 0 deletions examples/chip-tool/commands/common/RemoteDataModelLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <app/ConcreteCommandPath.h>
#include <app/EventHeader.h>
#include <app/MessageDef/StatusIB.h>
#include <crypto/CHIPCryptoPAL.h>
#include <lib/dnssd/Resolver.h>

class RemoteDataModelLoggerDelegate
Expand All @@ -40,6 +41,8 @@ CHIP_ERROR LogEventAsJSON(const chip::app::EventHeader & header, chip::TLV::TLVR
CHIP_ERROR LogErrorAsJSON(const chip::app::EventHeader & header, const chip::app::StatusIB & status);
CHIP_ERROR LogErrorAsJSON(const CHIP_ERROR & error);
CHIP_ERROR LogGetCommissionerNodeId(chip::NodeId value);
CHIP_ERROR LogGetCommissionerRootCertificate(const char * value);
CHIP_ERROR LogIssueNOCChain(const char * noc, const char * icac, const char * rcac, const char * ipk);
CHIP_ERROR LogDiscoveredNodeData(const chip::Dnssd::DiscoveredNodeData & nodeData);
void SetDelegate(RemoteDataModelLoggerDelegate * delegate);
}; // namespace RemoteDataModelLogger
4 changes: 4 additions & 0 deletions examples/chip-tool/commands/pairing/Commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "commands/common/Commands.h"
#include "commands/pairing/CloseSessionCommand.h"
#include "commands/pairing/GetCommissionerNodeIdCommand.h"
#include "commands/pairing/GetCommissionerRootCertificateCommand.h"
#include "commands/pairing/IssueNOCChainCommand.h"
#include "commands/pairing/OpenCommissioningWindowCommand.h"
#include "commands/pairing/PairingCommand.h"

Expand Down Expand Up @@ -241,6 +243,8 @@ void registerCommandsPairing(Commands & commands, CredentialIssuerCommands * cre
make_unique<OpenCommissioningWindowCommand>(credsIssuerConfig),
make_unique<CloseSessionCommand>(credsIssuerConfig),
make_unique<GetCommissionerNodeIdCommand>(credsIssuerConfig),
make_unique<GetCommissionerRootCertificateCommand>(credsIssuerConfig),
make_unique<IssueNOCChainCommand>(credsIssuerConfig),
};

commands.Register(clusterName, clusterCommands);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#pragma once

#include "../common/CHIPCommand.h"

#include "ToTLVCert.h"

class GetCommissionerRootCertificateCommand : public CHIPCommand
{
public:
GetCommissionerRootCertificateCommand(CredentialIssuerCommands * credIssuerCommands) :
CHIPCommand("get-commissioner-root-certificate", credIssuerCommands,
"Returns a base64-encoded RCAC prefixed with: 'base64:'")
{}

/////////// CHIPCommand Interface /////////
CHIP_ERROR RunCommand() override
{
chip::ByteSpan span;
ReturnErrorOnFailure(GetIdentityRootCertificate(GetIdentity(), span));

std::string rcac;
ReturnErrorOnFailure(ToTLVCert(span, rcac));
ChipLogProgress(chipTool, "RCAC: %s", rcac.c_str());

ReturnErrorOnFailure(RemoteDataModelLogger::LogGetCommissionerRootCertificate(rcac.c_str()));

SetCommandExitStatus(CHIP_NO_ERROR);
return CHIP_NO_ERROR;
}

chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(10); }
};
86 changes: 86 additions & 0 deletions examples/chip-tool/commands/pairing/IssueNOCChainCommand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#pragma once

#include "../common/CHIPCommand.h"

#include "ToTLVCert.h"

class IssueNOCChainCommand : public CHIPCommand
{
public:
IssueNOCChainCommand(CredentialIssuerCommands * credIssuerCommands) :
CHIPCommand("issue-noc-chain", credIssuerCommands,
"Returns a base64-encoded NOC, ICAC, RCAC, and IPK prefixed with: 'base64:'"),
mDeviceNOCChainCallback(OnDeviceNOCChainGeneration, this)
{
AddArgument("elements", &mNOCSRElements, "NOCSRElements encoded in hexadecimal");
AddArgument("node-id", 0, UINT64_MAX, &mNodeId, "The target node id");
}

/////////// CHIPCommand Interface /////////
CHIP_ERROR RunCommand() override
{
auto & commissioner = CurrentCommissioner();
ReturnErrorOnFailure(commissioner.IssueNOCChain(mNOCSRElements, mNodeId, &mDeviceNOCChainCallback));
return CHIP_NO_ERROR;
}

chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(10); }

static void OnDeviceNOCChainGeneration(void * context, CHIP_ERROR status, const chip::ByteSpan & noc,
const chip::ByteSpan & icac, const chip::ByteSpan & rcac,
chip::Optional<chip::IdentityProtectionKeySpan> ipk,
chip::Optional<chip::NodeId> adminSubject)
{
auto command = static_cast<IssueNOCChainCommand *>(context);

auto err = status;
VerifyOrReturn(CHIP_NO_ERROR == err, command->SetCommandExitStatus(err));

std::string nocStr;
err = ToTLVCert(noc, nocStr);
VerifyOrReturn(CHIP_NO_ERROR == err, command->SetCommandExitStatus(err));
ChipLogProgress(chipTool, "NOC: %s", nocStr.c_str());

std::string icacStr;
err = ToTLVCert(icac, icacStr);
VerifyOrReturn(CHIP_NO_ERROR == err, command->SetCommandExitStatus(err));
ChipLogProgress(chipTool, "ICAC: %s", icacStr.c_str());

std::string rcacStr;
err = ToTLVCert(rcac, rcacStr);
VerifyOrReturn(CHIP_NO_ERROR == err, command->SetCommandExitStatus(err));
ChipLogProgress(chipTool, "RCAC: %s", rcacStr.c_str());

auto ipkValue = ipk.ValueOr(chip::Crypto::IdentityProtectionKeySpan());
std::string ipkStr;
err = ToBase64(ipkValue, ipkStr);
VerifyOrReturn(CHIP_NO_ERROR == err, command->SetCommandExitStatus(err));
ChipLogProgress(chipTool, "IPK: %s", ipkStr.c_str());

err = RemoteDataModelLogger::LogIssueNOCChain(nocStr.c_str(), icacStr.c_str(), rcacStr.c_str(), ipkStr.c_str());
command->SetCommandExitStatus(err);
}

private:
chip::Callback::Callback<chip::Controller::OnNOCChainGeneration> mDeviceNOCChainCallback;
chip::ByteSpan mNOCSRElements;
chip::NodeId mNodeId;
};
52 changes: 52 additions & 0 deletions examples/chip-tool/commands/pairing/ToTLVCert.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#include "ToTLVCert.h"

#include <credentials/CHIPCert.h>
#include <lib/support/Base64.h>

constexpr const char kBase64Header[] = "base64:";
constexpr size_t kBase64HeaderLen = ArraySize(kBase64Header) - 1;

CHIP_ERROR ToBase64(const chip::ByteSpan & input, std::string & outputAsPrefixedBase64)
{
chip::Platform::ScopedMemoryBuffer<char> base64String;
base64String.Alloc(kBase64HeaderLen + BASE64_ENCODED_LEN(input.size()) + 1);
VerifyOrReturnError(base64String.Get() != nullptr, CHIP_ERROR_NO_MEMORY);

auto encodedLen = chip::Base64Encode(input.data(), static_cast<uint16_t>(input.size()), base64String.Get() + kBase64HeaderLen);
if (encodedLen)
{
memcpy(base64String.Get(), kBase64Header, kBase64HeaderLen);
encodedLen = static_cast<uint16_t>(encodedLen + kBase64HeaderLen);
}
base64String.Get()[encodedLen] = '\0';
outputAsPrefixedBase64 = std::string(base64String.Get(), encodedLen);

return CHIP_NO_ERROR;
}

CHIP_ERROR ToTLVCert(const chip::ByteSpan & derEncodedCertificate, std::string & tlvCertAsPrefixedBase64)
{
uint8_t chipCertBuffer[chip::Credentials::kMaxCHIPCertLength];
chip::MutableByteSpan chipCertBytes(chipCertBuffer);
ReturnErrorOnFailure(chip::Credentials::ConvertX509CertToChipCert(derEncodedCertificate, chipCertBytes));
ReturnErrorOnFailure(ToBase64(chipCertBytes, tlvCertAsPrefixedBase64));
return CHIP_NO_ERROR;
}
Loading