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

Fixed/Added CASE Identity Checks. #15829

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
20 changes: 16 additions & 4 deletions src/credentials/FabricTable.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
* Copyright (c) 2021-2022 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -317,12 +317,24 @@ CHIP_ERROR FabricInfo::VerifyCredentials(const ByteSpan & noc, const ByteSpan &
NodeId nodeId;
ReturnErrorOnFailure(ExtractNodeIdFabricIdFromOpCert(certificates.GetLastCert()[0], &nodeId, &fabricId));

FabricId icacFabricId = kUndefinedFabricId;
if (!icac.empty())
{
FabricId icacFabric = kUndefinedFabricId;
if (ExtractFabricIdFromCert(certificates.GetCertSet()[1], &icacFabric) == CHIP_NO_ERROR && icacFabric != kUndefinedFabricId)
if (ExtractFabricIdFromCert(certificates.GetCertSet()[1], &icacFabricId) == CHIP_NO_ERROR &&
emargolis marked this conversation as resolved.
Show resolved Hide resolved
icacFabricId != kUndefinedFabricId)
{
ReturnErrorCodeIf(icacFabric != fabricId, CHIP_ERROR_FABRIC_MISMATCH_ON_ICA);
ReturnErrorCodeIf(icacFabricId != fabricId, CHIP_ERROR_FABRIC_MISMATCH_ON_ICA);
}
}

FabricId rcacFabricId = kUndefinedFabricId;
if (ExtractFabricIdFromCert(certificates.GetCertSet()[0], &rcacFabricId) == CHIP_NO_ERROR && rcacFabricId != kUndefinedFabricId)
{
ReturnErrorCodeIf(rcacFabricId != fabricId, CHIP_ERROR_WRONG_CERT_DN);
if (!icac.empty())
{
// If FabricId attribute is present in RCAC then it SHOULD be present in ICAC as well.
ReturnErrorCodeIf(icacFabricId == kUndefinedFabricId, CHIP_ERROR_WRONG_CERT_DN);
}
}

Expand Down
32 changes: 20 additions & 12 deletions src/protocols/secure_channel/CASESession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,8 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg)

P256ECDSASignature tbsData2Signature;

P256PublicKey remoteCredential;
NodeId responderNodeId;
P256PublicKey responderPublicKey;

uint8_t responderRandom[kSigmaParamRandomNumberSize];
ByteSpan responderNOC;
Expand Down Expand Up @@ -841,7 +842,11 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg)

// Validate responder identity located in msg_r2_encrypted
// Constructing responder identity
SuccessOrExit(err = Validate_and_RetrieveResponderID(responderNOC, responderICAC, remoteCredential));
SuccessOrExit(err = ValidatePeerIdentity(responderNOC, responderICAC, responderNodeId, responderPublicKey));

// Verify that responderNodeId (from responderNOC) matches one that was included
// in the computation of the Destination Identifier when generating Sigma1.
VerifyOrReturnError(GetPeerNodeId() == responderNodeId, CHIP_ERROR_INVALID_CASE_PARAMETER);

// Construct msg_R2_Signed and validate the signature in msg_r2_encrypted
msg_r2_signed_len = TLV::EstimateStructOverhead(sizeof(uint16_t), responderNOC.size(), responderICAC.size(),
Expand All @@ -859,7 +864,7 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg)
SuccessOrExit(err = decryptedDataTlvReader.GetBytes(tbsData2Signature, tbsData2Signature.Length()));

// Validate signature
SuccessOrExit(err = remoteCredential.ECDSA_validate_msg_signature(msg_R2_Signed.Get(), msg_r2_signed_len, tbsData2Signature));
SuccessOrExit(err = responderPublicKey.ECDSA_validate_msg_signature(msg_R2_Signed.Get(), msg_r2_signed_len, tbsData2Signature));

// Retrieve session resumption ID
SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(kTag_TBEData_ResumptionID)));
Expand Down Expand Up @@ -1043,7 +1048,8 @@ CHIP_ERROR CASESession::HandleSigma3(System::PacketBufferHandle && msg)

P256ECDSASignature tbsData3Signature;

P256PublicKey remoteCredential;
NodeId initiatorNodeId;
P256PublicKey initiatorPublicKey;

ByteSpan initiatorNOC;
ByteSpan initiatorICAC;
Expand Down Expand Up @@ -1106,7 +1112,8 @@ CHIP_ERROR CASESession::HandleSigma3(System::PacketBufferHandle && msg)
// Step 5/6
// Validate initiator identity located in msg->Start()
// Constructing responder identity
SuccessOrExit(err = Validate_and_RetrieveResponderID(initiatorNOC, initiatorICAC, remoteCredential));
SuccessOrExit(err = ValidatePeerIdentity(initiatorNOC, initiatorICAC, initiatorNodeId, initiatorPublicKey));
SetPeerNodeId(initiatorNodeId);

// Step 4 - Construct Sigma3 TBS Data
msg_r3_signed_len = TLV::EstimateStructOverhead(sizeof(uint16_t), initiatorNOC.size(), initiatorICAC.size(),
Expand All @@ -1129,7 +1136,7 @@ CHIP_ERROR CASESession::HandleSigma3(System::PacketBufferHandle && msg)
// current flow of code, a malicious node can trigger a DoS style attack on the device.
// The same change should be made in Sigma2 processing.
// Step 7 - Validate Signature
SuccessOrExit(err = remoteCredential.ECDSA_validate_msg_signature(msg_R3_Signed.Get(), msg_r3_signed_len, tbsData3Signature));
SuccessOrExit(err = initiatorPublicKey.ECDSA_validate_msg_signature(msg_R3_Signed.Get(), msg_r3_signed_len, tbsData3Signature));

SuccessOrExit(err = mCommissioningHash.Finish(messageDigestSpan));

Expand Down Expand Up @@ -1259,19 +1266,20 @@ CHIP_ERROR CASESession::ValidateSigmaResumeMIC(const ByteSpan & resumeMIC, const
return CHIP_NO_ERROR;
}

CHIP_ERROR CASESession::Validate_and_RetrieveResponderID(const ByteSpan & responderNOC, const ByteSpan & responderICAC,
Crypto::P256PublicKey & responderID)
CHIP_ERROR CASESession::ValidatePeerIdentity(const ByteSpan & peerNOC, const ByteSpan & peerICAC, NodeId & peerNodeId,
Crypto::P256PublicKey & peerPublicKey)
{
ReturnErrorCodeIf(mFabricInfo == nullptr, CHIP_ERROR_INCORRECT_STATE);

ReturnErrorOnFailure(SetEffectiveTime());

PeerId peerId;
FabricId rawFabricId;
ReturnErrorOnFailure(
mFabricInfo->VerifyCredentials(responderNOC, responderICAC, mValidContext, peerId, rawFabricId, responderID));
FabricId peerNOCFabricId;
ReturnErrorOnFailure(mFabricInfo->VerifyCredentials(peerNOC, peerICAC, mValidContext, peerId, peerNOCFabricId, peerPublicKey));

VerifyOrReturnError(mFabricInfo->GetFabricId() == peerNOCFabricId, CHIP_ERROR_INVALID_CASE_PARAMETER);

SetPeerNodeId(peerId.GetNodeId());
peerNodeId = peerId.GetNodeId();

return CHIP_NO_ERROR;
}
Expand Down
4 changes: 2 additions & 2 deletions src/protocols/secure_channel/CASESession.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ class DLL_EXPORT CASESession : public Messaging::ExchangeDelegate, public Pairin

CHIP_ERROR ConstructSaltSigma2(const ByteSpan & rand, const Crypto::P256PublicKey & pubkey, const ByteSpan & ipk,
MutableByteSpan & salt);
CHIP_ERROR Validate_and_RetrieveResponderID(const ByteSpan & responderNOC, const ByteSpan & responderICAC,
Crypto::P256PublicKey & responderID);
CHIP_ERROR ValidatePeerIdentity(const ByteSpan & peerNOC, const ByteSpan & peerICAC, NodeId & peerNodeId,
Crypto::P256PublicKey & peerPublicKey);
CHIP_ERROR ConstructTBSData(const ByteSpan & senderNOC, const ByteSpan & senderICAC, const ByteSpan & senderPubKey,
const ByteSpan & receiverPubKey, uint8_t * tbsData, size_t & tbsDataLen);
CHIP_ERROR ConstructSaltSigma3(const ByteSpan & ipk, MutableByteSpan & salt);
Expand Down