[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
     {