[random] add `Fill<ObjectType>()` function (#9097)
This commit adds template `Fill<ObjectType>(ObjectType &aObject)`
functions for both `Crypto` and `NonCrypto` random number generation
modules. These functions fill a given object with random byes.
diff --git a/src/core/common/random.cpp b/src/core/common/random.cpp
index 482d68d..18efcef 100644
--- a/src/core/common/random.cpp
+++ b/src/core/common/random.cpp
@@ -54,7 +54,7 @@
#if !OPENTHREAD_RADIO
otPlatCryptoRandomInit();
- SuccessOrAssert(Random::Crypto::FillBuffer(reinterpret_cast<uint8_t *>(&seed), sizeof(seed)));
+ SuccessOrAssert(Random::Crypto::Fill(seed));
#else
SuccessOrAssert(otPlatEntropyGet(reinterpret_cast<uint8_t *>(&seed), sizeof(seed)));
#endif
diff --git a/src/core/common/random.hpp b/src/core/common/random.hpp
index baf8f7d..fb01e22 100644
--- a/src/core/common/random.hpp
+++ b/src/core/common/random.hpp
@@ -43,6 +43,7 @@
#include "common/debug.hpp"
#include "common/error.hpp"
#include "common/non_copyable.hpp"
+#include "common/type_traits.hpp"
namespace ot {
namespace Random {
@@ -175,6 +176,21 @@
void FillBuffer(uint8_t *aBuffer, uint16_t aSize);
/**
+ * Fills a given object with random bytes.
+ *
+ * @tparam ObjectType The object type to fill.
+ *
+ * @param[in] aObject A reference to the object to fill.
+ *
+ */
+template <typename ObjectType> void Fill(ObjectType &aObject)
+{
+ static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
+
+ FillBuffer(reinterpret_cast<uint8_t *>(&aObject), sizeof(ObjectType));
+}
+
+/**
* Adds a random jitter within a given range to a given value.
*
* @param[in] aValue A value to which the random jitter is added.
@@ -202,6 +218,24 @@
*/
inline Error FillBuffer(uint8_t *aBuffer, uint16_t aSize) { return Manager::CryptoFillBuffer(aBuffer, aSize); }
+/**
+ * Fills a given object with cryptographically secure random bytes.
+ *
+ * @tparam ObjectType The object type to fill.
+ *
+ * @param[in] aObject A reference to the object to fill.
+ *
+ * @retval kErrorNone Successfully filled @p aObject with random values.
+ * @retval kErrorFailed Failed to generate secure random bytes to fill the object.
+ *
+ */
+template <typename ObjectType> Error Fill(ObjectType &aObject)
+{
+ static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
+
+ return FillBuffer(reinterpret_cast<uint8_t *>(&aObject), sizeof(ObjectType));
+}
+
} // namespace Crypto
#endif // !OPENTHREAD_RADIO
diff --git a/src/core/mac/mac_types.cpp b/src/core/mac/mac_types.cpp
index 7ed4b1b..e1cb497 100644
--- a/src/core/mac/mac_types.cpp
+++ b/src/core/mac/mac_types.cpp
@@ -57,7 +57,7 @@
#if !OPENTHREAD_RADIO
void ExtAddress::GenerateRandom(void)
{
- IgnoreError(Random::Crypto::FillBuffer(m8, sizeof(ExtAddress)));
+ IgnoreError(Random::Crypto::Fill(*this));
SetGroup(false);
SetLocal(true);
}
diff --git a/src/core/meshcop/border_agent.cpp b/src/core/meshcop/border_agent.cpp
index d15e77c..6548d58 100644
--- a/src/core/meshcop/border_agent.cpp
+++ b/src/core/meshcop/border_agent.cpp
@@ -243,7 +243,7 @@
if (Get<Settings>().Read(id) != kErrorNone)
{
- Random::NonCrypto::FillBuffer(id.GetId().mId, sizeof(id));
+ Random::NonCrypto::Fill(id.GetId());
SuccessOrExit(error = Get<Settings>().Save(id));
}
diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp
index 5d9a028..60aa0da 100644
--- a/src/core/meshcop/dataset.cpp
+++ b/src/core/meshcop/dataset.cpp
@@ -80,7 +80,7 @@
SuccessOrExit(error = AsCoreType(&mNetworkKey).GenerateRandom());
SuccessOrExit(error = AsCoreType(&mPskc).GenerateRandom());
- SuccessOrExit(error = Random::Crypto::FillBuffer(mExtendedPanId.m8, sizeof(mExtendedPanId.m8)));
+ SuccessOrExit(error = Random::Crypto::Fill(mExtendedPanId));
SuccessOrExit(error = AsCoreType(&mMeshLocalPrefix).GenerateRandomUla());
snprintf(mNetworkName.m8, sizeof(mNetworkName), "%s-%04x", NetworkName::kNetworkNameInit, mPanId);
diff --git a/src/core/net/dhcp6.hpp b/src/core/net/dhcp6.hpp
index 1cfa12d..b2a0c18 100644
--- a/src/core/net/dhcp6.hpp
+++ b/src/core/net/dhcp6.hpp
@@ -107,7 +107,12 @@
* @retval kErrorFailed Failed to generate random sequence.
*
*/
- Error GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, kSize); }
+ Error GenerateRandom(void)
+ {
+ OT_UNUSED_VARIABLE(m8);
+
+ return Random::Crypto::Fill(*this);
+ }
private:
uint8_t m8[kSize];
diff --git a/src/core/net/ip6_address.cpp b/src/core/net/ip6_address.cpp
index ad97501..e6d9242 100644
--- a/src/core/net/ip6_address.cpp
+++ b/src/core/net/ip6_address.cpp
@@ -255,7 +255,7 @@
mFields.m8[7] >= 0x80);
}
-void InterfaceIdentifier::GenerateRandom(void) { SuccessOrAssert(Random::Crypto::FillBuffer(mFields.m8, kSize)); }
+void InterfaceIdentifier::GenerateRandom(void) { SuccessOrAssert(Random::Crypto::Fill(*this)); }
void InterfaceIdentifier::SetBytes(const uint8_t *aBuffer) { memcpy(mFields.m8, aBuffer, kSize); }
diff --git a/src/core/net/nat64_translator.cpp b/src/core/net/nat64_translator.cpp
index ee9cd2d..6513cb2 100644
--- a/src/core/net/nat64_translator.cpp
+++ b/src/core/net/nat64_translator.cpp
@@ -70,7 +70,7 @@
, mState(State::kStateDisabled)
, mMappingExpirerTimer(aInstance)
{
- Random::NonCrypto::FillBuffer(reinterpret_cast<uint8_t *>(&mNextMappingId), sizeof(mNextMappingId));
+ Random::NonCrypto::Fill(mNextMappingId);
mNat64Prefix.Clear();
mIp4Cidr.Clear();
diff --git a/src/core/net/tcp6.cpp b/src/core/net/tcp6.cpp
index 47c5027..7c9b1d3 100644
--- a/src/core/net/tcp6.cpp
+++ b/src/core/net/tcp6.cpp
@@ -1114,7 +1114,7 @@
uint32_t tcplp_sys_generate_isn()
{
uint32_t isn;
- IgnoreError(Random::Crypto::FillBuffer(reinterpret_cast<uint8_t *>(&isn), sizeof(isn)));
+ IgnoreError(Random::Crypto::Fill(isn));
return isn;
}
diff --git a/src/core/thread/key_manager.hpp b/src/core/thread/key_manager.hpp
index 1fa8e32..18f11f2 100644
--- a/src/core/thread/key_manager.hpp
+++ b/src/core/thread/key_manager.hpp
@@ -148,7 +148,7 @@
* @retval kErrorFailed Failed to generate random sequence.
*
*/
- Error GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, sizeof(m8)); }
+ Error GenerateRandom(void) { return Random::Crypto::Fill(*this); }
#endif
} OT_TOOL_PACKED_END;
@@ -178,7 +178,7 @@
* @retval kErrorNone Successfully generated a random Thread PSKc.
*
*/
- Error GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, sizeof(m8)); }
+ Error GenerateRandom(void) { return Random::Crypto::Fill(*this); }
#endif
} OT_TOOL_PACKED_END;
diff --git a/src/core/utils/slaac_address.cpp b/src/core/utils/slaac_address.cpp
index 825130a..ade1954 100644
--- a/src/core/utils/slaac_address.cpp
+++ b/src/core/utils/slaac_address.cpp
@@ -335,11 +335,11 @@
// If there is no previously saved secret key, generate
// a random one and save it.
- error = Random::Crypto::FillBuffer(aKey.m8, sizeof(IidSecretKey));
+ error = Random::Crypto::Fill(aKey);
if (error != kErrorNone)
{
- IgnoreError(Random::Crypto::FillBuffer(aKey.m8, sizeof(IidSecretKey)));
+ IgnoreError(Random::Crypto::Fill(aKey));
}
IgnoreError(Get<Settings>().Save<Settings::SlaacIidSecretKey>(aKey));
diff --git a/tests/unit/test_checksum.cpp b/tests/unit/test_checksum.cpp
index b0b17b5..82e74fd 100644
--- a/tests/unit/test_checksum.cpp
+++ b/tests/unit/test_checksum.cpp
@@ -190,7 +190,7 @@
// Write UDP header with a random payload.
- Random::NonCrypto::FillBuffer(reinterpret_cast<uint8_t *>(&udpHeader), sizeof(udpHeader));
+ Random::NonCrypto::Fill(udpHeader);
udpHeader.SetChecksum(0);
message->Write(0, udpHeader);
@@ -258,7 +258,7 @@
// Write ICMP6 header with a random payload.
- Random::NonCrypto::FillBuffer(reinterpret_cast<uint8_t *>(&icmp6Header), sizeof(icmp6Header));
+ Random::NonCrypto::Fill(icmp6Header);
icmp6Header.SetChecksum(0);
message->Write(0, icmp6Header);
@@ -332,7 +332,7 @@
// Write TCP header with a random payload.
- Random::NonCrypto::FillBuffer(reinterpret_cast<uint8_t *>(&tcpHeader), sizeof(tcpHeader));
+ Random::NonCrypto::Fill(tcpHeader);
message->Write(0, tcpHeader);
if (size > sizeof(tcpHeader))
@@ -387,7 +387,7 @@
// Write UDP header with a random payload.
- Random::NonCrypto::FillBuffer(reinterpret_cast<uint8_t *>(&udpHeader), sizeof(udpHeader));
+ Random::NonCrypto::Fill(udpHeader);
udpHeader.SetChecksum(0);
message->Write(0, udpHeader);
diff --git a/tests/unit/test_ndproxy_table.cpp b/tests/unit/test_ndproxy_table.cpp
index 4589db9..80f5d13 100644
--- a/tests/unit/test_ndproxy_table.cpp
+++ b/tests/unit/test_ndproxy_table.cpp
@@ -50,7 +50,7 @@
{
Ip6::InterfaceIdentifier iid;
- Random::NonCrypto::FillBuffer(iid.mFields.m8, sizeof(iid));
+ Random::NonCrypto::Fill(iid);
iid.mFields.m16[3] = aIndex;
return iid;
diff --git a/tests/unit/test_spinel_buffer.cpp b/tests/unit/test_spinel_buffer.cpp
index 0fbdb07..8d4f322 100644
--- a/tests/unit/test_spinel_buffer.cpp
+++ b/tests/unit/test_spinel_buffer.cpp
@@ -891,7 +891,7 @@
if (kUseTrueRandomNumberGenerator)
{
- SuccessOrQuit(Random::Crypto::FillBuffer(reinterpret_cast<uint8_t *>(&value), sizeof(value)));
+ SuccessOrQuit(Random::Crypto::Fill(value));
}
else
{