diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp index cc958313c..1e032eafc 100644 --- a/src/core/meshcop/dataset.cpp +++ b/src/core/meshcop/dataset.cpp @@ -605,5 +605,45 @@ void Dataset::ConvertToActive(void) const char *Dataset::TypeToString(Type aType) { return (aType == kActive) ? "Active" : "Pending"; } +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + +void Dataset::SaveTlvInSecureStorageAndClearValue(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef) +{ + using namespace ot::Crypto::Storage; + + Tlv *tlv = GetTlv(aTlvType); + + VerifyOrExit(tlv != nullptr); + VerifyOrExit(tlv->GetLength() > 0); + + SuccessOrAssert(ImportKey(aKeyRef, kKeyTypeRaw, kKeyAlgorithmVendor, kUsageExport, kTypePersistent, tlv->GetValue(), + tlv->GetLength())); + + memset(tlv->GetValue(), 0, tlv->GetLength()); + +exit: + return; +} + +Error Dataset::ReadTlvFromSecureStorage(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef) +{ + using namespace ot::Crypto::Storage; + + Error error = kErrorNone; + Tlv *tlv = GetTlv(aTlvType); + size_t readLength; + + VerifyOrExit(tlv != nullptr); + VerifyOrExit(tlv->GetLength() > 0); + + SuccessOrExit(error = ExportKey(aKeyRef, tlv->GetValue(), tlv->GetLength(), readLength)); + VerifyOrExit(readLength == tlv->GetLength(), error = OT_ERROR_FAILED); + +exit: + return error; +} + +#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + } // namespace MeshCoP } // namespace ot diff --git a/src/core/meshcop/dataset.hpp b/src/core/meshcop/dataset.hpp index 0f9a69e0c..21d3fb816 100644 --- a/src/core/meshcop/dataset.hpp +++ b/src/core/meshcop/dataset.hpp @@ -918,6 +918,35 @@ public: */ static const char *TypeToString(Type aType); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + + /** + * Saves a given TLV value in secure storage and clears the TLV value by setting all value bytes to zero. + * + * If the Dataset does not contain the @p aTlvType, no action is performed. + * + * @param[in] aTlvType The TLV type. + * @param[in] aKeyRef The `KeyRef` to use with secure storage. + * + */ + void SaveTlvInSecureStorageAndClearValue(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef); + + /** + * Reads and updates a given TLV value in Dataset from secure storage. + * + * If the Dataset does not contain the @p aTlvType, no action is performed and `kErrorNone` is returned. + * + * @param[in] aTlvType The TLV type. + * @param[in] aKeyRef The `KeyRef` to use with secure storage. + * + * @retval kErrorNone Successfully read the TLV value from secure storage and updated the Dataset. + * @retval KErrorFailed Could not read the @aKeyRef from secure storage. + * + */ + Error ReadTlvFromSecureStorage(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef); + +#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + private: void RemoveTlv(Tlv *aTlv); diff --git a/src/core/meshcop/dataset_local.cpp b/src/core/meshcop/dataset_local.cpp index ac1095732..0955bf175 100644 --- a/src/core/meshcop/dataset_local.cpp +++ b/src/core/meshcop/dataset_local.cpp @@ -218,112 +218,64 @@ exit: } #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + +const DatasetLocal::SecurelyStoredTlv DatasetLocal::kSecurelyStoredTlvs[] = { + { + Tlv::kNetworkKey, + Crypto::Storage::kActiveDatasetNetworkKeyRef, + Crypto::Storage::kPendingDatasetNetworkKeyRef, + }, + { + Tlv::kPskc, + Crypto::Storage::kActiveDatasetPskcRef, + Crypto::Storage::kPendingDatasetPskcRef, + }, +}; + void DatasetLocal::DestroySecurelyStoredKeys(void) const { - using namespace Crypto::Storage; - - KeyRef networkKeyRef = IsActive() ? kActiveDatasetNetworkKeyRef : kPendingDatasetNetworkKeyRef; - KeyRef pskcRef = IsActive() ? kActiveDatasetPskcRef : kPendingDatasetPskcRef; - - // Destroy securely stored keys associated with the given operational dataset type. - DestroyKey(networkKeyRef); - DestroyKey(pskcRef); + for (const SecurelyStoredTlv &entry : kSecurelyStoredTlvs) + { + Crypto::Storage::DestroyKey(entry.GetKeyRef(mType)); + } } void DatasetLocal::MoveKeysToSecureStorage(Dataset &aDataset) const { - using namespace Crypto::Storage; - - KeyRef networkKeyRef = IsActive() ? kActiveDatasetNetworkKeyRef : kPendingDatasetNetworkKeyRef; - KeyRef pskcRef = IsActive() ? kActiveDatasetPskcRef : kPendingDatasetPskcRef; - NetworkKeyTlv *networkKeyTlv = aDataset.GetTlv(); - PskcTlv *pskcTlv = aDataset.GetTlv(); - - if (networkKeyTlv != nullptr) + for (const SecurelyStoredTlv &entry : kSecurelyStoredTlvs) { - // If the dataset contains a network key, put it in the secure storage - // and zero the corresponding TLV element. - NetworkKey networkKey; - SuccessOrAssert(ImportKey(networkKeyRef, kKeyTypeRaw, kKeyAlgorithmVendor, kUsageExport, kTypePersistent, - networkKeyTlv->GetNetworkKey().m8, NetworkKey::kSize)); - networkKey.Clear(); - networkKeyTlv->SetNetworkKey(networkKey); - } - - if (pskcTlv != nullptr) - { - // If the dataset contains a PSKC, put it in the secure storage and zero - // the corresponding TLV element. - Pskc pskc; - SuccessOrAssert(ImportKey(pskcRef, kKeyTypeRaw, kKeyAlgorithmVendor, kUsageExport, kTypePersistent, - pskcTlv->GetPskc().m8, Pskc::kSize)); - pskc.Clear(); - pskcTlv->SetPskc(pskc); + aDataset.SaveTlvInSecureStorageAndClearValue(entry.mTlvType, entry.GetKeyRef(mType)); } } void DatasetLocal::EmplaceSecurelyStoredKeys(Dataset &aDataset) const { - using namespace Crypto::Storage; + bool moveKeys = false; - KeyRef networkKeyRef = IsActive() ? kActiveDatasetNetworkKeyRef : kPendingDatasetNetworkKeyRef; - KeyRef pskcRef = IsActive() ? kActiveDatasetPskcRef : kPendingDatasetPskcRef; - NetworkKeyTlv *networkKeyTlv = aDataset.GetTlv(); - PskcTlv *pskcTlv = aDataset.GetTlv(); - bool moveKeys = false; - size_t keyLen; - Error error; + // If reading any of the TLVs fails, it indicates they are not yet + // stored in secure storage and are still contained in the `Dataset` + // read from `Settings`. In this case, we move the keys to secure + // storage and then clear them from 'Settings'. - if (networkKeyTlv != nullptr) + for (const SecurelyStoredTlv &entry : kSecurelyStoredTlvs) { - // If the dataset contains a network key, its real value must have been moved to - // the secure storage upon saving the dataset, so restore it back now. - NetworkKey networkKey; - error = ExportKey(networkKeyRef, networkKey.m8, NetworkKey::kSize, keyLen); - - if (error != kErrorNone) + if (aDataset.ReadTlvFromSecureStorage(entry.mTlvType, entry.GetKeyRef(mType)) != kErrorNone) { - // If ExportKey fails, key is not in secure storage and is stored in settings moveKeys = true; } - else - { - OT_ASSERT(keyLen == NetworkKey::kSize); - networkKeyTlv->SetNetworkKey(networkKey); - } - } - - if (pskcTlv != nullptr) - { - // If the dataset contains a PSKC, its real value must have been moved to - // the secure storage upon saving the dataset, so restore it back now. - Pskc pskc; - error = ExportKey(pskcRef, pskc.m8, Pskc::kSize, keyLen); - - if (error != kErrorNone) - { - // If ExportKey fails, key is not in secure storage and is stored in settings - moveKeys = true; - } - else - { - OT_ASSERT(keyLen == Pskc::kSize); - pskcTlv->SetPskc(pskc); - } } if (moveKeys) { - // Clear the networkkey and Pskc stored in the settings and move them to secure storage. - // Store the network key and PSKC in the secure storage instead of settings. Dataset dataset; dataset.Set(GetType(), aDataset); MoveKeysToSecureStorage(dataset); - SuccessOrAssert(error = Get().SaveOperationalDataset(mType, dataset)); + SuccessOrAssert(Get().SaveOperationalDataset(mType, dataset)); } } -#endif + +#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE } // namespace MeshCoP } // namespace ot diff --git a/src/core/meshcop/dataset_local.hpp b/src/core/meshcop/dataset_local.hpp index 2981b7c02..249f069d5 100644 --- a/src/core/meshcop/dataset_local.hpp +++ b/src/core/meshcop/dataset_local.hpp @@ -184,14 +184,29 @@ public: Error Save(const Dataset &aDataset); private: - bool IsActive(void) const { return (mType == Dataset::kActive); } - void SetTimestamp(const Dataset &aDataset); #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + struct SecurelyStoredTlv + { + Crypto::Storage::KeyRef GetKeyRef(Dataset::Type aType) const + { + return (aType == Dataset::kActive) ? mActiveKeyRef : mPendingKeyRef; + } + + Tlv::Type mTlvType; + Crypto::Storage::KeyRef mActiveKeyRef; + Crypto::Storage::KeyRef mPendingKeyRef; + }; + + static const SecurelyStoredTlv kSecurelyStoredTlvs[]; + void MoveKeysToSecureStorage(Dataset &aDataset) const; void DestroySecurelyStoredKeys(void) const; void EmplaceSecurelyStoredKeys(Dataset &aDataset) const; #endif + bool IsActive(void) const { return (mType == Dataset::kActive); } + void SetTimestamp(const Dataset &aDataset); + Timestamp mTimestamp; ///< Active or Pending Timestamp TimeMilli mUpdateTime; ///< Local time last updated Dataset::Type mType; ///< Active or Pending