Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
maciejbaczmanski committed Aug 9, 2024
1 parent 450d9f0 commit a1ce106
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 54 deletions.
6 changes: 3 additions & 3 deletions src/app/chip_data_model.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ function(chip_configure_data_model APP_TARGET)
${CHIP_APP_BASE_DIR}/util/attribute-storage.cpp
${CHIP_APP_BASE_DIR}/util/attribute-table.cpp
${CHIP_APP_BASE_DIR}/util/binding-table.cpp
${CHIP_APP_BASE_DIR}/icd/server/ICDMonitoringTable.cpp
${CHIP_APP_BASE_DIR}/icd/server/ICDNotifier.cpp
${CHIP_APP_BASE_DIR}/icd/server/ICDConfigurationData.cpp
# ${CHIP_APP_BASE_DIR}/icd/server/ICDMonitoringTable.cpp
# ${CHIP_APP_BASE_DIR}/icd/server/ICDNotifier.cpp
# ${CHIP_APP_BASE_DIR}/icd/server/ICDConfigurationData.cpp
${CHIP_APP_BASE_DIR}/util/DataModelHandler.cpp
${CHIP_APP_BASE_DIR}/util/ember-compatibility-functions.cpp
${CHIP_APP_BASE_DIR}/util/ember-global-attribute-access-interface.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ Status ICDManagementServer::RegisterClient(CommandHandler * commandObj, const Co
entry.DeleteKey();
}

err = entry.SetKey(key);
err = entry.SetKey(key, true);
VerifyOrReturnError(CHIP_ERROR_INVALID_ARGUMENT != err, Status::ConstraintError);
VerifyOrReturnError(CHIP_NO_ERROR == err, Status::Failure);
err = table.Set(entry.index, entry);
Expand Down
35 changes: 29 additions & 6 deletions src/app/icd/server/ICDMonitoringTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@

#include <crypto/RandUtils.h>

#ifdef CONFIG_CHIP_CRYPTO_PSA
#include <crypto/CHIPCryptoPALPSA.h>
#endif

namespace chip {

enum class Fields : uint8_t
Expand Down Expand Up @@ -131,7 +135,7 @@ void ICDMonitoringEntry::Clear()
this->clientType = app::Clusters::IcdManagement::ClientTypeEnum::kPermanent;
}

CHIP_ERROR ICDMonitoringEntry::SetKey(ByteSpan keyData)
CHIP_ERROR ICDMonitoringEntry::SetKey(ByteSpan keyData, bool persistent)
{
VerifyOrReturnError(keyData.size() == sizeof(Crypto::Symmetric128BitsKeyByteArray), CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(symmetricKeystore != nullptr, CHIP_ERROR_INTERNAL);
Expand All @@ -140,7 +144,20 @@ CHIP_ERROR ICDMonitoringEntry::SetKey(ByteSpan keyData)
Crypto::Symmetric128BitsKeyByteArray keyMaterial;
memcpy(keyMaterial, keyData.data(), sizeof(Crypto::Symmetric128BitsKeyByteArray));

// TODO - Add function to set PSA key lifetime
#ifdef CONFIG_CHIP_CRYPTO_PSA
if (persistent)
{
ReturnErrorOnFailure(Crypto::FindFreeKeySlotInRange(aesKeyHandle.AsMutable<psa_key_id_t>(),
to_underlying(Crypto::KeyIdBase::ICDAesKeyRangeStart),
Crypto::kMaxICDClientKeys));
ReturnErrorOnFailure(Crypto::FindFreeKeySlotInRange(hmacKeyHandle.AsMutable<psa_key_id_t>(),
to_underlying(Crypto::KeyIdBase::ICDHmacKeyRangeStart),
Crypto::kMaxICDClientKeys));
}
#else
IgnoreUnusedVariable(persistent);
#endif // CONFIG_CHIP_CRYPTO_PSA

ReturnErrorOnFailure(symmetricKeystore->CreateKey(keyMaterial, aesKeyHandle));
CHIP_ERROR error = symmetricKeystore->CreateKey(keyMaterial, hmacKeyHandle);

Expand Down Expand Up @@ -242,15 +259,21 @@ CHIP_ERROR ICDMonitoringTable::Get(uint16_t index, ICDMonitoringEntry & entry) c

CHIP_ERROR ICDMonitoringTable::Find(NodeId id, ICDMonitoringEntry & entry)
{
uint16_t index = 0;
while (index < this->Limit())
CHIP_ERROR err;
uint16_t index;
ICDMonitoringEntry tempEntry(mSymmetricKeystore);

for (index = 0; index < this->Limit(); index++)
{
ReturnErrorOnFailure(this->Get(index++, entry));
if (id == entry.checkInNodeID)
SuccessOrExit(err = this->Get(index, tempEntry));
if (id == tempEntry.checkInNodeID)
{
entry = tempEntry;
return CHIP_NO_ERROR;
}
}

exit:
entry.index = index;
return CHIP_ERROR_NOT_FOUND;
}
Expand Down
5 changes: 3 additions & 2 deletions src/app/icd/server/ICDMonitoringTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,14 @@ struct ICDMonitoringEntry : public PersistentData<kICDMonitoringBufferSize>
* A new entry object should be used for each key when adding entries to the ICDMonitoring
* table.
*
* @param keyData A byte span containing the raw key
* @param keyData A byte span containing the raw key
* @param persistent Persistence of the key to be set (optional, needed only when setting persistent key with PSA Crypto API)
* @return CHIP_ERROR CHIP_NO_ERROR success
* CHIP_ERROR_INVALID_ARGUMENT wrong size of the raw key
* CHIP_ERROR_INTERNAL No KeyStore for the entry or Key Handle already present
* CHIP_ERROR_XXX Crypto API related failure
*/
CHIP_ERROR SetKey(ByteSpan keyData);
CHIP_ERROR SetKey(ByteSpan keyData, bool persistent = false);
CHIP_ERROR DeleteKey(void);
inline bool IsValid()
{
Expand Down
1 change: 1 addition & 0 deletions src/crypto/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ source_set("public_headers") {
"${chip_root}/src/lib/core",
"${chip_root}/src/lib/core:types",
"${chip_root}/src/lib/support",
"${chip_root}/src/app/icd/server:icd-server-config",
"${nlassert_root}:nlassert",
]
}
Expand Down
22 changes: 22 additions & 0 deletions src/crypto/CHIPCryptoPALPSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,28 @@ void Hash_SHA256_stream::Clear()
psa_hash_abort(toHashOperation(&mContext));
}

CHIP_ERROR FindFreeKeySlotInRange(psa_key_id_t & keyId, psa_key_id_t start, uint32_t range)
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t end = start + range;

VerifyOrReturnError(start >= PSA_KEY_ID_USER_MIN && end - 1 <= PSA_KEY_ID_USER_MAX, CHIP_ERROR_INVALID_ARGUMENT);

for(keyId = start; keyId < end; keyId++)
{
psa_status_t status = psa_get_key_attributes(keyId, &attributes);
if (status == PSA_ERROR_INVALID_HANDLE)
{
return CHIP_NO_ERROR;
}
else if (status != PSA_SUCCESS)
{
return CHIP_ERROR_INTERNAL;
}
}
return CHIP_ERROR_NOT_FOUND;
}

CHIP_ERROR PsaKdf::Init(const ByteSpan & secret, const ByteSpan & salt, const ByteSpan & info)
{
psa_status_t status = PSA_SUCCESS;
Expand Down
35 changes: 32 additions & 3 deletions src/crypto/CHIPCryptoPALPSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#pragma once

#include "CHIPCryptoPAL.h"
#include <app/icd/server/ICDServerConfig.h>
#include <lib/core/DataModelTypes.h>
#include <lib/support/SafePointerCast.h>

Expand Down Expand Up @@ -55,19 +56,47 @@ namespace Crypto {
#define CHIP_CONFIG_CRYPTO_PSA_KEY_ID_BASE 0x30000
#endif // CHIP_CONFIG_CRYPTO_PSA_KEY_ID_BASE

#if CHIP_CONFIG_ENABLE_ICD_CIP
static constexpr uint32_t kMaxICDClientKeys = CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC * CHIP_CONFIG_MAX_FABRICS;
#endif // CHIP_CONFIG_ENABLE_ICD_CIP

/**
* @brief Defines subranges of the PSA key identifier space used by Matter.
*/
enum class KeyIdBase : psa_key_id_t
{
Minimum = CHIP_CONFIG_CRYPTO_PSA_KEY_ID_BASE,
Operational = Minimum, ///< Base of the PSA key ID range for Node Operational Certificate private keys
Maximum = Operational + kMaxValidFabricIndex,
Minimum = CHIP_CONFIG_CRYPTO_PSA_KEY_ID_BASE,
Operational = Minimum, ///< Base of the PSA key ID range for Node Operational Certificate private keys
DACPrivKey = Operational + kMaxValidFabricIndex + 1,
#if CHIP_CONFIG_ENABLE_ICD_CIP
ICDHmacKeyRangeStart = DACPrivKey + 1,
ICDAesKeyRangeStart = ICDHmacKeyRangeStart + kMaxICDClientKeys,
ICDKeysRangeEnd = ICDAesKeyRangeStart + kMaxICDClientKeys,
#else
// If Check-In Protocol is disabled, set ICDKeysRangeEnd to previous key, to allow setting next key ID to `ICDKeysRangeEnd + 1`
ICDKeysRangeEnd = DACPrivKey,
#endif // CHIP_CONFIG_ENABLE_ICD_CIP
Maximum = ICDKeysRangeEnd,
};

static_assert(to_underlying(KeyIdBase::Minimum) >= PSA_KEY_ID_USER_MIN && to_underlying(KeyIdBase::Maximum) <= PSA_KEY_ID_USER_MAX,
"PSA key ID base out of allowed range");


/**
* @brief Finds first free persistent Key slot ID within range.
*
* @param[out] keyId Key ID handler to which free ID will be set.
* @param[in] start Starting ID in search range.
* @param[in] range Search range.
*
* @retval CHIP_NO_ERROR On success.
* @retval CHIP_ERROR_INTERNAL On PSA crypto API error.
* @retval CHIP_ERROR_NOT_FOUND On no free Key ID within range.
* @retval CHIP_ERROR_INVALID_ARGUMENT On search arguments out of PSA allowed range.
*/
CHIP_ERROR FindFreeKeySlotInRange(psa_key_id_t & keyId, psa_key_id_t start, uint32_t range);

/**
* @brief Calculates PSA key ID for Node Operational Certificate private key for the given fabric.
*/
Expand Down
81 changes: 42 additions & 39 deletions src/crypto/PSASessionKeystore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,62 +24,65 @@ namespace Crypto {

namespace {

class AesKeyAttributes
class keyAttributesBase
{
public:
AesKeyAttributes()
keyAttributesBase(psa_key_id_t keyId, psa_key_type_t type, psa_algorithm_t algorithm,
psa_key_usage_t usageFlags, size_t bits)
{
constexpr psa_algorithm_t kAlgorithm = PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8);

psa_set_key_type(&mAttrs, PSA_KEY_TYPE_AES);
psa_set_key_algorithm(&mAttrs, kAlgorithm);
psa_set_key_usage_flags(&mAttrs, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_bits(&mAttrs, CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES * 8);
psa_set_key_type(&mAttrs, type);
psa_set_key_algorithm(&mAttrs, algorithm);
psa_set_key_usage_flags(&mAttrs, usageFlags);
psa_set_key_bits(&mAttrs, bits);
if (to_underlying(KeyIdBase::Maximum) >= keyId && keyId >= to_underlying(KeyIdBase::Minimum))
{
psa_set_key_lifetime(&mAttrs, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_id(&mAttrs, keyId);
}
}

~AesKeyAttributes() { psa_reset_key_attributes(&mAttrs); }
~keyAttributesBase() { psa_reset_key_attributes(&mAttrs); }

const psa_key_attributes_t & Get() { return mAttrs; }

private:
psa_key_attributes_t mAttrs = PSA_KEY_ATTRIBUTES_INIT;
};

class HmacKeyAttributes
class AesKeyAttributes : public keyAttributesBase
{
public:
HmacKeyAttributes()
{
psa_set_key_type(&mAttrs, PSA_KEY_TYPE_HMAC);
psa_set_key_algorithm(&mAttrs, PSA_ALG_HMAC(PSA_ALG_SHA_256));
psa_set_key_usage_flags(&mAttrs, PSA_KEY_USAGE_SIGN_MESSAGE);
psa_set_key_bits(&mAttrs, CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES * 8);
}

~HmacKeyAttributes() { psa_reset_key_attributes(&mAttrs); }

const psa_key_attributes_t & Get() { return mAttrs; }

private:
psa_key_attributes_t mAttrs = PSA_KEY_ATTRIBUTES_INIT;
AesKeyAttributes(psa_key_id_t keyId = PSA_KEY_ID_NULL)
: keyAttributesBase(keyId,
PSA_KEY_TYPE_AES,
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8),
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES * 8)
{}
};

class HkdfKeyAttributes
class HmacKeyAttributes : public keyAttributesBase
{
public:
HkdfKeyAttributes()
{
psa_set_key_type(&mAttrs, PSA_KEY_TYPE_DERIVE);
psa_set_key_algorithm(&mAttrs, PSA_ALG_HKDF(PSA_ALG_SHA_256));
psa_set_key_usage_flags(&mAttrs, PSA_KEY_USAGE_DERIVE);
}

~HkdfKeyAttributes() { psa_reset_key_attributes(&mAttrs); }

const psa_key_attributes_t & Get() { return mAttrs; }
HmacKeyAttributes(psa_key_id_t keyId = PSA_KEY_ID_NULL)
: keyAttributesBase(keyId,
PSA_KEY_TYPE_HMAC,
PSA_ALG_HMAC(PSA_ALG_SHA_256),
PSA_KEY_USAGE_SIGN_MESSAGE,
CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES * 8)
{}
};

private:
psa_key_attributes_t mAttrs = PSA_KEY_ATTRIBUTES_INIT;
class HkdfKeyAttributes : public keyAttributesBase
{
public:
HkdfKeyAttributes(psa_key_id_t keyId = PSA_KEY_ID_NULL)
: keyAttributesBase(keyId,
PSA_KEY_TYPE_DERIVE,
PSA_ALG_HKDF(PSA_ALG_SHA_256),
PSA_KEY_USAGE_DERIVE,
0)
{}
};

} // namespace
Expand All @@ -89,7 +92,7 @@ CHIP_ERROR PSASessionKeystore::CreateKey(const Symmetric128BitsKeyByteArray & ke
// Destroy the old key if already allocated
psa_destroy_key(key.As<psa_key_id_t>());

AesKeyAttributes attrs;
AesKeyAttributes attrs(key.As<psa_key_id_t>());
psa_status_t status =
psa_import_key(&attrs.Get(), keyMaterial, sizeof(Symmetric128BitsKeyByteArray), &key.AsMutable<psa_key_id_t>());
LogPsaError(status);
Expand All @@ -103,7 +106,7 @@ CHIP_ERROR PSASessionKeystore::CreateKey(const Symmetric128BitsKeyByteArray & ke
// Destroy the old key if already allocated
psa_destroy_key(key.As<psa_key_id_t>());

HmacKeyAttributes attrs;
HmacKeyAttributes attrs(key.As<psa_key_id_t>());
psa_status_t status =
psa_import_key(&attrs.Get(), keyMaterial, sizeof(Symmetric128BitsKeyByteArray), &key.AsMutable<psa_key_id_t>());
LogPsaError(status);
Expand Down

0 comments on commit a1ce106

Please sign in to comment.