From 604013dc5d71d444f9fc3821f606d84f6a340a34 Mon Sep 17 00:00:00 2001 From: Zang MingJie Date: Thu, 24 Mar 2022 19:25:19 +0800 Subject: [PATCH 1/3] Skip calling OnFabricRetrievedFromStorage when the fabric is already initialized --- src/credentials/FabricTable.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/credentials/FabricTable.cpp b/src/credentials/FabricTable.cpp index e5b1fc37f95bdc..e01d71cccfbbce 100644 --- a/src/credentials/FabricTable.cpp +++ b/src/credentials/FabricTable.cpp @@ -618,15 +618,15 @@ CHIP_ERROR FabricTable::LoadFromStorage(FabricInfo * fabric) if (!fabric->IsInitialized()) { ReturnErrorOnFailure(fabric->LoadFromStorage(mStorage)); - } - FabricTableDelegate * delegate = mDelegate; - while (delegate) - { - ChipLogProgress(Discovery, "Fabric (%d) loaded from storage. Calling OnFabricRetrievedFromStorage", - fabric->GetFabricIndex()); - delegate->OnFabricRetrievedFromStorage(fabric); - delegate = delegate->mNext; + FabricTableDelegate * delegate = mDelegate; + while (delegate) + { + ChipLogProgress(Discovery, "Fabric (%d) loaded from storage. Calling OnFabricRetrievedFromStorage", + fabric->GetFabricIndex()); + delegate->OnFabricRetrievedFromStorage(fabric); + delegate = delegate->mNext; + } } return CHIP_NO_ERROR; } From 3abe59ff0156c09f58ff6393df4dd038c22a3a28 Mon Sep 17 00:00:00 2001 From: Zang MingJie Date: Wed, 2 Mar 2022 18:16:44 +0800 Subject: [PATCH 2/3] Crypto: Fix node id in nonce --- src/credentials/tests/CHIPCert_test_vectors.h | 1 + src/lib/support/Span.h | 9 + .../secure_channel/tests/TestPASESession.cpp | 8 +- src/transport/CryptoContext.cpp | 38 +-- src/transport/CryptoContext.h | 18 +- src/transport/SecureMessageCodec.cpp | 12 +- src/transport/SecureMessageCodec.h | 8 +- src/transport/SessionManager.cpp | 31 ++- src/transport/tests/TestSecureSession.cpp | 32 ++- src/transport/tests/TestSessionManager.cpp | 257 ++++++++++++------ 10 files changed, 278 insertions(+), 136 deletions(-) diff --git a/src/credentials/tests/CHIPCert_test_vectors.h b/src/credentials/tests/CHIPCert_test_vectors.h index f7aaa51c5f4908..08085e66a43af4 100644 --- a/src/credentials/tests/CHIPCert_test_vectors.h +++ b/src/credentials/tests/CHIPCert_test_vectors.h @@ -26,6 +26,7 @@ #pragma once +#include #include namespace chip { diff --git a/src/lib/support/Span.h b/src/lib/support/Span.h index 84bf035e6dbe4b..edcdd8ed353a62 100644 --- a/src/lib/support/Span.h +++ b/src/lib/support/Span.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include #include @@ -46,6 +47,10 @@ class Span constexpr explicit Span(T (&databuf)[N]) : Span(databuf, N) {} + template , std::remove_const_t>::value>> + constexpr Span(std::array & arr) : mDataBuf(arr.data()), mDataLen(N) + {} + template constexpr Span & operator=(T (&databuf)[N]) { @@ -169,6 +174,10 @@ class FixedSpan static_assert(M >= N, "Passed-in buffer too small for FixedSpan"); } + template , std::remove_const_t>::value>> + constexpr FixedSpan(std::array & arr) : mDataBuf(arr.data()) + {} + // Allow implicit construction from a FixedSpan of sufficient size over a // type that matches our type, up to const-ness. template , std::remove_const_t>::value>> diff --git a/src/protocols/secure_channel/tests/TestPASESession.cpp b/src/protocols/secure_channel/tests/TestPASESession.cpp index 13a75f8f66a083..11ada996512c61 100644 --- a/src/protocols/secure_channel/tests/TestPASESession.cpp +++ b/src/protocols/secure_channel/tests/TestPASESession.cpp @@ -416,7 +416,9 @@ void SecurePairingSerializeTest(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - err = session1.Encrypt(plain_text, sizeof(plain_text), encrypted, header, mac); + CryptoContext::NonceStorage nonce; + CryptoContext::BuildNonce(nonce, header.GetSecurityFlags(), header.GetMessageCounter(), kUndefinedNodeId); + err = session1.Encrypt(plain_text, sizeof(plain_text), encrypted, nonce, header, mac); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); } @@ -426,7 +428,9 @@ void SecurePairingSerializeTest(nlTestSuite * inSuite, void * inContext) testPairingSession2->DeriveSecureSession(session2, CryptoContext::SessionRole::kResponder) == CHIP_NO_ERROR); uint8_t decrypted[64]; - NL_TEST_ASSERT(inSuite, session2.Decrypt(encrypted, sizeof(plain_text), decrypted, header, mac) == CHIP_NO_ERROR); + CryptoContext::NonceStorage nonce; + CryptoContext::BuildNonce(nonce, header.GetSecurityFlags(), header.GetMessageCounter(), kUndefinedNodeId); + NL_TEST_ASSERT(inSuite, session2.Decrypt(encrypted, sizeof(plain_text), decrypted, nonce, header, mac) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, memcmp(plain_text, decrypted, sizeof(plain_text)) == 0); } diff --git a/src/transport/CryptoContext.cpp b/src/transport/CryptoContext.cpp index ab0ee35c1b2bec..a0d3fcf1305f6b 100644 --- a/src/transport/CryptoContext.cpp +++ b/src/transport/CryptoContext.cpp @@ -37,8 +37,7 @@ namespace chip { namespace { -constexpr size_t kAESCCMNonceLen = 13; -constexpr size_t kMaxAADLen = 128; +constexpr size_t kMaxAADLen = 128; /* Session Establish Key Info */ constexpr uint8_t SEKeysInfo[] = { 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x73 }; @@ -131,16 +130,13 @@ CHIP_ERROR CryptoContext::InitFromKeyPair(const Crypto::P256Keypair & local_keyp return InitFromSecret(ByteSpan(secret, secret.Length()), salt, infoType, role); } -CHIP_ERROR CryptoContext::GetNonce(const PacketHeader & header, uint8_t * nonce, size_t len) +CHIP_ERROR CryptoContext::BuildNonce(NonceView nonce, uint8_t securityFlags, uint32_t messageCounter, NodeId nodeId) { + Encoding::LittleEndian::BufferWriter bbuf(nonce.data(), nonce.size()); - VerifyOrReturnError(len == kAESCCMNonceLen, CHIP_ERROR_INVALID_ARGUMENT); - - Encoding::LittleEndian::BufferWriter bbuf(nonce, len); - - bbuf.Put8(header.GetSecurityFlags()); - bbuf.Put32(header.GetMessageCounter()); - bbuf.Put64(header.GetSourceNodeId().ValueOr(0)); + bbuf.Put8(securityFlags); + bbuf.Put32(messageCounter); + bbuf.Put64(nodeId); return bbuf.Fit() ? CHIP_NO_ERROR : CHIP_ERROR_NO_MEMORY; } @@ -161,8 +157,8 @@ CHIP_ERROR CryptoContext::GetAdditionalAuthData(const PacketHeader & header, uin return CHIP_NO_ERROR; } -CHIP_ERROR CryptoContext::Encrypt(const uint8_t * input, size_t input_length, uint8_t * output, PacketHeader & header, - MessageAuthenticationCode & mac) const +CHIP_ERROR CryptoContext::Encrypt(const uint8_t * input, size_t input_length, uint8_t * output, ConstNonceView nonce, + PacketHeader & header, MessageAuthenticationCode & mac) const { const size_t taglen = header.MICTagLength(); @@ -174,11 +170,9 @@ CHIP_ERROR CryptoContext::Encrypt(const uint8_t * input, size_t input_length, ui VerifyOrReturnError(output != nullptr, CHIP_ERROR_INVALID_ARGUMENT); uint8_t AAD[kMaxAADLen]; - uint8_t nonce[kAESCCMNonceLen]; uint16_t aadLen = sizeof(AAD); uint8_t tag[kMaxTagLen]; - ReturnErrorOnFailure(GetNonce(header, nonce, sizeof(nonce))); ReturnErrorOnFailure(GetAdditionalAuthData(header, AAD, aadLen)); if (mKeyContext) @@ -187,7 +181,7 @@ CHIP_ERROR CryptoContext::Encrypt(const uint8_t * input, size_t input_length, ui MutableByteSpan ciphertext(output, input_length); MutableByteSpan mic(tag, taglen); - ReturnErrorOnFailure(mKeyContext->EncryptMessage(plaintext, ByteSpan(AAD, aadLen), ByteSpan(nonce), mic, ciphertext)); + ReturnErrorOnFailure(mKeyContext->EncryptMessage(plaintext, ByteSpan(AAD, aadLen), nonce, mic, ciphertext)); } else { @@ -202,8 +196,8 @@ CHIP_ERROR CryptoContext::Encrypt(const uint8_t * input, size_t input_length, ui usage = kI2RKey; } - ReturnErrorOnFailure(AES_CCM_encrypt(input, input_length, AAD, aadLen, mKeys[usage], Crypto::kAES_CCM128_Key_Length, nonce, - sizeof(nonce), output, tag, taglen)); + ReturnErrorOnFailure(AES_CCM_encrypt(input, input_length, AAD, aadLen, mKeys[usage], Crypto::kAES_CCM128_Key_Length, + nonce.data(), nonce.size(), output, tag, taglen)); } mac.SetTag(&header, tag, taglen); @@ -211,12 +205,11 @@ CHIP_ERROR CryptoContext::Encrypt(const uint8_t * input, size_t input_length, ui return CHIP_NO_ERROR; } -CHIP_ERROR CryptoContext::Decrypt(const uint8_t * input, size_t input_length, uint8_t * output, const PacketHeader & header, - const MessageAuthenticationCode & mac) const +CHIP_ERROR CryptoContext::Decrypt(const uint8_t * input, size_t input_length, uint8_t * output, ConstNonceView nonce, + const PacketHeader & header, const MessageAuthenticationCode & mac) const { const size_t taglen = header.MICTagLength(); const uint8_t * tag = mac.GetTag(); - uint8_t nonce[kAESCCMNonceLen]; uint8_t AAD[kMaxAADLen]; uint16_t aadLen = sizeof(AAD); @@ -224,7 +217,6 @@ CHIP_ERROR CryptoContext::Decrypt(const uint8_t * input, size_t input_length, ui VerifyOrReturnError(input_length > 0, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(output != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - ReturnErrorOnFailure(GetNonce(header, nonce, sizeof(nonce))); ReturnErrorOnFailure(GetAdditionalAuthData(header, AAD, aadLen)); if (nullptr != mKeyContext) @@ -233,7 +225,7 @@ CHIP_ERROR CryptoContext::Decrypt(const uint8_t * input, size_t input_length, ui MutableByteSpan plaintext(output, input_length); ByteSpan mic(tag, taglen); - CHIP_ERROR err = mKeyContext->DecryptMessage(ciphertext, ByteSpan(AAD, aadLen), ByteSpan(nonce), mic, plaintext); + CHIP_ERROR err = mKeyContext->DecryptMessage(ciphertext, ByteSpan(AAD, aadLen), nonce, mic, plaintext); ReturnErrorOnFailure(err); } else @@ -250,7 +242,7 @@ CHIP_ERROR CryptoContext::Decrypt(const uint8_t * input, size_t input_length, ui } ReturnErrorOnFailure(AES_CCM_decrypt(input, input_length, AAD, aadLen, tag, taglen, mKeys[usage], - Crypto::kAES_CCM128_Key_Length, nonce, sizeof(nonce), output)); + Crypto::kAES_CCM128_Key_Length, nonce.data(), nonce.size(), output)); } return CHIP_NO_ERROR; } diff --git a/src/transport/CryptoContext.h b/src/transport/CryptoContext.h index 5a462fbe45cbaf..97b30cf80dc6bc 100644 --- a/src/transport/CryptoContext.h +++ b/src/transport/CryptoContext.h @@ -35,6 +35,11 @@ namespace chip { class DLL_EXPORT CryptoContext { public: + static constexpr size_t kAESCCMNonceLen = 13; + using NonceStorage = std::array; + using NonceView = FixedSpan; + using ConstNonceView = FixedSpan; + CryptoContext(); ~CryptoContext(); CryptoContext(CryptoContext &&) = default; @@ -86,6 +91,9 @@ class DLL_EXPORT CryptoContext */ CHIP_ERROR InitFromSecret(const ByteSpan & secret, const ByteSpan & salt, SessionInfoType infoType, SessionRole role); + /** @brief Build a Nonce buffer using given parameters for encrypt or decrypt. */ + static CHIP_ERROR BuildNonce(NonceView nonce, uint8_t securityFlags, uint32_t messageCounter, NodeId nodeId); + /** * @brief * Encrypt the input data using keys established in the secure channel @@ -93,12 +101,13 @@ class DLL_EXPORT CryptoContext * @param input Unencrypted input data * @param input_length Length of the input data * @param output Output buffer for encrypted data + * @param nonce Nonce buffer for encrypt * @param header message header structure. Encryption type will be set on the header. * @param mac - output the resulting mac * * @return CHIP_ERROR The result of encryption */ - CHIP_ERROR Encrypt(const uint8_t * input, size_t input_length, uint8_t * output, PacketHeader & header, + CHIP_ERROR Encrypt(const uint8_t * input, size_t input_length, uint8_t * output, ConstNonceView nonce, PacketHeader & header, MessageAuthenticationCode & mac) const; /** @@ -108,12 +117,13 @@ class DLL_EXPORT CryptoContext * @param input Encrypted input data * @param input_length Length of the input data * @param output Output buffer for decrypted data + * @param nonce Nonce buffer for decrypt * @param header message header structure * @return CHIP_ERROR The result of decryption * @param mac Input mac */ - CHIP_ERROR Decrypt(const uint8_t * input, size_t input_length, uint8_t * output, const PacketHeader & header, - const MessageAuthenticationCode & mac) const; + CHIP_ERROR Decrypt(const uint8_t * input, size_t input_length, uint8_t * output, ConstNonceView nonce, + const PacketHeader & header, const MessageAuthenticationCode & mac) const; ByteSpan GetAttestationChallenge() const { return ByteSpan(mKeys[kAttestationChallengeKey], Crypto::kAES_CCM128_Key_Length); } @@ -143,8 +153,6 @@ class DLL_EXPORT CryptoContext CryptoKey mKeys[KeyUsage::kNumCryptoKeys]; Crypto::SymmetricKeyContext * mKeyContext = nullptr; - static CHIP_ERROR GetNonce(const PacketHeader & header, uint8_t * nonce, size_t len); - // Use unencrypted header as additional authenticated data (AAD) during encryption and decryption. // The encryption operations includes AAD when message authentication tag is generated. This tag // is used at the time of decryption to integrity check the received data. diff --git a/src/transport/SecureMessageCodec.cpp b/src/transport/SecureMessageCodec.cpp index 98547858a10515..9c08d535ff57a3 100644 --- a/src/transport/SecureMessageCodec.cpp +++ b/src/transport/SecureMessageCodec.cpp @@ -36,8 +36,8 @@ using System::PacketBufferHandle; namespace SecureMessageCodec { -CHIP_ERROR Encrypt(const CryptoContext & context, PayloadHeader & payloadHeader, PacketHeader & packetHeader, - System::PacketBufferHandle & msgBuf) +CHIP_ERROR Encrypt(const CryptoContext & context, CryptoContext::ConstNonceView nonce, PayloadHeader & payloadHeader, + PacketHeader & packetHeader, System::PacketBufferHandle & msgBuf) { VerifyOrReturnError(!msgBuf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(!msgBuf->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH); @@ -52,7 +52,7 @@ CHIP_ERROR Encrypt(const CryptoContext & context, PayloadHeader & payloadHeader, uint16_t totalLen = msgBuf->TotalLength(); MessageAuthenticationCode mac; - ReturnErrorOnFailure(context.Encrypt(data, totalLen, data, packetHeader, mac)); + ReturnErrorOnFailure(context.Encrypt(data, totalLen, data, nonce, packetHeader, mac)); uint16_t taglen = 0; ReturnErrorOnFailure(mac.Encode(packetHeader, &data[totalLen], msgBuf->AvailableDataLength(), &taglen)); @@ -63,8 +63,8 @@ CHIP_ERROR Encrypt(const CryptoContext & context, PayloadHeader & payloadHeader, return CHIP_NO_ERROR; } -CHIP_ERROR Decrypt(const CryptoContext & context, PayloadHeader & payloadHeader, const PacketHeader & packetHeader, - System::PacketBufferHandle & msg) +CHIP_ERROR Decrypt(const CryptoContext & context, CryptoContext::ConstNonceView nonce, PayloadHeader & payloadHeader, + const PacketHeader & packetHeader, System::PacketBufferHandle & msg) { ReturnErrorCodeIf(msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT); @@ -93,7 +93,7 @@ CHIP_ERROR Decrypt(const CryptoContext & context, PayloadHeader & payloadHeader, msg->SetDataLength(len); uint8_t * plainText = msg->Start(); - ReturnErrorOnFailure(context.Decrypt(data, len, plainText, packetHeader, mac)); + ReturnErrorOnFailure(context.Decrypt(data, len, plainText, nonce, packetHeader, mac)); ReturnErrorOnFailure(payloadHeader.DecodeAndConsume(msg)); return CHIP_NO_ERROR; diff --git a/src/transport/SecureMessageCodec.h b/src/transport/SecureMessageCodec.h index 32460f0316944d..f074e792b59d21 100644 --- a/src/transport/SecureMessageCodec.h +++ b/src/transport/SecureMessageCodec.h @@ -49,8 +49,8 @@ namespace SecureMessageCodec { * the encrypted message. * @return A CHIP_ERROR value consistent with the result of the encryption operation */ -CHIP_ERROR Encrypt(const CryptoContext & context, PayloadHeader & payloadHeader, PacketHeader & packetHeader, - System::PacketBufferHandle & msgBuf); +CHIP_ERROR Encrypt(const CryptoContext & context, CryptoContext::ConstNonceView nonce, PayloadHeader & payloadHeader, + PacketHeader & packetHeader, System::PacketBufferHandle & msgBuf); /** * @brief @@ -66,8 +66,8 @@ CHIP_ERROR Encrypt(const CryptoContext & context, PayloadHeader & payloadHeader, * the decrypted message. * @return A CHIP_ERROR value consistent with the result of the decryption operation */ -CHIP_ERROR Decrypt(const CryptoContext & context, PayloadHeader & payloadHeader, const PacketHeader & packetHeader, - System::PacketBufferHandle & msgBuf); +CHIP_ERROR Decrypt(const CryptoContext & context, CryptoContext::ConstNonceView nonce, PayloadHeader & payloadHeader, + const PacketHeader & packetHeader, System::PacketBufferHandle & msgBuf); } // namespace SecureMessageCodec diff --git a/src/transport/SessionManager.cpp b/src/transport/SessionManager.cpp index 6dcbbdb5275613..de030265b5dd0d 100644 --- a/src/transport/SessionManager.cpp +++ b/src/transport/SessionManager.cpp @@ -170,7 +170,10 @@ CHIP_ERROR SessionManager::PrepareMessage(const SessionHandle & sessionHandle, P VerifyOrReturnError(nullptr != keyContext, CHIP_ERROR_INTERNAL); packetHeader.SetSessionId(keyContext->GetKeyHash()); - CHIP_ERROR err = SecureMessageCodec::Encrypt(CryptoContext(keyContext), payloadHeader, packetHeader, message); + CryptoContext::NonceStorage nonce; + CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), + groupSession->GetSourceNodeId()); + CHIP_ERROR err = SecureMessageCodec::Encrypt(CryptoContext(keyContext), nonce, payloadHeader, packetHeader, message); keyContext->Release(); ReturnErrorOnFailure(err); @@ -197,7 +200,18 @@ CHIP_ERROR SessionManager::PrepareMessage(const SessionHandle & sessionHandle, P // Trace before any encryption CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, message->Start(), message->TotalLength()); - ReturnErrorOnFailure(SecureMessageCodec::Encrypt(session->GetCryptoContext(), payloadHeader, packetHeader, message)); + CryptoContext::NonceStorage nonce; + if (session->GetSecureSessionType() == SecureSession::Type::kCASE) + { + FabricInfo * fabric = mFabricTable->FindFabricWithIndex(session->GetFabricIndex()); + VerifyOrDie(fabric != nullptr); + CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), messageCounter, fabric->GetNodeId()); + } + else + { + CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), messageCounter, kUndefinedNodeId); + } + ReturnErrorOnFailure(SecureMessageCodec::Encrypt(session->GetCryptoContext(), nonce, payloadHeader, packetHeader, message)); ReturnErrorOnFailure(counter.Advance()); #if CHIP_PROGRESS_LOGGING @@ -563,7 +577,11 @@ void SessionManager::SecureUnicastMessageDispatch(const PacketHeader & packetHea Transport::SecureSession * secureSession = session.Value()->AsSecureSession(); // Decrypt and verify the message before message counter verification or any further processing. - if (SecureMessageCodec::Decrypt(secureSession->GetCryptoContext(), payloadHeader, packetHeader, msg) != CHIP_NO_ERROR) + CryptoContext::NonceStorage nonce; + CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), + secureSession->GetSecureSessionType() == SecureSession::Type::kCASE ? secureSession->GetPeerNodeId() + : kUndefinedNodeId); + if (SecureMessageCodec::Decrypt(secureSession->GetCryptoContext(), nonce, payloadHeader, packetHeader, msg) != CHIP_NO_ERROR) { ChipLogError(Inet, "Secure transport received message, but failed to decode/authenticate it, discarding"); return; @@ -662,8 +680,11 @@ void SessionManager::SecureGroupMessageDispatch(const PacketHeader & packetHeade continue; } msgCopy = msg.CloneData(); - decrypted = - (CHIP_NO_ERROR == SecureMessageCodec::Decrypt(CryptoContext(groupContext.key), payloadHeader, packetHeader, msgCopy)); + CryptoContext::NonceStorage nonce; + CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), + packetHeader.GetSourceNodeId().Value()); + decrypted = (CHIP_NO_ERROR == + SecureMessageCodec::Decrypt(CryptoContext(groupContext.key), nonce, payloadHeader, packetHeader, msgCopy)); } iter->Release(); if (!decrypted) diff --git a/src/transport/tests/TestSecureSession.cpp b/src/transport/tests/TestSecureSession.cpp index f3fd41e5336af7..60625f717597be 100644 --- a/src/transport/tests/TestSecureSession.cpp +++ b/src/transport/tests/TestSecureSession.cpp @@ -83,6 +83,9 @@ void SecureChannelEncryptTest(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, packetHeader.IsEncrypted() == true); NL_TEST_ASSERT(inSuite, packetHeader.MICTagLength() == 16); + CryptoContext::NonceStorage nonce; + CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), 0); + P256Keypair keypair; NL_TEST_ASSERT(inSuite, keypair.Initialize() == CHIP_NO_ERROR); @@ -91,7 +94,7 @@ void SecureChannelEncryptTest(nlTestSuite * inSuite, void * inContext) // Test uninitialized channel NL_TEST_ASSERT(inSuite, - channel.Encrypt(plain_text, sizeof(plain_text), output, packetHeader, mac) == + channel.Encrypt(plain_text, sizeof(plain_text), output, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_USE_OF_SESSION_KEY); const char * salt = "Test Salt"; @@ -101,13 +104,13 @@ void SecureChannelEncryptTest(nlTestSuite * inSuite, void * inContext) CryptoContext::SessionRole::kInitiator) == CHIP_NO_ERROR); // Test initialized channel, but invalid arguments - NL_TEST_ASSERT(inSuite, channel.Encrypt(nullptr, 0, nullptr, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); - NL_TEST_ASSERT(inSuite, channel.Encrypt(plain_text, 0, nullptr, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); - NL_TEST_ASSERT(inSuite, - channel.Encrypt(plain_text, sizeof(plain_text), nullptr, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); + NL_TEST_ASSERT(inSuite, channel.Encrypt(nullptr, 0, nullptr, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); + NL_TEST_ASSERT(inSuite, channel.Encrypt(plain_text, 0, nullptr, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); + NL_TEST_ASSERT( + inSuite, channel.Encrypt(plain_text, sizeof(plain_text), nullptr, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); // Valid arguments - NL_TEST_ASSERT(inSuite, channel.Encrypt(plain_text, sizeof(plain_text), output, packetHeader, mac) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, channel.Encrypt(plain_text, sizeof(plain_text), output, nonce, packetHeader, mac) == CHIP_NO_ERROR); } void SecureChannelDecryptTest(nlTestSuite * inSuite, void * inContext) @@ -122,6 +125,9 @@ void SecureChannelDecryptTest(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, packetHeader.IsEncrypted() == true); NL_TEST_ASSERT(inSuite, packetHeader.MICTagLength() == 16); + CryptoContext::NonceStorage nonce; + CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), 0); + const char * salt = "Test Salt"; P256Keypair keypair; @@ -134,13 +140,13 @@ void SecureChannelDecryptTest(nlTestSuite * inSuite, void * inContext) channel.InitFromKeyPair(keypair, keypair2.Pubkey(), ByteSpan((const uint8_t *) salt, sizeof(salt)), CryptoContext::SessionInfoType::kSessionEstablishment, CryptoContext::SessionRole::kInitiator) == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, channel.Encrypt(plain_text, sizeof(plain_text), encrypted, packetHeader, mac) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, channel.Encrypt(plain_text, sizeof(plain_text), encrypted, nonce, packetHeader, mac) == CHIP_NO_ERROR); CryptoContext channel2; uint8_t output[128]; // Uninitialized channel NL_TEST_ASSERT(inSuite, - channel2.Decrypt(encrypted, sizeof(plain_text), output, packetHeader, mac) == + channel2.Decrypt(encrypted, sizeof(plain_text), output, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_USE_OF_SESSION_KEY); NL_TEST_ASSERT(inSuite, channel2.InitFromKeyPair(keypair2, keypair.Pubkey(), ByteSpan((const uint8_t *) salt, sizeof(salt)), @@ -148,13 +154,13 @@ void SecureChannelDecryptTest(nlTestSuite * inSuite, void * inContext) CryptoContext::SessionRole::kResponder) == CHIP_NO_ERROR); // Channel initialized, but invalid arguments to decrypt - NL_TEST_ASSERT(inSuite, channel2.Decrypt(nullptr, 0, nullptr, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); - NL_TEST_ASSERT(inSuite, channel2.Decrypt(encrypted, 0, nullptr, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); - NL_TEST_ASSERT(inSuite, - channel2.Decrypt(encrypted, sizeof(encrypted), nullptr, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); + NL_TEST_ASSERT(inSuite, channel2.Decrypt(nullptr, 0, nullptr, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); + NL_TEST_ASSERT(inSuite, channel2.Decrypt(encrypted, 0, nullptr, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); + NL_TEST_ASSERT( + inSuite, channel2.Decrypt(encrypted, sizeof(encrypted), nullptr, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); // Valid arguments - NL_TEST_ASSERT(inSuite, channel2.Decrypt(encrypted, sizeof(plain_text), output, packetHeader, mac) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, channel2.Decrypt(encrypted, sizeof(plain_text), output, nonce, packetHeader, mac) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, memcmp(plain_text, output, sizeof(plain_text)) == 0); } diff --git a/src/transport/tests/TestSessionManager.cpp b/src/transport/tests/TestSessionManager.cpp index 5039e3e70ba78d..4cda4fcaa699f3 100644 --- a/src/transport/tests/TestSessionManager.cpp +++ b/src/transport/tests/TestSessionManager.cpp @@ -24,6 +24,7 @@ #define CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API // Up here in case some other header // includes SessionManager.h indirectly +#include #include #include #include @@ -54,9 +55,7 @@ using TestContext = chip::Test::IOContext; TestContext sContext; -const char PAYLOAD[] = "Hello!"; -constexpr NodeId kSourceNodeId = 123654; -constexpr NodeId kDestinationNodeId = 111222333; +const char PAYLOAD[] = "Hello!"; const char LARGE_PAYLOAD[kMaxAppMessageLen + 1] = "test message"; @@ -147,17 +146,37 @@ void CheckMessageTest(nlTestSuite * inSuite, void * inContext) sessionManager.SetMessageDelegate(&callback); Optional peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); - SessionHolder localToRemoteSession; - SessionHolder remoteToLocalSession; - SecurePairingUsingTestSecret pairing1(1, 2); - err = - sessionManager.NewPairing(localToRemoteSession, peer, kSourceNodeId, &pairing1, CryptoContext::SessionRole::kInitiator, 1); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - - SecurePairingUsingTestSecret pairing2(2, 1); - err = sessionManager.NewPairing(remoteToLocalSession, peer, kDestinationNodeId, &pairing2, - CryptoContext::SessionRole::kResponder, 0); + FabricIndex aliceFabricIndex; + FabricInfo aliceFabric; + aliceFabric.TestOnlyBuildFabric( + ByteSpan(TestCerts::sTestCert_Root01_Chip, TestCerts::sTestCert_Root01_Chip_Len), + ByteSpan(TestCerts::sTestCert_ICA01_Chip, TestCerts::sTestCert_ICA01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_Chip, TestCerts::sTestCert_Node01_01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_PublicKey, TestCerts::sTestCert_Node01_01_PublicKey_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_PrivateKey, TestCerts::sTestCert_Node01_01_PrivateKey_Len)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTable.AddNewFabric(aliceFabric, &aliceFabricIndex)); + + FabricIndex bobFabricIndex; + FabricInfo bobFabric; + bobFabric.TestOnlyBuildFabric( + ByteSpan(TestCerts::sTestCert_Root02_Chip, TestCerts::sTestCert_Root02_Chip_Len), + ByteSpan(TestCerts::sTestCert_ICA02_Chip, TestCerts::sTestCert_ICA02_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_Chip, TestCerts::sTestCert_Node02_01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_PublicKey, TestCerts::sTestCert_Node02_01_PublicKey_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_PrivateKey, TestCerts::sTestCert_Node02_01_PrivateKey_Len)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTable.AddNewFabric(bobFabric, &bobFabricIndex)); + + SessionHolder aliceToBobSession; + SecurePairingUsingTestSecret aliceToBobPairing(1, 2); + err = sessionManager.NewPairing(aliceToBobSession, peer, fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), + &aliceToBobPairing, CryptoContext::SessionRole::kInitiator, aliceFabricIndex); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + SecurePairingUsingTestSecret bobToAlicePairing(2, 1); + SessionHolder bobToAliceSession; + err = sessionManager.NewPairing(bobToAliceSession, peer, fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), + &bobToAlicePairing, CryptoContext::SessionRole::kResponder, bobFabricIndex); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); // Should be able to send a message to itself by just calling send. @@ -172,10 +191,10 @@ void CheckMessageTest(nlTestSuite * inSuite, void * inContext) payloadHeader.SetMessageType(chip::Protocols::Echo::MsgType::EchoRequest); EncryptedPacketBufferHandle preparedMessage; - err = sessionManager.PrepareMessage(localToRemoteSession.Get(), payloadHeader, std::move(buffer), preparedMessage); + err = sessionManager.PrepareMessage(aliceToBobSession.Get(), payloadHeader, std::move(buffer), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), preparedMessage); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); @@ -186,10 +205,10 @@ void CheckMessageTest(nlTestSuite * inSuite, void * inContext) callback.LargeMessageSent = true; - err = sessionManager.PrepareMessage(localToRemoteSession.Get(), payloadHeader, std::move(large_buffer), preparedMessage); + err = sessionManager.PrepareMessage(aliceToBobSession.Get(), payloadHeader, std::move(large_buffer), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), preparedMessage); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); @@ -202,7 +221,7 @@ void CheckMessageTest(nlTestSuite * inSuite, void * inContext) callback.LargeMessageSent = true; - err = sessionManager.PrepareMessage(localToRemoteSession.Get(), payloadHeader, std::move(extra_large_buffer), preparedMessage); + err = sessionManager.PrepareMessage(aliceToBobSession.Get(), payloadHeader, std::move(extra_large_buffer), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_MESSAGE_TOO_LONG); sessionManager.Shutdown(); @@ -242,17 +261,37 @@ void SendEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) sessionManager.SetMessageDelegate(&callback); Optional peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); - SessionHolder localToRemoteSession; - SessionHolder remoteToLocalSession; - - SecurePairingUsingTestSecret pairing1(1, 2); - err = - sessionManager.NewPairing(localToRemoteSession, peer, kSourceNodeId, &pairing1, CryptoContext::SessionRole::kInitiator, 1); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - SecurePairingUsingTestSecret pairing2(2, 1); - err = sessionManager.NewPairing(remoteToLocalSession, peer, kDestinationNodeId, &pairing2, - CryptoContext::SessionRole::kResponder, 0); + FabricIndex aliceFabricIndex; + FabricInfo aliceFabric; + aliceFabric.TestOnlyBuildFabric( + ByteSpan(TestCerts::sTestCert_Root01_Chip, TestCerts::sTestCert_Root01_Chip_Len), + ByteSpan(TestCerts::sTestCert_ICA01_Chip, TestCerts::sTestCert_ICA01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_Chip, TestCerts::sTestCert_Node01_01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_PublicKey, TestCerts::sTestCert_Node01_01_PublicKey_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_PrivateKey, TestCerts::sTestCert_Node01_01_PrivateKey_Len)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTable.AddNewFabric(aliceFabric, &aliceFabricIndex)); + + FabricIndex bobFabricIndex; + FabricInfo bobFabric; + bobFabric.TestOnlyBuildFabric( + ByteSpan(TestCerts::sTestCert_Root02_Chip, TestCerts::sTestCert_Root02_Chip_Len), + ByteSpan(TestCerts::sTestCert_ICA02_Chip, TestCerts::sTestCert_ICA02_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_Chip, TestCerts::sTestCert_Node02_01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_PublicKey, TestCerts::sTestCert_Node02_01_PublicKey_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_PrivateKey, TestCerts::sTestCert_Node02_01_PrivateKey_Len)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTable.AddNewFabric(bobFabric, &bobFabricIndex)); + + SessionHolder aliceToBobSession; + SecurePairingUsingTestSecret aliceToBobPairing(1, 2); + err = sessionManager.NewPairing(aliceToBobSession, peer, fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), + &aliceToBobPairing, CryptoContext::SessionRole::kInitiator, aliceFabricIndex); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + SecurePairingUsingTestSecret bobToAlicePairing(2, 1); + SessionHolder bobToAliceSession; + err = sessionManager.NewPairing(bobToAliceSession, peer, fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), + &bobToAlicePairing, CryptoContext::SessionRole::kResponder, bobFabricIndex); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); // Should be able to send a message to itself by just calling send. @@ -269,19 +308,19 @@ void SendEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) payloadHeader.SetInitiator(true); - err = sessionManager.PrepareMessage(localToRemoteSession.Get(), payloadHeader, std::move(buffer), preparedMessage); + err = sessionManager.PrepareMessage(aliceToBobSession.Get(), payloadHeader, std::move(buffer), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), preparedMessage); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); // Reset receive side message counter, or duplicated message will be denied. - Transport::SecureSession * session = remoteToLocalSession.Get()->AsSecureSession(); + Transport::SecureSession * session = bobToAliceSession.Get()->AsSecureSession(); session->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(1); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), preparedMessage); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); @@ -323,17 +362,37 @@ void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) sessionManager.SetMessageDelegate(&callback); Optional peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); - SessionHolder localToRemoteSession; - SessionHolder remoteToLocalSession; - - SecurePairingUsingTestSecret pairing1(1, 2); - err = - sessionManager.NewPairing(localToRemoteSession, peer, kSourceNodeId, &pairing1, CryptoContext::SessionRole::kInitiator, 1); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - SecurePairingUsingTestSecret pairing2(2, 1); - err = sessionManager.NewPairing(remoteToLocalSession, peer, kDestinationNodeId, &pairing2, - CryptoContext::SessionRole::kResponder, 0); + FabricIndex aliceFabricIndex; + FabricInfo aliceFabric; + aliceFabric.TestOnlyBuildFabric( + ByteSpan(TestCerts::sTestCert_Root01_Chip, TestCerts::sTestCert_Root01_Chip_Len), + ByteSpan(TestCerts::sTestCert_ICA01_Chip, TestCerts::sTestCert_ICA01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_Chip, TestCerts::sTestCert_Node01_01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_PublicKey, TestCerts::sTestCert_Node01_01_PublicKey_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_PrivateKey, TestCerts::sTestCert_Node01_01_PrivateKey_Len)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTable.AddNewFabric(aliceFabric, &aliceFabricIndex)); + + FabricIndex bobFabricIndex; + FabricInfo bobFabric; + bobFabric.TestOnlyBuildFabric( + ByteSpan(TestCerts::sTestCert_Root02_Chip, TestCerts::sTestCert_Root02_Chip_Len), + ByteSpan(TestCerts::sTestCert_ICA02_Chip, TestCerts::sTestCert_ICA02_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_Chip, TestCerts::sTestCert_Node02_01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_PublicKey, TestCerts::sTestCert_Node02_01_PublicKey_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_PrivateKey, TestCerts::sTestCert_Node02_01_PrivateKey_Len)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTable.AddNewFabric(bobFabric, &bobFabricIndex)); + + SessionHolder aliceToBobSession; + SecurePairingUsingTestSecret aliceToBobPairing(1, 2); + err = sessionManager.NewPairing(aliceToBobSession, peer, fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), + &aliceToBobPairing, CryptoContext::SessionRole::kInitiator, aliceFabricIndex); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + SecurePairingUsingTestSecret bobToAlicePairing(2, 1); + SessionHolder bobToAliceSession; + err = sessionManager.NewPairing(bobToAliceSession, peer, fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), + &bobToAlicePairing, CryptoContext::SessionRole::kResponder, bobFabricIndex); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); // Should be able to send a message to itself by just calling send. @@ -350,17 +409,17 @@ void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) payloadHeader.SetInitiator(true); - err = sessionManager.PrepareMessage(localToRemoteSession.Get(), payloadHeader, std::move(buffer), preparedMessage); + err = sessionManager.PrepareMessage(aliceToBobSession.Get(), payloadHeader, std::move(buffer), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), preparedMessage); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); /* -------------------------------------------------------------------------------------------*/ // Reset receive side message counter, or duplicated message will be denied. - Transport::SecureSession * session = remoteToLocalSession.Get()->AsSecureSession(); + Transport::SecureSession * session = bobToAliceSession.Get()->AsSecureSession(); session->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(1); PacketHeader packetHeader; @@ -373,7 +432,7 @@ void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) packetHeader.SetMessageCounter(messageCounter + 1); NL_TEST_ASSERT(inSuite, badMessageCounterMsg.InsertPacketHeader(packetHeader) == CHIP_NO_ERROR); - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), badMessageCounterMsg); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), badMessageCounterMsg); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); @@ -389,7 +448,7 @@ void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) packetHeader.SetSessionId(3); NL_TEST_ASSERT(inSuite, badKeyIdMsg.InsertPacketHeader(packetHeader) == CHIP_NO_ERROR); - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), badKeyIdMsg); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), badKeyIdMsg); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); /* -------------------------------------------------------------------------------------------*/ @@ -398,7 +457,7 @@ void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); // Send the correct encrypted msg - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), preparedMessage); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); @@ -410,6 +469,8 @@ void StaleConnectionDropTest(nlTestSuite * inSuite, void * inContext) { TestContext & ctx = *reinterpret_cast(inContext); + constexpr NodeId kSourceNodeId = 123654; + IPAddress addr; IPAddress::FromString("::1", addr); CHIP_ERROR err = CHIP_NO_ERROR; @@ -507,17 +568,37 @@ void SendPacketWithOldCounterTest(nlTestSuite * inSuite, void * inContext) sessionManager.SetMessageDelegate(&callback); Optional peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); - SessionHolder localToRemoteSession; - SessionHolder remoteToLocalSession; - - SecurePairingUsingTestSecret pairing1(1, 2); - err = - sessionManager.NewPairing(localToRemoteSession, peer, kSourceNodeId, &pairing1, CryptoContext::SessionRole::kInitiator, 1); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - SecurePairingUsingTestSecret pairing2(2, 1); - err = sessionManager.NewPairing(remoteToLocalSession, peer, kDestinationNodeId, &pairing2, - CryptoContext::SessionRole::kResponder, 0); + FabricIndex aliceFabricIndex; + FabricInfo aliceFabric; + aliceFabric.TestOnlyBuildFabric( + ByteSpan(TestCerts::sTestCert_Root01_Chip, TestCerts::sTestCert_Root01_Chip_Len), + ByteSpan(TestCerts::sTestCert_ICA01_Chip, TestCerts::sTestCert_ICA01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_Chip, TestCerts::sTestCert_Node01_01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_PublicKey, TestCerts::sTestCert_Node01_01_PublicKey_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_PrivateKey, TestCerts::sTestCert_Node01_01_PrivateKey_Len)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTable.AddNewFabric(aliceFabric, &aliceFabricIndex)); + + FabricIndex bobFabricIndex; + FabricInfo bobFabric; + bobFabric.TestOnlyBuildFabric( + ByteSpan(TestCerts::sTestCert_Root02_Chip, TestCerts::sTestCert_Root02_Chip_Len), + ByteSpan(TestCerts::sTestCert_ICA02_Chip, TestCerts::sTestCert_ICA02_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_Chip, TestCerts::sTestCert_Node02_01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_PublicKey, TestCerts::sTestCert_Node02_01_PublicKey_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_PrivateKey, TestCerts::sTestCert_Node02_01_PrivateKey_Len)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTable.AddNewFabric(bobFabric, &bobFabricIndex)); + + SessionHolder aliceToBobSession; + SecurePairingUsingTestSecret aliceToBobPairing(1, 2); + err = sessionManager.NewPairing(aliceToBobSession, peer, fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), + &aliceToBobPairing, CryptoContext::SessionRole::kInitiator, aliceFabricIndex); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + SecurePairingUsingTestSecret bobToAlicePairing(2, 1); + SessionHolder bobToAliceSession; + err = sessionManager.NewPairing(bobToAliceSession, peer, fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), + &bobToAlicePairing, CryptoContext::SessionRole::kResponder, bobFabricIndex); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); callback.ReceiveHandlerCallCount = 0; @@ -533,10 +614,10 @@ void SendPacketWithOldCounterTest(nlTestSuite * inSuite, void * inContext) payloadHeader.SetInitiator(true); - err = sessionManager.PrepareMessage(localToRemoteSession.Get(), payloadHeader, std::move(buffer), preparedMessage); + err = sessionManager.PrepareMessage(aliceToBobSession.Get(), payloadHeader, std::move(buffer), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), preparedMessage); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); @@ -548,18 +629,18 @@ void SendPacketWithOldCounterTest(nlTestSuite * inSuite, void * inContext) buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len); NL_TEST_ASSERT(inSuite, !buffer.IsNull()); - err = sessionManager.PrepareMessage(localToRemoteSession.Get(), payloadHeader, std::move(buffer), newMessage); + err = sessionManager.PrepareMessage(aliceToBobSession.Get(), payloadHeader, std::move(buffer), newMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); } - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), newMessage); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), newMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); // Now resend our original message. It should be rejected as a duplicate. - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), preparedMessage); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); @@ -601,17 +682,37 @@ void SendPacketWithTooOldCounterTest(nlTestSuite * inSuite, void * inContext) sessionManager.SetMessageDelegate(&callback); Optional peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); - SessionHolder localToRemoteSession; - SessionHolder remoteToLocalSession; - - SecurePairingUsingTestSecret pairing1(1, 2); - err = - sessionManager.NewPairing(localToRemoteSession, peer, kSourceNodeId, &pairing1, CryptoContext::SessionRole::kInitiator, 1); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - SecurePairingUsingTestSecret pairing2(2, 1); - err = sessionManager.NewPairing(remoteToLocalSession, peer, kDestinationNodeId, &pairing2, - CryptoContext::SessionRole::kResponder, 0); + FabricIndex aliceFabricIndex; + FabricInfo aliceFabric; + aliceFabric.TestOnlyBuildFabric( + ByteSpan(TestCerts::sTestCert_Root01_Chip, TestCerts::sTestCert_Root01_Chip_Len), + ByteSpan(TestCerts::sTestCert_ICA01_Chip, TestCerts::sTestCert_ICA01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_Chip, TestCerts::sTestCert_Node01_01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_PublicKey, TestCerts::sTestCert_Node01_01_PublicKey_Len), + ByteSpan(TestCerts::sTestCert_Node01_01_PrivateKey, TestCerts::sTestCert_Node01_01_PrivateKey_Len)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTable.AddNewFabric(aliceFabric, &aliceFabricIndex)); + + FabricIndex bobFabricIndex; + FabricInfo bobFabric; + bobFabric.TestOnlyBuildFabric( + ByteSpan(TestCerts::sTestCert_Root02_Chip, TestCerts::sTestCert_Root02_Chip_Len), + ByteSpan(TestCerts::sTestCert_ICA02_Chip, TestCerts::sTestCert_ICA02_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_Chip, TestCerts::sTestCert_Node02_01_Chip_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_PublicKey, TestCerts::sTestCert_Node02_01_PublicKey_Len), + ByteSpan(TestCerts::sTestCert_Node02_01_PrivateKey, TestCerts::sTestCert_Node02_01_PrivateKey_Len)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTable.AddNewFabric(bobFabric, &bobFabricIndex)); + + SessionHolder aliceToBobSession; + SecurePairingUsingTestSecret aliceToBobPairing(1, 2); + err = sessionManager.NewPairing(aliceToBobSession, peer, fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), + &aliceToBobPairing, CryptoContext::SessionRole::kInitiator, aliceFabricIndex); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + SecurePairingUsingTestSecret bobToAlicePairing(2, 1); + SessionHolder bobToAliceSession; + err = sessionManager.NewPairing(bobToAliceSession, peer, fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), + &bobToAlicePairing, CryptoContext::SessionRole::kResponder, bobFabricIndex); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); callback.ReceiveHandlerCallCount = 0; @@ -627,10 +728,10 @@ void SendPacketWithTooOldCounterTest(nlTestSuite * inSuite, void * inContext) payloadHeader.SetInitiator(true); - err = sessionManager.PrepareMessage(localToRemoteSession.Get(), payloadHeader, std::move(buffer), preparedMessage); + err = sessionManager.PrepareMessage(aliceToBobSession.Get(), payloadHeader, std::move(buffer), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), preparedMessage); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); @@ -644,18 +745,18 @@ void SendPacketWithTooOldCounterTest(nlTestSuite * inSuite, void * inContext) buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len); NL_TEST_ASSERT(inSuite, !buffer.IsNull()); - err = sessionManager.PrepareMessage(localToRemoteSession.Get(), payloadHeader, std::move(buffer), newMessage); + err = sessionManager.PrepareMessage(aliceToBobSession.Get(), payloadHeader, std::move(buffer), newMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); } - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), newMessage); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), newMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); // Now resend our original message. It should be rejected as a duplicate. - err = sessionManager.SendPreparedMessage(localToRemoteSession.Get(), preparedMessage); + err = sessionManager.SendPreparedMessage(aliceToBobSession.Get(), preparedMessage); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); From a1a0506b2f2f6c099ed83b61348dfbbea5b2ef79 Mon Sep 17 00:00:00 2001 From: Zang MingJie Date: Thu, 24 Mar 2022 23:47:24 +0800 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Tennessee Carmel-Veilleux --- src/credentials/FabricTable.cpp | 3 +-- src/transport/SessionManager.cpp | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/credentials/FabricTable.cpp b/src/credentials/FabricTable.cpp index e01d71cccfbbce..6d5cad927ed798 100644 --- a/src/credentials/FabricTable.cpp +++ b/src/credentials/FabricTable.cpp @@ -622,8 +622,7 @@ CHIP_ERROR FabricTable::LoadFromStorage(FabricInfo * fabric) FabricTableDelegate * delegate = mDelegate; while (delegate) { - ChipLogProgress(Discovery, "Fabric (%d) loaded from storage. Calling OnFabricRetrievedFromStorage", - fabric->GetFabricIndex()); + ChipLogProgress(Discovery, "Fabric (%d) loaded from storage", fabric->GetFabricIndex()); delegate->OnFabricRetrievedFromStorage(fabric); delegate = delegate->mNext; } diff --git a/src/transport/SessionManager.cpp b/src/transport/SessionManager.cpp index de030265b5dd0d..fbec5c5b5d968c 100644 --- a/src/transport/SessionManager.cpp +++ b/src/transport/SessionManager.cpp @@ -209,6 +209,8 @@ CHIP_ERROR SessionManager::PrepareMessage(const SessionHandle & sessionHandle, P } else { + // PASE Sessions use the undefined node ID of all zeroes, since there is no node ID to use + // and the key is short-lived and always different for each PASE session. CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), messageCounter, kUndefinedNodeId); } ReturnErrorOnFailure(SecureMessageCodec::Encrypt(session->GetCryptoContext(), nonce, payloadHeader, packetHeader, message)); @@ -578,6 +580,8 @@ void SessionManager::SecureUnicastMessageDispatch(const PacketHeader & packetHea Transport::SecureSession * secureSession = session.Value()->AsSecureSession(); // Decrypt and verify the message before message counter verification or any further processing. CryptoContext::NonceStorage nonce; + // PASE Sessions use the undefined node ID of all zeroes, since there is no node ID to use + // and the key is short-lived and always different for each PASE session. CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), secureSession->GetSecureSessionType() == SecureSession::Type::kCASE ? secureSession->GetPeerNodeId() : kUndefinedNodeId);