1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/helpers.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <openssl/rand.h>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
16*d9f75844SAndroid Build Coastguard Worker #include <limits>
17*d9f75844SAndroid Build Coastguard Worker #include <memory>
18*d9f75844SAndroid Build Coastguard Worker
19*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
22*d9f75844SAndroid Build Coastguard Worker
23*d9f75844SAndroid Build Coastguard Worker // Protect against max macro inclusion.
24*d9f75844SAndroid Build Coastguard Worker #undef max
25*d9f75844SAndroid Build Coastguard Worker
26*d9f75844SAndroid Build Coastguard Worker namespace rtc {
27*d9f75844SAndroid Build Coastguard Worker
28*d9f75844SAndroid Build Coastguard Worker // Base class for RNG implementations.
29*d9f75844SAndroid Build Coastguard Worker class RandomGenerator {
30*d9f75844SAndroid Build Coastguard Worker public:
~RandomGenerator()31*d9f75844SAndroid Build Coastguard Worker virtual ~RandomGenerator() {}
32*d9f75844SAndroid Build Coastguard Worker virtual bool Init(const void* seed, size_t len) = 0;
33*d9f75844SAndroid Build Coastguard Worker virtual bool Generate(void* buf, size_t len) = 0;
34*d9f75844SAndroid Build Coastguard Worker };
35*d9f75844SAndroid Build Coastguard Worker
36*d9f75844SAndroid Build Coastguard Worker // The OpenSSL RNG.
37*d9f75844SAndroid Build Coastguard Worker class SecureRandomGenerator : public RandomGenerator {
38*d9f75844SAndroid Build Coastguard Worker public:
SecureRandomGenerator()39*d9f75844SAndroid Build Coastguard Worker SecureRandomGenerator() {}
~SecureRandomGenerator()40*d9f75844SAndroid Build Coastguard Worker ~SecureRandomGenerator() override {}
Init(const void * seed,size_t len)41*d9f75844SAndroid Build Coastguard Worker bool Init(const void* seed, size_t len) override { return true; }
Generate(void * buf,size_t len)42*d9f75844SAndroid Build Coastguard Worker bool Generate(void* buf, size_t len) override {
43*d9f75844SAndroid Build Coastguard Worker return (RAND_bytes(reinterpret_cast<unsigned char*>(buf), len) > 0);
44*d9f75844SAndroid Build Coastguard Worker }
45*d9f75844SAndroid Build Coastguard Worker };
46*d9f75844SAndroid Build Coastguard Worker
47*d9f75844SAndroid Build Coastguard Worker // A test random generator, for predictable output.
48*d9f75844SAndroid Build Coastguard Worker class TestRandomGenerator : public RandomGenerator {
49*d9f75844SAndroid Build Coastguard Worker public:
TestRandomGenerator()50*d9f75844SAndroid Build Coastguard Worker TestRandomGenerator() : seed_(7) {}
~TestRandomGenerator()51*d9f75844SAndroid Build Coastguard Worker ~TestRandomGenerator() override {}
Init(const void * seed,size_t len)52*d9f75844SAndroid Build Coastguard Worker bool Init(const void* seed, size_t len) override { return true; }
Generate(void * buf,size_t len)53*d9f75844SAndroid Build Coastguard Worker bool Generate(void* buf, size_t len) override {
54*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < len; ++i) {
55*d9f75844SAndroid Build Coastguard Worker static_cast<uint8_t*>(buf)[i] = static_cast<uint8_t>(GetRandom());
56*d9f75844SAndroid Build Coastguard Worker }
57*d9f75844SAndroid Build Coastguard Worker return true;
58*d9f75844SAndroid Build Coastguard Worker }
59*d9f75844SAndroid Build Coastguard Worker
60*d9f75844SAndroid Build Coastguard Worker private:
GetRandom()61*d9f75844SAndroid Build Coastguard Worker int GetRandom() {
62*d9f75844SAndroid Build Coastguard Worker return ((seed_ = seed_ * 214013L + 2531011L) >> 16) & 0x7fff;
63*d9f75844SAndroid Build Coastguard Worker }
64*d9f75844SAndroid Build Coastguard Worker int seed_;
65*d9f75844SAndroid Build Coastguard Worker };
66*d9f75844SAndroid Build Coastguard Worker
67*d9f75844SAndroid Build Coastguard Worker namespace {
68*d9f75844SAndroid Build Coastguard Worker
69*d9f75844SAndroid Build Coastguard Worker // TODO: Use Base64::Base64Table instead.
70*d9f75844SAndroid Build Coastguard Worker static const char kBase64[64] = {
71*d9f75844SAndroid Build Coastguard Worker 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
72*d9f75844SAndroid Build Coastguard Worker 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
73*d9f75844SAndroid Build Coastguard Worker 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
74*d9f75844SAndroid Build Coastguard Worker 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
75*d9f75844SAndroid Build Coastguard Worker '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
76*d9f75844SAndroid Build Coastguard Worker
77*d9f75844SAndroid Build Coastguard Worker static const char kHex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
78*d9f75844SAndroid Build Coastguard Worker '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
79*d9f75844SAndroid Build Coastguard Worker
80*d9f75844SAndroid Build Coastguard Worker static const char kUuidDigit17[4] = {'8', '9', 'a', 'b'};
81*d9f75844SAndroid Build Coastguard Worker
82*d9f75844SAndroid Build Coastguard Worker // This round about way of creating a global RNG is to safe-guard against
83*d9f75844SAndroid Build Coastguard Worker // indeterminant static initialization order.
GetGlobalRng()84*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<RandomGenerator>& GetGlobalRng() {
85*d9f75844SAndroid Build Coastguard Worker static std::unique_ptr<RandomGenerator>& global_rng =
86*d9f75844SAndroid Build Coastguard Worker *new std::unique_ptr<RandomGenerator>(new SecureRandomGenerator());
87*d9f75844SAndroid Build Coastguard Worker
88*d9f75844SAndroid Build Coastguard Worker return global_rng;
89*d9f75844SAndroid Build Coastguard Worker }
90*d9f75844SAndroid Build Coastguard Worker
Rng()91*d9f75844SAndroid Build Coastguard Worker RandomGenerator& Rng() {
92*d9f75844SAndroid Build Coastguard Worker return *GetGlobalRng();
93*d9f75844SAndroid Build Coastguard Worker }
94*d9f75844SAndroid Build Coastguard Worker
95*d9f75844SAndroid Build Coastguard Worker } // namespace
96*d9f75844SAndroid Build Coastguard Worker
SetRandomTestMode(bool test)97*d9f75844SAndroid Build Coastguard Worker void SetRandomTestMode(bool test) {
98*d9f75844SAndroid Build Coastguard Worker if (!test) {
99*d9f75844SAndroid Build Coastguard Worker GetGlobalRng().reset(new SecureRandomGenerator());
100*d9f75844SAndroid Build Coastguard Worker } else {
101*d9f75844SAndroid Build Coastguard Worker GetGlobalRng().reset(new TestRandomGenerator());
102*d9f75844SAndroid Build Coastguard Worker }
103*d9f75844SAndroid Build Coastguard Worker }
104*d9f75844SAndroid Build Coastguard Worker
InitRandom(int seed)105*d9f75844SAndroid Build Coastguard Worker bool InitRandom(int seed) {
106*d9f75844SAndroid Build Coastguard Worker return InitRandom(reinterpret_cast<const char*>(&seed), sizeof(seed));
107*d9f75844SAndroid Build Coastguard Worker }
108*d9f75844SAndroid Build Coastguard Worker
InitRandom(const char * seed,size_t len)109*d9f75844SAndroid Build Coastguard Worker bool InitRandom(const char* seed, size_t len) {
110*d9f75844SAndroid Build Coastguard Worker if (!Rng().Init(seed, len)) {
111*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "Failed to init random generator!";
112*d9f75844SAndroid Build Coastguard Worker return false;
113*d9f75844SAndroid Build Coastguard Worker }
114*d9f75844SAndroid Build Coastguard Worker return true;
115*d9f75844SAndroid Build Coastguard Worker }
116*d9f75844SAndroid Build Coastguard Worker
CreateRandomString(size_t len)117*d9f75844SAndroid Build Coastguard Worker std::string CreateRandomString(size_t len) {
118*d9f75844SAndroid Build Coastguard Worker std::string str;
119*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(CreateRandomString(len, &str));
120*d9f75844SAndroid Build Coastguard Worker return str;
121*d9f75844SAndroid Build Coastguard Worker }
122*d9f75844SAndroid Build Coastguard Worker
CreateRandomString(size_t len,const char * table,int table_size,std::string * str)123*d9f75844SAndroid Build Coastguard Worker static bool CreateRandomString(size_t len,
124*d9f75844SAndroid Build Coastguard Worker const char* table,
125*d9f75844SAndroid Build Coastguard Worker int table_size,
126*d9f75844SAndroid Build Coastguard Worker std::string* str) {
127*d9f75844SAndroid Build Coastguard Worker str->clear();
128*d9f75844SAndroid Build Coastguard Worker // Avoid biased modulo division below.
129*d9f75844SAndroid Build Coastguard Worker if (256 % table_size) {
130*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "Table size must divide 256 evenly!";
131*d9f75844SAndroid Build Coastguard Worker return false;
132*d9f75844SAndroid Build Coastguard Worker }
133*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> bytes(new uint8_t[len]);
134*d9f75844SAndroid Build Coastguard Worker if (!Rng().Generate(bytes.get(), len)) {
135*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "Failed to generate random string!";
136*d9f75844SAndroid Build Coastguard Worker return false;
137*d9f75844SAndroid Build Coastguard Worker }
138*d9f75844SAndroid Build Coastguard Worker str->reserve(len);
139*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < len; ++i) {
140*d9f75844SAndroid Build Coastguard Worker str->push_back(table[bytes[i] % table_size]);
141*d9f75844SAndroid Build Coastguard Worker }
142*d9f75844SAndroid Build Coastguard Worker return true;
143*d9f75844SAndroid Build Coastguard Worker }
144*d9f75844SAndroid Build Coastguard Worker
CreateRandomString(size_t len,std::string * str)145*d9f75844SAndroid Build Coastguard Worker bool CreateRandomString(size_t len, std::string* str) {
146*d9f75844SAndroid Build Coastguard Worker return CreateRandomString(len, kBase64, 64, str);
147*d9f75844SAndroid Build Coastguard Worker }
148*d9f75844SAndroid Build Coastguard Worker
CreateRandomString(size_t len,absl::string_view table,std::string * str)149*d9f75844SAndroid Build Coastguard Worker bool CreateRandomString(size_t len, absl::string_view table, std::string* str) {
150*d9f75844SAndroid Build Coastguard Worker return CreateRandomString(len, table.data(), static_cast<int>(table.size()),
151*d9f75844SAndroid Build Coastguard Worker str);
152*d9f75844SAndroid Build Coastguard Worker }
153*d9f75844SAndroid Build Coastguard Worker
CreateRandomData(size_t length,std::string * data)154*d9f75844SAndroid Build Coastguard Worker bool CreateRandomData(size_t length, std::string* data) {
155*d9f75844SAndroid Build Coastguard Worker data->resize(length);
156*d9f75844SAndroid Build Coastguard Worker // std::string is guaranteed to use contiguous memory in c++11 so we can
157*d9f75844SAndroid Build Coastguard Worker // safely write directly to it.
158*d9f75844SAndroid Build Coastguard Worker return Rng().Generate(&data->at(0), length);
159*d9f75844SAndroid Build Coastguard Worker }
160*d9f75844SAndroid Build Coastguard Worker
161*d9f75844SAndroid Build Coastguard Worker // Version 4 UUID is of the form:
162*d9f75844SAndroid Build Coastguard Worker // xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
163*d9f75844SAndroid Build Coastguard Worker // Where 'x' is a hex digit, and 'y' is 8, 9, a or b.
CreateRandomUuid()164*d9f75844SAndroid Build Coastguard Worker std::string CreateRandomUuid() {
165*d9f75844SAndroid Build Coastguard Worker std::string str;
166*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> bytes(new uint8_t[31]);
167*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(Rng().Generate(bytes.get(), 31));
168*d9f75844SAndroid Build Coastguard Worker str.reserve(36);
169*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < 8; ++i) {
170*d9f75844SAndroid Build Coastguard Worker str.push_back(kHex[bytes[i] % 16]);
171*d9f75844SAndroid Build Coastguard Worker }
172*d9f75844SAndroid Build Coastguard Worker str.push_back('-');
173*d9f75844SAndroid Build Coastguard Worker for (size_t i = 8; i < 12; ++i) {
174*d9f75844SAndroid Build Coastguard Worker str.push_back(kHex[bytes[i] % 16]);
175*d9f75844SAndroid Build Coastguard Worker }
176*d9f75844SAndroid Build Coastguard Worker str.push_back('-');
177*d9f75844SAndroid Build Coastguard Worker str.push_back('4');
178*d9f75844SAndroid Build Coastguard Worker for (size_t i = 12; i < 15; ++i) {
179*d9f75844SAndroid Build Coastguard Worker str.push_back(kHex[bytes[i] % 16]);
180*d9f75844SAndroid Build Coastguard Worker }
181*d9f75844SAndroid Build Coastguard Worker str.push_back('-');
182*d9f75844SAndroid Build Coastguard Worker str.push_back(kUuidDigit17[bytes[15] % 4]);
183*d9f75844SAndroid Build Coastguard Worker for (size_t i = 16; i < 19; ++i) {
184*d9f75844SAndroid Build Coastguard Worker str.push_back(kHex[bytes[i] % 16]);
185*d9f75844SAndroid Build Coastguard Worker }
186*d9f75844SAndroid Build Coastguard Worker str.push_back('-');
187*d9f75844SAndroid Build Coastguard Worker for (size_t i = 19; i < 31; ++i) {
188*d9f75844SAndroid Build Coastguard Worker str.push_back(kHex[bytes[i] % 16]);
189*d9f75844SAndroid Build Coastguard Worker }
190*d9f75844SAndroid Build Coastguard Worker return str;
191*d9f75844SAndroid Build Coastguard Worker }
192*d9f75844SAndroid Build Coastguard Worker
CreateRandomId()193*d9f75844SAndroid Build Coastguard Worker uint32_t CreateRandomId() {
194*d9f75844SAndroid Build Coastguard Worker uint32_t id;
195*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(Rng().Generate(&id, sizeof(id)));
196*d9f75844SAndroid Build Coastguard Worker return id;
197*d9f75844SAndroid Build Coastguard Worker }
198*d9f75844SAndroid Build Coastguard Worker
CreateRandomId64()199*d9f75844SAndroid Build Coastguard Worker uint64_t CreateRandomId64() {
200*d9f75844SAndroid Build Coastguard Worker return static_cast<uint64_t>(CreateRandomId()) << 32 | CreateRandomId();
201*d9f75844SAndroid Build Coastguard Worker }
202*d9f75844SAndroid Build Coastguard Worker
CreateRandomNonZeroId()203*d9f75844SAndroid Build Coastguard Worker uint32_t CreateRandomNonZeroId() {
204*d9f75844SAndroid Build Coastguard Worker uint32_t id;
205*d9f75844SAndroid Build Coastguard Worker do {
206*d9f75844SAndroid Build Coastguard Worker id = CreateRandomId();
207*d9f75844SAndroid Build Coastguard Worker } while (id == 0);
208*d9f75844SAndroid Build Coastguard Worker return id;
209*d9f75844SAndroid Build Coastguard Worker }
210*d9f75844SAndroid Build Coastguard Worker
CreateRandomDouble()211*d9f75844SAndroid Build Coastguard Worker double CreateRandomDouble() {
212*d9f75844SAndroid Build Coastguard Worker return CreateRandomId() / (std::numeric_limits<uint32_t>::max() +
213*d9f75844SAndroid Build Coastguard Worker std::numeric_limits<double>::epsilon());
214*d9f75844SAndroid Build Coastguard Worker }
215*d9f75844SAndroid Build Coastguard Worker
GetNextMovingAverage(double prev_average,double cur,double ratio)216*d9f75844SAndroid Build Coastguard Worker double GetNextMovingAverage(double prev_average, double cur, double ratio) {
217*d9f75844SAndroid Build Coastguard Worker return (ratio * prev_average + cur) / (ratio + 1);
218*d9f75844SAndroid Build Coastguard Worker }
219*d9f75844SAndroid Build Coastguard Worker
220*d9f75844SAndroid Build Coastguard Worker } // namespace rtc
221