Skip to content

Commit

Permalink
Update operational credentials cluster definition to include CSR and …
Browse files Browse the repository at this point in the history
…cert (#6599)

* Update operational credentials cluster definition to include CSR and cert

* Generate ZAP files

* Generate code from ZAP files

* restyled

* add csr length in response
  • Loading branch information
pan-apple authored May 10, 2021
1 parent 74f8da9 commit a80db86
Show file tree
Hide file tree
Showing 44 changed files with 1,895 additions and 11 deletions.
32 changes: 32 additions & 0 deletions examples/all-clusters-app/all-clusters-common/all-clusters-app.zap
Original file line number Diff line number Diff line change
Expand Up @@ -1750,6 +1750,22 @@
"incoming": 1,
"outgoing": 1
},
{
"name": "OpCSRRequest",
"code": 4,
"mfgCode": null,
"source": "client",
"incoming": 1,
"outgoing": 0
},
{
"name": "AddOpCert",
"code": 6,
"mfgCode": null,
"source": "client",
"incoming": 1,
"outgoing": 0
},
{
"name": "UpdateFabricLabel",
"code": 9,
Expand Down Expand Up @@ -1808,6 +1824,22 @@
"source": "server",
"incoming": 1,
"outgoing": 1
},
{
"name": "OpCSRResponse",
"code": 5,
"mfgCode": null,
"source": "server",
"incoming": 0,
"outgoing": 1
},
{
"name": "OpCertResponse",
"code": 8,
"mfgCode": null,
"source": "server",
"incoming": 0,
"outgoing": 1
}
],
"attributes": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7023,6 +7023,221 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En
{
switch (aCommandId)
{
case ZCL_ADD_OP_CERT_COMMAND_ID: {
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
chip::ByteSpan NOC;
bool NOCExists = false;
chip::ByteSpan ICACertificate;
bool ICACertificateExists = false;
chip::ByteSpan IPKValue;
bool IPKValueExists = false;
chip::NodeId CaseAdminNode;
bool CaseAdminNodeExists = false;
uint16_t AdminVendorId;
bool AdminVendorIdExists = false;
uint32_t validArgumentCount = 0;

while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
{
case 0:
if (NOCExists)
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
{
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
NOC = chip::ByteSpan(data, aDataTlv.GetLength());
}
if (CHIP_NO_ERROR == TLVUnpackError)
{
NOCExists = true;
validArgumentCount++;
}
break;
case 1:
if (ICACertificateExists)
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
{
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
ICACertificate = chip::ByteSpan(data, aDataTlv.GetLength());
}
if (CHIP_NO_ERROR == TLVUnpackError)
{
ICACertificateExists = true;
validArgumentCount++;
}
break;
case 2:
if (IPKValueExists)
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
{
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
IPKValue = chip::ByteSpan(data, aDataTlv.GetLength());
}
if (CHIP_NO_ERROR == TLVUnpackError)
{
IPKValueExists = true;
validArgumentCount++;
}
break;
case 3:
if (CaseAdminNodeExists)
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
TLVUnpackError = aDataTlv.Get(CaseAdminNode);
if (CHIP_NO_ERROR == TLVUnpackError)
{
CaseAdminNodeExists = true;
validArgumentCount++;
}
break;
case 4:
if (AdminVendorIdExists)
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
TLVUnpackError = aDataTlv.Get(AdminVendorId);
if (CHIP_NO_ERROR == TLVUnpackError)
{
AdminVendorIdExists = true;
validArgumentCount++;
}
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (TLVUnpackError != CHIP_NO_ERROR)
{
ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError);
break;
}
}

if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
else
{
ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
}

// TODO(#5590) We should encode a response of status code for invalid TLV.
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
emberAfOperationalCredentialsClusterAddOpCertCallback(apCommandObj, NOC, ICACertificate, IPKValue, CaseAdminNode,
AdminVendorId);
}
else
{
apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
ChipLogProgress(
Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
5, validArgumentCount, TLVError, TLVUnpackError);
}
break;
}
case ZCL_OP_CSR_REQUEST_COMMAND_ID: {
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
chip::ByteSpan CSRNonce;
bool CSRNonceExists = false;
uint32_t validArgumentCount = 0;

while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
{
case 0:
if (CSRNonceExists)
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
{
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
CSRNonce = chip::ByteSpan(data, aDataTlv.GetLength());
}
if (CHIP_NO_ERROR == TLVUnpackError)
{
CSRNonceExists = true;
validArgumentCount++;
}
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (TLVUnpackError != CHIP_NO_ERROR)
{
ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError);
break;
}
}

if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
else
{
ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
}

// TODO(#5590) We should encode a response of status code for invalid TLV.
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
emberAfOperationalCredentialsClusterOpCSRRequestCallback(apCommandObj, CSRNonce);
}
else
{
apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
ChipLogProgress(
Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
1, validArgumentCount, TLVError, TLVUnpackError);
}
break;
}
case ZCL_REMOVE_ALL_FABRICS_COMMAND_ID: {

// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2315,6 +2315,73 @@ EmberAfStatus emberAfOperationalCredentialsClusterServerCommandParse(EmberAfClus
{
switch (cmd->commandId)
{
case ZCL_ADD_OP_CERT_COMMAND_ID: {
uint16_t payloadOffset = cmd->payloadStartIndex;
chip::ByteSpan NOC;
chip::ByteSpan ICACertificate;
chip::ByteSpan IPKValue;
chip::NodeId CaseAdminNode;
uint16_t AdminVendorId;

if (cmd->bufLen < payloadOffset + 1u)
{
return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
}
{
uint8_t * rawData = emberAfGetString(cmd->buffer, payloadOffset, cmd->bufLen);
NOC = chip::ByteSpan(rawData + 1u, emberAfStringLength(rawData));
}
payloadOffset = static_cast<uint16_t>(payloadOffset + NOC.size() + 1u);
if (cmd->bufLen < payloadOffset + 1u)
{
return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
}
{
uint8_t * rawData = emberAfGetString(cmd->buffer, payloadOffset, cmd->bufLen);
ICACertificate = chip::ByteSpan(rawData + 1u, emberAfStringLength(rawData));
}
payloadOffset = static_cast<uint16_t>(payloadOffset + ICACertificate.size() + 1u);
if (cmd->bufLen < payloadOffset + 1u)
{
return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
}
{
uint8_t * rawData = emberAfGetString(cmd->buffer, payloadOffset, cmd->bufLen);
IPKValue = chip::ByteSpan(rawData + 1u, emberAfStringLength(rawData));
}
payloadOffset = static_cast<uint16_t>(payloadOffset + IPKValue.size() + 1u);
if (cmd->bufLen < payloadOffset + 8)
{
return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
}
CaseAdminNode = emberAfGetInt64u(cmd->buffer, payloadOffset, cmd->bufLen);
payloadOffset = static_cast<uint16_t>(payloadOffset + 8);
if (cmd->bufLen < payloadOffset + 2)
{
return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
}
AdminVendorId = emberAfGetInt16u(cmd->buffer, payloadOffset, cmd->bufLen);

wasHandled = emberAfOperationalCredentialsClusterAddOpCertCallback(nullptr, NOC, ICACertificate, IPKValue,
CaseAdminNode, AdminVendorId);
break;
}
case ZCL_OP_CSR_REQUEST_COMMAND_ID: {
uint16_t payloadOffset = cmd->payloadStartIndex;
chip::ByteSpan CSRNonce;

if (cmd->bufLen < payloadOffset + 1u)
{
return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
}
{
uint8_t * rawData = emberAfGetString(cmd->buffer, payloadOffset, cmd->bufLen);
CSRNonce = chip::ByteSpan(rawData + 1u, emberAfStringLength(rawData));
}

wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback(nullptr, CSRNonce);
break;
}
case ZCL_REMOVE_ALL_FABRICS_COMMAND_ID: {
wasHandled = emberAfOperationalCredentialsClusterRemoveAllFabricsCallback(nullptr);
break;
Expand Down
20 changes: 20 additions & 0 deletions examples/all-clusters-app/all-clusters-common/gen/callback.h
Original file line number Diff line number Diff line change
Expand Up @@ -2803,6 +2803,26 @@ bool emberAfOnOffClusterOnCallback(chip::app::Command * commandObj);

bool emberAfOnOffClusterToggleCallback(chip::app::Command * commandObj);

/**
* @brief Operational Credentials Cluster AddOpCert Command callback
* @param noc
* @param iCACertificate
* @param iPKValue
* @param caseAdminNode
* @param adminVendorId
*/

bool emberAfOperationalCredentialsClusterAddOpCertCallback(chip::app::Command * commandObj, chip::ByteSpan NOC,
chip::ByteSpan ICACertificate, chip::ByteSpan IPKValue,
chip::NodeId CaseAdminNode, uint16_t AdminVendorId);

/**
* @brief Operational Credentials Cluster OpCSRRequest Command callback
* @param cSRNonce
*/

bool emberAfOperationalCredentialsClusterOpCSRRequestCallback(chip::app::Command * commandObj, chip::ByteSpan CSRNonce);

/**
* @brief Operational Credentials Cluster RemoveAllFabrics Command callback
*/
Expand Down
Loading

0 comments on commit a80db86

Please sign in to comment.