Skip to content

Commit

Permalink
cleanup delegate API
Browse files Browse the repository at this point in the history
  • Loading branch information
pan-apple committed Jul 30, 2021
1 parent 9291538 commit 7193a5b
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 44 deletions.
33 changes: 29 additions & 4 deletions src/controller/CHIPDeviceController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,31 @@ CHIP_ERROR DeviceController::LoadLocalCredentials(Transport::FabricInfo * fabric

ChipLogProgress(Controller, "Getting certificate chain for the controller from the issuer");

// As per specifications section 11.22.5.1. Constant RESP_MAX
constexpr uint16_t kMaxRspLen = 900;
chip::Platform::ScopedMemoryBuffer<uint8_t> csrElements;
ReturnErrorCodeIf(!csrElements.Alloc(kMaxRspLen), CHIP_ERROR_NO_MEMORY);

TLV::TLVWriter csrElementWriter;
TLV::TLVType containerType;
csrElementWriter.Init(csrElements.Get(), kMaxRspLen);
ReturnErrorOnFailure(csrElementWriter.StartContainer(TLV::AnonymousTag, TLV::TLVType::kTLVType_Structure, containerType));
ReturnErrorOnFailure(csrElementWriter.Put(TLV::ContextTag(1), ByteSpan(CSR.Get(), csrLength)));

// TODO - Need a mechanism to generate CSRNonce for commissioner's CSR
ReturnErrorOnFailure(csrElementWriter.Put(TLV::ContextTag(2), ByteSpan()));
ReturnErrorOnFailure(csrElementWriter.Put(TLV::ContextTag(3), ByteSpan()));
ReturnErrorOnFailure(csrElementWriter.Put(TLV::ContextTag(4), ByteSpan()));
ReturnErrorOnFailure(csrElementWriter.Put(TLV::ContextTag(5), ByteSpan()));
ReturnErrorOnFailure(csrElementWriter.EndContainer(containerType));
ReturnErrorOnFailure(csrElementWriter.Finalize());

mOperationalCredentialsDelegate->SetNodeIdForNextNOCRequest(mLocalDeviceId);
mOperationalCredentialsDelegate->SetFabricIdForNextNOCRequest(0);

// TODO - Need a mechanism to generate signature for commissioner's CSR
ReturnErrorOnFailure(mOperationalCredentialsDelegate->GenerateNOCChain(
Optional<NodeId>(mLocalDeviceId), 0, ByteSpan(CSR.Get(), csrLength), ByteSpan(), ByteSpan(), ByteSpan(), ByteSpan(),
ByteSpan(csrElements.Get(), csrElementWriter.GetLengthWritten()), ByteSpan(), ByteSpan(), ByteSpan(), ByteSpan(),
&mLocalNOCChainCallback));

ReturnErrorOnFailure(mFabrics.Store(fabric->GetFabricIndex()));
Expand Down Expand Up @@ -1296,9 +1319,11 @@ CHIP_ERROR DeviceCommissioner::ProcessOpCSR(const ByteSpan & NOCSRElements, cons

ChipLogProgress(Controller, "Getting certificate chain for the device from the issuer");

return mOperationalCredentialsDelegate->GenerateNOCChain(Optional<NodeId>(device->GetDeviceId()), 0, NOCSRElements,
AttestationSignature, ByteSpan(), ByteSpan(), ByteSpan(),
&mDeviceNOCChainCallback);
mOperationalCredentialsDelegate->SetNodeIdForNextNOCRequest(device->GetDeviceId());
mOperationalCredentialsDelegate->SetFabricIdForNextNOCRequest(0);

return mOperationalCredentialsDelegate->GenerateNOCChain(NOCSRElements, AttestationSignature, ByteSpan(), ByteSpan(),
ByteSpan(), &mDeviceNOCChainCallback);
}

CHIP_ERROR DeviceCommissioner::SendOperationalCertificate(Device * device, const ByteSpan & opCertBuf)
Expand Down
18 changes: 9 additions & 9 deletions src/controller/ExampleOperationalCredentialsIssuer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,24 +89,24 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::Initialize(PersistentStorageDele
return CHIP_NO_ERROR;
}

CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChain(const Optional<NodeId> & nodeId, FabricId fabricId,
const ByteSpan & csrElements,
CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChain(const ByteSpan & csrElements,
const ByteSpan & attestationSignature, const ByteSpan & DAC,
const ByteSpan & PAI, const ByteSpan & PAA,
Callback::Callback<OnNOCChainGeneration> * onCompletion)
{
VerifyOrReturnError(mInitialized, CHIP_ERROR_INCORRECT_STATE);
NodeId assignedId;
if (nodeId.HasValue())
if (mNodeIdRequested)
{
assignedId = nodeId.Value();
assignedId = mNextRequestedNodeId;
mNodeIdRequested = false;
}
else
{
assignedId = mNextAvailableNodeId++;
}

X509CertRequestParams noc_request = { 1, mIntermediateIssuerId, mNow, mNow + mValidity, true, fabricId, true, assignedId };
X509CertRequestParams noc_request = { 1, mIntermediateIssuerId, mNow, mNow + mValidity, true, mNextFabricId, true, assignedId };

ChipLogProgress(Controller, "Verifying Certificate Signing Request");
TLVReader reader;
Expand Down Expand Up @@ -138,7 +138,7 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChain(const Optional<
ReturnErrorOnFailure(NewNodeOperationalX509Cert(noc_request, CertificateIssuerLevel::kIssuerIsIntermediateCA, pubkey,
mIntermediateIssuer, noc.Get(), kMaxCHIPDERCertLength, nocLen));

X509CertRequestParams icac_request = { 0, mIssuerId, mNow, mNow + mValidity, true, fabricId, false, 0 };
X509CertRequestParams icac_request = { 0, mIssuerId, mNow, mNow + mValidity, true, mNextFabricId, false, 0 };

chip::Platform::ScopedMemoryBuffer<uint8_t> icac;
ReturnErrorCodeIf(!icac.Alloc(kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
Expand All @@ -153,19 +153,19 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChain(const Optional<
uint16_t rootCertBufLen = kMaxCHIPDERCertLength;

CHIP_ERROR err = CHIP_NO_ERROR;
PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key,
PERSISTENT_KEY_OP(mNextFabricId, kOperationalCredentialsRootCertificateStorage, key,
err = mStorage->SyncGetKeyValue(key, rcac.Get(), rootCertBufLen));
if (err != CHIP_NO_ERROR)
{
// Storage doesn't have an existing root certificate. Let's create one and add it to the storage.
X509CertRequestParams request = { 0, mIssuerId, mNow, mNow + mValidity, true, fabricId, false, 0 };
X509CertRequestParams request = { 0, mIssuerId, mNow, mNow + mValidity, true, mNextFabricId, false, 0 };
uint32_t outCertLen = 0;
ChipLogProgress(Controller, "Generating RCAC");
ReturnErrorOnFailure(NewRootX509Cert(request, mIssuer, rcac.Get(), kMaxCHIPDERCertLength, outCertLen));

VerifyOrReturnError(CanCastTo<uint16_t>(outCertLen), CHIP_ERROR_INVALID_ARGUMENT);
rootCertBufLen = static_cast<uint16_t>(outCertLen);
PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key,
PERSISTENT_KEY_OP(mNextFabricId, kOperationalCredentialsRootCertificateStorage, key,
err = mStorage->SyncSetKeyValue(key, rcac.Get(), rootCertBufLen));
ReturnErrorOnFailure(err);
}
Expand Down
18 changes: 15 additions & 3 deletions src/controller/ExampleOperationalCredentialsIssuer.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,17 @@ class DLL_EXPORT ExampleOperationalCredentialsIssuer : public OperationalCredent
public:
virtual ~ExampleOperationalCredentialsIssuer() {}

CHIP_ERROR GenerateNOCChain(const Optional<NodeId> & nodeId, FabricId fabricId, const ByteSpan & csrElements,
const ByteSpan & attestationSignature, const ByteSpan & DAC, const ByteSpan & PAI,
const ByteSpan & PAA, Callback::Callback<OnNOCChainGeneration> * onCompletion) override;
CHIP_ERROR GenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & attestationSignature, const ByteSpan & DAC,
const ByteSpan & PAI, const ByteSpan & PAA,
Callback::Callback<OnNOCChainGeneration> * onCompletion) override;

void SetNodeIdForNextNOCRequest(NodeId nodeId) override
{
mNextRequestedNodeId = nodeId;
mNodeIdRequested = true;
}

void SetFabricIdForNextNOCRequest(FabricId fabricId) override { mNextFabricId = fabricId; }

/**
* @brief Initialize the issuer with the keypair in the storage.
Expand Down Expand Up @@ -88,6 +96,10 @@ class DLL_EXPORT ExampleOperationalCredentialsIssuer : public OperationalCredent

NodeId mNextAvailableNodeId = 1;
PersistentStorageDelegate * mStorage = nullptr;

NodeId mNextRequestedNodeId = 1;
FabricId mNextFabricId = 0;
bool mNodeIdRequested = false;
};

} // namespace Controller
Expand Down
23 changes: 17 additions & 6 deletions src/controller/OperationalCredentialsDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ class DLL_EXPORT OperationalCredentialsDelegate
*
* The delegate will call `onCompletion` when the NOC certificate chain is ready.
*
* @param[in] nodeId Optional node ID. If provided, the generated NOC must use the provided ID.
* If ID is not provided, the delegate must generate one.
* @param[in] fabricId Fabric ID for which the certificate is being requested.
* @param[in] csrElements CSR elements as per specifications section 11.22.5.6. NOCSR Elements.
* @param[in] attestationSignature Attestation signature as per specifications section 11.22.7.6. CSRResponse Command.
* @param[in] DAC Device attestation certificate received from the device being commissioned
Expand All @@ -62,9 +59,23 @@ class DLL_EXPORT OperationalCredentialsDelegate
*
* @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code.
*/
virtual CHIP_ERROR GenerateNOCChain(const Optional<NodeId> & nodeId, FabricId fabricId, const ByteSpan & csrElements,
const ByteSpan & attestationSignature, const ByteSpan & DAC, const ByteSpan & PAI,
const ByteSpan & PAA, Callback::Callback<OnNOCChainGeneration> * onCompletion) = 0;
virtual CHIP_ERROR GenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & attestationSignature, const ByteSpan & DAC,
const ByteSpan & PAI, const ByteSpan & PAA,
Callback::Callback<OnNOCChainGeneration> * onCompletion) = 0;

/**
* This function sets the node ID for which the next NOC Chain would be requested. The node ID is
* provided as a hint, and the delegate implementation may chose to ignore it and pick node ID of
* their choice.
*/
virtual void SetNodeIdForNextNOCRequest(NodeId nodeId) {}

/**
* This function sets the fabric ID for which the next NOC Chain should be generated. This API is
* not required to be implemented if the delegate implementation has other mechanisms to find the
* fabric ID.
*/
virtual void SetFabricIdForNextNOCRequest(FabricId fabricId) {}
};

} // namespace Controller
Expand Down
18 changes: 10 additions & 8 deletions src/controller/java/AndroidDeviceControllerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ void AndroidDeviceControllerWrapper::CallJavaMethod(const char * methodName, jin

// TODO Refactor this API to match latest spec, so that GenerateNodeOperationalCertificate receives the full CSR Elements data
// payload.
CHIP_ERROR AndroidDeviceControllerWrapper::GenerateNOCChain(const Optional<NodeId> & nodeId, FabricId fabricId,
const ByteSpan & csrElements, const ByteSpan & attestationSignature,
CHIP_ERROR AndroidDeviceControllerWrapper::GenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & attestationSignature,
const ByteSpan & DAC, const ByteSpan & PAI, const ByteSpan & PAA,
Callback::Callback<OnNOCChainGeneration> * onCompletion)
{
Expand All @@ -82,16 +81,19 @@ CHIP_ERROR AndroidDeviceControllerWrapper::GenerateNOCChain(const Optional<NodeI
Initialize();

chip::NodeId assignedId;
if (nodeId.HasValue())
if (mNodeIdRequested)
{
assignedId = nodeId.Value();
assignedId = mNextRequestedNodeId;
mNodeIdRequested = false;
}
else
{
assignedId = mNextAvailableNodeId++;
}

chip::Credentials::X509CertRequestParams request = { 1, mIssuerId, mNow, mNow + mValidity, true, fabricId, true, assignedId };
chip::Credentials::X509CertRequestParams request = {
1, mIssuerId, mNow, mNow + mValidity, true, mNextFabricId, true, assignedId
};

TLVReader reader;
reader.Init(csrElements.data(), static_cast<uint32_t>(csrElements.size()));
Expand Down Expand Up @@ -128,18 +130,18 @@ CHIP_ERROR AndroidDeviceControllerWrapper::GenerateNOCChain(const Optional<NodeI
uint16_t rootCertBufLen = kMaxCHIPDERCertLength;

CHIP_ERROR err = CHIP_NO_ERROR;
PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key,
PERSISTENT_KEY_OP(mNextFabricId, kOperationalCredentialsRootCertificateStorage, key,
err = SyncGetKeyValue(key, rcac.Get(), rootCertBufLen));
if (err != CHIP_NO_ERROR)
{
// Storage doesn't have an existing root certificate. Let's create one and add it to the storage.
chip::Credentials::X509CertRequestParams request = { 0, mIssuerId, mNow, mNow + mValidity, true, fabricId, false, 0 };
chip::Credentials::X509CertRequestParams request = { 0, mIssuerId, mNow, mNow + mValidity, true, mNextFabricId, false, 0 };
uint32_t outCertLen = 0;
ReturnErrorOnFailure(NewRootX509Cert(request, mIssuer, rcac.Get(), kMaxCHIPDERCertLength, outCertLen));

VerifyOrReturnError(CanCastTo<uint16_t>(outCertLen), CHIP_ERROR_INVALID_ARGUMENT);
rootCertBufLen = static_cast<uint16_t>(outCertLen);
PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key,
PERSISTENT_KEY_OP(mNextFabricId, kOperationalCredentialsRootCertificateStorage, key,
err = SyncSetKeyValue(key, rcac.Get(), rootCertBufLen));
ReturnErrorOnFailure(err);
}
Expand Down
15 changes: 13 additions & 2 deletions src/controller/java/AndroidDeviceControllerWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,18 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel
void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR error) override;

// OperationalCredentialsDelegate implementation
CHIP_ERROR GenerateNOCChain(const chip::Optional<chip::NodeId> & nodeId, chip::FabricId fabricId,
const chip::ByteSpan & csrElements, const chip::ByteSpan & attestationSignature,
CHIP_ERROR GenerateNOCChain(const chip::ByteSpan & csrElements, const chip::ByteSpan & attestationSignature,
const chip::ByteSpan & DAC, const chip::ByteSpan & PAI, const chip::ByteSpan & PAA,
chip::Callback::Callback<chip::Controller::OnNOCChainGeneration> * onCompletion) override;

void SetNodeIdForNextNOCRequest(NodeId nodeId) override
{
mNextRequestedNodeId = nodeId;
mNodeIdRequested = true;
}

void SetFabricIdForNextNOCRequest(FabricId fabricId) override { mNextFabricId = fabricId; }

// DeviceStatusDelegate implementation
void OnMessage(chip::System::PacketBufferHandle && msg) override;
void OnStatusChange(void) override;
Expand Down Expand Up @@ -99,6 +106,10 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel

chip::NodeId mNextAvailableNodeId = 1;

NodeId mNextRequestedNodeId = 1;
FabricId mNextFabricId = 0;
bool mNodeIdRequested = false;

AndroidDeviceControllerWrapper(ChipDeviceControllerPtr controller, pthread_mutex_t * stackLock) :
mController(std::move(controller)), mStackLock(stackLock)
{
Expand Down
17 changes: 14 additions & 3 deletions src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,18 @@ class CHIPOperationalCredentialsDelegate : public chip::Controller::OperationalC

CHIP_ERROR init(CHIPPersistentStorageDelegateBridge * storage);

CHIP_ERROR GenerateNOCChain(const chip::Optional<chip::NodeId> & nodeId, chip::FabricId fabricId,
const chip::ByteSpan & csrElements, const chip::ByteSpan & attestationSignature, const chip::ByteSpan & DAC,
const chip::ByteSpan & PAI, const chip::ByteSpan & PAA,
CHIP_ERROR GenerateNOCChain(const chip::ByteSpan & csrElements, const chip::ByteSpan & attestationSignature,
const chip::ByteSpan & DAC, const chip::ByteSpan & PAI, const chip::ByteSpan & PAA,
chip::Callback::Callback<chip::Controller::OnNOCChainGeneration> * onCompletion) override;

void SetNodeIdForNextNOCRequest(chip::NodeId nodeId) override
{
mNextRequestedNodeId = nodeId;
mNodeIdRequested = true;
}

void SetFabricIdForNextNOCRequest(chip::FabricId fabricId) override { mNextFabricId = fabricId; }

void SetDeviceID(chip::NodeId deviceId) { mDeviceBeingPaired = deviceId; }
void ResetDeviceID() { mDeviceBeingPaired = chip::kUndefinedNodeId; }

Expand Down Expand Up @@ -69,6 +76,10 @@ class CHIPOperationalCredentialsDelegate : public chip::Controller::OperationalC
CHIPPersistentStorageDelegateBridge * mStorage;

chip::NodeId mDeviceBeingPaired = chip::kUndefinedNodeId;

chip::NodeId mNextRequestedNodeId = 1;
chip::FabricId mNextFabricId = 0;
bool mNodeIdRequested = false;
};

NS_ASSUME_NONNULL_END
18 changes: 9 additions & 9 deletions src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,8 @@ static BOOL isRunningTests(void)
return CHIP_NO_ERROR;
}

CHIP_ERROR CHIPOperationalCredentialsDelegate::GenerateNOCChain(const chip::Optional<chip::NodeId> & nodeId,
chip::FabricId fabricId, const chip::ByteSpan & csrElements, const chip::ByteSpan & attestationSignature,
const chip::ByteSpan & DAC, const chip::ByteSpan & PAI, const chip::ByteSpan & PAA,
CHIP_ERROR CHIPOperationalCredentialsDelegate::GenerateNOCChain(const chip::ByteSpan & csrElements,
const chip::ByteSpan & attestationSignature, const chip::ByteSpan & DAC, const chip::ByteSpan & PAI, const chip::ByteSpan & PAA,
chip::Callback::Callback<chip::Controller::OnNOCChainGeneration> * onCompletion)
{
uint32_t validityStart, validityEnd;
Expand All @@ -260,8 +259,9 @@ static BOOL isRunningTests(void)
}

chip::NodeId assignedId;
if (nodeId.HasValue()) {
assignedId = nodeId.Value();
if (mNodeIdRequested) {
assignedId = mNextRequestedNodeId;
mNodeIdRequested = false;
} else {
if (mDeviceBeingPaired == chip::kUndefinedNodeId) {
return CHIP_ERROR_INCORRECT_STATE;
Expand All @@ -270,7 +270,7 @@ static BOOL isRunningTests(void)
}

chip::Credentials::X509CertRequestParams noc_request
= { 1, mIssuerId, validityStart, validityEnd, true, fabricId, true, assignedId };
= { 1, mIssuerId, validityStart, validityEnd, true, mNextFabricId, true, assignedId };

TLVReader reader;
reader.Init(csrElements.data(), static_cast<uint32_t>(csrElements.size()));
Expand Down Expand Up @@ -306,19 +306,19 @@ static BOOL isRunningTests(void)

CHIP_ERROR err = CHIP_NO_ERROR;
PERSISTENT_KEY_OP(
fabricId, kOperationalCredentialsRootCertificateStorage, key, err = mStorage->SyncGetKeyValue(key, rcac, rcacLen));
mNextFabricId, kOperationalCredentialsRootCertificateStorage, key, err = mStorage->SyncGetKeyValue(key, rcac, rcacLen));

if (err != CHIP_NO_ERROR) {
chip::Credentials::X509CertRequestParams rcac_request
= { 0, mIssuerId, validityStart, validityEnd, true, fabricId, false, 0 };
= { 0, mIssuerId, validityStart, validityEnd, true, mNextFabricId, false, 0 };
uint32_t outCertLen = 0;
ReturnErrorOnFailure(chip::Credentials::NewRootX509Cert(
rcac_request, mIssuerKey, rcac, chip::Controller::kMaxCHIPDERCertLength, outCertLen));

VerifyOrReturnError(CanCastTo<uint16_t>(outCertLen), CHIP_ERROR_INVALID_ARGUMENT);
rcacLen = static_cast<uint16_t>(outCertLen);
PERSISTENT_KEY_OP(
fabricId, kOperationalCredentialsRootCertificateStorage, key, err = mStorage->SyncSetKeyValue(key, rcac, rcacLen));
mNextFabricId, kOperationalCredentialsRootCertificateStorage, key, err = mStorage->SyncSetKeyValue(key, rcac, rcacLen));
ReturnErrorOnFailure(err);
}

Expand Down

0 comments on commit 7193a5b

Please sign in to comment.