3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2013-2017 Nest Labs, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * This file implements utility functions for deriving random integers.
23 * @note These utility functions do not generate cryptographically strong
24 * random number. To get cryptographically strong random data use
25 * chip::Platform::Security::GetSecureRandomData().
29 #include "RandUtils.h"
35 #ifndef __STDC_LIMIT_MACROS
36 #define __STDC_LIMIT_MACROS
42 * @def NORMALIZED_RAND_RANGE(reqRange)
44 * This macro calculates normalized range for the output of rand() function
45 * based on the requested random range [0, reqRange].
48 * For most of the platforms we support, RAND_MAX is usually 0x7FFF or 0x7FFFFFFF.
49 * In these cases normalization for ranges [0, UINT8_MAX] or [0, UINT16_MAX]
52 * @param[in] reqRange The requested random number range.
54 * @return normalized random range.
57 #define NORMALIZED_RAND_RANGE(reqRange) (((reqRange) + 1) * ((RAND_MAX + 1) / ((reqRange) + 1)))
59 #if RAND_MAX < UINT8_MAX
60 #error "RAND_MAX value is too small. RandUtils functions assume that RAND_MAX is greater or equal to UINT8_MAX."
65 // rand() returns int, which is always smaller than the size of uint64_t
66 // and rand() cannot be used directly to generate random uint64_t number.
67 return static_cast<uint64_t>(GetRandU32()) ^ (static_cast<uint64_t>(GetRandU32()) << (sizeof(uint32_t) * CHAR_BIT));
72 // Check if (RAND_MAX == UINT32_MAX) but it is unlikely because rand() returns signed int,
73 // which maximum possible value is 0x7FFFFFFF (smaller that UINT32_MAX = 0xFFFFFFFF).
74 #if RAND_MAX == UINT32_MAX
75 return static_cast<uint32_t>(rand());
77 return static_cast<uint32_t>(GetRandU16()) ^ (static_cast<uint32_t>(GetRandU16()) << (sizeof(uint16_t) * CHAR_BIT));
83 #if RAND_MAX >= UINT16_MAX
84 #if (RAND_MAX == INT_MAX) || (RAND_MAX == NORMALIZED_RAND_RANGE(UINT16_MAX))
85 // rand() random output range normalization is not needed.
86 return static_cast<uint16_t>(rand());
88 // Otherwise, Normilize the output range of rand() and reject rand() outputs outside of that range.
92 if (r < NORMALIZED_RAND_RANGE(UINT16_MAX))
93 return static_cast<uint16_t>(r);
97 return static_cast<uint16_t>(GetRandU8()) ^ (static_cast<uint16_t>(GetRandU8()) << CHAR_BIT);
103 #if (RAND_MAX == INT_MAX) || (RAND_MAX == NORMALIZED_RAND_RANGE(UINT8_MAX))
104 // rand() random output range normalization is not needed.
105 return static_cast<uint8_t>(rand());
107 // Otherwise, Normilize the output range of rand() and reject rand() outputs outside of that range.
111 if (r < NORMALIZED_RAND_RANGE(UINT8_MAX))
112 return static_cast<uint8_t>(r);