2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
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.
11 #include "webrtc/base/helpers.h"
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)
22 #if defined(WEBRTC_WIN)
23 #define WIN32_LEAN_AND_MEAN
28 #endif // FEATURE_ENABLED_SSL
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"
36 // Protect against max macro inclusion.
41 // Base class for RNG implementations.
42 class 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;
49 #if defined(SSL_USE_OPENSSL)
51 class SecureRandomGenerator : public RandomGenerator {
53 SecureRandomGenerator() {}
54 ~SecureRandomGenerator() {}
55 virtual bool Init(const void* seed, size_t len) {
58 virtual bool Generate(void* buf, size_t len) {
59 return (RAND_bytes(reinterpret_cast<unsigned char*>(buf), len) > 0);
63 #elif defined(SSL_USE_NSS_RNG)
65 class SecureRandomGenerator : public RandomGenerator {
67 SecureRandomGenerator() {}
68 ~SecureRandomGenerator() {}
69 virtual bool Init(const void* seed, size_t len) {
72 virtual bool Generate(void* buf, size_t len) {
73 return (PK11_GenerateRandom(reinterpret_cast<unsigned char*>(buf),
74 static_cast<int>(len)) == SECSuccess);
79 #if defined(WEBRTC_WIN)
80 class SecureRandomGenerator : public RandomGenerator {
82 SecureRandomGenerator() : advapi32_(NULL), rtl_gen_random_(NULL) {}
83 ~SecureRandomGenerator() {
84 FreeLibrary(advapi32_);
87 virtual bool Init(const void* seed, size_t seed_len) {
88 // We don't do any additional seeding on Win32, we just use the CryptoAPI
89 // RNG (which is exposed as a hidden function off of ADVAPI32 so that we
90 // don't need to drag in all of CryptoAPI)
91 if (rtl_gen_random_) {
95 advapi32_ = LoadLibrary(L"advapi32.dll");
100 rtl_gen_random_ = reinterpret_cast<RtlGenRandomProc>(
101 GetProcAddress(advapi32_, "SystemFunction036"));
102 if (!rtl_gen_random_) {
103 FreeLibrary(advapi32_);
109 virtual bool Generate(void* buf, size_t len) {
110 if (!rtl_gen_random_ && !Init(NULL, 0)) {
113 return (rtl_gen_random_(buf, static_cast<int>(len)) != FALSE);
117 typedef BOOL (WINAPI *RtlGenRandomProc)(PVOID, ULONG);
119 RtlGenRandomProc rtl_gen_random_;
122 #elif !defined(FEATURE_ENABLE_SSL)
124 // No SSL implementation -- use rand()
125 class SecureRandomGenerator : public RandomGenerator {
127 virtual bool Init(const void* seed, size_t len) {
129 srand(*reinterpret_cast<const int*>(seed));
131 srand(*reinterpret_cast<const char*>(seed));
135 virtual bool Generate(void* buf, size_t len) {
136 char* bytes = reinterpret_cast<char*>(buf);
137 for (size_t i = 0; i < len; ++i) {
138 bytes[i] = static_cast<char>(rand());
146 #error No SSL implementation has been selected!
151 // A test random generator, for predictable output.
152 class TestRandomGenerator : public RandomGenerator {
154 TestRandomGenerator() : seed_(7) {
156 ~TestRandomGenerator() {
158 virtual bool Init(const void* seed, size_t len) {
161 virtual bool Generate(void* buf, size_t len) {
162 for (size_t i = 0; i < len; ++i) {
163 static_cast<uint8*>(buf)[i] = static_cast<uint8>(GetRandom());
170 return ((seed_ = seed_ * 214013L + 2531011L) >> 16) & 0x7fff;
175 // TODO: Use Base64::Base64Table instead.
176 static const char BASE64[64] = {
177 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
178 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
179 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
180 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
181 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
186 // This round about way of creating a global RNG is to safe-guard against
187 // indeterminant static initialization order.
188 scoped_ptr<RandomGenerator>& GetGlobalRng() {
189 LIBJINGLE_DEFINE_STATIC_LOCAL(scoped_ptr<RandomGenerator>, global_rng,
190 (new SecureRandomGenerator()));
194 RandomGenerator& Rng() {
195 return *GetGlobalRng();
200 void SetRandomTestMode(bool test) {
202 GetGlobalRng().reset(new SecureRandomGenerator());
204 GetGlobalRng().reset(new TestRandomGenerator());
208 bool InitRandom(int seed) {
209 return InitRandom(reinterpret_cast<const char*>(&seed), sizeof(seed));
212 bool InitRandom(const char* seed, size_t len) {
213 if (!Rng().Init(seed, len)) {
214 LOG(LS_ERROR) << "Failed to init random generator!";
220 std::string CreateRandomString(size_t len) {
222 CreateRandomString(len, &str);
226 bool CreateRandomString(size_t len,
227 const char* table, int table_size,
230 scoped_ptr<uint8[]> bytes(new uint8[len]);
231 if (!Rng().Generate(bytes.get(), len)) {
232 LOG(LS_ERROR) << "Failed to generate random string!";
236 for (size_t i = 0; i < len; ++i) {
237 str->push_back(table[bytes[i] % table_size]);
242 bool CreateRandomString(size_t len, std::string* str) {
243 return CreateRandomString(len, BASE64, 64, str);
246 bool CreateRandomString(size_t len, const std::string& table,
248 return CreateRandomString(len, table.c_str(),
249 static_cast<int>(table.size()), str);
252 uint32 CreateRandomId() {
254 if (!Rng().Generate(&id, sizeof(id))) {
255 LOG(LS_ERROR) << "Failed to generate random id!";
260 uint64 CreateRandomId64() {
261 return static_cast<uint64>(CreateRandomId()) << 32 | CreateRandomId();
264 uint32 CreateRandomNonZeroId() {
267 id = CreateRandomId();
272 double CreateRandomDouble() {
273 return CreateRandomId() / (std::numeric_limits<uint32>::max() +
274 std::numeric_limits<double>::epsilon());