~ubuntu-branches/debian/experimental/kopete/experimental

« back to all changes in this revision

Viewing changes to protocols/jabber/googletalk/libjingle/talk/base/helpers.cc

  • Committer: Package Import Robot
  • Author(s): Maximiliano Curia
  • Date: 2015-02-24 11:32:57 UTC
  • mfrom: (1.1.41 vivid)
  • Revision ID: package-import@ubuntu.com-20150224113257-gnupg4v7lzz18ij0
Tags: 4:14.12.2-1
* New upstream release (14.12.2).
* Bump Standards-Version to 3.9.6, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * libjingle
3
 
 * Copyright 2004--2005, Google Inc.
4
 
 *
5
 
 * Redistribution and use in source and binary forms, with or without
6
 
 * modification, are permitted provided that the following conditions are met:
7
 
 *
8
 
 *  1. Redistributions of source code must retain the above copyright notice,
9
 
 *     this list of conditions and the following disclaimer.
10
 
 *  2. Redistributions in binary form must reproduce the above copyright notice,
11
 
 *     this list of conditions and the following disclaimer in the documentation
12
 
 *     and/or other materials provided with the distribution.
13
 
 *  3. The name of the author may not be used to endorse or promote products
14
 
 *     derived from this software without specific prior written permission.
15
 
 *
16
 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17
 
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19
 
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
 
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25
 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 
 */
27
 
 
28
 
#include "talk/base/helpers.h"
29
 
 
30
 
#include <limits>
31
 
 
32
 
#ifdef WIN32
33
 
#define WIN32_LEAN_AND_MEAN
34
 
#include <windows.h>
35
 
#include <ntsecapi.h>
36
 
#else
37
 
#ifdef SSL_USE_OPENSSL
38
 
#include <openssl/rand.h>
39
 
#endif
40
 
#endif
41
 
 
42
 
#include "talk/base/base64.h"
43
 
#include "talk/base/basictypes.h"
44
 
#include "talk/base/logging.h"
45
 
#include "talk/base/scoped_ptr.h"
46
 
#include "talk/base/timeutils.h"
47
 
 
48
 
// Protect against max macro inclusion.
49
 
#undef max
50
 
 
51
 
namespace talk_base {
52
 
 
53
 
// Base class for RNG implementations.
54
 
class RandomGenerator {
55
 
 public:
56
 
  virtual ~RandomGenerator() {}
57
 
  virtual bool Init(const void* seed, size_t len) = 0;
58
 
  virtual bool Generate(void* buf, size_t len) = 0;
59
 
};
60
 
 
61
 
// The real random generators, using either CryptoAPI or OpenSSL.
62
 
// We also support the 'old' generator on Mac/Linux until we have time to
63
 
// fully test the OpenSSL one.
64
 
#ifdef WIN32
65
 
class SecureRandomGenerator : public RandomGenerator {
66
 
 public:
67
 
  SecureRandomGenerator() : advapi32_(NULL), rtl_gen_random_(NULL) {}
68
 
  ~SecureRandomGenerator() {
69
 
    FreeLibrary(advapi32_);
70
 
  }
71
 
 
72
 
  virtual bool Init(const void* seed, size_t seed_len) {
73
 
    // We don't do any additional seeding on Win32, we just use the CryptoAPI
74
 
    // RNG (which is exposed as a hidden function off of ADVAPI32 so that we
75
 
    // don't need to drag in all of CryptoAPI)
76
 
    if (rtl_gen_random_) {
77
 
      return true;
78
 
    }
79
 
 
80
 
    advapi32_ = LoadLibrary(L"advapi32.dll");
81
 
    if (!advapi32_) {
82
 
      return false;
83
 
    }
84
 
 
85
 
    rtl_gen_random_ = reinterpret_cast<RtlGenRandomProc>(
86
 
        GetProcAddress(advapi32_, "SystemFunction036"));
87
 
    if (!rtl_gen_random_) {
88
 
      FreeLibrary(advapi32_);
89
 
      return false;
90
 
    }
91
 
 
92
 
    return true;
93
 
  }
94
 
  virtual bool Generate(void* buf, size_t len) {
95
 
    if (!rtl_gen_random_ && !Init(NULL, 0)) {
96
 
      return false;
97
 
    }
98
 
    return (rtl_gen_random_(buf, static_cast<int>(len)) != FALSE);
99
 
  }
100
 
 
101
 
 private:
102
 
  typedef BOOL (WINAPI *RtlGenRandomProc)(PVOID, ULONG);
103
 
  HINSTANCE advapi32_;
104
 
  RtlGenRandomProc rtl_gen_random_;
105
 
};
106
 
#else
107
 
#ifndef SSL_USE_OPENSSL
108
 
// The old RNG.
109
 
class SecureRandomGenerator : public RandomGenerator {
110
 
 public:
111
 
  SecureRandomGenerator() : seed_(1) {
112
 
  }
113
 
  ~SecureRandomGenerator() {
114
 
  }
115
 
  virtual bool Init(const void* seed, size_t len) {
116
 
    uint32 hash = 0;
117
 
    for (size_t i = 0; i < len; ++i) {
118
 
      hash = ((hash << 2) + hash) + static_cast<const char*>(seed)[i];
119
 
    }
120
 
 
121
 
    seed_ = Time() ^ hash;
122
 
    return true;
123
 
  }
124
 
  virtual bool Generate(void* buf, size_t len) {
125
 
    for (size_t i = 0; i < len; ++i) {
126
 
      static_cast<uint8*>(buf)[i] = static_cast<uint8>(GetRandom());
127
 
    }
128
 
    return true;
129
 
  }
130
 
 
131
 
 private:
132
 
  int GetRandom() {
133
 
    return ((seed_ = seed_ * 214013L + 2531011L) >> 16) & 0x7fff;
134
 
  }
135
 
  int seed_;
136
 
};
137
 
#else
138
 
// The OpenSSL RNG. Need to make sure it doesn't run out of entropy.
139
 
class SecureRandomGenerator : public RandomGenerator {
140
 
 public:
141
 
  SecureRandomGenerator() : inited_(false) {
142
 
  }
143
 
  ~SecureRandomGenerator() {
144
 
  }
145
 
  virtual bool Init(const void* seed, size_t len) {
146
 
    // By default, seed from the system state.
147
 
    if (!inited_) {
148
 
      if (RAND_poll() <= 0) {
149
 
        return false;
150
 
      }
151
 
      inited_ = true;
152
 
    }
153
 
    // Allow app data to be mixed in, if provided.
154
 
    if (seed) {
155
 
      RAND_seed(seed, len);
156
 
    }
157
 
    return true;
158
 
  }
159
 
  virtual bool Generate(void* buf, size_t len) {
160
 
    if (!inited_ && !Init(NULL, 0)) {
161
 
      return false;
162
 
    }
163
 
    return (RAND_bytes(reinterpret_cast<unsigned char*>(buf), len) > 0);
164
 
  }
165
 
 
166
 
 private:
167
 
  bool inited_;
168
 
};
169
 
#endif  // SSL_USE_OPENSSL
170
 
#endif  // WIN32
171
 
 
172
 
// A test random generator, for predictable output.
173
 
class TestRandomGenerator : public RandomGenerator {
174
 
 public:
175
 
  TestRandomGenerator() : seed_(7) {
176
 
  }
177
 
  ~TestRandomGenerator() {
178
 
  }
179
 
  virtual bool Init(const void* seed, size_t len) {
180
 
    return true;
181
 
  }
182
 
  virtual bool Generate(void* buf, size_t len) {
183
 
    for (size_t i = 0; i < len; ++i) {
184
 
      static_cast<uint8*>(buf)[i] = static_cast<uint8>(GetRandom());
185
 
    }
186
 
    return true;
187
 
  }
188
 
 
189
 
 private:
190
 
  int GetRandom() {
191
 
    return ((seed_ = seed_ * 214013L + 2531011L) >> 16) & 0x7fff;
192
 
  }
193
 
  int seed_;
194
 
};
195
 
 
196
 
// TODO: Use Base64::Base64Table instead.
197
 
static const char BASE64[64] = {
198
 
  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
199
 
  'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
200
 
  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
201
 
  'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
202
 
  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
203
 
};
204
 
 
205
 
namespace {
206
 
 
207
 
// This round about way of creating a global RNG is to safe-guard against
208
 
// indeterminant static initialization order.
209
 
scoped_ptr<RandomGenerator>& GetGlobalRng() {
210
 
  LIBJINGLE_DEFINE_STATIC_LOCAL(scoped_ptr<RandomGenerator>, global_rng,
211
 
                                (new SecureRandomGenerator()));
212
 
  return global_rng;
213
 
}
214
 
 
215
 
RandomGenerator& Rng() {
216
 
  return *GetGlobalRng();
217
 
}
218
 
 
219
 
}  // namespace
220
 
 
221
 
void SetRandomTestMode(bool test) {
222
 
  if (!test) {
223
 
    GetGlobalRng().reset(new SecureRandomGenerator());
224
 
  } else {
225
 
    GetGlobalRng().reset(new TestRandomGenerator());
226
 
  }
227
 
}
228
 
 
229
 
bool InitRandom(int seed) {
230
 
  return InitRandom(reinterpret_cast<const char*>(&seed), sizeof(seed));
231
 
}
232
 
 
233
 
bool InitRandom(const char* seed, size_t len) {
234
 
  if (!Rng().Init(seed, len)) {
235
 
    LOG(LS_ERROR) << "Failed to init random generator!";
236
 
    return false;
237
 
  }
238
 
  return true;
239
 
}
240
 
 
241
 
std::string CreateRandomString(size_t len) {
242
 
  std::string str;
243
 
  CreateRandomString(len, &str);
244
 
  return str;
245
 
}
246
 
 
247
 
bool CreateRandomString(size_t len,
248
 
                        const char* table, int table_size,
249
 
                        std::string* str) {
250
 
  str->clear();
251
 
  scoped_array<uint8> bytes(new uint8[len]);
252
 
  if (!Rng().Generate(bytes.get(), len)) {
253
 
    LOG(LS_ERROR) << "Failed to generate random string!";
254
 
    return false;
255
 
  }
256
 
  str->reserve(len);
257
 
  for (size_t i = 0; i < len; ++i) {
258
 
    str->push_back(table[bytes[i] % table_size]);
259
 
  }
260
 
  return true;
261
 
}
262
 
 
263
 
bool CreateRandomString(size_t len, std::string* str) {
264
 
  return CreateRandomString(len, BASE64, 64, str);
265
 
}
266
 
 
267
 
bool CreateRandomString(size_t len, const std::string& table,
268
 
                        std::string* str) {
269
 
  return CreateRandomString(len, table.c_str(),
270
 
                            static_cast<int>(table.size()), str);
271
 
}
272
 
 
273
 
uint32 CreateRandomId() {
274
 
  uint32 id;
275
 
  if (!Rng().Generate(&id, sizeof(id))) {
276
 
    LOG(LS_ERROR) << "Failed to generate random id!";
277
 
  }
278
 
  return id;
279
 
}
280
 
 
281
 
uint32 CreateRandomNonZeroId() {
282
 
  uint32 id;
283
 
  do {
284
 
    id = CreateRandomId();
285
 
  } while (id == 0);
286
 
  return id;
287
 
}
288
 
 
289
 
double CreateRandomDouble() {
290
 
  return CreateRandomId() / (std::numeric_limits<uint32>::max() +
291
 
      std::numeric_limits<double>::epsilon());
292
 
}
293
 
 
294
 
}  // namespace talk_base