[crypto-storage] add KeyRefManager to select KeyRef values (#11102)

This commit introduces `Crypto::Storage::KeyRefManager`, which manages
and selects the `KeyRef` values. `ot::Instance` now will have its own
`KeyRefManager`. Under `MULTIPLE_INSTANCE_ENABLE`, this allows
different `ot::Instance`s to use different `KeyRef` ranges by setting
an instance-specific offset. This offset is used when determining the
`KeyRef` numerical value for secure storage access.
This commit is contained in:
Abtin Keshavarzian
2025-01-07 15:39:07 -08:00
committed by GitHub
parent 3470934f74
commit f3dded43b6
9 changed files with 134 additions and 43 deletions
+11 -9
View File
@@ -39,6 +39,7 @@ namespace ot {
namespace Crypto {
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Error Key::ExtractKey(uint8_t *aKeyBuffer, uint16_t &aKeyLength) const
{
Error error = kErrorNone;
@@ -56,17 +57,18 @@ exit:
return error;
}
void Storage::DestroyPersistentKeys(void)
void Storage::KeyRefManager::DestroyPersistentKeys(void)
{
DestroyKey(kNetworkKeyRef);
DestroyKey(kPskcRef);
DestroyKey(kActiveDatasetNetworkKeyRef);
DestroyKey(kActiveDatasetPskcRef);
DestroyKey(kPendingDatasetNetworkKeyRef);
DestroyKey(kPendingDatasetPskcRef);
DestroyKey(kEcdsaRef);
DestroyKey(KeyRefFor(kNetworkKey));
DestroyKey(KeyRefFor(kPskc));
DestroyKey(KeyRefFor(kActiveDatasetNetworkKey));
DestroyKey(KeyRefFor(kActiveDatasetPskc));
DestroyKey(KeyRefFor(kPendingDatasetNetworkKey));
DestroyKey(KeyRefFor(kPendingDatasetPskc));
DestroyKey(KeyRefFor(kEcdsa));
}
#endif
#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
LiteralKey::LiteralKey(const Key &aKey)
: mKey(aKey.GetBytes())
+79 -13
View File
@@ -42,6 +42,7 @@
#include "common/clearable.hpp"
#include "common/code_utils.hpp"
#include "common/error.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
namespace ot {
@@ -94,14 +95,84 @@ enum StorageType : uint8_t
*/
typedef otCryptoKeyRef KeyRef;
constexpr KeyRef kInvalidKeyRef = 0x80000000; ///< Invalid `KeyRef` value (PSA_KEY_ID_VENDOR_MAX + 1).
constexpr KeyRef kNetworkKeyRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 1;
constexpr KeyRef kPskcRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 2;
constexpr KeyRef kActiveDatasetNetworkKeyRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 3;
constexpr KeyRef kActiveDatasetPskcRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 4;
constexpr KeyRef kPendingDatasetNetworkKeyRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 5;
constexpr KeyRef kPendingDatasetPskcRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 6;
constexpr KeyRef kEcdsaRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 7;
constexpr KeyRef kInvalidKeyRef = 0x80000000; ///< Invalid `KeyRef` value (PSA_KEY_ID_VENDOR_MAX + 1).
/**
* Manages and selects the `KeyRef` values.
*/
class KeyRefManager : public InstanceLocator
{
public:
/**
* Represents difference `KeyRef` types.
*/
enum Type : uint8_t
{
kNetworkKey = 1,
kPskc = 2,
kActiveDatasetNetworkKey = 3,
kActiveDatasetPskc = 4,
kPendingDatasetNetworkKey = 5,
kPendingDatasetPskc = 6,
kEcdsa = 7,
};
/**
* Initializes the `KeyRefManager`.
*
* @param[in] aInstance A reference to the OpenThread instance.
*/
explicit KeyRefManager(Instance &aInstance)
: InstanceLocator(aInstance)
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
, mExtraOffset(0)
#endif
{
}
/**
* Determines the `KeyRef` to use for a given `Type`.
*
* @param[in] aType The key ref type.
*
* @returns The `KeyRef` associated with @p aType.
*/
KeyRef KeyRefFor(Type aType)
{
KeyRef keyRef = kPsaItsNvmOffset + aType;
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
keyRef += mExtraOffset;
#endif
return keyRef;
}
/**
* Delete all the persistent keys.
*/
void DestroyPersistentKeys(void);
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
static constexpr uint32_t kKeyRefExtraOffset = 32; ///< Recommended extra offset to use.
/**
* Sets the additional `KeyRef` offset value to use when determining the `KeyRef`s.
*
* This is intended for when `MULTIPLE_INSTANCE_ENABLE` is enabled to ensure different `ot::Instance`s use
* different `KeyRef` value ranges.
*
* @param[in] aOffset The offset value.
*/
void SetKeyRefExtraOffset(uint32_t aOffset) { mExtraOffset = aOffset; }
#endif
private:
static constexpr KeyRef kPsaItsNvmOffset = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET;
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
uint32_t mExtraOffset;
#endif
};
/**
* Determine if a given `KeyRef` is valid or not.
@@ -181,11 +252,6 @@ inline void DestroyKey(KeyRef aKeyRef)
*/
inline bool HasKey(KeyRef aKeyRef) { return otPlatCryptoHasKey(aKeyRef); }
/**
* Delete all the persistent keys stored in PSA ITS.
*/
void DestroyPersistentKeys(void);
} // namespace Storage
#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+11
View File
@@ -75,6 +75,9 @@ Instance::Instance(void)
: mTimerMilliScheduler(*this)
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
, mTimerMicroScheduler(*this)
#endif
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
, mCryptoStorageKeyRefManager(*this)
#endif
, mRadio(*this)
#if OPENTHREAD_CONFIG_UPTIME_ENABLE
@@ -276,6 +279,14 @@ Instance::Instance(void)
, mIsInitialized(false)
, mId(Random::NonCrypto::GetUint32())
{
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
#if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
mCryptoStorageKeyRefManager.SetKeyRefExtraOffset(Crypto::Storage::KeyRefManager::kKeyRefExtraOffset * GetIdx(this));
#else
#error "MULTIPLE_INSTANCE (without static allocation) is used with PLATFORM_KEY_REFERENCES_ENABLE " \
"The `KeyRef` values will be shared across different `Instance` objects"
#endif
#endif
}
#if (OPENTHREAD_MTD || OPENTHREAD_FTD) && !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+9
View File
@@ -79,6 +79,7 @@
#include "common/notifier.hpp"
#include "common/settings.hpp"
#include "crypto/mbedtls.hpp"
#include "crypto/storage.hpp"
#include "mac/mac.hpp"
#include "mac/wakeup_tx_scheduler.hpp"
#include "meshcop/border_agent.hpp"
@@ -464,6 +465,10 @@ private:
Random::Manager mRandomManager;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Storage::KeyRefManager mCryptoStorageKeyRefManager;
#endif
// Radio is initialized before other member variables
// (particularly, SubMac and Mac) to allow them to use its methods
// from their constructor.
@@ -769,6 +774,10 @@ template <> inline SettingsDriver &Instance::Get(void) { return mSettingsDriver;
template <> inline MeshForwarder &Instance::Get(void) { return mMeshForwarder; }
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
template <> inline Crypto::Storage::KeyRefManager &Instance::Get(void) { return mCryptoStorageKeyRefManager; }
#endif
#if OPENTHREAD_CONFIG_MULTI_RADIO
template <> inline RadioSelector &Instance::Get(void) { return mRadioSelector; }
#endif
+11 -7
View File
@@ -755,13 +755,13 @@ void DatasetManager::TlvList::Add(uint8_t aTlvType)
const DatasetManager::SecurelyStoredTlv DatasetManager::kSecurelyStoredTlvs[] = {
{
Tlv::kNetworkKey,
Crypto::Storage::kActiveDatasetNetworkKeyRef,
Crypto::Storage::kPendingDatasetNetworkKeyRef,
KeyRefManager::kActiveDatasetNetworkKey,
KeyRefManager::kPendingDatasetNetworkKey,
},
{
Tlv::kPskc,
Crypto::Storage::kActiveDatasetPskcRef,
Crypto::Storage::kPendingDatasetPskcRef,
KeyRefManager::kActiveDatasetPskc,
KeyRefManager::kPendingDatasetPskc,
},
};
@@ -769,7 +769,7 @@ void DatasetManager::DestroySecurelyStoredKeys(void) const
{
for (const SecurelyStoredTlv &entry : kSecurelyStoredTlvs)
{
Crypto::Storage::DestroyKey(entry.GetKeyRef(mType));
Crypto::Storage::DestroyKey(Get<KeyRefManager>().KeyRefFor(entry.GetKeyRefType(mType)));
}
}
@@ -777,7 +777,9 @@ void DatasetManager::MoveKeysToSecureStorage(Dataset &aDataset) const
{
for (const SecurelyStoredTlv &entry : kSecurelyStoredTlvs)
{
SaveTlvInSecureStorageAndClearValue(aDataset, entry.mTlvType, entry.GetKeyRef(mType));
KeyRef keyRef = Get<KeyRefManager>().KeyRefFor(entry.GetKeyRefType(mType));
SaveTlvInSecureStorageAndClearValue(aDataset, entry.mTlvType, keyRef);
}
}
@@ -792,7 +794,9 @@ void DatasetManager::EmplaceSecurelyStoredKeys(Dataset &aDataset) const
for (const SecurelyStoredTlv &entry : kSecurelyStoredTlvs)
{
if (ReadTlvFromSecureStorage(aDataset, entry.mTlvType, entry.GetKeyRef(mType)) != kErrorNone)
KeyRef keyRef = Get<KeyRefManager>().KeyRefFor(entry.GetKeyRefType(mType));
if (ReadTlvFromSecureStorage(aDataset, entry.mTlvType, keyRef) != kErrorNone)
{
moveKeys = true;
}
+8 -6
View File
@@ -238,18 +238,20 @@ private:
};
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
using KeyRef = Crypto::Storage::KeyRef;
using KeyRef = Crypto::Storage::KeyRef;
using KeyRefManager = Crypto::Storage::KeyRefManager;
using KeyRefType = Crypto::Storage::KeyRefManager::Type;
struct SecurelyStoredTlv
{
KeyRef GetKeyRef(Dataset::Type aType) const
KeyRefType GetKeyRefType(Dataset::Type aType) const
{
return (aType == Dataset::kActive) ? mActiveKeyRef : mPendingKeyRef;
return (aType == Dataset::kActive) ? mActiveKeyRefType : mPendingKeyRefType;
}
Tlv::Type mTlvType;
KeyRef mActiveKeyRef;
KeyRef mPendingKeyRef;
Tlv::Type mTlvType;
KeyRefType mActiveKeyRefType;
KeyRefType mPendingKeyRefType;
};
static const SecurelyStoredTlv kSecurelyStoredTlvs[];
+1 -1
View File
@@ -1110,7 +1110,7 @@ Error Client::PrepareUpdateMessage(MsgInfo &aInfo)
aInfo.mRecordCount = 0;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
aInfo.mKeyInfo.SetKeyRef(kSrpEcdsaKeyRef);
aInfo.mKeyInfo.SetKeyRef(Get<Crypto::Storage::KeyRefManager>().KeyRefFor(Crypto::Storage::KeyRefManager::kEcdsa));
#endif
SuccessOrExit(error = ReadOrGenerateKey(aInfo.mKeyInfo));
-4
View File
@@ -749,10 +749,6 @@ private:
// Number of fast data polls after SRP Update tx (11x 188ms = ~2 seconds)
static constexpr uint8_t kFastPollsAfterUpdateTx = 11;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
static constexpr uint32_t kSrpEcdsaKeyRef = Crypto::Storage::kEcdsaRef;
#endif
#if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
static constexpr uint8_t kMaxTimeoutFailuresToSwitchServer =
OPENTHREAD_CONFIG_SRP_CLIENT_MAX_TIMEOUT_FAILURES_TO_SWITCH_SERVER;
+4 -3
View File
@@ -586,7 +586,7 @@ void KeyManager::StoreNetworkKey(const NetworkKey &aNetworkKey, bool aOverWriteE
{
NetworkKeyRef keyRef;
keyRef = Crypto::Storage::kNetworkKeyRef;
keyRef = Get<Crypto::Storage::KeyRefManager>().KeyRefFor(Crypto::Storage::KeyRefManager::kNetworkKey);
if (!aOverWriteExisting)
{
@@ -617,7 +617,7 @@ exit:
void KeyManager::StorePskc(const Pskc &aPskc)
{
PskcRef keyRef = Crypto::Storage::kPskcRef;
PskcRef keyRef = Get<Crypto::Storage::KeyRefManager>().KeyRefFor(Crypto::Storage::KeyRefManager::kPskc);
Crypto::Storage::DestroyKey(keyRef);
@@ -671,7 +671,8 @@ void KeyManager::DestroyTemporaryKeys(void)
Get<Mac::Mac>().ClearMode2Key();
}
void KeyManager::DestroyPersistentKeys(void) { Crypto::Storage::DestroyPersistentKeys(); }
void KeyManager::DestroyPersistentKeys(void) { Get<Crypto::Storage::KeyRefManager>().DestroyPersistentKeys(); }
#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
} // namespace ot