From edf539ce27bebd9ead17c3a29ecd2fbe1ae9aa85 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 30 May 2023 13:25:10 -0700 Subject: [PATCH] [random] add `Fill()` function (#9097) This commit adds template `Fill(ObjectType &aObject)` functions for both `Crypto` and `NonCrypto` random number generation modules. These functions fill a given object with random byes. --- src/core/common/random.cpp | 2 +- src/core/common/random.hpp | 34 +++++++++++++++++++++++++++++++ src/core/mac/mac_types.cpp | 2 +- src/core/meshcop/border_agent.cpp | 2 +- src/core/meshcop/dataset.cpp | 2 +- src/core/net/dhcp6.hpp | 7 ++++++- src/core/net/ip6_address.cpp | 2 +- src/core/net/nat64_translator.cpp | 2 +- src/core/net/tcp6.cpp | 2 +- src/core/thread/key_manager.hpp | 4 ++-- src/core/utils/slaac_address.cpp | 4 ++-- tests/unit/test_checksum.cpp | 8 ++++---- tests/unit/test_ndproxy_table.cpp | 2 +- tests/unit/test_spinel_buffer.cpp | 2 +- 14 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/core/common/random.cpp b/src/core/common/random.cpp index 482d68d75..18efcef8a 100644 --- a/src/core/common/random.cpp +++ b/src/core/common/random.cpp @@ -54,7 +54,7 @@ Manager::Manager(void) #if !OPENTHREAD_RADIO otPlatCryptoRandomInit(); - SuccessOrAssert(Random::Crypto::FillBuffer(reinterpret_cast(&seed), sizeof(seed))); + SuccessOrAssert(Random::Crypto::Fill(seed)); #else SuccessOrAssert(otPlatEntropyGet(reinterpret_cast(&seed), sizeof(seed))); #endif diff --git a/src/core/common/random.hpp b/src/core/common/random.hpp index baf8f7d93..fb01e22c8 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 { @@ -174,6 +175,21 @@ uint32_t GetUint32InRange(uint32_t aMin, uint32_t aMax); */ 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 void Fill(ObjectType &aObject) +{ + static_assert(!TypeTraits::IsPointer::kValue, "ObjectType must not be a pointer"); + + FillBuffer(reinterpret_cast(&aObject), sizeof(ObjectType)); +} + /** * Adds a random jitter within a given range to a given value. * @@ -202,6 +218,24 @@ namespace Crypto { */ 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 Error Fill(ObjectType &aObject) +{ + static_assert(!TypeTraits::IsPointer::kValue, "ObjectType must not be a pointer"); + + return FillBuffer(reinterpret_cast(&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 7ed4b1b31..e1cb4972b 100644 --- a/src/core/mac/mac_types.cpp +++ b/src/core/mac/mac_types.cpp @@ -57,7 +57,7 @@ PanId GenerateRandomPanId(void) #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 d15e77c21..6548d5829 100644 --- a/src/core/meshcop/border_agent.cpp +++ b/src/core/meshcop/border_agent.cpp @@ -243,7 +243,7 @@ Error BorderAgent::GetId(Id &aId) if (Get().Read(id) != kErrorNone) { - Random::NonCrypto::FillBuffer(id.GetId().mId, sizeof(id)); + Random::NonCrypto::Fill(id.GetId()); SuccessOrExit(error = Get().Save(id)); } diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp index 5d9a02877..60aa0dae0 100644 --- a/src/core/meshcop/dataset.cpp +++ b/src/core/meshcop/dataset.cpp @@ -80,7 +80,7 @@ Error Dataset::Info::GenerateRandom(Instance &aInstance) 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 1cfa12dfa..b2a0c187e 100644 --- a/src/core/net/dhcp6.hpp +++ b/src/core/net/dhcp6.hpp @@ -107,7 +107,12 @@ public: * @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 ad975010f..e6d924296 100644 --- a/src/core/net/ip6_address.cpp +++ b/src/core/net/ip6_address.cpp @@ -255,7 +255,7 @@ bool InterfaceIdentifier::IsReservedSubnetAnycast(void) const 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 ee9cd2d70..6513cb2df 100644 --- a/src/core/net/nat64_translator.cpp +++ b/src/core/net/nat64_translator.cpp @@ -70,7 +70,7 @@ Translator::Translator(Instance &aInstance) , mState(State::kStateDisabled) , mMappingExpirerTimer(aInstance) { - Random::NonCrypto::FillBuffer(reinterpret_cast(&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 47c50278e..7c9b1d3cc 100644 --- a/src/core/net/tcp6.cpp +++ b/src/core/net/tcp6.cpp @@ -1114,7 +1114,7 @@ bool tcplp_sys_autobind(otInstance *aInstance, uint32_t tcplp_sys_generate_isn() { uint32_t isn; - IgnoreError(Random::Crypto::FillBuffer(reinterpret_cast(&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 1fa8e320a..18f11f20b 100644 --- a/src/core/thread/key_manager.hpp +++ b/src/core/thread/key_manager.hpp @@ -148,7 +148,7 @@ public: * @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 @@ public: * @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 825130a17..ade19541c 100644 --- a/src/core/utils/slaac_address.cpp +++ b/src/core/utils/slaac_address.cpp @@ -335,11 +335,11 @@ void Slaac::GetIidSecretKey(IidSecretKey &aKey) const // 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().Save(aKey)); diff --git a/tests/unit/test_checksum.cpp b/tests/unit/test_checksum.cpp index b0b17b5f6..82e74fdd7 100644 --- a/tests/unit/test_checksum.cpp +++ b/tests/unit/test_checksum.cpp @@ -190,7 +190,7 @@ void TestUdpMessageChecksum(void) // Write UDP header with a random payload. - Random::NonCrypto::FillBuffer(reinterpret_cast(&udpHeader), sizeof(udpHeader)); + Random::NonCrypto::Fill(udpHeader); udpHeader.SetChecksum(0); message->Write(0, udpHeader); @@ -258,7 +258,7 @@ void TestIcmp6MessageChecksum(void) // Write ICMP6 header with a random payload. - Random::NonCrypto::FillBuffer(reinterpret_cast(&icmp6Header), sizeof(icmp6Header)); + Random::NonCrypto::Fill(icmp6Header); icmp6Header.SetChecksum(0); message->Write(0, icmp6Header); @@ -332,7 +332,7 @@ void TestTcp4MessageChecksum(void) // Write TCP header with a random payload. - Random::NonCrypto::FillBuffer(reinterpret_cast(&tcpHeader), sizeof(tcpHeader)); + Random::NonCrypto::Fill(tcpHeader); message->Write(0, tcpHeader); if (size > sizeof(tcpHeader)) @@ -387,7 +387,7 @@ void TestUdp4MessageChecksum(void) // Write UDP header with a random payload. - Random::NonCrypto::FillBuffer(reinterpret_cast(&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 4589db93a..80f5d13dd 100644 --- a/tests/unit/test_ndproxy_table.cpp +++ b/tests/unit/test_ndproxy_table.cpp @@ -50,7 +50,7 @@ Ip6::InterfaceIdentifier generateRandomIid(uint16_t aIndex) { 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 0fbdb07a4..8d4f32257 100644 --- a/tests/unit/test_spinel_buffer.cpp +++ b/tests/unit/test_spinel_buffer.cpp @@ -891,7 +891,7 @@ uint32_t GetRandom(uint32_t max) if (kUseTrueRandomNumberGenerator) { - SuccessOrQuit(Random::Crypto::FillBuffer(reinterpret_cast(&value), sizeof(value))); + SuccessOrQuit(Random::Crypto::Fill(value)); } else {