From 1381068e7e0f54c80870f4ad54969ffdf561ecff Mon Sep 17 00:00:00 2001 From: Tennessee Carmel-Veilleux Date: Tue, 20 Jul 2021 21:12:40 -0400 Subject: [PATCH] Add intermediate digest computation to Hash_SHA256_Stream (#8496) * Add intermediate digest computation to Hash_SHA256_Stream - Add GetDigest() to Hash_SHA256_Stream and associated tests - Make Hash_SHA256_Stream work with safe spans (partial fix to #4189) - Fix all usages of Hash_SHA256_Stream - Drive-by simplification of hex conversion in Rotating ID Testing done: - Cert tests (test_suite.sh) for both mbedTLS and OpenSSL - gn check on host - cross-validation check of rotating ID with the following Python snippet: ``` >>> to_hash = b"TEST_SN" + b"\x00\x00" >>> print(to_octet_string(b"\x00\x00" + CHIP_Crypto_Hash(to_hash)[-16:]).replace(":","").upper()) 00007C5F6E176CD40F68685D100A1CF8A98B ``` This was verified against cert tests output: ``` [1626748850.369690][132218:132218] CHIP:DL: Device Configuration: [1626748850.369695][132218:132218] CHIP:DL: Serial Number: TEST_SN [1626748850.369699][132218:132218] CHIP:DL: Vendor Id: 9050 (0x235A) [1626748850.369702][132218:132218] CHIP:DL: Product Id: 65279 (0xFEFF) [1626748850.369706][132218:132218] CHIP:DL: Product Revision: 1 [1626748850.369709][132218:132218] CHIP:DL: Setup Pin Code: 20202021 [1626748850.369713][132218:132218] CHIP:DL: Setup Discriminator: 3840 (0xF00) [1626748850.369716][132218:132218] CHIP:DL: Manufacturing Date: (not set) [1626748850.369720][132218:132218] CHIP:DL: Device Type: 65535 (0xFFFF) [1626748850.369732][132218:132218] CHIP:SVR: SetupQRCode: [MT:YNJV7VSC00KA0648G00] ............................. [1626748850.370936][132218:132218] CHIP:DL: rotatingDeviceId: 00007C5F6E176CD40F68685D100A1CF8A98B ``` Issue #4189 Fixes #8495 * Restyled by clang-format * Fix for scripts/build test failure * Fix build on ESP32, apply review comments * Apply review comment from @emargolis Co-authored-by: Restyled.io Co-authored-by: Switi Mhaiske --- src/credentials/GenerateChipX509Cert.cpp | 7 +- src/crypto/CHIPCryptoPAL.cpp | 5 +- src/crypto/CHIPCryptoPAL.h | 62 ++++++++++++- src/crypto/CHIPCryptoPALOpenSSL.cpp | 38 ++++++-- src/crypto/CHIPCryptoPALmbedTLS.cpp | 36 +++++-- src/crypto/tests/CHIPCryptoPALTest.cpp | 93 ++++++++++++++++++- src/protocols/secure_channel/CASESession.cpp | 28 +++--- src/protocols/secure_channel/PASESession.cpp | 18 ++-- .../AdditionalDataPayloadGenerator.cpp | 25 +++-- 9 files changed, 252 insertions(+), 60 deletions(-) diff --git a/src/credentials/GenerateChipX509Cert.cpp b/src/credentials/GenerateChipX509Cert.cpp index 43a602ca0fed82..c7ec3c53e418de 100644 --- a/src/credentials/GenerateChipX509Cert.cpp +++ b/src/credentials/GenerateChipX509Cert.cpp @@ -42,6 +42,7 @@ namespace chip { namespace Credentials { using namespace chip::ASN1; +using namespace chip::Crypto; using namespace chip::Protocols; namespace { @@ -58,8 +59,6 @@ enum IsCACert kNotCACert, }; -constexpr uint8_t kSHA1_Hash_Langth = 20; - CHIP_ERROR EncodeSubjectPublicKeyInfo(const Crypto::P256PublicKey & pubkey, ASN1Writer & writer) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -95,7 +94,7 @@ CHIP_ERROR EncodeAuthorityKeyIdentifierExtension(const Crypto::P256PublicKey & p { ASN1_START_SEQUENCE { - uint8_t keyid[kSHA1_Hash_Langth]; + uint8_t keyid[kSHA1_Hash_Length]; ReturnErrorOnFailure(Crypto::Hash_SHA1(pubkey, pubkey.Length(), keyid)); ReturnErrorOnFailure( @@ -123,7 +122,7 @@ CHIP_ERROR EncodeSubjectKeyIdentifierExtension(const Crypto::P256PublicKey & pub ASN1_START_OCTET_STRING_ENCAPSULATED { - uint8_t keyid[kSHA1_Hash_Langth]; + uint8_t keyid[kSHA1_Hash_Length]; ReturnErrorOnFailure(Crypto::Hash_SHA1(pubkey, pubkey.Length(), keyid)); ReturnErrorOnFailure(writer.PutOctetString(keyid, static_cast(sizeof(keyid)))); diff --git a/src/crypto/CHIPCryptoPAL.cpp b/src/crypto/CHIPCryptoPAL.cpp index 3542a7f1dd2010..de08e82d0c2a7a 100644 --- a/src/crypto/CHIPCryptoPAL.cpp +++ b/src/crypto/CHIPCryptoPAL.cpp @@ -472,13 +472,14 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitImpl() CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::Hash(const uint8_t * in, size_t in_len) { - ReturnErrorOnFailure(sha256_hash_ctx.AddData(in, in_len)); + ReturnErrorOnFailure(sha256_hash_ctx.AddData(ByteSpan{ in, in_len })); return CHIP_NO_ERROR; } CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::HashFinalize(uint8_t * out) { - ReturnErrorOnFailure(sha256_hash_ctx.Finish(out)); + MutableByteSpan out_span(out, kSHA256_Hash_Length); + ReturnErrorOnFailure(sha256_hash_ctx.Finish(out_span)); return CHIP_NO_ERROR; } diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h index 1a4f8c74d326e8..653f685a136570 100644 --- a/src/crypto/CHIPCryptoPAL.h +++ b/src/crypto/CHIPCryptoPAL.h @@ -42,6 +42,7 @@ constexpr size_t kP256_FE_Length = 32; constexpr size_t kP256_ECDSA_Signature_Length_Raw = (2 * kP256_FE_Length); constexpr size_t kP256_Point_Length = (2 * kP256_FE_Length + 1); constexpr size_t kSHA256_Hash_Length = 32; +constexpr size_t kSHA1_Hash_Length = 20; constexpr size_t CHIP_CRYPTO_GROUP_SIZE_BYTES = kP256_FE_Length; constexpr size_t CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES = kP256_Point_Length; @@ -66,12 +67,24 @@ constexpr size_t kP256_PublicKey_Length = CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES; * the implementation files. */ constexpr size_t kMAX_Spake2p_Context_Size = 1024; -constexpr size_t kMAX_Hash_SHA256_Context_Size = 296; constexpr size_t kMAX_P256Keypair_Context_Size = 512; constexpr size_t kEmitDerIntegerWithoutTagOverhead = 1; // 1 sign stuffer constexpr size_t kEmitDerIntegerOverhead = 3; // Tag + Length byte + 1 sign stuffer +/* + * Worst case is OpenSSL, so let's use its worst case and let static assert tell us if + * we are wrong, since `typedef SHA_LONG unsigned int` is default. + * SHA_LONG h[8]; + * SHA_LONG Nl, Nh; + * SHA_LONG data[SHA_LBLOCK]; // SHA_LBLOCK is 16 for SHA256 + * unsigned int num, md_len; + * + * We also have to account for possibly some custom extensions on some targets, + * especially for mbedTLS, so an extra sizeof(uint64_t) is added to account. + */ +constexpr size_t kMAX_Hash_SHA256_Context_Size = ((sizeof(unsigned int) * (8 + 2 + 16 + 2)) + sizeof(uint64_t)); + /* * Overhead to encode a raw ECDSA signature in X9.62 format in ASN.1 DER * @@ -509,9 +522,52 @@ class Hash_SHA256_stream Hash_SHA256_stream(); ~Hash_SHA256_stream(); + /** + * @brief Re-initialize digest computation to an empty context. + * + * @return CHIP_ERROR_INTERNAL on failure to initialize the context, + * CHIP_NO_ERROR otherwise. + */ CHIP_ERROR Begin(); - CHIP_ERROR AddData(const uint8_t * data, size_t data_length); - CHIP_ERROR Finish(uint8_t * out_buffer); + + /** + * @brief Add some data to the digest computation, updating internal state. + * + * @param[in] data The span of bytes to include in the digest update process. + * + * @return CHIP_ERROR_INTERNAL on failure to ingest the data, CHIP_NO_ERROR otherwise. + */ + CHIP_ERROR AddData(const ByteSpan data); + + /** + * @brief Get the intermediate padded digest for the current state of the stream. + * + * More data can be added before finish is called. + * + * @param[inout] out_buffer Output buffer to receive the digest. `out_buffer` must + * be at least `kSHA256_Hash_Length` bytes long. The `out_buffer` size + * will be set to `kSHA256_Hash_Length` on success. + * + * @return CHIP_ERROR_INTERNAL on failure to compute the digest, CHIP_ERROR_BUFFER_TOO_SMALL + * if out_buffer is too small, CHIP_NO_ERROR otherwise. + */ + CHIP_ERROR GetDigest(MutableByteSpan & out_buffer); + + /** + * @brief Finalize the stream digest computation, getting the final digest. + * + * @param[inout] out_buffer Output buffer to receive the digest. `out_buffer` must + * be at least `kSHA256_Hash_Length` bytes long. The `out_buffer` size + * will be set to `kSHA256_Hash_Length` on success. + * + * @return CHIP_ERROR_INTERNAL on failure to compute the digest, CHIP_ERROR_BUFFER_TOO_SMALL + * if out_buffer is too small, CHIP_NO_ERROR otherwise. + */ + CHIP_ERROR Finish(MutableByteSpan & out_buffer); + + /** + * @brief Clear-out internal digest data to avoid lingering the state. + */ void Clear(); private: diff --git a/src/crypto/CHIPCryptoPALOpenSSL.cpp b/src/crypto/CHIPCryptoPALOpenSSL.cpp index cc5727e492f220..6cebb87dfe5324 100644 --- a/src/crypto/CHIPCryptoPALOpenSSL.cpp +++ b/src/crypto/CHIPCryptoPALOpenSSL.cpp @@ -304,7 +304,13 @@ CHIP_ERROR Hash_SHA1(const uint8_t * data, const size_t data_length, uint8_t * o Hash_SHA256_stream::Hash_SHA256_stream() {} -Hash_SHA256_stream::~Hash_SHA256_stream() {} +Hash_SHA256_stream::~Hash_SHA256_stream() +{ + Clear(); +} + +static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(SHA256_CTX), + "kMAX_Hash_SHA256_Context_Size is too small for the size of underlying SHA256_CTX"); static inline SHA256_CTX * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context) { @@ -321,29 +327,47 @@ CHIP_ERROR Hash_SHA256_stream::Begin() return CHIP_NO_ERROR; } -CHIP_ERROR Hash_SHA256_stream::AddData(const uint8_t * data, const size_t data_length) +CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data) { SHA256_CTX * const context = to_inner_hash_sha256_context(&mContext); - const int result = SHA256_Update(context, Uint8::to_const_uchar(data), data_length); + const int result = SHA256_Update(context, Uint8::to_const_uchar(data.data()), data.size()); VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL); return CHIP_NO_ERROR; } -CHIP_ERROR Hash_SHA256_stream::Finish(uint8_t * out_buffer) +CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer) { - SHA256_CTX * const context = to_inner_hash_sha256_context(&mContext); + SHA256_CTX * context = to_inner_hash_sha256_context(&mContext); + + // Back-up context as we are about to finalize the hash to extract digest. + SHA256_CTX previous_ctx = *context; + + // Pad + compute digest, then finalize context. It is restored next line to continue. + CHIP_ERROR result = Finish(out_buffer); - const int result = SHA256_Final(Uint8::to_uchar(out_buffer), context); + // Restore context prior to finalization. + *context = previous_ctx; + + return result; +} + +CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer) +{ + VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL); + + SHA256_CTX * const context = to_inner_hash_sha256_context(&mContext); + const int result = SHA256_Final(Uint8::to_uchar(out_buffer.data()), context); VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL); + out_buffer = out_buffer.SubSpan(0, kSHA256_Hash_Length); return CHIP_NO_ERROR; } void Hash_SHA256_stream::Clear() { - memset(this, 0, sizeof(*this)); + OPENSSL_cleanse(this, sizeof(*this)); } CHIP_ERROR HKDF_sha::HKDF_SHA256(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, const size_t salt_length, diff --git a/src/crypto/CHIPCryptoPALmbedTLS.cpp b/src/crypto/CHIPCryptoPALmbedTLS.cpp index 538ea58ad9ec08..3facd29aa57f48 100644 --- a/src/crypto/CHIPCryptoPALmbedTLS.cpp +++ b/src/crypto/CHIPCryptoPALmbedTLS.cpp @@ -204,7 +204,13 @@ CHIP_ERROR Hash_SHA1(const uint8_t * data, const size_t data_length, uint8_t * o Hash_SHA256_stream::Hash_SHA256_stream(void) {} -Hash_SHA256_stream::~Hash_SHA256_stream(void) {} +Hash_SHA256_stream::~Hash_SHA256_stream(void) +{ + Clear(); +} + +static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(mbedtls_sha256_context), + "kMAX_Hash_SHA256_Context_Size is too small for the size of underlying mbedtls_sha256_context"); static inline mbedtls_sha256_context * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context) { @@ -221,29 +227,47 @@ CHIP_ERROR Hash_SHA256_stream::Begin(void) return CHIP_NO_ERROR; } -CHIP_ERROR Hash_SHA256_stream::AddData(const uint8_t * data, const size_t data_length) +CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data) { mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); - const int result = mbedtls_sha256_update_ret(context, Uint8::to_const_uchar(data), data_length); + const int result = mbedtls_sha256_update_ret(context, Uint8::to_const_uchar(data.data()), data.size()); VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); return CHIP_NO_ERROR; } -CHIP_ERROR Hash_SHA256_stream::Finish(uint8_t * out_buffer) +CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer) +{ + mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); + + // Back-up context as we are about to finalize the hash to extract digest. + mbedtls_sha256_context previous_ctx = *context; + + // Pad + compute digest, then finalize context. It is restored next line to continue. + CHIP_ERROR result = Finish(out_buffer); + + // Restore context prior to finalization. + *context = previous_ctx; + + return result; +} + +CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer) { + VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL); mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); - const int result = mbedtls_sha256_finish_ret(context, Uint8::to_uchar(out_buffer)); + const int result = mbedtls_sha256_finish_ret(context, Uint8::to_uchar(out_buffer.data())); VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + out_buffer = out_buffer.SubSpan(0, kSHA256_Hash_Length); return CHIP_NO_ERROR; } void Hash_SHA256_stream::Clear(void) { - memset(this, 0, sizeof(*this)); + mbedtls_platform_zeroize(this, sizeof(*this)); } CHIP_ERROR HKDF_sha::HKDF_SHA256(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, const size_t salt_length, diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp index 21fcf6e89ade41..87c736d88ce78a 100644 --- a/src/crypto/tests/CHIPCryptoPALTest.cpp +++ b/src/crypto/tests/CHIPCryptoPALTest.cpp @@ -766,23 +766,108 @@ static void TestHash_SHA256_Stream(nlTestSuite * inSuite, void * inContext) { size_t rand_data_length = static_cast(rand()) % (data_length + 1); - error = sha256.AddData(data, rand_data_length); + error = sha256.AddData(ByteSpan{ data, rand_data_length }); NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR); data += rand_data_length; data_length -= rand_data_length; } - error = sha256.AddData(data, data_length); + error = sha256.AddData(ByteSpan{ data, data_length }); NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR); - error = sha256.Finish(out_buffer); + MutableByteSpan out_span(out_buffer); + error = sha256.Finish(out_span); NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, out_span.size() == kSHA256_Hash_Length); - bool success = memcmp(v.hash, out_buffer, sizeof(out_buffer)) == 0; + bool success = memcmp(v.hash, out_span.data(), out_span.size()) == 0; NL_TEST_ASSERT(inSuite, success); } + NL_TEST_ASSERT(inSuite, numOfTestsExecuted == ArraySize(hash_sha256_test_vectors)); + + // Test partial digests + uint8_t source_buf[2 * kSHA256_Hash_Length]; + + // Use a basic counter for all data + for (size_t idx = 0; idx < sizeof(source_buf); idx++) + { + source_buf[idx] = static_cast(idx & 0xFFu); + } + + // Use split blocks of every length including digest length, to cover + // all padding cases. + for (size_t block1_size = 1; block1_size <= kSHA256_Hash_Length; block1_size++) + { + for (size_t block2_size = 1; block2_size <= kSHA256_Hash_Length; block2_size++) + { + uint8_t partial_digest1[kSHA256_Hash_Length]; + uint8_t partial_digest2[kSHA256_Hash_Length]; + uint8_t partial_digest_ref[kSHA256_Hash_Length]; + uint8_t total_digest[kSHA256_Hash_Length]; + uint8_t total_digest_ref[kSHA256_Hash_Length]; + MutableByteSpan partial_digest_span1(partial_digest1); + MutableByteSpan partial_digest_span2(partial_digest2); + MutableByteSpan total_digest_span(total_digest); + + Hash_SHA256_stream sha256; + NL_TEST_ASSERT(inSuite, sha256.Begin() == CHIP_NO_ERROR); + + // Compute partial digest after first block + NL_TEST_ASSERT(inSuite, sha256.AddData(ByteSpan{ &source_buf[0], block1_size }) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, sha256.GetDigest(partial_digest_span1) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, partial_digest_span1.size() == kSHA256_Hash_Length); + + // Validate partial digest matches expectations + Hash_SHA256(&source_buf[0], block1_size, &partial_digest_ref[0]); + NL_TEST_ASSERT(inSuite, 0 == memcmp(partial_digest_span1.data(), partial_digest_ref, partial_digest_span1.size())); + + // Compute partial digest and total digest after second block + NL_TEST_ASSERT(inSuite, sha256.AddData(ByteSpan{ &source_buf[block1_size], block2_size }) == CHIP_NO_ERROR); + + NL_TEST_ASSERT(inSuite, sha256.GetDigest(partial_digest_span2) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, partial_digest_span2.size() == kSHA256_Hash_Length); + + NL_TEST_ASSERT(inSuite, sha256.Finish(total_digest_span) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, total_digest_span.size() == kSHA256_Hash_Length); + + // Validate second partial digest matches final digest + Hash_SHA256(&source_buf[0], block1_size + block2_size, &total_digest_ref[0]); + NL_TEST_ASSERT(inSuite, 0 == memcmp(partial_digest_span2.data(), total_digest_ref, partial_digest_span2.size())); + NL_TEST_ASSERT(inSuite, 0 == memcmp(total_digest_span.data(), total_digest_ref, total_digest_span.size())); + } + } + + // Validate error cases + { + uint8_t source_buf2[5] = { 1, 2, 3, 4, 5 }; + uint8_t digest_buf_too_small[kSHA256_Hash_Length - 1]; + uint8_t digest_buf_ok[kSHA256_Hash_Length]; + uint8_t digest_buf_ref[kSHA256_Hash_Length]; + MutableByteSpan digest_span_too_small(digest_buf_too_small); + MutableByteSpan digest_span_ok(digest_buf_ok); + + Hash_SHA256(&source_buf2[0], sizeof(source_buf2), &digest_buf_ref[0]); + + Hash_SHA256_stream sha256; + NL_TEST_ASSERT(inSuite, sha256.Begin() == CHIP_NO_ERROR); + + NL_TEST_ASSERT(inSuite, sha256.AddData(ByteSpan{ source_buf2 }) == CHIP_NO_ERROR); + + // Check that error behavior works on buffer too small + NL_TEST_ASSERT(inSuite, sha256.GetDigest(digest_span_too_small) == CHIP_ERROR_BUFFER_TOO_SMALL); + NL_TEST_ASSERT(inSuite, sha256.Finish(digest_span_too_small) == CHIP_ERROR_BUFFER_TOO_SMALL); + + // Check that both GetDigest/Finish can still work after error. + NL_TEST_ASSERT(inSuite, sha256.GetDigest(digest_span_ok) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, 0 == memcmp(digest_span_ok.data(), digest_buf_ref, digest_span_ok.size())); + + memset(digest_buf_ok, 0, sizeof(digest_buf_ok)); + + NL_TEST_ASSERT(inSuite, sha256.Finish(digest_span_ok) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, 0 == memcmp(digest_span_ok.data(), digest_buf_ref, digest_span_ok.size())); + } } static void TestHMAC_SHA256(nlTestSuite * inSuite, void * inContext) diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index fc58c0ae188fc9..8f8da8f985dbf4 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -386,7 +386,7 @@ CHIP_ERROR CASESession::SendSigmaR1() ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriter.Finalize(&msg_R1)); - ReturnErrorOnFailure(mCommissioningHash.AddData(msg_R1->Start(), msg_R1->DataLength())); + ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msg_R1->Start(), msg_R1->DataLength() })); ReturnErrorOnFailure(ComputeIPK(mConnectionState.GetLocalKeyID(), mIPK, sizeof(mIPK))); @@ -421,7 +421,7 @@ CHIP_ERROR CASESession::HandleSigmaR1(System::PacketBufferHandle & msg) ChipLogDetail(SecureChannel, "Received SigmaR1 msg"); - err = mCommissioningHash.AddData(msg->Start(), msg->DataLength()); + err = mCommissioningHash.AddData(ByteSpan{ msg->Start(), msg->DataLength() }); SuccessOrExit(err); tlvReader.Init(std::move(msg)); @@ -610,7 +610,7 @@ CHIP_ERROR CASESession::SendSigmaR2() SuccessOrExit(err = tlvWriter.Finalize(&msg_R2)); } - err = mCommissioningHash.AddData(msg_R2->Start(), msg_R2->DataLength()); + err = mCommissioningHash.AddData(ByteSpan{ msg_R2->Start(), msg_R2->DataLength() }); SuccessOrExit(err); mNextExpectedMsg = Protocols::SecureChannel::MsgType::CASE_SigmaR3; @@ -729,7 +729,7 @@ CHIP_ERROR CASESession::HandleSigmaR2(System::PacketBufferHandle & msg) kAEADKeySize); SuccessOrExit(err); - err = mCommissioningHash.AddData(buf, buflen); + err = mCommissioningHash.AddData(ByteSpan{ buf, buflen }); SuccessOrExit(err); // Step 4 @@ -812,6 +812,7 @@ CHIP_ERROR CASESession::SendSigmaR3() { CHIP_ERROR err = CHIP_NO_ERROR; + MutableByteSpan messageDigestSpan(mMessageDigest); System::PacketBufferHandle msg_R3; uint16_t data_len; @@ -925,7 +926,7 @@ CHIP_ERROR CASESession::SendSigmaR3() SuccessOrExit(err); } - err = mCommissioningHash.AddData(msg_R3->Start(), msg_R3->DataLength()); + err = mCommissioningHash.AddData(ByteSpan{ msg_R3->Start(), msg_R3->DataLength() }); SuccessOrExit(err); // Call delegate to send the Msg3 to peer @@ -934,7 +935,7 @@ CHIP_ERROR CASESession::SendSigmaR3() ChipLogDetail(SecureChannel, "Sent SigmaR3 msg"); - err = mCommissioningHash.Finish(mMessageDigest); + err = mCommissioningHash.Finish(messageDigestSpan); SuccessOrExit(err); mPairingComplete = true; @@ -957,6 +958,7 @@ CHIP_ERROR CASESession::SendSigmaR3() CHIP_ERROR CASESession::HandleSigmaR3(System::PacketBufferHandle & msg) { CHIP_ERROR err = CHIP_NO_ERROR; + MutableByteSpan messageDigestSpan(mMessageDigest); System::PacketBufferTLVReader tlvReader; System::PacketBufferTLVReader suppTlvReader; TLV::TLVReader decryptedDataTlvReader; @@ -1030,7 +1032,7 @@ CHIP_ERROR CASESession::HandleSigmaR3(System::PacketBufferHandle & msg) kAEADKeySize); SuccessOrExit(err); - err = mCommissioningHash.AddData(buf, bufLen); + err = mCommissioningHash.AddData(ByteSpan{ buf, bufLen }); SuccessOrExit(err); // Step 2 @@ -1078,7 +1080,7 @@ CHIP_ERROR CASESession::HandleSigmaR3(System::PacketBufferHandle & msg) err = remoteCredential.ECDSA_validate_msg_signature(msg_R3_Signed.Get(), msg_r3_signed_len, sigmaR3SignedData); SuccessOrExit(err); - err = mCommissioningHash.Finish(mMessageDigest); + err = mCommissioningHash.Finish(messageDigestSpan); SuccessOrExit(err); mPairingComplete = true; @@ -1165,8 +1167,9 @@ CHIP_ERROR CASESession::ConstructSaltSigmaR2(const ByteSpan & rand, const P256Pu bbuf.Put(ipk, ipkLen); bbuf.Put(rand.data(), kSigmaParamRandomNumberSize); bbuf.Put(pubkey, pubkey.Length()); - ReturnErrorOnFailure(mCommissioningHash.Finish(md)); - bbuf.Put(md, kSHA256_Hash_Length); + MutableByteSpan messageDigestSpan(md); + ReturnErrorOnFailure(mCommissioningHash.Finish(messageDigestSpan)); + bbuf.Put(messageDigestSpan.data(), messageDigestSpan.size()); ReturnErrorOnFailure(mCommissioningHash.Begin()); VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_NO_MEMORY); @@ -1181,8 +1184,9 @@ CHIP_ERROR CASESession::ConstructSaltSigmaR3(const uint8_t * ipk, size_t ipkLen, Encoding::LittleEndian::BufferWriter bbuf(salt.data(), salt.size()); bbuf.Put(ipk, ipkLen); - ReturnErrorOnFailure(mCommissioningHash.Finish(md)); - bbuf.Put(md, kSHA256_Hash_Length); + MutableByteSpan messageDigestSpan(md); + ReturnErrorOnFailure(mCommissioningHash.Finish(messageDigestSpan)); + bbuf.Put(messageDigestSpan.data(), messageDigestSpan.size()); ReturnErrorOnFailure(mCommissioningHash.Begin()); VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_NO_MEMORY); diff --git a/src/protocols/secure_channel/PASESession.cpp b/src/protocols/secure_channel/PASESession.cpp index 81033c7934dcdd..fc8dbf2cee994e 100644 --- a/src/protocols/secure_channel/PASESession.cpp +++ b/src/protocols/secure_channel/PASESession.cpp @@ -186,7 +186,7 @@ CHIP_ERROR PASESession::Init(uint16_t myKeyId, uint32_t setupCode, SessionEstabl Clear(); ReturnErrorOnFailure(mCommissioningHash.Begin()); - ReturnErrorOnFailure(mCommissioningHash.AddData(Uint8::from_const_char(kSpake2pContext), strlen(kSpake2pContext))); + ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ Uint8::from_const_char(kSpake2pContext), strlen(kSpake2pContext) })); mDelegate = delegate; @@ -230,7 +230,7 @@ CHIP_ERROR PASESession::GeneratePASEVerifier(PASEVerifier & verifier, bool useRa CHIP_ERROR PASESession::SetupSpake2p(uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen) { - uint8_t context[32] = { + uint8_t context[kSHA256_Hash_Length] = { 0, }; @@ -242,8 +242,10 @@ CHIP_ERROR PASESession::SetupSpake2p(uint32_t pbkdf2IterCount, const uint8_t * s ReturnErrorOnFailure(PASESession::ComputePASEVerifier(mSetupPINCode, pbkdf2IterCount, salt, saltLen, mPASEVerifier)); } - ReturnErrorOnFailure(mCommissioningHash.Finish(context)); - ReturnErrorOnFailure(mSpake2p.Init(context, sizeof(context))); + MutableByteSpan contextSpan{ context, sizeof(context) }; + + ReturnErrorOnFailure(mCommissioningHash.Finish(contextSpan)); + ReturnErrorOnFailure(mSpake2p.Init(contextSpan.data(), contextSpan.size())); return CHIP_NO_ERROR; } @@ -356,7 +358,7 @@ CHIP_ERROR PASESession::SendPBKDFParamRequest() req->SetDataLength(kPBKDFParamRandomNumberSize); // Update commissioning hash with the pbkdf2 param request that's being sent. - ReturnErrorOnFailure(mCommissioningHash.AddData(req->Start(), req->DataLength())); + ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ req->Start(), req->DataLength() })); mNextExpectedMsg = Protocols::SecureChannel::MsgType::PBKDFParamResponse; @@ -382,7 +384,7 @@ CHIP_ERROR PASESession::HandlePBKDFParamRequest(const System::PacketBufferHandle ChipLogDetail(SecureChannel, "Received PBKDF param request"); // Update commissioning hash with the received pbkdf2 param request - err = mCommissioningHash.AddData(req, reqlen); + err = mCommissioningHash.AddData(ByteSpan{ req, reqlen }); SuccessOrExit(err); err = SendPBKDFParamResponse(); @@ -427,7 +429,7 @@ CHIP_ERROR PASESession::SendPBKDFParamResponse() resp->SetDataLength(static_cast(resplen)); // Update commissioning hash with the pbkdf2 param response that's being sent. - ReturnErrorOnFailure(mCommissioningHash.AddData(resp->Start(), resp->DataLength())); + ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ resp->Start(), resp->DataLength() })); ReturnErrorOnFailure(SetupSpake2p(mIterationCount, mSalt, mSaltLength)); ReturnErrorOnFailure(mSpake2p.ComputeL(mPoint, &sizeof_point, &mPASEVerifier[1][0], kSpake2p_WS_Length)); @@ -471,7 +473,7 @@ CHIP_ERROR PASESession::HandlePBKDFParamResponse(const System::PacketBufferHandl VerifyOrExit(CanCastTo(iterCount), err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); // Update commissioning hash with the received pbkdf2 param response - err = mCommissioningHash.AddData(resp, resplen); + err = mCommissioningHash.AddData(ByteSpan{ resp, resplen }); SuccessOrExit(err); err = SetupSpake2p(static_cast(iterCount), msgptr, saltlen); diff --git a/src/setup_payload/AdditionalDataPayloadGenerator.cpp b/src/setup_payload/AdditionalDataPayloadGenerator.cpp index 7441fc9aec257f..d72e7d9bf6e604 100644 --- a/src/setup_payload/AdditionalDataPayloadGenerator.cpp +++ b/src/setup_payload/AdditionalDataPayloadGenerator.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include using namespace chip; @@ -41,6 +42,8 @@ using namespace chip::Crypto; using namespace chip::SetupPayloadData; using namespace chip::Encoding::LittleEndian; +using chip::Encoding::BytesToUppercaseHexString; + CHIP_ERROR AdditionalDataPayloadGenerator::generateAdditionalDataPayload(uint16_t lifetimeCounter, const char * serialNumberBuffer, size_t serialNumberBufferSize, PacketBufferHandle & bufferHandle, @@ -80,8 +83,7 @@ CHIP_ERROR AdditionalDataPayloadGenerator::generateRotatingDeviceId(uint16_t lif { uint8_t outputBuffer[RotatingDeviceId::kMaxLength]; uint8_t hashOutputBuffer[kSHA256_Hash_Length]; - BufferWriter outputBufferWriter(outputBuffer, ArraySize(outputBuffer)); - size_t rotatingDeviceIdBufferIndex = 0; + BufferWriter outputBufferWriter(outputBuffer, sizeof(outputBuffer)); uint8_t lifetimeCounterBuffer[2]; Put16(lifetimeCounterBuffer, lifetimeCounter); @@ -92,24 +94,19 @@ CHIP_ERROR AdditionalDataPayloadGenerator::generateRotatingDeviceId(uint16_t lif // RDI = Lifetime_Counter + SuffixBytes(SHA256(Serial_Number + Lifetime_Counter), 16) Hash_SHA256_stream hash; + MutableByteSpan hashOutputSpan(hashOutputBuffer); ReturnErrorOnFailure(hash.Begin()); - ReturnErrorOnFailure(hash.AddData(Uint8::from_const_char(serialNumberBuffer), serialNumberBufferSize)); - ReturnErrorOnFailure(hash.AddData(lifetimeCounterBuffer, sizeof(lifetimeCounter))); - ReturnErrorOnFailure(hash.Finish(hashOutputBuffer)); + ReturnErrorOnFailure(hash.AddData(ByteSpan{ Uint8::from_const_char(serialNumberBuffer), serialNumberBufferSize })); + ReturnErrorOnFailure(hash.AddData(ByteSpan{ lifetimeCounterBuffer, sizeof(lifetimeCounter) })); + ReturnErrorOnFailure(hash.Finish(hashOutputSpan)); outputBufferWriter.Put16(lifetimeCounter); outputBufferWriter.Put(&hashOutputBuffer[kSHA256_Hash_Length - RotatingDeviceId::kHashSuffixLength], RotatingDeviceId::kHashSuffixLength); - for (rotatingDeviceIdBufferIndex = 0; rotatingDeviceIdBufferIndex < outputBufferWriter.Needed(); rotatingDeviceIdBufferIndex++) - { - snprintf(&rotatingDeviceIdBuffer[rotatingDeviceIdBufferIndex * 2], - rotatingDeviceIdBufferSize - rotatingDeviceIdBufferIndex * 2, "%02X", - outputBufferWriter.Buffer()[rotatingDeviceIdBufferIndex]); - } - - rotatingDeviceIdBuffer[rotatingDeviceIdBufferIndex * 2] = 0; - rotatingDeviceIdValueOutputSize = rotatingDeviceIdBufferIndex * 2; + ReturnErrorOnFailure( + BytesToUppercaseHexString(outputBuffer, outputBufferWriter.Needed(), rotatingDeviceIdBuffer, rotatingDeviceIdBufferSize)); + rotatingDeviceIdValueOutputSize = outputBufferWriter.Needed() * 2; ChipLogDetail(DeviceLayer, "rotatingDeviceId: %s", rotatingDeviceIdBuffer); return CHIP_NO_ERROR;