1 /*
2  *  Copyright (c) 2019, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *  This file includes definitions for OpenThread random number generation.
32  */
33 
34 #ifndef RANDOM_HPP_
35 #define RANDOM_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <stdint.h>
40 
41 #include <openthread/platform/crypto.h>
42 
43 #include "common/debug.hpp"
44 #include "common/error.hpp"
45 #include "common/non_copyable.hpp"
46 #include "common/type_traits.hpp"
47 
48 namespace ot {
49 namespace Random {
50 
51 /**
52  * Manages random number generator initialization/deinitialization.
53  */
54 class Manager : private NonCopyable
55 {
56 public:
57     /**
58      * Initializes the object.
59      */
60     Manager(void);
61 
62     /**
63      * This destructor deinitializes the object.
64      */
65     ~Manager(void);
66 
67     /**
68      * Generates and returns a random value using a non-crypto Pseudo Random Number Generator.
69      *
70      * @returns    A random `uint32_t` value.
71      */
72     static uint32_t NonCryptoGetUint32(void);
73 
74 #if !OPENTHREAD_RADIO
75     /**
76      * Fills a given buffer with cryptographically secure random bytes.
77      *
78      * @param[out] aBuffer  A pointer to a buffer to fill with the random bytes.
79      * @param[in]  aSize    Size of buffer (number of bytes to fill).
80      *
81      * @retval kErrorNone    Successfully filled buffer with random values.
82      */
CryptoFillBuffer(uint8_t * aBuffer,uint16_t aSize)83     static Error CryptoFillBuffer(uint8_t *aBuffer, uint16_t aSize) { return otPlatCryptoRandomGet(aBuffer, aSize); }
84 #endif
85 
86 private:
87     class NonCryptoPrng // A non-crypto Pseudo Random Number Generator (PRNG)
88     {
89     public:
90         void     Init(uint32_t aSeed);
91         uint32_t GetNext(void);
92 
93     private:
94         uint32_t mState;
95     };
96 
97     static uint16_t      sInitCount;
98     static NonCryptoPrng sPrng;
99 };
100 
101 namespace NonCrypto {
102 
103 /**
104  * Generates and returns a random `uint32_t` value.
105  *
106  * @returns    A random `uint32_t` value.
107  */
GetUint32(void)108 inline uint32_t GetUint32(void) { return Manager::NonCryptoGetUint32(); }
109 
110 /**
111  * Generates and returns a random byte.
112  *
113  * @returns A random `uint8_t` value.
114  */
GetUint8(void)115 inline uint8_t GetUint8(void) { return static_cast<uint8_t>(GetUint32() & 0xff); }
116 
117 /**
118  * Generates and returns a random `uint16_t` value.
119  *
120  * @returns A random `uint16_t` value.
121  */
GetUint16(void)122 inline uint16_t GetUint16(void) { return static_cast<uint16_t>(GetUint32() & 0xffff); }
123 
124 /**
125  * Generates and returns a random `uint8_t` value within a given range `[aMin, aMax)`.
126  *
127  * @param[in]  aMin  A minimum value (this value can be included in returned random result).
128  * @param[in]  aMax  A maximum value (this value is excluded from returned random result).
129  *
130  * @returns    A random `uint8_t` value in the given range (i.e., aMin <= random value < aMax).
131  */
132 uint8_t GetUint8InRange(uint8_t aMin, uint8_t aMax);
133 
134 /**
135  * Generates and returns a random `uint16_t` value within a given range `[aMin, aMax)`.
136  *
137  * @note The returned random value can include the @p aMin value but excludes the @p aMax.
138  *
139  * @param[in]  aMin  A minimum value (this value can be included in returned random result).
140  * @param[in]  aMax  A maximum value (this value is excluded from returned random result).
141  *
142  * @returns    A random `uint16_t` value in the given range (i.e., aMin <= random value < aMax).
143  */
144 uint16_t GetUint16InRange(uint16_t aMin, uint16_t aMax);
145 
146 /**
147  * Generates and returns a random `uint32_t` value within a given range `[aMin, aMax)`.
148  *
149  * @note The returned random value can include the @p aMin value but excludes the @p aMax.
150  *
151  * @param[in]  aMin  A minimum value (this value can be included in returned random result).
152  * @param[in]  aMax  A maximum value (this value is excluded from returned random result).
153  *
154  * @returns    A random `uint32_t` value in the given range (i.e., aMin <= random value < aMax).
155  */
156 uint32_t GetUint32InRange(uint32_t aMin, uint32_t aMax);
157 
158 /**
159  * Fills a given buffer with random bytes.
160  *
161  * @param[out] aBuffer  A pointer to a buffer to fill with the random bytes.
162  * @param[in]  aSize    Size of buffer (number of bytes to fill).
163  */
164 void FillBuffer(uint8_t *aBuffer, uint16_t aSize);
165 
166 /**
167  * Fills a given object with random bytes.
168  *
169  * @tparam    ObjectType   The object type to fill.
170  *
171  * @param[in] aObject      A reference to the object to fill.
172  */
Fill(ObjectType & aObject)173 template <typename ObjectType> void Fill(ObjectType &aObject)
174 {
175     static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
176 
177     FillBuffer(reinterpret_cast<uint8_t *>(&aObject), sizeof(ObjectType));
178 }
179 
180 /**
181  * Adds a random jitter within a given range to a given value.
182  *
183  * @param[in]  aValue     A value to which the random jitter is added.
184  * @param[in]  aJitter    Maximum jitter. Random jitter is selected from the range `[-aJitter, aJitter]`.
185  *
186  * @returns    The given value with an added random jitter.
187  */
188 uint32_t AddJitter(uint32_t aValue, uint16_t aJitter);
189 
190 } // namespace NonCrypto
191 
192 #if !OPENTHREAD_RADIO
193 
194 namespace Crypto {
195 
196 /**
197  * Fills a given buffer with cryptographically secure random bytes.
198  *
199  * @param[out] aBuffer  A pointer to a buffer to fill with the random bytes.
200  * @param[in]  aSize    Size of buffer (number of bytes to fill).
201  *
202  * @retval kErrorNone    Successfully filled buffer with random values.
203  */
FillBuffer(uint8_t * aBuffer,uint16_t aSize)204 inline Error FillBuffer(uint8_t *aBuffer, uint16_t aSize) { return Manager::CryptoFillBuffer(aBuffer, aSize); }
205 
206 /**
207  * Fills a given object with cryptographically secure random bytes.
208  *
209  * @tparam    ObjectType   The object type to fill.
210  *
211  * @param[in] aObject      A reference to the object to fill.
212  *
213  * @retval kErrorNone    Successfully filled @p aObject with random values.
214  * @retval kErrorFailed  Failed to generate secure random bytes to fill the object.
215  */
Fill(ObjectType & aObject)216 template <typename ObjectType> Error Fill(ObjectType &aObject)
217 {
218     static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
219 
220     return FillBuffer(reinterpret_cast<uint8_t *>(&aObject), sizeof(ObjectType));
221 }
222 
223 } // namespace Crypto
224 
225 #endif // !OPENTHREAD_RADIO
226 
227 } // namespace Random
228 } // namespace ot
229 
230 #endif // RANDOM_HPP_
231