-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
[CASESession] Factoring Out Sigma2 and Sigma3 Parsing Functions for Improved Testability #36941
base: master
Are you sure you want to change the base?
[CASESession] Factoring Out Sigma2 and Sigma3 Parsing Functions for Improved Testability #36941
Conversation
…sionParameters as an outparam and does not touch PairingSession class member mRemoteSessionParameters - a utility SetRemoteSessionParameters to be able to set PairingSession class member mRemoteSessionParameters
9351204
to
403d4ee
Compare
PR #36941: Size comparison from 2249628 to 403d4ee Full report (69 builds for bl602, bl702, bl702l, cc13x4_26x4, cc32xx, cyw30739, efr32, esp32, linux, nrfconnect, nxp, psoc6, qpg, stm32, telink, tizen)
|
PR #36941: Size comparison from 2249628 to ea053d8 Increases above 0.2%:
Full report (69 builds for bl602, bl702, bl702l, cc13x4_26x4, cc32xx, cyw30739, efr32, esp32, linux, nrfconnect, nxp, psoc6, qpg, stm32, telink, tizen)
|
ea053d8
to
cc77e8c
Compare
PR #36941: Size comparison from 2249628 to cc77e8c Increases above 0.2%:
Full report (69 builds for bl602, bl702, bl702l, cc13x4_26x4, cc32xx, cyw30739, efr32, esp32, linux, nrfconnect, nxp, psoc6, qpg, stm32, telink, tizen)
|
df9a3e8
to
5c9281b
Compare
0fe56e3
to
1a6f27b
Compare
PR #36941: Size comparison from d5e9829 to 1a6f27b Full report (70 builds for bl602, bl702, bl702l, cc13x4_26x4, cc32xx, cyw30739, efr32, esp32, linux, nrfconnect, nxp, psoc6, qpg, stm32, telink, tizen)
|
1a6f27b
to
c4dfb95
Compare
edb0de3
to
6723bd3
Compare
PR #36941: Size comparison from d5e9829 to 6723bd3 Full report (70 builds for bl602, bl702, bl702l, cc13x4_26x4, cc32xx, cyw30739, efr32, esp32, linux, nrfconnect, nxp, psoc6, qpg, stm32, telink, tizen)
|
SuccessOrExit(err = AES_CCM_decrypt(msg_R2_Encrypted.Get(), msg_r2_encrypted_len, nullptr, 0, | ||
msg_R2_Encrypted.Get() + msg_r2_encrypted_len, CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, | ||
sr2k.KeyHandle(), kTBEData2_Nonce, kTBEDataNonceLength, msg_R2_Encrypted.Get())); | ||
size_t msgR2EncryptedLen = parsedSigma2.msgR2Encrypted.AllocatedSize() - CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Relying on allocated size is riskier than just storing the actual length. Suggest having 2 spans in parsedSigma2 -> msgR2EncryptedPayload (mutable) and msgR2Mic (immutable), which both are backed by a msgR2Encrypted memory buffer (i.e. what you have now). That will avoid just below doing size arithmetic much further from the place where it is allocated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
// Retrieve session resumption ID | ||
ReturnErrorOnFailure(decryptedDataTlvReader.Next(AsTlvContextTag(TBEDataTags::kResumptionID))); | ||
ReturnErrorOnFailure(decryptedDataTlvReader.GetByteView(outParsedSigma2TBE.resumptionId)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the GetByteView really implies that everything is processed inline and all at once, since it's only valid according while the backing storage is in scope. Was it verified that there is no use-after-scope at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- unit tests with ASAN were executed.
- Also we still initialize the TLV Reader at the same place as before (i.e. in
HandleSigma2()
) the decoded bits are only used there.
|
||
if (data.keystore != nullptr) | ||
{ | ||
SuccessOrExit(err = helper->ScheduleWork()); | ||
ReturnErrorOnFailure(helper->ScheduleWork()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is async and will swithc context. It is certain that there is nothing here that will be out of scope later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not change the scope of any of the decoded elements, so it should be fine.
containerType = TLV::kTLVType_Structure; | ||
SuccessOrExit(err = decryptedDataTlvReader.Next(containerType, TLV::AnonymousTag())); | ||
SuccessOrExit(err = decryptedDataTlvReader.EnterContainer(containerType)); | ||
msgR3EncryptedLen = msgR3Encrypted.AllocatedSize() - CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as equivalent code above in Sigma2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
SuccessOrExit(err = ConstructTBSData(data.initiatorNOC, data.initiatorICAC, ByteSpan(mRemotePubKey, mRemotePubKey.Length()), | ||
ByteSpan(mEphemeralKey->Pubkey(), mEphemeralKey->Pubkey().Length()), | ||
data.msg_R3_Signed.Get(), data.msg_r3_signed_len)); | ||
data.msgR3Signed.Get(), data.msgR3SignedLen)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we passed a mutable span instead to the ConstructTBSData, then it may be clearer that it's a max length in msgR3SignedLen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean I should modify ConstructTBSData
to take a MutableByteSpan instead of a Pointer + length? that would require more changes in the other parts of the code, it might be better to do it as a follow up.
signedDataTlvReader.Init(data.msg_R3_Signed.Get(), data.msg_r3_signed_len); | ||
SuccessOrExit(err = signedDataTlvReader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag())); | ||
TLV::ContiguousBufferTLVReader signedDataTlvReader; | ||
signedDataTlvReader.Init(data.msgR3Signed.Get(), data.msgR3SignedLen); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did data.msgR3SignedLen
get mutated by ConstructedTBSData to be the real length? I think so. This is another reason of having the mutable span that keeps state clearly here.
SuccessOrExit(err = signedDataTlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(TBSDataTags::kSenderNOC))); | ||
SuccessOrExit(err = signedDataTlvReader.Get(data.initiatorNOC)); | ||
SuccessOrExit(err = signedDataTlvReader.Next(AsTlvContextTag(TBSDataTags::kSenderNOC))); | ||
SuccessOrExit(err = signedDataTlvReader.GetByteView(data.initiatorNOC)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again here, the byte view is a span backed by the lifetime of data.msgR3Signed
underlying buffer. Are we certain there are no use after scope possibilities ehre.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, data.msgR3Signed
is part of the workdata struct used in HandleSigma3b
, where we use these spans.
Actually before my change, they were also using TLVReader::Get(ByteSpan & v)
, I changed it to GetByteView just to have an additional check for ByteString and more clarity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually this whole sequence TBS parsing was done only to keep the spans valid in scope where they are used --> HandleSigma3b
connectedhomeip/src/protocols/secure_channel/CASESession.cpp
Lines 1988 to 2005 in d5e9829
// initiatorNOC and initiatorICAC are spans into msg_R3_Encrypted | |
// which is going away, so to save memory, redirect them to their | |
// copies in msg_R3_signed, which is staying around | |
TLV::TLVReader signedDataTlvReader; | |
signedDataTlvReader.Init(data.msg_R3_Signed.Get(), data.msg_r3_signed_len); | |
SuccessOrExit(err = signedDataTlvReader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag())); | |
SuccessOrExit(err = signedDataTlvReader.EnterContainer(containerType)); | |
SuccessOrExit(err = signedDataTlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(TBSDataTags::kSenderNOC))); | |
SuccessOrExit(err = signedDataTlvReader.Get(data.initiatorNOC)); | |
if (!data.initiatorICAC.empty()) | |
{ | |
SuccessOrExit(err = signedDataTlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(TBSDataTags::kSenderICAC))); | |
SuccessOrExit(err = signedDataTlvReader.Get(data.initiatorICAC)); | |
} | |
} | |
@@ -2018,6 +2006,71 @@ CHIP_ERROR CASESession::HandleSigma3a(System::PacketBufferHandle && msg) | |||
return err; | |||
} | |||
|
|||
CHIP_ERROR CASESession::ParseSigma3(ContiguousBufferTLVReader & tlvReader, | |||
Platform::ScopedMemoryBufferWithSize<uint8_t> & msgR3Encrypted) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest passing a MutableByteSpan. The fact that we are mutating the payload to decrypt in place was never really stated, but it's actually what's happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it looks like even the alloc is done by this method on the provided msgR3Encrypted. Suggest calling it outMsgR3Encrypted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added comments to the method in the header file, as well as during instantiation of parameters passed to it
I made it like:
CHIP_ERROR CASESession::ParseSigma3(ContiguousBufferTLVReader & tlvReader,
Platform::ScopedMemoryBufferWithSize<uint8_t> & outMsgR3Encrypted,
MutableByteSpan & outMsgR3EncryptedPayload, ByteSpan & outMsgR3Mic)
ByteSpan responderRandom; | ||
uint16_t responderSessionId; | ||
ByteSpan responderEphPubKey; | ||
Platform::ScopedMemoryBufferWithSize<uint8_t> msgR2Encrypted; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- For each of these, indicate which are backed by the the msgXxxxx allocated buffer
- Move the uint16_t after SessionParameterrs and the bool after that, to minimize gaps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
struct ParsedSigma2TBEData | ||
{ | ||
ByteSpan responderNOC; | ||
ByteSpan responderICAC; | ||
Crypto::P256ECDSASignature tbsData2Signature; | ||
ByteSpan resumptionId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For all the bytespans, the backing of the bytespan and lifetime must be indicated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added comments in all the structs, as well as for all the newly created ParseSigma*
functions
{ | ||
FabricIndex fabricIndex; | ||
|
||
// Use one or the other |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? How is this enforced?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually this is legacy code, All I did was move the struct from .cpp to .h to have all the structs together and have the possibility to include them in tests
ByteSpan initiatorNOC; | ||
ByteSpan initiatorICAC; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely for all structs in added in this PR, indicate the lifetimes in terms of methods or otherwise, and what is the storage that backs the spans.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do, (although this particular struct and one before it are legacy code)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Backing and Lifetime added.
4c0fd48
to
a68f2c0
Compare
PR #36941: Size comparison from 8a0fc4d to a68f2c0 Full report (71 builds for bl602, bl702, bl702l, cc13x4_26x4, cc32xx, cyw30739, efr32, esp32, linux, nrfconnect, nxp, psoc6, qpg, stm32, telink, tizen)
|
a68f2c0
to
386d4b9
Compare
386d4b9
to
f7b8166
Compare
PR #36941: Size comparison from 958c1cb to f7b8166 Full report (71 builds for bl602, bl702, bl702l, cc13x4_26x4, cc32xx, cyw30739, efr32, esp32, linux, nrfconnect, nxp, psoc6, qpg, stm32, telink, tizen)
|
Overview:
This PR continues the CASESession refactoring efforts to improve testability and robustness, building on:
Key Changes:
1. Refactoring:
2. Hardening and Fixes:
TBSData2Signature
andTBSData3Signature
.EndOfContainer
TLV elements by ensuringExitContainer
is called after TLV-Reading containers TLV Reading of Containers often missed a call to ExitContainer #36959.Testing