From 3682006f2c61e519258a931bfb6498b305e8c69b Mon Sep 17 00:00:00 2001 From: Martin Turon Date: Thu, 7 Jul 2022 05:52:51 -0700 Subject: [PATCH] [privacy] Add KDF for PrivacyKey with test (#20405) * [privacy] Add PrivacyKey KDF. * [privacy] Add test for DeriveGroupPrivacyKey. --- src/crypto/CHIPCryptoPAL.cpp | 25 ++++++++++++++++++ src/crypto/CHIPCryptoPAL.h | 9 +++++++ src/crypto/tests/CHIPCryptoPALTest.cpp | 36 ++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/src/crypto/CHIPCryptoPAL.cpp b/src/crypto/CHIPCryptoPAL.cpp index f70a4ae5b86d93..eb0bb489f11797 100644 --- a/src/crypto/CHIPCryptoPAL.cpp +++ b/src/crypto/CHIPCryptoPAL.cpp @@ -805,6 +805,31 @@ CHIP_ERROR DeriveGroupSessionId(const ByteSpan & operational_key, uint16_t & ses return CHIP_NO_ERROR; } +/* Operational Group Key Group, PrivacyKey Info: "PrivacyKey" */ +static const uint8_t kGroupPrivacyInfo[] = { 'P', 'r', 'i', 'v', 'a', 'c', 'y', 'K', 'e', 'y' }; + +/* + PrivacyKey = + Crypto_KDF + ( + InputKey = EncryptionKey, + Salt = [], + Info = "PrivacyKey", + Length = CRYPTO_SYMMETRIC_KEY_LENGTH_BITS + ) +*/ +CHIP_ERROR DeriveGroupPrivacyKey(const ByteSpan & encryption_key, MutableByteSpan & out_key) +{ + VerifyOrReturnError(Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES == encryption_key.size(), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES <= out_key.size(), CHIP_ERROR_INVALID_ARGUMENT); + + const ByteSpan null_span = ByteSpan(nullptr, 0); + + Crypto::HKDF_sha crypto; + return crypto.HKDF_SHA256(encryption_key.data(), encryption_key.size(), null_span.data(), null_span.size(), kGroupPrivacyInfo, + sizeof(kGroupPrivacyInfo), out_key.data(), Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES); +} + CHIP_ERROR ExtractVIDPIDFromAttributeString(DNAttrType attrType, const ByteSpan & attr, AttestationCertVidPid & vidpidFromMatterAttr, AttestationCertVidPid & vidpidFromCNAttr) { diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h index 077b668de55532..48646af8560313 100644 --- a/src/crypto/CHIPCryptoPAL.h +++ b/src/crypto/CHIPCryptoPAL.h @@ -1577,5 +1577,14 @@ CHIP_ERROR DeriveGroupOperationalKey(const ByteSpan & epoch_key, const ByteSpan **/ CHIP_ERROR DeriveGroupSessionId(const ByteSpan & operational_key, uint16_t & session_id); +/** + * @brief Derives the Privacy Group Key using the Key Derivation Function (KDF) from the given epoch key. + * @param[in] epoch_key The epoch key. Must be CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length. + * @param[out] out_key Symmetric key used as the privacy key during message processing for group communication. + The buffer size must be at least CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length. + * @return Returns a CHIP_NO_ERROR on succcess, or CHIP_ERROR_INTERNAL if the provided key is invalid. + **/ +CHIP_ERROR DeriveGroupPrivacyKey(const ByteSpan & epoch_key, MutableByteSpan & out_key); + } // namespace Crypto } // namespace chip diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp index aef0d3d77c4d7f..bb2cb9870ae436 100644 --- a/src/crypto/tests/CHIPCryptoPALTest.cpp +++ b/src/crypto/tests/CHIPCryptoPALTest.cpp @@ -2260,6 +2260,16 @@ const uint8_t kGroupOperationalKey3[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYT const uint16_t kGroupSessionId1 = 0x6c80; const uint16_t kGroupSessionId2 = 0x0c48; +static const uint8_t kGroupPrivacyKey1[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0xb8, 0x27, 0x9f, 0x89, 0x62, 0x1e, + 0xd3, 0x27, 0xa9, 0xc3, 0x9f, 0x6a, + 0x27, 0x24, 0x73, 0x58 }; +static const uint8_t kGroupPrivacyKey2[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0xf7, 0x25, 0x70, 0xc3, 0xc0, 0x89, + 0xa0, 0xfe, 0x28, 0x75, 0x83, 0x57, + 0xaf, 0xff, 0xb8, 0xd2 }; +static const uint8_t kGroupPrivacyKey3[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0x01, 0xf8, 0xd1, 0x92, 0x71, 0x26, + 0xf1, 0x94, 0x08, 0x25, 0x72, 0xd4, + 0x9b, 0x1f, 0xdc, 0x73 }; + static void TestGroup_OperationalKeyDerivation(nlTestSuite * inSuite, void * inContext) { uint8_t key_buffer[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0 }; @@ -2305,6 +2315,31 @@ static void TestGroup_SessionIdDerivation(nlTestSuite * inSuite, void * inContex NL_TEST_ASSERT(inSuite, kGroupSessionId2 == session_id); } +static void TestGroup_PrivacyKeyDerivation(nlTestSuite * inSuite, void * inContext) +{ + uint8_t key_buffer[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0 }; + ByteSpan encryption_key; + MutableByteSpan privacy_key(key_buffer, sizeof(key_buffer)); + + // Invalid Epoch Key + NL_TEST_ASSERT(inSuite, CHIP_ERROR_INVALID_ARGUMENT == DeriveGroupPrivacyKey(ByteSpan(), privacy_key)); + + // Epoch Key 1 + encryption_key = ByteSpan(kGroupOperationalKey1, sizeof(kGroupOperationalKey1)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == DeriveGroupPrivacyKey(encryption_key, privacy_key)); + NL_TEST_ASSERT(inSuite, 0 == memcmp(privacy_key.data(), kGroupPrivacyKey1, sizeof(kGroupPrivacyKey1))); + + // Epoch Key 2 + encryption_key = ByteSpan(kGroupOperationalKey2, sizeof(kGroupOperationalKey2)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == DeriveGroupPrivacyKey(encryption_key, privacy_key)); + NL_TEST_ASSERT(inSuite, 0 == memcmp(privacy_key.data(), kGroupPrivacyKey2, sizeof(kGroupPrivacyKey2))); + + // Epoch Key 3 (example from spec) + encryption_key = ByteSpan(kGroupOperationalKey3, sizeof(kGroupOperationalKey3)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == DeriveGroupPrivacyKey(encryption_key, privacy_key)); + NL_TEST_ASSERT(inSuite, 0 == memcmp(privacy_key.data(), kGroupPrivacyKey3, sizeof(kGroupPrivacyKey3))); +} + /** * Test Suite. It lists all the test functions. */ @@ -2370,6 +2405,7 @@ static const nlTest sTests[] = { NL_TEST_DEF("Test Vendor ID and Product ID Extraction from x509 Attestation Certificate", TestVIDPID_x509Extraction), NL_TEST_DEF("Test Group Operation Key Derivation", TestGroup_OperationalKeyDerivation), NL_TEST_DEF("Test Group Session ID Derivation", TestGroup_SessionIdDerivation), + NL_TEST_DEF("Test Group Privacy Key Derivation", TestGroup_PrivacyKeyDerivation), NL_TEST_SENTINEL() };