Skip to content

Commit

Permalink
[privacy] Add KDF for PrivacyKey with test (#20405)
Browse files Browse the repository at this point in the history
* [privacy] Add PrivacyKey KDF.

* [privacy] Add test for DeriveGroupPrivacyKey.
  • Loading branch information
turon authored and pull[bot] committed Jul 18, 2023
1 parent 4dacdaa commit 3682006
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/crypto/CHIPCryptoPAL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
9 changes: 9 additions & 0 deletions src/crypto/CHIPCryptoPAL.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
36 changes: 36 additions & 0 deletions src/crypto/tests/CHIPCryptoPALTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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()
};

Expand Down

0 comments on commit 3682006

Please sign in to comment.