Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / base / helpers.cc
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:
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:
53   SecureRandomGenerator() {}
54   ~SecureRandomGenerator() {}
55   virtual bool Init(const void* seed, size_t len) {
56     return true;
57   }
58   virtual bool Generate(void* buf, size_t len) {
59     return (RAND_bytes(reinterpret_cast<unsigned char*>(buf), len) > 0);
60   }
61 };
62
63 #elif defined(SSL_USE_NSS_RNG)
64 // The NSS RNG.
65 class SecureRandomGenerator : public RandomGenerator {
66  public:
67   SecureRandomGenerator() {}
68   ~SecureRandomGenerator() {}
69   virtual bool Init(const void* seed, size_t len) {
70     return true;
71   }
72   virtual bool Generate(void* buf, size_t len) {
73     return (PK11_GenerateRandom(reinterpret_cast<unsigned char*>(buf),
74                                 static_cast<int>(len)) == SECSuccess);
75   }
76 };
77
78 #else
79 #if defined(WEBRTC_WIN)
80 class SecureRandomGenerator : public RandomGenerator {
81  public:
82   SecureRandomGenerator() : advapi32_(NULL), rtl_gen_random_(NULL) {}
83   ~SecureRandomGenerator() {
84     FreeLibrary(advapi32_);
85   }
86
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_) {
92       return true;
93     }
94
95     advapi32_ = LoadLibrary(L"advapi32.dll");
96     if (!advapi32_) {
97       return false;
98     }
99
100     rtl_gen_random_ = reinterpret_cast<RtlGenRandomProc>(
101         GetProcAddress(advapi32_, "SystemFunction036"));
102     if (!rtl_gen_random_) {
103       FreeLibrary(advapi32_);
104       return false;
105     }
106
107     return true;
108   }
109   virtual bool Generate(void* buf, size_t len) {
110     if (!rtl_gen_random_ && !Init(NULL, 0)) {
111       return false;
112     }
113     return (rtl_gen_random_(buf, static_cast<int>(len)) != FALSE);
114   }
115
116  private:
117   typedef BOOL (WINAPI *RtlGenRandomProc)(PVOID, ULONG);
118   HINSTANCE advapi32_;
119   RtlGenRandomProc rtl_gen_random_;
120 };
121
122 #elif !defined(FEATURE_ENABLE_SSL)
123
124 // No SSL implementation -- use rand()
125 class SecureRandomGenerator : public RandomGenerator {
126  public:
127   virtual bool Init(const void* seed, size_t len) {
128     if (len >= 4) {
129       srand(*reinterpret_cast<const int*>(seed));
130     } else {
131       srand(*reinterpret_cast<const char*>(seed));
132     }
133     return true;
134   }
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());
139     }
140     return true;
141   }
142 };
143
144 #else
145
146 #error No SSL implementation has been selected!
147
148 #endif  // WEBRTC_WIN 
149 #endif
150
151 // A test random generator, for predictable output.
152 class TestRandomGenerator : public RandomGenerator {
153  public:
154   TestRandomGenerator() : seed_(7) {
155   }
156   ~TestRandomGenerator() {
157   }
158   virtual bool Init(const void* seed, size_t len) {
159     return true;
160   }
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());
164     }
165     return true;
166   }
167
168  private:
169   int GetRandom() {
170     return ((seed_ = seed_ * 214013L + 2531011L) >> 16) & 0x7fff;
171   }
172   int seed_;
173 };
174
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', '+', '/'
182 };
183
184 namespace {
185
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()));
191   return global_rng;
192 }
193
194 RandomGenerator& Rng() {
195   return *GetGlobalRng();
196 }
197
198 }  // namespace
199
200 void SetRandomTestMode(bool test) {
201   if (!test) {
202     GetGlobalRng().reset(new SecureRandomGenerator());
203   } else {
204     GetGlobalRng().reset(new TestRandomGenerator());
205   }
206 }
207
208 bool InitRandom(int seed) {
209   return InitRandom(reinterpret_cast<const char*>(&seed), sizeof(seed));
210 }
211
212 bool InitRandom(const char* seed, size_t len) {
213   if (!Rng().Init(seed, len)) {
214     LOG(LS_ERROR) << "Failed to init random generator!";
215     return false;
216   }
217   return true;
218 }
219
220 std::string CreateRandomString(size_t len) {
221   std::string str;
222   CreateRandomString(len, &str);
223   return str;
224 }
225
226 bool CreateRandomString(size_t len,
227                         const char* table, int table_size,
228                         std::string* str) {
229   str->clear();
230   scoped_ptr<uint8[]> bytes(new uint8[len]);
231   if (!Rng().Generate(bytes.get(), len)) {
232     LOG(LS_ERROR) << "Failed to generate random string!";
233     return false;
234   }
235   str->reserve(len);
236   for (size_t i = 0; i < len; ++i) {
237     str->push_back(table[bytes[i] % table_size]);
238   }
239   return true;
240 }
241
242 bool CreateRandomString(size_t len, std::string* str) {
243   return CreateRandomString(len, BASE64, 64, str);
244 }
245
246 bool CreateRandomString(size_t len, const std::string& table,
247                         std::string* str) {
248   return CreateRandomString(len, table.c_str(),
249                             static_cast<int>(table.size()), str);
250 }
251
252 uint32 CreateRandomId() {
253   uint32 id;
254   if (!Rng().Generate(&id, sizeof(id))) {
255     LOG(LS_ERROR) << "Failed to generate random id!";
256   }
257   return id;
258 }
259
260 uint64 CreateRandomId64() {
261   return static_cast<uint64>(CreateRandomId()) << 32 | CreateRandomId();
262 }
263
264 uint32 CreateRandomNonZeroId() {
265   uint32 id;
266   do {
267     id = CreateRandomId();
268   } while (id == 0);
269   return id;
270 }
271
272 double CreateRandomDouble() {
273   return CreateRandomId() / (std::numeric_limits<uint32>::max() +
274       std::numeric_limits<double>::epsilon());
275 }
276
277 }  // namespace rtc