1 /*
2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/base/helpers.h"
12 
13 #include <limits>
14 
15 #if defined(FEATURE_ENABLE_SSL)
16 #include "webrtc/base/sslconfig.h"
17 #if defined(SSL_USE_OPENSSL)
18 #include <openssl/rand.h>
19 #elif defined(SSL_USE_NSS_RNG)
20 #include "pk11func.h"
21 #else
22 #if defined(WEBRTC_WIN)
23 #define WIN32_LEAN_AND_MEAN
24 #include <windows.h>
25 #include <ntsecapi.h>
26 #endif  // WEBRTC_WIN
27 #endif  // else
28 #endif  // FEATURE_ENABLED_SSL
29 
30 #include "webrtc/base/base64.h"
31 #include "webrtc/base/basictypes.h"
32 #include "webrtc/base/logging.h"
33 #include "webrtc/base/scoped_ptr.h"
34 #include "webrtc/base/timeutils.h"
35 
36 // Protect against max macro inclusion.
37 #undef max
38 
39 namespace rtc {
40 
41 // Base class for RNG implementations.
42 class RandomGenerator {
43  public:
~RandomGenerator()44   virtual ~RandomGenerator() {}
45   virtual bool Init(const void* seed, size_t len) = 0;
46   virtual bool Generate(void* buf, size_t len) = 0;
47 };
48 
49 #if defined(SSL_USE_OPENSSL)
50 // The OpenSSL RNG.
51 class SecureRandomGenerator : public RandomGenerator {
52  public:
SecureRandomGenerator()53   SecureRandomGenerator() {}
~SecureRandomGenerator()54   ~SecureRandomGenerator() override {}
Init(const void * seed,size_t len)55   bool Init(const void* seed, size_t len) override { return true; }
Generate(void * buf,size_t len)56   bool Generate(void* buf, size_t len) override {
57     return (RAND_bytes(reinterpret_cast<unsigned char*>(buf), len) > 0);
58   }
59 };
60 
61 #elif defined(SSL_USE_NSS_RNG)
62 // The NSS RNG.
63 class SecureRandomGenerator : public RandomGenerator {
64  public:
SecureRandomGenerator()65   SecureRandomGenerator() {}
~SecureRandomGenerator()66   ~SecureRandomGenerator() override {}
Init(const void * seed,size_t len)67   bool Init(const void* seed, size_t len) override { return true; }
Generate(void * buf,size_t len)68   bool Generate(void* buf, size_t len) override {
69     return (PK11_GenerateRandom(reinterpret_cast<unsigned char*>(buf),
70                                 static_cast<int>(len)) == SECSuccess);
71   }
72 };
73 
74 #else
75 #if defined(WEBRTC_WIN)
76 class SecureRandomGenerator : public RandomGenerator {
77  public:
SecureRandomGenerator()78   SecureRandomGenerator() : advapi32_(NULL), rtl_gen_random_(NULL) {}
~SecureRandomGenerator()79   ~SecureRandomGenerator() {
80     FreeLibrary(advapi32_);
81   }
82 
Init(const void * seed,size_t seed_len)83   virtual bool Init(const void* seed, size_t seed_len) {
84     // We don't do any additional seeding on Win32, we just use the CryptoAPI
85     // RNG (which is exposed as a hidden function off of ADVAPI32 so that we
86     // don't need to drag in all of CryptoAPI)
87     if (rtl_gen_random_) {
88       return true;
89     }
90 
91     advapi32_ = LoadLibrary(L"advapi32.dll");
92     if (!advapi32_) {
93       return false;
94     }
95 
96     rtl_gen_random_ = reinterpret_cast<RtlGenRandomProc>(
97         GetProcAddress(advapi32_, "SystemFunction036"));
98     if (!rtl_gen_random_) {
99       FreeLibrary(advapi32_);
100       return false;
101     }
102 
103     return true;
104   }
Generate(void * buf,size_t len)105   virtual bool Generate(void* buf, size_t len) {
106     if (!rtl_gen_random_ && !Init(NULL, 0)) {
107       return false;
108     }
109     return (rtl_gen_random_(buf, static_cast<int>(len)) != FALSE);
110   }
111 
112  private:
113   typedef BOOL (WINAPI *RtlGenRandomProc)(PVOID, ULONG);
114   HINSTANCE advapi32_;
115   RtlGenRandomProc rtl_gen_random_;
116 };
117 
118 #elif !defined(FEATURE_ENABLE_SSL)
119 
120 // No SSL implementation -- use rand()
121 class SecureRandomGenerator : public RandomGenerator {
122  public:
Init(const void * seed,size_t len)123   virtual bool Init(const void* seed, size_t len) {
124     if (len >= 4) {
125       srand(*reinterpret_cast<const int*>(seed));
126     } else {
127       srand(*reinterpret_cast<const char*>(seed));
128     }
129     return true;
130   }
Generate(void * buf,size_t len)131   virtual bool Generate(void* buf, size_t len) {
132     char* bytes = reinterpret_cast<char*>(buf);
133     for (size_t i = 0; i < len; ++i) {
134       bytes[i] = static_cast<char>(rand());
135     }
136     return true;
137   }
138 };
139 
140 #else
141 
142 #error No SSL implementation has been selected!
143 
144 #endif  // WEBRTC_WIN
145 #endif
146 
147 // A test random generator, for predictable output.
148 class TestRandomGenerator : public RandomGenerator {
149  public:
TestRandomGenerator()150   TestRandomGenerator() : seed_(7) {
151   }
~TestRandomGenerator()152   ~TestRandomGenerator() override {
153   }
Init(const void * seed,size_t len)154   bool Init(const void* seed, size_t len) override { return true; }
Generate(void * buf,size_t len)155   bool Generate(void* buf, size_t len) override {
156     for (size_t i = 0; i < len; ++i) {
157       static_cast<uint8*>(buf)[i] = static_cast<uint8>(GetRandom());
158     }
159     return true;
160   }
161 
162  private:
GetRandom()163   int GetRandom() {
164     return ((seed_ = seed_ * 214013L + 2531011L) >> 16) & 0x7fff;
165   }
166   int seed_;
167 };
168 
169 // TODO: Use Base64::Base64Table instead.
170 static const char BASE64[64] = {
171   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
172   'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
173   'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
174   'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
175   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
176 };
177 
178 namespace {
179 
180 // This round about way of creating a global RNG is to safe-guard against
181 // indeterminant static initialization order.
GetGlobalRng()182 scoped_ptr<RandomGenerator>& GetGlobalRng() {
183   LIBJINGLE_DEFINE_STATIC_LOCAL(scoped_ptr<RandomGenerator>, global_rng,
184                                 (new SecureRandomGenerator()));
185   return global_rng;
186 }
187 
Rng()188 RandomGenerator& Rng() {
189   return *GetGlobalRng();
190 }
191 
192 }  // namespace
193 
SetRandomTestMode(bool test)194 void SetRandomTestMode(bool test) {
195   if (!test) {
196     GetGlobalRng().reset(new SecureRandomGenerator());
197   } else {
198     GetGlobalRng().reset(new TestRandomGenerator());
199   }
200 }
201 
InitRandom(int seed)202 bool InitRandom(int seed) {
203   return InitRandom(reinterpret_cast<const char*>(&seed), sizeof(seed));
204 }
205 
InitRandom(const char * seed,size_t len)206 bool InitRandom(const char* seed, size_t len) {
207   if (!Rng().Init(seed, len)) {
208     LOG(LS_ERROR) << "Failed to init random generator!";
209     return false;
210   }
211   return true;
212 }
213 
CreateRandomString(size_t len)214 std::string CreateRandomString(size_t len) {
215   std::string str;
216   CreateRandomString(len, &str);
217   return str;
218 }
219 
CreateRandomString(size_t len,const char * table,int table_size,std::string * str)220 bool CreateRandomString(size_t len,
221                         const char* table, int table_size,
222                         std::string* str) {
223   str->clear();
224   scoped_ptr<uint8[]> bytes(new uint8[len]);
225   if (!Rng().Generate(bytes.get(), len)) {
226     LOG(LS_ERROR) << "Failed to generate random string!";
227     return false;
228   }
229   str->reserve(len);
230   for (size_t i = 0; i < len; ++i) {
231     str->push_back(table[bytes[i] % table_size]);
232   }
233   return true;
234 }
235 
CreateRandomString(size_t len,std::string * str)236 bool CreateRandomString(size_t len, std::string* str) {
237   return CreateRandomString(len, BASE64, 64, str);
238 }
239 
CreateRandomString(size_t len,const std::string & table,std::string * str)240 bool CreateRandomString(size_t len, const std::string& table,
241                         std::string* str) {
242   return CreateRandomString(len, table.c_str(),
243                             static_cast<int>(table.size()), str);
244 }
245 
CreateRandomId()246 uint32 CreateRandomId() {
247   uint32 id;
248   if (!Rng().Generate(&id, sizeof(id))) {
249     LOG(LS_ERROR) << "Failed to generate random id!";
250   }
251   return id;
252 }
253 
CreateRandomId64()254 uint64 CreateRandomId64() {
255   return static_cast<uint64>(CreateRandomId()) << 32 | CreateRandomId();
256 }
257 
CreateRandomNonZeroId()258 uint32 CreateRandomNonZeroId() {
259   uint32 id;
260   do {
261     id = CreateRandomId();
262   } while (id == 0);
263   return id;
264 }
265 
CreateRandomDouble()266 double CreateRandomDouble() {
267   return CreateRandomId() / (std::numeric_limits<uint32>::max() +
268       std::numeric_limits<double>::epsilon());
269 }
270 
271 }  // namespace rtc
272