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 
47 namespace ot {
48 namespace Random {
49 
50 /**
51  * This class manages random number generator initialization/deinitialization.
52  *
53  */
54 class Manager : private NonCopyable
55 {
56 public:
57     /**
58      * This constructor initializes the object.
59      *
60      */
61     Manager(void);
62 
63     /**
64      * This destructor deinitializes the object.
65      *
66      */
67     ~Manager(void);
68 
69     /**
70      * This static method generates and returns a random value using a non-crypto Pseudo Random Number Generator.
71      *
72      * @returns    A random `uint32_t` value.
73      *
74      */
75     static uint32_t NonCryptoGetUint32(void);
76 
77 #if !OPENTHREAD_RADIO
78     /**
79      * This static method fills a given buffer with cryptographically secure random bytes.
80      *
81      * @param[out] aBuffer  A pointer to a buffer to fill with the random bytes.
82      * @param[in]  aSize    Size of buffer (number of bytes to fill).
83      *
84      * @retval kErrorNone    Successfully filled buffer with random values.
85      *
86      */
CryptoFillBuffer(uint8_t * aBuffer,uint16_t aSize)87     static Error CryptoFillBuffer(uint8_t *aBuffer, uint16_t aSize) { return otPlatCryptoRandomGet(aBuffer, aSize); }
88 #endif
89 
90 private:
91     class NonCryptoPrng // A non-crypto Pseudo Random Number Generator (PRNG)
92     {
93     public:
94         void     Init(uint32_t aSeed);
95         uint32_t GetNext(void);
96 
97     private:
98         uint32_t mState;
99     };
100 
101     static uint16_t      sInitCount;
102     static NonCryptoPrng sPrng;
103 };
104 
105 namespace NonCrypto {
106 
107 /**
108  * This function generates and returns a random `uint32_t` value.
109  *
110  * @returns    A random `uint32_t` value.
111  *
112  */
GetUint32(void)113 inline uint32_t GetUint32(void) { return Manager::NonCryptoGetUint32(); }
114 
115 /**
116  * This function generates and returns a random byte.
117  *
118  * @returns A random `uint8_t` value.
119  *
120  */
GetUint8(void)121 inline uint8_t GetUint8(void) { return static_cast<uint8_t>(GetUint32() & 0xff); }
122 
123 /**
124  * This function generates and returns a random `uint16_t` value.
125  *
126  * @returns A random `uint16_t` value.
127  *
128  */
GetUint16(void)129 inline uint16_t GetUint16(void) { return static_cast<uint16_t>(GetUint32() & 0xffff); }
130 
131 /**
132  * This function generates and returns a random `uint8_t` value within a given range `[aMin, aMax)`.
133  *
134  * @param[in]  aMin  A minimum value (this value can be included in returned random result).
135  * @param[in]  aMax  A maximum value (this value is excluded from returned random result).
136  *
137  * @returns    A random `uint8_t` value in the given range (i.e., aMin <= random value < aMax).
138  *
139  */
140 uint8_t GetUint8InRange(uint8_t aMin, uint8_t aMax);
141 
142 /**
143  * This function generates and returns a random `uint16_t` value within a given range `[aMin, aMax)`.
144  *
145  * @note The returned random value can include the @p aMin value but excludes the @p aMax.
146  *
147  * @param[in]  aMin  A minimum value (this value can be included in returned random result).
148  * @param[in]  aMax  A maximum value (this value is excluded from returned random result).
149  *
150  * @returns    A random `uint16_t` value in the given range (i.e., aMin <= random value < aMax).
151  *
152  */
153 uint16_t GetUint16InRange(uint16_t aMin, uint16_t aMax);
154 
155 /**
156  * This function generates and returns a random `uint32_t` value within a given range `[aMin, aMax)`.
157  *
158  * @note The returned random value can include the @p aMin value but excludes the @p aMax.
159  *
160  * @param[in]  aMin  A minimum value (this value can be included in returned random result).
161  * @param[in]  aMax  A maximum value (this value is excluded from returned random result).
162  *
163  * @returns    A random `uint32_t` value in the given range (i.e., aMin <= random value < aMax).
164  *
165  */
166 uint32_t GetUint32InRange(uint32_t aMin, uint32_t aMax);
167 
168 /**
169  * This function fills a given buffer with random bytes.
170  *
171  * @param[out] aBuffer  A pointer to a buffer to fill with the random bytes.
172  * @param[in]  aSize    Size of buffer (number of bytes to fill).
173  *
174  */
175 void FillBuffer(uint8_t *aBuffer, uint16_t aSize);
176 
177 /**
178  * This function adds a random jitter within a given range to a given value.
179  *
180  * @param[in]  aValue     A value to which the random jitter is added.
181  * @param[in]  aJitter    Maximum jitter. Random jitter is selected from the range `[-aJitter, aJitter]`.
182  *
183  * @returns    The given value with an added random jitter.
184  *
185  */
186 uint32_t AddJitter(uint32_t aValue, uint16_t aJitter);
187 
188 } // namespace NonCrypto
189 
190 #if !OPENTHREAD_RADIO
191 
192 namespace Crypto {
193 
194 /**
195  * This function fills a given buffer with cryptographically secure random bytes.
196  *
197  * @param[out] aBuffer  A pointer to a buffer to fill with the random bytes.
198  * @param[in]  aSize    Size of buffer (number of bytes to fill).
199  *
200  * @retval kErrorNone    Successfully filled buffer with random values.
201  *
202  */
FillBuffer(uint8_t * aBuffer,uint16_t aSize)203 inline Error FillBuffer(uint8_t *aBuffer, uint16_t aSize) { return Manager::CryptoFillBuffer(aBuffer, aSize); }
204 
205 } // namespace Crypto
206 
207 #endif // !OPENTHREAD_RADIO
208 
209 } // namespace Random
210 } // namespace ot
211 
212 #endif // RANDOM_HPP_
213