Skip to content

Commit

Permalink
Added New Credentials Validity Checks for UpdateNOC Command.
Browse files Browse the repository at this point in the history
Factored out common code that performs those validity checks.
  • Loading branch information
emargolis committed Jun 1, 2022
1 parent 50d1c8e commit 708b9fe
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,8 @@ bool emberAfOperationalCredentialsClusterUpdateNOCCallback(app::CommandHandler *

CHIP_ERROR err = CHIP_NO_ERROR;
FabricIndex fabricIndex = 0;
PeerId operationalId;
FabricId fabricId;

ChipLogProgress(Zcl, "OpCreds: Received an UpdateNOC command");

Expand All @@ -814,6 +816,20 @@ bool emberAfOperationalCredentialsClusterUpdateNOCCallback(app::CommandHandler *
VerifyOrExit(fabric != nullptr, nocResponse = ConvertToNOCResponseStatus(CHIP_ERROR_INSUFFICIENT_PRIVILEGE));
fabricIndex = fabric->GetFabricIndex();

err = fabric->ValidateNewNOCCredentials(NOCValue, ICACValue.ValueOr(ByteSpan()), operationalId, fabricId);
VerifyOrExit(fabric->GetFabricId() == fabricId, nocResponse = ConvertToNOCResponseStatus(CHIP_ERROR_INSUFFICIENT_PRIVILEGE));

if (err == CHIP_ERROR_FABRIC_MISMATCH_ON_ICA || err == CHIP_ERROR_CERT_NOT_TRUSTED || err == CHIP_ERROR_INVALID_SIGNATURE)
{
err = CHIP_ERROR_INSUFFICIENT_PRIVILEGE;
}
if (err != CHIP_NO_ERROR && err != CHIP_ERROR_WRONG_NODE_ID && err != CHIP_ERROR_INCORRECT_STATE &&
err != CHIP_ERROR_INVALID_PUBLIC_KEY && err != CHIP_ERROR_INSUFFICIENT_PRIVILEGE)
{
err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT;
}
VerifyOrExit(err == CHIP_NO_ERROR, nocResponse = ConvertToNOCResponseStatus(err));

err = fabric->SetNOCCert(NOCValue);
VerifyOrExit(err == CHIP_NO_ERROR, nocResponse = ConvertToNOCResponseStatus(err));

Expand Down
46 changes: 25 additions & 21 deletions src/credentials/FabricTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,28 @@ CHIP_ERROR FabricInfo::SetExternallyOwnedOperationalKeypair(P256Keypair * keyPai
return CHIP_NO_ERROR;
}

CHIP_ERROR FabricInfo::ValidateNewNOCCredentials(const ByteSpan & noc, const ByteSpan & icac, PeerId & operationalId,
FabricId & fabricId)
{
P256PublicKey pubkey;
ValidationContext validContext;
validContext.Reset();
validContext.mRequiredKeyUsages.Set(KeyUsageFlags::kDigitalSignature);
validContext.mRequiredKeyPurposes.Set(KeyPurposeFlags::kServerAuth);

ChipLogProgress(Discovery, "Verifying the received credentials");
ReturnErrorOnFailure(VerifyCredentials(noc, icac, mRootCert, validContext, operationalId, fabricId, pubkey));

VerifyOrReturnError(mOperationalKey != nullptr, CHIP_ERROR_INCORRECT_STATE);

// Verify that public key in NOC matches public key generated by node and sent in CSRResponse message.
VerifyOrReturnError(mOperationalKey->Pubkey().Length() == pubkey.Length(), CHIP_ERROR_INVALID_PUBLIC_KEY);
VerifyOrReturnError(memcmp(mOperationalKey->Pubkey().ConstBytes(), pubkey.Bytes(), pubkey.Length()) == 0,
CHIP_ERROR_INVALID_PUBLIC_KEY);

return CHIP_NO_ERROR;
}

void FabricInfo::ReleaseCert(MutableByteSpan & cert)
{
if (cert.data() != nullptr)
Expand Down Expand Up @@ -580,35 +602,17 @@ CHIP_ERROR FabricTable::LoadFromStorage(FabricInfo * fabric)

CHIP_ERROR FabricInfo::SetFabricInfo(FabricInfo & newFabric)
{
P256PublicKey pubkey;
ValidationContext validContext;
validContext.Reset();
validContext.mRequiredKeyUsages.Set(KeyUsageFlags::kDigitalSignature);
validContext.mRequiredKeyPurposes.Set(KeyPurposeFlags::kServerAuth);

// Make sure to not modify any of our state until VerifyCredentials passes.
PeerId operationalId;
FabricId fabricId;
ChipLogProgress(Discovery, "Verifying the received credentials");
CHIP_ERROR err = VerifyCredentials(newFabric.mNOCCert, newFabric.mICACert, newFabric.mRootCert, validContext, operationalId,
fabricId, pubkey);
if (err != CHIP_NO_ERROR && err != CHIP_ERROR_WRONG_NODE_ID)
CHIP_ERROR err = newFabric.ValidateNewNOCCredentials(newFabric.mNOCCert, newFabric.mICACert, operationalId, fabricId);
if (err != CHIP_NO_ERROR && err != CHIP_ERROR_WRONG_NODE_ID && err != CHIP_ERROR_INCORRECT_STATE &&
err != CHIP_ERROR_INVALID_PUBLIC_KEY)
{
err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT;
}
ReturnErrorOnFailure(err);

auto * operationalKey = newFabric.GetOperationalKey();
if (operationalKey == nullptr)
{
return CHIP_ERROR_INCORRECT_STATE;
}

// Verify that public key in NOC matches public key generated by node and sent in CSRResponse message.
VerifyOrReturnError(operationalKey->Pubkey().Length() == pubkey.Length(), CHIP_ERROR_INVALID_PUBLIC_KEY);
VerifyOrReturnError(memcmp(operationalKey->Pubkey().ConstBytes(), pubkey.Bytes(), pubkey.Length()) == 0,
CHIP_ERROR_INVALID_PUBLIC_KEY);

if (newFabric.mHasExternallyOwnedOperationalKey)
{
ReturnErrorOnFailure(SetExternallyOwnedOperationalKeypair(operationalKey));
Expand Down
2 changes: 2 additions & 0 deletions src/credentials/FabricTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ class DLL_EXPORT FabricInfo
Credentials::ValidationContext & context, PeerId & nocPeerId, FabricId & fabricId,
Crypto::P256PublicKey & nocPubkey);

CHIP_ERROR ValidateNewNOCCredentials(const ByteSpan & noc, const ByteSpan & icac, PeerId & operationalId, FabricId & fabricId);

/**
* Reset the state to a completely uninitialized status.
*/
Expand Down

0 comments on commit 708b9fe

Please sign in to comment.